def create_expand_pow_optimization(limit): """ Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``. The requirements for expansions are that the base needs to be a symbol and the exponent needs to be an Integer (and be less than or equal to ``limit``). Parameters ========== limit : int The highest power which is expanded into multiplication. Examples ======== >>> from sympy import Symbol, sin >>> from sympy.codegen.rewriting import create_expand_pow_optimization >>> x = Symbol('x') >>> expand_opt = create_expand_pow_optimization(3) >>> expand_opt(x**5 + x**3) x**5 + x*x*x >>> expand_opt(x**5 + x**3 + sin(x)**3) x**5 + sin(x)**3 + x*x*x """ return ReplaceOptim( lambda e: e.is_Pow and e.base.is_symbol and e.exp.is_Integer and abs( e.exp) <= limit, lambda p: (UnevaluatedExpr(Mul(*([p.base] * +p.exp), evaluate=False)) if p.exp > 0 else 1 / UnevaluatedExpr( Mul(*([p.base] * -p.exp), evaluate=False))))
def test_UnevaluatedExpr(): p, q, r = symbols("p q r", real=True) q_r = UnevaluatedExpr(q + r) expr = abs(exp(p + q_r)) assert fcode(expr, source_format="free") == "exp(p + (q + r))" x, y, z = symbols("x y z") y_z = UnevaluatedExpr(y + z) expr2 = abs(exp(x + y_z)) assert fcode(expr2, human=False)[2].lstrip() == "exp(re(x) + re(y + z))" assert fcode(expr2, user_functions={ "re": "realpart" }).lstrip() == "exp(realpart(x) + realpart(y + z))"
def ccode(eq) -> str: """Transforms a sympy expression into C99 code. Applies C99 optimizations (`sympy.codegen.rewriting.optims_c99`). Expands `pow(x; 2)` into `x*x` and `pow(x, 3)` into `x*x*x` for performance. Args: eq (sympy expression): expression to convert. Returns: a string representing the C code. """ # If the rhs is a int or float (v = 0.0), cast it to a symbol to avoid numerical errors. if isinstance(eq, (float)): eq = sp.Symbol(str(float(eq))) elif isinstance(eq, (int)): eq = sp.Symbol(str(int(eq))) # Optimize for C99 try: eq = optimize(eq, optims_c99) except: logger = logging.getLogger(__name__) logger.exception(str(eq)) sys.exit(1) # Explicitly expand the use of pow(x, 2) pow2 = ReplaceOptim( lambda p: p.is_Pow and p.exp == 2, lambda p: UnevaluatedExpr(Mul(p.base, p.base, evaluate=False)) ) eq = pow2(eq) # Explicitly expand the use of pow(x, 3) pow3 = ReplaceOptim( lambda p: p.is_Pow and p.exp == 3, lambda p: UnevaluatedExpr(Mul(Mul(p.base, p.base, evaluate=False), p.base, evaluate=False)) ) eq = pow3(eq) # Get the equivalent C code eq = sp.ccode( eq, ) # Remove the extralines of Piecewise return " ".join(eq.replace('\n', ' ').split())
def test_own_module(): f = lambdify(x, sin(x), math) assert f(0) == 0.0 p, q, r = symbols("p q r", real=True) ae = abs(exp(p + UnevaluatedExpr(q + r))) f = lambdify([p, q, r], [ae, ae], modules=math) results = f(1.0, 1e18, -1e18) refvals = [math.exp(1.0)] * 2 for res, ref in zip(results, refvals): assert abs((res - ref) / ref) < 1e-15
def create_expand_pow_optimization(limit, *, base_req=lambda b: b.is_symbol): """ Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``. Explanation =========== The requirements for expansions are that the base needs to be a symbol and the exponent needs to be an Integer (and be less than or equal to ``limit``). Parameters ========== limit : int The highest power which is expanded into multiplication. base_req : function returning bool Requirement on base for expansion to happen, default is to return the ``is_symbol`` attribute of the base. Examples ======== >>> from sympy import Symbol, sin >>> from sympy.codegen.rewriting import create_expand_pow_optimization >>> x = Symbol('x') >>> expand_opt = create_expand_pow_optimization(3) >>> expand_opt(x**5 + x**3) x**5 + x*x*x >>> expand_opt(x**5 + x**3 + sin(x)**3) x**5 + sin(x)**3 + x*x*x >>> opt2 = create_expand_pow_optimization(3 , base_req=lambda b: not b.is_Function) >>> opt2((x+1)**2 + sin(x)**2) sin(x)**2 + (x + 1)*(x + 1) """ return ReplaceOptim( lambda e: e.is_Pow and base_req(e.base) and e.exp.is_Integer and abs(e.exp) <= limit, lambda p: ( UnevaluatedExpr(Mul(*([p.base]*+p.exp), evaluate=False)) if p.exp > 0 else 1/UnevaluatedExpr(Mul(*([p.base]*-p.exp), evaluate=False)) ))
def test_UnevaluatedExpr(): a, b = symbols("a b") expr1 = 2*UnevaluatedExpr(a+b) assert str(expr1) == "2*(a + b)"