Source code for solprop.backends.numba_cpu.tables

# SPDX-FileCopyrightText: 2026 John C. Travers and contributors
#
# SPDX-License-Identifier: GPL-3.0-or-later

"""Evaluate the reference z-table representation into persistent host stage arrays."""

import numpy as np
from jaxtyping import Complex

from solprop.translate.chebyshev import PiecewiseChebyshev

__all__ = ["HostTable"]


[docs] class HostTable: """Hold a Chebyshev table's Clenshaw work and stage output on the host. The operation order follows NumPy's ``chebval``. Only this adapter handles the general z table; the existing constant and expansion stage routes are unchanged. Parameters ---------- table : PiecewiseChebyshev Array-valued complex table sampled in translation. Attributes ---------- table : PiecewiseChebyshev The immutable translated coefficients. work : numpy.ndarray Three Clenshaw arrays, shape ``(3, *value_shape)``, complex128. value : numpy.ndarray Evaluation result, shape value_shape, complex128. left : numpy.ndarray Saved left endpoint for a difference, shape value_shape, complex128. """ table: PiecewiseChebyshev work: np.ndarray value: np.ndarray left: np.ndarray def __init__(self, table: PiecewiseChebyshev) -> None: self.table = table self.work = np.empty((3, *table.value_shape), dtype=complex) self.value = np.empty(table.value_shape, dtype=complex) self.left = np.empty_like(self.value)
[docs] def at(self, z: float) -> Complex[np.ndarray, " *value"]: """Evaluate the table at one position into its reusable result array. Parameters ---------- z : float Position in m, within the sampled span. Returns ------- numpy.ndarray The result, overwritten by the next call. """ index = self.table.interval_containing(z) lo, hi = self.table.breakpoints[index : index + 2] x = float((2.0 * z - lo - hi) / (hi - lo)) coefficients = self.table.coefficients[index] if len(coefficients) == 1: np.copyto(self.value, coefficients[0]) return self.value first, second, temporary = self.work np.copyto(first, coefficients[-2]) np.copyto(second, coefficients[-1]) for offset in range(3, len(coefficients) + 1): np.subtract(coefficients[-offset], second, out=temporary) np.multiply(second, 2.0 * x, out=second) np.add(first, second, out=second) first, temporary = temporary, first np.multiply(second, x, out=self.value) np.add(first, self.value, out=self.value) return self.value
[docs] def delta(self, z0: float, z1: float) -> Complex[np.ndarray, " *value"]: """Subtract two endpoint values into the reusable result array. Parameters ---------- z0, z1 : float Endpoint positions in m, within the sampled span. Returns ------- numpy.ndarray Table(z1) - table(z0), overwritten by the next call. """ np.copyto(self.left, self.at(z0)) self.at(z1) np.subtract(self.value, self.left, out=self.value) return self.value
[docs] @property def nbytes(self) -> int: """Return the bytes of owned work arrays. Returns ------- int Resident scratch and results in bytes, excluding immutable coefficients. """ return self.work.nbytes + self.value.nbytes + self.left.nbytes