Skip to content

Latest commit

 

History

History
567 lines (453 loc) · 31.1 KB

File metadata and controls

567 lines (453 loc) · 31.1 KB

Changelog

All notable changes to PyChebyshev will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.21.1] - 2026-04-27

Added

  • ChebyshevTT.sobol_indices() — first-order and total-order Sobol sensitivity indices computed natively by contracting through the TT coefficient cores. O(d · n · r²) per dim, no dense materialization. Mirrors v0.20 ChebyshevApproximation.sobol_indices API; keys are user-frame dim indices regardless of internal _dim_order.

Fixed

  • ChebyshevTT.roots()/minimize()/maximize() previously validated fixed values against the storage-frame domain instead of the user-frame physical domain. Under with_auto_order() or reorder() with non-uniform per-dim domains, this could raise misleading errors or accept invalid inputs. Now validates against user-frame domain.
  • ChebyshevTT.inner_product() previously returned a meaningless Frobenius product when self._dim_order != other._dim_order, with no error. Now raises ValueError with a reorder() alignment hint, matching v0.20.1 binary algebra behavior.
  • ChebyshevTT.get_evaluation_points() previously returned columns in storage order, breaking eval(get_evaluation_points()[i]) for any TT with non-identity _dim_order. Now returns columns in user-frame order.
  • ChebyshevTT.eval_multi() previously mutated self._dim_order via try/finally, racing under concurrent calls (issue #19). Now uses a private _eval_storage_frame helper with no mutation.
  • ChebyshevTT.integrate() error messages on out-of-domain bounds previously referenced the storage-frame dim index instead of the user-frame index passed by the caller (issue #20). Now references the user-frame index.
  • _algebra._check_compatible previously raised "Domain mismatch" when comparing two interpolants with mixed tuple vs list domain syntax even when bounds were numerically identical (issue #22). Now uses np.allclose for comparison.

Performance

  • vectorized_eval_batch now hoists the differentiation matrix matmul outside the per-point loop. Significant speedup for derivative batch evaluations on large point sets.
  • _calculus._optimize_1d (used by all four classes' minimize/maximize) now uses a single vectorized barycentric evaluation over critical points + endpoints instead of a Python list comprehension.

Notes

  • Closes the v0.20+v0.20.1 _dim_order cluster on ChebyshevTT. All TT methods that read self.domain[d] or self.n_nodes[d] now consistently translate user-frame indices to storage-frame internally.
  • No breaking API changes: all "Fixed" items change wrong behavior to correct behavior. The inner_product strict-mode raises on mismatched _dim_order (previously silently returned wrong numbers), which is a behavior change in the failure path only.

[0.21.0] - 2026-04-27

Added

  • ChebyshevSlider.roots(dim, fixed) — find all roots along dim with other dims fixed
  • ChebyshevSlider.minimize(dim, fixed) — find global minimum along dim
  • ChebyshevSlider.maximize(dim, fixed) — find global maximum along dim
  • ChebyshevTT.roots(dim, fixed) — same, for ChebyshevTT (user-frame dim, transparent under _dim_order)
  • ChebyshevTT.minimize(dim, fixed) — same, for ChebyshevTT
  • ChebyshevTT.maximize(dim, fixed) — same, for ChebyshevTT

Notes

  • Closes the calculus parity gap promised since v0.17. All four public classes (ChebyshevApproximation, ChebyshevSpline, ChebyshevSlider, ChebyshevTT) now support the full calculus surface: integrate, roots, minimize, maximize.
  • Implementation reuses the existing 1-D primitives in _calculus.py (_roots_1d, _optimize_1d) — no new math.
  • Mirrors v0.9 ChebyshevApproximation/ChebyshevSpline semantics: multi-D requires fixed={d: v, ...} for all dims except target.
  • Under ChebyshevTT.with_auto_order() / reorder() (v0.20+), the user-frame dim and fixed keys translate to storage frame transparently via slice() and to_dense().

[0.20.1] - 2026-04-27

Fixed — TT _dim_order Full Threading

  • ChebyshevTT.eval_multi(), slice(), extrude(), to_dense(), partial integrate(dims=...), and unary algebra (__neg__, scalar __mul__, __rmul__, __truediv__, __imul__, __itruediv__) now correctly thread _dim_order through their implementations. The v0.20 NotImplementedError guards on these methods are removed; users with TTs built via with_auto_order can now use the full surface transparently.
  • Binary algebra (__add__, __sub__, __iadd__, __isub__) now succeeds when both operands share the same _dim_order, with the result inheriting that order. Mismatched _dim_order raises ValueError (instead of v0.20's NotImplementedError) with a hint pointing at reorder().

Added

  • ChebyshevTT.reorder(new_order, *, max_rank=None, tolerance=None) — realign storage to a target permutation via TT-swap (adjacent-axis SVDs in coefficient space). Functional API; returns a new TT. Accepts max_rank= and tolerance= overrides for swap-time SVD truncation. Used as the explicit alignment escape hatch for binary algebra between TTs of different dim_order.
  • New private helper _tt_swap_adjacent() in _algebra.py.
  • compare_v0201_dim_threading.py — repo-root script demonstrating the full TT surface working under non-identity dim_order.

Tests

  • New tests/test_v0201_dim_threading.py (~40 tests).
  • tests/test_v020_adaptive_refinement.py::TestDimOrderGuards updated: guard tests flipped from "raises NotImplementedError" to "now works".

[0.20.0] - 2026-04-26

Added — Adaptive Refinement + Cross-Language Interop

  • ChebyshevSpline.auto_knots(f, num_dim, domain, ...) classmethod — auto-place knots at function kinks via curvature-spike scan. Heuristic; tunable via threshold_factor, max_knots_per_dim, n_scan_points.
  • sobol_indices() instance method on ChebyshevApproximation and ChebyshevSpline — returns first-order and total-order Sobol sensitivity indices computed directly from spectral coefficients (no Monte Carlo, no extra function evals).
  • ChebyshevTT.with_auto_order(f, ...) classmethod — heuristic dimension reordering (greedy-swap or random) to minimize TT rank. New dim_order property; eval/save/load handle permutation transparently. __setstate__ backfill for pre-v0.20 pickles.
  • Reference .pcb readers in Rust and Juliareaders/rust/ (Cargo crate pcb_reader) and readers/julia/ (Pkg package PCBReader). Both ship as standalone projects within this repo. They parse the v0.14 .pcb format spec and return interpolant data; evaluation is left to the consumer.
  • New private helper _sensitivity.py with _compute_sobol_from_coeffs().
  • New tests/fixtures/*.pcb files (generated by scripts/generate_test_fixtures.py) shared across Python/Rust/Julia test suites.

Beyond MoCaX: auto-knot detection, Sobol indices, and TT dim reordering are PyChebyshev-unique adaptive features. The cross-language readers deliver on the v0.14 portability promise.

Known limitations (planned for v0.20.1)

  • ChebyshevTT.with_auto_order() produces a TT whose permuted _dim_order is only threaded through eval() and full integrate(). Other methods — eval_multi(), slice(), extrude(), to_dense(), partial integrate(), __add__/__sub__ (when the two TTs have mismatched _dim_order) — raise NotImplementedError (or ValueError for algebra mismatch) when called on a with_auto_order result with non-identity dim permutation. This avoids silent wrong-results bugs. Full threading planned for v0.20.1.
  • ChebyshevApproximation._build_fixed_grid() now raises ValueError if the user-supplied function returns NaN or Inf at any grid point, preventing subsequent calls from silently using corrupt tensor_values.
  • _compute_sobol_from_coeffs() now raises ValueError if the input coefficient tensor contains NaN or Inf.

[0.19.0] - 2026-04-26

Added — Build & Diagnostics

  • n_workers= keyword-only constructor kwarg on ChebyshevApproximation and ChebyshevSpline for parallel function evaluation at build time via concurrent.futures.ProcessPoolExecutor. None (default) = sequential, -1 = os.cpu_count(), positive int = pool size. Function and additional_data must be picklable.
  • verbose=2 opt-in tqdm progress bars on ChebyshevSpline.build(), ChebyshevSlider.build(), and ChebyshevTT.build() (TT-Cross sweeps). Existing verbose=True/False behavior unchanged.
  • ChebyshevApproximation.plot_convergence(target_error=None, max_n=64, ax=None) — builds at increasing N, plots error decay on log-y axis with optional target line.
  • plot_1d(ax=None, n_points=200, fixed=None), plot_2d_surface(...), plot_2d_contour(...) instance methods on all four classes. Use fixed= to constrain dimensions when the source has more dims than the plot needs.
  • New optional dependency group pychebyshev[viz] (matplotlib + tqdm). Plot methods raise ImportError with install hint when used without the group; tqdm fallback emits a warning.
  • New private helpers: _progress.py, _parallel.py, _viz.py.

Beyond MoCaX: MoCaX has neither parallel build nor visualization helpers.

[0.18.0] - 2026-04-26

Added — TT Feature Parity

  • ChebyshevTT.nodes(num_dim, domain, n_nodes) static — Chebyshev grid generation matching ChebyshevApproximation.nodes().
  • ChebyshevTT.from_values(tensor_values, num_dim, domain, n_nodes, max_rank=None, tolerance=1e-6, ...) classmethod — build TT directly from a precomputed full tensor via TT-SVD compression, skipping TT-Cross.
  • ChebyshevTT.extrude(params) — add a dimension where the function is constant. Inserts a rank-preserving constant core at the specified position.
  • ChebyshevTT.slice(params) — fix a dimension at a value via barycentric contraction (with fast path when value coincides with a node). Same absorption pattern as v0.17 TT integrate.
  • TT algebra: __add__, __sub__, __neg__, __mul__ (scalar), __rmul__, __truediv__ (scalar), plus __iadd__, __isub__, __imul__, __itruediv__. TT addition uses block-diagonal core stacking + TT-SVD rounding to max(self.max_rank, other.max_rank) to prevent rank explosion.
  • ChebyshevTT.to_dense() — materialize the TT chain into a full N-D tensor via einsum chain (after coefficient → value conversion).
  • New private helpers: _extrude_tt_core, _slice_tt_core in _extrude_slice.py; _tt_add_cores, _tt_round_cores in _algebra.py; _tt_svd_from_tensor in tensor_train.py.

After v0.18, ChebyshevTT has full surface parity with ChebyshevApproximation for non-calculus features. All additions are strictly additive — no breaking changes.

[0.17.0] - 2026-04-25

Added — Integrate Everywhere

  • ChebyshevSlider.integrate(dims=None, bounds=None) — full and partial integration via the sliding-decomposition closed form. Returns a scalar on full integration; a ChebyshevSlider over surviving dims on partial.
  • ChebyshevTT.integrate(dims=None, bounds=None) — full and partial integration via Fejér-1 quadrature contraction into each integrated core's node axis. Returns a scalar on full integration; a ChebyshevTT over surviving dims on partial. Works on TT objects built via Cross, SVD, and ALS methods.
  • New private helpers in _calculus.py: _slider_partition_intersect(), _integrate_tt_along_dim().
  • Extended user-guide page docs/user-guide/calculus.md with v0.17 Slider/TT integration sections.

After v0.17, all four PyChebyshev classes support integration. Roots/min/max on Slider/TT remain deferred to v0.21.

Beyond MoCaX: MoCaX 4.3.1 has no integrate() API on any class.

[0.16.0] - 2026-04-25

Added — Polish Bundle (final MoCaX 4.3.1 cosmetic mirror)

  • clone() deep copy method on all four classes (ChebyshevApproximation, ChebyshevSpline, ChebyshevSlider, ChebyshevTT). Like save/load, the source function callable is not duplicated; clone has function = None.
  • Instance getters: get_max_derivative_order() (all four), get_error_threshold() (Approximation/Spline), get_special_points() (Approximation/Spline; Approximation now stores special_points with __setstate__ backfill), get_evaluation_points() and get_num_evaluation_points() (all four; eval grid size semantics, matching len(get_evaluation_points()) == get_num_evaluation_points()).
  • peek_format_version(filename) static on ChebyshevApproximation — read .pcb major version without deserializing.
  • is_dimensionality_allowed(num_dim) static on all four classes (returns True for any positive int; hook for future per-class capability caps).
  • defer_build=True keyword-only ctor flag + set_original_function_values(values) instance mutator on ChebyshevApproximation and ChebyshevSpline — in-place deferred construction. Bit-identical to the from_values() factory. Spline path threads additional_data to pieces; atomic per-piece validation.
  • Optional typed helpers Domain, Ns, SpecialPoints (frozen dataclasses) exported from the package; constructors of all four classes accept raw lists or these dataclasses.
  • ChebyshevTT ctor now accepts max_derivative_order: int = 2 keyword-only kwarg; __setstate__ backfill for backward-compat pickles.

All additions are strictly additive — no breaking changes.

[0.15.0] - 2026-04-25

Added

  • additional_data= constructor kwarg on ChebyshevApproximation, ChebyshevSpline, ChebyshevSlider, and ChebyshevTT. Threads user-supplied context through every f(point, data) call during build.
  • set_descriptor(str) / get_descriptor() on all four classes for free-form text labels.
  • get_derivative_id(orders) registry + eval(point, derivative_id=...) on ChebyshevApproximation, ChebyshevSpline, and ChebyshevSlider for stable session-local integer IDs over derivative-orders tuples.
  • is_construction_finished(), get_constructor_type(), get_used_ns() on all four classes for introspection.

Changed

  • ChebyshevApproximation.get_derivative_id was previously a no-op stub returning the input list. It now returns a stable session-local int per registered orders tuple. Breaking for code relying on the prior identity behavior.

Notes

  • Binary .pcb save raises NotImplementedError if additional_data is not None. Use format='pickle' for full persistence.
  • Binary .pcb does not store descriptor or the derivative_id registry; pickle does.

[0.14.0] - 2026-04-24

Added

  • Portable .pcb binary serialization format for ChebyshevApproximation and ChebyshevSpline. Closes the MoCaX cross-language serialization gap in PyChebyshev's specific way.
    • New format= kwarg on save() (default 'pickle', opt in to 'binary').
    • load() auto-detects via 4-byte magic header b"PCB\x00". No behaviour change for existing pickle files.
    • C reference reader at examples/binary_reader/ (not in CI).
    • Format spec at docs/user-guide/binary-format.md.
    • Stdlib struct + NumPy only — no new runtime dependencies.

Restrictions

  • format='binary' requires flat n_nodes for ChebyshevSpline. Splines built with nested per-piece n_nodes raise NotImplementedError and fall back to pickle.
  • ChebyshevSlider and ChebyshevTT remain pickle-only in v0.14.

[0.13.1] - 2026-04-24

Changed

  • Bump transitive dev dependency requests 2.32.5 → 2.33.0 (docs tooling only; no runtime impact on installed wheels).

[0.13.0] - 2026-04-24

Added

  • ChebyshevTT now supports method='als' — rank-adaptive Alternating Least Squares build, alongside the existing 'cross' and 'svd' methods. Starts at rank 1 and increments by 1 per outer iteration until the relative grid-Frobenius residual ‖T_als − T_grid‖_F / ‖T_grid‖_F < tolerance or max_rank is reached.
  • ChebyshevTT.run_completion(tolerance, max_iter) — refines an already- built TT (from any method) at fixed rank via ALS sweeps. Sharpens a fast Cross build without rebuilding.
  • ChebyshevTT.inner_product(other) — exact TT inner product via core-by-core contraction. Strict grid-compat validation.
  • ChebyshevTT.orth_left(position) / orth_right(position) — in-place QR/LQ canonicalization sweeps. The represented tensor is unchanged.

MoCaX parity

Closes: MOCAX_CONSTRUCTOR_TT_ALS, MocaxTT.runCompletion, MocaxTT.innerProduct, MocaxTT.orthLeft/orthRight.

[0.12.0] - 2026-04-24

Added

  • special_points kwarg on ChebyshevApproximation.__init__ — declare domain kinks directly at construction. Constructor dispatches transparently to ChebyshevSpline when any dim is non-empty (precedent: pathlib.Path).
  • Per-sub-interval n_nodes in ChebyshevSpline — accept nested List[List[int | None]] form where n_nodes[d][i] is the node count for piece i along dimension d.
  • compare_special_points.py — MoCaX MocaxSpecialPoints value-match benchmark at the repo root (local-only, not in CI). Values agree with MoCaX to ~6.7e-16 (machine epsilon) across 1D and 2D cases.
  • User guide: docs/user-guide/special-points.md — motivation, API, worked examples (abs(x), barrier option payoff).

Changed

  • ChebyshevApproximation(f, d, dom, n_nodes, ..., special_points=[[...]]) returns a ChebyshevSpline instance when special_points declares any kink. This matches MoCaX parity and what was actually built.
  • Nested-form n_nodes validation in ChebyshevSpline is strict: all dims must be nested when any is; inner length must equal len(knots[d]) + 1.

MoCaX parity (4.3.1)

Closes: core special_points kwarg; per-sub-interval Ns.

[0.11.0] - 2026-04-24

Added

  • Error-driven construction for ChebyshevApproximation and ChebyshevSpline. Constructors now accept error_threshold and max_n kwargs, and n_nodes entries may be None (signalling auto-N mode). The build-time doubling loop doubles the worst-contributing auto dim each iteration until the sup-norm error estimate falls below the target or max_n is hit.
  • ChebyshevApproximation.get_optimal_n1() classmethod — 1-D capacity estimator returning the smallest N that satisfies error_threshold over a 1-D domain.
  • ChebyshevApproximation.get_error_threshold() — accessor returning the target threshold passed to __init__ (or None if unset).
  • ChebyshevSpline.error_threshold / max_n kwargs, applied per piece — pieces near kinks refine more than smooth pieces.
  • ChebyshevSpline.knots parameter is now optional; defaults to [[] for _ in range(num_dimensions)] (single piece per dim).
  • Internal _error_estimate_per_dim() helper on ChebyshevApproximation — per-dim last-coefficient magnitudes used by the doubling loop.
  • Internal _original_n_nodes attribute — preserves the user's original n_nodes (including None sentinels) so build() can be called a second time with a tightened threshold to re-run the doubling loop.
  • Backward-compat __setstate__ shim populates _original_n_nodes from n_nodes when loading pre-v0.11 pickles.
  • 30 new tests across tests/test_error_threshold.py (27) and tests/test_barycentric.py (3, TestErrorEstimatePerDim). All run in CI.
  • New user-guide page: Error-Driven Construction with motivation, algorithm, Black-Scholes 5D example, and references.
  • compare_error_threshold.py — local MoCaX value-match benchmark (not in CI; imports gitignored mocax_lib/).

Changed

  • ChebyshevApproximation.__init__ signature: n_nodes is now list of (int or None), optional (was mandatory list of int). Either n_nodes or error_threshold must be supplied. None entries in n_nodes require error_threshold to be set.
  • ChebyshevSpline.__init__ signature: same as above; knots is now optional.
  • ChebyshevApproximation.build() refactored into a public wrapper that dispatches to _build_fixed_grid (original behavior) or _build_with_threshold (new doubling loop). No behavior change for explicit-N builds.
  • In auto-N mode, n_evaluations and build_time now accumulate across doubling iterations (not just the final iteration).
  • ChebyshevSpline.total_build_evals handles heterogeneous-N auto-N builds by summing per-piece n_evaluations.

[0.10.1] - 2026-02-20

Fixed

  • Corrected Good (1961) citation: journal is The Quarterly Journal of Mathematics 12(1):61-68, not Quarterly Journal of Mechanics and Applied Mathematics 14:195-196. Fixed in _calculus.py, barycentric.py, and calculus.md.
  • Fixed Trefethen book year from "SIAM 2019" to "SIAM 2013" in concepts.md and greeks.md (2019 is the extended edition; all citations reference the 2013 first edition).
  • Fixed TT-Cross attribution in tensor-train.md: now correctly cites both Oseledets & Tyrtyshnikov (2010) and Savostyanov & Oseledets (2011).
  • Added 30+ missing inline citations across 11 documentation pages, verified against original sources. Key additions: Runge (1901) for Runge's phenomenon, Berrut & Trefethen (2004) for barycentric formula and differentiation matrices, Trefethen (2013) chapter references for Lebesgue constant, Bernstein ellipse, spectral convergence of derivatives, and Chebyshev node generation.
  • Added formal References sections to concepts.md, spline.md, sliding.md, and tensor-train.md.

[0.10.0] - 2026-02-20

Added

  • ChebyshevApproximation.nodes() static method to generate Chebyshev grid points without evaluating any function. Returns per-dimension node arrays, the full Cartesian product grid, and the expected tensor shape.
  • ChebyshevApproximation.from_values() class method to construct a fully functional interpolant from pre-computed function values. Supports all operations: evaluation, derivatives, integration, rootfinding, optimization, algebra, extrusion/slicing, and serialization.
  • ChebyshevSpline.nodes() static method returning per-piece node information for piecewise Chebyshev interpolation with knots.
  • ChebyshevSpline.from_values() class method to construct a spline from per-piece pre-computed values.
  • Guard in build() for both classes: raises RuntimeError with a clear message when function=None (e.g., after from_values(), load(), or algebra operations).
  • Input validation in from_values(): shape mismatch, NaN/Inf detection, dimension consistency, and domain ordering.
  • 65 new tests covering core equivalence (bit-identical to build()), edge cases (NaN/Inf, shape mismatch, domain validation, duplicate knots, boundary evaluation, 4D, algebra chains), and cross-compatibility.
  • Documentation page: "Pre-computed Values" with workflow, indexing convention, mathematical justification, API reference, and MoCaX Extend comparison.

[0.9.5] - 2026-02-15

Added

  • Sub-interval integration via bounds parameter on integrate() for both ChebyshevApproximation and ChebyshevSpline. Uses generalized Fejér-1 quadrature with sub-interval Chebyshev moments computed from closed-form antiderivatives (Trefethen 2013, Ch. 19).
  • Spline sub-interval integration with automatic piece overlap clipping: pieces with no overlap are skipped, partial overlaps receive sub-interval bounds, fully contained pieces use standard Fejér-1 weights.
  • 22 new tests for sub-interval integration (14 for ChebyshevApproximation, 8 for ChebyshevSpline), including polynomial exactness, scipy cross-validation, additivity, and error handling.

[0.9.0] - 2026-02-15

Added

  • integrate() method on ChebyshevApproximation and ChebyshevSpline for definite integration via Fejér-1 quadrature (Waldvogel 2006), with O(n log n) weight computation via DCT-III and O(n^d) multi-D contraction via BLAS.
  • roots() method on ChebyshevApproximation and ChebyshevSpline for finding all real roots along a dimension via companion matrix eigenvalues (numpy.polynomial.chebyshev.chebroots).
  • minimize() / maximize() methods on ChebyshevApproximation and ChebyshevSpline for global optimization via derivative rootfinding and endpoint evaluation.
  • Partial integration returns a lower-dimensional ChebyshevApproximation (analogous to slice()).
  • Internal _calculus.py module with shared helpers for Fejér-1 weights, 1-D rootfinding, and 1-D optimization.
  • New documentation page: Chebyshev Calculus (integration, roots, optimization).
  • 52 new tests for calculus operations (test_calculus.py).

[0.8.0] - 2026-02-15

Added

  • extrude() and slice() methods on ChebyshevApproximation, ChebyshevSpline, and ChebyshevSlider.
  • Extrusion adds new dimensions where the function is constant, enabling portfolio combination across different risk-factor sets.
  • Slicing fixes a dimension at a value, reducing dimensionality via barycentric interpolation (with fast path at exact nodes).
  • Extrude-then-slice round-trip preserves the original interpolant exactly.
  • Internal _extrude_slice.py module with shared validation and tensor manipulation helpers.
  • New documentation page: Extrusion & Slicing (mathematical proofs, API reference, portfolio use case).
  • compare_extrude_slice.py -- MoCaX comparison script (local only, not in CI).
  • 63 new tests for extrusion and slicing across all three classes.

[0.7.0] - 2026-02-14

Added

  • Arithmetic operators (+, -, *, /, unary -, +=, -=, *=, /=) for ChebyshevApproximation, ChebyshevSpline, and ChebyshevSlider.
  • Portfolio-level combination of Chebyshev interpolants via weighted sums -- no re-evaluation needed.
  • Derivatives and error estimates propagate correctly through algebraic operations.
  • Internal _algebra.py module with shared compatibility validation.
  • _from_grid() factory on ChebyshevApproximation, _from_pieces() on ChebyshevSpline, _from_slides() on ChebyshevSlider.

[0.6.0] - 2026-02-14

Added

  • ChebyshevSpline class for piecewise Chebyshev interpolation with user-specified knots (Section 3.8, Ruiz & Zeron 2021)
  • Knot-based domain partitioning: place knots at kinks or discontinuities to restore spectral convergence on each piece
  • eval(), eval_multi(), eval_batch() with automatic piece routing via np.searchsorted
  • Analytical derivatives within each piece via spectral differentiation matrices (inherited from ChebyshevApproximation)
  • ValueError raised when requesting derivatives at knot boundaries (left/right derivatives differ)
  • error_estimate() returning the maximum error across all disjoint pieces
  • save() / load() serialization following the same pattern as other PyChebyshev classes
  • num_pieces, total_build_evals, build_time properties
  • New documentation page: Chebyshev Splines (mathematical justification, usage guide)
  • compare_spline.py — MoCaX spine comparison script (local only, not in CI)
  • ~34 new tests for spline construction, accuracy, derivatives, batch eval, serialization

[0.5.0] - 2026-02-12

Added

  • ChebyshevTT class for Chebyshev interpolation in Tensor Train format (Chapter 6, Ruiz & Zeron 2021)
  • TT-Cross approximation (method='cross') for building from O(d * n * r^2) function evaluations instead of O(n^d)
  • TT-SVD build option (method='svd') for validation and moderate-dimension problems
  • eval() for single-point evaluation via TT inner product with Chebyshev polynomial contraction
  • eval_batch() for vectorized batch evaluation of multiple points simultaneously via numpy einsum
  • eval_multi() for finite-difference derivatives (1st and 2nd order, including cross-derivatives)
  • error_estimate() for approximate error estimation from Chebyshev coefficient cores
  • save() / load() serialization with version compatibility checks (same pattern as other classes)
  • tt_ranks and compression_ratio properties for inspecting the TT decomposition
  • _maxvol() module-level function implementing the maximum-volume row selection algorithm
  • _tt_cross() module-level function implementing TT-Cross with alternating left-right sweeps and maxvol pivot selection

[0.4.0] - 2026-02-10

Added

  • error_estimate() method on ChebyshevApproximation — estimates supremum-norm interpolation error from Chebyshev expansion coefficients via DCT-II, without needing the true function (Ruiz & Zeron 2021, Section 3.4)
  • error_estimate() method on ChebyshevSlider — returns sum of per-slide error estimates
  • _chebyshev_coefficients_1d() static method for computing Chebyshev expansion coefficients from values at Type I nodes
  • Error estimate shown in __str__() output for both classes when built
  • New documentation page: Error Estimation (mathematical background, usage examples)
  • 12 new tests for error estimation (8 for barycentric, 4 for slider)
  • compare_error_estimation.py — local benchmarking script comparing PyChebyshev vs MoCaX error estimates

[0.3.0] - 2026-02-10

Deprecated

  • fast_eval() — use vectorized_eval() instead, which is ~150x faster via BLAS GEMV
  • [jit] optional dependency (Numba) — no longer needed since BLAS path outperforms JIT
  • _jit.py module — will be removed in a future version

Changed

  • README, docs, and CLAUDE.md updated to reflect BLAS GEMV as the primary fast path
  • Removed Numba JIT installation instructions from all documentation
  • Removed numba from dev dependencies

[0.2.1] - 2026-02-10

Added

  • save() and load() methods on ChebyshevApproximation and ChebyshevSlider for persisting built interpolants to disk (pickle-based)
  • __repr__ and __str__ methods on both classes for human-readable printing
  • Version compatibility check on load with warning for mismatched versions
  • New documentation page: Saving & Loading Interpolants
  • 21 new tests for serialization and printing

[0.2.0] - 2026-02-09

Added

  • ChebyshevSlider class for high-dimensional approximation via the Sliding Technique (Ch. 7, Ruiz & Zeron 2021)
  • Additive decomposition into low-dimensional slides around a pivot point
  • Analytical derivatives per slide with correct cross-group mixed partial handling (returns 0)
  • Documentation page for the Sliding Technique with usage examples and limitations
  • 24 new tests for slider (additive, coupled, 5D, cross-group derivatives, validation)

Changed

  • README updated: repositioned as a library (was standalone educational script)
  • Getting Started section now uses pip install pychebyshev with code examples
  • Fixed repo URL in docs (maxjingwezhang0xC000005)

[0.1.1] - 2026-02-07

Fixed

  • README images now load on PyPI (use absolute GitHub URLs instead of relative paths)

[0.1.0] - 2026-02-07

Added

  • ChebyshevApproximation class for multi-dimensional Chebyshev tensor interpolation
  • Barycentric interpolation with full weight pre-computation
  • Analytical derivatives via spectral differentiation matrices (1st and 2nd order)
  • vectorized_eval() using BLAS matrix-vector products (~0.065 ms/query)
  • vectorized_eval_multi() with shared barycentric weights (~0.29 ms for price + 5 Greeks)
  • fast_eval() with Numba JIT compilation (optional)
  • Node coincidence handling for all evaluation methods
  • MkDocs + Material documentation with KaTeX math rendering
  • pytest test suite (22 tests covering 3D/5D accuracy and method consistency)
  • GitHub Actions CI/CD for testing and PyPI publishing