Example #1
0
    def do_compare(self, l1, l2):
        if l1.same(l2):
            return True
        elif l1 == Symbol('System`True') and l2 == Symbol('System`False'):
            return False
        elif l1 == Symbol('System`False') and l2 == Symbol('System`True'):
            return False
        elif isinstance(l1, String) and isinstance(l2, String):
            return False
        elif l1.has_form('List', None) and l2.has_form('List', None):
            if len(l1.leaves) != len(l2.leaves):
                return False
            for item1, item2 in zip(l1.leaves, l2.leaves):
                result = self.do_compare(item1, item2)
                if not result:
                    return result
            return True

        l1_sympy = l1.to_sympy()
        l2_sympy = l2.to_sympy()

        if l1_sympy is None or l2_sympy is None:
            return None
        if l1_sympy.is_number and l2_sympy.is_number:
            # assert min_prec(l1, l2) is None
            prec = 64  # TODO: Use $MaxExtraPrecision
            if l1_sympy.n(dps(prec)) == l2_sympy.n(dps(prec)):
                return True
            return False
        else:
            return None
Example #2
0
    def do_compare(self, l1, l2):
        if l1.same(l2):
            return True
        elif l1 == Symbol('System`True') and l2 == Symbol('System`False'):
            return False
        elif l1 == Symbol('System`False') and l2 == Symbol('System`True'):
            return False
        elif isinstance(l1, String) and isinstance(l2, String):
            return False

        l1_sympy = l1.to_sympy()
        l2_sympy = l2.to_sympy()
        if l1_sympy is None or l2_sympy is None:
            return None
        if l1_sympy.is_number and l2_sympy.is_number:
            # assert min_prec(l1, l2) is None
            prec = 64  # TODO: Use $MaxExtraPrecision
            if l1_sympy.n(dps(prec)) == l2_sympy.n(dps(prec)):
                return True
            return False
        elif l1.has_form('List', None) and l2.has_form('List', None):
            if len(l1.leaves) != len(l2.leaves):
                return False
            for item1, item2 in zip(l1.leaves, l2.leaves):
                result = self.do_compare(item1, item2)
                if not result:
                    return result
            return True
        else:
            return None
Example #3
0
    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)
Example #4
0
    def equal2(self, l1: Any, l2: Any) -> Union[bool, None]:
        """
        Two-argument Equal[]
        """
        if l1.sameQ(l2):
            return True
        elif l1 == SymbolTrue and l2 == SymbolFalse:
            return False
        elif l1 == SymbolFalse and l2 == SymbolTrue:
            return False
        elif isinstance(l1, String) and isinstance(l2, String):
            return False
        elif l1.has_form("List", None) and l2.has_form("List", None):
            if len(l1.leaves) != len(l2.leaves):
                return False
            for item1, item2 in zip(l1.leaves, l2.leaves):
                result = self.equal2(item1, item2)
                if not result:
                    return result
            return True

        # Use Mathics' built-in comparisons for Real and Integer. These use
        # WL's interpretation of Equal[] which allows for slop in Reals
        # in the least significant digit of precision, while for Integers, comparison
        # has to be exact.

        if (isinstance(l1, Real)
                and isinstance(l2, Real)) or (isinstance(l1, Integer)
                                              and isinstance(l2, Integer)):
            return l1 == l2

        # For everything else, use sympy.

        l1_sympy = l1.to_sympy(evaluate=True, prec=COMPARE_PREC)
        l2_sympy = l2.to_sympy(evaluate=True, prec=COMPARE_PREC)

        if l1_sympy is None or l2_sympy is None:
            return None

        if not is_number(l1_sympy):
            l1_sympy = mp_convert_constant(l1_sympy, prec=COMPARE_PREC)
        if not is_number(l2_sympy):
            l2_sympy = mp_convert_constant(l2_sympy, prec=COMPARE_PREC)

        if l1_sympy.is_number and l2_sympy.is_number:
            # assert min_prec(l1, l2) is None
            prec = COMPARE_PREC  # TODO: Use $MaxExtraPrecision
            if l1_sympy.n(dps(prec)) == l2_sympy.n(dps(prec)):
                return True
            return False
        else:
            return None
