def apply_complex(self, z, evaluation): 'Abs[z_Complex]' return Expression( 'Sqrt', Expression('Plus', Number.from_mp(z.value.real**2), Number.from_mp(z.value.imag**2)))
def pyobject(self, ex, obj): from mathics.core import expression from mathics.core.expression import Number if obj is None: return expression.Symbol('Null') elif isinstance(obj, (list, tuple)) or is_Vector(obj): return expression.Expression('List', *(from_sage(item, self.subs) for item in obj)) elif isinstance(obj, Constant): return expression.Symbol(obj._conversions.get('mathematica', obj._name)) elif is_Integer(obj): return expression.Integer(str(obj)) elif isinstance(obj, sage.Rational): rational = expression.Rational(str(obj)) if rational.value.denom() == 1: return expression.Integer(rational.value.numer()) else: return rational elif isinstance(obj, sage.RealDoubleElement) or is_RealNumber(obj): return expression.Real(str(obj)) elif is_ComplexNumber(obj): real = Number.from_string(str(obj.real())).value imag = Number.from_string(str(obj.imag())).value return expression.Complex(real, imag) elif isinstance(obj, NumberFieldElement_quadratic): # TODO: this need not be a complex number, but we assume so! real = Number.from_string(str(obj.real())).value imag = Number.from_string(str(obj.imag())).value return expression.Complex(real, imag) else: return expression.from_python(obj)
def apply_complex(self, z, evaluation): 'Abs[z_Complex]' real, imag = z.to_sympy().as_real_imag() return Expression( 'Sqrt', Expression('Plus', Number.from_mp(real**2), Number.from_mp(imag**2)))
def apply(self, z, evaluation): '%(name)s[z__]' args = z.numerify(evaluation).get_sequence() mpmath_function = self.get_mpmath_function(args) result = None # if no arguments are inexact attempt to use sympy if all(not x.is_inexact() for x in args): result = Expression(self.get_name(), *args).to_sympy() result = self.prepare_mathics(result) result = from_sympy(result) # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1] return result.evaluate_leaves(evaluation) elif mpmath_function is None: return if not all(isinstance(arg, Number) for arg in args): return if any(arg.is_machine_precision() for arg in args): # if any argument has machine precision then the entire calculation # is done with machine precision. float_args = [ arg.round().get_float_value(permit_complex=True) for arg in args ] if None in float_args: return result = self.call_mpmath(mpmath_function, float_args) if isinstance(result, (mpmath.mpc, mpmath.mpf)): if mpmath.isinf(result) and isinstance(result, mpmath.mpc): result = Symbol('ComplexInfinity') elif mpmath.isinf(result) and result > 0: result = Expression('DirectedInfinity', Integer(1)) elif mpmath.isinf(result) and result < 0: result = Expression('DirectedInfinity', Integer(-1)) elif mpmath.isnan(result): result = Symbol('Indeterminate') else: result = Number.from_mpmath(result) else: prec = min_prec(*args) d = dps(prec) args = [ Expression('N', arg, Integer(d)).evaluate(evaluation) for arg in args ] with mpmath.workprec(prec): mpmath_args = [x.to_mpmath() for x in args] if None in mpmath_args: return result = self.call_mpmath(mpmath_function, mpmath_args) if isinstance(result, (mpmath.mpc, mpmath.mpf)): result = Number.from_mpmath(result, d) return result
def apply(self, items, evaluation): 'Times[items___]' #TODO: Clean this up and optimise it items = items.numerify(evaluation).get_sequence() number = (sympy.Integer(1), sympy.Integer(0)) leaves = [] prec = min_prec(*items) is_real = all([not isinstance(i, Complex) for i in items]) for item in items: if isinstance(item, Number): if isinstance(item, Complex): sym_real, sym_imag = item.real.to_sympy(), item.imag.to_sympy() else: sym_real, sym_imag = item.to_sympy(), sympy.Integer(0) if prec is not None: sym_real = sym_real.n(dps(prec)) sym_imag = sym_imag.n(dps(prec)) if sym_real.is_zero and sym_imag.is_zero and prec is None: return Integer('0') number = (number[0]*sym_real - number[1]*sym_imag, number[0]*sym_imag + number[1]*sym_real) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0]): leaves[-1].leaves[1] = Expression('Plus', item.leaves[1], leaves[-1].leaves[1]) elif leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1]): leaves[-1] = Expression('Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item): leaves[-1] = Expression('Power', item, Expression('Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if number == (1, 0): number = None elif number == (-1, 0) and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves] number = None if number is not None: if number[1].is_zero and is_real: leaves.insert(0, Number.from_mp(number[0], prec)) elif number[1].is_zero and number[1].is_Integer and prec is None: leaves.insert(0, Number.from_mp(number[0], prec)) else: leaves.insert(0, Complex(from_sympy(number[0]), from_sympy(number[1]), prec)) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form("Times", None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append(Expression("Times", Number.from_mp(last_count), last_item))
def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append(Expression( 'Times', Number.from_mp(last_count), last_item))
def apply(self, z, evaluation): '%(name)s[z__]' args = z.numerify(evaluation).get_sequence() mpmath_function = self.get_mpmath_function(args) result = None # if no arguments are inexact attempt to use sympy if all(not x.is_inexact() for x in args): result = Expression(self.get_name(), *args).to_sympy() result = self.prepare_mathics(result) result = from_sympy(result) # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1] return result.evaluate_leaves(evaluation) elif mpmath_function is None: return if not all(isinstance(arg, Number) for arg in args): return if any(arg.is_machine_precision() for arg in args): # if any argument has machine precision then the entire calculation # is done with machine precision. float_args = [arg.round().get_float_value(permit_complex=True) for arg in args] if None in float_args: return result = self.call_mpmath(mpmath_function, float_args) if isinstance(result, (mpmath.mpc, mpmath.mpf)): if mpmath.isinf(result) and isinstance(result, mpmath.mpc): result = Symbol('ComplexInfinity') elif mpmath.isinf(result) and result > 0: result = Expression('DirectedInfinity', Integer(1)) elif mpmath.isinf(result) and result < 0: result = Expression('DirectedInfinity', Integer(-1)) elif mpmath.isnan(result): result = Symbol('Indeterminate') else: result = Number.from_mpmath(result) else: prec = min_prec(*args) d = dps(prec) args = [Expression('N', arg, Integer(d)).evaluate(evaluation) for arg in args] with mpmath.workprec(prec): mpmath_args = [x.to_mpmath() for x in args] if None in mpmath_args: return result = self.call_mpmath(mpmath_function, mpmath_args) if isinstance(result, (mpmath.mpc, mpmath.mpf)): result = Number.from_mpmath(result, d) return result
def post_parse(self, expression): if (expression.get_head().get_name() == 'Minus' # noqa and len(expression.leaves) == 1 and isinstance(expression.leaves[0], Number)): return Number.from_mp(-expression.leaves[0].to_sympy()) else: return super(Minus, self).post_parse(expression)
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = add(index, di) return self.get_result(result)
def apply_real(self, x, evaluation): 'Abs[x_?RealNumberQ]' if x.value < 0: return Number.from_mp(-x.value) else: return x
def apply(self, items, evaluation): 'Times[items___]' items = items.numerify(evaluation).get_sequence() number = mpz(1) leaves = [] for item in items: if isinstance(item, Number): if get_type(item.value) == 'z' and item.value == 0: return Integer('0') number = mul(number, item.value) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0]): leaves[-1].leaves[1] = Expression('Plus', item.leaves[1], leaves[-1].leaves[1]) elif leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1]): leaves[-1] = Expression('Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item): leaves[-1] = Expression('Power', item, Expression('Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if get_type(number) == 'z': if number == 1: number = None elif number == -1 and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves] number = None if number is not None: leaves.insert(0, Number.from_mp(number)) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def post_parse(self, expression): if expression.get_head().get_name() == 'Minus' and len( expression.leaves) == 1 and isinstance(expression.leaves[0], Number): return Number.from_mp(-expression.leaves[0].to_sympy()) else: return super(Minus, self).post_parse(expression)
def negate(item): if item.has_form('Times', 1, None): if isinstance(item.leaves[0], Number): neg = Number.from_mp(-item.leaves[0].to_sympy()) if neg.same(Integer(1)): if len(item.leaves) == 1: return neg else: return Expression('Times', *item.leaves[1:]) else: return Expression('Times', neg, *item.leaves[1:]) else: return Expression('Times', -1, *item.leaves) elif isinstance(item, (Integer, Rational, Real, Complex)): return Number.from_mp(-item.to_sympy()) else: return Expression('Times', -1, item)
def apply_real(self, x, evaluation): "Abs[x_?RealNumberQ]" sym_x = x.to_sympy() if sym_x < 0: return Number.from_mp(-sym_x) else: return x
def apply_real(self, x, evaluation): 'Abs[x_?RealNumberQ]' sym_x = x.to_sympy() if sym_x < 0: return Number.from_mp(-sym_x) else: return x
def negate(item): if item.has_form("Times", 1, None): if isinstance(item.leaves[0], (Integer, Rational, Real, Complex)): neg = Number.from_mp(-item.leaves[0].to_sympy()) if neg.same(Integer(1)): if len(item.leaves) == 1: return neg else: return Expression("Times", *item.leaves[1:]) else: return Expression("Times", neg, *item.leaves[1:]) else: return Expression("Times", -1, *item.leaves) elif isinstance(item, (Integer, Rational, Real, Complex)): return Number.from_mp(-item.to_sympy()) else: return Expression("Times", -1, item)
def inverse(item): if item.has_form("Power", 2) and isinstance(item.leaves[1], (Integer, Rational, Real)): neg = Number.from_mp(-item.leaves[1].to_sympy()) if neg.same(Integer(1)): return item.leaves[0] else: return Expression("Power", item.leaves[0], neg) else: return item
def apply(self, items, evaluation): 'Plus[items___]' items = items.numerify(evaluation).get_sequence() number = mpz(0) leaves = [] last_item = last_count = None def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append( Expression('Times', Number.from_mp(last_count), last_item)) for item in items: if isinstance(item, Number): number = add(number, item.value) else: count = rest = None if item.has_form('Times', None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.value rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression('Times', *rest) break if count is None: count = mpz(1) rest = item if last_item is not None and last_item == rest: last_count = add(last_count, count) else: append_last() last_item = rest last_count = count append_last() if not (get_type(number) == 'z' and number == 0): leaves.insert(0, Number.from_mp(number)) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression('Plus', *leaves)
def format_times(self, items, evaluation, op='\u2062'): 'Times[items__]' def inverse(item): if item.has_form('Power', 2) and isinstance( # noqa item.leaves[1], (Integer, Rational, Real)): neg = Number.from_mp(-item.leaves[1].to_sympy()) if neg.same(Integer(1)): return item.leaves[0] else: return Expression('Power', item.leaves[0], neg) else: return item items = items.get_sequence() positive = [] negative = [] for item in items: if (item.has_form('Power', 2) and isinstance(item.leaves[1], (Integer, Rational, Real)) and item.leaves[1].to_sympy() < 0): # nopep8 negative.append(inverse(item)) elif isinstance(item, Rational): numerator = item.numerator() if not numerator.same(Integer(1)): positive.append(numerator) negative.append(item.denominator()) else: positive.append(item) if (positive and isinstance(positive[0], (Integer, Real)) and positive[0].to_sympy() < 0): # nopep8 positive[0] = Number.from_mp(-positive[0].to_sympy()) if positive[0].same(Integer(1)): del positive[0] minus = True else: minus = False positive = [Expression('HoldForm', item) for item in positive] negative = [Expression('HoldForm', item) for item in negative] if positive: positive = create_infix(positive, op, 400, 'None') else: positive = Integer(1) if negative: negative = create_infix(negative, op, 400, 'None') result = Expression('Divide', Expression('HoldForm', positive), Expression('HoldForm', negative)) else: result = positive if minus: result = Expression( 'Minus', result) # Expression('PrecedenceForm', result, 481)) result = Expression('HoldForm', result) return result
def format_times(self, items, evaluation, op='\u2062'): 'Times[items__]' def inverse(item): if item.has_form('Power', 2) and isinstance( # noqa item.leaves[1], (Integer, Rational, Real)): neg = Number.from_mp(-item.leaves[1].to_sympy()) if neg.same(Integer(1)): return item.leaves[0] else: return Expression('Power', item.leaves[0], neg) else: return item items = items.get_sequence() positive = [] negative = [] for item in items: if (item.has_form('Power', 2) and isinstance(item.leaves[1], (Integer, Rational, Real)) and item.leaves[1].to_sympy() < 0): # nopep8 negative.append(inverse(item)) elif isinstance(item, Rational): numerator = item.numerator() if not numerator.same(Integer(1)): positive.append(numerator) negative.append(item.denominator()) else: positive.append(item) if (positive and isinstance(positive[0], (Integer, Real)) and positive[0].to_sympy() < 0): # nopep8 positive[0] = Number.from_mp(-positive[0].to_sympy()) if positive[0].same(Integer(1)): del positive[0] minus = True else: minus = False positive = [Expression('HoldForm', item) for item in positive] negative = [Expression('HoldForm', item) for item in negative] if positive: positive = create_infix(positive, op, 400, 'None') else: positive = Integer(1) if negative: negative = create_infix(negative, op, 400, 'None') result = Expression('Divide', Expression( 'HoldForm', positive), Expression('HoldForm', negative)) else: result = positive if minus: result = Expression( 'Minus', result) # Expression('PrecedenceForm', result, 481)) result = Expression('HoldForm', result) return result
def inverse(item): if item.has_form('Power', 2) and isinstance( # noqa item.leaves[1], (Integer, Rational, Real)): neg = Number.from_mp(-item.leaves[1].to_sympy()) if neg.same(Integer(1)): return item.leaves[0] else: return Expression('Power', item.leaves[0], neg) else: return item
def apply(self, z, s, a, evaluation): '%(name)s[z_, s_, a_]' py_z = z.to_python() py_s = s.to_python() py_a = a.to_python() try: return Number.from_mpmath(mpmath.lerchphi(py_z, py_s, py_a)) except: pass
def apply(self, items, evaluation): 'Plus[items___]' items = items.numerify(evaluation).get_sequence() number = mpz(0) leaves = [] last_item = last_count = None def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append(Expression('Times', Number.from_mp(last_count), last_item)) for item in items: if isinstance(item, Number): number = add(number, item.value) else: count = rest = None if item.has_form('Times', None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.value rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression('Times', *rest) break if count is None: count = mpz(1) rest = item if last_item is not None and last_item == rest: last_count = add(last_count, count) else: append_last() last_item = rest last_count = count append_last() if not (get_type(number) == 'z' and number == 0): leaves.insert(0, Number.from_mp(number)) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression('Plus', *leaves)
def post_parse(self, expression): if len(expression.leaves) == 2: if isinstance(expression.leaves[0], Integer) and \ isinstance(expression.leaves[1], Integer) and expression.leaves[1].to_sympy() != 0: return Number.from_mp(Rational(expression.leaves[0].to_sympy(), expression.leaves[1].to_sympy()).to_sympy()) else: if isinstance(expression.leaves[0], Integer) and expression.leaves[0].to_sympy() == 1: return Expression('Power', expression.leaves[1].post_parse(), Integer(-1)) else: return Expression('Times', expression.leaves[0].post_parse(), Expression('Power', expression.leaves[1].post_parse(), Integer(-1))) else: return super(Divide, self).post_parse(expression)
def apply(self, r, i, evaluation): 'Complex[r_?NumberQ, i_?NumberQ]' if isinstance(r, Complex) or isinstance(i, Complex): sym_form = r.to_sympy() + sympy.I * i.to_sympy() sym_r, sym_i = sym_form.simplify().as_real_imag() else: sym_r, sym_i = r.to_sympy(), i.to_sympy() if isinstance(sym_i, sympy.Integer) and sym_i == 0: return Number.from_mp(sym_r) else: return Complex(sym_r, sym_i)
def apply(self, imin, imax, di, evaluation): 'Range[imin_?RealNumberQ, imax_?RealNumberQ, di_?RealNumberQ]' imin = imin.value imax = imax.value di = di.value index = imin result = [] while index <= imax: evaluation.check_stopped() result.append(Number.from_mp(index)) index += di return Expression('List', *result)
def mp_eig(mp_matrix) -> Expression: try: _, ER = mp.eig(mp_matrix) except: return None eigenvalues = ER.tolist() # Sort the eigenvalues in the Mathematica convention: largest first. eigenvalues.sort(key=lambda v: (abs(v[0]), -v[0].real, -(v[0].imag)), reverse=True) eigenvalues = [[Number.from_mpmath(c) for c in row] for row in eigenvalues] return Expression("List", *eigenvalues)
def apply(self, r, i, evaluation): "Complex[r_?NumberQ, i_?NumberQ]" if isinstance(r, Complex) or isinstance(i, Complex): sym_form = r.to_sympy() + sympy.I * i.to_sympy() sym_r, sym_i = sym_form.simplify().as_real_imag() else: sym_r, sym_i = r.to_sympy(), i.to_sympy() if isinstance(sym_i, sympy.Integer) and sym_i == 0: return Number.from_mp(sym_r) else: return Complex(sym_r, sym_i)
def apply_inexact(self, n, k, evaluation): 'Binomial[n_?InexactNumberQ, k_?NumberQ]' with workprec(min_prec(n, k)): n = gmpy2mpmath(n.value) k = gmpy2mpmath(k.value) result = mpmath.binomial(n, k) try: result = mpmath2gmpy(result) except SpecialValueError, exc: return Symbol(exc.name) number = Number.from_mp(result) return number
def apply(self, items, evaluation): 'Times[items___]' items = items.numerify(evaluation).get_sequence() number = mpz(1) leaves = [] for item in items: if isinstance(item, Number): if get_type(item.value) == 'z' and item.value == 0: return Integer('0') number = mul(number, item.value) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif leaves and item.has_form('Power', 2) and leaves[-1].has_form( 'Power', 2) and item.leaves[0].same(leaves[-1].leaves[0]): leaves[-1].leaves[1] = Expression('Plus', item.leaves[1], leaves[-1].leaves[1]) elif leaves and item.has_form('Power', 2) and item.leaves[0].same( leaves[-1]): leaves[-1] = Expression( 'Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif leaves and leaves[-1].has_form( 'Power', 2) and leaves[-1].leaves[0].same(item): leaves[-1] = Expression( 'Power', item, Expression('Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if get_type(number) == 'z': if number == 1: number = None elif number == -1 and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [ Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves ] number = None if number is not None: leaves.insert(0, Number.from_mp(number)) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' if di.get_int_value() == 1 and isinstance(self, SympyFunction): whole_expr = Expression(self.get_name(), expr, Expression('List', i, imin, imax)) sympy_expr = whole_expr.to_sympy() # apply Together to produce results similar to Mathematica result = sympy.together(sympy_expr) result = from_sympy(result) result = cancel(result) if not result.same(whole_expr): return result index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = index + di return self.get_result(result)
def apply_N(self, k, precision, evaluation): 'N[AiryBiZero[k_Integer], precision_]' try: d = get_precision(precision, evaluation) except PrecisionValueError: return if d is None: p = machine_precision else: p = _prec(d) k_int = k.get_int_value() with mpmath.workprec(p): result = mpmath.airybizero(k_int) return Number.from_mpmath(result, d)
def chop(expr, delta=10.0**(-10.0)): if isinstance(expr, Real): if -delta < expr.to_python() < delta: return Integer(0) #return expr elif isinstance(expr, Complex) and expr.get_precision() is not None: real, imag = expr.real, expr.imag if -delta < real.to_python() < delta: real = sympy.Integer(0) if -delta < imag.to_python() < delta: imag = sympy.Integer(0) if imag != 0: return Complex(real, imag) else: return Number.from_mp(real) elif isinstance(expr, Expression): return Expression(chop(expr.head), *[chop(leaf) for leaf in expr.leaves]) return expr
def chop(expr, delta=10.0 ** (-10.0)): if isinstance(expr, Real): if -delta < expr.to_python() < delta: return Integer(0) # return expr elif isinstance(expr, Complex) and expr.get_precision() is not None: real, imag = expr.real, expr.imag if -delta < real.to_python() < delta: real = sympy.Integer(0) if -delta < imag.to_python() < delta: imag = sympy.Integer(0) if imag != 0: return Complex(real, imag) else: return Number.from_mp(real) elif isinstance(expr, Expression): return Expression(chop(expr.head), *[chop(leaf) for leaf in expr.leaves]) return expr
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' if di.get_int_value() == 1 and isinstance(self, SageFunction): whole_expr = Expression(self.get_name(), expr, Expression('List', i, imin, imax)) sympy_expr = whole_expr.to_sympy() # apply Together to produce results similar to Mathematica result = sympy.together(sympy_expr) result = from_sympy(result) result = cancel(result) if not result.same(whole_expr): return result index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = add(index, di) return self.get_result(result)
def post_parse(self, expression): if len(expression.leaves) == 2: if isinstance(expression.leaves[0], Integer) and \ isinstance(expression.leaves[1], Integer) and expression.leaves[1].value != 0: return Number.from_mp( Rational(expression.leaves[0].value, expression.leaves[1].value).value) else: if isinstance(expression.leaves[0], Integer) and expression.leaves[0].value == 1: return Expression('Power', expression.leaves[1].post_parse(), Integer(-1)) else: return Expression( 'Times', expression.leaves[0].post_parse(), Expression('Power', expression.leaves[1].post_parse(), Integer(-1))) else: return super(Divide, self).post_parse(expression)
def post_parse(self, expression): if len(expression.leaves) == 2: if (isinstance(expression.leaves[0], Integer) and # noqa isinstance(expression.leaves[1], Integer) and expression.leaves[1].to_sympy() != 0): return Number.from_mp( Rational(expression.leaves[0].to_sympy(), expression.leaves[1].to_sympy()).to_sympy()) else: if (isinstance(expression.leaves[0], Integer) and # noqa expression.leaves[0].to_sympy() == 1): return Expression('Power', expression.leaves[1].post_parse(), Integer(-1)) else: return Expression( 'Times', expression.leaves[0].post_parse(), Expression('Power', expression.leaves[1].post_parse(), Integer(-1))) else: return super(Divide, self).post_parse(expression)
def apply_complex(self, number, evaluation): 'Re[number_Complex]' return Number.from_mp(number.value.real)
def apply(self, items, evaluation): 'Plus[items___]' items = items.numerify(evaluation).get_sequence() leaves = [] last_item = last_count = None prec = min_prec(*items) is_real = all([not isinstance(i, Complex) for i in items]) if prec is None: number = (sympy.Integer(0), sympy.Integer(0)) else: number = (sympy.Float('0.0', dps(prec)), sympy.Float('0.0', dps(prec))) def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append( Expression('Times', Number.from_mp(last_count), last_item)) for item in items: if isinstance(item, Number): # TODO: Optimise this for the case of adding many real numbers if isinstance(item, Complex): sym_real, sym_imag = item.real.to_sympy( ), item.imag.to_sympy() else: sym_real, sym_imag = item.to_sympy(), sympy.Integer(0) if prec is not None: sym_real = sym_real.n(dps(prec)) sym_imag = sym_imag.n(dps(prec)) number = (number[0] + sym_real, number[1] + sym_imag) else: count = rest = None if item.has_form('Times', None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.to_sympy() rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression('Times', *rest) break if count is None: count = sympy.Integer(1) rest = item if last_item is not None and last_item == rest: last_count = add(last_count, count) else: append_last() last_item = rest last_count = count append_last() if prec is not None or number != (0, 0): if number[1].is_zero and is_real: leaves.insert(0, Number.from_mp(number[0], prec)) elif number[1].is_zero and number[1].is_Integer and prec is None: leaves.insert(0, Number.from_mp(number[0], prec)) else: leaves.insert(0, Complex(number[0], number[1], prec)) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression('Plus', *leaves)
def apply_complex(self, z, evaluation): 'Abs[z_Complex]' real, imag = z.to_sympy().as_real_imag() return Expression('Sqrt', Expression('Plus', Number.from_mp(real ** 2), Number.from_mp(imag ** 2)))
def apply(self, items, evaluation): 'Power[items__]' items_sequence = items.get_sequence() if len(items_sequence) == 2: x, y = items_sequence else: return Expression('Power', *items_sequence) if y.get_int_value() == 1: return x elif x.get_int_value() == 1: return x elif y.get_int_value() == 0: if x.get_int_value() == 0: evaluation.message('Power', 'indet', Expression('Power', x, y)) return Symbol('Indeterminate') else: return Integer(1) elif x.has_form('Power', 2) and isinstance(y, Integer): return Expression('Power', x.leaves[0], Expression('Times', x.leaves[1], y)) elif x.has_form('Times', None) and isinstance(y, Integer): return Expression('Times', *[Expression('Power', leaf, y) for leaf in x.leaves]) elif isinstance(x, (Rational, Integer)) and isinstance(y, Integer): if y.value >= 0: result = mpq(x.value) ** y.value return Number.from_mp(result) else: if x.value == 0: evaluation.message('Power', 'infy') return Symbol('ComplexInfinity') else: # BUG in gmpy 1.14: mpz(1).qdiv(mpz(2)) == 2 denom = mpq(x.value) ** mpq(-y.value) return Number.from_mp(mpz(1) / denom) elif isinstance(x, (Integer, Rational)) and isinstance(y, Rational): try: if y.value >= 0: neg = x.value < 0 result = mpq(-x.value if neg else x.value) ** y.value result = Number.from_mp(result) if neg: result = Expression('Times', result, Symbol('I')) return result else: if x.value == 0: evaluation.message('Power', 'infy') return Symbol('ComplexInfinity') else: return Number.from_mp(mpz(1).qdiv(x.value ** (-y.value))) except ValueError: return Expression('Power', x, y) elif isinstance(x, Real) and isinstance(y, Integer): if y.value >= 0: return Number.from_mp(x.value ** y.value) else: if x.value == 0: evaluation.message('Power', 'infy') return Symbol('ComplexInfinity') else: return Number.from_mp(x.value ** y.value) elif (isinstance(x, Complex) and isinstance(y, (Integer, Real))) or \ (isinstance(x, Real) and isinstance(y, Complex)) or \ (isinstance(x, Complex) and x.is_inexact() and isinstance(y, (Rational, Complex))) or \ (isinstance(x, Complex) and isinstance(y, Complex) and y.is_inexact()): try: return Number.from_mp(x.value ** y.value) except ZeroDivisionError: evaluation.message('Power', 'infy') return Symbol('ComplexInfinity') elif (isinstance(x, Number) and isinstance(y, Real)) or (isinstance(x, Real) and \ isinstance(y, Number)): try: return Number.from_mp(real_power(x.value, y.value)) except ZeroDivisionError: evaluation.message('Power', 'infy') return Symbol('ComplexInfinity') else: numerified_items = items.numerify(evaluation) return Expression('Power', *numerified_items.get_sequence())
z = gmpy2mpmath(z.value) try: result = self.eval(z) except ValueError, exc: text = str(exc) if text == 'gamma function pole': return Symbol('ComplexInfinity') else: raise except ZeroDivisionError: return try: result = mpmath2gmpy(result) except SpecialValueError, exc: return Symbol(exc.name) number = Number.from_mp(result) return number class Plus(BinaryOperator, SageFunction): """ 'Plus' represents a sum of terms. >> 1 + 2 = 3 'Plus' performs basic simplification of terms: >> a + b + a = 2 a + b >> a + a + 3 * a = 5 a
def apply(self, expr, k, evaluation): "Round[expr_?RealNumberQ, k_?RealNumberQ]" return Number.from_mp(round(expr.value, k.value))
def apply_complex(self, number, evaluation): 'Im[number_Complex]' real, imag = number.to_sympy().as_real_imag() return Number.from_mp(imag)
def apply(self, items, evaluation): "Plus[items___]" items = items.numerify(evaluation).get_sequence() leaves = [] last_item = last_count = None prec = min_prec(*items) is_real = all([not isinstance(i, Complex) for i in items]) if prec is None: number = (sympy.Integer(0), sympy.Integer(0)) else: number = (sympy.Float("0.0", dps(prec)), sympy.Float("0.0", dps(prec))) def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form("Times", None): last_item.leaves.insert(0, Number.from_mp(last_count)) leaves.append(last_item) else: leaves.append(Expression("Times", Number.from_mp(last_count), last_item)) for item in items: if isinstance(item, Number): # TODO: Optimise this for the case of adding many real numbers if isinstance(item, Complex): sym_real, sym_imag = item.real.to_sympy(), item.imag.to_sympy() else: sym_real, sym_imag = item.to_sympy(), sympy.Integer(0) if prec is not None: sym_real = sym_real.n(dps(prec)) sym_imag = sym_imag.n(dps(prec)) number = (number[0] + sym_real, number[1] + sym_imag) else: count = rest = None if item.has_form("Times", None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.to_sympy() rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression("Times", *rest) break if count is None: count = sympy.Integer(1) rest = item if last_item is not None and last_item == rest: last_count = add(last_count, count) else: append_last() last_item = rest last_count = count append_last() if prec is not None or number != (0, 0): if number[1].is_zero and is_real: leaves.insert(0, Number.from_mp(number[0], prec)) elif number[1].is_zero and number[1].is_Integer and prec is None: leaves.insert(0, Number.from_mp(number[0], prec)) else: leaves.insert(0, Complex(number[0], number[1], prec)) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression("Plus", *leaves)
def apply(self, items, evaluation): 'Times[items___]' items = items.numerify(evaluation).get_sequence() leaves = [] numbers = [] prec = min_prec(*items) is_machine_precision = any(item.is_machine_precision() for item in items) # find numbers and simplify Times -> Power for item in items: if isinstance(item, Number): numbers.append(item) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif (leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0])): leaves[-1].leaves[1] = Expression( 'Plus', item.leaves[1], leaves[-1].leaves[1]) elif (leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1])): leaves[-1] = Expression( 'Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif (leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item)): leaves[-1] = Expression('Power', item, Expression( 'Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if numbers: if prec is not None: if is_machine_precision: numbers = [item.to_mpmath() for item in numbers] number = mpmath.fprod(numbers) number = Number.from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fprod(numbers) number = Number.from_mpmath(number, dps(prec)) else: number = sympy.Mul(*[item.to_sympy() for item in numbers]) number = from_sympy(number) else: number = Integer(1) if number.same(Integer(1)): number = None elif number.is_zero: return number elif number.same(Integer(-1)) and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves] number = None for leaf in leaves: leaf.last_evaluated = None if number is not None: leaves.insert(0, number) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def apply(self, items, evaluation): 'Times[items___]' # TODO: Clean this up and optimise it items = items.numerify(evaluation).get_sequence() number = (sympy.Integer(1), sympy.Integer(0)) leaves = [] prec = min_prec(*items) is_real = all([not isinstance(i, Complex) for i in items]) for item in items: if isinstance(item, Number): if isinstance(item, Complex): sym_real, sym_imag = item.real.to_sympy( ), item.imag.to_sympy() else: sym_real, sym_imag = item.to_sympy(), sympy.Integer(0) if prec is not None: sym_real = sym_real.n(dps(prec)) sym_imag = sym_imag.n(dps(prec)) if sym_real.is_zero and sym_imag.is_zero and prec is None: return Integer('0') number = (number[0] * sym_real - number[1] * sym_imag, number[0] * sym_imag + number[1] * sym_real) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif (leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0])): leaves[-1].leaves[1] = Expression('Plus', item.leaves[1], leaves[-1].leaves[1]) elif (leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1])): leaves[-1] = Expression( 'Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif (leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item)): leaves[-1] = Expression( 'Power', item, Expression('Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if number == (1, 0): number = None elif number == (-1, 0) and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [ Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves ] number = None if number is not None: if number[1].is_zero and is_real: leaves.insert(0, Number.from_mp(number[0], prec)) elif number[1].is_zero and number[1].is_Integer and prec is None: leaves.insert(0, Number.from_mp(number[0], prec)) else: leaves.insert( 0, Complex(from_sympy(number[0]), from_sympy(number[1]), prec)) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def apply_complex(self, number, evaluation): 'Im[number_Complex]' return Number.from_mp(number.value.imag)
def apply_complex(self, z, evaluation): 'Abs[z_Complex]' return Expression('Sqrt', Expression('Plus', Number.from_mp(z.value.real ** 2), Number.from_mp(z.value.imag ** 2)))
def apply_complex(self, number, evaluation): "Im[number_Complex]" real, imag = number.to_sympy().as_real_imag() return Number.from_mp(imag)
def apply(self, items, evaluation): 'Plus[items___]' items = items.numerify(evaluation).get_sequence() leaves = [] last_item = last_count = None prec = min_prec(*items) is_machine_precision = any(item.is_machine_precision() for item in items) numbers = [] def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, from_sympy(last_count)) leaves.append(last_item) else: leaves.append(Expression( 'Times', from_sympy(last_count), last_item)) for item in items: if isinstance(item, Number): numbers.append(item) else: count = rest = None if item.has_form('Times', None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.to_sympy() rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression('Times', *rest) break if count is None: count = sympy.Integer(1) rest = item if last_item is not None and last_item == rest: last_count = last_count + count else: append_last() last_item = rest last_count = count append_last() if numbers: if prec is not None: if is_machine_precision: numbers = [item.to_mpmath() for item in numbers] number = mpmath.fsum(numbers) number = Number.from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fsum(numbers) number = Number.from_mpmath(number, dps(prec)) else: number = from_sympy(sum(item.to_sympy() for item in numbers)) else: number = Integer(0) if not number.same(Integer(0)): leaves.insert(0, number) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression('Plus', *leaves)
def apply_complex(self, z, evaluation): "Abs[z_Complex]" real, imag = z.to_sympy().as_real_imag() return Expression("Sqrt", Expression("Plus", Number.from_mp(real ** 2), Number.from_mp(imag ** 2)))