예제 #1
0
    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)
예제 #2
0
    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))
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
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