コード例 #1
0
ファイル: test_arithmetic.py プロジェクト: sealemar/Mathics
 def testTrueDiv(self):
     cases = (
         (Symbol('a') / 3, Expression('Times', Rational(1, 3), Symbol('a'))),
         (Integer(8) / 2, Integer(4)),
         (Integer(8) / (-2), Integer(-4)),
         (Integer(7) / 2, Rational(7, 2)),
         (Expression('List', 1, 9) / Expression('List', -1, 3), Expression('List', -1, 3)))
     self._testCases(cases)
コード例 #2
0
 def testTrueDiv(self):
     cases = (
         (Symbol("a") / 3, Expression("Times", Rational(1, 3),
                                      Symbol("a"))),
         (Integer(8) / 2, Integer(4)),
         (Integer(8) / (-2), Integer(-4)),
         (Integer(7) / 2, Rational(7, 2)),
         (
             Expression("List", 1, 9) / Expression("List", -1, 3),
             Expression("List", -1, 3),
         ),
     )
     self._testCases(cases)
コード例 #3
0
ファイル: basic.py プロジェクト: skirpichev/Mathics
    def apply_check(self, x, y, evaluation):
        "Power[x_, y_]"

        # Power uses _MPMathFunction but does some error checking first
        if isinstance(x, Number) and x.is_zero:
            if isinstance(y, Number):
                y_err = y
            else:
                y_err = Expression(SymbolN, y).evaluate(evaluation)
            if isinstance(y_err, Number):
                py_y = y_err.round_to_float(permit_complex=True).real
                if py_y > 0:
                    return x
                elif py_y == 0.0:
                    evaluation.message("Power", "indet",
                                       Expression("Power", x, y_err))
                    return Symbol("Indeterminate")
                elif py_y < 0:
                    evaluation.message("Power", "infy",
                                       Expression("Power", x, y_err))
                    return Symbol("ComplexInfinity")
        if isinstance(x, Complex) and x.real.is_zero:
            yhalf = Expression("Times", y, Rational(1, 2))
            factor = self.apply(Expression("Sequence", x.imag, y), evaluation)
            return Expression("Times", factor,
                              Expression("Power", Integer(-1), yhalf))

        result = self.apply(Expression(SymbolSequence, x, y), evaluation)
        if result is None or result != SymbolNull:
            return result
コード例 #4
0
    def apply(self, n, m, evaluation):
        'Rational[n_Integer, m_Integer]'

        if m.value == 1:
            return Integer(n.value)
        else:
            return Rational(n.value, m.value)
コード例 #5
0
    def apply(self, n, m, evaluation):
        'Rational[n_Integer, m_Integer]'

        if m.to_sympy() == 1:
            return Integer(n.to_sympy())
        else:
            return Rational(n.to_sympy(), m.to_sympy())
コード例 #6
0
ファイル: arithmetic.py プロジェクト: skirpichev/Mathics
    def apply(self, n, m, evaluation):
        "%(name)s[n_Integer, m_Integer]"

        if m.value == 1:
            return n
        else:
            return Rational(n.value, m.value)
コード例 #7
0
    def apply(self, l, k, f, evaluation):
        "Combinatorica`BinarySearch[l_List, k_, f_] /; Length[l] > 0"

        leaves = l.leaves

        lower_index = 1
        upper_index = len(leaves)

        if (
                lower_index > upper_index
        ):  # empty list l? Length[l] > 0 condition should guard us, but check anyway
            return Symbol("$Aborted")

        # "transform" is a handy wrapper for applying "f" or nothing
        if f.get_name() == "System`Identity":

            def transform(x):
                return x

        else:

            def transform(x):
                return Expression(f, x).evaluate(evaluation)

        # loop invariants (true at any time in the following loop):
        # (1) lower_index <= upper_index
        # (2) k > leaves[i] for all i < lower_index
        # (3) k < leaves[i] for all i > upper_index
        while True:
            pivot_index = (lower_index +
                           upper_index) >> 1  # i.e. a + (b - a) // 2
            # as lower_index <= upper_index, lower_index <= pivot_index <= upper_index
            pivot = transform(leaves[pivot_index - 1])  # 1-based to 0-based

            # we assume a trichotomous relation: k < pivot, or k = pivot, or k > pivot
            if k < pivot:
                if pivot_index == lower_index:  # see invariant (2), to see that
                    # k < leaves[pivot_index] and k > leaves[pivot_index - 1]
                    return Rational((pivot_index - 1) + pivot_index, 2)
                upper_index = pivot_index - 1
            elif k == pivot:
                return Integer(pivot_index)
            else:  # k > pivot
                if pivot_index == upper_index:  # see invariant (3), to see that
                    # k > leaves[pivot_index] and k < leaves[pivot_index + 1]
                    return Rational(pivot_index + (pivot_index + 1), 2)
                lower_index = pivot_index + 1
コード例 #8
0
    def apply_makeboxes(self, x, x0, data, nmin, nmax, den, form, evaluation):
        """MakeBoxes[SeriesData[x_, x0_, data_List, nmin_Integer, nmax_Integer, den_Integer], form_Symbol]"""

        form = form.get_name()
        if x0.is_zero:
            variable = x
        else:
            variable = Expression(
                SymbolPlus, x, Expression(SymbolTimes, IntegerMinusOne, x0)
            )
        den = den.get_int_value()
        nmin = nmin.get_int_value()
        nmax = nmax.get_int_value() + 1
        if den != 1:
            powers = [Rational(i, den) for i in range(nmin, nmax)]
            powers = powers + [Rational(nmax, den)]
        else:
            powers = [Integer(i) for i in range(nmin, nmax)]
            powers = powers + [Integer(nmax)]

        expansion = []
        for i, leaf in enumerate(data.leaves):
            if leaf.is_numeric() and leaf.is_zero:
                continue
            if powers[i].is_zero:
                expansion.append(leaf)
                continue
            if powers[i] == Integer1:
                if leaf == Integer1:
                    term = variable
                else:
                    term = Expression(SymbolTimes, leaf, variable)
            else:
                if leaf == Integer1:
                    term = Expression(SymbolPower, variable, powers[i])
                else:
                    term = Expression(
                        SymbolTimes, leaf, Expression(SymbolPower, variable, powers[i])
                    )
            expansion.append(term)
        expansion = expansion + [
            Expression(SymbolPower, Expression("O", variable), powers[-1])
        ]
        # expansion = [ex.format(form) for ex in expansion]
        expansion = Expression(SymbolPlus, *expansion)
        return expansion.format(evaluation, form)
