feat: initial release
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMinimumMaximum(t *testing.T) {
|
||||
a := mustFromInts(t, []int64{1, 5, 3}, 3)
|
||||
b := mustFromInts(t, []int64{4, 2, 3}, 3)
|
||||
|
||||
mn, err := Minimum(a, b)
|
||||
if err != nil {
|
||||
t.Fatalf("Minimum: %v", err)
|
||||
}
|
||||
if !Equal(mustFromInts(t, []int64{1, 2, 3}, 3), mn) {
|
||||
t.Fatalf("Minimum: %s", mn)
|
||||
}
|
||||
mx, err := Maximum(a, b)
|
||||
if err != nil {
|
||||
t.Fatalf("Maximum: %v", err)
|
||||
}
|
||||
if !Equal(mustFromInts(t, []int64{4, 5, 3}, 3), mx) {
|
||||
t.Fatalf("Maximum: %s", mx)
|
||||
}
|
||||
|
||||
// Promotion and NaN propagation.
|
||||
f := mustFromFloats(t, []float64{1.0, math.NaN()}, 2)
|
||||
fb := mustFromFloats(t, []float64{0.5, 1.0}, 2)
|
||||
fmin, _ := Minimum(f, fb)
|
||||
if v, _ := FloatAt(fmin, 0); v != 0.5 {
|
||||
t.Fatalf("Minimum promote: %v", v)
|
||||
}
|
||||
if v, _ := FloatAt(fmin, 1); !math.IsNaN(v) {
|
||||
t.Fatalf("Minimum NaN must propagate: %v", v)
|
||||
}
|
||||
i := mustFromInts(t, []int64{1}, 1)
|
||||
mixed, _ := Minimum(i, mustFromFloats(t, []float64{0.5}, 1))
|
||||
if mixed.Dtype() != Float {
|
||||
t.Fatalf("Minimum promote dtype: %s", mixed.Dtype())
|
||||
}
|
||||
|
||||
c := mustFromComplexes(t, []complex128{1}, 1)
|
||||
if _, err := Minimum(c, c); err == nil || !strings.Contains(err.Error(), "no ordering") {
|
||||
t.Fatalf("Minimum complex: %v", err)
|
||||
}
|
||||
if _, err := Maximum(a, mustFromInts(t, []int64{1}, 1)); err == nil || !strings.Contains(err.Error(), "shape mismatch") {
|
||||
t.Fatalf("Maximum shape: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClip(t *testing.T) {
|
||||
a := mustFromInts(t, []int64{-5, 3, 99}, 3)
|
||||
|
||||
cli, err := ClipI(a, 0, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("ClipI: %v", err)
|
||||
}
|
||||
if !Equal(mustFromInts(t, []int64{0, 3, 10}, 3), cli) {
|
||||
t.Fatalf("ClipI: %s", cli)
|
||||
}
|
||||
if cli.Dtype() != Int {
|
||||
t.Fatalf("ClipI keeps int: %s", cli.Dtype())
|
||||
}
|
||||
|
||||
clf, err := ClipF(a, -1.5, 1.5)
|
||||
if err != nil {
|
||||
t.Fatalf("ClipF: %v", err)
|
||||
}
|
||||
if clf.Dtype() != Float {
|
||||
t.Fatalf("ClipF dtype: %s", clf.Dtype())
|
||||
}
|
||||
if v, _ := FloatAt(clf, 0); v != -1.5 {
|
||||
t.Fatalf("ClipF lo: %v", v)
|
||||
}
|
||||
if v, _ := FloatAt(clf, 2); v != 1.5 {
|
||||
t.Fatalf("ClipF hi: %v", v)
|
||||
}
|
||||
|
||||
f := mustFromFloats(t, []float64{0.5, 2.5}, 2)
|
||||
fc, _ := ClipI(f, 1, 2)
|
||||
if v, _ := FloatAt(fc, 0); v != 1 {
|
||||
t.Fatalf("ClipI on float: %v", v)
|
||||
}
|
||||
|
||||
if _, err := ClipI(a, 5, 0); err == nil || !strings.Contains(err.Error(), "lo must be at most hi") {
|
||||
t.Fatalf("ClipI range: %v", err)
|
||||
}
|
||||
if _, err := ClipF(a, 2, 1); err == nil || !strings.Contains(err.Error(), "lo must be at most hi") {
|
||||
t.Fatalf("ClipF range: %v", err)
|
||||
}
|
||||
c := mustFromComplexes(t, []complex128{1}, 1)
|
||||
if _, err := ClipI(c, 0, 1); err == nil || !strings.Contains(err.Error(), "no ordering") {
|
||||
t.Fatalf("ClipI complex: %v", err)
|
||||
}
|
||||
if _, err := ClipF(c, 0, 1); err == nil || !strings.Contains(err.Error(), "no ordering") {
|
||||
t.Fatalf("ClipF complex: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestElementsGeneric(t *testing.T) {
|
||||
i := mustFromInts(t, []int64{1, 2}, 2)
|
||||
|
||||
// Same-type access returns the values unchanged.
|
||||
ints, err := i.Elements[int64]()
|
||||
if err != nil || ints[0] != 1 || ints[1] != 2 {
|
||||
t.Fatalf("Elements[int64]: %v %v", ints, err)
|
||||
}
|
||||
|
||||
// Widening converts along the ladder.
|
||||
floats, err := i.Elements[float64]()
|
||||
if err != nil || floats[0] != 1 || floats[1] != 2 {
|
||||
t.Fatalf("Elements[float64]: %v %v", floats, err)
|
||||
}
|
||||
complexes, err := i.Elements[complex128]()
|
||||
if err != nil || complexes[1] != complex(2, 0) {
|
||||
t.Fatalf("Elements[complex128]: %v %v", complexes, err)
|
||||
}
|
||||
|
||||
// Float arrays widen to complex; narrowing errors.
|
||||
f := mustFromFloats(t, []float64{2.5}, 1)
|
||||
fc, err := f.Elements[complex128]()
|
||||
if err != nil || fc[0] != complex(2.5, 0) {
|
||||
t.Fatalf("Elements float to complex: %v %v", fc, err)
|
||||
}
|
||||
if _, err := f.Elements[int64](); err == nil || !strings.Contains(err.Error(), "cannot narrow float to int64") {
|
||||
t.Fatalf("Elements float to int64: %v", err)
|
||||
}
|
||||
|
||||
c := mustFromComplexes(t, []complex128{complex(1, 2)}, 1)
|
||||
if _, err := c.Elements[float64](); err == nil || !strings.Contains(err.Error(), "cannot narrow complex to float64") {
|
||||
t.Fatalf("Elements complex to float64: %v", err)
|
||||
}
|
||||
cc, err := c.Elements[complex128]()
|
||||
if err != nil || cc[0] != complex(1, 2) {
|
||||
t.Fatalf("Elements[complex128] on complex: %v %v", cc, err)
|
||||
}
|
||||
|
||||
// The returned slice is a copy.
|
||||
vals, _ := i.Elements[int64]()
|
||||
vals[0] = 99
|
||||
if v, _ := IntAt(i, 0); v != 1 {
|
||||
t.Fatalf("Elements must copy: %d", v)
|
||||
}
|
||||
|
||||
// The integer class widens to int64 exactly, the rule IntAt
|
||||
// carries: a narrow source is an exact widening, never a
|
||||
// narrowing refusal.
|
||||
n8, err := FromInt8s([]int8{-128, -1, 0, 1, 127}, 5)
|
||||
if err != nil {
|
||||
t.Fatalf("FromInt8s: %v", err)
|
||||
}
|
||||
nv, err := n8.Elements[int64]()
|
||||
if err != nil {
|
||||
t.Fatalf("Elements[int64] on int8: %v", err)
|
||||
}
|
||||
for j, w := range []int64{-128, -1, 0, 1, 127} {
|
||||
if nv[j] != w {
|
||||
t.Fatalf("Elements[int64] int8[%d] = %d, want %d", j, nv[j], w)
|
||||
}
|
||||
}
|
||||
bs, err := FromBools([]bool{true, false, true}, 3)
|
||||
if err != nil {
|
||||
t.Fatalf("FromBools: %v", err)
|
||||
}
|
||||
bi, err := bs.Elements[int64]()
|
||||
if err != nil || bi[0] != 1 || bi[1] != 0 || bi[2] != 1 {
|
||||
t.Fatalf("Elements[int64] on bool = %v, %v; want [1 0 1]", bi, err)
|
||||
}
|
||||
u32, err := FromUint32s([]uint32{0, 4294967295}, 2)
|
||||
if err != nil {
|
||||
t.Fatalf("FromUint32s: %v", err)
|
||||
}
|
||||
ui, err := u32.Elements[int64]()
|
||||
if err != nil || ui[0] != 0 || ui[1] != 4294967295 {
|
||||
t.Fatalf("Elements[int64] on uint32 = %v, %v; want [0 4294967295] exact", ui, err)
|
||||
}
|
||||
// A complex source has no exact int64 image: the genuine
|
||||
// narrowing keeps its refusal.
|
||||
if _, err := c.Elements[int64](); err == nil || !strings.Contains(err.Error(), "cannot narrow complex to int64") {
|
||||
t.Fatalf("Elements complex to int64: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user