def testReal(self): _test_group( MachineReal(1.17361), MachineReal(-1.42), MachineReal(42.846195714), MachineReal(42.846195714), MachineReal(42.846195713), Real("42.846195713", 18), Real("-1.42", 3), )
def test_d(self): expr = Expression( "Plus", Symbol("x"), MachineReal(1.5), Integer(2), Symbol("x") ) args = [CompileArg("System`x", real_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(2.5), 8.5)
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 get_constant(self, precision, evaluation, have_mpmath=False): try: d = get_precision(precision, evaluation) except PrecisionValueError: return sympy_fn = self.to_sympy() if d is None: result = self.get_mpmath_function() if have_mpmath else sympy_fn() return MachineReal(result) else: return PrecisionReal(sympy_fn.n(d))
def apply_N(self, precision, evaluation): 'N[E, precision_]' try: d = get_precision(precision, evaluation) except PrecisionValueError: return if d is None: return MachineReal(math.e) else: return PrecisionReal(sympy.E.n(d))
def apply_N(self, precision, evaluation): "N[Pi, precision_]" try: d = get_precision(precision, evaluation) except PrecisionValueError: return if d is None: return MachineReal(math.pi) else: return PrecisionReal(sympy.pi.n(d))
def apply_N(self, precision, evaluation): "N[Catalan, precision_]" try: d = get_precision(precision, evaluation) except PrecisionValueError: return if d is None: return MachineReal(mpmath.catalan) else: return PrecisionReal(sympy.Catalan.n(d))
def get_constant(self, precision, evaluation, preference=None): # first, determine the precision machine_d = int(0.30103 * machine_precision) d = None if precision: try: d = get_precision(precision, evaluation) except PrecisionValueError: pass if d is None: d = machine_d # If preference not especified, determine it # from the precision. if preference is None: if d <= machine_d: preference = "numpy" else: preference = "mpmath" # If preference is not valid, send a message and return. if not (preference in ("sympy", "numpy", "mpmath")): evaluation.message( f'{preference} not in ("sympy", "numpy", "mpmath")') return # Try to determine the numeric value value = None if preference == "mpmath" and not hasattr(self, "mpmath_name"): preference = "numpy" elif preference == "sympy" and not hasattr(self, "sympy_name"): preference = "numpy" if preference == "numpy" and not hasattr(self, "numpy_name"): if hasattr(self, "sympy_name"): preference = "sympy" elif hasattr(self, "mpmath_name"): preference = "mpmath" else: preference = "" if preference == "numpy": value = numpy_constant(self.numpy_name) if d == machine_d: return MachineReal(value) if preference == "sympy": value = sympy_constant(self.sympy_name, d + 2) if preference == "mpmath": value = mp_constant(self.mpmath_name, d * 2) if value: return PrecisionReal(sympy.Float(str(value), d)) # If the value is not available, return none # and keep it unevaluated. return
def get_precision(value, evaluation) -> typing.Optional[int]: if value.get_name() == 'System`MachinePrecision': return None else: from mathics.core.expression import Symbol, MachineReal dmin = _get_float_inf(Symbol('$MinPrecision'), evaluation) dmax = _get_float_inf(Symbol('$MaxPrecision'), evaluation) d = value.round_to_float(evaluation) assert dmin is not None and dmax is not None if d is None: evaluation.message('N', 'precbd', value) elif d < dmin: dmin = int(dmin) evaluation.message('N', 'precsm', value, MachineReal(dmin)) return dmin elif d > dmax: dmax = int(dmax) evaluation.message('N', 'preclg', value, MachineReal(dmax)) return dmax else: return d raise PrecisionValueError()
def apply_N(self, precision, evaluation): "N[Degree, precision_]" try: d = get_precision(precision, evaluation) except PrecisionValueError: return # FIXME: There are all sorts of interactions between in the trig functions, # that are expected to work out right. Until we have convertion between # mpmath and sympy worked out so that values can be made the to the same # precision and compared. we have to not use mpmath right now. # return self.get_constant(precision, evaluation, preference="mpmath") if d is None: return MachineReal(math.pi / 180) else: return PrecisionReal((sympy.pi / 180).n(d))
def get_constant(self, precision, evaluation, preference="mpmath"): try: d = get_precision(precision, evaluation) except PrecisionValueError: return mpmath_name = self.mpmath_name if d is None: return MachineReal(mp_fn(mpmath_name)) elif preference == "mpmath": result = mp_fn(mpmath_name, d) else: sympy_fn = self.to_sympy() try: result = sympy_fn.n(d) except: from trepan.api import debug; debug() pass return PrecisionReal(result)
def get_constant(self, precision, evaluation, preference="sympy"): try: d = get_precision(precision, evaluation) except PrecisionValueError: return sympy_fn = self.to_sympy() if d is None: if hasattr(self, "mpmath_name"): # Prefer mpmath when precision is not given. result = mp_fn(self.mpmath_name) else: result = sympy_fn() return MachineReal(result) if preference == "sympy": result = sympy_fn_n(d) elif hasattr(self, "mpmath_name"): result = mp_fn(self.mpmath_name, d) return PrecisionReal(result)
def testReal(self): _test_group(MachineReal(1.17361), MachineReal(-1.42), MachineReal(42.846195714), MachineReal(42.846195714), MachineReal(42.846195713), Real('42.846195713', 18), Real('-1.42', 3))
def test_if_real_int(self): expr = Expression("If", Symbol("x"), MachineReal(3), Integer(2)) args = [CompileArg("System`x", bool_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(True), 3.0) self.assertTypeEqual(cfunc(False), 2.0)
def test_pow_int_real(self): expr = Expression("Power", Symbol("x"), MachineReal(5.5)) args = [CompileArg("System`x", int_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(8), 8 ** 5.5)
def test_pow_real_int(self): expr = Expression("Power", MachineReal(2.5), Symbol("x")) args = [CompileArg("System`x", int_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(4), 2.5 ** 4)
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)
def evaluate(self, evaluation): return MachineReal(machine_epsilon)
def test_d(self): expr = Expression('Plus', Symbol('x'), MachineReal(1.5), Integer(2), Symbol('x')) args = [CompileArg('System`x', real_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(2.5), 8.5)
def test_if_int_real(self): expr = Expression('If', Symbol('x'), Integer(2), MachineReal(3)) args = [CompileArg('System`x', bool_type)] cfunc = _compile(expr, args) self.assertTypeEqual(cfunc(True), 2.0) self.assertTypeEqual(cfunc(False), 3.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__)))
def c(i, r): return Complex(MachineReal(i), MachineReal(i))