экспорт выражений в C, часть 1 [wolfram-mathematica] - PullRequest
13 голосов
/ 25 марта 2011

У меня есть несколько выражений, сгенерированных в Mathematica, которые я хотел бы экспортировать в исходный код внешней программы на Си. «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 Ответ

14 голосов
/ 25 марта 2011

Для данного случая вы можете использовать что-то вроде следующего:

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 -с.Вы можете преобразовать его в строку в любое время, используя что-то вроде 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}]]]];

, который также сохранит исходный порядок ваших терминов и избавит от ненужных скобок,так что этот, кажется, точно соответствует вашим спецификациям.

Как правило, вы можете захотеть взглянуть на новые возможности «символического C-генерирования» версии 8. Отображение вашего кода в символические 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 здесь).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...