Example #5
0
    def apply_makeboxes(self, expr, n, f, evaluation):
        '''MakeBoxes[BaseForm[expr_, n_],
            f:StandardForm|TraditionalForm|OutputForm]'''

        base = n.get_int_value()

        if base <= 0:
            evaluation.message('BaseForm', 'intpm', expr, n)
            return

        if not (isinstance(expr, Integer) or isinstance(expr, Real)):
            return Expression("MakeBoxes", expr, f)

        p = dps(expr.get_precision()) if isinstance(expr, Real) else 0

        try:
            val = convert_base(expr.get_real_value(), base, p)
        except ValueError:
            return evaluation.message('BaseForm', 'basf', n)

        if f.get_name() == 'System`OutputForm':
            return from_python("%s_%d" % (val, base))
        else:
            return Expression('SubscriptBox', from_python(val),
                              from_python(base))
Example #6
0
    def apply_makeboxes(self, expr, n, f, evaluation):
        '''MakeBoxes[BaseForm[expr_, n_],
            f:StandardForm|TraditionalForm|OutputForm]'''

        base = n.get_int_value()

        if base <= 0:
            evaluation.message('BaseForm', 'intpm', expr, n)
            return

        if not (isinstance(expr, Integer) or isinstance(expr, Real)):
            return Expression("MakeBoxes", expr, f)

        p = dps(expr.get_precision()) if isinstance(expr, Real) else 0

        try:
            val = convert_base(expr.get_real_value(), base, p)
        except ValueError:
            return evaluation.message('BaseForm', 'basf', n)

        if f.get_name() == 'System`OutputForm':
            return from_python("%s_%d" % (val, base))
        else:
            return Expression(
                'SubscriptBox', from_python(val), from_python(base))
Example #7
0
    def apply_complex(self, x, evaluation):
        'Precision[x_Complex]'

        if x.is_inexact():
            return Real(dps(x.get_precision()))
        else:
            return Symbol('Infinity')
Example #8
0
    def apply_complex(self, x, evaluation):
        'Precision[x_Complex]'

        if x.is_inexact():
            return Real(dps(x.get_precision()))
        else:
            return Symbol('Infinity')
Example #9
0
    def apply(self, z, evaluation):
        'Precision[z_]'

        if not z.is_inexact():
            return Symbol('Infinity')
        elif z.to_sympy().is_zero:
            return Real(0)
        else:
            return Real(dps(z.get_precision()))
Example #10
0
    def apply(self, z, evaluation):
        "Precision[z_]"

        if not z.is_inexact():
            return Symbol("Infinity")
        elif z.to_sympy().is_zero:
            return Real(0)
        else:
            return Real(dps(z.get_precision()))
Example #11
0
    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
Example #12
0
def do_compare(l1, l2):
    if l1.same(l2):
        return True
    elif isinstance(l1, String) and isinstance(l2, String):
        return False
    elif l1.to_sympy().is_number and l2.to_sympy().is_number:
        #assert min_prec(l1, l2) is None
        prec = 64       #TODO: Use $MaxExtraPrecision
        if l1.to_sympy().n(dps(prec)) == l2.to_sympy().n(dps(prec)):
           return True
        return False
    elif l1.has_form('List', None) and l2.has_form('List', None):
        if len(l1.leaves) != len(l2.leaves):
            return False
        for item1, item2 in zip(l1.leaves, l2.leaves):
            result = do_compare(item1, item2)
            if not result:
                return result
        return True
    else:
        return None
Example #13
0
def do_compare(l1, l2):
    if l1.same(l2):
        return True
    elif isinstance(l1, String) and isinstance(l2, String):
        return False
    elif l1.to_sympy().is_number and l2.to_sympy().is_number:
        #assert min_prec(l1, l2) is None
        prec = 64  #TODO: Use $MaxExtraPrecision
        if l1.to_sympy().n(dps(prec)) == l2.to_sympy().n(dps(prec)):
            return True
        return False
    elif l1.has_form('List', None) and l2.has_form('List', None):
        if len(l1.leaves) != len(l2.leaves):
            return False
        for item1, item2 in zip(l1.leaves, l2.leaves):
            result = do_compare(item1, item2)
            if not result:
                return result
        return True
    else:
        return None