コード例 #9
0
ファイル: test_hash.py プロジェクト: wxchen4277/Mathics
 def testInstances(self):
     # duplicate instantiations of same content (like Integer 5) to test for potential instantiation randomness.
     _test_group(
         list(
             map(lambda f: (f(), f()),
                 (lambda: Integer(5), lambda: Rational(5, 2),
                  lambda: MachineReal(5.12345678),
                  lambda: Complex(Integer(5), Integer(2)),
                  lambda: String('xy'), lambda: Symbol('xy')))))
コード例 #10
0
 def testAcrossTypes(self):
     _test_group(
         Integer(1),
         Rational(1, 1),
         Real(1),
         Complex(Integer(1), Integer(1)),
         String("1"),
         Symbol("1"),
     )
コード例 #11
0
ファイル: numeric.py プロジェクト: stephenoba/Mathics
 def apply_dx(self, x, dx, evaluation):
     "Rationalize[x_, dx_]"
     py_x = x.to_sympy()
     if py_x is None:
         return x
     py_dx = dx.to_sympy()
     if (py_dx is None or (not py_dx.is_number) or (not py_dx.is_real)
             or py_dx.is_negative):
         return evaluation.message("Rationalize", "tolnn", dx)
     elif py_dx == 0:
         return from_sympy(self.find_exact(py_x))
     a = self.approx_interval_continued_fraction(py_x - py_dx, py_x + py_dx)
     sym_x = sympy.ntheory.continued_fraction_reduce(a)
     return Rational(sym_x)
コード例 #12
0
 def testRational(self):
     _test_group(
         Rational(1, 3),
         Rational(1, 3),
         Rational(2, 6),
         Rational(-1, 3),
         Rational(-10, 30),
         Rational(10, 5),
     )
コード例 #13
0
    def testInteger(self):
        self.check("0", Integer(0))
        self.check("1", Integer(1))
        self.check("-1", Integer(-1))

        self.check("8^^23", Integer(19))
        self.check("10*^3", Integer(10000))
        self.check("10*^-3", Rational(1, 100))
        self.check("8^^23*^2", Integer(1216))

        n = random.randint(-sys.maxsize, sys.maxsize)
        self.check(str(n), Integer(n))

        n = random.randint(sys.maxsize, sys.maxsize * sys.maxsize)
        self.check(str(n), Integer(n))
コード例 #14
0
    def testInteger(self):
        self.check('0', Integer(0))
        self.check('1', Integer(1))
        self.check('-1', Integer(-1))

        self.check('8^^23', Integer(19))
        self.check('10*^3', Integer(10000))
        self.check('10*^-3', Rational(1, 100))
        self.check('8^^23*^2', Integer(1216))

        n = random.randint(-sys.maxint, sys.maxint)
        self.check(str(n), Integer(n))

        n = random.randint(sys.maxint, sys.maxint * sys.maxint)
        self.check(str(n), Integer(n))
コード例 #15
0
 def post_parse(self, expression):
     if len(expression.leaves) == 2:
         if isinstance(expression.leaves[0], Integer) and \
             isinstance(expression.leaves[1], Integer) and expression.leaves[1].value != 0:
             return Number.from_mp(
                 Rational(expression.leaves[0].value,
                          expression.leaves[1].value).value)
         else:
             if isinstance(expression.leaves[0],
                           Integer) and expression.leaves[0].value == 1:
                 return Expression('Power',
                                   expression.leaves[1].post_parse(),
                                   Integer(-1))
             else:
                 return Expression(
                     'Times', expression.leaves[0].post_parse(),
                     Expression('Power', expression.leaves[1].post_parse(),
                                Integer(-1)))
     else:
         return super(Divide, self).post_parse(expression)
コード例 #16
0
        def result():
            min_count = max(0, int(num_pixels * py_min_color_coverage))
            max_count = min(num_pixels,
                            int(num_pixels * py_max_color_coverage))

            for prototype, count, members in dominant:
                if max_count >= count > min_count:
                    if py_prop == "Count":
                        yield Integer(count)
                    elif py_prop == "Coverage":
                        yield Rational(int(count), num_pixels)
                    elif py_prop == "CoverageImage":
                        mask = numpy.ndarray(shape=pixels.shape,
                                             dtype=numpy.bool)
                        mask.fill(0)
                        for i in members:
                            mask = mask | (pixels == i)
                        yield Image(mask.reshape(tuple(reversed(im.size))),
                                    "Grayscale")
                    else:
                        yield Expression(out_palette_head, *prototype)
コード例 #17
0
    def post_parse(self, expression):
        if len(expression.leaves) == 2:
            if (isinstance(expression.leaves[0], Integer) and  # noqa
                    isinstance(expression.leaves[1], Integer) and
                    expression.leaves[1].to_sympy() != 0):

                return Number.from_mp(
                    Rational(expression.leaves[0].to_sympy(),
                             expression.leaves[1].to_sympy()).to_sympy())
            else:
                if (isinstance(expression.leaves[0], Integer) and  # noqa
                        expression.leaves[0].to_sympy() == 1):

                    return Expression('Power',
                                      expression.leaves[1].post_parse(),
                                      Integer(-1))
                else:
                    return Expression(
                        'Times', expression.leaves[0].post_parse(),
                        Expression('Power', expression.leaves[1].post_parse(),
                                   Integer(-1)))
        else:
            return super(Divide, self).post_parse(expression)
