Source file src/simd/internal/spec/mathlib_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package spec
     6  
     7  import (
     8  	"math"
     9  	"testing"
    10  )
    11  
    12  func assertEq[T comparable](t *testing.T, got, want T, msg string) {
    13  	t.Helper()
    14  	if got != want {
    15  		t.Errorf("%s: got %v, want %v", msg, got, want)
    16  	}
    17  }
    18  
    19  func TestIsSigned(t *testing.T) {
    20  	assertEq(t, isSigned[int8](), true, "isSigned[int8]()")
    21  	assertEq(t, isSigned[uint8](), false, "isSigned[uint8]()")
    22  	assertEq(t, isSigned[int16](), true, "isSigned[int16]()")
    23  	assertEq(t, isSigned[uint16](), false, "isSigned[uint16]()")
    24  	assertEq(t, isSigned[int32](), true, "isSigned[int32]()")
    25  	assertEq(t, isSigned[uint32](), false, "isSigned[uint32]()")
    26  	assertEq(t, isSigned[int64](), true, "isSigned[int64]()")
    27  	assertEq(t, isSigned[uint64](), false, "isSigned[uint64]()")
    28  }
    29  
    30  func TestMaxVal(t *testing.T) {
    31  	assertEq(t, maxVal[int8](), int8(math.MaxInt8), "maxVal[int8]")
    32  	assertEq(t, maxVal[uint8](), uint8(math.MaxUint8), "maxVal[uint8]")
    33  	assertEq(t, maxVal[int16](), int16(math.MaxInt16), "maxVal[int16]")
    34  	assertEq(t, maxVal[uint16](), uint16(math.MaxUint16), "maxVal[uint16]")
    35  	assertEq(t, maxVal[int32](), int32(math.MaxInt32), "maxVal[int32]")
    36  	assertEq(t, maxVal[uint32](), uint32(math.MaxUint32), "maxVal[uint32]")
    37  	assertEq(t, maxVal[int64](), int64(math.MaxInt64), "maxVal[int64]")
    38  	assertEq(t, maxVal[uint64](), uint64(math.MaxUint64), "maxVal[uint64]")
    39  }
    40  
    41  func TestMinVal(t *testing.T) {
    42  	assertEq(t, minVal[int8](), int8(math.MinInt8), "minVal[int8]")
    43  	assertEq(t, minVal[uint8](), uint8(0), "minVal[uint8]")
    44  	assertEq(t, minVal[int16](), int16(math.MinInt16), "minVal[int16]")
    45  	assertEq(t, minVal[uint16](), uint16(0), "minVal[uint16]")
    46  	assertEq(t, minVal[int32](), int32(math.MinInt32), "minVal[int32]")
    47  	assertEq(t, minVal[uint32](), uint32(0), "minVal[uint32]")
    48  	assertEq(t, minVal[int64](), int64(math.MinInt64), "minVal[int64]")
    49  	assertEq(t, minVal[uint64](), uint64(0), "minVal[uint64]")
    50  }
    51  
    52  func TestSaturate(t *testing.T) {
    53  	// saturate[T Ints | Uints, U Ints | Uints](x T) U
    54  
    55  	// Signed to signed: int16 -> int8
    56  	assertEq(t, saturate[int16, int8](126), int8(126), "saturate[int16, int8](126)")
    57  	assertEq(t, saturate[int16, int8](-127), int8(-127), "saturate[int16, int8](-127)")
    58  	assertEq(t, saturate[int16, int8](128), int8(math.MaxInt8), "saturate[int16, int8](128) overflow")
    59  	assertEq(t, saturate[int16, int8](-129), int8(math.MinInt8), "saturate[int16, int8](-129) underflow")
    60  
    61  	// Unsigned to unsigned: uint16 -> uint8
    62  	assertEq(t, saturate[uint16, uint8](254), uint8(254), "saturate[uint16, uint8](254)")
    63  	assertEq(t, saturate[uint16, uint8](256), uint8(math.MaxUint8), "saturate[uint16, uint8](256) overflow")
    64  
    65  	// Signed to unsigned: int16 -> uint8
    66  	assertEq(t, saturate[int16, uint8](1), uint8(1), "saturate[int16, uint8](1)")
    67  	assertEq(t, saturate[int16, uint8](-1), uint8(0), "saturate[int16, uint8](-1) underflow")
    68  	assertEq(t, saturate[int16, uint8](254), uint8(254), "saturate[int16, uint8](254)")
    69  	assertEq(t, saturate[int16, uint8](256), uint8(math.MaxUint8), "saturate[int16, uint8](256) overflow")
    70  
    71  	// Unsigned to signed: uint16 -> int8
    72  	assertEq(t, saturate[uint16, int8](126), int8(126), "saturate[uint16, int8](126)")
    73  	assertEq(t, saturate[uint16, int8](128), int8(math.MaxInt8), "saturate[uint16, int8](128) overflow")
    74  
    75  	// Wider bounds: int64 to int32
    76  	assertEq(t, saturate[int64, int32](math.MaxInt32-1), int32(math.MaxInt32-1), "saturate[int64, int32](MaxInt32-1)")
    77  	assertEq(t, saturate[int64, int32](math.MaxInt32+1), int32(math.MaxInt32), "saturate[int64, int32](MaxInt32+1) overflow")
    78  	assertEq(t, saturate[int64, int32](math.MinInt32+1), int32(math.MinInt32+1), "saturate[int64, int32](MinInt32+1)")
    79  	assertEq(t, saturate[int64, int32](math.MinInt32-1), int32(math.MinInt32), "saturate[int64, int32](MinInt32-1) underflow")
    80  }
    81  
    82  func TestAddSaturated(t *testing.T) {
    83  	// Signed int8
    84  	assertEq(t, addSaturated[int8](125, 1), int8(126), "addSaturated[int8](125, 1)")
    85  	assertEq(t, addSaturated[int8](120, 10), int8(math.MaxInt8), "addSaturated[int8](120, 10) overflow")
    86  	assertEq(t, addSaturated[int8](-126, -1), int8(-127), "addSaturated[int8](-126, -1)")
    87  	assertEq(t, addSaturated[int8](-120, -10), int8(math.MinInt8), "addSaturated[int8](-120, -10) underflow")
    88  
    89  	// Unsigned uint8
    90  	assertEq(t, addSaturated[uint8](253, 1), uint8(254), "addSaturated[uint8](253, 1)")
    91  	assertEq(t, addSaturated[uint8](250, 10), uint8(math.MaxUint8), "addSaturated[uint8](250, 10) overflow")
    92  	assertEq(t, addSaturated[uint8](254, 0), uint8(254), "addSaturated[uint8](254, 0)")
    93  
    94  	// Signed int64
    95  	assertEq(t, addSaturated[int64](math.MaxInt64-2, 1), int64(math.MaxInt64-1), "addSaturated[int64](MaxInt64-2, 1)")
    96  	assertEq(t, addSaturated[int64](math.MaxInt64-5, 10), int64(math.MaxInt64), "addSaturated[int64](max-5, 10) overflow")
    97  	assertEq(t, addSaturated[int64](math.MinInt64+2, -1), int64(math.MinInt64+1), "addSaturated[int64](MinInt64+2, -1)")
    98  	assertEq(t, addSaturated[int64](math.MinInt64+5, -10), int64(math.MinInt64), "addSaturated[int64](min+5, -10) underflow")
    99  
   100  	// Unsigned uint64
   101  	assertEq(t, addSaturated[uint64](math.MaxUint64-2, 1), uint64(math.MaxUint64-1), "addSaturated[uint64](MaxUint64-2, 1)")
   102  	assertEq(t, addSaturated[uint64](math.MaxUint64-5, 10), uint64(math.MaxUint64), "addSaturated[uint64](max-5, 10) overflow")
   103  }
   104  
   105  func TestMulSaturatedUSS(t *testing.T) {
   106  	// mulSaturatedUSS[X Uints, Y Ints](x X, y Y) Y
   107  
   108  	// uint8, int8
   109  	assertEq(t, mulSaturatedUSS[uint8, int8](0, 10), int8(0), "mulSaturatedUSS[uint8, int8](0, 10)")
   110  	assertEq(t, mulSaturatedUSS[uint8, int8](10, 0), int8(0), "mulSaturatedUSS[uint8, int8](10, 0)")
   111  	assertEq(t, mulSaturatedUSS[uint8, int8](2, 63), int8(126), "mulSaturatedUSS[uint8, int8](2, 63)")
   112  	assertEq(t, mulSaturatedUSS[uint8, int8](1, 126), int8(126), "mulSaturatedUSS[uint8, int8](1, 126)")
   113  	assertEq(t, mulSaturatedUSS[uint8, int8](1, -127), int8(-127), "mulSaturatedUSS[uint8, int8](1, -127)")
   114  	assertEq(t, mulSaturatedUSS[uint8, int8](10, 20), int8(math.MaxInt8), "mulSaturatedUSS[uint8, int8](10, 20) positive overflow")
   115  	assertEq(t, mulSaturatedUSS[uint8, int8](10, -20), int8(math.MinInt8), "mulSaturatedUSS[uint8, int8](10, -20) negative overflow")
   116  
   117  	// uint64, int64
   118  	assertEq(t, mulSaturatedUSS[uint64, int64](2, (math.MaxInt64-1)/2), int64(math.MaxInt64-1), "mulSaturatedUSS[uint64, int64](2, (MaxInt64-1)/2)")
   119  	assertEq(t, mulSaturatedUSS[uint64, int64](2, math.MaxInt64), int64(math.MaxInt64), "mulSaturatedUSS[uint64, int64](2, MaxInt64) overflow")
   120  	assertEq(t, mulSaturatedUSS[uint64, int64](2, (math.MinInt64/2)+1), int64(math.MinInt64+2), "mulSaturatedUSS[uint64, int64](2, (MinInt64/2)+1)")
   121  	assertEq(t, mulSaturatedUSS[uint64, int64](2, math.MinInt64), int64(math.MinInt64), "mulSaturatedUSS[uint64, int64](2, MinInt64) underflow")
   122  	assertEq(t, mulSaturatedUSS[uint64, int64](math.MaxUint64, 1), int64(math.MaxInt64), "mulSaturatedUSS[uint64, int64](MaxUint64, 1) overflow")
   123  	assertEq(t, mulSaturatedUSS[uint64, int64](math.MaxUint64, -1), int64(math.MinInt64), "mulSaturatedUSS[uint64, int64](MaxUint64, -1) underflow")
   124  }
   125  

View as plain text