Example #14
0
    def apply(self, f, xs, evaluation):
        'Integrate[f_, xs__]'

        f_sympy = f.to_sympy()
        if f_sympy is None or isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form('List', 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
                if a is None or b is None:
                    return
            else:
                a = b = None
            if not x.get_name():
                evaluation.message('Integrate', 'ilim')
                return
            x = x.to_sympy()
            if x is None:
                return
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return
        except ValueError:
            # e.g. ValueError: can't raise polynomial to a negative power
            return
        except NotImplementedError:
            # e.g. NotImplementedError: Result depends on the sign of
            # -sign(_Mathics_User_j)*sign(_Mathics_User_w)
            return

        if prec is not None and isinstance(result, sympy.Integral):
            # TODO MaxExtaPrecision -> maxn
            result = result.evalf(dps(prec))
        result = from_sympy(result)
        return result
Example #15
0
    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
Example #16
0
    def apply(self, f, xs, evaluation):
        'Integrate[f_, xs__]'

        f_sympy = f.to_sympy()
        if f_sympy is None or isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form('List', 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
                if a is None or b is None:
                    return
            else:
                a = b = None
            if not x.get_name():
                evaluation.message('Integrate', 'ilim')
                return
            x = x.to_sympy()
            if x is None:
                return
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return
        except ValueError:
            # e.g. ValueError: can't raise polynomial to a negative power
            return
        except NotImplementedError:
            # e.g. NotImplementedError: Result depends on the sign of
            # -sign(_Mathics_User_j)*sign(_Mathics_User_w)
            return

        if prec is not None and isinstance(result, sympy.Integral):
            # TODO MaxExtaPrecision -> maxn
            result = result.evalf(dps(prec))
        result = from_sympy(result)
        return result
Example #17
0
    def do_compare(self, l1, l2):
        if l1.same(l2):
            return True
        elif l1 == SymbolTrue and l2 == SymbolFalse:
            return False
        elif l1 == SymbolFalse and l2 == SymbolTrue:
            return False
        elif isinstance(l1, String) and isinstance(l2, String):
            return False
        elif l1.has_form("List", None) and l2.has_form("List", None):
            if len(l1.leaves) != len(l2.leaves):
                return False
            for item1, item2 in zip(l1.leaves, l2.leaves):
                result = self.do_compare(item1, item2)
                if not result:
                    return result
            return True

        l1_sympy = l1.to_sympy(evaluate=True, prec=COMPARE_PREC)
        l2_sympy = l2.to_sympy(evaluate=True, prec=COMPARE_PREC)

        if l1_sympy is None or l2_sympy is None:
            return None

        if not hasattr(l1_sympy, "is_number"):
            l1_sympy = mp_convert_constant(l1_sympy, prec=COMPARE_PREC)
        if not hasattr(l2_sympy, "is_number"):
            l2_sympy = mp_convert_constant(l2_sympy, prec=COMPARE_PREC)

        if l1_sympy.is_number and l2_sympy.is_number:
            # assert min_prec(l1, l2) is None
            prec = COMPARE_PREC  # TODO: Use $MaxExtraPrecision
            if l1_sympy.n(dps(prec)) == l2_sympy.n(dps(prec)):
                return True
            return False
        else:
            return None
Example #18
0
    def sympy_equal(self, lhs, rhs, max_extra_prec=None) -> Optional[bool]:
        try:
            lhs_sympy = lhs.to_sympy(evaluate=True, prec=COMPARE_PREC)
            rhs_sympy = rhs.to_sympy(evaluate=True, prec=COMPARE_PREC)
        except NotImplementedError:
            return None

        if lhs_sympy is None or rhs_sympy is None:
            return None

        if not is_number(lhs_sympy):
            lhs_sympy = mp_convert_constant(lhs_sympy, prec=COMPARE_PREC)
        if not is_number(rhs_sympy):
            rhs_sympy = mp_convert_constant(rhs_sympy, prec=COMPARE_PREC)

        # WL's interpretation of Equal[] which allows for slop in Reals
        # in the least significant digit of precision, while for Integers, comparison
        # has to be exact.

        if lhs_sympy.is_number and rhs_sympy.is_number:
            # assert min_prec(lhs, rhs) is None
            if max_extra_prec:
                prec = max_extra_prec
            else:
                prec = COMPARE_PREC
            lhs = lhs_sympy.n(dps(prec))
            rhs = rhs_sympy.n(dps(prec))
            if lhs == rhs:
                return True
            tol = 10 ** (-prec)
            diff = abs(lhs - rhs)
            if isinstance(diff, sympy.core.add.Add):
                return sympy.re(diff) < tol
            else:
                return diff < tol
        else:
            return None
Example #19
0
    def apply_makeboxes(self, expr, n, f, evaluation):
        """MakeBoxes[BaseForm[expr_, n_],
            f:StandardForm|TraditionalForm|OutputForm]"""

        base = n.get_int_value()

        if base <= 0:
            evaluation.message("BaseForm", "intpm", expr, n)
            return

        if not (isinstance(expr, Integer) or isinstance(expr, Real)):
            return Expression("MakeBoxes", expr, f)

        p = dps(expr.get_precision()) if isinstance(expr, Real) else 0
        val = convert_base(expr.get_real_value(), base, p)

        if f.get_name() == "OutputForm":
            return from_python("%s_%d" % (val, base))
        else:
            return Expression("SubscriptBox", from_python(val), from_python(base))
Example #20
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):
                        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)
