| 216 | // Pass 1 — float probes: solve `A(x) = A(x0)` (float RHS, no |
| 217 | // clearDenominators scaling) for a concrete probe `x0`. Exercises the |
| 218 | // `__a = 1` degenerate (unscaled) shape. |
| 219 | let floatOk = false; |
| 220 | for (const x0 of SOLVE_SELFTEST_PROBES) { |
| 221 | const c = ce.expr(substituteSymbol(innerA, '_x', x0) as never).N(); |
| 222 | const cre = (c as unknown as { re?: number }).re; |
| 223 | const cim = (c as unknown as { im?: number }).im ?? 0; |
| 224 | if (typeof cre !== 'number' || !Number.isFinite(cre) || Math.abs(cim) > 1e-12) |
| 225 | continue; // probe lands outside the real domain of A |
| 226 | const eq = ce.expr([ |
| 227 | 'Subtract', |
| 228 | substituteSymbol(innerA, '_x', 'x'), |
| 229 | c.json, |
| 230 | ] as never); |
| 231 | let roots: unknown; |
| 232 | try { |
| 233 | roots = (eq as unknown as { solve(v: string): unknown }).solve('x'); |
| 234 | } catch { |
| 235 | continue; |
| 236 | } |
| 237 | if (!Array.isArray(roots) || roots.length === 0) continue; |
| 238 | for (const r of roots) { |
| 239 | const rv = (r as { N(): { re?: number } }).N().re; |
| 240 | if ( |
| 241 | typeof rv === 'number' && |
| 242 | Number.isFinite(rv) && |
| 243 | Math.abs(rv - x0) < 1e-6 * (1 + Math.abs(x0)) |
| 244 | ) { |
| 245 | floatOk = true; |
| 246 | break; |
| 247 | } |
| 248 | } |
| 249 | if (floatOk) break; |
| 250 | } |
| 251 | if (!floatOk) |
| 252 | return { ok: false, detail: 'no float probe yielded a validating root ≈ x0' }; |
| 253 | |
| 254 | // Pass 2 — rational RHS: solve `A(x) − 1/2 = 0` with an EXACT rational RHS. |
| 255 | // `findUnivariateRoots` runs `clearDenominators`, which now SKIPS exact |
| 256 | // numeric-literal denominators, so the equation is NOT rescaled and reaches |
| 257 | // the templates as `Add(A(_x), −1/2)`; the `__b` wildcard + `useVariations` |
| 258 | // (covering `__a = 1` for the scale-generalized templates) absorbs the |
| 259 | // rational offset. This pass runs for BOTH scale-generalized and product-inner |
| 260 | // templates — the product-inner shape (`x·eˣ = −1/10`) is now reachable |
| 261 | // because rational RHSs are no longer flattened away. Skip — do not fail — |
| 262 | // when `A(x) = 1/2` has no real solution (`f(1/2)` non-real/non-finite): the |
| 263 | // probe simply cannot exercise the path for that inner function. |
| 264 | const half: MathJSON = ['Rational', 1, 2]; |
| 265 | // `f(1/2)` analog: the root the template should produce, via the replace |
| 266 | // template with `__b = −1/2`, `__a = 1` (so `−__b/__a = 1/2`). |
| 267 | const rootAnalog = ce |
| 268 | .expr( |
| 269 | substituteSymbol( |
| 270 | substituteSymbol(replace, '__b', ['Rational', -1, 2]), |
| 271 | '__a', |
| 272 | 1 |
| 273 | ) as never |
| 274 | ) |
| 275 | .N(); |