|
| 1 | +/** |
| 2 | + * @function agm |
| 3 | + * @description This finds the Arithmetic-Geometric Mean between any 2 numbers. |
| 4 | + * @param {Number} a - 1st number, also used to store Arithmetic Mean. |
| 5 | + * @param {Number} g - 2nd number, also used to store Geometric Mean. |
| 6 | + * @return {Number} - AGM of both numbers. |
| 7 | + * @see [AGM](https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean) |
| 8 | + */ |
| 9 | + |
| 10 | + export const agm = (a, g) => { |
| 11 | + if (a === g) return a; //avoid rounding errors, and increase efficiency |
| 12 | + let x; //temp var, for detecting rounding differences between `sqrt` and division |
| 13 | + do { |
| 14 | + [a, g, x] = [(a + g) / 2, Math.sqrt(a * g), a] |
| 15 | + } while (a !== x && !isNaN(a)); |
| 16 | + /* |
| 17 | + `x !== a` ensures the return value has full precision, |
| 18 | + and prevents infinite loops caused by rounding errors (no need for "epsilon"). |
| 19 | + Precision is not the same as accuracy, but they're related. |
| 20 | + This function isn't always 100% accurate (round-errors), but at least is more than 95% accurate. |
| 21 | + `!isNaN(x)` prevents infinite loops caused by invalid inputs like: negatives, NaNs and both Infinities. |
| 22 | + */ |
| 23 | + return a |
| 24 | +} |
0 commit comments