コード例 #18
0
ファイル: convert.py プロジェクト: yarwelp/Mathics
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import (Symbol, Integer, Rational, Real,
                                         Complex, String, Expression,
                                         MachineReal)
    from mathics.core.numbers import machine_precision

    from sympy.core import numbers, function, symbol

    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if isinstance(expr, int):
        return Integer(expr)
    if isinstance(expr, float):
        return Real(expr)
    if isinstance(expr, complex):
        return Complex(Real(expr.real), Real(expr.imag))
    if isinstance(expr, six.string_types):
        return String(expr)
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix):
        if len(expr.shape) == 2 and (expr.shape[1] == 1):
            # This is a vector (only one column)
            # Transpose and select first row to get result equivalent to Mathematica
            return Expression(
                'List', *[from_sympy(item) for item in expr.T.tolist()[0]])
        else:
            return Expression(
                'List',
                *[[from_sympy(item) for item in row] for row in expr.tolist()])
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = six.text_type(expr)
            if isinstance(expr, symbol.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if is_Cn_expr(name):
                return Expression('C', int(name[1:]))
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
            if name.startswith(sympy_slot_prefix):
                index = name[len(sympy_slot_prefix):]
                return Expression('Slot', int(index))
        elif expr.is_NumberSymbol:
            name = six.text_type(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(expr, (numbers.Infinity, numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, numbers.ImaginaryUnit):
            return Complex(Integer(0), Integer(1))
        elif isinstance(expr, numbers.Integer):
            return Integer(expr.p)
        elif isinstance(expr, numbers.Rational):
            if expr.q == 0:
                if expr.p > 0:
                    return Symbol('Infinity')
                elif expr.p < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert expr.p == 0
                    return Symbol('Indeterminate')
            return Rational(expr.p, expr.q)
        elif isinstance(expr, numbers.Float):
            if expr._prec == machine_precision:
                return MachineReal(float(expr))
            return Real(expr)
        elif isinstance(expr, numbers.NaN):
            return Symbol('Indeterminate')
        elif isinstance(expr, function.FunctionClass):
            return Symbol(six.text_type(expr))
    elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]):
        # Hack to convert 3 * I to Complex[0, 3]
        return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()])
    elif expr.is_Add:
        return Expression('Plus',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Mul:
        return Expression('Times',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Equality:
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, SympyExpression):
        return expr.expr

    elif isinstance(expr, sympy.Piecewise):
        args = expr.args
        default = []
        if len(args) > 0:
            default_case, default_cond = args[-1]
            if default_cond == sympy.true:
                args = args[:-1]
                if isinstance(default_case,
                              sympy.Integer) and int(default_case) == 0:
                    pass  # ignore, as 0 default case is always implicit in Piecewise[]
                else:
                    default = [from_sympy(default_case)]
        return Expression(
            'Piecewise',
            Expression(
                'List', *[
                    Expression('List', from_sympy(case), from_sympy(cond))
                    for case, cond in args
                ]), *default)

    elif isinstance(expr, sympy.RootSum):
        return Expression('RootSum', from_sympy(expr.poly),
                          from_sympy(expr.fun))
    elif isinstance(expr, sympy.PurePoly):
        coeffs = expr.coeffs()
        monoms = expr.monoms()
        result = []
        for coeff, monom in zip(coeffs, monoms):
            factors = []
            if coeff != 1:
                factors.append(from_sympy(coeff))
            for index, exp in enumerate(monom):
                if exp != 0:
                    slot = Expression('Slot', index + 1)
                    if exp == 1:
                        factors.append(slot)
                    else:
                        factors.append(
                            Expression('Power', slot, from_sympy(exp)))
            if factors:
                result.append(Expression('Times', *factors))
            else:
                result.append(Integer(1))
        return Expression('Function', Expression('Plus', *result))
    elif isinstance(expr, sympy.Lambda):
        vars = [
            sympy.Symbol('%s%d' % (sympy_slot_prefix, index + 1))
            for index in range(len(expr.variables))
        ]
        return Expression('Function', from_sympy(expr(*vars)))

    elif expr.is_Function or isinstance(
            expr,
        (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
        else:
            name = expr.func.__name__
            if is_Cn_expr(name):
                return Expression(Expression('C', int(name[1:])),
                                  *[from_sympy(arg) for arg in expr.args])
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            return builtin.from_sympy(name, args)
        return Expression(Symbol(name), *args)

    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])

    # elif isinstance(expr, sympy.Sum):
    #    return Expression('Sum', )

    elif isinstance(expr, sympy.LessThan):
        return Expression('LessEqual', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictLessThan):
        return Expression('Less', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.GreaterThan):
        return Expression('GreaterEqual',
                          *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictGreaterThan):
        return Expression('Greater', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Unequality):
        return Expression('Unequal', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Equality):
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])
    elif expr is sympy.true:
        return Symbol('True')
    elif expr is sympy.false:
        return Symbol('False')
    else:
        raise ValueError("Unknown SymPy expression: %s" % expr)
