(ce: ComputeEngine, x: BigNum)
| 3041 | * with the term recurrence tₙ = tₙ₋₁ · x²·(2n−1) / (n·(2n+1)). |
| 3042 | * Odd function. Grows like e^{x²}, so it overflows to ±∞ for large |x|. |
| 3043 | */ |
| 3044 | export function erfi(x: number): number { |
| 3045 | if (Number.isNaN(x)) return NaN; |
| 3046 | if (x === 0) return 0; |
| 3047 | if (!Number.isFinite(x)) return x > 0 ? Infinity : -Infinity; |
| 3048 | |
| 3049 | const sign = x < 0 ? -1 : 1; |
| 3050 | const ax = Math.abs(x); |
| 3051 | const x2 = ax * ax; |
| 3052 | let term = ax; // n = 0 term: x |
| 3053 | let sum = ax; |
| 3054 | for (let n = 1; n < 1000; n++) { |
| 3055 | term *= (x2 * (2 * n - 1)) / (n * (2 * n + 1)); |
| 3056 | sum += term; |
| 3057 | if (term < sum * 1e-18) break; |
| 3058 | } |
| 3059 | return sign * (2 / Math.sqrt(Math.PI)) * sum; |
| 3060 | } |
| 3061 | |
| 3062 | /** |
| 3063 | * Bignum imaginary error function. The Maclaurin series above has only |
| 3064 | * positive terms (no cancellation), so the relative error tracks the working |
| 3065 | * precision. Precision scales with `BigDecimal.precision`. |
| 3066 | */ |
| 3067 | function bigErfiSeries(x: BigNum, tolDigits: number): BigNum { |
| 3068 | const x2 = x.mul(x); |
| 3069 | let term = x; // n = 0 |
| 3070 | let sum = x; |
| 3071 | const tol = new BigDecimal(10).pow(-tolDigits); |
| 3072 | const maxTerms = 1000 + 10 * Math.ceil(x2.toNumber()) + 10 * tolDigits; |
| 3073 | for (let n = 1; n <= maxTerms; n++) { |
| 3074 | // tₙ = tₙ₋₁ · x²·(2n−1) / (n·(2n+1)) |
no test coverage detected