Advertisement
eacousineau

ToMatlab Bugfix

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