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 pointsdydx(list[list], required): First derivatives (dy/dx) at each data pointx_new(list[list], required): X-coordinates at which to evaluate the interpolated valuesextrapolate(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}"