将表达式导出到C,第1部分[wolfram-mathematica]

Dan*_*olm 13 wolfram-mathematica

我在Mathematica中生成了几个表达式,我想将它们导出到外部C程序的源代码中."CForm"几乎完成了我想做的事情,除了取幂表示为调用Power().我的表达只涉及小功率所以我更希望C中的表达式使用内联乘法而不是调用Power().

例如CForm[2 hgt^2 k1inv^3 mx0 wid^2 + hgt^2 k1inv^3 wid^3]收益率

2*Power(hgt,2)*Power(k1inv,3)*mx0*Power(wid,2) + Power(hgt,2)*Power(k1inv,3)*Power(wid,3)

..我想要产生的是:

2*hgt*hgt*k1inv*k1inv*k1inv*mx0*wid*wid + hgt*hgt*k1inv*k1inv*k1inv*wid*wid*wid

我最初尝试挑选Power[..]表达式的内部部分并将其重新映射到乘法使用x_Symbol^y_Integer /; y > 1 :> Fold[Times, 1, Table[#1, {#2}]]已被mathematica阻止,立即将我精心生成的子表达式转换a*a*aPower[a,3];-)我知道它只是试图帮助但我不能弄清楚如何让它停下来,在这种情况下......

正如我已经写过这个问题,我已经想到我可以将输出捕获CForm到一个字符串然后执行字符串模式匹配和操作,但这是一个好方法吗?我想我喜欢将它作为Mathematica表达式进行处理,因为我重新映射然后输出..?

Leo*_*rin 14

对于手头的情况,您可以使用以下内容:

Clear[getCFormNoPowers];
getCFormNoPowers[expr_] :=
  Module[{times},      
   Apply[Function[code, Hold[CForm[code]], HoldAll],
     Hold[#] &[expr /. x_Symbol^y_Integer /; y > 1 :> 
         times @@ Table[x, {y}]] /. times -> Times]];
Run Code Online (Sandbox Code Playgroud)

例如,

In[52]:= getCFormNoPowers[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3]

Out[52]= Hold[2*mx0*(hgt*hgt)*(wid*wid)*(k1inv*k1inv*k1inv) + 
hgt*hgt*(k1inv*k1inv*k1inv)* (wid*wid*wid)]
Run Code Online (Sandbox Code Playgroud)

结果包含在内Hold,以防止其评估回到Power-s.您可以随时使用类似的内容将其转换为字符串ToString[HoldForm@@result].或者你可以进一步操纵.

编辑:

作为替代方案,您可以这样做:

Clear[getCFormNoPowers];
getCFormNoPowers[expr_] :=
 Block[{Times},
   SetAttributes[Times, {Flat, OneIdentity}];
   Apply[Function[code, Hold[CForm[code]], HoldAll],
   Hold[#] &[expr /. x_Symbol^y_Integer /; y > 1 :> Times @@ Table[x, {y}]]]];
Run Code Online (Sandbox Code Playgroud)

这也将保留您的条款的原始顺序,并将摆脱不必要的括号,所以这似乎恰好符合您的规格.

通常,您可能希望查看版本8的新"符号C生成"功能.将代码映射到符号C表达式可能是一种更强大的方法.这样,您不必一直担心评估,并且您可以使用新功能在最后生成整个C程序.

编辑2:

为了说明如何使用SymbolicC解决问题:

Needs["SymbolicC`"];

Clear[getCFormNoPowersSymC];
getCFormNoPowersSymC[expr_] :=
  Block[{Times},
   SetAttributes[Times, {Flat, Orderless}];
   ToCCodeString[
     expr /. x_Symbol^y_Integer /; y > 1 :> Times @@ Table[x, {y}] //.     
       HoldPattern[(op : (Times | Plus))[args__]] :>  COperator[op, {args}]]];

In[53]:= getCFormNoPowersSymC[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3]

Out[53]= 2 * hgt * hgt * k1inv * k1inv * k1inv * mx0 * wid * wid + 
    hgt * hgt * k1inv * k1inv * k1inv * wid * wid * wid
Run Code Online (Sandbox Code Playgroud)

这种方法IMO有几个优点.也许两个主要的可组合性(一个可以用符号形式嵌套这样的表达式,从较小的代码构建更大的代码块),以及一个人不必考虑评估的事实(我不需要任何技巧)Hold这里).