Пример #1
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
Пример #2
0
    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
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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
Пример #6
0
    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)