eacousineau

ToMatlab Bugfix

Jun 15th, 2011
2,339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.13 KB | None | 0 0
  1.  
  2. (****** ToMatlab.mth -- Mathematica expressions into Matlab form *************)
  3.  
  4. (*
  5.  
  6. ToMatlab[expr]
  7.  
  8. Converts the expression expr into matlab syntax and
  9. returns it as a String.
  10.  
  11. ToMatlab[expr, name]
  12.  
  13. Returns an assignment of expr into name as a String. name can be also
  14. a more complicated string, e.g.,
  15.  
  16. ToMatlab[If[t,a,b],"function y=iffun(t,a,b)\ny"].
  17.  
  18. The special symbol Colon can be used to denote the matlab colon
  19. operator :, and Colon[a,b] for a:b, Colon[a,b,c] for a:b:c.
  20.  
  21.  
  22. WriteMatlab[expr, file]
  23. WriteMatlab[expr, file, name]
  24.  
  25. Writes the expr in matlab form into the given file. The second form
  26. makes this an assignment into the variable name. Example:
  27.  
  28. f = OpenWrite["file.m"];
  29. WriteMatlab[Cos[x]-x, f, y];
  30. Close[f];
  31.  
  32. The file argument can also be a String that gives the name of the
  33. file:
  34.  
  35. WriteMatlab[Cos[x]-x, "file.m", y];
  36.  
  37. achieves the same result as the previous example (but this limits one
  38. expression per file).
  39.  
  40.  
  41. PrintMatlab[expr]
  42. PrintMatlab[expr, name]
  43.  
  44. is like ToMatlab but instead of returning the String, it is printed on
  45. the screen.
  46.  
  47.  
  48. RulesToMatlab[rules]
  49.  
  50. Where rules is the result from Solve or NSolve: converts the rules into
  51. individual assignment statements.
  52.  
  53. *)
  54.  
  55. (* (C) 1997-1999 Harri Ojanen
  56. http://www.iki.fi/~harri.ojanen/ *)
  57.  
  58. (*
  59. Last modified June 15 2011 by Eric Cousineau
  60. Fixed a bug concerning vertcat errors in Matlab due to binary/unary operators in Matlab and the Dot-Dot-Dot operator
  61. *)
  62.  
  63. BeginPackage["MatlabUtils`ToMatlab`"]
  64.  
  65. ToMatlab::usage =
  66. "ToMatlab[expr] converts the expression expr into matlab syntax and returns it as a String.\nToMatlab[expr, name] returns an assignment of expr into name as a String. name can be also a more complicated string, e.g., ToMatlab[If[t,a,b],\"function y=iffun(t,a,b)\\ny\"].\nThe special symbol Colon can be used to denote the matlab colon operator :, and Colon[a,b] for a:b, Colon[a,b,c] for a:b:c.\nSee also WriteMatlab and PrintMatlab.\nAll functions accept an optional last argument that is the maximum line width."
  67.  
  68. WriteMatlab::usage =
  69. "WriteMatlab[expr, file] or WriteMatlab[expr, file, name] Writes the expr in matlab form into the given file. The second form makes this an assignment into the variable name.\nExample: f = OpenWrite[\"file.m\"]; WriteMatlab[Cos[x]-x, f, y]; Close[f];\nThe file argument can also be a String that gives the name of the file: WriteMatlab[Cos[x]-x, \"file.m\", y]; achieves the same result as the previous example (but this limits one expression per file).\nSee also ToMatlab and PrintMatlab."
  70.  
  71. PrintMatlab::usage =
  72. "PrintMatlab[expr] or PrintMatlab[expr, name] is like ToMatlab but instead of returning the String, it is printed on the screen. See also ToMatlab and WriteMatlab."
  73.  
  74. RulesToMatlab::usage =
  75. "RulesToMatlab[rules] where rules is from Solve or NSolve converts the rules into individual assignment statements."
  76.  
  77. (*SetMargin::usage = "SetMargin[margin]"
  78. RestoreMargin::usage = "RestoreMargin[]"*)
  79.  
  80.  
  81. Begin["`Private`"]
  82.  
  83. WriteMatlab[e_, file_OutputStream] :=
  84. (WriteString[file, ToMatlab[e,72]];)
  85.  
  86. WriteMatlab[e_, file_OutputStream, name_] :=
  87. (WriteString[file, ToMatlab[e,name,72]];) /; (!NumberQ[name])
  88.  
  89. WriteMatlab[e_, file_String] :=
  90. (Block[{f = OpenWrite[file]},
  91. WriteString[f, ToMatlab[e,72]];
  92. Close[f];];)
  93.  
  94. WriteMatlab[e_, file_String, name_] :=
  95. (Block[{f = OpenWrite[file]},
  96. WriteString[f, ToMatlab[e,name,72]];
  97. Close[f];];) /; (!NumberQ[name])
  98.  
  99. WriteMatlab[e_, file_OutputStream, margin_Integer] :=
  100. (WriteString[file, ToMatlab[e,margin]];)
  101.  
  102. WriteMatlab[e_, file_OutputStream, name_, margin_Integer] :=
  103. (WriteString[file, ToMatlab[e,name,margin]];)
  104.  
  105. WriteMatlab[e_, file_String, margin_Integer] :=
  106. (Block[{f = OpenWrite[file]},
  107. WriteString[f, ToMatlab[e,margin]];
  108. Close[f];];)
  109.  
  110. WriteMatlab[e_, file_String, name_, margin_Integer] :=
  111. (Block[{f = OpenWrite[file]},
  112. WriteString[f, ToMatlab[e,name,margin]];
  113. Close[f];];)
  114.  
  115.  
  116. PrintMatlab[e_] :=
  117. (Print[ToMatlab[e, 60]];)
  118.  
  119. PrintMatlab[e_, name_] :=
  120. (Print[ToMatlab[e, name, 60]];) /; (!NumberQ[name])
  121.  
  122. PrintMatlab[e_, margin_Integer] :=
  123. (Print[ToMatlab[e, margin]];)
  124.  
  125. PrintMatlab[e_, name_, margin_Integer] :=
  126. (Print[ToMatlab[e, name, margin]];)
  127.  
  128.  
  129. ToMatlab[e_] := foldlines[ToMatlabaux[e] <> ";\n"]
  130.  
  131. ToMatlab[e_, name_] :=
  132. ToMatlabaux[name] <> "=" <> foldlines[ToMatlabaux[e] <> ";\n"] /;
  133. (!NumberQ[name])
  134.  
  135. ToMatlab[e_, margin_Integer] :=
  136. Block[{s},
  137. SetMargin[margin];
  138. s = foldlines[ToMatlabaux[e] <> ";\n"];
  139. RestoreMargin[];
  140. s]
  141.  
  142. ToMatlab[e_, name_, margin_Integer] :=
  143. Block[{s},
  144. SetMargin[margin];
  145. s = ToMatlabaux[name] <> "=" <> foldlines[ToMatlabaux[e] <> ";\n"];
  146. RestoreMargin[];
  147. s]
  148.  
  149.  
  150. RulesToMatlab[l_List] :=
  151. If[Length[l] === 0,
  152. "",
  153. Block[{s = RulesToMatlab[ l[[1]] ]},
  154. Do[s = s <> RulesToMatlab[ l[[i]] ], {i, 2, Length[l]}];
  155. s]]
  156.  
  157. RulesToMatlab[Rule[x_, a_]]:=
  158. ToMatlab[a, ToMatlab[x] // StringDrop[#, -2]&]
  159.  
  160. (*** Numbers and strings *****************************************************)
  161.  
  162. ToMatlabaux[s_String] := s
  163.  
  164. ToMatlabaux[n_Integer] :=
  165. If[n >= 0, ToString[n], "(" <> ToString[n] <> ")"]
  166.  
  167. (*ToMatlabaux[r_Rational] :=
  168. "(" <> ToMatlabaux[Numerator[r]] <> "/" <>
  169. ToMatlabaux[Denominator[r]] <> ")"*)
  170.  
  171. ToMatlabaux[r_Rational] :=
  172. "(" <> ToString[Numerator[r]] <> " / " <>
  173. ToString[Denominator[r]] <> ")"
  174.  
  175. ToMatlabaux[r_Real] :=
  176. Block[{a = MantissaExponent[r]},
  177. If[r >= 0,
  178. ToString[N[a[[1]],18]] <> "e" <> ToString[a[[2]]],
  179. "(" <> ToString[N[a[[1]],18]] <> "e" <> ToString[a[[2]]] <> ")"]]
  180.  
  181. ToMatlabaux[I] := "sqrt(-1)";
  182.  
  183. ToMatlabaux[c_Complex] :=
  184. "(" <>
  185. If[Re[c] === 0,
  186. "",
  187. ToMatlabaux[Re[c]] <> " + "] <>
  188. If[Im[c] === 1,
  189. "sqrt(-1)",
  190. "sqrt(-1) * " <> ToMatlabaux[Im[c]] ] <> ")"
  191.  
  192.  
  193. (*** Lists, vectors and matrices *********************************************)
  194.  
  195. numberMatrixQ[m_] := MatrixQ[m] && (And @@ Map[numberListQ,m])
  196.  
  197. numberListQ[l_] := ListQ[l] && (And @@ Map[NumberQ,l])
  198.  
  199. numbermatrixToMatlab[m_] :=
  200. Block[{i, s=""},
  201. For[i=1, i<=Length[m], i++,
  202. s = s <> numbermatrixrow[m[[i]]];
  203. If[i < Length[m], s = s <> ";"]];
  204. s]
  205.  
  206. numbermatrixrow[l_] :=
  207. Block[{i, s=""},
  208. For[i=1, i<=Length[l], i++,
  209. s = s <> ToMatlabaux[l[[i]]];
  210. If[i < Length[l], s = s <> ", "]];
  211. s]
  212.  
  213. ToMatlabaux[l_List /; MatrixQ[l]] :=
  214. If[numberMatrixQ[l],
  215. "[" <> numbermatrixToMatlab[l] <> "]",
  216. "[" <> matrixToMatlab[l] <> "]"]
  217.  
  218. matrixToMatlab[m_] :=
  219. If[Length[m] === 1,
  220. ToMatlabargs[m[[1]]],
  221. ToMatlabargs[m[[1]]] <> ";" <>
  222. matrixToMatlab[ argslistdrop[m] ] ]
  223.  
  224. ToMatlabaux[l_List] := "[" <> ToMatlabargs[l] <> "]"
  225.  
  226.  
  227. (*** Symbols *****************************************************************)
  228.  
  229. ToMatlabaux[Colon] = ":"
  230. ToMatlabaux[Abs] = "abs"
  231. ToMatlabaux[Min] = "min"
  232. ToMatlabaux[Max] = "max"
  233. ToMatlabaux[Sin] = "sin"
  234. ToMatlabaux[Cos] = "cos"
  235. ToMatlabaux[Tan] = "tan"
  236. ToMatlabaux[Cot] = "cot"
  237. ToMatlabaux[Csc] = "csc"
  238. ToMatlabaux[Sec] = "sec"
  239. ToMatlabaux[ArcSin] = "asin"
  240. ToMatlabaux[ArcCos] = "acos"
  241. ToMatlabaux[ArcTan] = "atan"
  242. ToMatlabaux[ArcCot] = "acot"
  243. ToMatlabaux[ArcCsc] = "acsc"
  244. ToMatlabaux[ArcSec] = "asec"
  245. ToMatlabaux[Sinh] := "sinh"
  246. ToMatlabaux[Cosh] := "cosh"
  247. ToMatlabaux[Tanh] := "tanh"
  248. ToMatlabaux[Coth] := "coth"
  249. ToMatlabaux[Csch] := "csch"
  250. ToMatlabaux[Sech] := "sech"
  251. ToMatlabaux[ArcSinh] := "asinh"
  252. ToMatlabaux[ArcCosh] := "acosh"
  253. ToMatlabaux[ArcTanh] := "atanh"
  254. ToMatlabaux[ArcCoth] := "acoth"
  255. ToMatlabaux[ArcCsch] := "acsch"
  256. ToMatlabaux[ArcSech] := "asech"
  257. ToMatlabaux[Log] := "log"
  258. ToMatlabaux[Exp] := "exp"
  259. ToMatlabaux[MatrixExp] := "expm"
  260. ToMatlabaux[Pi] := "pi"
  261. ToMatlabaux[E] := "exp(1)"
  262. ToMatlabaux[True] := "true"
  263. ToMatlabaux[False] := "false"
  264.  
  265. ToMatlabaux[e_Symbol] := ToString[e]
  266.  
  267.  
  268. (*** Relational operators ****************************************************)
  269.  
  270. ToMatlabaux[e_ /; Head[e] === Equal] :=
  271. ToMatlabrelop[ argslist[e], "=="]
  272. ToMatlabaux[e_ /; Head[e] === Unequal] :=
  273. ToMatlabrelop[ argslist[e], "~="]
  274. ToMatlabaux[e_ /; Head[e] === Less] :=
  275. ToMatlabrelop[ argslist[e], "<"]
  276. ToMatlabaux[e_ /; Head[e] === Greater] :=
  277. ToMatlabrelop[ argslist[e], ">"]
  278. ToMatlabaux[e_ /; Head[e] === LessEqual] :=
  279. ToMatlabrelop[ argslist[e], "<="]
  280. ToMatlabaux[e_ /; Head[e] === GreaterEqual] :=
  281. ToMatlabrelop[ argslist[e], ">="]
  282. ToMatlabaux[e_ /; Head[e] === And] :=
  283. ToMatlabrelop[ argslist[e], "&"]
  284. ToMatlabaux[e_ /; Head[e] === Or] :=
  285. ToMatlabrelop[ argslist[e], "|"]
  286. ToMatlabaux[e_ /; Head[e] === Not] :=
  287. "~(" <> ToMatlabaux[e[[1]]] <> ")"
  288.  
  289. ToMatlabrelop[e_, o_] :=
  290. If[Length[e] === 1,
  291. "(" <> ToMatlabaux[e[[1]]] <> ")",
  292. "(" <> ToMatlabaux[e[[1]]] <> ") " <> o <> " " <>
  293. ToMatlabrelop[ argslistdrop[e], o] ]
  294.  
  295. relopQ[e_] := MemberQ[{Equal, Unequal, Less, Greater, LessEqual,
  296. GreaterEqual, And, Or, Not}, Head[e]]
  297.  
  298.  
  299. (*** Addition, multiplication and powers *************************************)
  300.  
  301. ToMatlabaux[e_ /; Head[e] === Plus] :=
  302. If[relopQ[e[[1]]],
  303. "(" <> ToMatlabaux[e[[1]]] <> ")",
  304. ToMatlabaux[e[[1]]] ] <>
  305. " + " <>
  306. If[Length[e] === 2,
  307. If[relopQ[e[[2]]],
  308. "(" <> ToMatlabaux[e[[2]]] <> ")",
  309. ToMatlabaux[e[[2]]] ],
  310. ToMatlabaux[ dropfirst[e] ]]
  311.  
  312. ToMatlabaux[e_ /; Head[e] === Times] :=
  313. If[Head[e[[1]]] === Plus,
  314. "(" <> ToMatlabaux[e[[1]]] <> ")",
  315. ToMatlabaux[e[[1]]] ] <>
  316. " .* " <>
  317. If[Length[e] === 2,
  318. If[Head[e[[2]]] === Plus,
  319. "(" <> ToMatlabaux[e[[2]]] <> ")",
  320. ToMatlabaux[e[[2]]] ],
  321. ToMatlabaux[ dropfirst[e] ]]
  322.  
  323. ToMatlabaux[e_ /; Head[e] === Power] :=
  324. If[Head[e[[1]]] === Plus || Head[e[[1]]] === Times || Head[e[[1]]] === Power,
  325. "(" <> ToMatlabaux[e[[1]]] <> ")",
  326. ToMatlabaux[e[[1]]] ] <>
  327. " .^ " <>
  328. If[Length[e] === 2,
  329. If[Head[e[[2]]] === Plus || Head[e[[2]]] === Times || Head[e[[2]]] === Power,
  330. "(" <> ToMatlabaux[e[[2]]] <> ")",
  331. ToMatlabaux[e[[2]]] ],
  332. ToMatlabaux[ dropfirst[e] ]]
  333.  
  334.  
  335. (*** Special cases of functions **********************************************)
  336.  
  337. ToMatlabaux[Rule[_,r_]] := ToMatlabaux[r]
  338.  
  339. ToMatlabaux[Log[10, z_]] := "log10(" <> ToMatlabaux[z] <> ")"
  340. ToMatlabaux[Log[b_, z_]] :=
  341. "log(" <> ToMatlabaux[z] <> ") ./ log(" <> ToMatlabaux[b] <> ")"
  342.  
  343. ToMatlabaux[Power[e_, 1/2]] := "sqrt(" <> ToMatlabaux[e] <> ")"
  344. ToMatlabaux[Power[E, z_]] := "exp(" <> ToMatlabaux[z] <> ")"
  345.  
  346. ToMatlabaux[If[test_, t_, f_]] :=
  347. Block[{teststr = ToMatlabaux[test]},
  348. "((" <> teststr <> ") .* (" <> ToMatlabaux[t] <> ") + (~("
  349. <> teststr <> ")) .* (" <> ToMatlabaux[f] <> "))"]
  350.  
  351. ToMatlabaux[e__ /; (Head[e] === Max || Head[e] == Min)] :=
  352. ToMatlabaux[Head[e]] <> "(" <>
  353. If[ Length[e] === 2,
  354. ToMatlabargs[e] <> ")",
  355. ToMatlabaux[e[[1]]] <> ", " <> ToMatlabaux[dropfirst[e]] <> ")"]
  356.  
  357. ToMatlabaux[Colon[a_,b_]] :=
  358. "((" <> ToMatlabaux[a] <> "):(" <> ToMatlabaux[b] <> "))"
  359. (*Is this correct? *)
  360. ToMatlabaux[Colon[a_,b_,c_]] :=
  361. "((" <> ToMatlabaux[a] <> "):(" <> ToMatlabaux[b] <>
  362. "):(" <> ToMatlabaux[c] <> "))"
  363.  
  364.  
  365. (*** General functions *******************************************************)
  366.  
  367. ToMatlabaux[e_] :=
  368. ToMatlabaux[Head[e]] <> "(" <>
  369. ToMatlabargs[ argslist[e] ] <> ")"
  370.  
  371. ToMatlabargs[e_] :=
  372. If[Length[e] === 1,
  373. ToMatlabaux[e[[1]]],
  374. ToMatlabaux[e[[1]]] <> "," <>
  375. ToMatlabargs[ argslistdrop[e] ] ]
  376.  
  377.  
  378. (*** Argument lists **********************************************************)
  379.  
  380. (*** argslist returns a List of the arguments ***)
  381. argslist[e_] :=
  382. Block[{ARGSLISTINDEX}, Table[ e[[ARGSLISTINDEX]],
  383. {ARGSLISTINDEX, 1, Length[e]}]]
  384.  
  385. (*** argslistdrop returns a List of all arguments except the first one ***)
  386. argslistdrop[e_] :=
  387. Block[{ARGSLISTINDEX}, Table[ e[[ARGSLISTINDEX]],
  388. {ARGSLISTINDEX, 2, Length[e]}]]
  389.  
  390. (*** dropfirst is like argslistdrop but retains the original Head ***)
  391. dropfirst[e_] :=
  392. e[[ Block[{i}, Table[i, {i,2,Length[e]}]] ]]
  393.  
  394.  
  395. (*** Folding long lines ******************************************************)
  396.  
  397. MARGIN = 66
  398. MARGINS = {}
  399.  
  400. SetMargin[m_] := (MARGINS = Prepend[MARGINS, MARGIN]; MARGIN = m; MARGINS)
  401.  
  402. RestoreMargin[] :=
  403. If[Length[MARGINS] > 0,
  404. MARGIN = MARGINS[[1]];
  405. MARGINS = Drop[MARGINS, 1]]
  406.  
  407. foldlines[s_String] :=
  408. Block[{cut, sin=s, sout=""},
  409. While[StringLength[sin] >= MARGIN,
  410. cut = findcut[sin];
  411. If[cut > 0,
  412. sout = sout <> StringTake[sin,cut] <> " ...\n ";
  413. sin = StringDrop[sin,cut],
  414. (* else *)
  415. sout = sout <> StringTake[sin,MARGIN];
  416. sin = StringDrop[sin,MARGIN]]];
  417. sout <> sin]
  418.  
  419. findcut[s_String] :=
  420. Block[{i=MARGIN},
  421. While[i > 0 &&
  422. !MemberQ[{";", ",", "(", ")", "+", "*", " "}, StringTake[s,{i}]],
  423. i--];
  424. i]
  425.  
  426. End[]
  427.  
  428. EndPackage[]
Advertisement
Add Comment
Please, Sign In to add comment