public static function differentiate($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::isSpacingConstant($sorted);
// Descriptive constants
$x = self::X;
$y = self::Y;
// Initialize
$n = count($sorted);
$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
*/
if ($sorted[1][$x] == $target) {
$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;
} else {
throw new Exception\BadDataException('Your target must be the midpoint of your input');
}
return $derivative;
}