将平方项和立方项转换为乘法

Converting squared and cube terms into multiplication

我正在尝试使用来自 sympy 的 ccode() 将来自 sage 的大表达式转换为有效的 C 代码。但是,我的表达式有很多平方项和立方项。由于 pow(x,2) 比 x*x 慢得多,我试图在转换之前在我的表达式中扩展这些术语。 基于 this 对话,我编写了以下代码:

    from sympy import Symbol, Mul, Pow, pprint, Matrix, symbols
    from sympy.core import numbers


    def pow_to_mul(expr):
         """
         Convert integer powers in an expression to Muls, like a**2 => a*a.
         """
         pows = list(expr.atoms(Pow))
         pows = [p for p in pows if p.as_base_exp()[1]>=0]
         if any(not e.is_Integer for b, e in (i.as_base_exp() for i in pows)):

              raise ValueError("A power contains a non-integer exponent")
         repl = zip(pows, (Mul(*[b]*e,evaluate=False) for b,e in (i.as_base_exp() for i in pows)))
         return expr.subs(repl)

它部分有效,但只要幂是乘法的自变量就会失败:

    >>>_=var('x')
    >>>print pow_to_mul((x^3+2*x^2)._sympy_())
    2*x**2 + x*x*x
    >>>print pow_to_mul((x^2/(1+x^2)+(1-x^2)/(1+x^2))._sympy_())
    x**2/(x*x + 1) - (x*x - 1)/(x*x + 1)

为什么?我该如何改变呢? 非常感谢,

如果你用-ffast-math编译,编译器会为你做这个优化。如果您使用的是古老的编译器或不能影响构建过程中使用的优化级别,您可以将用户定义的函数传递给 ccode(使用 SymPy 主分支):

>>> ccode(x**97 + 4*x**7 + 5*x**3 + 3**pi, user_functions={'Pow': [
...   (lambda b, e: e.is_Integer and e < 42, lambda b, e: '*'.join([b]*int(e))),
...   (lambda b, e: not e.is_Integer, 'pow')]})
'pow(x, 97) + 4*x*x*x*x*x*x*x + 5*x*x*x + pow(3, M_PI)'