コード例 #19
0
class Power(BinaryOperator, _MPMathFunction):
    """
    <dl>
    <dt>'Power[$a$, $b$]'</dt>
    <dt>'$a$ ^ $b$'</dt>
        <dd>represents $a$ raised to the power of $b$.
    </dl>

    >> 4 ^ (1/2)
     = 2
    >> 4 ^ (1/3)
     = 2 ^ (2 / 3)
    >> 3^123
     = 48519278097689642681155855396759336072749841943521979872827

    >> (y ^ 2) ^ (1/2)
     = Sqrt[y ^ 2]
    >> (y ^ 2) ^ 3
     = y ^ 6

    >> Plot[Evaluate[Table[x^y, {y, 1, 5}]], {x, -1.5, 1.5}, AspectRatio -> 1]
     = -Graphics-

    Use a decimal point to force numeric evaluation:
    >> 4.0 ^ (1/3)
     = 1.5874

    'Power' has default value 1 for its second argument:
    >> DefaultValues[Power]
     = {HoldPattern[Default[Power, 2]] :> 1}
    >> a /. x_ ^ n_. :> {x, n}
     = {a, 1}

    'Power' can be used with complex numbers:
    >> (1.5 + 1.0 I) ^ 3.5
     = -3.68294 + 6.95139 I
    >> (1.5 + 1.0 I) ^ (3.5 + 1.5 I)
     = -3.19182 + 0.645659 I

    #> 1/0
     : Infinite expression 1 / 0 encountered.
     = ComplexInfinity
    #> 0 ^ -2
     : Infinite expression 1 / 0 ^ 2 encountered.
     = ComplexInfinity
    #> 0 ^ (-1/2)
     : Infinite expression 1 / Sqrt[0] encountered.
     = ComplexInfinity
    #> 0 ^ -Pi
     : Infinite expression 1 / 0 ^ 3.14159 encountered.
     = ComplexInfinity
    #> 0 ^ (2 I E)
     : Indeterminate expression 0 ^ (0. + 5.43656 I) encountered.
     = Indeterminate
    #> 0 ^ - (Pi + 2 E I)
     : Infinite expression 0 ^ (-3.14159 - 5.43656 I) encountered.
     = ComplexInfinity

    #> 0 ^ 0
     : Indeterminate expression 0 ^ 0 encountered.
     = Indeterminate

    #> Sqrt[-3+2. I]
     = 0.550251 + 1.81735 I
    #> Sqrt[-3+2 I]
     = Sqrt[-3 + 2 I]
    #> (3/2+1/2I)^2
     = 2 + 3 I / 2
    #> I ^ I
     = I ^ I

    #> 2 ^ 2.0
     = 4.

    #> Pi ^ 4.
     = 97.4091

    #> a ^ b
     = a ^ b
    """

    operator = '^'
    precedence = 590
    attributes = ('Listable', 'NumericFunction', 'OneIdentity')
    grouping = 'Right'

    default_formats = False

    sympy_name = 'Pow'
    mpmath_name = 'power'
    nargs = 2

    messages = {
        'infy': "Infinite expression `1` encountered.",
        'indet': 'Indeterminate expression `1` encountered.',

    }

    defaults = {
        2: '1',
    }

    formats = {
        Expression('Power', Expression('Pattern', Symbol('x'),
                   Expression('Blank')), Rational(1, 2)): 'HoldForm[Sqrt[x]]',
        (('InputForm', 'OutputForm'), 'x_ ^ y_'): (
            'Infix[{HoldForm[x], HoldForm[y]}, "^", 590, Right]'),
        ('', 'x_ ^ y_'): (
            'PrecedenceForm[Superscript[OuterPrecedenceForm[HoldForm[x], 590],'
            '  HoldForm[y]], 590]'),

        ('', 'x_ ^ y_?Negative'): (
            'HoldForm[Divide[1, #]]&[If[y==-1, HoldForm[x], HoldForm[x]^-y]]'),
    }

    rules = {
        'Power[]': '1',
        'Power[x_]': 'x',
    }

    def apply_check(self, x, y, evaluation):
        'Power[x_, y_]'

        # Power uses _MPMathFunction but does some error checking first
        if isinstance(x, Number) and x.is_zero:
            if isinstance(y, Number):
                y_err = y
            else:
                y_err = Expression('N', y).evaluate(evaluation)
            if isinstance(y_err, Number):
                py_y = y_err.round_to_float(permit_complex=True).real
                if py_y > 0:
                    return x
                elif py_y == 0.0:
                    evaluation.message('Power', 'indet', Expression('Power', x, y_err))
                    return Symbol('Indeterminate')
                elif py_y < 0:
                    evaluation.message('Power', 'infy', Expression('Power', x, y_err))
                    return Symbol('ComplexInfinity')

        result = self.apply(Expression('Sequence', x, y), evaluation)
        if result is None or result != Symbol('Null'):
            return result
