$source * The source of our approximation. Should be either * a callback function or a set of arrays. Each array * (point) contains precisely two numbers, an x and y. * Example array: [[1,2], [2,3], [3,4]]. * Example callback: function($x) {return $x**2;} * @param int|float ...$args * The arguments of our callback function: start, * end, and n. Example: differentiate($target, $source, 0, 8, 3). * If $source is a set of points, do not input any * $args. Example: approximate($source). * * @return float * The approximation of f'($target), i.e. the derivative * of our input at our target point * * @throws Exception\BadDataException */ public static function differentiate(float $target, $source, ...$args) { // Get an array of points from our $source argument $points = self::getPoints($source, $args); // Validate input, sort points, make sure spacing is constant, and make // sure our target is contained in an interval supplied by our $source self::validate($points, $degree = 3); $sorted = self::sort($points); self::assertSpacingConstant($sorted); // Descriptive constants $x = self::X; $y = self::Y; // Guard clause - target must equal the x-component of the midpoint if ($sorted[1][$x] != $target) { throw new Exception\BadDataException('Your target must be the midpoint of your input'); } // Initialize $h = ($sorted[2][$x] - $sorted[0][$x]) / 2; /* * 1 h² * f″(x₀) = - [f(x₀-h) - 2f(x₀) + f(x₀+h)] - - f⁽⁴⁾(ζ) * h² 12 * * where ζ lies between x₀ - h and x₀ + h */ $f⟮x₀⧿h⟯ = $sorted[0][$y]; $f⟮x₀⟯ = $sorted[1][$y]; $f⟮x₀⧾h⟯ = $sorted[2][$y]; $derivative = ($f⟮x₀⧿h⟯ - 2 * $f⟮x₀⟯ + $f⟮x₀⧾h⟯) / ($h ** 2); return $derivative; } }