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)
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)
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
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)
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())
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)
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
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)
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')))))
def testAcrossTypes(self): _test_group( Integer(1), Rational(1, 1), Real(1), Complex(Integer(1), Integer(1)), String("1"), Symbol("1"), )
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)
def testRational(self): _test_group( Rational(1, 3), Rational(1, 3), Rational(2, 6), Rational(-1, 3), Rational(-10, 30), Rational(10, 5), )
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))
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))
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)
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)
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)
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)
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
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)
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
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
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)
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())
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__)))