1 | import sign from "./sign";
|
2 |
|
3 | /**
|
4 | * [Bisection method](https://en.wikipedia.org/wiki/Bisection_method) is a root-finding
|
5 | * method that repeatedly bisects an interval to find the root.
|
6 | *
|
7 | * This function returns a numerical approximation to the exact value.
|
8 | *
|
9 | * @param {Function} func input function
|
10 | * @param {number} start - start of interval
|
11 | * @param {number} end - end of interval
|
12 | * @param {number} maxIterations - the maximum number of iterations
|
13 | * @param {number} errorTolerance - the error tolerance
|
14 | * @returns {number} estimated root value
|
15 | * @throws {TypeError} Argument func must be a function
|
16 | *
|
17 | * @example
|
18 | * bisect(Math.cos,0,4,100,0.003); // => 1.572265625
|
19 | */
|
20 | function bisect(func, start, end, maxIterations, errorTolerance) {
|
21 | if (typeof func !== "function")
|
22 | throw new TypeError("func must be a function");
|
23 |
|
24 | for (let i = 0; i < maxIterations; i++) {
|
25 | const output = (start + end) / 2;
|
26 |
|
27 | if (
|
28 | func(output) === 0 ||
|
29 | Math.abs((end - start) / 2) < errorTolerance
|
30 | ) {
|
31 | return output;
|
32 | }
|
33 |
|
34 | if (sign(func(output)) === sign(func(start))) {
|
35 | start = output;
|
36 | } else {
|
37 | end = output;
|
38 | }
|
39 | }
|
40 |
|
41 | throw new Error("maximum number of iterations exceeded");
|
42 | }
|
43 |
|
44 | export default bisect;
|