def build_ideal(x, terms): """ Build generators for our ideal. Terms is an iterable with elements of the form (fn, coeff), indicating that we have a generator fn(coeff*x). If any of the terms is trigonometric, sin(x) and cos(x) are guaranteed to appear in terms. Similarly for hyperbolic functions. For tan(n*x), sin(n*x) and cos(n*x) are guaranteed. """ gens = [] I = [] y = Dummy('y') for fn, coeff in terms: for c, s, t, rel in ([cos, sin, tan, cos(x)**2 + sin(x)**2 - 1], [ cosh, sinh, tanh, cosh(x)**2 - sinh(x)**2 - 1 ]): if coeff == 1 and fn in [c, s]: I.append(rel) elif fn == t: I.append(t(coeff * x) * c(coeff * x) - s(coeff * x)) elif fn in [c, s]: cn = fn(coeff * y).expand(trig=True).subs(y, x) I.append(fn(coeff * x) - cn) return list(set(I))
def test_C99CodePrinter__precision(): n = symbols('n', integer=True) f32_printer = C99CodePrinter(dict(type_aliases={real: float32})) f64_printer = C99CodePrinter(dict(type_aliases={real: float64})) f80_printer = C99CodePrinter(dict(type_aliases={real: float80})) assert f32_printer.doprint(sin(x+2.1)) == 'sinf(x + 2.1F)' assert f64_printer.doprint(sin(x+2.1)) == 'sin(x + 2.1000000000000001)' assert f80_printer.doprint(sin(x+Float('2.0'))) == 'sinl(x + 2.0L)' for printer, suffix in zip([f32_printer, f64_printer, f80_printer], ['f', '', 'l']): def check(expr, ref): assert printer.doprint(expr) == ref.format(s=suffix, S=suffix.upper()) check(Abs(n), 'abs(n)') check(Abs(x + 2.0), 'fabs{s}(x + 2.0{S})') check(sin(x + 4.0)**cos(x - 2.0), 'pow{s}(sin{s}(x + 4.0{S}), cos{s}(x - 2.0{S}))') check(exp(x*8.0), 'exp{s}(8.0{S}*x)') check(exp2(x), 'exp2{s}(x)') check(expm1(x*4.0), 'expm1{s}(4.0{S}*x)') check(Mod(n, 2), '((n) % (2))') check(Mod(2*n + 3, 3*n + 5), '((2*n + 3) % (3*n + 5))') check(Mod(x + 2.0, 3.0), 'fmod{s}(1.0{S}*x + 2.0{S}, 3.0{S})') check(Mod(x, 2.0*x + 3.0), 'fmod{s}(1.0{S}*x, 2.0{S}*x + 3.0{S})') check(log(x/2), 'log{s}((1.0{S}/2.0{S})*x)') check(log10(3*x/2), 'log10{s}((3.0{S}/2.0{S})*x)') check(log2(x*8.0), 'log2{s}(8.0{S}*x)') check(log1p(x), 'log1p{s}(x)') check(2**x, 'pow{s}(2, x)') check(2.0**x, 'pow{s}(2.0{S}, x)') check(x**3, 'pow{s}(x, 3)') check(x**4.0, 'pow{s}(x, 4.0{S})') check(sqrt(3+x), 'sqrt{s}(x + 3)') check(Cbrt(x-2.0), 'cbrt{s}(x - 2.0{S})') check(hypot(x, y), 'hypot{s}(x, y)') check(sin(3.*x + 2.), 'sin{s}(3.0{S}*x + 2.0{S})') check(cos(3.*x - 1.), 'cos{s}(3.0{S}*x - 1.0{S})') check(tan(4.*y + 2.), 'tan{s}(4.0{S}*y + 2.0{S})') check(asin(3.*x + 2.), 'asin{s}(3.0{S}*x + 2.0{S})') check(acos(3.*x + 2.), 'acos{s}(3.0{S}*x + 2.0{S})') check(atan(3.*x + 2.), 'atan{s}(3.0{S}*x + 2.0{S})') check(atan2(3.*x, 2.*y), 'atan2{s}(3.0{S}*x, 2.0{S}*y)') check(sinh(3.*x + 2.), 'sinh{s}(3.0{S}*x + 2.0{S})') check(cosh(3.*x - 1.), 'cosh{s}(3.0{S}*x - 1.0{S})') check(tanh(4.0*y + 2.), 'tanh{s}(4.0{S}*y + 2.0{S})') check(asinh(3.*x + 2.), 'asinh{s}(3.0{S}*x + 2.0{S})') check(acosh(3.*x + 2.), 'acosh{s}(3.0{S}*x + 2.0{S})') check(atanh(3.*x + 2.), 'atanh{s}(3.0{S}*x + 2.0{S})') check(erf(42.*x), 'erf{s}(42.0{S}*x)') check(erfc(42.*x), 'erfc{s}(42.0{S}*x)') check(gamma(x), 'tgamma{s}(x)') check(loggamma(x), 'lgamma{s}(x)') check(ceiling(x + 2.), "ceil{s}(x + 2.0{S})") check(floor(x + 2.), "floor{s}(x + 2.0{S})") check(fma(x, y, -z), 'fma{s}(x, y, -z)') check(Max(x, 8.0, x**4.0), 'fmax{s}(8.0{S}, fmax{s}(x, pow{s}(x, 4.0{S})))') check(Min(x, 2.0), 'fmin{s}(2.0{S}, x)')
def f(rv): if not rv.is_Mul: return rv commutative_part, noncommutative_part = rv.args_cnc() # Since as_powers_dict loses order information, # if there is more than one noncommutative factor, # it should only be used to simplify the commutative part. if (len(noncommutative_part) > 1): return f(Mul(*commutative_part)) * Mul(*noncommutative_part) rvd = rv.as_powers_dict() newd = rvd.copy() def signlog(expr, sign=S.One): if expr is S.Exp1: return sign, S.One elif isinstance(expr, exp) or (expr.is_Pow and expr.base == S.Exp1): return sign, expr.exp elif sign is S.One: return signlog(-expr, sign=-S.One) else: return None, None ee = rvd[S.Exp1] for k in rvd: if k.is_Add and len(k.args) == 2: # k == c*(1 + sign*E**x) c = k.args[0] sign, x = signlog(k.args[1] / c) if not x: continue m = rvd[k] newd[k] -= m if ee == -x * m / 2: # sinh and cosh newd[S.Exp1] -= ee ee = 0 if sign == 1: newd[2 * c * cosh(x / 2)] += m else: newd[-2 * c * sinh(x / 2)] += m elif newd[1 - sign * S.Exp1**x] == -m: # tanh del newd[1 - sign * S.Exp1**x] if sign == 1: newd[-c / tanh(x / 2)] += m else: newd[-c * tanh(x / 2)] += m else: newd[1 + sign * S.Exp1**x] += m newd[c] += m return Mul(*[k**newd[k] for k in newd])
def f(rv): if not rv.is_Mul: return rv commutative_part, noncommutative_part = rv.args_cnc() # Since as_powers_dict loses order information, # if there is more than one noncommutative factor, # it should only be used to simplify the commutative part. if (len(noncommutative_part) > 1): return f(Mul(*commutative_part))*Mul(*noncommutative_part) rvd = rv.as_powers_dict() newd = rvd.copy() def signlog(expr, sign=1): if expr is S.Exp1: return sign, 1 elif isinstance(expr, exp): return sign, expr.args[0] elif sign == 1: return signlog(-expr, sign=-1) else: return None, None ee = rvd[S.Exp1] for k in rvd: if k.is_Add and len(k.args) == 2: # k == c*(1 + sign*E**x) c = k.args[0] sign, x = signlog(k.args[1]/c) if not x: continue m = rvd[k] newd[k] -= m if ee == -x*m/2: # sinh and cosh newd[S.Exp1] -= ee ee = 0 if sign == 1: newd[2*c*cosh(x/2)] += m else: newd[-2*c*sinh(x/2)] += m elif newd[1 - sign*S.Exp1**x] == -m: # tanh del newd[1 - sign*S.Exp1**x] if sign == 1: newd[-c/tanh(x/2)] += m else: newd[-c*tanh(x/2)] += m else: newd[1 + sign*S.Exp1**x] += m newd[c] += m return Mul(*[k**newd[k] for k in newd])
def f(rv): if not rv.is_Mul: return rv rvd = rv.as_powers_dict() newd = rvd.copy() def signlog(expr, sign=1): if expr is S.Exp1: return sign, 1 elif isinstance(expr, exp): return sign, expr.args[0] elif sign == 1: return signlog(-expr, sign=-1) else: return None, None ee = rvd[S.Exp1] for k in rvd: if k.is_Add and len(k.args) == 2: # k == c*(1 + sign*E**x) c = k.args[0] sign, x = signlog(k.args[1]/c) if not x: continue m = rvd[k] newd[k] -= m if ee == -x*m/2: # sinh and cosh newd[S.Exp1] -= ee ee = 0 if sign == 1: newd[2*c*cosh(x/2)] += m else: newd[-2*c*sinh(x/2)] += m elif newd[1 - sign*S.Exp1**x] == -m: # tanh del newd[1 - sign*S.Exp1**x] if sign == 1: newd[-c/tanh(x/2)] += m else: newd[-c*tanh(x/2)] += m else: newd[1 + sign*S.Exp1**x] += m newd[c] += m return Mul(*[k**newd[k] for k in newd])
def build_ideal(x, terms): """ Build generators for our ideal. Terms is an iterable with elements of the form (fn, coeff), indicating that we have a generator fn(coeff*x). If any of the terms is trigonometric, sin(x) and cos(x) are guaranteed to appear in terms. Similarly for hyperbolic functions. For tan(n*x), sin(n*x) and cos(n*x) are guaranteed. """ I = [] y = Dummy('y') for fn, coeff in terms: for c, s, t, rel in ( [cos, sin, tan, cos(x)**2 + sin(x)**2 - 1], [cosh, sinh, tanh, cosh(x)**2 - sinh(x)**2 - 1]): if coeff == 1 and fn in [c, s]: I.append(rel) elif fn == t: I.append(t(coeff*x)*c(coeff*x) - s(coeff*x)) elif fn in [c, s]: cn = fn(coeff*y).expand(trig=True).subs(y, x) I.append(fn(coeff*x) - cn) return list(set(I))
def _expr_big_minus(cls, a, z, n): return cosh(2 * a * asinh(sqrt(z)) + 2 * a * pi * I * n)
def test_jscode_functions(): assert jscode(sin(x)**cos(x)) == "Math.pow(Math.sin(x), Math.cos(x))" assert jscode(sinh(x) * cosh(x)) == "Math.sinh(x)*Math.cosh(x)" assert jscode(Max(x, y) + Min(x, y)) == "Math.max(x, y) + Math.min(x, y)" assert jscode(tanh(x) * acosh(y)) == "Math.tanh(x)*Math.acosh(y)" assert jscode(asin(x) - acos(y)) == "-Math.acos(y) + Math.asin(x)"
def _expr_small_minus(cls, a, z): return cosh(2 * a * asinh(sqrt(z)))
def _expr_big(cls, a, z, n): return cosh(2 * a * acosh(sqrt(z)) + a * pi * I * (2 * n - 1))
def _expr_big(cls, a, z, n): return cosh(2*a*acosh(sqrt(z)) + a*pi*I*(2*n - 1))
def _expr_big_minus(cls, a, z, n): return cosh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n)
def test_tensorflow_math(): if not tf: skip("TensorFlow not installed") expr = Abs(x) assert tensorflow_code(expr) == "tensorflow.math.abs(x)" _compare_tensorflow_scalar((x, ), expr) expr = sign(x) assert tensorflow_code(expr) == "tensorflow.math.sign(x)" _compare_tensorflow_scalar((x, ), expr) expr = ceiling(x) assert tensorflow_code(expr) == "tensorflow.math.ceil(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = floor(x) assert tensorflow_code(expr) == "tensorflow.math.floor(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = exp(x) assert tensorflow_code(expr) == "tensorflow.math.exp(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = sqrt(x) assert tensorflow_code(expr) == "tensorflow.math.sqrt(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = x**4 assert tensorflow_code(expr) == "tensorflow.math.pow(x, 4)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = cos(x) assert tensorflow_code(expr) == "tensorflow.math.cos(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = acos(x) assert tensorflow_code(expr) == "tensorflow.math.acos(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(0, 0.95)) expr = sin(x) assert tensorflow_code(expr) == "tensorflow.math.sin(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = asin(x) assert tensorflow_code(expr) == "tensorflow.math.asin(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = tan(x) assert tensorflow_code(expr) == "tensorflow.math.tan(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = atan(x) assert tensorflow_code(expr) == "tensorflow.math.atan(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = atan2(y, x) assert tensorflow_code(expr) == "tensorflow.math.atan2(y, x)" _compare_tensorflow_scalar((y, x), expr, rng=lambda: random.random()) expr = cosh(x) assert tensorflow_code(expr) == "tensorflow.math.cosh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = acosh(x) assert tensorflow_code(expr) == "tensorflow.math.acosh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = sinh(x) assert tensorflow_code(expr) == "tensorflow.math.sinh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = asinh(x) assert tensorflow_code(expr) == "tensorflow.math.asinh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = tanh(x) assert tensorflow_code(expr) == "tensorflow.math.tanh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = atanh(x) assert tensorflow_code(expr) == "tensorflow.math.atanh(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.uniform(-.5, .5)) expr = erf(x) assert tensorflow_code(expr) == "tensorflow.math.erf(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random()) expr = loggamma(x) assert tensorflow_code(expr) == "tensorflow.math.lgamma(x)" _compare_tensorflow_scalar((x, ), expr, rng=lambda: random.random())
def _expr_small_minus(cls, a, z): return cosh(2*a*asinh(sqrt(z)))
def _trigpats(): global _trigpat a, b, c = symbols('a b c', cls=Wild) d = Wild('d', commutative=False) # for the simplifications like sinh/cosh -> tanh: # DO NOT REORDER THE FIRST 14 since these are assumed to be in this # order in _match_div_rewrite. matchers_division = ( (a * sin(b)**c / cos(b)**c, a * tan(b)**c, sin(b), cos(b)), (a * tan(b)**c * cos(b)**c, a * sin(b)**c, sin(b), cos(b)), (a * cot(b)**c * sin(b)**c, a * cos(b)**c, sin(b), cos(b)), (a * tan(b)**c / sin(b)**c, a / cos(b)**c, sin(b), cos(b)), (a * cot(b)**c / cos(b)**c, a / sin(b)**c, sin(b), cos(b)), (a * cot(b)**c * tan(b)**c, a, sin(b), cos(b)), (a * (cos(b) + 1)**c * (cos(b) - 1)**c, a * (-sin(b)**2)**c, cos(b) + 1, cos(b) - 1), (a * (sin(b) + 1)**c * (sin(b) - 1)**c, a * (-cos(b)**2)**c, sin(b) + 1, sin(b) - 1), (a * sinh(b)**c / cosh(b)**c, a * tanh(b)**c, S.One, S.One), (a * tanh(b)**c * cosh(b)**c, a * sinh(b)**c, S.One, S.One), (a * coth(b)**c * sinh(b)**c, a * cosh(b)**c, S.One, S.One), (a * tanh(b)**c / sinh(b)**c, a / cosh(b)**c, S.One, S.One), (a * coth(b)**c / cosh(b)**c, a / sinh(b)**c, S.One, S.One), (a * coth(b)**c * tanh(b)**c, a, S.One, S.One), (c * (tanh(a) + tanh(b)) / (1 + tanh(a) * tanh(b)), tanh(a + b) * c, S.One, S.One), ) matchers_add = ( (c * sin(a) * cos(b) + c * cos(a) * sin(b) + d, sin(a + b) * c + d), (c * cos(a) * cos(b) - c * sin(a) * sin(b) + d, cos(a + b) * c + d), (c * sin(a) * cos(b) - c * cos(a) * sin(b) + d, sin(a - b) * c + d), (c * cos(a) * cos(b) + c * sin(a) * sin(b) + d, cos(a - b) * c + d), (c * sinh(a) * cosh(b) + c * sinh(b) * cosh(a) + d, sinh(a + b) * c + d), (c * cosh(a) * cosh(b) + c * sinh(a) * sinh(b) + d, cosh(a + b) * c + d), ) # for cos(x)**2 + sin(x)**2 -> 1 matchers_identity = ( (a * sin(b)**2, a - a * cos(b)**2), (a * tan(b)**2, a * (1 / cos(b))**2 - a), (a * cot(b)**2, a * (1 / sin(b))**2 - a), (a * sin(b + c), a * (sin(b) * cos(c) + sin(c) * cos(b))), (a * cos(b + c), a * (cos(b) * cos(c) - sin(b) * sin(c))), (a * tan(b + c), a * ((tan(b) + tan(c)) / (1 - tan(b) * tan(c)))), (a * sinh(b)**2, a * cosh(b)**2 - a), (a * tanh(b)**2, a - a * (1 / cosh(b))**2), (a * coth(b)**2, a + a * (1 / sinh(b))**2), (a * sinh(b + c), a * (sinh(b) * cosh(c) + sinh(c) * cosh(b))), (a * cosh(b + c), a * (cosh(b) * cosh(c) + sinh(b) * sinh(c))), (a * tanh(b + c), a * ((tanh(b) + tanh(c)) / (1 + tanh(b) * tanh(c)))), ) # Reduce any lingering artifacts, such as sin(x)**2 changing # to 1-cos(x)**2 when sin(x)**2 was "simpler" artifacts = ( (a - a * cos(b)**2 + c, a * sin(b)**2 + c, cos), (a - a * (1 / cos(b))**2 + c, -a * tan(b)**2 + c, cos), (a - a * (1 / sin(b))**2 + c, -a * cot(b)**2 + c, sin), (a - a * cosh(b)**2 + c, -a * sinh(b)**2 + c, cosh), (a - a * (1 / cosh(b))**2 + c, a * tanh(b)**2 + c, cosh), (a + a * (1 / sinh(b))**2 + c, a * coth(b)**2 + c, sinh), # same as above but with noncommutative prefactor (a * d - a * d * cos(b)**2 + c, a * d * sin(b)**2 + c, cos), (a * d - a * d * (1 / cos(b))**2 + c, -a * d * tan(b)**2 + c, cos), (a * d - a * d * (1 / sin(b))**2 + c, -a * d * cot(b)**2 + c, sin), (a * d - a * d * cosh(b)**2 + c, -a * d * sinh(b)**2 + c, cosh), (a * d - a * d * (1 / cosh(b))**2 + c, a * d * tanh(b)**2 + c, cosh), (a * d + a * d * (1 / sinh(b))**2 + c, a * d * coth(b)**2 + c, sinh), ) _trigpat = (a, b, c, d, matchers_division, matchers_add, matchers_identity, artifacts) return _trigpat
def test_jscode_functions(): assert jscode(sin(x) ** cos(x)) == "Math.pow(Math.sin(x), Math.cos(x))" assert jscode(sinh(x) * cosh(x)) == "Math.sinh(x)*Math.cosh(x)" assert jscode(Max(x, y) + Min(x, y)) == "Math.max(x, y) + Math.min(x, y)" assert jscode(tanh(x)*acosh(y)) == "Math.tanh(x)*Math.acosh(y)" assert jscode(asin(x)-acos(y)) == "-Math.acos(y) + Math.asin(x)"
def exptrigsimp(expr, simplify=True): """ Simplifies exponential / trigonometric / hyperbolic functions. When ``simplify`` is True (default) the expression obtained after the simplification step will be then be passed through simplify to precondition it so the final transformations will be applied. Examples ======== >>> from sympy import exptrigsimp, exp, cosh, sinh >>> from sympy.abc import z >>> exptrigsimp(exp(z) + exp(-z)) 2*cosh(z) >>> exptrigsimp(cosh(z) - sinh(z)) exp(-z) """ from sympy.simplify.fu import hyper_as_trig, TR2i from sympy.simplify.simplify import bottom_up def exp_trig(e): # select the better of e, and e rewritten in terms of exp or trig # functions choices = [e] if e.has(*_trigs): choices.append(e.rewrite(exp)) choices.append(e.rewrite(cos)) return min(*choices, key=count_ops) newexpr = bottom_up(expr, exp_trig) if simplify: newexpr = newexpr.simplify() # conversion from exp to hyperbolic ex = newexpr.atoms(exp, S.Exp1) ex = [ei for ei in ex if 1/ei not in ex] ## sinh and cosh for ei in ex: e2 = ei**-2 if e2 in ex: a = e2.args[0]/2 if not e2 is S.Exp1 else S.Half newexpr = newexpr.subs((e2 + 1)*ei, 2*cosh(a)) newexpr = newexpr.subs((e2 - 1)*ei, 2*sinh(a)) ## exp ratios to tan and tanh for ei in ex: n, d = ei - 1, ei + 1 et = n/d etinv = d/n # not 1/et or else recursion errors arise a = ei.args[0] if ei.func is exp else S.One if a.is_Mul or a is S.ImaginaryUnit: c = a.as_coefficient(I) if c: t = S.ImaginaryUnit*tan(c/2) newexpr = newexpr.subs(etinv, 1/t) newexpr = newexpr.subs(et, t) continue t = tanh(a/2) newexpr = newexpr.subs(etinv, 1/t) newexpr = newexpr.subs(et, t) # sin/cos and sinh/cosh ratios to tan and tanh, respectively if newexpr.has(HyperbolicFunction): e, f = hyper_as_trig(newexpr) newexpr = f(TR2i(e)) if newexpr.has(TrigonometricFunction): newexpr = TR2i(newexpr) # can we ever generate an I where there was none previously? if not (newexpr.has(I) and not expr.has(I)): expr = newexpr return expr
def exptrigsimp(expr, simplify=True): """ Simplifies exponential / trigonometric / hyperbolic functions. When ``simplify`` is True (default) the expression obtained after the simplification step will be then be passed through simplify to precondition it so the final transformations will be applied. Examples ======== >>> from sympy import exptrigsimp, exp, cosh, sinh >>> from sympy.abc import z >>> exptrigsimp(exp(z) + exp(-z)) 2*cosh(z) >>> exptrigsimp(cosh(z) - sinh(z)) exp(-z) """ from sympy.simplify.fu import hyper_as_trig, TR2i from sympy.simplify.simplify import bottom_up def exp_trig(e): # select the better of e, and e rewritten in terms of exp or trig # functions choices = [e] if e.has(*_trigs): choices.append(e.rewrite(exp)) choices.append(e.rewrite(cos)) return min(*choices, key=count_ops) newexpr = bottom_up(expr, exp_trig) if simplify: newexpr = newexpr.simplify() # conversion from exp to hyperbolic ex = newexpr.atoms(exp, S.Exp1) ex = [ei for ei in ex if 1 / ei not in ex] ## sinh and cosh for ei in ex: e2 = ei**-2 if e2 in ex: a = e2.args[0] / 2 if not e2 is S.Exp1 else S.Half newexpr = newexpr.subs((e2 + 1) * ei, 2 * cosh(a)) newexpr = newexpr.subs((e2 - 1) * ei, 2 * sinh(a)) ## exp ratios to tan and tanh for ei in ex: n, d = ei - 1, ei + 1 et = n / d etinv = d / n # not 1/et or else recursion errors arise a = ei.args[0] if ei.func is exp else S.One if a.is_Mul or a is S.ImaginaryUnit: c = a.as_coefficient(I) if c: t = S.ImaginaryUnit * tan(c / 2) newexpr = newexpr.subs(etinv, 1 / t) newexpr = newexpr.subs(et, t) continue t = tanh(a / 2) newexpr = newexpr.subs(etinv, 1 / t) newexpr = newexpr.subs(et, t) # sin/cos and sinh/cosh ratios to tan and tanh, respectively if newexpr.has(HyperbolicFunction): e, f = hyper_as_trig(newexpr) newexpr = f(TR2i(e)) if newexpr.has(TrigonometricFunction): newexpr = TR2i(newexpr) # can we ever generate an I where there was none previously? if not (newexpr.has(I) and not expr.has(I)): expr = newexpr return expr
def test_C99CodePrinter__precision(): n = symbols("n", integer=True) f32_printer = C99CodePrinter(dict(type_aliases={real: float32})) f64_printer = C99CodePrinter(dict(type_aliases={real: float64})) f80_printer = C99CodePrinter(dict(type_aliases={real: float80})) assert f32_printer.doprint(sin(x + 2.1)) == "sinf(x + 2.1F)" assert f64_printer.doprint(sin(x + 2.1)) == "sin(x + 2.1000000000000001)" assert f80_printer.doprint(sin(x + Float("2.0"))) == "sinl(x + 2.0L)" for printer, suffix in zip([f32_printer, f64_printer, f80_printer], ["f", "", "l"]): def check(expr, ref): assert printer.doprint(expr) == ref.format(s=suffix, S=suffix.upper()) check(Abs(n), "abs(n)") check(Abs(x + 2.0), "fabs{s}(x + 2.0{S})") check( sin(x + 4.0) ** cos(x - 2.0), "pow{s}(sin{s}(x + 4.0{S}), cos{s}(x - 2.0{S}))", ) check(exp(x * 8.0), "exp{s}(8.0{S}*x)") check(exp2(x), "exp2{s}(x)") check(expm1(x * 4.0), "expm1{s}(4.0{S}*x)") check(Mod(n, 2), "((n) % (2))") check(Mod(2 * n + 3, 3 * n + 5), "((2*n + 3) % (3*n + 5))") check(Mod(x + 2.0, 3.0), "fmod{s}(1.0{S}*x + 2.0{S}, 3.0{S})") check(Mod(x, 2.0 * x + 3.0), "fmod{s}(1.0{S}*x, 2.0{S}*x + 3.0{S})") check(log(x / 2), "log{s}((1.0{S}/2.0{S})*x)") check(log10(3 * x / 2), "log10{s}((3.0{S}/2.0{S})*x)") check(log2(x * 8.0), "log2{s}(8.0{S}*x)") check(log1p(x), "log1p{s}(x)") check(2 ** x, "pow{s}(2, x)") check(2.0 ** x, "pow{s}(2.0{S}, x)") check(x ** 3, "pow{s}(x, 3)") check(x ** 4.0, "pow{s}(x, 4.0{S})") check(sqrt(3 + x), "sqrt{s}(x + 3)") check(Cbrt(x - 2.0), "cbrt{s}(x - 2.0{S})") check(hypot(x, y), "hypot{s}(x, y)") check(sin(3.0 * x + 2.0), "sin{s}(3.0{S}*x + 2.0{S})") check(cos(3.0 * x - 1.0), "cos{s}(3.0{S}*x - 1.0{S})") check(tan(4.0 * y + 2.0), "tan{s}(4.0{S}*y + 2.0{S})") check(asin(3.0 * x + 2.0), "asin{s}(3.0{S}*x + 2.0{S})") check(acos(3.0 * x + 2.0), "acos{s}(3.0{S}*x + 2.0{S})") check(atan(3.0 * x + 2.0), "atan{s}(3.0{S}*x + 2.0{S})") check(atan2(3.0 * x, 2.0 * y), "atan2{s}(3.0{S}*x, 2.0{S}*y)") check(sinh(3.0 * x + 2.0), "sinh{s}(3.0{S}*x + 2.0{S})") check(cosh(3.0 * x - 1.0), "cosh{s}(3.0{S}*x - 1.0{S})") check(tanh(4.0 * y + 2.0), "tanh{s}(4.0{S}*y + 2.0{S})") check(asinh(3.0 * x + 2.0), "asinh{s}(3.0{S}*x + 2.0{S})") check(acosh(3.0 * x + 2.0), "acosh{s}(3.0{S}*x + 2.0{S})") check(atanh(3.0 * x + 2.0), "atanh{s}(3.0{S}*x + 2.0{S})") check(erf(42.0 * x), "erf{s}(42.0{S}*x)") check(erfc(42.0 * x), "erfc{s}(42.0{S}*x)") check(gamma(x), "tgamma{s}(x)") check(loggamma(x), "lgamma{s}(x)") check(ceiling(x + 2.0), "ceil{s}(x + 2.0{S})") check(floor(x + 2.0), "floor{s}(x + 2.0{S})") check(fma(x, y, -z), "fma{s}(x, y, -z)") check(Max(x, 8.0, x ** 4.0), "fmax{s}(8.0{S}, fmax{s}(x, pow{s}(x, 4.0{S})))") check(Min(x, 2.0), "fmin{s}(2.0{S}, x)")
def _trigpats(): global _trigpat a, b, c = symbols('a b c', cls=Wild) d = Wild('d', commutative=False) # for the simplifications like sinh/cosh -> tanh: # DO NOT REORDER THE FIRST 14 since these are assumed to be in this # order in _match_div_rewrite. matchers_division = ( (a*sin(b)**c/cos(b)**c, a*tan(b)**c, sin(b), cos(b)), (a*tan(b)**c*cos(b)**c, a*sin(b)**c, sin(b), cos(b)), (a*cot(b)**c*sin(b)**c, a*cos(b)**c, sin(b), cos(b)), (a*tan(b)**c/sin(b)**c, a/cos(b)**c, sin(b), cos(b)), (a*cot(b)**c/cos(b)**c, a/sin(b)**c, sin(b), cos(b)), (a*cot(b)**c*tan(b)**c, a, sin(b), cos(b)), (a*(cos(b) + 1)**c*(cos(b) - 1)**c, a*(-sin(b)**2)**c, cos(b) + 1, cos(b) - 1), (a*(sin(b) + 1)**c*(sin(b) - 1)**c, a*(-cos(b)**2)**c, sin(b) + 1, sin(b) - 1), (a*sinh(b)**c/cosh(b)**c, a*tanh(b)**c, S.One, S.One), (a*tanh(b)**c*cosh(b)**c, a*sinh(b)**c, S.One, S.One), (a*coth(b)**c*sinh(b)**c, a*cosh(b)**c, S.One, S.One), (a*tanh(b)**c/sinh(b)**c, a/cosh(b)**c, S.One, S.One), (a*coth(b)**c/cosh(b)**c, a/sinh(b)**c, S.One, S.One), (a*coth(b)**c*tanh(b)**c, a, S.One, S.One), (c*(tanh(a) + tanh(b))/(1 + tanh(a)*tanh(b)), tanh(a + b)*c, S.One, S.One), ) matchers_add = ( (c*sin(a)*cos(b) + c*cos(a)*sin(b) + d, sin(a + b)*c + d), (c*cos(a)*cos(b) - c*sin(a)*sin(b) + d, cos(a + b)*c + d), (c*sin(a)*cos(b) - c*cos(a)*sin(b) + d, sin(a - b)*c + d), (c*cos(a)*cos(b) + c*sin(a)*sin(b) + d, cos(a - b)*c + d), (c*sinh(a)*cosh(b) + c*sinh(b)*cosh(a) + d, sinh(a + b)*c + d), (c*cosh(a)*cosh(b) + c*sinh(a)*sinh(b) + d, cosh(a + b)*c + d), ) # for cos(x)**2 + sin(x)**2 -> 1 matchers_identity = ( (a*sin(b)**2, a - a*cos(b)**2), (a*tan(b)**2, a*(1/cos(b))**2 - a), (a*cot(b)**2, a*(1/sin(b))**2 - a), (a*sin(b + c), a*(sin(b)*cos(c) + sin(c)*cos(b))), (a*cos(b + c), a*(cos(b)*cos(c) - sin(b)*sin(c))), (a*tan(b + c), a*((tan(b) + tan(c))/(1 - tan(b)*tan(c)))), (a*sinh(b)**2, a*cosh(b)**2 - a), (a*tanh(b)**2, a - a*(1/cosh(b))**2), (a*coth(b)**2, a + a*(1/sinh(b))**2), (a*sinh(b + c), a*(sinh(b)*cosh(c) + sinh(c)*cosh(b))), (a*cosh(b + c), a*(cosh(b)*cosh(c) + sinh(b)*sinh(c))), (a*tanh(b + c), a*((tanh(b) + tanh(c))/(1 + tanh(b)*tanh(c)))), ) # Reduce any lingering artifacts, such as sin(x)**2 changing # to 1-cos(x)**2 when sin(x)**2 was "simpler" artifacts = ( (a - a*cos(b)**2 + c, a*sin(b)**2 + c, cos), (a - a*(1/cos(b))**2 + c, -a*tan(b)**2 + c, cos), (a - a*(1/sin(b))**2 + c, -a*cot(b)**2 + c, sin), (a - a*cosh(b)**2 + c, -a*sinh(b)**2 + c, cosh), (a - a*(1/cosh(b))**2 + c, a*tanh(b)**2 + c, cosh), (a + a*(1/sinh(b))**2 + c, a*coth(b)**2 + c, sinh), # same as above but with noncommutative prefactor (a*d - a*d*cos(b)**2 + c, a*d*sin(b)**2 + c, cos), (a*d - a*d*(1/cos(b))**2 + c, -a*d*tan(b)**2 + c, cos), (a*d - a*d*(1/sin(b))**2 + c, -a*d*cot(b)**2 + c, sin), (a*d - a*d*cosh(b)**2 + c, -a*d*sinh(b)**2 + c, cosh), (a*d - a*d*(1/cosh(b))**2 + c, a*d*tanh(b)**2 + c, cosh), (a*d + a*d*(1/sinh(b))**2 + c, a*d*coth(b)**2 + c, sinh), ) _trigpat = (a, b, c, d, matchers_division, matchers_add, matchers_identity, artifacts) return _trigpat
def test_torch_math(): if not torch: skip("Torch not installed") ma = torch.tensor([[1, 2, -3, -4]]) expr = Abs(x) assert torch_code(expr) == "torch.abs(x)" f = lambdify(x, expr, 'torch') y = f(ma) c = torch.abs(ma) assert (y == c).all() expr = sign(x) assert torch_code(expr) == "torch.sign(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.randint(0, 10)) expr = ceiling(x) assert torch_code(expr) == "torch.ceil(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = floor(x) assert torch_code(expr) == "torch.floor(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = exp(x) assert torch_code(expr) == "torch.exp(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) # expr = sqrt(x) # assert torch_code(expr) == "torch.sqrt(x)" # _compare_torch_scalar((x,), expr, rng=lambda: random.random()) # expr = x ** 4 # assert torch_code(expr) == "torch.pow(x, 4)" # _compare_torch_scalar((x,), expr, rng=lambda: random.random()) expr = cos(x) assert torch_code(expr) == "torch.cos(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = acos(x) assert torch_code(expr) == "torch.acos(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(0, 0.95)) expr = sin(x) assert torch_code(expr) == "torch.sin(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = asin(x) assert torch_code(expr) == "torch.asin(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = tan(x) assert torch_code(expr) == "torch.tan(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = atan(x) assert torch_code(expr) == "torch.atan(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) # expr = atan2(y, x) # assert torch_code(expr) == "torch.atan2(y, x)" # _compare_torch_scalar((y, x), expr, rng=lambda: random.random()) expr = cosh(x) assert torch_code(expr) == "torch.cosh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = acosh(x) assert torch_code(expr) == "torch.acosh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = sinh(x) assert torch_code(expr) == "torch.sinh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = asinh(x) assert torch_code(expr) == "torch.asinh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = tanh(x) assert torch_code(expr) == "torch.tanh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(1, 2)) expr = atanh(x) assert torch_code(expr) == "torch.atanh(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.uniform(-.5, .5)) expr = erf(x) assert torch_code(expr) == "torch.erf(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random()) expr = loggamma(x) assert torch_code(expr) == "torch.lgamma(x)" _compare_torch_scalar((x, ), expr, rng=lambda: random.random())