| 17 | import { isNumber } from '../boxed-expression/type-guards.js'; |
| 18 | |
| 19 | export function toTimesPower(ce: ComputeEngine, e: Expression): Expression { |
| 20 | if (e.symbol || !e.ops) return e; |
| 21 | const ops = e.ops.map((o) => toTimesPower(ce, o)); |
| 22 | |
| 23 | switch (e.operator) { |
| 24 | case 'Negate': |
| 25 | return mul(ce, [ce.NegativeOne, ...factors(ops[0])]); |
| 26 | case 'Subtract': |
| 27 | return ce._fn('Add', [ |
| 28 | ops[0], |
| 29 | mul(ce, [ce.NegativeOne, ...factors(ops[1])]), |
| 30 | ]); |
| 31 | case 'Divide': |
| 32 | return mul(ce, [...factors(ops[0]), ...invert(ce, ops[1])]); |
| 33 | case 'Sqrt': |
| 34 | return pow(ce, ops[0], ce.expr(['Rational', 1, 2] as any)); |
| 35 | case 'Root': { |
| 36 | const n = ops[1]; |
| 37 | if (isNumber(n) && n.isInteger) |
| 38 | return pow(ce, ops[0], ce.expr(['Rational', 1, n.re as any] as any)); |
| 39 | break; |
| 40 | } |
| 41 | case 'Power': |
| 42 | return pow(ce, ops[0], ops[1]); |
| 43 | } |
| 44 | |
| 45 | if (e.operator === 'Multiply') return mul(ce, ops.flatMap(factors)); |
| 46 | return rebuilt(ce, e, ops); |
| 47 | } |
| 48 | |
| 49 | function rebuilt( |
| 50 | ce: ComputeEngine, |