Example #21
0
    def apply(self, f, xs, evaluation, options):
        "Integrate[f_, xs__, OptionsPattern[]]"
        self.patpow0 = Pattern.create(
            Expression("Power", Integer0, Expression("Blank")))
        assuming = options["System`Assumptions"].evaluate(evaluation)
        f_sympy = f.to_sympy()
        if f_sympy is None or isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form("List", 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
                if a is None or b is None:
                    return
            else:
                a = b = None
            if not x.get_name():
                evaluation.message("Integrate", "ilim")
                return
            x = x.to_sympy()
            if x is None:
                return
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return
        except ValueError:
            # e.g. ValueError: can't raise polynomial to a negative power
            return
        except NotImplementedError:
            # e.g. NotImplementedError: Result depends on the sign of
            # -sign(_Mathics_User_j)*sign(_Mathics_User_w)
            return
        if prec is not None and isinstance(result, sympy.Integral):
            # TODO MaxExtaPrecision -> maxn
            result = result.evalf(dps(prec))
        else:
            result = from_sympy(result)
        # If the result is defined as a Piecewise expression,
        # use ConditionalExpression.
        # This does not work now because the form sympy returns the values
        if result.get_head_name() == "System`Piecewise":
            cases = result._leaves[0]._leaves
            if len(result._leaves) == 1:
                if cases[-1]._leaves[1].is_true():
                    default = cases[-1]._leaves[0]
                    cases = result._leaves[0]._leaves[:-1]
                else:
                    default = SymbolUndefined
            else:
                cases = result._leaves[0]._leaves
                default = result._leaves[1]
            if default.has_form("Integrate", None):
                if default._leaves[0] == f:
                    default = SymbolUndefined

            simplified_cases = []
            for case in cases:
                # TODO: if something like 0^n or 1/expr appears,
                # put the condition n!=0 or expr!=0 accordingly in the list of
                # conditions...
                cond = Expression("Simplify", case._leaves[1],
                                  assuming).evaluate(evaluation)
                resif = Expression("Simplify", case._leaves[0],
                                   assuming).evaluate(evaluation)
                if cond.is_true():
                    return resif
                if resif.has_form("ConditionalExpression", 2):
                    cond = Expression("And", resif._leaves[1], cond)
                    cond = Expression("Simplify", cond,
                                      assuming).evaluate(evaluation)
                    resif = resif._leaves[0]
                simplified_cases.append(Expression(SymbolList, resif, cond))
            cases = simplified_cases
            if default == SymbolUndefined and len(cases) == 1:
                cases = cases[0]
                result = Expression("ConditionalExpression", *(cases._leaves))
            else:
                result = Expression(result._head, cases, default)
        else:
            result = Expression("Simplify", result,
                                assuming).evaluate(evaluation)
        return result
Example #22
0
 def apply_N(self, precision, evaluation):
     'N[E, precision_]'
     precision = get_precision(precision, evaluation)
     if precision is not None:
         return Real(sympy.E.n(dps(precision)), p=precision)
Example #23
0
    def convert_Number(self, node):
        s = node.value
        if s[0] == '-':
            sign_prefix, s = s[0], s[1:]
            sign = -1
        else:
            sign_prefix = ''
            sign = 1

        # fast exit
        if s.isdigit():
            return ma.Integer(sign * int(s))

        # Look for base
        s = s.split('^^')
        if len(s) == 1:
            base, s = 10, s[0]
        else:
            assert len(s) == 2
            base, s = int(s[0]), s[1]
            assert 2 <= base <= 36

        # Look for mantissa
        s = s.split('*^')
        if len(s) == 1:
            n, s = 0, s[0]
        else:
            # TODO: modify regex and provide error message if n not an int
            n, s = int(s[1]), s[0]

        # Look at precision ` suffix to get precision/accuracy
        prec, acc = None, None
        s = s.split('`', 1)
        if len(s) == 1:
            suffix, s = None, s[0]
        else:
            suffix, s = s[1], s[0]

            if suffix == '':
                prec = machine_precision
            elif suffix.startswith('`'):
                acc = float(suffix[1:])
            else:
                if re.match('0+$', s) is not None:
                    return ma.Integer(0)
                prec = float(suffix)

        # Look for decimal point
        if s.count('.') == 0:
            if suffix is None:
                if n < 0:
                    return ma.Rational(sign * int(s, base), base**abs(n))
                else:
                    return ma.Integer(sign * int(s, base) * (base**n))
            else:
                s = s + '.'
        if base == 10:
            if n != 0:
                s = s + 'E' + str(n)  # sympy handles this
            if acc is not None:
                if float(s) == 0:
                    prec = 0.
                else:
                    prec = acc + log10(float(s)) + n
            # XXX
            if prec is not None:
                prec = dps(prec)
            # return ma.Real(s, prec, acc)
            return ma.Real(sign_prefix + s, prec)
        else:
            # Convert the base
            assert isinstance(base, int) and 2 <= base <= 36

            # Put into standard form mantissa * base ^ n
            s = s.split('.')
            if len(s) == 1:
                man = s[0]
            else:
                n -= len(s[1])
                man = s[0] + s[1]

            man = sign * int(man, base)
            if n >= 0:
                result = ma.Integer(man * base**n)
            else:
                result = ma.Rational(man, base**-n)

            if acc is None and prec is None:
                acc = len(s[1])
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
                if prec10 < 18:
                    prec10 = None
            elif acc is not None:
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
            elif prec is not None:
                if prec == machine_precision:
                    prec10 = machine_precision
                else:
                    prec10 = prec * log10(base)
            # XXX
            if prec10 is None:
                prec10 = machine_precision
            else:
                prec10 = dps(prec10)
            return result.round(prec10)
Example #24
0
    def apply_real(self, x, evaluation):
        'Precision[x_Real]'

        return Real(dps(x.get_precision()))
Example #25
0
    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)
