latex.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /* eslint no-template-curly-in-string: "off" */
  2. import escapeLatexLib from 'escape-latex';
  3. import { hasOwnProperty } from './object.js';
  4. export var latexSymbols = {
  5. // GREEK LETTERS
  6. Alpha: 'A',
  7. alpha: '\\alpha',
  8. Beta: 'B',
  9. beta: '\\beta',
  10. Gamma: '\\Gamma',
  11. gamma: '\\gamma',
  12. Delta: '\\Delta',
  13. delta: '\\delta',
  14. Epsilon: 'E',
  15. epsilon: '\\epsilon',
  16. varepsilon: '\\varepsilon',
  17. Zeta: 'Z',
  18. zeta: '\\zeta',
  19. Eta: 'H',
  20. eta: '\\eta',
  21. Theta: '\\Theta',
  22. theta: '\\theta',
  23. vartheta: '\\vartheta',
  24. Iota: 'I',
  25. iota: '\\iota',
  26. Kappa: 'K',
  27. kappa: '\\kappa',
  28. varkappa: '\\varkappa',
  29. Lambda: '\\Lambda',
  30. lambda: '\\lambda',
  31. Mu: 'M',
  32. mu: '\\mu',
  33. Nu: 'N',
  34. nu: '\\nu',
  35. Xi: '\\Xi',
  36. xi: '\\xi',
  37. Omicron: 'O',
  38. omicron: 'o',
  39. Pi: '\\Pi',
  40. pi: '\\pi',
  41. varpi: '\\varpi',
  42. Rho: 'P',
  43. rho: '\\rho',
  44. varrho: '\\varrho',
  45. Sigma: '\\Sigma',
  46. sigma: '\\sigma',
  47. varsigma: '\\varsigma',
  48. Tau: 'T',
  49. tau: '\\tau',
  50. Upsilon: '\\Upsilon',
  51. upsilon: '\\upsilon',
  52. Phi: '\\Phi',
  53. phi: '\\phi',
  54. varphi: '\\varphi',
  55. Chi: 'X',
  56. chi: '\\chi',
  57. Psi: '\\Psi',
  58. psi: '\\psi',
  59. Omega: '\\Omega',
  60. omega: '\\omega',
  61. // logic
  62. true: '\\mathrm{True}',
  63. false: '\\mathrm{False}',
  64. // other
  65. i: 'i',
  66. // TODO use \i ??
  67. inf: '\\infty',
  68. Inf: '\\infty',
  69. infinity: '\\infty',
  70. Infinity: '\\infty',
  71. oo: '\\infty',
  72. lim: '\\lim',
  73. undefined: '\\mathbf{?}'
  74. };
  75. export var latexOperators = {
  76. transpose: '^\\top',
  77. ctranspose: '^H',
  78. factorial: '!',
  79. pow: '^',
  80. dotPow: '.^\\wedge',
  81. // TODO find ideal solution
  82. unaryPlus: '+',
  83. unaryMinus: '-',
  84. bitNot: '\\~',
  85. // TODO find ideal solution
  86. not: '\\neg',
  87. multiply: '\\cdot',
  88. divide: '\\frac',
  89. // TODO how to handle that properly?
  90. dotMultiply: '.\\cdot',
  91. // TODO find ideal solution
  92. dotDivide: '.:',
  93. // TODO find ideal solution
  94. mod: '\\mod',
  95. add: '+',
  96. subtract: '-',
  97. to: '\\rightarrow',
  98. leftShift: '<<',
  99. rightArithShift: '>>',
  100. rightLogShift: '>>>',
  101. equal: '=',
  102. unequal: '\\neq',
  103. smaller: '<',
  104. larger: '>',
  105. smallerEq: '\\leq',
  106. largerEq: '\\geq',
  107. bitAnd: '\\&',
  108. bitXor: '\\underline{|}',
  109. bitOr: '|',
  110. and: '\\wedge',
  111. xor: '\\veebar',
  112. or: '\\vee'
  113. };
  114. export var latexFunctions = {
  115. // arithmetic
  116. abs: {
  117. 1: '\\left|${args[0]}\\right|'
  118. },
  119. add: {
  120. 2: "\\left(${args[0]}".concat(latexOperators.add, "${args[1]}\\right)")
  121. },
  122. cbrt: {
  123. 1: '\\sqrt[3]{${args[0]}}'
  124. },
  125. ceil: {
  126. 1: '\\left\\lceil${args[0]}\\right\\rceil'
  127. },
  128. cube: {
  129. 1: '\\left(${args[0]}\\right)^3'
  130. },
  131. divide: {
  132. 2: '\\frac{${args[0]}}{${args[1]}}'
  133. },
  134. dotDivide: {
  135. 2: "\\left(${args[0]}".concat(latexOperators.dotDivide, "${args[1]}\\right)")
  136. },
  137. dotMultiply: {
  138. 2: "\\left(${args[0]}".concat(latexOperators.dotMultiply, "${args[1]}\\right)")
  139. },
  140. dotPow: {
  141. 2: "\\left(${args[0]}".concat(latexOperators.dotPow, "${args[1]}\\right)")
  142. },
  143. exp: {
  144. 1: '\\exp\\left(${args[0]}\\right)'
  145. },
  146. expm1: "\\left(e".concat(latexOperators.pow, "{${args[0]}}-1\\right)"),
  147. fix: {
  148. 1: '\\mathrm{${name}}\\left(${args[0]}\\right)'
  149. },
  150. floor: {
  151. 1: '\\left\\lfloor${args[0]}\\right\\rfloor'
  152. },
  153. gcd: '\\gcd\\left(${args}\\right)',
  154. hypot: '\\hypot\\left(${args}\\right)',
  155. log: {
  156. 1: '\\ln\\left(${args[0]}\\right)',
  157. 2: '\\log_{${args[1]}}\\left(${args[0]}\\right)'
  158. },
  159. log10: {
  160. 1: '\\log_{10}\\left(${args[0]}\\right)'
  161. },
  162. log1p: {
  163. 1: '\\ln\\left(${args[0]}+1\\right)',
  164. 2: '\\log_{${args[1]}}\\left(${args[0]}+1\\right)'
  165. },
  166. log2: '\\log_{2}\\left(${args[0]}\\right)',
  167. mod: {
  168. 2: "\\left(${args[0]}".concat(latexOperators.mod, "${args[1]}\\right)")
  169. },
  170. multiply: {
  171. 2: "\\left(${args[0]}".concat(latexOperators.multiply, "${args[1]}\\right)")
  172. },
  173. norm: {
  174. 1: '\\left\\|${args[0]}\\right\\|',
  175. 2: undefined // use default template
  176. },
  177. nthRoot: {
  178. 2: '\\sqrt[${args[1]}]{${args[0]}}'
  179. },
  180. nthRoots: {
  181. 2: '\\{y : $y^{args[1]} = {${args[0]}}\\}'
  182. },
  183. pow: {
  184. 2: "\\left(${args[0]}\\right)".concat(latexOperators.pow, "{${args[1]}}")
  185. },
  186. round: {
  187. 1: '\\left\\lfloor${args[0]}\\right\\rceil',
  188. 2: undefined // use default template
  189. },
  190. sign: {
  191. 1: '\\mathrm{${name}}\\left(${args[0]}\\right)'
  192. },
  193. sqrt: {
  194. 1: '\\sqrt{${args[0]}}'
  195. },
  196. square: {
  197. 1: '\\left(${args[0]}\\right)^2'
  198. },
  199. subtract: {
  200. 2: "\\left(${args[0]}".concat(latexOperators.subtract, "${args[1]}\\right)")
  201. },
  202. unaryMinus: {
  203. 1: "".concat(latexOperators.unaryMinus, "\\left(${args[0]}\\right)")
  204. },
  205. unaryPlus: {
  206. 1: "".concat(latexOperators.unaryPlus, "\\left(${args[0]}\\right)")
  207. },
  208. // bitwise
  209. bitAnd: {
  210. 2: "\\left(${args[0]}".concat(latexOperators.bitAnd, "${args[1]}\\right)")
  211. },
  212. bitNot: {
  213. 1: latexOperators.bitNot + '\\left(${args[0]}\\right)'
  214. },
  215. bitOr: {
  216. 2: "\\left(${args[0]}".concat(latexOperators.bitOr, "${args[1]}\\right)")
  217. },
  218. bitXor: {
  219. 2: "\\left(${args[0]}".concat(latexOperators.bitXor, "${args[1]}\\right)")
  220. },
  221. leftShift: {
  222. 2: "\\left(${args[0]}".concat(latexOperators.leftShift, "${args[1]}\\right)")
  223. },
  224. rightArithShift: {
  225. 2: "\\left(${args[0]}".concat(latexOperators.rightArithShift, "${args[1]}\\right)")
  226. },
  227. rightLogShift: {
  228. 2: "\\left(${args[0]}".concat(latexOperators.rightLogShift, "${args[1]}\\right)")
  229. },
  230. // combinatorics
  231. bellNumbers: {
  232. 1: '\\mathrm{B}_{${args[0]}}'
  233. },
  234. catalan: {
  235. 1: '\\mathrm{C}_{${args[0]}}'
  236. },
  237. stirlingS2: {
  238. 2: '\\mathrm{S}\\left(${args}\\right)'
  239. },
  240. // complex
  241. arg: {
  242. 1: '\\arg\\left(${args[0]}\\right)'
  243. },
  244. conj: {
  245. 1: '\\left(${args[0]}\\right)^*'
  246. },
  247. im: {
  248. 1: '\\Im\\left\\lbrace${args[0]}\\right\\rbrace'
  249. },
  250. re: {
  251. 1: '\\Re\\left\\lbrace${args[0]}\\right\\rbrace'
  252. },
  253. // logical
  254. and: {
  255. 2: "\\left(${args[0]}".concat(latexOperators.and, "${args[1]}\\right)")
  256. },
  257. not: {
  258. 1: latexOperators.not + '\\left(${args[0]}\\right)'
  259. },
  260. or: {
  261. 2: "\\left(${args[0]}".concat(latexOperators.or, "${args[1]}\\right)")
  262. },
  263. xor: {
  264. 2: "\\left(${args[0]}".concat(latexOperators.xor, "${args[1]}\\right)")
  265. },
  266. // matrix
  267. cross: {
  268. 2: '\\left(${args[0]}\\right)\\times\\left(${args[1]}\\right)'
  269. },
  270. ctranspose: {
  271. 1: "\\left(${args[0]}\\right)".concat(latexOperators.ctranspose)
  272. },
  273. det: {
  274. 1: '\\det\\left(${args[0]}\\right)'
  275. },
  276. dot: {
  277. 2: '\\left(${args[0]}\\cdot${args[1]}\\right)'
  278. },
  279. expm: {
  280. 1: '\\exp\\left(${args[0]}\\right)'
  281. },
  282. inv: {
  283. 1: '\\left(${args[0]}\\right)^{-1}'
  284. },
  285. pinv: {
  286. 1: '\\left(${args[0]}\\right)^{+}'
  287. },
  288. sqrtm: {
  289. 1: "{${args[0]}}".concat(latexOperators.pow, "{\\frac{1}{2}}")
  290. },
  291. trace: {
  292. 1: '\\mathrm{tr}\\left(${args[0]}\\right)'
  293. },
  294. transpose: {
  295. 1: "\\left(${args[0]}\\right)".concat(latexOperators.transpose)
  296. },
  297. // probability
  298. combinations: {
  299. 2: '\\binom{${args[0]}}{${args[1]}}'
  300. },
  301. combinationsWithRep: {
  302. 2: '\\left(\\!\\!{\\binom{${args[0]}}{${args[1]}}}\\!\\!\\right)'
  303. },
  304. factorial: {
  305. 1: "\\left(${args[0]}\\right)".concat(latexOperators.factorial)
  306. },
  307. gamma: {
  308. 1: '\\Gamma\\left(${args[0]}\\right)'
  309. },
  310. lgamma: {
  311. 1: '\\ln\\Gamma\\left(${args[0]}\\right)'
  312. },
  313. // relational
  314. equal: {
  315. 2: "\\left(${args[0]}".concat(latexOperators.equal, "${args[1]}\\right)")
  316. },
  317. larger: {
  318. 2: "\\left(${args[0]}".concat(latexOperators.larger, "${args[1]}\\right)")
  319. },
  320. largerEq: {
  321. 2: "\\left(${args[0]}".concat(latexOperators.largerEq, "${args[1]}\\right)")
  322. },
  323. smaller: {
  324. 2: "\\left(${args[0]}".concat(latexOperators.smaller, "${args[1]}\\right)")
  325. },
  326. smallerEq: {
  327. 2: "\\left(${args[0]}".concat(latexOperators.smallerEq, "${args[1]}\\right)")
  328. },
  329. unequal: {
  330. 2: "\\left(${args[0]}".concat(latexOperators.unequal, "${args[1]}\\right)")
  331. },
  332. // special
  333. erf: {
  334. 1: 'erf\\left(${args[0]}\\right)'
  335. },
  336. // statistics
  337. max: '\\max\\left(${args}\\right)',
  338. min: '\\min\\left(${args}\\right)',
  339. variance: '\\mathrm{Var}\\left(${args}\\right)',
  340. // trigonometry
  341. acos: {
  342. 1: '\\cos^{-1}\\left(${args[0]}\\right)'
  343. },
  344. acosh: {
  345. 1: '\\cosh^{-1}\\left(${args[0]}\\right)'
  346. },
  347. acot: {
  348. 1: '\\cot^{-1}\\left(${args[0]}\\right)'
  349. },
  350. acoth: {
  351. 1: '\\coth^{-1}\\left(${args[0]}\\right)'
  352. },
  353. acsc: {
  354. 1: '\\csc^{-1}\\left(${args[0]}\\right)'
  355. },
  356. acsch: {
  357. 1: '\\mathrm{csch}^{-1}\\left(${args[0]}\\right)'
  358. },
  359. asec: {
  360. 1: '\\sec^{-1}\\left(${args[0]}\\right)'
  361. },
  362. asech: {
  363. 1: '\\mathrm{sech}^{-1}\\left(${args[0]}\\right)'
  364. },
  365. asin: {
  366. 1: '\\sin^{-1}\\left(${args[0]}\\right)'
  367. },
  368. asinh: {
  369. 1: '\\sinh^{-1}\\left(${args[0]}\\right)'
  370. },
  371. atan: {
  372. 1: '\\tan^{-1}\\left(${args[0]}\\right)'
  373. },
  374. atan2: {
  375. 2: '\\mathrm{atan2}\\left(${args}\\right)'
  376. },
  377. atanh: {
  378. 1: '\\tanh^{-1}\\left(${args[0]}\\right)'
  379. },
  380. cos: {
  381. 1: '\\cos\\left(${args[0]}\\right)'
  382. },
  383. cosh: {
  384. 1: '\\cosh\\left(${args[0]}\\right)'
  385. },
  386. cot: {
  387. 1: '\\cot\\left(${args[0]}\\right)'
  388. },
  389. coth: {
  390. 1: '\\coth\\left(${args[0]}\\right)'
  391. },
  392. csc: {
  393. 1: '\\csc\\left(${args[0]}\\right)'
  394. },
  395. csch: {
  396. 1: '\\mathrm{csch}\\left(${args[0]}\\right)'
  397. },
  398. sec: {
  399. 1: '\\sec\\left(${args[0]}\\right)'
  400. },
  401. sech: {
  402. 1: '\\mathrm{sech}\\left(${args[0]}\\right)'
  403. },
  404. sin: {
  405. 1: '\\sin\\left(${args[0]}\\right)'
  406. },
  407. sinh: {
  408. 1: '\\sinh\\left(${args[0]}\\right)'
  409. },
  410. tan: {
  411. 1: '\\tan\\left(${args[0]}\\right)'
  412. },
  413. tanh: {
  414. 1: '\\tanh\\left(${args[0]}\\right)'
  415. },
  416. // unit
  417. to: {
  418. 2: "\\left(${args[0]}".concat(latexOperators.to, "${args[1]}\\right)")
  419. },
  420. // utils
  421. numeric: function numeric(node, options) {
  422. // Not sure if this is strictly right but should work correctly for the vast majority of use cases.
  423. return node.args[0].toTex();
  424. },
  425. // type
  426. number: {
  427. 0: '0',
  428. 1: '\\left(${args[0]}\\right)',
  429. 2: '\\left(\\left(${args[0]}\\right)${args[1]}\\right)'
  430. },
  431. string: {
  432. 0: '\\mathtt{""}',
  433. 1: '\\mathrm{string}\\left(${args[0]}\\right)'
  434. },
  435. bignumber: {
  436. 0: '0',
  437. 1: '\\left(${args[0]}\\right)'
  438. },
  439. complex: {
  440. 0: '0',
  441. 1: '\\left(${args[0]}\\right)',
  442. 2: "\\left(\\left(${args[0]}\\right)+".concat(latexSymbols.i, "\\cdot\\left(${args[1]}\\right)\\right)")
  443. },
  444. matrix: {
  445. 0: '\\begin{bmatrix}\\end{bmatrix}',
  446. 1: '\\left(${args[0]}\\right)',
  447. 2: '\\left(${args[0]}\\right)'
  448. },
  449. sparse: {
  450. 0: '\\begin{bsparse}\\end{bsparse}',
  451. 1: '\\left(${args[0]}\\right)'
  452. },
  453. unit: {
  454. 1: '\\left(${args[0]}\\right)',
  455. 2: '\\left(\\left(${args[0]}\\right)${args[1]}\\right)'
  456. }
  457. };
  458. export var defaultTemplate = '\\mathrm{${name}}\\left(${args}\\right)';
  459. var latexUnits = {
  460. deg: '^\\circ'
  461. };
  462. export function escapeLatex(string) {
  463. return escapeLatexLib(string, {
  464. preserveFormatting: true
  465. });
  466. }
  467. // @param {string} name
  468. // @param {boolean} isUnit
  469. export function toSymbol(name, isUnit) {
  470. isUnit = typeof isUnit === 'undefined' ? false : isUnit;
  471. if (isUnit) {
  472. if (hasOwnProperty(latexUnits, name)) {
  473. return latexUnits[name];
  474. }
  475. return '\\mathrm{' + escapeLatex(name) + '}';
  476. }
  477. if (hasOwnProperty(latexSymbols, name)) {
  478. return latexSymbols[name];
  479. }
  480. return escapeLatex(name);
  481. }