def apply(self, n, b, evaluation): "MantissaExponent[n_, b_]" # Handle Input with special cases such as PI and E n_sympy, b_sympy = n.to_sympy(), b.to_sympy() expr = Expression("MantissaExponent", n, b) if isinstance(n.to_python(), complex): evaluation.message("MantissaExponent", "realx", n) return expr if n_sympy.is_constant(): temp_n = apply_N(n, evaluation) py_n = temp_n.to_python() else: return expr if b_sympy.is_constant(): temp_b = apply_N(b, evaluation) py_b = temp_b.to_python() else: return expr if not py_b > 1: evaluation.message("MantissaExponent", "rbase", b) return expr base_exp = int(mpmath.log(py_n, py_b)) exp = (base_exp + 1) if base_exp >= 0 else base_exp return Expression("List", Expression("Divide", n, b**exp), exp)
def apply(self, f, x, x0, evaluation, options): "FindRoot[f_, {x_, x0_}, OptionsPattern[]]" # First, determine x0 and x x0 = apply_N(x0, evaluation) if not isinstance(x0, Number): evaluation.message("FindRoot", "snum", x0) return x_name = x.get_name() if not x_name: evaluation.message("FindRoot", "sym", x, 2) return # Now, get the explicit form of f, depending of x # keeping x without evaluation (Like inside a "Block[{x},f]) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # If after evaluation, we get an "Equal" expression, # convert it in a function by substracting both # members. Again, ensure the scope in the evaluation if f.get_head_name() == "System`Equal": f = Expression("Plus", f.leaves[0], Expression("Times", Integer(-1), f.leaves[1])) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # Determine the method method = options["System`Method"] if isinstance(method, Symbol): method = method.get_name().split("`")[-1] if method == "Automatic": method = "Newton" elif not isinstance(method, String): method = None evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return else: method = method.value # Determine the "jacobian" if method in ("Newton", ) and options["System`Jacobian"].sameQ( Symbol("Automatic")): def diff(evaluation): return Expression("D", f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) options["System`Jacobian"] = d method = self.methods.get(method, None) if method is None: evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return x0, success = method(f, x0, x, options, evaluation) if not success: return return Expression(SymbolList, Expression(SymbolRule, x, x0))
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_2(self, n, evaluation): "MantissaExponent[n_]" n_sympy = n.to_sympy() expr = Expression("MantissaExponent", n) if isinstance(n.to_python(), complex): evaluation.message("MantissaExponent", "realx", n) return expr # Handle Input with special cases such as PI and E if n_sympy.is_constant(): temp_n = apply_N(n, evaluation) py_n = temp_n.to_python() else: return expr base_exp = int(mpmath.log10(py_n)) exp = (base_exp + 1) if base_exp >= 0 else base_exp return Expression("List", Expression("Divide", n, (10**exp)), exp)
def find_root_newton(f, x0, x, opts, evaluation) -> (Number, bool): df = opts["System`Jacobian"] maxit = opts["System`MaxIterations"] x_name = x.get_name() if maxit.sameQ(Symbol("Automatic")): maxit = 100 else: maxit = maxit.evaluate(evaluation).get_int_value() def sub(evaluation): d_value = df.evaluate(evaluation) if d_value == Integer(0): return None return Expression("Times", f, Expression("Power", d_value, Integer(-1))).evaluate(evaluation) count = 0 while count < maxit: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message("FindRoot", "dsing", x, x0) return x0, False x1 = Expression("Plus", x0, Expression("Times", Integer(-1), minus)).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message("FindRoot", "nnum", x, x0) return x0, False # TODO: use Precision goal... if x1 == x0: break x0 = apply_N(x1, evaluation) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message("FindRoot", "maxiter") return x0, True