将平方项和立方项转换为乘法 [英] Converting squared and cube terms into multiplication

查看:78
本文介绍了将平方项和立方项转换为乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to convert a big expression from sage into valid C code using ccode() from sympy. However, my expression has many squared and cube terms. As pow(x,2) is far slower than x*x, I'm trying to expand those terms in my expression before the conversion. Based on this conversation, I wrote the following code :

    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)

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

It partially works, but fails as long as the power is argument of a multiplication:

    >>>_=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)

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

Why? And how can I change that ? Thank you very much,

推荐答案

如果使用 -ffast-math 进行编译,则编译器将为您进行此优化.如果您使用的是古老的编译器,或者不能影响构建过程中使用的优化级别,则可以将用户定义的函数传递给ccode(使用SymPy master分支):

If you compile with -ffast-math the compiler will do this optimization for you. If you are using an ancient compiler or cannot affect the level of optimization used in the build process you may pass a user defined function to ccode (using SymPy master branch):

>>> 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)'

这篇关于将平方项和立方项转换为乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