poly
Status: released v0.1.0.
Polynomials in pure Go (CGO_ENABLED=0): evaluation, arithmetic, least-squares
fitting, roots, and the Chebyshev, Legendre, Hermite, HermiteE and Laguerre
bases, with the semantics of numpy.polyfit, numpy.roots, the
numpy.poly1d helpers and the numpy.polynomial package.
go get github.com/go-approx/poly@v0.1.0import "github.com/go-approx/poly"
fit, _ := poly.Polyfit(x, y, 3, nil) // highest degree first, like np.polyfit
r, _ := poly.Roots(fit.Coef) // companion-matrix eigenvalues
v := poly.Polyval(fit.Coef, 0.5) // Horner; PolyvalComp is compensated
s, _, _ := poly.FitSeries(poly.Chebyshev, x, y, 8, nil) // lowest degree first, like numpy.polynomial
y0, _ := s.Val(0.3)Coefficient order differs between the two families, as in NumPy: the
poly1d family is highest degree first, the numpy.polynomial family lowest
degree first.
What is provided
| here | NumPy |
|---|---|
Polyval, PolyvalAll | np.polyval |
PolyvalComp, PolyvalCompAll | (none) compensated Horner, Graillat-Langlois-Louvet 2009 |
Polyder, Polyint | np.polyder, np.polyint |
Conv, Deconv, Polymul, Polyadd, Polysub | np.convolve, np.polydiv, np.polymul, np.polyadd, np.polysub |
PolyFromRoots, PolyFromComplexRoots | np.poly |
Polyfit (weights, rcond, covariance scaled or unscaled, rank) | np.polyfit |
Roots | np.roots |
Basis (Chebyshev, Legendre, Hermite, HermiteE, Laguerre) with Val, Vander, Der, Int, RootsBasis, FitBasis | chebval, chebvander, chebder, chebint, chebroots, chebfit and the leg, herm, herme, lag equivalents |
Series (NewSeries, FitSeries, Val, Der, Int, Roots), MapParms, MapDomain, GetDomain | numpy.polynomial.Chebyshev etc. with domain/window mapping |
Verification
The reference is NumPy 2.5.4 (SciPy 1.18.1 installed alongside), run as an
oracle from Go. A tagged test (-tags oracle) generates the fixtures in
testdata/ (deterministic inputs, large cases regenerated from their seed);
the ordinary tests read them and need no Python. Octave is not installed on
the host, so no Octave oracle was run.
Measured against NumPy, as the README reports:
| quantity | result |
|---|---|
Polyval, Polyder, Polyint, Polyadd, Polysub, Deconv, PolyFromRoots | 3434 of 3434 values bit-identical |
Conv, Polymul | 229 of 917 bit-identical; max error 0.90 eps relative to the sum of abs(a_i b_j) (NumPy’s convolve uses a different summation order) |
PolyvalComp | worst error / theoretical bound = 0.00095; more accurate than Horner at 677 of 780 points |
each of the 5 bases: Val, Vander, Der, Int, Series.Val/Der/Int | 10016 of 10016 values bit-identical |
Roots | 8 of 24 cases identical in value and order; well-conditioned random degree <= 50: max positional error 4e-15 |
Polyfit | 78 fits; coefficient deviation at most 1.67 conditioning units |
The bit-identical rows hold on every architecture because every product that
feeds a sum is rounded explicitly, which forbids fused multiply-add. The
least-squares fits are not bit-identical across architectures: their QR runs
on go-simd/floats, whose Dot adds in SIMD lanes in an order that depends on
the vector width. The fit tolerances hold on every architecture CI runs.
Gates: gofmt -l . empty, go vet, go test -race, 100.0% statement
coverage with -coverpkg=./..., and a CI that runs Linux, macOS, Windows,
arm64, qemu riscv64/loong64/ppc64le/s390x/arm, 386, compiles every
GOOS/GOARCH and runs govulncheck.
Performance
docs/perf.md has
the comparison of Go against NumPy on one core, interleaved rounds. It is only
meaningful on an idle machine; the table states the load it was taken at. The
Householder QR of the fits runs its inner products and updates on
go-simd/floats (Dot, Axpy: assembly generated by go-asmgen), and the
Vandermonde and series design matrices are built in cache-sized row blocks.
Gaps
float64 only; one-dimensional coefficient and data arrays; a single integer
degree (no list of degrees as np.polyfit allows in 2.x). No
complex-coefficient Polyval or fits. No numpy.polynomial.Polynomial
(power-basis series) class beyond the poly1d functions. Conv is not
bit-identical to np.convolve. No Octave oracle.
Source: go-approx/poly, BSD-3-Clause.
Created on by tannevaled
Modified on by tannevaled