예제 #1
0
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))))
예제 #2
0
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))"
예제 #3
0
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())
예제 #4
0
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
예제 #5
0
파일: rewriting.py 프로젝트: rikardn/sympy
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))
        ))
예제 #6
0
def test_UnevaluatedExpr():
    a, b = symbols("a b")
    expr1 = 2*UnevaluatedExpr(a+b)
    assert str(expr1) == "2*(a + b)"