def apply(self, z, evaluation): "%(name)s[z__]" args = z.numerify(evaluation).get_sequence() mpmath_function = self.get_mpmath_function(tuple(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 = call_mpmath(mpmath_function, tuple(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", Integer1) elif mpmath.isinf(result) and result < 0: result = Expression("DirectedInfinity", Integer(-1)) elif mpmath.isnan(result): result = Symbol("Indeterminate") else: result = from_mpmath(result) else: prec = min_prec(*args) d = dps(prec) args = [apply_N(arg, evaluation, Integer(d)) for arg in args] with mpmath.workprec(prec): mpmath_args = [x.to_mpmath() for x in args] if None in mpmath_args: return result = call_mpmath(mpmath_function, tuple(mpmath_args)) if isinstance(result, (mpmath.mpc, mpmath.mpf)): result = from_mpmath(result, d) return result
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 from_mpmath(mpmath.lerchphi(py_z, py_s, py_a)) except: pass
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 = [[from_mpmath(c) for c in row] for row in eigenvalues] return Expression("List", *eigenvalues)
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 from_mpmath(result, d)
def apply(self, items, evaluation): "Times[items___]" items = items.numerify(evaluation).get_sequence() leaves = [] numbers = [] infinity_factor = False 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].sameQ(leaves[-1].leaves[0])): leaves[-1] = Expression( "Power", leaves[-1].leaves[0], Expression("Plus", item.leaves[1], leaves[-1].leaves[1]), ) elif (leaves and item.has_form("Power", 2) and item.leaves[0].sameQ(leaves[-1])): leaves[-1] = Expression( "Power", leaves[-1], Expression("Plus", item.leaves[1], Integer1)) elif (leaves and leaves[-1].has_form("Power", 2) and leaves[-1].leaves[0].sameQ(item)): leaves[-1] = Expression( "Power", item, Expression("Plus", Integer1, leaves[-1].leaves[1])) elif item.get_head().sameQ(SymbolDirectedInfinity): infinity_factor = True if len(item.leaves) > 1: direction = item.leaves[0] if isinstance(direction, Number): numbers.append(direction) else: leaves.append(direction) elif item.sameQ(SymbolInfinity) or item.sameQ( SymbolComplexInfinity): infinity_factor = True 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 = from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fprod(numbers) number = from_mpmath(number, dps(prec)) else: number = sympy.Mul(*[item.to_sympy() for item in numbers]) number = from_sympy(number) else: number = Integer1 if number.sameQ(Integer1): number = None elif number.is_zero: if infinity_factor: return Symbol("Indeterminate") return number elif number.sameQ(Integer(-1)) and leaves and leaves[0].has_form( "Plus", None): leaves[0] = Expression( leaves[0].get_head(), *[ Expression("Times", Integer(-1), leaf) for leaf in leaves[0].leaves ], ) number = None for leaf in leaves: leaf.clear_cache() if number is not None: leaves.insert(0, number) if not leaves: if infinity_factor: return SymbolComplexInfinity return Integer1 if len(leaves) == 1: ret = leaves[0] else: ret = Expression("Times", *leaves) if infinity_factor: return Expression(SymbolDirectedInfinity, ret) else: return ret
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): leaves.append( Expression("Times", from_sympy(last_count), *last_item.leaves)) 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.get_mutable_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 = from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fsum(numbers) number = from_mpmath(number, dps(prec)) else: number = from_sympy(sum(item.to_sympy() for item in numbers)) else: number = Integer0 if not number.sameQ(Integer0): leaves.insert(0, number) if not leaves: return Integer0 elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression("Plus", *leaves)