Recursively expand products and positive-integer powers of sums into a flat * sum, treating every leaf (E^…, symbols, x-powers) as opaque. Used after * `hyperbolicToExp` because CE's `Expand` is shallow — it will not expand a * Power(Add, n) that sits as a factor inside a Multiply. Non-integer
(ce: ComputeEngine, e: Expression)
| 3676 | if (u.symbol === x || CALCULUS_FNS.has(u.operator)) return false; |
| 3677 | |
| 3678 | if (u.operator === 'Power' && u.ops && !u.ops[0].has(x)) { |
| 3679 | const exp = u.ops[1]; |
| 3680 | if (linX(exp, x)) { |
| 3681 | st.flag = true; |
| 3682 | return foeTestAux(u.ops[0], exp, x, st); |
| 3683 | } |
| 3684 | // F^(a+b+…) → F^a · F^b · … : test each summand |
| 3685 | if (exp.operator === 'Add' && exp.ops) { |
| 3686 | st.flag = true; |
| 3687 | return exp.ops.every((t) => |
| 3688 | foeTest(ce.function('Power', [u.ops![0], t]), x, st) |
| 3689 | ); |
| 3690 | } |
| 3691 | } |
| 3692 | if (HYPERBOLIC_HEADS.has(u.operator) && u.ops && linX(u.ops[0], x)) |
| 3693 | return foeTestAux(ce.E, u.ops[0], x, st); |
| 3694 | |
| 3695 | for (const op of u.ops ?? []) if (!foeTest(op, x, st)) return false; |
| 3696 | return true; |
| 3697 | } |
| 3698 | |
| 3699 | /** FunctionOfExponentialFunctionAux: u with F^v → x (the new integration |
| 3700 | * variable), using the registered $base$/$expon$. */ |
| 3701 | function foeFunctionAux(u: Expression, x: string, st: FoeState): Expression { |
| 3702 | const ce = u.engine; |
| 3703 | if (!u.ops || u.ops.length === 0) return u; // atom |
| 3704 | |
| 3705 | if (u.operator === 'Power' && !u.ops[0].has(x)) { |
| 3706 | const G = u.ops[0]; |
| 3707 | const w = u.ops[1]; |
| 3708 | if (linX(w, x)) { |
| 3709 | const p = safeSimplify( |
| 3710 | G.ln() |
no test coverage detected