PureFunctionOf{Sin,Cos,Tan}Q: every trig subterm of argument `v` has a head * in `allowed`, and no bare `x` appears (IntegrationUtilityFunctions.m).
( u: Expression, v: Expression, x: string, allowed: Set<string> )
| 3450 | // carries x (the common trig case `cos/cos`, `sec²/sec²` reduces in canonical |
| 3451 | // form, so Simplify is skipped entirely). |
| 3452 | // --------------------------------------------------------------------------- |
| 3453 | |
| 3454 | /** Rubi EasyDQ — conservative: true iff y is cheap to differentiate wrt x. |
| 3455 | * Fail-closed (unknown shapes → false), which only makes DerivativeDivides |
| 3456 | * decline a binding; it never produces a wrong quotient. */ |
| 3457 | function easyDQ(u: Expression, x: string): boolean { |
| 3458 | if (!u.ops || u.ops.length === 0 || !u.has(x)) return true; // atom / x-free |
| 3459 | const op = u.operator; |
| 3460 | if (CALCULUS_FNS.has(op)) return false; |
| 3461 | if (op === 'Power') return !u.ops[1].has(x) && easyDQ(u.ops[0], x); |
| 3462 | if (op === 'Divide') return u.ops.every((o) => easyDQ(o, x)); |
| 3463 | if (u.ops.length === 1) return easyDQ(u.ops[0], x); // Sin[v], Cos[v], Negate… |
| 3464 | if (op === 'Multiply') { |
| 3465 | const nonfree = u.ops.filter((o) => o.has(x)); |
no test coverage detected