コード例 #20
0
ファイル: convert.py プロジェクト: morganastra/Mathics
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import Symbol, Integer, Rational, Real, Expression
    
    from sympy.core import numbers, function, symbol
    
    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix):
        return Expression('List', *[Expression('List', *[from_sympy(item) for item in row]) for row in expr.tolist()])
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = unicode(expr)
            if isinstance(expr, symbol.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if name.startswith(sage_symbol_prefix):
                name = name[len(sage_symbol_prefix):]
        elif expr.is_NumberSymbol:
            name = unicode(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(expr, (numbers.Infinity, numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, numbers.ImaginaryUnit):
            return Symbol('I')
        elif isinstance(expr, numbers.Integer):
            return Integer(expr.p)
        elif isinstance(expr, numbers.Rational):
            if expr.q == 0:
                if expr.p > 0:
                    return Symbol('Infinity')
                elif expr.p < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert expr.p == 0
                    return Symbol('Indeterminate')
            return Rational(expr.p, expr.q)
        elif isinstance(expr, numbers.Float):
            return Real(expr.num)
        elif isinstance(expr, function.FunctionClass):
            return Symbol(unicode(expr))
    elif expr.is_Add:
        return Expression('Plus', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Mul:
        return Expression('Times', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    
    elif isinstance(expr, SympyExpression):
        #print "SympyExpression: %s" % expr
        return expr.expr
    
    elif expr.is_Function or isinstance(expr, (sympy.Integral, sympy.Derivative)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
        else:
            name = expr.func.__name__
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            name = builtin.get_name()
            args = builtin.from_sympy(args)
        else:
            if name.startswith(sage_symbol_prefix):
                name = name[len(sage_symbol_prefix):]
        return Expression(Symbol(name), *args)
    
    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])
    
    else:
        raise ValueError("Unknown SymPy expression: %s" % expr)
コード例 #21
0
ファイル: basic.py プロジェクト: skirpichev/Mathics
class Power(BinaryOperator, _MPMathFunction):
    """
    <dl>
    <dt>'Power[$a$, $b$]'</dt>
    <dt>'$a$ ^ $b$'</dt>
        <dd>represents $a$ raised to the power of $b$.
    </dl>

    >> 4 ^ (1/2)
     = 2
    >> 4 ^ (1/3)
     = 2 ^ (2 / 3)
    >> 3^123
     = 48519278097689642681155855396759336072749841943521979872827

    >> (y ^ 2) ^ (1/2)
     = Sqrt[y ^ 2]
    >> (y ^ 2) ^ 3
     = y ^ 6

    >> Plot[Evaluate[Table[x^y, {y, 1, 5}]], {x, -1.5, 1.5}, AspectRatio -> 1]
     = -Graphics-

    Use a decimal point to force numeric evaluation:
    >> 4.0 ^ (1/3)
     = 1.5874

    'Power' has default value 1 for its second argument:
    >> DefaultValues[Power]
     = {HoldPattern[Default[Power, 2]] :> 1}
    >> a /. x_ ^ n_. :> {x, n}
     = {a, 1}

    'Power' can be used with complex numbers:
    >> (1.5 + 1.0 I) ^ 3.5
     = -3.68294 + 6.95139 I
    >> (1.5 + 1.0 I) ^ (3.5 + 1.5 I)
     = -3.19182 + 0.645659 I

    #> 1/0
     : Infinite expression 1 / 0 encountered.
     = ComplexInfinity
    #> 0 ^ -2
     : Infinite expression 1 / 0 ^ 2 encountered.
     = ComplexInfinity
    #> 0 ^ (-1/2)
     : Infinite expression 1 / Sqrt[0] encountered.
     = ComplexInfinity
    #> 0 ^ -Pi
     : Infinite expression 1 / 0 ^ 3.14159 encountered.
     = ComplexInfinity
    #> 0 ^ (2 I E)
     : Indeterminate expression 0 ^ (0. + 5.43656 I) encountered.
     = Indeterminate
    #> 0 ^ - (Pi + 2 E I)
     : Infinite expression 0 ^ (-3.14159 - 5.43656 I) encountered.
     = ComplexInfinity

    #> 0 ^ 0
     : Indeterminate expression 0 ^ 0 encountered.
     = Indeterminate

    #> Sqrt[-3+2. I]
     = 0.550251 + 1.81735 I
    #> Sqrt[-3+2 I]
     = Sqrt[-3 + 2 I]
    #> (3/2+1/2I)^2
     = 2 + 3 I / 2
    #> I ^ I
     = -1 ^ (I / 2)

    #> 2 ^ 2.0
     = 4.

    #> Pi ^ 4.
     = 97.4091

    #> a ^ b
     = a ^ b
    """

    operator = "^"
    precedence = 590
    attributes = ("Listable", "NumericFunction", "OneIdentity")
    grouping = "Right"

    default_formats = False

    sympy_name = "Pow"
    mpmath_name = "power"
    nargs = 2

    messages = {
        "infy": "Infinite expression `1` encountered.",
        "indet": "Indeterminate expression `1` encountered.",
    }

    defaults = {
        2: "1",
    }

    formats = {
        Expression(
            "Power",
            Expression("Pattern", Symbol("x"), Expression("Blank")),
            Rational(1, 2),
        ):
        "HoldForm[Sqrt[x]]",
        (("InputForm", "OutputForm"), "x_ ^ y_"):
        ('Infix[{HoldForm[x], HoldForm[y]}, "^", 590, Right]'),
        ("", "x_ ^ y_"):
        ("PrecedenceForm[Superscript[OuterPrecedenceForm[HoldForm[x], 590],"
         "  HoldForm[y]], 590]"),
        ("", "x_ ^ y_?Negative"):
        ("HoldForm[Divide[1, #]]&[If[y==-1, HoldForm[x], HoldForm[x]^-y]]"),
        ("", "x_?Negative ^ y_"):
        ('Infix[{HoldForm[(x)], HoldForm[y]},"^", 590, Right]'),
    }

    rules = {
        "Power[]": "1",
        "Power[x_]": "x",
    }

    summary_text = "exponentiation"

    def apply_check(self, x, y, evaluation):
        "Power[x_, y_]"

        # Power uses _MPMathFunction but does some error checking first
        if isinstance(x, Number) and x.is_zero:
            if isinstance(y, Number):
                y_err = y
            else:
                y_err = Expression(SymbolN, y).evaluate(evaluation)
            if isinstance(y_err, Number):
                py_y = y_err.round_to_float(permit_complex=True).real
                if py_y > 0:
                    return x
                elif py_y == 0.0:
                    evaluation.message("Power", "indet",
                                       Expression("Power", x, y_err))
                    return Symbol("Indeterminate")
                elif py_y < 0:
                    evaluation.message("Power", "infy",
                                       Expression("Power", x, y_err))
                    return Symbol("ComplexInfinity")
        if isinstance(x, Complex) and x.real.is_zero:
            yhalf = Expression("Times", y, Rational(1, 2))
            factor = self.apply(Expression("Sequence", x.imag, y), evaluation)
            return Expression("Times", factor,
                              Expression("Power", Integer(-1), yhalf))

        result = self.apply(Expression(SymbolSequence, x, y), evaluation)
        if result is None or result != SymbolNull:
            return result
コード例 #22
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
コード例 #23
0
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import (Symbol, Integer, Rational, Real,
                                         Complex, String, Expression)

    from sympy.core import numbers, function, symbol

    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if isinstance(expr, int):
        return Integer(expr)
    if isinstance(expr, float):
        return Real(expr)
    if isinstance(expr, complex):
        return Complex(expr.real, expr.imag)
    if isinstance(expr, str):
        return String(expr)
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix):
        return Expression(
            'List', *[
                Expression('List', *[from_sympy(item) for item in row])
                for row in expr.tolist()
            ])
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = unicode(expr)
            if isinstance(expr, symbol.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if ((
                    not name.startswith(sympy_symbol_prefix) or  # noqa
                    name.startswith(sympy_slot_prefix))
                    and name.startswith('C')):
                return Expression('C', int(name[1:]))
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
            if name.startswith(sympy_slot_prefix):
                index = name[len(sympy_slot_prefix):]
                return Expression('Slot', int(index))
        elif expr.is_NumberSymbol:
            name = unicode(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(expr, (numbers.Infinity, numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, numbers.ImaginaryUnit):
            return Complex(0, 1)
        elif isinstance(expr, numbers.Integer):
            return Integer(expr.p)
        elif isinstance(expr, numbers.Rational):
            if expr.q == 0:
                if expr.p > 0:
                    return Symbol('Infinity')
                elif expr.p < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert expr.p == 0
                    return Symbol('Indeterminate')
            return Rational(expr.p, expr.q)
        elif isinstance(expr, numbers.Float):
            return Real(expr)
        elif isinstance(expr, numbers.NaN):
            return Symbol('Indeterminate')
        elif isinstance(expr, function.FunctionClass):
            return Symbol(unicode(expr))
    elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]):
        # Hack to convert 3 * I to Complex[0, 3]
        return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()])
    elif expr.is_Add:
        return Expression('Plus',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Mul:
        return Expression('Times',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Equality:
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, SympyExpression):
        # print "SympyExpression: %s" % expr
        return expr.expr

    elif isinstance(expr, sympy.RootSum):
        return Expression('RootSum', from_sympy(expr.poly),
                          from_sympy(expr.fun))
    elif isinstance(expr, sympy.PurePoly):
        coeffs = expr.coeffs()
        monoms = expr.monoms()
        result = []
        for coeff, monom in zip(coeffs, monoms):
            factors = []
            if coeff != 1:
                factors.append(from_sympy(coeff))
            for index, exp in enumerate(monom):
                if exp != 0:
                    slot = Expression('Slot', index + 1)
                    if exp == 1:
                        factors.append(slot)
                    else:
                        factors.append(
                            Expression('Power', slot, from_sympy(exp)))
            if factors:
                result.append(Expression('Times', *factors))
            else:
                result.append(Integer(1))
        return Expression('Function', Expression('Plus', *result))
    elif isinstance(expr, sympy.Lambda):
        vars = [
            sympy.Symbol('%s%d' % (sympy_slot_prefix, index + 1))
            for index in range(len(expr.variables))
        ]
        return Expression('Function', from_sympy(expr(*vars)))

    elif expr.is_Function or isinstance(
            expr,
        (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
        else:
            name = expr.func.__name__
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            name = builtin.get_name()
            args = builtin.from_sympy(args)
        return Expression(Symbol(name), *args)

    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])

    # elif isinstance(expr, sympy.Sum):
    #    return Expression('Sum', )

    elif isinstance(expr, sympy.LessThan):
        return Expression('LessEqual', [from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictLessThan):
        return Expression('Less', [from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.GreaterThan):
        return Expression('GreaterEqual',
                          [from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictGreaterThan):
        return Expression('Greater', [from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Unequality):
        return Expression('Unequal', [from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Equality):
        return Expression('Equal', [from_sympy(arg) for arg in expr.args])
    else:
        raise ValueError("Unknown SymPy expression: %s" % expr)
コード例 #24
0
class Power(BinaryOperator, SympyFunction):
    """
    <dl>
    <dt>'Power[$a$, $b$]'</dt>
    <dt>'$a$ ^ $b$'</dt>
        <dd>represents $a$ raised to the power of $b$.
    </dl>

    >> 4 ^ (1/2)
     = 2
    >> 4 ^ (1/3)
     = 2 ^ (2 / 3)
    >> 3^123
     = 48519278097689642681155855396759336072749841943521979872827

    >> (y ^ 2) ^ (1/2)
     = Sqrt[y ^ 2]
    >> (y ^ 2) ^ 3
     = y ^ 6

    >> Plot[Evaluate[Table[x^y, {y, 1, 5}]], {x, -1.5, 1.5}, AspectRatio -> 1]
     = -Graphics-

    Use a decimal point to force numeric evaluation:
    >> 4.0 ^ (1/3)
     = 1.58740105196819947

    'Power' has default value 1 for its second argument:
    >> DefaultValues[Power]
     = {HoldPattern[Default[Power, 2]] :> 1}
    >> a /. x_ ^ n_. :> {x, n}
     = {a, 1}

    'Power' can be used with complex numbers:
    >> (1.5 + 1.0 I) ^ 3.5
     = -3.68294005782191823 + 6.9513926640285049 I
    >> (1.5 + 1.0 I) ^ (3.5 + 1.5 I)
     = -3.19181629045628082 + 0.645658509416156807 I

    #> 1/0
     : Infinite expression (division by zero) encountered.
     = ComplexInfinity
    #> Sqrt[-3+2. I]
     = 0.550250522700337511 + 1.81735402102397062 I
    #> Sqrt[-3+2 I]
     = Sqrt[-3 + 2 I]
    #> (3/2+1/2I)^2
     = 2 + 3 I / 2
    #> I ^ I
     = I ^ I

    #> 2 ^ 2.0
     = 4.

    #> Pi ^ 4.
     = 97.4090910340024374
    """

    operator = '^'
    precedence = 590
    attributes = ('Listable', 'NumericFunction', 'OneIdentity')
    grouping = 'Right'

    default_formats = False

    sympy_name = 'Pow'

    messages = {
        'infy': "Infinite expression (division by zero) encountered.",
    }

    defaults = {
        2: '1',
    }

    formats = {
        Expression('Power',
                   Expression('Pattern', Symbol('x'), Expression('Blank')),
                   Rational(1, 2)):
        'HoldForm[Sqrt[x]]',
        (('InputForm', 'OutputForm'), 'x_ ^ y_'):
        ('Infix[{HoldForm[x], HoldForm[y]}, "^", 590, Right]'),
        ('', 'x_ ^ y_'):
        ('PrecedenceForm[Superscript[OuterPrecedenceForm[HoldForm[x], 590],'
         '  HoldForm[y]], 590]'),
        ('', 'x_ ^ y_?Negative'):
        ('HoldForm[Divide[1, #]]&[If[y==-1, HoldForm[x], HoldForm[x]^-y]]'),
    }

    rules = {}

    def apply(self, items, evaluation):
        'Power[items__]'

        items_sequence = items.get_sequence()

        if len(items_sequence) == 2:
            x, y = items_sequence
        else:
            return Expression('Power', *items_sequence)

        if y.get_int_value() == 1:
            return x
        elif x.get_int_value() == 1:
            return x
        elif y.get_int_value() == 0:
            if x.get_int_value() == 0:
                evaluation.message('Power', 'indet', Expression('Power', x, y))
                return Symbol('Indeterminate')
            else:
                return Integer(1)

        elif x.has_form('Power', 2) and isinstance(y, Integer):
            return Expression('Power', x.leaves[0],
                              Expression('Times', x.leaves[1], y))
        elif x.has_form('Times', None) and isinstance(y, Integer):
            return Expression(
                'Times', *[Expression('Power', leaf, y) for leaf in x.leaves])

        elif (isinstance(x, Number) and isinstance(y, Number)
              and not (x.is_inexact() or y.is_inexact())):

            sym_x, sym_y = x.to_sympy(), y.to_sympy()

            try:
                if sympy.re(sym_y) >= 0:
                    result = sym_x**sym_y
                else:
                    if sym_x == 0:
                        evaluation.message('Power', 'infy')
                        return Symbol('ComplexInfinity')
                    result = sympy.Integer(1) / (sym_x**(-sym_y))
                if isinstance(result, sympy.Pow):
                    result = result.simplify()
                    args = [from_sympy(expr) for expr in result.as_base_exp()]
                    result = Expression('Power', *args)
                    result = result.evaluate_leaves(evaluation)
                    return result

                return from_sympy(result)
            except ValueError:
                return Expression('Power', x, y)
            except ZeroDivisionError:
                evaluation.message('Power', 'infy')
                return Symbol('ComplexInfinity')

        elif (isinstance(x, Number) and isinstance(y, Number)
              and (x.is_inexact() or y.is_inexact())):
            try:
                prec = min_prec(x, y)
                with mpmath.workprec(prec):
                    mp_x = sympy2mpmath(x.to_sympy())
                    mp_y = sympy2mpmath(y.to_sympy())
                    result = mp_x**mp_y
                    if isinstance(result, mpmath.mpf):
                        return Real(str(result), prec)
                    elif isinstance(result, mpmath.mpc):
                        return Complex(str(result.real), str(result.imag),
                                       prec)
            except ZeroDivisionError:
                evaluation.message('Power', 'infy')
                return Symbol('ComplexInfinity')
        else:
            numerified_items = items.numerify(evaluation)
            return Expression('Power', *numerified_items.get_sequence())
コード例 #25
0
def from_sympy(expr):
    from mathics.builtin import sympy_to_mathics
    from mathics.core.expression import (Symbol, Integer, Rational, Real,
                                         Complex, String, Expression,
                                         MachineReal)
    from mathics.core.numbers import machine_precision

    if isinstance(expr, (tuple, list)):
        return Expression('List', *[from_sympy(item) for item in expr])
    if isinstance(expr, int):
        return Integer(expr)
    if isinstance(expr, float):
        return Real(expr)
    if isinstance(expr, complex):
        return Complex(Real(expr.real), Real(expr.imag))
    if isinstance(expr, str):
        return String(expr)
    if expr is None:
        return Symbol('Null')
    if isinstance(expr, sympy.Matrix) or isinstance(expr,
                                                    sympy.ImmutableMatrix):
        if len(expr.shape) == 2 and (expr.shape[1] == 1):
            # This is a vector (only one column)
            # Transpose and select first row to get result equivalent to Mathematica
            return Expression(
                'List', *[from_sympy(item) for item in expr.T.tolist()[0]])
        else:
            return Expression(
                'List',
                *[[from_sympy(item) for item in row] for row in expr.tolist()])
    if isinstance(expr, sympy.MatPow):
        return Expression('MatrixPower', from_sympy(expr.base),
                          from_sympy(expr.exp))
    if expr.is_Atom:
        name = None
        if expr.is_Symbol:
            name = str(expr)
            if isinstance(expr, sympy.Dummy):
                name = name + ('__Dummy_%d' % expr.dummy_index)
                return Symbol(name, sympy_dummy=expr)
            if is_Cn_expr(name):
                return Expression('C', int(name[1:]))
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
            if name.startswith(sympy_slot_prefix):
                index = name[len(sympy_slot_prefix):]
                return Expression('Slot', int(index))
        elif expr.is_NumberSymbol:
            name = str(expr)
        if name is not None:
            builtin = sympy_to_mathics.get(name)
            if builtin is not None:
                name = builtin.get_name()
            return Symbol(name)
        elif isinstance(
                expr,
            (sympy.core.numbers.Infinity, sympy.core.numbers.ComplexInfinity)):
            return Symbol(expr.__class__.__name__)
        elif isinstance(expr, sympy.core.numbers.NegativeInfinity):
            return Expression('Times', Integer(-1), Symbol('Infinity'))
        elif isinstance(expr, sympy.core.numbers.ImaginaryUnit):
            return Complex(Integer(0), Integer(1))
        elif isinstance(expr, sympy.Integer):
            return Integer(int(expr))
        elif isinstance(expr, sympy.Rational):
            numerator, denominator = map(int, expr.as_numer_denom())
            if denominator == 0:
                if numerator > 0:
                    return Symbol('Infinity')
                elif numerator < 0:
                    return Expression('Times', Integer(-1), Symbol('Infinity'))
                else:
                    assert numerator == 0
                    return Symbol('Indeterminate')
            return Rational(numerator, denominator)
        elif isinstance(expr, sympy.Float):
            if expr._prec == machine_precision:
                return MachineReal(float(expr))
            return Real(expr)
        elif isinstance(expr, sympy.core.numbers.NaN):
            return Symbol('Indeterminate')
        elif isinstance(expr, sympy.core.function.FunctionClass):
            return Symbol(str(expr))
        elif expr is sympy.true:
            return Symbol('True')
        elif expr is sympy.false:
            return Symbol('False')

    elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]):
        # Hack to convert 3 * I to Complex[0, 3]
        return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()])
    elif expr.is_Add:
        return Expression('Plus',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Mul:
        return Expression('Times',
                          *sorted([from_sympy(arg) for arg in expr.args]))
    elif expr.is_Pow:
        return Expression('Power', *[from_sympy(arg) for arg in expr.args])
    elif expr.is_Equality:
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, SympyExpression):
        return expr.expr

    elif isinstance(expr, sympy.Piecewise):
        args = expr.args
        return Expression(
            'Piecewise',
            Expression(
                'List', *[
                    Expression('List', from_sympy(case), from_sympy(cond))
                    for case, cond in args
                ]))

    elif isinstance(expr, SympyPrime):
        return Expression('Prime', from_sympy(expr.args[0]))
    elif isinstance(expr, sympy.RootSum):
        return Expression('RootSum', from_sympy(expr.poly),
                          from_sympy(expr.fun))
    elif isinstance(expr, sympy.PurePoly):
        coeffs = expr.coeffs()
        monoms = expr.monoms()
        result = []
        for coeff, monom in zip(coeffs, monoms):
            factors = []
            if coeff != 1:
                factors.append(from_sympy(coeff))
            for index, exp in enumerate(monom):
                if exp != 0:
                    slot = Expression('Slot', index + 1)
                    if exp == 1:
                        factors.append(slot)
                    else:
                        factors.append(
                            Expression('Power', slot, from_sympy(exp)))
            if factors:
                result.append(Expression('Times', *factors))
            else:
                result.append(Integer(1))
        return Expression('Function', Expression('Plus', *result))
    elif isinstance(expr, sympy.CRootOf):
        try:
            e, i = expr.args
        except ValueError:
            return Expression('Null')

        try:
            e = sympy.PurePoly(e)
        except:
            pass

        return Expression('Root', from_sympy(e), i + 1)
    elif isinstance(expr, sympy.Lambda):
        vars = [
            sympy.Symbol('%s%d' % (sympy_slot_prefix, index + 1))
            for index in range(len(expr.variables))
        ]
        return Expression('Function', from_sympy(expr(*vars)))

    elif expr.is_Function or isinstance(
            expr,
        (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)):
        if isinstance(expr, sympy.Integral):
            name = 'Integral'
        elif isinstance(expr, sympy.Derivative):
            name = 'Derivative'
            margs = []
            for arg in expr.args:
                # parse (x, 1) ==> just x for test_conversion
                # IMHO this should be removed in future versions
                if isinstance(arg, sympy.Tuple):
                    if arg[1] == 1:
                        margs.append(from_sympy(arg[0]))
                    else:
                        margs.append(from_sympy(arg))
                else:
                    margs.append(from_sympy(arg))
            builtin = sympy_to_mathics.get(name)
            return builtin.from_sympy(name, margs)

        elif isinstance(expr, sympy.sign):
            name = 'Sign'
        else:
            name = expr.func.__name__
            if is_Cn_expr(name):
                return Expression(Expression('C', int(name[1:])),
                                  *[from_sympy(arg) for arg in expr.args])
            if name.startswith(sympy_symbol_prefix):
                name = name[len(sympy_symbol_prefix):]
        args = [from_sympy(arg) for arg in expr.args]
        builtin = sympy_to_mathics.get(name)
        if builtin is not None:
            return builtin.from_sympy(name, args)
        return Expression(Symbol(name), *args)

    elif isinstance(expr, sympy.Tuple):
        return Expression('List', *[from_sympy(arg) for arg in expr.args])

    # elif isinstance(expr, sympy.Sum):
    #    return Expression('Sum', )

    elif isinstance(expr, sympy.LessThan):
        return Expression('LessEqual', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictLessThan):
        return Expression('Less', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.GreaterThan):
        return Expression('GreaterEqual',
                          *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.StrictGreaterThan):
        return Expression('Greater', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Unequality):
        return Expression('Unequal', *[from_sympy(arg) for arg in expr.args])
    elif isinstance(expr, sympy.Equality):
        return Expression('Equal', *[from_sympy(arg) for arg in expr.args])

    elif isinstance(expr, sympy.O):
        if expr.args[0].func == sympy.core.power.Pow:
            [var, power] = [from_sympy(arg) for arg in expr.args[0].args]
            o = Expression('O', var)
            return Expression('Power', o, power)
        else:
            return Expression('O', from_sympy(expr.args[0]))
    else:
        raise ValueError(
            "Unknown SymPy expression: {} (instance of {})".format(
                expr, str(expr.__class__)))