<commit_before><?php
namespace Math\NumericalAnalysis\Interpolation;

use Math\Functions\Polynomial;
use Math\Functions\Piecewise;

/**
 * Clamped Cubic Spline Interpolating Polyonomial
 *
 * In numerical analysis, cubic splines are used for polynomial
 * interpolation.
 *
 * A cubic spline is a spline constructed of piecewise third-order polynomials
 * which pass through a set of m control points." In the case of the Clamped
 * cubic spline, the first derivative of piecewise polynomial is set to equal the
 * first derivative of our input at the endpoints.
 *
 * Cubic spline interpolation belongs to a collection of techniques that
 * interpolate a function or a set of values, producing a continuous polynomial.
 * In the case of the cubic spline, a piecewise function (polynomial) is produced.
 * We can either directly supply a set of inputs and their corresponding outputs
 * for said function, or if we explicitly know the function, we can define it as
 * a callback function and then generate a set of points by evaluating that
 * function at n points between a start and end point. We then use these values
 * to interpolate our piecewise polynomial.
 *
 * https://en.wikipedia.org/wiki/Spline_interpolation
 * http://mathworld.wolfram.com/CubicSpline.html
 */
class ClampedCubicSpline extends Interpolation
{
    /**
     * @var int Index of z (y-prime)
     */
    const Z = 2;