Example #26
0
Support for numeric evaluation with arbitrary precision is just a proof-of-concept.
Precision is not "guarded" through the evaluation process. Only integer precision is supported.
However, things like 'N[Pi, 100]' should work as expected.
"""

from gmpy import mpz, mpf
import mpmath
from mpmath import mpi

from mathics.builtin.base import Builtin, Predefined
from mathics.core.numbers import dps, mpmath2gmpy
from mathics.core import numbers
from mathics.core.expression import Integer, Rational, Real, Complex, Atom, Expression, Number, Symbol

machine_precision = dps(mpf(64))


def get_precision(prec, evaluation):
    if prec.get_name() == "MachinePrecision":
        return numbers.prec(machine_precision)
    elif isinstance(prec, (Integer, Rational, Real)):
        return numbers.prec(prec.value)
    else:
        evaluation.message("N", "precbd", prec)
        return None


class N(Builtin):
    """
    <dl>
Example #27
0
    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)
Example #28
0
    def t_number(self, t):
        r'''
        ( (?# Two possible forms depending on whether base is specified)
            (\d+\^\^([a-zA-Z0-9]+\.?[a-zA-Z0-9]*|[a-zA-Z0-9]*\.?[a-zA-Z0-9]+))
            | (\d+\.?\d*|\d*\.?\d+)
        )
        (``?(\+|-)?(\d+\.?\d*|\d*\.?\d+)|`)?        (?# Precision / Accuracy)
        (\*\^(\+|-)?\d+)?                           (?# Exponent)
        '''
        s = t.value

        # Look for base
        s = s.split('^^')
        if len(s) == 1:
            base, s = 10, s[0]
        else:
            assert len(s) == 2
            base, s = int(s[0]), s[1]
            assert 2 <= base <= 36

        # Look for mantissa
        s = s.split('*^')
        if len(s) == 1:
            n, s = 0, s[0]
        else:
            # TODO: modify regex and provide error message if n not an int
            n, s = int(s[1]), s[0]

        # Look at precision ` suffix to get precision/accuracy
        prec, acc = None, None
        s = s.split('`', 1)
        if len(s) == 1:
            suffix, s = None, s[0]
        else:
            suffix, s = s[1], s[0]

            if suffix == '':
                prec = machine_precision
            elif suffix.startswith('`'):
                acc = float(suffix[1:])
            else:
                if re.match('0+$', s) is not None:
                    t.value = Integer(0)
                    return t
                prec = float(suffix)

        # Look for decimal point
        if s.count('.') == 0:
            if suffix is None:
                if n < 0:
                    t.value = Rational(int(s, base), base ** abs(n))
                else:
                    t.value = Integer(int(s, base) * (base ** n))
                return t
            else:
                s = s + '.'

        if base == 10:
            if n != 0:
                s = s + 'E' + str(n)    # sympy handles this

            if acc is not None:
                if float(s) == 0:
                    prec = 0.
                else:
                    prec = acc + log10(float(s)) + n

            # XXX
            if prec is not None:
                prec = dps(prec)
            t.value = Real(s, prec)
            # t.value = Real(s, prec, acc)
        else:
            # Convert the base
            assert isinstance(base, int) and 2 <= base <= 36

            # Put into standard form mantissa * base ^ n
            s = s.split('.')
            if len(s) == 1:
                man = s[0]
            else:
                n -= len(s[1])
                man = s[0] + s[1]

            man = int(man, base)

            if n >= 0:
                result = Integer(man * base ** n)
            else:
                result = Rational(man, base ** -n)

            if acc is None and prec is None:
                acc = len(s[1])
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
                if prec10 < 18:
                    prec10 = None
            elif acc is not None:
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
            elif prec is not None:
                if prec == machine_precision:
                    prec10 = machine_precision
                else:
                    prec10 = prec * log10(base)
            # XXX
            if prec10 is None:
                prec10 = machine_precision
            else:
                prec10 = dps(prec10)

            t.value = result.round(prec10)

        return t
