// Copyright (c) 2026 Petr Balvín (https://petrbalvin.org) // SPDX-License-Identifier: MIT package tensor import ( "crypto/sha256" "encoding/binary" "encoding/hex" "fmt" "hash" "maps" "math" "os" "path/filepath" "runtime" "runtime/debug" "slices" "testing" "sourcedock.dev/petrbalvin/tensor/internal/core" "sourcedock.dev/petrbalvin/tensor/spmd" ) // The oracle harness. Every domain runs one fixed workload through the // re-exported facade only, the raw bits of every output are hashed, and // the per-case digest is pinned in the table below. A silent behaviour // change, a swapped reduction order, a regression in a kernel: any of // them moves the digest and fails the test. A deliberate change to an // algorithm re-records the table in the same commit, so the diff shows // exactly which case moved. // // Inputs are fixed literals or the seeded generator, which is // bit-stable across Go releases by construction, and the parallel // kernels promise a fixed reduction order, so the digest is // deterministic on a given architecture. Run with // TENSOR_ORACLE_RECORD=1 to print the current digests instead of // comparing them. // oracleDigest accumulates the raw bits of the given values. Supported // carriers: *Array, Scalar, float64, []float64, string, bool and int; // anything else is a harness bug and panics. type oracleDigest struct { h hash.Hash } func newOracleDigest() *oracleDigest { return &oracleDigest{h: sha256.New()} } func (d *oracleDigest) array(t *testing.T, a *core.Array) { d.h.Write([]byte{byte(a.Dtype())}) for _, s := range a.Shape() { var buf [8]byte binary.LittleEndian.PutUint64(buf[:], uint64(s)) d.h.Write(buf[:]) } switch a.Dtype() { case core.Int: for _, v := range a.RawInts()[:a.Len()] { var buf [8]byte binary.LittleEndian.PutUint64(buf[:], uint64(v)) d.h.Write(buf[:]) } case core.Float32: for _, v := range a.RawFloat32s()[:a.Len()] { var buf [4]byte binary.LittleEndian.PutUint32(buf[:], math.Float32bits(v)) d.h.Write(buf[:]) } case core.Float16: for _, v := range a.RawHalves()[:a.Len()] { var buf [2]byte binary.LittleEndian.PutUint16(buf[:], v) d.h.Write(buf[:]) } case core.Float: for _, v := range a.RawFloats()[:a.Len()] { d.f64(v) } case core.Complex: for _, v := range a.RawComplexes()[:a.Len()] { d.f64(real(v)) d.f64(imag(v)) } case core.Bool: // The boolean payload hashes as its own bytes, one 0 or 1 per // element, the layout every mask round-trip is read back in. for _, v := range a.RawBools()[:a.Len()] { if v { d.h.Write([]byte{1}) } else { d.h.Write([]byte{0}) } } case core.Int8: for _, v := range a.RawInt8s()[:a.Len()] { d.h.Write([]byte{byte(v)}) } case core.Uint8: for _, v := range a.RawUint8s()[:a.Len()] { d.h.Write([]byte{byte(v)}) } case core.Int16: for _, v := range a.RawInt16s()[:a.Len()] { var buf [2]byte binary.LittleEndian.PutUint16(buf[:], uint16(v)) d.h.Write(buf[:]) } case core.Uint16: for _, v := range a.RawUint16s()[:a.Len()] { var buf [2]byte binary.LittleEndian.PutUint16(buf[:], uint16(v)) d.h.Write(buf[:]) } case core.Int32: for _, v := range a.RawInt32s()[:a.Len()] { var buf [4]byte binary.LittleEndian.PutUint32(buf[:], uint32(v)) d.h.Write(buf[:]) } case core.Uint32: for _, v := range a.RawUint32s()[:a.Len()] { var buf [4]byte binary.LittleEndian.PutUint32(buf[:], uint32(v)) d.h.Write(buf[:]) } default: // An unhashed payload would pin nothing: fail loudly in the // test rather than panicking or hashing the wrong bytes. t.Fatalf("oracle harness: array payload of dtype %s (%d) has no hash rule", a.Dtype(), a.Dtype()) } } func (d *oracleDigest) f64(v float64) { var buf [8]byte binary.LittleEndian.PutUint64(buf[:], math.Float64bits(v)) d.h.Write(buf[:]) } func (d *oracleDigest) floats(vals []float64) { var n [8]byte binary.LittleEndian.PutUint64(n[:], uint64(len(vals))) d.h.Write(n[:]) for _, v := range vals { d.f64(v) } } func (d *oracleDigest) int(v int) { var buf [8]byte binary.LittleEndian.PutUint64(buf[:], uint64(v)) d.h.Write(buf[:]) } // result carries one output of an oracle case into the digest. func (d *oracleDigest) result(t *testing.T, v any) { switch x := v.(type) { case *Array: d.array(t, x) case Scalar: d.f64(x.Float()) case float64: d.f64(x) case []float64: d.floats(x) case string: d.h.Write([]byte(x)) case bool: // Error paths carry the fact of the refusal, not its wording: // the text may be reworded, the refusal must not disappear. if x { d.h.Write([]byte{1}) } else { d.h.Write([]byte{0}) } case int: d.int(x) default: panic("oracle harness: unsupported carrier type") } } func (d *oracleDigest) sum() string { return hex.EncodeToString(d.h.Sum(nil)) } // mustA builds an array from fixed values. func mustA(t *testing.T, vals []float64, shape ...int) *Array { t.Helper() a, err := FromFloats(vals, shape...) if err != nil { t.Fatal(err) } return a } // randA draws n deterministic samples through the seeded generator. func randA(t *testing.T, seed int64, n int) *Array { t.Helper() g := NewGenerator(seed) a, err := Floats(g, n) if err != nil { t.Fatal(err) } return a } // wobble is the bounded deterministic wiggle the formula-driven // workloads use in place of a generator: a fixed function of the // index, so a case's inputs are its own, not the generator state's. func wobble(i int) float64 { return 0.3*math.Sin(7.3*float64(i)+1.1)*math.Cos(2.1*float64(i)) + 0.1*math.Sin(0.7*float64(i)) } // oracleCases is the harness workload: one entry per domain feature, // every output it produces fed into the digest. var oracleCases = []struct { name string run func(t *testing.T) []any }{ {"spmd-shards", func(t *testing.T) []any { // The distributed reduction answers the single-array // reduction's exact bits at any world size: the digest pins // the shards' answers beside the single-array ones they must // equal, over a length that cuts the fold's partition into // several blocks. const gn = 200001 vals := make([]float64, gn) for i := range vals { vals[i] = float64((i*6559)%2001-1000) / 7.0 if i%401 == 3 { vals[i] = math.NaN() } } yVals := make([]float64, gn) for i := range yVals { yVals[i] = float64((i*7919)%901-450) / 5.0 } whole, err := FromFloats(vals, gn) if err != nil { t.Fatal(err) } wantSum := Sum(whole) wantMax, err := Max(whole) if err != nil { t.Fatal(err) } out := []any{wantSum, wantMax} for _, size := range []int{1, 3, 5} { // Each rank writes its own slots; the digest takes them in // rank order after the world has joined up again. answers := make([]core.Scalar, size*5) err := spmd.Launch(size, func(w *spmd.World) error { span, err := spmd.Partition(gn, size, w.Rank()) if err != nil { return err } local, err := Slice(whole, 0, span.Lo, span.Hi) if err != nil { return err } gotSum, err := w.AllReduceShards(local, span, spmd.Sum) if err != nil { return err } gotMax, err := w.AllReduceShards(local, span, spmd.Max) if err != nil { return err } gotProd, err := w.AllReduceShards(local, span, spmd.Prod) if err != nil { return err } gotNorm, err := w.AllReduceNormShards(local, span, 2) if err != nil { return err } second, err := FromFloats(yVals, gn) if err != nil { return err } secondLocal, err := Slice(second, 0, span.Lo, span.Hi) if err != nil { return err } gotDot, err := w.AllReduceDotShards(local, secondLocal, span) if err != nil { return err } wantProd, err := Prod(whole, 0, false) if err != nil { return err } wantNorm, err := Norm(whole, 2, 0, false) if err != nil { return err } wantDot, err := Dot(whole, second) if err != nil { return err } if math.Float64bits(gotSum.Float()) != math.Float64bits(wantSum.Float()) || math.Float64bits(gotMax.Float()) != math.Float64bits(wantMax.Float()) || math.Float64bits(gotProd.Float()) != math.Float64bits(wantProd.FloatAt(0)) || math.Float64bits(gotNorm.Float()) != math.Float64bits(wantNorm.FloatAt(0)) || math.Float64bits(gotDot.Float()) != math.Float64bits(wantDot.Float()) { t.Fatalf("size %d: the sharded answers moved against the single-array reduction", size) } answers[w.Rank()*5] = gotSum answers[w.Rank()*5+1] = gotMax answers[w.Rank()*5+2] = gotProd answers[w.Rank()*5+3] = gotNorm answers[w.Rank()*5+4] = gotDot return nil }) if err != nil { t.Fatal(err) } for _, s := range answers { out = append(out, s) } out = append(out, fmt.Sprintf("size %d agreed", size)) } return out }}, {"core-elementwise", func(t *testing.T) []any { a := randA(t, 1, 64) b := randA(t, 2, 64) sum, _ := Add(a, b) prod, _ := Mul(a, b) return []any{sum, prod, MulF(a, 1.5)} }}, {"core-matmul-einsum", func(t *testing.T) []any { a := randA(t, 3, 64) b := randA(t, 4, 64) mm, err := MatMul2D(mustA(t, a.RawFloats(), 8, 8), mustA(t, b.RawFloats(), 8, 8)) if err != nil { t.Fatal(err) } e, err := Einsum("ij,jk->ik", mustA(t, a.RawFloats(), 8, 8), mustA(t, b.RawFloats(), 8, 8)) if err != nil { t.Fatal(err) } return []any{mm, e} }}, {"core-sort-argsort", func(t *testing.T) []any { vals := randA(t, 5, 200).RawFloats() vals[3] = math.NaN() vals[17] = math.Copysign(0, -1) vals[42] = math.Inf(1) vals[43] = math.Inf(-1) vals[7] = vals[8] // a tie src := mustA(t, vals, len(vals)) s, err := Sort(src) if err != nil { t.Fatal(err) } idx, err := ArgSort(src) if err != nil { t.Fatal(err) } return []any{s, idx} }}, {"core-reductions", func(t *testing.T) []any { a := randA(t, 6, 1000) b := randA(t, 7, 1000) dot, err := Dot(a, b) if err != nil { t.Fatal(err) } mean, err := Mean(a) if err != nil { t.Fatal(err) } mn, err := Min(a) if err != nil { t.Fatal(err) } mx, err := Max(a) if err != nil { t.Fatal(err) } cs, err := CumSum(a, 0) if err != nil { t.Fatal(err) } return []any{Sum(a), mean, mn, mx, dot, cs} }}, {"core-shape", func(t *testing.T) []any { a := randA(t, 8, 24) m := mustA(t, a.RawFloats(), 4, 6) tr, err := TransposeAxes(m, 1, 0) if err != nil { t.Fatal(err) } r, err := Reshape(m, 3, 8) if err != nil { t.Fatal(err) } sl, err := Slice(m, 0, 1, 3) if err != nil { t.Fatal(err) } return []any{tr, r, sl} }}, {"core-fft", func(t *testing.T) []any { a := randA(t, 9, 256) spec, err := FFT(a) if err != nil { t.Fatal(err) } back, err := IFFT(spec) if err != nil { t.Fatal(err) } return []any{spec, back} }}, {"core-quasirandom", func(t *testing.T) []any { sob, err := SobolPoints(64, 4, 0) if err != nil { t.Fatal(err) } sob2, err := SobolPoints(32, 4, 1000) if err != nil { t.Fatal(err) } hal, err := HaltonPoints(64, 4, 0) if err != nil { t.Fatal(err) } return []any{sob, sob2, hal} }}, {"linalg-solve-inv-det", func(t *testing.T) []any { a := randA(t, 10, 25) // Diagonal dominance keeps the solve well conditioned. m := mustA(t, a.RawFloats(), 5, 5) md := m.RawFloats() for i := range 5 { md[i*5+i] += 10 } b := randA(t, 11, 5) x, err := Solve(m, b) if err != nil { t.Fatal(err) } iv, err := Inv(m) if err != nil { t.Fatal(err) } det, err := Det(m) if err != nil { t.Fatal(err) } return []any{x, iv, det} }}, {"linalg-factorisations", func(t *testing.T) []any { a := randA(t, 12, 36) m := mustA(t, a.RawFloats(), 6, 6) // Symmetrise, then shift to positive definite. sym := make([]float64, 36) mm := m.RawFloats() for i := range 6 { for j := range 6 { sym[i*6+j] = (mm[i*6+j] + mm[j*6+i]) / 2 } sym[i*6+i] += 8 } pd := mustA(t, sym, 6, 6) q, r, err := QR(pd) if err != nil { t.Fatal(err) } chol, err := Cholesky(pd) if err != nil { t.Fatal(err) } u, sigma, vt, err := SVD(pd) if err != nil { t.Fatal(err) } vals, vecs, err := Eigen(pd) if err != nil { t.Fatal(err) } return []any{q, r, chol, u, sigma, vt, vals, vecs} }}, {"linalg-sparse-complex", func(t *testing.T) []any { const n = 32 // Hermitian tridiagonal: real diagonal, imaginary couplings // conjugated across the diagonal. var hIdx []int64 var hVal []complex128 for i := range n { hIdx = append(hIdx, int64(i), int64(i)) hVal = append(hVal, 2+0i) if i+1 < n { hIdx = append(hIdx, int64(i), int64(i+1)) hVal = append(hVal, 0.5i) hIdx = append(hIdx, int64(i+1), int64(i)) hVal = append(hVal, -0.5i) } } hIndices, err := FromInts(hIdx, len(hVal), 2) if err != nil { t.Fatal(err) } hValues, err := FromComplexes(hVal, len(hVal)) if err != nil { t.Fatal(err) } h, err := NewSparseCOO(hIndices, hValues, []int{n, n}) if err != nil { t.Fatal(err) } ones := make([]complex128, n) for i := range ones { ones[i] = 1 } rhs, err := FromComplexes(ones, n) if err != nil { t.Fatal(err) } xCG, err := SpSolveComplexCG(h, rhs, 1e-12, 200) if err != nil { t.Fatal(err) } // Genuinely non-Hermitian: different off-diagonal values. var gIdx []int64 var gVal []complex128 for i := range n { gIdx = append(gIdx, int64(i), int64(i)) gVal = append(gVal, 2+1i) if i+1 < n { gIdx = append(gIdx, int64(i), int64(i+1)) gVal = append(gVal, 1) gIdx = append(gIdx, int64(i+1), int64(i)) gVal = append(gVal, 0.25i) } } gIndices, err := FromInts(gIdx, len(gVal), 2) if err != nil { t.Fatal(err) } gValues, err := FromComplexes(gVal, len(gVal)) if err != nil { t.Fatal(err) } g, err := NewSparseCOO(gIndices, gValues, []int{n, n}) if err != nil { t.Fatal(err) } xBiCG, err := SpSolveComplexBiCGSTAB(g, rhs, 1e-12, 400) if err != nil { t.Fatal(err) } vals, vecs, err := SpEigenComplex(h, 4, NewGenerator(11)) if err != nil { t.Fatal(err) } return []any{xCG, xBiCG, vals, vecs} }}, {"linalg-sparse-cholesky", func(t *testing.T) []any { // A shuffled 5-point Laplacian: the ordering does the work, // the solve must answer A⁻¹·(A·v) = v for both orderings. const n = 100 g := NewGenerator(31) perm := make([]int, n) for i := range perm { perm[i] = i } for i := n - 1; i > 0; i-- { j := int(g.Next() % uint64(i+1)) perm[i], perm[j] = perm[j], perm[i] } label := func(x, y, w int) int { return perm[y*w+x] } var idx []int64 var vals []float64 add := func(r, c int, v float64) { idx = append(idx, int64(r), int64(c)) vals = append(vals, v) } const w, h = 10, 10 for y := range h { for x := range w { add(label(x, y, w), label(x, y, w), 4) if x+1 < w { add(label(x, y, w), label(x+1, y, w), -1) add(label(x+1, y, w), label(x, y, w), -1) } if y+1 < h { add(label(x, y, w), label(x, y+1, w), -1) add(label(x, y+1, w), label(x, y, w), -1) } } } indices, err := FromInts(idx, len(vals), 2) if err != nil { t.Fatal(err) } valArray, err := FloatsFromArray(vals, len(vals)) if err != nil { t.Fatal(err) } coo, err := NewSparseCOO(indices, valArray, []int{n, n}) if err != nil { t.Fatal(err) } csr, err := CSRFromCOO(coo) if err != nil { t.Fatal(err) } v := make([]float64, n) for i := range v { v[i] = float64(i%13) - 6 + 0.5*float64(i%7) } xTrue := New(Float, n) for i := range v { xTrue.RawFloats()[i] = v[i] } b, err := csr.MatVec(xTrue) if err != nil { t.Fatal(err) } nat, err := NewSparseCholesky(coo, SparseOrderingNatural) if err != nil { t.Fatal(err) } rcm, err := NewSparseCholesky(coo, SparseOrderingReverseCuthillMcKee) if err != nil { t.Fatal(err) } xn, err := nat.Solve(b) if err != nil { t.Fatal(err) } xr, err := rcm.Solve(b) if err != nil { t.Fatal(err) } pn := nat.Permutation() pr := rcm.Permutation() pnf := make([]float64, len(pn)) prf := make([]float64, len(pr)) for i := range pn { pnf[i] = float64(pn[i]) prf[i] = float64(pr[i]) } return []any{pnf, prf, float64(nat.NNZ()), float64(rcm.NNZ()), xn, xr} }}, {"linalg-sparse-lu", func(t *testing.T) []any { // A nonsymmetric banded system with real fill: the factor must // invert the map the CSR MatVec builds, pivoting included. const n = 40 g := NewGenerator(41) var idx []int64 var vals []float64 add := func(r, c int, v float64) { idx = append(idx, int64(r), int64(c)) vals = append(vals, v) } for i := range n { add(i, i, 5+2*g.Unit()) if i+1 < n { add(i, i+1, -1-g.Unit()) add(i+1, i, -1-g.Unit()) } if i+3 < n { add(i, i+3, -0.6*g.Unit()) } if i+4 < n { add(i+4, i, -0.4*g.Unit()) } } indices, err := FromInts(idx, len(vals), 2) if err != nil { t.Fatal(err) } valArray, err := FloatsFromArray(vals, len(vals)) if err != nil { t.Fatal(err) } coo, err := NewSparseCOO(indices, valArray, []int{n, n}) if err != nil { t.Fatal(err) } csr, err := CSRFromCOO(coo) if err != nil { t.Fatal(err) } v := make([]float64, n) for i := range v { v[i] = float64(i%9) - 4 + 0.25*float64(i%5) } xTrue := New(Float, n) for i := range v { xTrue.RawFloats()[i] = v[i] } b, err := csr.MatVec(xTrue) if err != nil { t.Fatal(err) } f, err := NewSparseLU(coo) if err != nil { t.Fatal(err) } x, err := f.Solve(b) if err != nil { t.Fatal(err) } p := f.Permutation() pf := make([]float64, len(p)) for i := range p { pf[i] = float64(p[i]) } return []any{pf, float64(f.NNZ()), x} }}, {"integrate-fem-poisson", func(t *testing.T) []any { // The manufactured solution u = sin(πx)·sin(πy) on a 10×10 // structured mesh of the unit square: assemble, lift the // boundary, solve through the sparse Cholesky. const m = 10 n := (m + 1) * (m + 1) vertices := make([]float64, 2*n) for j := range m + 1 { for i := range m + 1 { vertices[2*(j*(m+1)+i)] = float64(i) / float64(m) vertices[2*(j*(m+1)+i)+1] = float64(j) / float64(m) } } at := func(i, j int) int64 { return int64(j*(m+1) + i) } idx := make([]int64, 0, 6*m*m) for j := range m { for i := range m { idx = append(idx, at(i, j), at(i+1, j), at(i+1, j+1), at(i, j), at(i+1, j+1), at(i, j+1)) } } vArr, err := FromFloats(vertices, n, 2) if err != nil { t.Fatal(err) } tArr, err := FromInts(idx, m*m*2, 3) if err != nil { t.Fatal(err) } mesh, err := NewTriangleMesh2D(vArr, tArr) if err != nil { t.Fatal(err) } sol := func(x, y float64) float64 { return math.Sin(math.Pi*x) * math.Sin(math.Pi*y) } src := func(x, y float64) float64 { return 2 * math.Pi * math.Pi * sol(x, y) } var bound []int var vals []float64 for j := range m + 1 { for i := range m + 1 { if i == 0 || i == m || j == 0 || j == m { bound = append(bound, j*(m+1)+i) vals = append(vals, sol(float64(i)/float64(m), float64(j)/float64(m))) } } } u, err := SolvePoissonFEM2D(mesh, src, FEMPoissonOptions{Kappa: 1, DirichletNodes: bound, DirichletValues: vals, Ordering: SparseOrderingReverseCuthillMcKee}) if err != nil { t.Fatal(err) } first := make([]float64, 0, 12) for i := range 12 { first = append(first, u.FloatAt(i)) } return []any{first, u.FloatAt(n / 2), u.FloatAt(n - 1)} }}, {"signal-welch-savgol", func(t *testing.T) []any { x := randA(t, 13, 512) freqs, psd, err := WelchPSD(x, 1000, 128, 64, "hann") if err != nil { t.Fatal(err) } sm, err := SavitzkyGolay(x, 11, 3) if err != nil { t.Fatal(err) } return []any{freqs, psd, sm} }}, {"signal-wavelets", func(t *testing.T) []any { x := randA(t, 14, 128) coef, err := DWT(x, 3) if err != nil { t.Fatal(err) } back, err := IDWT(coef, 3) if err != nil { t.Fatal(err) } cw, err := CWT(x, Morlet, []float64{1, 2, 4, 8}, 1) if err != nil { t.Fatal(err) } return []any{coef, back, cw} }}, {"signal-lombscargle-conv", func(t *testing.T) []any { g := NewGenerator(15) times, err := Floats(g, 100) if err != nil { t.Fatal(err) } acc := 0.0 for i, v := range times.RawFloats() { acc += v + 0.1 times.RawFloats()[i] = acc // irregular but increasing } vals := randA(t, 16, 100) freqs, power, err := LombScargle(times, vals, 0.1, 5, 32) if err != nil { t.Fatal(err) } input := mustA(t, randA(t, 17, 64).RawFloats(), 1, 1, 64) kernel := mustA(t, randA(t, 18, 5).RawFloats(), 1, 1, 5) conv, err := Conv1D(input, kernel, nil, 1, 0, 1) if err != nil { t.Fatal(err) } return []any{freqs, power, conv} }}, {"signal-filters-stencils", func(t *testing.T) []any { x := randA(t, 19, 256) b, a, err := ButterworthLowPass(4, 1000, 100) if err != nil { t.Fatal(err) } filt, err := FilterApply(b, a, x) if err != nil { t.Fatal(err) } grad, err := Gradient1D(x, 0.5) if err != nil { t.Fatal(err) } m := mustA(t, randA(t, 20, 64).RawFloats(), 8, 8) lap, err := Laplacian(m, 1.0, 1.0) if err != nil { t.Fatal(err) } return []any{filt, grad, lap} }}, {"stats-moments-quantiles", func(t *testing.T) []any { a := randA(t, 21, 1000) v, err := Var(a) if err != nil { t.Fatal(err) } s, err := Std(a) if err != nil { t.Fatal(err) } med, err := Median(a) if err != nil { t.Fatal(err) } q, err := Quantile(a, []float64{0.05, 0.25, 0.5, 0.75, 0.95}) if err != nil { t.Fatal(err) } mean, err := Mean(a) if err != nil { t.Fatal(err) } return []any{mean, v, s, med, q} }}, {"stats-correlation-regression", func(t *testing.T) []any { x := randA(t, 22, 200) ac, err := Autocorrelate(x, 16) if err != nil { t.Fatal(err) } pac, err := PartialAutocorrelate(x, 8) if err != nil { t.Fatal(err) } // The design carries its own intercept column. xd := x.RawFloats() design := make([]float64, 400) for i := range 200 { design[i*2] = 1 design[i*2+1] = xd[i] } lr, err := LinearRegression(mustA(t, design, 200, 2), randA(t, 23, 200)) if err != nil { t.Fatal(err) } return []any{ac, pac, lr.Coefficients, lr.StandardErrors, lr.PValues, lr.ResidualVariance, lr.RSquared} }}, {"stats-poisson-regression", func(t *testing.T) []any { // Counts from the seeded generator: one draw per row at the // mean the true coefficients produce. g := NewGenerator(24) xv := randA(t, 23, 120) design := make([]float64, 240) y := make([]float64, 120) for i := range 120 { design[i*2] = 1 design[i*2+1] = xv.FloatAt(i) counts, err := PoissonDraws(g, 1, math.Exp(0.3+0.7*xv.FloatAt(i))) if err != nil { t.Fatal(err) } y[i] = counts.FloatAt(0) } res, err := PoissonRegression(mustA(t, design, 120, 2), mustA(t, y, 120)) if err != nil { t.Fatal(err) } return []any{res.Coefficients, res.StandardErrors, res.PValues, res.Fitted, res.LogLikelihood, res.Iterations} }}, {"stats-distributions", func(t *testing.T) []any { tt, df, p, err := WelchTTest(randA(t, 24, 50), randA(t, 25, 60)) if err != nil { t.Fatal(err) } gc, err := GammaCDF(2.5, 3, 1.5) if err != nil { t.Fatal(err) } ec, err := ExponentialCDF(1.25, 2) if err != nil { t.Fatal(err) } sc, err := StudentTCDF(1.5, 7) if err != nil { t.Fatal(err) } pc, err := PoissonCDF(3, 2.5) if err != nil { t.Fatal(err) } bc, err := BinomialCDF(4, 10, 0.35) if err != nil { t.Fatal(err) } nq, err := NormalQuantile(0.975) if err != nil { t.Fatal(err) } return []any{NormalCDF(1.96), tt, df, p, gc, ec, sc, pc, bc, nq} }}, {"integrate-quadrature-ode", func(t *testing.T) []any { q, qerr, err := IntegrateFunction(func(x float64) (float64, error) { return math.Exp(-x * x), nil }, 0, 1, QuadratureOptions{}) if err != nil { t.Fatal(err) } decay := func(t float64, y *Array) (*Array, error) { return MulF(y, -1), nil } y0 := mustA(t, []float64{1}, 1) end, err := IntegrateODE(decay, 0, 2, y0, ODEOptions{MaxSteps: 10000}) if err != nil { t.Fatal(err) } nd, err := IntegrateND(func(x []float64) float64 { return math.Exp(-x[0] - x[1]*x[1]) }, []float64{0, 0}, []float64{1, 1}, CubatureOptions{}) if err != nil { t.Fatal(err) } heat, err := IntegrateHeat1D(mustA(t, []float64{1, 2, 3, 4, 5, 6, 7, 8}, 8), 0.1, 0.1, 0.05, 0.005, 3, 0, 0) if err != nil { t.Fatal(err) } return []any{q, qerr, end, nd, heat} }}, {"optim-roots-minima", func(t *testing.T) []any { root, err := FindRoot(func(x float64) float64 { return math.Cos(x) - x }, 0, 1, 1e-12) if err != nil { t.Fatal(err) } rosen := func(p *Array) (float64, error) { x := p.FloatAt(0) y := p.FloatAt(1) return (1-x)*(1-x) + 100*(y-x*x)*(y-x*x), nil } pt, val, err := Minimise(rosen, mustA(t, []float64{-1.2, 1}, 2), MinimiseOptions{MaxIterations: 500, Tolerance: 1e-12}) if err != nil { t.Fatal(err) } return []any{root, pt, val} }}, {"optim-bounded-minima", func(t *testing.T) []any { // The bounded solver on the wall case: with x forced past 1.5 // the Rosenbrock neck at (1, 1) is infeasible and the minimum // sits at (1.5, 2.25) with value 0.25, the first coordinate // pinned by the projection and released never. rosen := func(p *Array) (float64, error) { x := p.FloatAt(0) y := p.FloatAt(1) return (1-x)*(1-x) + 100*(y-x*x)*(y-x*x), nil } pt, val, err := MinimiseLBFGS(rosen, nil, mustA(t, []float64{-1.2, 1}, 2), LBFGSOptions{Tolerance: 1e-10, Lower: []float64{1.5, math.Inf(-1)}}) if err != nil { t.Fatal(err) } refused := false _, _, err = MinimiseLBFGS(rosen, nil, mustA(t, []float64{0, 0}, 2), LBFGSOptions{Lower: []float64{2}, Upper: []float64{1}}) if err != nil { refused = true } return []any{pt, val, refused} }}, {"optim-constrained-minima", func(t *testing.T) []any { // The augmented Lagrangian on an active inequality: the bowl // around (2, -1) cut by x + y ≤ 0 bottoms out on the wall at // (1.5, -1.5) with value 0.5. bowl := func(p *Array) (float64, error) { dx := p.FloatAt(0) - 2 dy := p.FloatAt(1) + 1 return dx*dx + dy*dy, nil } A := mustA(t, []float64{1, 1}, 1, 2) pt, val, err := MinimiseConstrained(bowl, nil, mustA(t, []float64{4, 4}, 2), LinearConstraints{A: A, Lower: []float64{math.Inf(-1)}, Upper: []float64{0}}, LBFGSOptions{Tolerance: 1e-10}) if err != nil { t.Fatal(err) } refused := false _, _, err = MinimiseConstrained(bowl, nil, mustA(t, []float64{0, 0}, 2), LinearConstraints{Lower: []float64{0}, Upper: []float64{1}}, LBFGSOptions{}) if err != nil { refused = true } return []any{pt, val, refused} }}, {"grad-backward", func(t *testing.T) []any { x := FromArray(mustA(t, []float64{1.5, -2, 3}, 3), true) loss, err := x.Mul(x) if err != nil { t.Fatal(err) } l, err := loss.Sum() if err != nil { t.Fatal(err) } if err := l.Backward(); err != nil { t.Fatal(err) } return []any{x.Grad()} }}, {"io-roundtrips", func(t *testing.T) []any { dir := t.TempDir() a := randA(t, 26, 24) m := mustA(t, a.RawFloats(), 4, 6) fitsPath := filepath.Join(dir, "o.fits") if err := SaveFITS(fitsPath, m, map[string]string{"OBJECT": "oracle"}); err != nil { t.Fatal(err) } backFits, hdr, err := LoadFITS(fitsPath) if err != nil { t.Fatal(err) } ncPath := filepath.Join(dir, "o.nc") dims := []NetCDFDim{{Name: "row", Length: 4}, {Name: "col", Length: 6}} vars := []NetCDFVar{{Name: "field", Dims: []string{"row", "col"}, Values: m}} if err := SaveNetCDF(ncPath, dims, vars, map[string]string{"title": "oracle"}); err != nil { t.Fatal(err) } _, backNc, ncAttrs, err := LoadNetCDF(ncPath) if err != nil { t.Fatal(err) } return []any{backFits, hdr["OBJECT"], backNc[0].Values, ncAttrs["title"]} }}, {"core-views-and-int-precision", func(t *testing.T) []any { // Views, the integer range above 2^53 and a widened query // array: the 2026-09 review found defects in all three. x := randA(t, 41, 12) view, err := Slice(x, 0, 3, 9) if err != nil { t.Fatal(err) } pow, err := PowI(view, 3) if err != nil { t.Fatal(err) } big, err := FromInts([]int64{1 << 53, 1<<53 + 1, -(1 << 53)}, 3) if err != nil { t.Fatal(err) } hi, err := ArgMax(big) if err != nil { t.Fatal(err) } lo, err := ArgMin(big) if err != nil { t.Fatal(err) } // A float32 view whose payload is longer than its extent: the // widening inside Interpolate2D used to walk the payload. xs, err := FromFloat32s(make([]float32, x.Len()), x.Len()) if err != nil { t.Fatal(err) } for i := range xs.Len() { // Stay inside the (3, 4) grid's closed domain. xs.SetFloatAt(i, float64(i%4)) } viewXs, err := Slice(xs, 0, 0, view.Len()) if err != nil { t.Fatal(err) } grid, err := FromFloats(make([]float64, 12), 3, 4) if err != nil { t.Fatal(err) } // The y queries need their own range: the grid's y domain is // [0, rows−1], narrower than x's. ys, err := FromFloat32s(make([]float32, viewXs.Len()), viewXs.Len()) if err != nil { t.Fatal(err) } for i := range ys.Len() { ys.SetFloatAt(i, float64(i%3)) } interp, err := Interpolate2D(grid, viewXs, ys, 0, 0, 1, 1) if err != nil { t.Fatal(err) } return []any{pow, hi, lo, interp} }}, {"io-hdf5-fixture", func(t *testing.T) []any { // The HDF5 reference-library fixture: contiguous ints, a chunked // deflate+shuffle float vector, a float32 matrix in a group, // and attributes inherited from the groups. sets, err := LoadHDF5(filepath.Join("io", "testdata", "h5", "fixture.h5")) if err != nil { t.Fatal(err) } out := []any{} for _, d := range sets { out = append(out, d.Path, d.Values) for _, k := range slices.Sorted(maps.Keys(d.Attrs)) { out = append(out, k, d.Attrs[k]) } } return out }}, {"io-hostile-inputs", func(t *testing.T) []any { // A header that lies about its sizes must be refused, never // allocated and never panicked over: both files here are a few // dozen bytes and claim data no file could hold. dir := t.TempDir() ncPath := filepath.Join(dir, "hostile.nc") if err := os.WriteFile(ncPath, hostileOracleHeader(), 0o644); err != nil { t.Fatal(err) } _, _, _, ncErr := LoadNetCDF(ncPath) fitsPath := filepath.Join(dir, "hostile.fits") if err := os.WriteFile(fitsPath, hostileOracleTable(), 0o644); err != nil { t.Fatal(err) } _, fitsErr := LoadFITSTable(fitsPath) return []any{ncErr != nil, fitsErr != nil} }}, {"core-float16", func(t *testing.T) []any { // The half dtype end to end: narrowing of values that straddle // the format's corners, arithmetic through the promotion // ladder, ordering that must widen before it compares. vals := []float64{1, -2.5, 0.25, 65504, -65504, 1.0 / 16384, 1.0 / 16777216, 0.1, 2048.5} h, err := FromFloat16s(vals, len(vals)) if err != nil { t.Fatal(err) } s := Sum(h) sorted, err := Sort(h) if err != nil { t.Fatal(err) } prod := MulF(h, 2) widened, err := Add(h, mustA(t, make([]float64, len(vals)), len(vals))) if err != nil { t.Fatal(err) } ints, err := Astype(h, Int) if err != nil { t.Fatal(err) } return []any{h, s, sorted, prod, widened, ints, HalfToFloat64(HalfFromFloat64(0.1)), HalfToFloat64(0x7BFF), HalfToFloat64(0x0001), HalfFromFloat64(65520) == 0x7C00, HalfFromFloat64(-1.0/33554432.0) == 0x8000} }}, {"signal-kalman-arma", func(t *testing.T) []any { // The linear filter on a scalar random walk with noisy // measurements from the seeded generator, the unscented filter // over the same exactly linear model, and the AR fit with its // theoretical spectrum. g := NewGenerator(50) z, err := Floats(g, 40) if err != nil { t.Fatal(err) } one := mustA(t, []float64{1}, 1, 1) qv := mustA(t, []float64{0.01}, 1, 1) rv := mustA(t, []float64{1}, 1, 1) zero := mustA(t, []float64{0}, 1) pv := mustA(t, []float64{1}, 1, 1) res, err := KalmanFilter(z, one, one, KalmanOptions{ InitialState: zero, InitialCovariance: pv, ProcessNoise: qv, MeasurementNoise: rv}) if err != nil { t.Fatal(err) } uk, err := UnscentedKalmanFilter(z, func(x *Array) (*Array, error) { return MulF(x, 1), nil }, func(x *Array) (*Array, error) { return MulF(x, 1), nil }, KalmanOptions{ InitialState: zero, InitialCovariance: pv, ProcessNoise: qv, MeasurementNoise: rv}) if err != nil { t.Fatal(err) } x, err := Floats(NewGenerator(51), 300) if err != nil { t.Fatal(err) } ar, err := EstimateAR(x, 2) if err != nil { t.Fatal(err) } freqs, psd, err := ARMASpectrum(ar, 32) if err != nil { t.Fatal(err) } return []any{res.States, res.Covariances, res.Innovations, res.LogLikelihood, uk.LogLikelihood, uk.States, ar.AR, ar.InnovationVariance, ar.AIC, freqs, psd} }}, {"signal-windows-filtfilt-dwt", func(t *testing.T) []any { // The window catalogue, the zero-phase filter, the 2-D median // and the Daubechies transform over seeded inputs. hann, err := WindowHann(16, false) if err != nil { t.Fatal(err) } kaiser, err := WindowKaiser(16, 4.5, true) if err != nil { t.Fatal(err) } x := randA(t, 52, 128) b, a, err := ButterworthLowPass(3, 100, 20) if err != nil { t.Fatal(err) } ff, err := Filtfilt(b, a, x) if err != nil { t.Fatal(err) } img := mustA(t, randA(t, 53, 64).RawFloats(), 8, 8) med, err := MedianFilter2D(img, 3) if err != nil { t.Fatal(err) } coef, err := DaubechiesDWT(x, DB4, 2, DWTPeriodic) if err != nil { t.Fatal(err) } back, err := DaubechiesIDWT(coef, DB4, 2, DWTPeriodic) if err != nil { t.Fatal(err) } return []any{hann, kaiser, ff, med, coef, back} }}, {"stats-distributions2-multipletest", func(t *testing.T) []any { // The second-league distributions and the corrections, on // fixed parameters and the classic Benjamini-Hochberg vector. wc, err := WeibullCDF(1.5, 2, 3) if err != nil { t.Fatal(err) } wq, err := WeibullQuantile(0.4, 2, 3) if err != nil { t.Fatal(err) } lc, err := LognormalCDF(1, 0, 0.5) if err != nil { t.Fatal(err) } pq, err := ParetoQuantile(0.5, 1, 3) if err != nil { t.Fatal(err) } nb, err := NegativeBinomialCDF(5, 3, 0.4) if err != nil { t.Fatal(err) } ncx, err := NoncentralChiSquareCDF(9, 4, 2.5) if err != nil { t.Fatal(err) } nct, err := NoncentralTCDF(2, 8, 3) if err != nil { t.Fatal(err) } ncf, err := NoncentralFQuantile(0.5, 4, 10, 2) if err != nil { t.Fatal(err) } draws, err := DirichletDraws(NewGenerator(54), 12, []float64{2, 3, 4}) if err != nil { t.Fatal(err) } px := randA(t, 55, 100) py := randA(t, 56, 100) rho, err := SpearmanRho(px, py) if err != nil { t.Fatal(err) } tau, err := KendallTau(px, py) if err != nil { t.Fatal(err) } p := []float64{0.001, 0.008, 0.039, 0.041, 0.042, 0.06, 0.074, 0.205, 0.212, 0.216, 0.222, 0.251, 0.269, 0.275, 0.34, 0.341, 0.384, 0.456, 0.657, 0.876} bonf, err := Bonferroni(p) if err != nil { t.Fatal(err) } holm, err := Holm(p) if err != nil { t.Fatal(err) } bh, err := BenjaminiHochberg(p) if err != nil { t.Fatal(err) } return []any{wc, wq, lc, pq, nb, ncx, nct, ncf, draws, rho, tau, bonf, holm, bh} }}, {"stats-regression2", func(t *testing.T) []any { // The regularised, robust and quantile fits on one seeded // design, with one gross outlier the robust fit must survive. g := NewGenerator(57) xv, err := Floats(g, 60) if err != nil { t.Fatal(err) } n := xv.Len() design := make([]float64, 0, 2*n) y := make([]float64, n) for i := range n { design = append(design, 1, xv.FloatAt(i)) y[i] = 1 + 2*xv.FloatAt(i) + 0.3*(float64(i%7)-3) } y[7] += 100 dArr := mustA(t, design, n, 2) yArr := mustA(t, y, n) xOnly := make([]float64, n) for i := range n { xOnly[i] = xv.FloatAt(i) } xArr := mustA(t, xOnly, n, 1) lasso, err := Lasso(xArr, yArr, 0.05) if err != nil { t.Fatal(err) } en, err := ElasticNet(xArr, yArr, 0.05, 0.5) if err != nil { t.Fatal(err) } huber, err := HuberRegression(dArr, yArr) if err != nil { t.Fatal(err) } si, sl, err := TheilSenRegression(xv, yArr) if err != nil { t.Fatal(err) } qr, err := QuantileRegression(dArr, yArr, 0.75) if err != nil { t.Fatal(err) } return []any{lasso.Intercept, lasso.Coefficients, lasso.Iterations, en.Coefficients, huber.Coefficients, huber.Scale, huber.Iterations, si, sl, qr.Coefficients, qr.Objective} }}, {"stats-unsupervised", func(t *testing.T) []any { // PCA over a seeded cloud, k-means over two blobs, the mixture // over a univariate draw and the Gaussian-process posterior. g := NewGenerator(58) a1, err := Normal(g, 48, 0, 1) if err != nil { t.Fatal(err) } a2, err := Normal(g, 48, 0, 1) if err != nil { t.Fatal(err) } a3, err := Normal(g, 48, 0, 1) if err != nil { t.Fatal(err) } cloud := make([]float64, 144) for i := range 48 { cloud[3*i] = 3 * a1.FloatAt(i) cloud[3*i+1] = a2.FloatAt(i) cloud[3*i+2] = 0.1 * a3.FloatAt(i) } pca, err := PCA(mustA(t, cloud, 48, 3)) if err != nil { t.Fatal(err) } bg := NewGenerator(59) b1, err := Normal(bg, 40, 0, 1) if err != nil { t.Fatal(err) } b2, err := Normal(bg, 40, 0, 1) if err != nil { t.Fatal(err) } b3, err := Normal(bg, 40, 8, 1) if err != nil { t.Fatal(err) } b4, err := Normal(bg, 40, 8, 1) if err != nil { t.Fatal(err) } blobs := make([]float64, 160) for i := range 40 { blobs[2*i] = b1.FloatAt(i) blobs[2*i+1] = b2.FloatAt(i) blobs[40+2*i] = b3.FloatAt(i) blobs[40+2*i+1] = b4.FloatAt(i) } km, err := KMeans(NewGenerator(60), mustA(t, blobs, 80, 2), 2) if err != nil { t.Fatal(err) } centres := make([]float64, 0, 4) for _, c := range km.Centres { centres = append(centres, c...) } mg := NewGenerator(61) hi, err := Normal(mg, 40, 6, 1) if err != nil { t.Fatal(err) } lo, err := Normal(mg, 40, 0, 1) if err != nil { t.Fatal(err) } mix := make([]float64, 80) for i := range 40 { mix[2*i] = hi.FloatAt(i) mix[2*i+1] = lo.FloatAt(i) } gmm, err := GaussianMixture(NewGenerator(62), mustA(t, mix, 80, 1), 2) if err != nil { t.Fatal(err) } means := make([]float64, 0, len(gmm.Means)) for _, m := range gmm.Means { means = append(means, m...) } trainX := mustA(t, randA(t, 63, 16).RawFloats(), 16, 1) sinVals, err := Sin(trainX) if err != nil { t.Fatal(err) } trainY, err := Reshape(sinVals, 16) if err != nil { t.Fatal(err) } testX := mustA(t, randA(t, 64, 8).RawFloats(), 8, 1) kern, err := SquaredExponentialKernel(1) if err != nil { t.Fatal(err) } gp, err := GaussianProcessRegression(kern, trainX, trainY, 0.05, testX) if err != nil { t.Fatal(err) } mll, err := MarginalLogLikelihood(kern, trainX, trainY, 0.05) if err != nil { t.Fatal(err) } return []any{pca.Loadings, pca.ExplainedVarianceRatio, float64(km.Iterations), centres, km.Inertia, gmm.Weights, means, gmm.BIC, gp.Mean, gp.Variance, mll} }}, {"stats-contingency", func(t *testing.T) []any { // The exact and the asymptotic table tests over fixed tables, // every alternative, and the effect sizes beside them. out := []any{} tables := [][]float64{ {12, 5, 7, 10}, {8, 2, 1, 5}, {17, 0, 0, 23}, {21, 8, 3, 9, 15, 11, 4, 12, 30}, } for ti, tab := range tables[:3] { a, _, err := FisherExactTest(mustA(t, tab, 2, 2), TwoSided) if err != nil { t.Fatal(err) } less, _, err := FisherExactTest(mustA(t, tab, 2, 2), Less) if err != nil { t.Fatal(err) } greater, or, err := FisherExactTest(mustA(t, tab, 2, 2), Greater) if err != nil { t.Fatal(err) } out = append(out, a, less, greater, or) p, err := McNemarTest(mustA(t, tab, 2, 2)) if err != nil { t.Fatal(err) } out = append(out, p) if ti < 2 { v, err := CramersV(mustA(t, tab, 2, 2)) if err != nil { t.Fatal(err) } out = append(out, v) } } chi2, df, p, err := ChiSquareIndependence(mustA(t, tables[3], 3, 3)) if err != nil { t.Fatal(err) } v, err := CramersV(mustA(t, tables[3], 3, 3)) if err != nil { t.Fatal(err) } out = append(out, chi2, df, p, v) return out }}, {"stats-mixedmodel", func(t *testing.T) []any { // A balanced random-intercept fit and a random-slope fit, over // formula-driven data no generator touches. const groups8 = 8 const per = 6 y := make([]float64, 0, groups8*per) labels := make([]int, 0, groups8*per) for g := range groups8 { effect := 2 * math.Sin(1.7*float64(g)+0.4) for i := range per { y = append(y, 5+effect+wobble(g*per+i)) labels = append(labels, g) } } ones := make([]float64, len(y)) for i := range ones { ones[i] = 1 } res, err := LinearMixedModel(mustA(t, y, len(y)), mustA(t, ones, len(y), 1), mustA(t, ones, len(y), 1), labels) if err != nil { t.Fatal(err) } out := []any{res.Coefficients, res.StandardErrors, res.RandomEffects[0], res.RandomEffects[7], res.RandomCovariance, res.ResidualVariance, res.LogLikelihood, res.Converged, fmt.Sprintf("%v", res.GroupLabels)} // The slope fit: the random design carries the covariate // alone, the identified configuration. slopes := []float64{0.9, -1.1, 1.9, -0.3, -1.8, 0.4} sy := make([]float64, 0, len(slopes)*per) sx := make([]float64, 0, 2*len(slopes)*per) sz := make([]float64, 0, len(slopes)*per) slabels := make([]int, 0, len(slopes)*per) jitter := make([]float64, 0, len(slopes)*per) for g := range slopes { for _, x := range []float64{-1, -0.6, -0.2, 0.2, 0.6, 1} { jitter = append(jitter, wobble(len(jitter)+13)*0.1) slabels = append(slabels, g) sz = append(sz, x) } } mean := 0.0 for _, j := range jitter { mean += j } mean /= float64(len(jitter)) for g, s := range slopes { for k := range per { i := g*per + k x := sz[i] sy = append(sy, 1+2*x+0.5*s*x+0.1*(jitter[i]-mean)) sx = append(sx, 1, x) } } slope, err := LinearMixedModel(mustA(t, sy, len(sy)), mustA(t, sx, len(sy), 2), mustA(t, sz, len(sz), 1), slabels) if err != nil { t.Fatal(err) } return append(out, slope.Coefficients, slope.RandomCovariance, slope.ResidualVariance, slope.Converged) }}, {"stats-hmm", func(t *testing.T) []any { // The scaled recursions, the decode and the Baum-Welch fit on // a fixed sequence under a fixed model. model, err := NewHiddenMarkovModel([]float64{0.6, 0.4}, []float64{0.7, 0.3, 0.2, 0.8}, []float64{0.9, 0.1, 0.25, 0.75}) if err != nil { t.Fatal(err) } observations := []int{0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0} filtered, ll, err := model.Forward(observations) if err != nil { t.Fatal(err) } smoothed, sll, err := model.Smooth(observations) if err != nil { t.Fatal(err) } path, pathProb, err := model.Viterbi(observations) if err != nil { t.Fatal(err) } out := []any{filtered[len(observations)-1], smoothed[0], ll, sll, fmt.Sprintf("%v", path), pathProb} seq := make([]int, 240) for i := range seq { // The wiggle stays inside ±0.4, so the shifted scale is // positive and the modulo lands inside the symbol set. seq[i] = int(wobble(i)*100+200) % 3 } fit, err := FitHiddenMarkovModel(NewGenerator(77), seq, 2, 3) if err != nil { t.Fatal(err) } return append(out, fit.Model.Initial, fit.Model.Transition, fit.Model.Emission, fit.LogLikelihood, fit.Converged) }}, {"stats-hierarchy", func(t *testing.T) []any { // The five linkages over one fixed two-column sample, with the // cuts the dendrogram answers. sample := make([]float64, 24) for i := range 12 { sample[2*i] = wobble(2*i+5)*3 + float64(i%4) sample[2*i+1] = wobble(2*i+31) * 2 } out := []any{} for _, method := range []Linkage{SingleLinkage, CompleteLinkage, AverageLinkage, CentroidLinkage, WardLinkage} { d, err := HierarchicalClustering(mustA(t, sample, 12, 2), method) if err != nil { t.Fatal(err) } labels, err := d.Cut(3) if err != nil { t.Fatal(err) } out = append(out, d.Heights, fmt.Sprintf("%v", labels), d.Sizes[10]) } first, err := HierarchicalClustering(mustA(t, sample, 12, 2), WardLinkage) if err != nil { t.Fatal(err) } byHeight, err := first.CutHeight(first.Heights[8]) if err != nil { t.Fatal(err) } return append(out, fmt.Sprintf("%v", byHeight)) }}, {"integrate-stiff-solvers", func(t *testing.T) []any { // The stiff batch on one decay problem, the index-1 DAE on its // circuit, the collocation on a linear two-point problem, the // symplectic pair and the advection pair. decay := func(t float64, y *Array) (*Array, error) { return MulF(y, -1), nil } y0 := mustA(t, []float64{1}, 1) stats := &BDFVarStats{} bdf, err := IntegrateBDFVar(decay, 0, 2, y0, BDFVarOptions{MaxSteps: 10000, Stats: stats}) if err != nil { t.Fatal(err) } ros, err := IntegrateROS4(decay, 0, 2, y0, ODEOptions{MaxSteps: 10000}) if err != nil { t.Fatal(err) } daeRHS := func(t float64, y *Array) (*Array, error) { out, err := Zeros(Float, 2) if err != nil { return nil, err } out.SetFloatAt(0, 1-y.FloatAt(0)) out.SetFloatAt(1, y.FloatAt(1)-y.FloatAt(0)) return out, nil } mass, err := FromFloats([]float64{1, 0, 0, 0}, 2, 2) if err != nil { t.Fatal(err) } dae, err := IntegrateDAE(daeRHS, mass, 0, 1, mustA(t, []float64{0, 0}, 2), 50, DAEOptions{}) if err != nil { t.Fatal(err) } colRHS := func(t float64, y *Array) (*Array, error) { out, err := Zeros(Float, 2) if err != nil { return nil, err } out.SetFloatAt(0, y.FloatAt(1)) return out, nil } col, err := SolveBoundaryCollocation(colRHS, 0, 1, mustA(t, []float64{0, 0}, 2), BoundaryConditions{Start: []int{0}, End: []int{0}, EndValues: []float64{1}}, CollocationOptions{}) if err != nil { t.Fatal(err) } accel := func(q *Array) (*Array, error) { return MulF(q, -1), nil } positions, momenta, err := IntegrateYoshida4(accel, 0, 6.283185307179586, mustA(t, []float64{1}, 1), mustA(t, []float64{0}, 1), 200) if err != nil { t.Fatal(err) } gradH := func(z *Array) (*Array, error) { out, err := Zeros(Float, 2) if err != nil { return nil, err } out.SetFloatAt(0, z.FloatAt(1)) out.SetFloatAt(1, z.FloatAt(0)) return out, nil } mids, _, err := IntegrateMidpoint(gradH, 0, 1, mustA(t, []float64{1}, 1), mustA(t, []float64{1}, 1), 32, MidpointOptions{}) if err != nil { t.Fatal(err) } n := 64 dx := 1.0 / 65 pulse := make([]float64, n) for i := range n { c := (float64(i) + 0.5) * dx if c >= 0.3 && c <= 0.6 { pulse[i] = 1 } } upwind, err := IntegrateUpwindAdvection1D(mustA(t, pulse, n), 1, dx, 0.2, 0.9*dx, 2, 0, 0) if err != nil { t.Fatal(err) } koren, err := IntegrateAdvection1D(mustA(t, pulse, n), 1, dx, 0.2, 0.9*dx, 2, 0, 0) if err != nil { t.Fatal(err) } return []any{bdf, float64(stats.MaxOrder), ros, dae, col.Values[len(col.Values)-1], float64(len(col.Mesh)), positions[len(positions)-1], momenta[len(momenta)-1], mids[len(mids)-1], upwind, koren} }}, {"integrate-fem3d", func(t *testing.T) []any { // The tetrahedral Poisson assembly on the unit box with the // manufactured sin(πx)·sin(πy)·sin(πz) solution. mesh, err := BoxTetraMesh3D(0, 0, 0, 1, 1, 1, 4, 4, 4) if err != nil { t.Fatal(err) } src := func(x, y, z float64) float64 { return 3 * math.Pi * math.Pi * math.Sin(math.Pi*x) * math.Sin(math.Pi*y) * math.Sin(math.Pi*z) } var bound []int var vals []float64 for i := range mesh.Vertices3() { x, y, z := mesh.Vertices[3*i], mesh.Vertices[3*i+1], mesh.Vertices[3*i+2] if x == 0 || x == 1 || y == 0 || y == 1 || z == 0 || z == 1 { bound = append(bound, i) vals = append(vals, 0) } } u, err := SolvePoissonFEM3D(mesh, src, FEMPoisson3DOptions{ Kappa: 1, DirichletNodes: bound, DirichletValues: vals, Ordering: SparseOrderingReverseCuthillMcKee}) if err != nil { t.Fatal(err) } return []any{u.FloatAt(u.Len() / 2), u.FloatAt(u.Len() - 1), u.FloatAt(7)} }}, {"linalg-sparse-lsqr-rrqr-update", func(t *testing.T) []any { // Sparse least squares against a consistent right-hand side, // the pivoted QR on a seeded matrix and the sparse rank-one // round trip on a banded factor. g := NewGenerator(65) const m, n = 12, 8 var idx []int64 var vals []float64 for i := range m { idx = append(idx, int64(i), int64(i%(n))) vals = append(vals, 2+g.Unit()) if i+1 < m && i%(n)+1 < n { idx = append(idx, int64(i), int64(i%n+1)) vals = append(vals, -0.5-0.5*g.Unit()) } } indices, err := FromInts(idx, len(vals), 2) if err != nil { t.Fatal(err) } valArr, err := FloatsFromArray(vals, len(vals)) if err != nil { t.Fatal(err) } coo, err := NewSparseCOO(indices, valArr, []int{m, n}) if err != nil { t.Fatal(err) } csr, err := CSRFromCOO(coo) if err != nil { t.Fatal(err) } xTrue := New(Float, n) for i := range n { xTrue.RawFloats()[i] = float64(i%5) - 2 + 0.25*float64(i%3) } b, err := csr.MatVec(xTrue) if err != nil { t.Fatal(err) } xl, infoL, err := SpLSQR(coo, b, 1e-12, 300, 0) if err != nil { t.Fatal(err) } xm, infoM, err := SpLSMR(coo, b, 1e-12, 300, 0) if err != nil { t.Fatal(err) } dm := mustA(t, randA(t, 66, 60).RawFloats(), 10, 6) q, r, perm, rank, err := RRQR(dm) if err != nil { t.Fatal(err) } permF := make([]float64, len(perm)) for i, p := range perm { permF[i] = float64(p) } b6 := randA(t, 67, 10) xr, err := SolveRRQR(dm, b6) if err != nil { t.Fatal(err) } const bn = 30 var bIdx []int64 var bVals []float64 for i := range bn { bIdx = append(bIdx, int64(i), int64(i)) bVals = append(bVals, 4) if i+1 < bn { bIdx = append(bIdx, int64(i), int64(i+1)) bVals = append(bVals, -1) bIdx = append(bIdx, int64(i+1), int64(i)) bVals = append(bVals, -1) } } bIndices, err := FromInts(bIdx, len(bVals), 2) if err != nil { t.Fatal(err) } bValArr, err := FloatsFromArray(bVals, len(bVals)) if err != nil { t.Fatal(err) } bCoo, err := NewSparseCOO(bIndices, bValArr, []int{bn, bn}) if err != nil { t.Fatal(err) } factor, err := NewSparseCholesky(bCoo, SparseOrderingNatural) if err != nil { t.Fatal(err) } bv := New(Float, bn) for i := range bn { bv.RawFloats()[i] = float64(i%7) - 3 } before, err := factor.Solve(bv) if err != nil { t.Fatal(err) } upd := New(Float, bn) upd.RawFloats()[7] = 2 if err := factor.Update(upd); err != nil { t.Fatal(err) } after, err := factor.Solve(bv) if err != nil { t.Fatal(err) } if err := factor.Downdate(upd); err != nil { t.Fatal(err) } restored, err := factor.Solve(bv) if err != nil { t.Fatal(err) } return []any{xl, infoL.Criterion, infoL.ResidualNorm, float64(infoL.Iterations), xm, infoM.Criterion, q, r, permF, float64(rank), xr, before, after, restored} }}, {"optim-lp-qp-global2", func(t *testing.T) []any { // The simplex through the two-sided rows, the active-set QP on // an active wall, the seeded global pair on one rotated bowl, // the nonlinear equality and the scalar bracket. a := mustA(t, []float64{1, 1, 1, 0}, 2, 2) xLP, vLP, err := MinimiseLinearRows(mustA(t, []float64{1, 1}, 2), LinearConstraints{A: a, Lower: []float64{2, math.Inf(-1)}, Upper: []float64{math.Inf(1), 3}}, LinearProgramOptions{}) if err != nil { t.Fatal(err) } h := mustA(t, []float64{2, 0, 0, 2}, 2, 2) xQP, vQP, multQP, err := MinimiseQP(h, mustA(t, []float64{-2, -4}, 2), LinearConstraints{A: mustA(t, []float64{1, 0}, 1, 2), Lower: []float64{math.Inf(-1)}, Upper: []float64{1}}, nil, QPOptions{}) if err != nil { t.Fatal(err) } cmaF := func(p *Array) (float64, error) { var s float64 w := []float64{4, 3, 2, 1} for i := range 4 { di := p.FloatAt(i) - float64(i+1) s += w[i] * di * di if i+1 < 4 { s += 0.5 * di * (p.FloatAt(i+1) - float64(i+2)) } } return s, nil } xCMA, vCMA, err := MinimiseCMAES(cmaF, mustA(t, []float64{2, -2, 1, -1}, 4), CMAESOptions{Sigma0: 0.5, Generations: 300, Tolerance: 1e-10, Seed: 7}) if err != nil { t.Fatal(err) } xSA, vSA, err := MinimiseSimulatedAnnealing(cmaF, mustA(t, []float64{2, -2, 1, -1}, 4), SimulatedAnnealingOptions{Steps: 20000, Tolerance: 1e-6, Seed: 42, AllowBudgetExit: true}) if err != nil { t.Fatal(err) } xNL, vNL, multNL, err := MinimiseNonlinearConstrained( func(p *Array) (float64, error) { return p.FloatAt(0), nil }, nil, mustA(t, []float64{0.5, 0.5}, 2), NonlinearConstraints{Equalities: []func(*Array) (float64, error){ func(p *Array) (float64, error) { x, y := p.FloatAt(0), p.FloatAt(1) return x*x + y*y - 1, nil }, }}, LBFGSOptions{}) if err != nil { t.Fatal(err) } root, err := FindRootBrent(func(x float64) float64 { return math.Cos(x) - x }, -10, 10, BrentOptions{}) if err != nil { t.Fatal(err) } broydenRHS := func(x *Array) (*Array, error) { out, err := Zeros(Float, 2) if err != nil { return nil, err } xf, yf := x.FloatAt(0), x.FloatAt(1) out.SetFloatAt(0, xf*xf+yf*yf-1) out.SetFloatAt(1, xf-yf) return out, nil } xBr, resBr, err := FindRootSystem(broydenRHS, mustA(t, []float64{2, 0.5}, 2), RootSystemOptions{UseBroyden: true}) if err != nil { t.Fatal(err) } return []any{xLP, vLP, xQP, vQP, multQP, xCMA, vCMA, xSA, vSA, xNL, vNL, multNL, root, xBr, resBr} }}, {"io-hdf5-write", func(t *testing.T) []any { // The writer round trip: chunked, shuffled, deflated floats, a // float32 matrix, wide integers, a nested group and attributes, // read back through the unchanged reader in both superblocks. dir := t.TempDir() f64 := randA(t, 68, 32) f32, err := FromFloat32s([]float32{1.5, -2.5, 3.25, 4, 5, 6}, 2, 3) if err != nil { t.Fatal(err) } wide, err := FromInts([]int64{5, -3, 1 << 40}, 3) if err != nil { t.Fatal(err) } nested, err := FromFloats([]float64{1, 2, 3, 4}, 2, 2) if err != nil { t.Fatal(err) } sets := []HDF5Dataset{ {Path: "/signals/main", Shape: f64.Shape(), Values: f64, Attrs: map[string]string{"units": "m"}}, {Path: "/image", Shape: f32.Shape(), Values: f32}, {Path: "/wide", Shape: wide.Shape(), Values: wide}, {Path: "/g/sub/deep", Shape: nested.Shape(), Values: nested}, } attrs := map[string]map[string]string{"/": {"title": "oracle"}, "/g": {"note": "middle"}} classic := filepath.Join(dir, "classic.h5") if err := SaveHDF5(classic, sets, attrs, HDF5WriteOptions{Gzip: 6, Shuffle: true}); err != nil { t.Fatal(err) } back, err := LoadHDF5(classic) if err != nil { t.Fatal(err) } out := []any{} for _, d := range back { out = append(out, d.Path, d.Values) for _, k := range slices.Sorted(maps.Keys(d.Attrs)) { out = append(out, k, d.Attrs[k]) } } latest := filepath.Join(dir, "latest.h5") if err := SaveHDF5(latest, sets, attrs, HDF5WriteOptions{Latest: true}); err != nil { t.Fatal(err) } backLatest, err := LoadHDF5(latest) if err != nil { t.Fatal(err) } out = append(out, len(backLatest) == len(back)) for _, d := range backLatest { if d.Path == "/signals/main" { out = append(out, d.Values) } } return out }}, {"io-hdf5-narrow-write-roundtrip", func(t *testing.T) []any { // The seven narrow dtypes through the writer and back, the // values at each dtype's extremes: bool through the boolean // enumeration convention, every integer at its stored width and // signedness. The same sets are written contiguous, in the // latest layout and chunked with shuffle and deflate, and every // read-back must land the written dtype and values. dir := t.TempDir() sets := []HDF5Dataset{} must := func(values *Array, err error) *Array { if err != nil { t.Fatal(err) } return values } put := func(path string, values *Array) { sets = append(sets, HDF5Dataset{Path: path, Shape: values.Shape(), Values: values}) } put("/bool", must(FromBools([]bool{false, true, true, false}, 2, 2))) put("/i8", must(FromInt8s([]int8{-128, 127, 0, -1}, 2, 2))) put("/u8", must(FromUint8s([]uint8{0, 255, 7, 128}, 2, 2))) put("/i16", must(FromInt16s([]int16{-32768, 32767, 0, -2}, 2, 2))) put("/u16", must(FromUint16s([]uint16{0, 65535, 5, 32768}, 2, 2))) put("/i32", must(FromInt32s([]int32{-2147483648, 2147483647, 0, -3}, 2, 2))) put("/u32", must(FromUint32s([]uint32{0, 4294967295, 9, 2147483648}, 2, 2))) out := []any{} for _, c := range []struct { file string opts HDF5WriteOptions }{ {"contiguous.h5", HDF5WriteOptions{}}, {"latest.h5", HDF5WriteOptions{Latest: true}}, {"chunked.h5", HDF5WriteOptions{Gzip: 1, Shuffle: true, ChunkBytes: 8}}, } { path := filepath.Join(dir, c.file) if err := SaveHDF5(path, sets, nil, c.opts); err != nil { t.Fatal(err) } back, err := LoadHDF5(path) if err != nil { t.Fatal(err) } out = append(out, c.file) for _, d := range back { out = append(out, d.Path, d.Values) } } return out }}, {"io-hdf5-uint8-roundtrip", func(t *testing.T) []any { // A uint8 dataset through the HDF5 read path: the fixture pins // the reader's decode directly, hand-built in the classic // layout, and must land uint8 on the values below. The writer // path is covered by io-hdf5-narrow-write-roundtrip above, // which writes every narrow dtype and reads it back. path := filepath.Join(t.TempDir(), "u8.h5") file := oracleHDF5Narrow(oracleHDF5Fixed(1, false), []uint64{5}, []byte{0, 1, 200, 255, 42}) if err := os.WriteFile(path, file, 0o644); err != nil { t.Fatal(err) } sets, err := LoadHDF5(path) if err != nil { t.Fatal(err) } return []any{len(sets), sets[0].Path, sets[0].Values} }}, {"io-hdf5-int16-roundtrip", func(t *testing.T) []any { // An int16 dataset through the same hand-built fixture path: // the read-back must land int16 on the extremes below. path := filepath.Join(t.TempDir(), "i16.h5") file := oracleHDF5Narrow(oracleHDF5Fixed(2, true), []uint64{4}, []byte{0xfd, 0xff, 0x00, 0x80, 0xff, 0x7f, 0x07, 0x00}) if err := os.WriteFile(path, file, 0o644); err != nil { t.Fatal(err) } sets, err := LoadHDF5(path) if err != nil { t.Fatal(err) } return []any{len(sets), sets[0].Path, sets[0].Values} }}, {"io-hdf5-bool-roundtrip", func(t *testing.T) []any { // A boolean enumeration dataset, the convention HDF5 writers // carry booleans in: the read-back must land core.Bool. path := filepath.Join(t.TempDir(), "bool.h5") file := oracleHDF5Narrow(oracleHDF5EnumBool(), []uint64{3}, []byte{1, 0, 1}) if err := os.WriteFile(path, file, 0o644); err != nil { t.Fatal(err) } sets, err := LoadHDF5(path) if err != nil { t.Fatal(err) } return []any{len(sets), sets[0].Path, sets[0].Values} }}, {"io-netcdf-classic-natives", func(t *testing.T) []any { // A NetCDF classic file carrying byte, short, int, char, float // and double values, read natively. The NetCDF writer stores // float64, float32 and int64 only, so the fixture is written // here as classic-format bytes and the oracle pins the landings. path := filepath.Join(t.TempDir(), "natives.nc") if err := os.WriteFile(path, oracleNetCDFNatives(), 0o644); err != nil { t.Fatal(err) } _, vars, _, err := LoadNetCDF(path) if err != nil { t.Fatal(err) } out := []any{len(vars)} for _, v := range vars { out = append(out, v.Name, v.Values) } return out }}, {"optim-lm-fit", func(t *testing.T) []any { // The Levenberg-Marquardt fit through the Fit surface: an // exact exponential decay with a requested covariance, then a // diagonal-Sigma run whose first observation carries a quarter // of the variance, so the whitening moves the answer. The // digest pins the parameters, both chi2 values, the statuses // and the covariance. xs := []float64{0, 1, 2, 3, 4, 5, 6, 7} ys := make([]float64, len(xs)) for i, x := range xs { ys[i] = 2.5*math.Exp(-0.7*float64(x)) + 0.3 } residual := func(p *Array) (*Array, error) { out := New(Float, len(xs)) for i := range len(xs) { out.RawFloats()[i] = ys[i] - (p.FloatAt(0)*math.Exp(-p.FloatAt(1)*float64(xs[i])) + p.FloatAt(2)) } return out, nil } p0, err := FromFloats([]float64{2, 0.5, 0.1}, 3) if err != nil { t.Fatal(err) } res, err := LevenbergMarquardtFit(residual, p0, LMOptions{RequestCovariance: true}) if err != nil { t.Fatal(err) } if res.Status != FitConverged { t.Fatalf("status %d, want FitConverged", res.Status) } out := []any{res.Parameters, res.Chi2, int(res.Status), res.Covariance} sigma, err := FromFloats([]float64{0.25, 1, 1, 1, 1, 1, 1, 1}, 8) if err != nil { t.Fatal(err) } wres, err := LevenbergMarquardtFit(residual, p0, LMOptions{Sigma: sigma}) if err != nil { t.Fatal(err) } if wres.Status != FitConverged { t.Fatalf("weighted status %d, want FitConverged", wres.Status) } return append(out, wres.Parameters, wres.Chi2, int(wres.Status)) }}, {"core-cosm1", func(t *testing.T) []any { // The small-argument cosine deficit across its regimes: the // digest pins the factored series from the underflowed end to // the crossover and the direct subtraction above it. a, err := FromFloats([]float64{ 1e-300, 1e-12, 1e-9, 1e-8, 1e-4, 0.01, 0.5, math.Pi / 4, 0.79, 1, 2, -0.3, -2.5, 1e6, }, 14) if err != nil { t.Fatal(err) } v, err := Cosm1(a) if err != nil { t.Fatal(err) } return []any{v} }}, {"core-substream", func(t *testing.T) []any { // The substream family and the scalar splitmix64 chain: the // digest pins the first draws of three members of one seed's // family beside the chain of states the scalar surface hands // out, so a change to the seeding moves loudly. out := []any{} for _, i := range []int{0, 1, 7} { g, err := Substream(42, i) if err != nil { t.Fatal(err) } a, err := Floats(g, 8) if err != nil { t.Fatal(err) } out = append(out, a) } state, v := Splitmix64(0) for range 3 { out = append(out, fmt.Sprintf("%#016x", state), fmt.Sprintf("%#016x", v)) state, v = Splitmix64(state) } return out }}, {"signal-chirp", func(t *testing.T) []any { // The chirp synthesiser: the digest pins a rising sweep, a // falling one and the constant tone that must be the plain // sine. rise, err := Chirp(64, 5, 60, 128) if err != nil { t.Fatal(err) } fall, err := Chirp(16, 900, 100, 8000) if err != nil { t.Fatal(err) } tone, err := Chirp(32, 11, 11, 256) if err != nil { t.Fatal(err) } return []any{rise, fall, tone} }}, {"core-besseljreal", func(t *testing.T) []any { // The real-order Bessel J across its regimes: the series at a // small argument, the climb seeded from the expansion, the // fractional Miller walk past the argument, and the integer // delegation, pinned beside the points themselves. type point struct { nu, x float64 } pts := []point{ {0.5, 2}, {2.5, 0.05}, {1.5, 12.1}, {2.3, 15}, {7.7, 40}, {20.5, 15}, {1.7, 1000}, {3, 20}, } out := []any{len(pts)} for _, p := range pts { v, err := BesselJRealOrder(p.nu, p.x) if err != nil { t.Fatal(err) } out = append(out, v) } return out }}, {"integrate-filon", func(t *testing.T) []any { // The Filon quadrature across its regimes: polynomial // amplitudes, where the construction is exact whatever the // carrier does, an exponential amplitude under a carrier of // five hundred, and the zero-frequency degeneration beside // them. poly := func(x float64) (float64, error) { return x, nil } c1, s1, err := IntegrateFilon(poly, 2, 7, 500, FilonOptions{}) if err != nil { t.Fatal(err) } exp := func(x float64) (float64, error) { return math.Exp(0.5 * x), nil } c2, s2, err := IntegrateFilon(exp, 2, 7, 500, FilonOptions{}) if err != nil { t.Fatal(err) } c3, s3, err := IntegrateFilon(exp, 0, 3, 0, FilonOptions{}) if err != nil { t.Fatal(err) } return []any{c1, s1, c2, s2, c3, s3} }}, {"core-narrow", func(t *testing.T) []any { // The narrow integer dtypes end to end: every width over the // corners of its own range, promotion across widths and across // the class boundary, the exact int64 folds, the bool masks the // comparisons answer and the selection and logic they feed. i8, err := Int8sFromArray([]int8{-128, -1, 0, 1, 127, -128, 127, 0, 3, -7}, 10) if err != nil { t.Fatal(err) } u8, err := Uint8sFromArray([]uint8{0, 1, 127, 128, 255, 254, 3, 0, 9, 200}, 10) if err != nil { t.Fatal(err) } i16, err := Int16sFromArray([]int16{-32768, -1, 0, 1, 32767, -32768, 32767, 0, 500, -900}, 10) if err != nil { t.Fatal(err) } u16, err := Uint16sFromArray([]uint16{0, 1, 32767, 32768, 65535, 65534, 7, 0, 40, 60000}, 10) if err != nil { t.Fatal(err) } i32, err := Int32sFromArray([]int32{-2147483648, -1, 0, 1, 2147483647, -2147483648, 2147483647, 0, 70000, -300}, 10) if err != nil { t.Fatal(err) } u32, err := Uint32sFromArray([]uint32{0, 1, 2147483647, 2147483648, 4294967295, 4294967294, 11, 0, 5, 4000000000}, 10) if err != nil { t.Fatal(err) } cross1, err := Add(i8, u16) if err != nil { t.Fatal(err) } cross2, err := Sub(i32, u8) if err != nil { t.Fatal(err) } cross3, err := Mul(i16, u8) if err != nil { t.Fatal(err) } cross4, err := Add(u32, i16) if err != nil { t.Fatal(err) } ltMask, err := Lt(i8, u16) if err != nil { t.Fatal(err) } eqMask, err := EqI(u8, 1) if err != nil { t.Fatal(err) } leMask, err := LeI(i32, -1) if err != nil { t.Fatal(err) } geMask, err := GeF(i8, 0.5) if err != nil { t.Fatal(err) } ltfMask, err := LtF(i16, -0.5) if err != nil { t.Fatal(err) } joined, err := And(ltMask, eqMask) if err != nil { t.Fatal(err) } flipped, err := Not(eqMask) if err != nil { t.Fatal(err) } picked, err := Select(i8, joined) if err != nil { t.Fatal(err) } chosen, err := Where(eqMask, u8, i8) if err != nil { t.Fatal(err) } widened, err := Astype(u32, Float) if err != nil { t.Fatal(err) } wide, err := FromInts([]int64{2147483648, -2147483649, -1}, 3) if err != nil { t.Fatal(err) } _, narrowErr := Astype(wide, Int32) if narrowErr == nil { t.Fatal("Astype narrowed 2^31 into int32") } inRange, err := FromInts([]int64{2147483647, -2147483648, -1}, 3) if err != nil { t.Fatal(err) } narrowed, err := Astype(inRange, Int32) if err != nil { t.Fatal(err) } count, err := CountNonzero(leMask) if err != nil { t.Fatal(err) } minU8, err := Min(u8) if err != nil { t.Fatal(err) } maxI32, err := Max(i32) if err != nil { t.Fatal(err) } return []any{i8, u8, i16, u16, i32, u32, cross1, cross2, cross3, cross4, Sum(i8), Sum(i16), Sum(u32), minU8, maxI32, ltMask, eqMask, leMask, geMask, ltfMask, joined, flipped, picked, chosen, widened, narrowed, narrowErr != nil, count} }}, } // hostileNetCDF builds a CDF-1 file whose single variable spans three // dimensions of 2^21, 2^20 and 2^20 elements: their product times the // 8-byte element width wraps to zero in 64-bit arithmetic, so a reader // that multiplies before it bounds would allocate what the header // claims. The file is 112 bytes. func hostileOracleHeader() []byte { u32 := func(v uint32) []byte { var b [4]byte binary.BigEndian.PutUint32(b[:], v) return b[:] } name := func(s string) []byte { b := u32(uint32(len(s))) b = append(b, s...) for len(s)%4 != 0 { b = append(b, 0) s += " " } return b } var b []byte b = append(b, 'C', 'D', 'F', 1) b = append(b, u32(0)...) // numrecs b = append(b, u32(10)...) // NC_DIMENSION b = append(b, u32(3)...) for i, l := range []uint32{1 << 21, 1 << 20, 1 << 20} { b = append(b, name(string(rune('a'+i)))...) b = append(b, u32(l)...) } b = append(b, u32(0)...) // absent attribute list b = append(b, u32(0)...) b = append(b, u32(11)...) // NC_VARIABLE b = append(b, u32(1)...) b = append(b, name("v")...) b = append(b, u32(3)...) b = append(b, u32(0)...) b = append(b, u32(1)...) b = append(b, u32(2)...) b = append(b, u32(0)...) // absent variable attributes b = append(b, u32(0)...) b = append(b, u32(6)...) // NC_DOUBLE b = append(b, u32(0)...) // vsize b = append(b, u32(0)...) // begin return b } // hostileFITSTable builds a BINTABLE header with a zero-width TFORM and // no data block: the row arithmetic must not be able to divide by the // row size, and the truncated file must be refused. func hostileOracleTable() []byte { var b []byte for _, body := range []string{ "XTENSION= 'BINTABLE'", "BITPIX = 8", "NAXIS = 2", "NAXIS1 = 4", "NAXIS2 = 2", "TFIELDS = 1", "TFORM1 = 'X '", "END", } { b = append(b, []byte(body)...) for len(b)%80 != 0 { b = append(b, ' ') } } return b } // oracleHDF5Fixed renders a version 1 fixed-point datatype message of // the given element width and signedness, with the bit offset and bit // precision the HDF5 file format specification's fixed-point property // table defines behind the header. func oracleHDF5Fixed(size uint32, signed bool) []byte { m := []byte{0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // version 1, class 0 if signed { m[1] = 0x08 // class bit field: bit 3 marks two's complement } binary.LittleEndian.PutUint32(m[4:], size) binary.LittleEndian.PutUint16(m[10:], uint16(8*size)) // bit precision return m } // oracleHDF5EnumBool renders the boolean enumeration datatype message: // class 8 over a one-byte unsigned base, the member names padded in // their own fields to multiples of eight bytes, the member values // packed behind them, exactly as the HDF5 file format specification's // enumeration class defines. func oracleHDF5EnumBool() []byte { m := []byte{0x18, 2, 0, 0, 1, 0, 0, 0} // class 8, two members, size 1 m = append(m, oracleHDF5Fixed(1, false)...) // the base type for _, name := range []string{"TRUE", "FALSE"} { start := len(m) m = append(m, name...) m = append(m, 0) for (len(m)-start)%8 != 0 { m = append(m, 0) } } return append(m, 1, 0) // TRUE = 1, FALSE = 0 } // oracleHDF5Narrow builds a minimal classic-layout HDF5 file carrying // one dataset: a version 0 superblock of eight-byte addresses and // lengths, a version 1 object header with the given datatype message, // contiguous storage and the payload bytes. The io tests build their // hostile fixtures the same way; these bytes are fixed, so the digest // of what the reader lands is stable across runs. func oracleHDF5Narrow(dtypeMsg []byte, dims []uint64, payload []byte) []byte { const headerAt, dataAt = 96, 448 align8 := func(n int) int { return (n + 7) / 8 * 8 } n := dataAt + len(payload) f := make([]byte, n) copy(f, []byte{0x89, 'H', 'D', 'F', '\r', '\n', 0x1a, '\n'}) f[8] = 0 // superblock version 0, the classic layout f[13], f[14] = 8, 8 // address and length sizes put := func(at int, v uint64) { binary.LittleEndian.PutUint64(f[at:], v) } put(32, math.MaxUint64) // free space undefined put(40, uint64(n)) // end of file put(48, math.MaxUint64) // driver information undefined put(64, headerAt) // the root object header space := make([]byte, 8+8*len(dims)) space[0] = 1 // dataspace version 1 space[1] = byte(len(dims)) for i, d := range dims { binary.LittleEndian.PutUint64(space[8+8*i:], d) } lay := make([]byte, 18) lay[0], lay[1] = 3, 1 // layout version 3, contiguous binary.LittleEndian.PutUint64(lay[2:], dataAt) binary.LittleEndian.PutUint64(lay[10:], uint64(len(payload))) msgs := []struct { typ uint16 body []byte }{ {1, space}, // dataspace {3, dtypeMsg}, {8, lay}, // data layout } off := headerAt f[off] = 1 // object header version 1 binary.LittleEndian.PutUint16(f[off+2:], uint16(len(msgs))) binary.LittleEndian.PutUint32(f[off+4:], 1) // reference count region := off + 16 size := 0 for _, m := range msgs { size = align8(size + 8 + len(m.body)) } binary.LittleEndian.PutUint32(f[off+8:], uint32(size)) for _, m := range msgs { binary.LittleEndian.PutUint16(f[region:], m.typ) binary.LittleEndian.PutUint16(f[region+2:], uint16(len(m.body))) copy(f[region+8:], m.body) region += align8(8 + len(m.body)) } copy(f[dataAt:], payload) return f } // oracleNetCDFNatives builds a CDF-1 file by hand carrying one // variable per classic type code: NC_BYTE, NC_SHORT, NC_INT, NC_CHAR, // NC_FLOAT and NC_DOUBLE over one shared four-element dimension, the // integers at the extremes of every width and the floats at // recognisable values. The NetCDF writer stores float64, float32 and // int64 only, so the fixture bytes live here exactly as the foreign // fixtures the io package carries. func oracleNetCDFNatives() []byte { u32 := func(v uint32) []byte { var b [4]byte binary.BigEndian.PutUint32(b[:], v) return b[:] } name := func(s string) []byte { b := u32(uint32(len(s))) b = append(b, s...) for len(b)%4 != 0 { b = append(b, 0) } return b } type classicVar struct { name string code uint32 data []byte } vars := []classicVar{ {"b", 1, []byte{0x80, 0xff, 0x00, 0x7f}}, // NC_BYTE: -128, -1, 0, 127 {"s", 3, []byte{0x80, 0x00, 0xff, 0xff, 0x00, 0x01, 0x7f, 0xff}}, // NC_SHORT extremes {"i", 4, []byte{0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 1, 0x7f, 0xff, 0xff, 0xff}}, // NC_INT {"c", 2, []byte{0x00, 0x41, 0xc8, 0xff}}, // NC_CHAR: raw bytes {"f", 5, []byte{ // NC_FLOAT: 1.5, -2.5, 0, 3.25 0x3f, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x00, 0x00}}, {"d", 6, []byte{ // NC_DOUBLE: 1.5, -2.5, 0, 4 0x3f, 0xf8, 0, 0, 0, 0, 0, 0, 0xc0, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x10, 0, 0, 0, 0, 0, 0}}, } var b []byte b = append(b, 'C', 'D', 'F', 1) b = append(b, u32(0)...) // numrecs b = append(b, u32(10)...) // NC_DIMENSION b = append(b, u32(1)...) // one dimension b = append(b, name("n")...) b = append(b, u32(4)...) // length 4 b = append(b, u32(0)...) // gatt_list ABSENT b = append(b, u32(0)...) // gatt_list ABSENT b = append(b, u32(11)...) // NC_VARIABLE b = append(b, u32(uint32(len(vars)))...) // six variables // The header ends where the first payload begins: one 36-byte // variable record per variable behind the fixed prefix. begin := len(b) + len(vars)*36 off := begin for _, v := range vars { b = append(b, name(v.name)...) b = append(b, u32(1)...) // rank 1 b = append(b, u32(0)...) // dimid 0 b = append(b, u32(0)...) // variable attributes ABSENT b = append(b, u32(0)...) // variable attributes ABSENT b = append(b, u32(v.code)...) b = append(b, u32(uint32(len(v.data)))...) // vsize b = append(b, u32(uint32(off))...) off += len(v.data) } for _, v := range vars { b = append(b, v.data...) } return b } // pinnedOracleDigests is the recorded behaviour of the harness, keyed // by runtime.GOOS/GOARCH plus the code generation the binary was built // with: floating-point kernels may differ between architectures (FMA // availability, libm corners), and GOAMD64 decides whether the compiler // may contract a multiply and an add into one fused operation, which // changes the last bits without changing the algorithm. A deliberate // algorithm change re-records the affected entries on the configuration // it was made on; an accidental one fails the test there. A build whose // combination has no block skips loudly until it is recorded, so // determinism is measured per configuration, never claimed in general. // // The portable build is the product and the only build, and its // digests are recorded at the toolchain default level (v1): the // compiler has no auto-vectoriser, so a pinned higher level would buy // only scalar FMA contraction, which the bit-pinned kernels already // suppress by spelling. A build pinned to another GOAMD64 level has no // block and skips with the recording instructions rather than failing. // // A re-recorded digest is sometimes the point itself: an old digest // can have pinned a bug, and three entries exist because their // predecessors did. signal-welch-savgol's magnitude goes through // math.Hypot, so it no longer rounds through a squared sum. // optim-roots-minima and optim-constrained-minima carry the L-BFGS // line search that no longer returns its start point when a stiff // objective rejects every trial step, the Nelder-Mead that no longer // stops on a simplex lying on one level set, and MinimiseConstrained // returning f at the answer instead of the augmented Lagrangian value. var pinnedOracleDigests = map[string]map[string]string{ "linux/amd64+v1": { "spmd-shards": "0bec5217a9a79b182241ac0937f32e9d20c89a5b392fc797ab3787a03fc8c9ed", "io-hdf5-narrow-write-roundtrip": "f2e87eaadcbab846e4acf5473b3023faca3015cd3b3f0919c4c3792114589ee9", "io-hdf5-uint8-roundtrip": "54550518525945c92d970a38d2d81a5005fb8a899b597819c6060610ae77dd54", "io-hdf5-int16-roundtrip": "b4163c6e9ed7a04ddb4a2328d394afe074237533738d19aa5ecaa68bff9e2685", "io-hdf5-bool-roundtrip": "fa56fd9a421d2e78f17711e717f851c4b19dc1f6946d5c4e1dddad85cc42d347", "io-netcdf-classic-natives": "c0219b60aa963176ce509f5633c22b96bc070529db1035d53a643b67d614d01b", "core-elementwise": "0812ac01c62b084326d0e590941a46327136e9022a101fad68998781b68f7014", "core-matmul-einsum": "a62b07d724f06603fe4c5ebf3d448b61d7638b93d1b58df605d94096d30ba4b4", "core-sort-argsort": "24fc532b4140bc6633b5fabb8a19c708c1919932c75ae8fce048c413c94aff0f", "core-reductions": "764eac75a3bcc1a38f7975ed4de1e5df39d70889dfb845507ef1cfe1ff456eac", "core-shape": "c84940b2aff4e4a25e7a4292fa6d76c2a0306f328ba334e3a6085843d94fcc3b", "core-fft": "1848e23763a0a72f282eff45c1cc54a3d2486f4ff53b12b4a8f462bcdc773061", "core-quasirandom": "000620721b8ce6fff07287da6301b89dbcdaa7293d68a0783aae60fa4370aa6d", "linalg-solve-inv-det": "5b73c4a57a6221f2b5abd3b6769d6aa13723db0ada0373e870d551f795c61bf3", "linalg-factorisations": "f70c03b3759703a6fcd1ff1ef3cbab024acd000781e2065331c18f95c45b4d15", "linalg-sparse-cholesky": "da49d6554341ffbf40500a99f241e0133528c2e6fadfc385cfa6d7d59685da28", "linalg-sparse-lu": "3ccf6e7064b410c3c6df0a6b2697b4c66f3722aec99491ed9298db6212d65fbb", "integrate-fem-poisson": "065cb65bb7fba9838ed6f84b703d7ffb69d877564bfbe006905e81fdea6b9175", "linalg-sparse-complex": "d81a8dd242a23ce7026ded53c44a4fea3a58d9b20c8be4ed2c03147c740e2130", "signal-welch-savgol": "36d6581ac2b06191b2d6eb743e042283d8cd0cbc187c54b6d40f490eef5984a4", "signal-wavelets": "f324710c1f67c8e5bb099731c8647c944744a62e9219ef8fdbb070412df434ab", "signal-lombscargle-conv": "4c3f3eb0f292b978d701dcea384ccbfc26be06acff348756ec0bda19c4cca20e", "signal-filters-stencils": "00bccd2f3b5d61f07c3383280dc8111897e1eaf57a6e16a0d70081a703a8b158", "stats-moments-quantiles": "61d196193641395bbb855685f2727cfe29521848bba111d89de9f480ef7264cc", "stats-correlation-regression": "f398fea69ae522ffaafdf0d307edd02d657aaf7a452c6c75d174307becbf7218", "stats-poisson-regression": "e385d9fda18acef4669ac1d1f1e8b12a5abeb682eff37a06f6ec140dd7b9f91a", "stats-distributions": "8986f622708f3f1f28c1c00fed9225014c17a90a8e0714e2ce6e2f181ee03321", "integrate-quadrature-ode": "66dd47bbc30de692902937078808da5322c76e6de1facaf5099fd72344f248a5", "optim-roots-minima": "9af044a7e71416f0ab1f8dcbd4073f199163791ad28779b59c7faabdf982e6f4", "optim-bounded-minima": "368dbb82d31c5e53c7dad9f944921e741ccccedafa7fda8d8b180f9daa58628e", "optim-constrained-minima": "884020c56542ac84e5460f0cbd171f64904f86254ebbae6479e3bd6662cc6662", "grad-backward": "0f3a1be94160019b796b457aa42531817685b7bc478ed041cc6c73ec5810b744", "io-roundtrips": "de1a36e2b2e9235a40af37b4ee5823e526f6a46583c34af6245dbbd322e3f1e3", "core-views-and-int-precision": "ca3c789ead2894ed2c53416f128b8aa665aed9dc3d4d67e38ae9d540a1ac5ccd", "io-hdf5-fixture": "01e96137069f7d9dd7d4cd2e236de8f5fbcf4ba6121a1f121f21c041197cf117", "io-hostile-inputs": "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", "core-float16": "6af37847cc6187b64f2bb20b7fefdd3b28a039e42988708d942c41bf62576949", "signal-kalman-arma": "874b9c7bfd3dae3111cb49576a51913972ad572963a2ab7ad1eaa3187f15196b", "signal-windows-filtfilt-dwt": "b435d694350e7a7f06303ded85c2b63e0e562795cf69686f2ae854f2c6dc81c5", "stats-distributions2-multipletest": "6d2f2661fa3a2bdaefbdf16f3d26b41ef69b29c93347e16e6df8542f30b14078", "stats-regression2": "cabb52d66ccb5d92b8d0885f5a5a166c1814d364dc75a4e8cac89819820edba3", "stats-unsupervised": "c8a17031b7133d58a6b6b6ec21a5624281d8f291717749869e41251b3e8ef68f", "integrate-stiff-solvers": "48276e65576eeefa8d7c3da8da42ee782441462ce34cf6bb814e494c0e00668f", "integrate-fem3d": "8323b5c89ac9187441cfac694193ef6394aff0508e71b53052d1b76fd59a535b", "linalg-sparse-lsqr-rrqr-update": "806455d7e53765a272afca8cfef90aa233ab78e62e4ad682c085ff7e117231fc", "optim-lp-qp-global2": "510ce65940755a164784ed4577502db2b60604aa9cbe184f22b2ab2a4c03bd57", "io-hdf5-write": "21482614860f885f277b05666924ab3b63a2c55b8b24734cbadc4577f2c7ac90", "optim-lm-fit": "cdbf15c3a4c5615e1a364a9fe4e5ec431d0cb65d9744cab52cbca66af51c58cf", "core-cosm1": "f995296d5c1f285ec6f2e719ee62f8eaf7c9a8e751cea8702cbe16b3df66ddb2", "core-substream": "ce49fae36f5e15b37aacc25d62b97c9f800d51aa08dee553cee1a5b6e1c01798", "signal-chirp": "ff9af5783d32eed88bf2658bde5660c247a0bd30a699c403f1755da290830a4b", "core-besseljreal": "49698a21228f091079cd65ae94cda134b16c3b0bec58a47642f6ad3fec7461d7", "integrate-filon": "4d5242520a5c144e4bdf111df83c2f2faf4fadce0859f87738acab91e3ed93e0", "core-narrow": "80913507636c4aabcdc57e5f90a75cd18499c86e244d84006650de3e1273da92", "stats-contingency": "9ac61a7a29227ddae02861076c85a669fd467f466a8c1118c52965ad4ac20a1b", "stats-mixedmodel": "6db27ea7908863a1f2d0725325d8a72a93a5ec83ad3882bca28a5d3d2b614227", "stats-hmm": "779e2c9cb8ee1e1871b17a04a42b2d574ff3de6132430bae8c58be502d450b75", "stats-hierarchy": "c4171ae9c61b76c676d016356ae319c5e3c15c0e32f7d0c26f0b1b38700cb96e", }, "linux/amd64+v1+race": { "spmd-shards": "0bec5217a9a79b182241ac0937f32e9d20c89a5b392fc797ab3787a03fc8c9ed", "io-hdf5-narrow-write-roundtrip": "f2e87eaadcbab846e4acf5473b3023faca3015cd3b3f0919c4c3792114589ee9", "io-hdf5-uint8-roundtrip": "54550518525945c92d970a38d2d81a5005fb8a899b597819c6060610ae77dd54", "io-hdf5-int16-roundtrip": "b4163c6e9ed7a04ddb4a2328d394afe074237533738d19aa5ecaa68bff9e2685", "io-hdf5-bool-roundtrip": "fa56fd9a421d2e78f17711e717f851c4b19dc1f6946d5c4e1dddad85cc42d347", "io-netcdf-classic-natives": "c0219b60aa963176ce509f5633c22b96bc070529db1035d53a643b67d614d01b", "core-elementwise": "0812ac01c62b084326d0e590941a46327136e9022a101fad68998781b68f7014", "core-matmul-einsum": "a62b07d724f06603fe4c5ebf3d448b61d7638b93d1b58df605d94096d30ba4b4", "core-sort-argsort": "24fc532b4140bc6633b5fabb8a19c708c1919932c75ae8fce048c413c94aff0f", "core-reductions": "764eac75a3bcc1a38f7975ed4de1e5df39d70889dfb845507ef1cfe1ff456eac", "core-shape": "c84940b2aff4e4a25e7a4292fa6d76c2a0306f328ba334e3a6085843d94fcc3b", "core-fft": "1848e23763a0a72f282eff45c1cc54a3d2486f4ff53b12b4a8f462bcdc773061", "core-quasirandom": "000620721b8ce6fff07287da6301b89dbcdaa7293d68a0783aae60fa4370aa6d", "linalg-solve-inv-det": "5b73c4a57a6221f2b5abd3b6769d6aa13723db0ada0373e870d551f795c61bf3", "linalg-factorisations": "f70c03b3759703a6fcd1ff1ef3cbab024acd000781e2065331c18f95c45b4d15", "linalg-sparse-cholesky": "da49d6554341ffbf40500a99f241e0133528c2e6fadfc385cfa6d7d59685da28", "linalg-sparse-lu": "3ccf6e7064b410c3c6df0a6b2697b4c66f3722aec99491ed9298db6212d65fbb", "integrate-fem-poisson": "065cb65bb7fba9838ed6f84b703d7ffb69d877564bfbe006905e81fdea6b9175", "linalg-sparse-complex": "d81a8dd242a23ce7026ded53c44a4fea3a58d9b20c8be4ed2c03147c740e2130", "signal-welch-savgol": "36d6581ac2b06191b2d6eb743e042283d8cd0cbc187c54b6d40f490eef5984a4", "signal-wavelets": "f324710c1f67c8e5bb099731c8647c944744a62e9219ef8fdbb070412df434ab", "signal-lombscargle-conv": "4c3f3eb0f292b978d701dcea384ccbfc26be06acff348756ec0bda19c4cca20e", "signal-filters-stencils": "00bccd2f3b5d61f07c3383280dc8111897e1eaf57a6e16a0d70081a703a8b158", "stats-moments-quantiles": "61d196193641395bbb855685f2727cfe29521848bba111d89de9f480ef7264cc", "stats-correlation-regression": "f398fea69ae522ffaafdf0d307edd02d657aaf7a452c6c75d174307becbf7218", "stats-poisson-regression": "e385d9fda18acef4669ac1d1f1e8b12a5abeb682eff37a06f6ec140dd7b9f91a", "stats-distributions": "8986f622708f3f1f28c1c00fed9225014c17a90a8e0714e2ce6e2f181ee03321", "integrate-quadrature-ode": "66dd47bbc30de692902937078808da5322c76e6de1facaf5099fd72344f248a5", "optim-roots-minima": "9af044a7e71416f0ab1f8dcbd4073f199163791ad28779b59c7faabdf982e6f4", "optim-bounded-minima": "368dbb82d31c5e53c7dad9f944921e741ccccedafa7fda8d8b180f9daa58628e", "optim-constrained-minima": "884020c56542ac84e5460f0cbd171f64904f86254ebbae6479e3bd6662cc6662", "grad-backward": "0f3a1be94160019b796b457aa42531817685b7bc478ed041cc6c73ec5810b744", "io-roundtrips": "de1a36e2b2e9235a40af37b4ee5823e526f6a46583c34af6245dbbd322e3f1e3", "core-views-and-int-precision": "ca3c789ead2894ed2c53416f128b8aa665aed9dc3d4d67e38ae9d540a1ac5ccd", "io-hdf5-fixture": "01e96137069f7d9dd7d4cd2e236de8f5fbcf4ba6121a1f121f21c041197cf117", "io-hostile-inputs": "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", "core-float16": "6af37847cc6187b64f2bb20b7fefdd3b28a039e42988708d942c41bf62576949", "signal-kalman-arma": "874b9c7bfd3dae3111cb49576a51913972ad572963a2ab7ad1eaa3187f15196b", "signal-windows-filtfilt-dwt": "b435d694350e7a7f06303ded85c2b63e0e562795cf69686f2ae854f2c6dc81c5", "stats-distributions2-multipletest": "6d2f2661fa3a2bdaefbdf16f3d26b41ef69b29c93347e16e6df8542f30b14078", "stats-regression2": "cabb52d66ccb5d92b8d0885f5a5a166c1814d364dc75a4e8cac89819820edba3", "stats-unsupervised": "c8a17031b7133d58a6b6b6ec21a5624281d8f291717749869e41251b3e8ef68f", "integrate-stiff-solvers": "48276e65576eeefa8d7c3da8da42ee782441462ce34cf6bb814e494c0e00668f", "integrate-fem3d": "8323b5c89ac9187441cfac694193ef6394aff0508e71b53052d1b76fd59a535b", "linalg-sparse-lsqr-rrqr-update": "806455d7e53765a272afca8cfef90aa233ab78e62e4ad682c085ff7e117231fc", "optim-lp-qp-global2": "510ce65940755a164784ed4577502db2b60604aa9cbe184f22b2ab2a4c03bd57", "io-hdf5-write": "21482614860f885f277b05666924ab3b63a2c55b8b24734cbadc4577f2c7ac90", "optim-lm-fit": "cdbf15c3a4c5615e1a364a9fe4e5ec431d0cb65d9744cab52cbca66af51c58cf", "core-cosm1": "f995296d5c1f285ec6f2e719ee62f8eaf7c9a8e751cea8702cbe16b3df66ddb2", "core-substream": "ce49fae36f5e15b37aacc25d62b97c9f800d51aa08dee553cee1a5b6e1c01798", "signal-chirp": "ff9af5783d32eed88bf2658bde5660c247a0bd30a699c403f1755da290830a4b", "core-besseljreal": "49698a21228f091079cd65ae94cda134b16c3b0bec58a47642f6ad3fec7461d7", "integrate-filon": "4d5242520a5c144e4bdf111df83c2f2faf4fadce0859f87738acab91e3ed93e0", "core-narrow": "80913507636c4aabcdc57e5f90a75cd18499c86e244d84006650de3e1273da92", "stats-contingency": "9ac61a7a29227ddae02861076c85a669fd467f466a8c1118c52965ad4ac20a1b", "stats-mixedmodel": "6db27ea7908863a1f2d0725325d8a72a93a5ec83ad3882bca28a5d3d2b614227", "stats-hmm": "779e2c9cb8ee1e1871b17a04a42b2d574ff3de6132430bae8c58be502d450b75", "stats-hierarchy": "c4171ae9c61b76c676d016356ae319c5e3c15c0e32f7d0c26f0b1b38700cb96e", }, } // oracleBuild names the code generation this binary was built with: the // GOAMD64 level decides whether the compiler may contract a multiply and // an add into one fused operation, and the race detector's // instrumentation changes which loops the compiler still contracts. // Each changes the last bits of ordinary arithmetic without changing // the algorithm, so the digests are keyed by both alongside the // architecture: a build whose combination has no recorded block skips // loudly instead of failing, exactly as an unseen architecture does. func oracleBuild() string { level := "v1" if bi, ok := debug.ReadBuildInfo(); ok { for _, s := range bi.Settings { if s.Key == "GOAMD64" && s.Value != "" { level = s.Value } } } return "+" + level + oracleRaceSuffix } // oracleKey names this architecture and code-generation block. func oracleKey() string { return runtime.GOOS + "/" + runtime.GOARCH + oracleBuild() } func TestOracle(t *testing.T) { record := os.Getenv("TENSOR_ORACLE_RECORD") == "1" current := make(map[string]string, len(oracleCases)) for _, c := range oracleCases { d := newOracleDigest() for _, v := range c.run(t) { d.result(t, v) } current[c.name] = d.sum() } if record { for _, c := range oracleCases { t.Logf("oracle %s %s", c.name, current[c.name]) } t.Logf("record these into pinnedOracleDigests[%q] and commit", oracleKey()) return } pinned, known := pinnedOracleDigests[oracleKey()] if !known { t.Skipf("no oracle digests recorded for %s; run TENSOR_ORACLE_RECORD=1 go test -run TestOracle -v . on it, "+ "then commit the pinnedOracleDigests[%q] block", oracleKey(), oracleKey()) } if len(pinned) != len(oracleCases) { t.Fatalf("pinnedOracleDigests[%q] holds %d entries, the harness runs %d; record with TENSOR_ORACLE_RECORD=1", oracleKey(), len(pinned), len(oracleCases)) } for _, c := range oracleCases { want, ok := pinned[c.name] if !ok { t.Errorf("oracle case %q is not pinned", c.name) continue } if current[c.name] != want { t.Errorf("oracle case %q moved:\n got %s\nwant %s\n"+ "If the change is deliberate, re-record with TENSOR_ORACLE_RECORD=1 in the same commit.", c.name, current[c.name], want) } } }