    /**
     * Interpolate
     *
     * @param          $source   The source of our approximation. Should be either
     *                           a callback function or a set of arrays. Each array
     *                           (point) contains precisely three numbers: x, y, and y'
     *                           Example array: [[1,2,1], [2,3,0], [3,4,2]].
     *                           Example callback: function($x) {return $x**2;}
     * @param numbers  ... $args (Optional) An additonal callback: our first derivative,
     *                           and arguments of our callback functions: start,
     *                           end, and n.
     *                           Example: approximate($source, $derivative, 0, 8, 5).
     *                           If $source is a set of points, do not input any
     *                           $args. Example: approximate($source).
     *
     * @return Piecewise         The interpolting (piecewise) polynomial, as an
     *                           instance of Piecewise.
     */
    public static function interpolate($source, ... $args)
    {
        // Get an array of points from our $source argument
        $points = self::getSplinePoints($source, $args);

        // Validate input and sort points
        self::validateSpline($points, $degree = 1);
        $sorted = self::sort($points);

        // Descriptive constants
        $x = self::X;
        $y = self::Y;

        // Initialize
        $n     = count($sorted);
        $k     = $n - 1;
        $h     = [];
        $a     = [];
        $μ     = [0];
        $z     = [0];
        $z[$k] = 0;
        $c     = [];
        $c[$k] = 0;
        $poly  = [];

        for ($i = 0; $i < $k; $i++) {
            $xᵢ     = $sorted[$i][$x];
            $xᵢ₊₁   = $sorted[$i+1][$x];
            $a[$i]  = $sorted[$i][$y];
            $h[$i]  = $xᵢ₊₁ - $xᵢ;

            if ($i == 0) {
                continue;
            }

            $xᵢ₋₁   = $sorted[$i-1][$x];
            $f⟮xᵢ⟯   = $sorted[$i][$y];    // yᵢ
            $f⟮xᵢ₊₁⟯ = $sorted[$i+1][$y];  // yᵢ₊₁
            $f⟮xᵢ₋₁⟯ = $sorted[$i-1][$y];  // yᵢ₋₁

            $α      = (3/$h[$i])*($f⟮xᵢ₊₁⟯ - $f⟮xᵢ⟯) - (3/$h[$i-1])*($f⟮xᵢ⟯ - $f⟮xᵢ₋₁⟯);
            $l      = 2*($xᵢ₊₁ - $xᵢ₋₁) - $h[$i-1]*$μ[$i-1];
            $μ[$i]  = $h[$i]/$l;
            $z[$i]  = ($α - $h[$i-1]*$z[$i-1])/$l;
        }

        for ($i = $k-1; $i >= 0; $i--) {
            $xᵢ       = $sorted[$i][$x];
            $xᵢ₊₁     = $sorted[$i+1][$x];
            $f⟮xᵢ⟯     = $sorted[$i][$y];    // yᵢ
            $f⟮xᵢ₊₁⟯   = $sorted[$i+1][$y];  // yᵢ₊₁

            $c[$i]    = $z[$i] - $μ[$i]*$c[$i+1];
            $b[$i]    = ($f⟮xᵢ₊₁⟯ - $f⟮xᵢ⟯)/$h[$i] - $h[$i]*($c[$i+1] + 2*$c[$i])/3;<commit_msg>Renamed constant to y’ (y-prime)<commit_after><?php
namespace Math\NumericalAnalysis\Interpolation;

use Math\Functions\Polynomial;
use Math\Functions\Piecewise;

/**
 * Clamped Cubic Spline Interpolating Polyonomial
 *
 * In numerical analysis, cubic splines are used for polynomial
 * interpolation.
 *
 * A cubic spline is a spline constructed of piecewise third-order polynomials
 * which pass through a set of m control points." In the case of the Clamped
 * cubic spline, the first derivative of piecewise polynomial is set to equal the
 * first derivative of our input at the endpoints.
 *
 * Cubic spline interpolation belongs to a collection of techniques that
 * interpolate a function or a set of values, producing a continuous polynomial.
 * In the case of the cubic spline, a piecewise function (polynomial) is produced.
 * We can either directly supply a set of inputs and their corresponding outputs
 * for said function, or if we explicitly know the function, we can define it as
 * a callback function and then generate a set of points by evaluating that
 * function at n points between a start and end point. We then use these values
 * to interpolate our piecewise polynomial.
 *
 * https://en.wikipedia.org/wiki/Spline_interpolation
 * http://mathworld.wolfram.com/CubicSpline.html
 */
class ClampedCubicSpline extends Interpolation
{
    /**
     * @var int Index of y’ (y-prime)
     */
    const Y’ = 2;

    /**
     * Interpolate
     *
     * @param          $source   The source of our approximation. Should be either
     *                           a callback function or a set of arrays. Each array
     *                           (point) contains precisely three numbers: x, y, and y'
     *                           Example array: [[1,2,1], [2,3,0], [3,4,2]].
     *                           Example callback: function($x) {return $x**2;}
     * @param numbers  ... $args (Optional) An additonal callback: our first derivative,
     *                           and arguments of our callback functions: start,
     *                           end, and n.
     *                           Example: approximate($source, $derivative, 0, 8, 5).
     *                           If $source is a set of points, do not input any
     *                           $args. Example: approximate($source).
     *
     * @return Piecewise         The interpolting (piecewise) polynomial, as an
     *                           instance of Piecewise.
     */
    public static function interpolate($source, ... $args)
    {
        // Get an array of points from our $source argument
        $points = self::getSplinePoints($source, $args);

        // Validate input and sort points
        self::validateSpline($points, $degree = 1);
        $sorted = self::sort($points);

        // Descriptive constants
        $x  = self::X;
        $y  = self::Y;
        $y’ = self::Y’;

        // Initialize
        $n     = count($sorted);
        $k     = $n - 1;
        $x₀    = $sorted[0][$x];
        $x₁    = $sorted[1][$x];
        $f⟮x₀⟯  = $sorted[0][$y];  // y₀
        $f⟮x₁⟯  = $sorted[1][$y];  // y₁
        $y’₀   = $sorted[0][$z];  // y₀-prime
        $h     = [$x₁-$x₀];
        $a     = [(3/$h[0])*($f⟮x₁⟯-$f⟮x₀⟯) - 3*$y’₀];
        $μ     = [0.5];
        $z     = [$a[0]/(2*$h[0])];
        $c     = [];
        $c[$k] = 0;
        $poly  = [];

        for ($i = 0; $i < $k; $i++) {
            $xᵢ     = $sorted[$i][$x];
            $xᵢ₊₁   = $sorted[$i+1][$x];
            $a[$i]  = $sorted[$i][$y];
            $h[$i]  = $xᵢ₊₁ - $xᵢ;

            if ($i == 0) {
                continue;
            }

            $xᵢ₋₁   = $sorted[$i-1][$x];
            $f⟮xᵢ⟯   = $sorted[$i][$y];    // yᵢ
            $f⟮xᵢ₊₁⟯ = $sorted[$i+1][$y];  // yᵢ₊₁
            $f⟮xᵢ₋₁⟯ = $sorted[$i-1][$y];  // yᵢ₋₁

            $α      = (3/$h[$i])*($f⟮xᵢ₊₁⟯ - $f⟮xᵢ⟯) - (3/$h[$i-1])*($f⟮xᵢ⟯ - $f⟮xᵢ₋₁⟯);
            $l      = 2*($xᵢ₊₁ - $xᵢ₋₁) - $h[$i-1]*$μ[$i-1];
            $μ[$i]  = $h[$i]/$l;
            $z[$i]  = ($α - $h[$i-1]*$z[$i-1])/$l;
        }

        $f⟮xₙ⟯   = $sorted[$k][$y];   // yₙ
        $f⟮xₙ₋₁⟯ = $sorted[$k-1][$y]; // yₙ₋₁
        $y’ₙ    = $sorted[$k][$z];   // yₙ-prime
        $l      = $h[$k-1]*(2 - $μ[$k - 1]);
        $a[$k]  = 3*$y’ₙ - 3*($f⟮xₙ⟯ - $f⟮xₙ₋₁⟯)/$h[$k-1];
        $z[$k]  = 1;

        for ($i = $k-1; $i >= 0; $i--) {
            $xᵢ       = $sorted[$i][$x];
            $xᵢ₊₁     = $sorted[$i+1][$x];
            $f⟮xᵢ⟯     = $sorted[$i][$y];    // yᵢ
            $f⟮xᵢ₊₁⟯   = $sorted[$i+1][$y];  // yᵢ₊₁

            $c[$i]    = $z[$i] - $μ[$i]*$c[$i+1];
            $b[$i]    = ($f⟮xᵢ₊₁⟯ - $f⟮xᵢ⟯)/$h[$i] - $h[$i]*($c[$i+1] + 2*$c[$i])/3;
{'fraction_non_alphanumeric': 0.16694848382369518, 'fraction_numerical': 0.011498140006763611, 'mean_word_length': 1.6925644916540212, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1369566', 'n_tokens_mistral': 3427, 'n_tokens_neox': 3325, 'n_words': 818}