Example #29
0
    def apply_real(self, x, evaluation):
        'Precision[x_Real]'

        return Real(dps(x.get_precision()))
Example #30
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):
                        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)
Example #31
0
 def apply_N(self, precision, evaluation):
     'N[E, precision_]'
     precision = get_precision(precision, evaluation)
     if precision is not None:
         return Real(sympy.E.n(dps(precision)), p=precision)
Example #32
0
    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)
Example #33
0
Support for numeric evaluation with arbitrary precision is just a proof-of-concept.
Precision is not "guarded" through the evaluation process. Only integer precision is supported.
However, things like 'N[Pi, 100]' should work as expected.
"""

from gmpy import mpz, mpf
import mpmath
from mpmath import mpi

from mathics.builtin.base import Builtin, Predefined
from mathics.core.numbers import dps, mpmath2gmpy
from mathics.core import numbers
from mathics.core.expression import Integer, Rational, Real, Complex, Atom, Expression, Number, Symbol

machine_precision = dps(mpf(53))


def get_precision(prec, evaluation):
    if prec.get_name() == 'MachinePrecision':
        return numbers.prec(machine_precision)
    elif isinstance(prec, (Integer, Rational, Real)):
        return numbers.prec(prec.value)
    else:
        evaluation.message('N', 'precbd', prec)
        return None


class N(Builtin):
    """
    <dl>
Example #34
0
    def apply_N(self, prec, evaluation):
        'N[MachinePrecision, prec_]'

        prec = get_precision(prec, evaluation)
        if prec is not None:
            return Real(dps(machine_precision), prec)
