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

时间:2011-03-25 14:31:07

标签: 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*a转换为正确的回到Power[a,3] ;-)我知道它只是试图帮助,但我无法弄清楚如何要求它停止,在这种情况下......

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

1 个答案:

答案 0 :(得分: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]];

例如,

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

结果包含在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}]]]];

这也将保留您的条款的原始顺序,并将摆脱不必要的括号,因此这个似乎与您的规格完全一致。

通常,您可能希望查看版本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

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