| 90 | } |
| 91 | |
| 92 | function mjToSympy(e: any): string { |
| 93 | if (typeof e === 'number') return String(e); |
| 94 | if (typeof e === 'string') return CONSTS[e] || e; |
| 95 | const [h, ...a] = e; |
| 96 | const A = a.map(mjToSympy); |
| 97 | switch (h) { |
| 98 | case 'Add': return '(' + A.join(' + ') + ')'; |
| 99 | case 'Subtract': return '(' + A[0] + ' - ' + A[1] + ')'; |
| 100 | case 'Negate': return '(-' + A[0] + ')'; |
| 101 | case 'Multiply': return '(' + A.join('*') + ')'; |
| 102 | case 'Divide': return '(' + A[0] + '/' + A[1] + ')'; |
| 103 | case 'Power': return '(' + A[0] + ')**(' + A[1] + ')'; |
| 104 | case 'Rational': return 'Rational(' + a[0] + ',' + a[1] + ')'; |
| 105 | case 'Sqrt': return 'sqrt(' + A[0] + ')'; |
| 106 | case 'Root': return '(' + A[0] + ')**(Rational(1,' + a[1] + '))'; |
| 107 | case 'Abs': return 'Abs(' + A[0] + ')'; |
| 108 | case 'Exp': return 'exp(' + A[0] + ')'; |
| 109 | case 'Ln': case 'Log': return 'log(' + A.join(', ') + ')'; |
| 110 | case 'Sin': case 'Cos': case 'Tan': case 'Cot': case 'Sec': case 'Csc': |
| 111 | case 'Sinh': case 'Cosh': case 'Tanh': |
| 112 | return h.toLowerCase() + '(' + A[0] + ')'; |
| 113 | case 'Arcsin': return 'asin(' + A[0] + ')'; |
| 114 | case 'Arccos': return 'acos(' + A[0] + ')'; |
| 115 | case 'Arctan': return 'atan(' + A[0] + ')'; |
| 116 | default: throw new Error('untranslatable: ' + h); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | function median(xs: number[]) { const s = [...xs].sort((a, b) => a - b); const m = Math.floor(s.length / 2); return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2; } |
| 121 | function timeit(fn: () => void) { |