Wolfram mathematica 将表达式导出到C,第1部分[wolfram mathematica]
我有几个用Mathematica生成的表达式,我想导出到外部C程序的源代码中。“CForm”几乎实现了我想要的功能,除了求幂表示为调用Wolfram mathematica 将表达式导出到C,第1部分[wolfram mathematica],wolfram-mathematica,Wolfram Mathematica,我有几个用Mathematica生成的表达式,我想导出到外部C程序的源代码中。“CForm”几乎实现了我想要的功能,除了求幂表示为调用Power()。我的表达式只涉及小的幂,因此我更希望C中的表达式使用内联乘法,而不是调用Power() 例如,CForm[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3] 2*功率(hgt,2)*功率(k1inv,3)*mx0*功率(wid,2)+ 功率(hgt,2)*功率(k1inv,3)*功率(wid,3) …而我想
Power()
。我的表达式只涉及小的幂,因此我更希望C中的表达式使用内联乘法,而不是调用Power()
例如,CForm[2 hgt^2 k1inv^3 mx0 wid^2+hgt^2 k1inv^3 wid^3]
2*功率(hgt,2)*功率(k1inv,3)*mx0*功率(wid,2)+
功率(hgt,2)*功率(k1inv,3)*功率(wid,3)
…而我想产生的是:
2*hgt*hgt*k1inv*k1inv*mx0*wid*wid+
hgt*hgt*k1inv*k1inv*k1inv*wid*wid*wid
我最初尝试选择表达式的内部幂[..]
部分,并使用x\u符号^y\u整数/,将其重新映射到乘法;y>1:>Fold[Times,1,Table[#1,{#2}]
被mathematica立即将我精心生成的子表达式a*a*a
右转为幂[a,3]
;-)我知道它只是想帮忙,但我不知道如何让它停下来,在这种情况下
在我写这个问题时,我突然想到,我可以将
CForm
的输出捕获到一个字符串中,然后对其执行字符串模式匹配和操作,但这是一个好方法吗?我想我更喜欢将其作为Mathematica表达式进行处理,因为我需要重新映射,然后输出..?对于手头的案例,您可以使用以下内容:
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:
要说明如何使用SymbolicCC解决问题,请执行以下操作:
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
这种方法有几个优点。也许这两个主要因素是可组合性(人们可以将这些表达式嵌套在它们的符号形式中,从较小的代码块中构建较大的代码块),以及一个不需要考虑太多计算的事实(我不需要在这里使用
Hold
的任何技巧)。感谢您给出了一个很好的答案,我仍然对它的许多微妙之处感到困惑(例如,为什么HoldAll
用于CForm?
巧妙地使用时间,但随后在Hold
之外改为时间。以及未记录的(?)使用HoldAll
作为应用的参数),我实际上删除了HoldAll
,这是不必要的。另请参见另一个带有块的解决方案。将属性添加到纯函数的可能性记录在函数
页面中,这是“更多信息”部分下的最后一项。如果我使用了函数[Null,Hold[CForm[#]和HoldAll]
,则会使用未记录的用法。这里最有趣的是,CForm
在Hold
内部工作。因此,与其他形式一样,它不是通常的命令,而是表示输出的特殊模式;如果我复制输出,然后粘贴到笔记本中,它似乎是Hold中的一个字符串值,例如Hold[“2 hgt hgt hgt hgt k1inv k1inv k1inv mx0 wid wid+hgt hgt hgt k1inv k1inv k1inv wid wid”]
但将相同的复制缓冲区粘贴到文本编辑器中或执行Fullform
显示它正在被保存Hold[CForm][2 hgt hgt k1inv k1inv k1inv mx0 wid wid+hgt hgt hgt k1inv k1inv k1inv wid wid wid]
;奇怪,但CForm的文档确实警告说它只是一个巧妙的语法糖衣。顺便说一句,非常感谢您的帮助,这解决了我的问题。@Leonid Shifrin我一直在研究“符号C代”8的功能,但除了用Mathematica表示c程序,或者用参数化方法描述它,以便您可以快速生成同一程序的多个版本之外,我还不知道如何以合理的方式使用它。回到问题上来,我不知道如何用它来代替CForm。我可以想象你可以用符号C的概念来代替CForm,但这是工作,我希望Mathematica能帮我这么做。@Sjoerd坦白地说,我还没有太多地使用它。但在这种情况下,它并不太难,代码大小也差不多(见我文章的编辑部分),而这也可以作为构建更大程序的构建块,因此可以像这样累积自己的函数,最终将它们转换为Mathematica的一小部分C的迷你编译器,以满足个人需要。