HERMITE_SPLINE

Overview

The HERMITE_SPLINE function performs piecewise cubic interpolation using the Cubic Hermite Spline method, which matches both function values and first derivatives at each data point. Unlike standard cubic spline interpolation that only fits values, Hermite splines require explicit derivative (tangent) information at each point, providing precise control over the curve’s shape and ensuring C1 continuity (continuous first derivative) across the entire interpolation domain.

This implementation uses SciPy’s CubicHermiteSpline class from the scipy.interpolate module. The result is represented internally as a piecewise polynomial (PPoly).

For a single interval [x_k, x_{k+1}], the Cubic Hermite spline is defined using four Hermite basis functions:

p(t) = h_{00}(t) \cdot p_k + h_{10}(t) \cdot (x_{k+1} - x_k) \cdot m_k + h_{01}(t) \cdot p_{k+1} + h_{11}(t) \cdot (x_{k+1} - x_k) \cdot m_{k+1}

where t = (x - x_k) / (x_{k+1} - x_k) is the normalized parameter, p_k and p_{k+1} are the endpoint values, m_k and m_{k+1} are the derivatives at those points, and h_{00}, h_{10}, h_{01}, h_{11} are the Hermite basis functions:

h_{00}(t) = 2t^3 - 3t^2 + 1, \quad h_{10}(t) = t^3 - 2t^2 + t
h_{01}(t) = -2t^3 + 3t^2, \quad h_{11}(t) = t^3 - t^2

Cubic Hermite splines are extensively used in computer graphics, animation systems, and geometric modeling for generating smooth curves and motion trajectories that pass through specified control points. They are particularly valuable when derivative information is known or can be estimated, as in physics simulations where both position and velocity data are available. The method is named after French mathematician Charles Hermite.

The function supports three extrapolation modes: False (returns NaN for out-of-bounds points), True (extrapolates using the first and last polynomial segments), and periodic (applies periodic boundary conditions).

This example function is provided as-is without any representation of accuracy.

Excel Usage

=HERMITE_SPLINE(x, y, dydx, x_new, extrapolate)
  • x (list[list], required): X-coordinates of the data points (must be strictly increasing)
  • y (list[list], required): Y-coordinates of the data points
  • dydx (list[list], required): First derivatives (dy/dx) at each data point
  • x_new (list[list], required): X-coordinates at which to evaluate the interpolated values
  • extrapolate (str, optional, default: “False”): Extrapolation mode (‘True’, ‘False’, or ‘periodic’)

Returns (list[list]): A 2D list of interpolated values, or error message (str) if invalid.

Examples

Example 1: Demo case 1

Inputs:

x y dydx x_new
0 0 1 0.5
1 1 2 1.5
2 4 3

Excel formula:

=HERMITE_SPLINE({0;1;2}, {0;1;4}, {1;2;3}, {0.5;1.5})

Expected output:

Result
0.375
2.375

Example 2: Demo case 2

Inputs:

x y dydx x_new
0 1 0.5 1.5
1 2 0
2 1.5 1
3 3 2

Excel formula:

=HERMITE_SPLINE({0;1;2;3}, {1;2;1.5;3}, {0.5;0;1;2}, 1.5)

Expected output:

Result
1.625

Example 3: Demo case 3

Inputs:

x y dydx x_new extrapolate
0 0 1 2.5 True
1 1 0
2 0 -1

Excel formula:

=HERMITE_SPLINE({0;1;2}, {0;1;0}, {1;0;-1}, {2.5}, "True")

Expected output:

Result
-0.125

Example 4: Demo case 4

Inputs:

x y dydx x_new extrapolate
0 0 2 3 periodic
1 1 0
2 0 -2

Excel formula:

=HERMITE_SPLINE({0;1;2}, {0;1;0}, {2;0;-2}, {3}, "periodic")

Expected output:

Result
1

Python Code

from scipy.interpolate import CubicHermiteSpline as scipy_CubicHermiteSpline
import math

def hermite_spline(x, y, dydx, x_new, extrapolate='False'):
    """
    Piecewise-cubic interpolator matching values and first derivatives.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicHermiteSpline.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        x (list[list]): X-coordinates of the data points (must be strictly increasing)
        y (list[list]): Y-coordinates of the data points
        dydx (list[list]): First derivatives (dy/dx) at each data point
        x_new (list[list]): X-coordinates at which to evaluate the interpolated values
        extrapolate (str, optional): Extrapolation mode ('True', 'False', or 'periodic') Valid options: True, False, Periodic. Default is 'False'.

    Returns:
        list[list]: A 2D list of interpolated values, or error message (str) if invalid.
    """
    def to2d(val):
        """Convert scalar or 2D list to 2D list format."""
        return [[val]] if not isinstance(val, list) else val

    def flatten(arr):
        """Flatten a 2D list to 1D."""
        return [item for sublist in arr for item in sublist]

    def validate_numeric_array(arr, name):
        """Validate that array contains only numeric values."""
        for row in arr:
            if not isinstance(row, list):
                return f"Invalid input: {name} must be a 2D list."
            for val in row:
                if not isinstance(val, (int, float)):
                    return f"Invalid input: {name} must contain only numeric values."
                if math.isnan(val) or math.isinf(val):
                    return f"Invalid input: {name} must contain only finite values."
        return None

    try:
        # Normalize inputs to 2D lists
        x = to2d(x)
        y = to2d(y)
        dydx = to2d(dydx)
        x_new = to2d(x_new)

        # Convert extrapolate string to appropriate type for scipy
        if isinstance(extrapolate, str):
            if extrapolate.lower() == "true":
                extrapolate = True
            elif extrapolate.lower() == "false":
                extrapolate = False
            elif extrapolate.lower() == "periodic":
                extrapolate = "periodic"
            else:
                return f"Invalid input: extrapolate must be 'True', 'False', or 'periodic', got '{extrapolate}'."
        elif extrapolate is None:
            extrapolate = False

        # Validate inputs
        error = validate_numeric_array(x, "x")
        if error:
            return error
        error = validate_numeric_array(y, "y")
        if error:
            return error
        error = validate_numeric_array(dydx, "dydx")
        if error:
            return error
        error = validate_numeric_array(x_new, "x_new")
        if error:
            return error

        # Flatten arrays
        x_flat = flatten(x)
        y_flat = flatten(y)
        dydx_flat = flatten(dydx)
        x_new_flat = flatten(x_new)

        # Check array lengths match
        if len(x_flat) != len(y_flat) or len(x_flat) != len(dydx_flat):
            return "Invalid input: x, y, and dydx must have the same length."

        if len(x_flat) < 2:
            return "Invalid input: at least 2 data points are required."

        # Create interpolator and evaluate
        interp = scipy_CubicHermiteSpline(x_flat, y_flat, dydx_flat, extrapolate=extrapolate)
        result = interp(x_new_flat)

        # Convert result to 2D list
        return [[val] for val in result]

    except ValueError as e:
        return f"Invalid input: {e}"
    except Exception as e:
        return f"scipy.interpolate.CubicHermiteSpline error: {e}"

Online Calculator