<commit_before><?php

namespace Math\NumericalAnalysis\NumericalDifferentiation;

/**
 * Three Point Formula
 *
 * In numerical analysis, the three point formula is used for approximating
 * the derivative of a function at a point in its domain.
 *
 * 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 3 points between a start and end point.
 */
class ThreePointFormula extends NumericalDifferentiation
{
    /**
     * Use the Three Point Formula to aproximate the derivative of a function at
     * our $target. Our input can support either a set of arrays, or a callback
     * function with arguments (to produce a set of arrays). Each array in our
     * input contains two numbers which correspond to coordinates (x, y) or
     * equivalently, (x, f(x)), of the function f(x) whose derivative we are
     * approximating.
     *
     * Example: approximate(function($x) {return $x**2;}, 0, 4 ,3) will produce
     * a set of arrays by evaluating the callback at 3 evenly spaced points
     * between 0 and 4. Then, this array will be used in our approximation.
     *
     * Three Point Formula:

     *   - If the 2nd point is our $target, use the Midpoint Formula:
     *
     *              1                     h²
     *     f'(x₀) = - [f(x₀+h)-f(x₀-h)] - - f⁽³⁾(ζ₁)
     *              2h                    6
     *
     *         where ζ₁ lies between x₀ - h and x₀ + h
     *
     *   - If the 1st or 3rd point is our $target, use the Endpoint Formula:
     *   - Note that when the 3rd point is our $target, we use a negative h.
     *
     *              1                               h²
     *     f'(x₀) = - [-3f(x₀)+4f(x₀+h)-f(x₀+2h)] + - f⁽³⁾(ζ₀)
     *              2h                              3
     *
     *         where ζ₀ lies between x₀ and x₀ + 2h
     *
     * @param numbers  $target   The value at which we are approximating the derivative
     * @param          $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 numbers  ... $args The arguments of our callback function: start,
     *                           end, and n. Example: approximate($source, 0, 8, 3).
     *                           If $source is a set of points, do not input any
     *                           $args. Example: approximate($source).
     *
     * @return number            The approximation to the integral of f(x)
     */
    public static function differentiate($target, $source, ... $args)
    {
        // get an array of points from our $source argument
        $points = self::getPoints($source, $args);

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

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

        // Initialize
        $n = count($sorted);
        $h = ($sorted[2][$x] - $sorted[0][$x])/2;

        /*
         * If the 2nd point is our $target, use the Midpoint Formula:
         *
         *          1                     h²
         * f'(x₀) = - [f(x₀+h)-f(x₀-h)] - - f⁽³⁾(ζ₁)
         *          2h                    6
         *
         *     where ζ₁ lies between x₀ - h and x₀ + h
         *
         * If the 1st or 3rd point is our $target, use the Endpoint Formula:<commit_msg>Added isSpacingConstant method to ThreePointFormula<commit_after><?php

namespace Math\NumericalAnalysis\NumericalDifferentiation;

/**
 * Three Point Formula
 *
 * In numerical analysis, the three point formula is used for approximating
 * the derivative of a function at a point in its domain.
 *
 * 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 3 points between a start and end point.
 */
class ThreePointFormula extends NumericalDifferentiation
{
    /**
     * Use the Three Point Formula to aproximate the derivative of a function at
     * our $target. Our input can support either a set of arrays, or a callback
     * function with arguments (to produce a set of arrays). Each array in our
     * input contains two numbers which correspond to coordinates (x, y) or
     * equivalently, (x, f(x)), of the function f(x) whose derivative we are
     * approximating.
     *
     * Example: approximate(function($x) {return $x**2;}, 0, 4 ,3) will produce
     * a set of arrays by evaluating the callback at 3 evenly spaced points
     * between 0 and 4. Then, this array will be used in our approximation.
     *
     * Three Point Formula:

     *   - If the 2nd point is our $target, use the Midpoint Formula:
     *
     *              1                     h²
     *     f'(x₀) = - [f(x₀+h)-f(x₀-h)] - - f⁽³⁾(ζ₁)
     *              2h                    6
     *
     *         where ζ₁ lies between x₀ - h and x₀ + h
     *
     *   - If the 1st or 3rd point is our $target, use the Endpoint Formula:
     *   - Note that when the 3rd point is our $target, we use a negative h.
     *
     *              1                               h²
     *     f'(x₀) = - [-3f(x₀)+4f(x₀+h)-f(x₀+2h)] + - f⁽³⁾(ζ₀)
     *              2h                              3
     *
     *         where ζ₀ lies between x₀ and x₀ + 2h
     *
     * @param numbers  $target   The value at which we are approximating the derivative
     * @param          $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 numbers  ... $args The arguments of our callback function: start,
     *                           end, and n. Example: approximate($source, 0, 8, 3).
     *                           If $source is a set of points, do not input any
     *                           $args. Example: approximate($source).
     *
     * @return number            The approximation of f'($target), i.e. the derivative
     *                           of our input at our target point
     */
    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, and make sure spacing is constant
        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;

        /*
         * If the 2nd point is our $target, use the Midpoint Formula:
         *
         *          1                     h²
         * f'(x₀) = - [f(x₀+h)-f(x₀-h)] - - f⁽³⁾(ζ₁)
         *          2h                    6
         *
         *     where ζ₁ lies between x₀ - h and x₀ + h
         *
         * If the 1st or 3rd point is our $target, use the Endpoint Formula:
{'fraction_non_alphanumeric': 0.09360495100567302, 'fraction_numerical': 0.010830324909747292, 'mean_word_length': 1.625930941096818, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 31, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5528140', 'n_tokens_mistral': 2295, 'n_tokens_neox': 2177, 'n_words': 866}