Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bisection
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 1
 root
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\Math\Solver\Root
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\Math\Solver\Root;
16
17/**
18 * Find the root of a function.
19 *
20 * @package phpOMS\Math\Solver\Root
21 * @license OMS License 2.0
22 * @link    https://jingga.app
23 * @since   1.0.0
24 */
25final class Bisection
26{
27    /**
28     * Epsilon for float comparison.
29     *
30     * @var float
31     * @since 1.0.0
32     */
33    public const EPSILON = 1e-6;
34
35    /**
36     * Perform bisection to find the root of a function
37     *
38     * Iteratively searches for root between two points on the x-axis
39     *
40     * @param Callable $func          Function defintion
41     * @param float    $a             Start value
42     * @param float    $b             End value
43     * @param int      $maxIterations Maximum amount of iterations
44     *
45     * @throws \Exception
46     *
47     * @return float
48     *
49     * @since 1.0.0
50     */
51    public static function root(callable $func, float $a, float $b, int $maxIterations = 100) : float
52    {
53        if ($func($a) * $func($b) >= 0) {
54            throw new \Exception("Function values at endpoints must have opposite signs.");
55        }
56
57        $iteration = 0;
58        while (($b - $a) / 2 > self::EPSILON && $iteration < $maxIterations) {
59            $c = ($a + $b) / 2;
60
61            $y = $func($c);
62
63            if ($y === 0.0) {
64                return $c;
65            }
66
67            if ($y * $func($a) < 0) {
68                $b = $c;
69            } else {
70                $a = $c;
71            }
72
73            ++$iteration;
74        }
75
76        return ($a + $b) / 2;
77    }
78}