Example #35
0
Support for numeric evaluation with arbitrary precision is just a proof-of-concept.
Precision is not "guarded" through the evaluation process. Only integer precision is supported.
However, things like 'N[Pi, 100]' should work as expected.
"""

from gmpy import mpz, mpf
import mpmath
from mpmath import mpi

from mathics.builtin.base import Builtin, Predefined
from mathics.core.numbers import dps, mpmath2gmpy
from mathics.core import numbers
from mathics.core.expression import Integer, Rational, Real, Complex, Atom, Expression, Number, Symbol

machine_precision = dps(mpf(53))

def get_precision(prec, evaluation):
    if prec.get_name() == 'MachinePrecision':
        return numbers.prec(machine_precision)
    elif isinstance(prec, (Integer, Rational, Real)):
        return numbers.prec(prec.value)
    else:
        evaluation.message('N', 'precbd', prec)
        return None

class N(Builtin):
    """
    <dl>
    <dt>'N[$expr$, $prec$]'
        <dd>evaluates $expr$ numerically with a precision of $prec$ digits.
Example #36
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
Example #37
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_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)
Example #38
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_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)
Example #39
0
    def t_number(self, t):
        r'''
        ( (?# Two possible forms depending on whether base is specified)
            (\d+\^\^([a-zA-Z0-9]+\.?[a-zA-Z0-9]*|[a-zA-Z0-9]*\.?[a-zA-Z0-9]+))
            | (\d+\.?\d*|\d*\.?\d+)
        )
        (``?(\+|-)?(\d+\.?\d*|\d*\.?\d+)|`)?        (?# Precision / Accuracy)
        (\*\^(\+|-)?\d+)?                           (?# Exponent)
        '''
        s = t.value

        # Look for base
        s = s.split('^^')
        if len(s) == 1:
            base, s = 10, s[0]
        else:
            assert len(s) == 2
            base, s = int(s[0]), s[1]
            assert 2 <= base <= 36

        # Look for mantissa
        s = s.split('*^')
        if len(s) == 1:
            n, s = 0, s[0]
        else:
            #TODO: modify regex and provide error message if n not an int
            n, s = int(s[1]), s[0]

        # Look at precision ` suffix to get precision/accuracy
        prec, acc = None, None
        s = s.split('`', 1)
        if len(s) == 1:
            suffix, s = None, s[0]
        else:
            suffix, s = s[1], s[0]

            if suffix == '':
                prec = machine_precision
            elif suffix.startswith('`'):
                acc = float(suffix[1:])
            else:
                if re.match('0+$', s) is not None:
                    t.value = Integer(0)
                    return t
                prec = float(suffix)

        # Look for decimal point
        if s.count('.') == 0:
            if suffix is None:
                if n < 0:
                    t.value = Rational(int(s, base), base**abs(n))
                else:
                    t.value = Integer(int(s, base) * (base**n))
                return t
            else:
                s = s + '.'

        if base == 10:
            if n != 0:
                s = s + 'E' + str(n)  # sympy handles this

            if acc is not None:
                if float(s) == 0:
                    prec = 0.
                else:
                    prec = acc + log10(float(s)) + n

            #XXX
            if prec is not None:
                prec = dps(prec)
            t.value = Real(s, prec)
            #t.value = Real(s, prec, acc)
        else:
            # Convert the base
            assert isinstance(base, int) and 2 <= base <= 36

            # Put into standard form mantissa * base ^ n
            s = s.split('.')
            if len(s) == 1:
                man = s[0]
            else:
                n -= len(s[1])
                man = s[0] + s[1]

            man = int(man, base)

            if n >= 0:
                result = Integer(man * base**n)
            else:
                result = Rational(man, base**-n)

            if acc is None and prec is None:
                acc = len(s[1])
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
                if prec10 < 18:
                    prec10 = None
            elif acc is not None:
                acc10 = acc * log10(base)
                prec10 = acc10 + log10(result.to_python())
            elif prec is not None:
                if prec == machine_precision:
                    prec10 = machine_precision
                else:
                    prec10 = prec * log10(base)
            #XXX
            if prec10 is None:
                prec10 = machine_precision
            else:
                prec10 = dps(prec10)

            t.value = result.round(prec10)

        return t
Example #40
0
    def apply_N(self, prec, evaluation):
        'N[MachinePrecision, prec_]'

        prec = get_precision(prec, evaluation)
        if prec is not None:
            return Real(dps(machine_precision), prec)
Example #41
0
 def apply_N(self, precision, evaluation):
     "N[Pi, precision_]"
     precision = get_precision(precision, evaluation)
     if precision is not None:
         return Real(sympy.pi.n(dps(precision)), p=precision)