Source file src/simd/convert_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  //go:build goexperiment.simd
     6  
     7  package simd_test
     8  
     9  import (
    10  	"math"
    11  	"simd"
    12  	"simd/internal/test_helpers"
    13  	"testing"
    14  	"unsafe"
    15  )
    16  
    17  // withEdges returns xs followed by values around the limits of the narrower
    18  // integer types, which xs may lack. It repeats the edge values enough that
    19  // every window of the result that TestV2Ve tries puts every edge value in
    20  // every lane, for vectors of up to 64 elements.
    21  func withEdges[X integer](xs []X, edges ...int64) []X {
    22  	const maxLanes = 64
    23  	r := append([]X(nil), xs...)
    24  	for i := range len(edges) + maxLanes {
    25  		r = append(r, X(edges[i%len(edges)]))
    26  	}
    27  	return r
    28  }
    29  
    30  func sat[Z integer, X integer](x X) Z {
    31  	// Compare in int64 or uint64, depending on the signedness of x.
    32  	lo, hi := minOf[Z](), maxOf[Z]()
    33  	if x < 0 {
    34  		if int64(x) < lo {
    35  			return Z(lo)
    36  		}
    37  	} else if uint64(x) > hi {
    38  		return Z(hi)
    39  	}
    40  	return Z(x)
    41  }
    42  
    43  func minOf[Z integer]() int64 {
    44  	var z Z
    45  	if z-1 > 0 {
    46  		return 0
    47  	}
    48  	return -1 << (8*sizeOf[Z]() - 1)
    49  }
    50  
    51  func maxOf[Z integer]() uint64 {
    52  	var z Z
    53  	if z-1 > 0 {
    54  		return 1<<(8*sizeOf[Z]()) - 1
    55  	}
    56  	return 1<<(8*sizeOf[Z]()-1) - 1
    57  }
    58  
    59  func sizeOf[Z integer]() uint {
    60  	var z Z
    61  	return uint(unsafe.Sizeof(z))
    62  }
    63  
    64  func conv[Z, X number](x X) Z { return Z(x) }
    65  
    66  func TestWidthChangingConversions(t *testing.T) {
    67  	edges := []int64{math.MinInt32 - 1, math.MinInt32, math.MinInt16 - 1, math.MinInt16, math.MinInt8 - 1, math.MinInt8,
    68  		-1, 0, 1, math.MaxInt8, math.MaxInt8 + 1, math.MaxUint8, math.MaxUint8 + 1,
    69  		math.MaxInt16, math.MaxInt16 + 1, math.MaxUint16, math.MaxUint16 + 1,
    70  		math.MaxInt32, math.MaxInt32 + 1, math.MaxUint32, math.MaxUint32 + 1, math.MaxInt64, math.MinInt64}
    71  	i8 := withEdges(test_helpers.Int8s(), edges...)
    72  	i16 := withEdges(test_helpers.Int16s(), edges...)
    73  	i32 := withEdges(test_helpers.Int32s(), edges...)
    74  	i64 := withEdges(test_helpers.Int64s(), edges...)
    75  	u8 := withEdges(test_helpers.Uint8s(), edges...)
    76  	u16 := withEdges(test_helpers.Uint16s(), edges...)
    77  	u32 := withEdges(test_helpers.Uint32s(), edges...)
    78  	u64 := withEdges(test_helpers.Uint64s(), edges...)
    79  
    80  	test_helpers.TestV2Ve(t, i8, simd.LoadInt8s, simd.Int8s.ExtendToInt16, conv[int16, int8])
    81  	test_helpers.TestV2Ve(t, i16, simd.LoadInt16s, simd.Int16s.ExtendToInt32, conv[int32, int16])
    82  	test_helpers.TestV2Ve(t, i32, simd.LoadInt32s, simd.Int32s.ExtendToInt64, conv[int64, int32])
    83  	test_helpers.TestV2Ve(t, u8, simd.LoadUint8s, simd.Uint8s.ExtendToUint16, conv[uint16, uint8])
    84  	test_helpers.TestV2Ve(t, u16, simd.LoadUint16s, simd.Uint16s.ExtendToUint32, conv[uint32, uint16])
    85  	test_helpers.TestV2Ve(t, u32, simd.LoadUint32s, simd.Uint32s.ExtendToUint64, conv[uint64, uint32])
    86  
    87  	test_helpers.TestV2Ve(t, i16, simd.LoadInt16s, simd.Int16s.TruncToInt8, conv[int8, int16])
    88  	test_helpers.TestV2Ve(t, i32, simd.LoadInt32s, simd.Int32s.TruncToInt16, conv[int16, int32])
    89  	test_helpers.TestV2Ve(t, i64, simd.LoadInt64s, simd.Int64s.TruncToInt32, conv[int32, int64])
    90  	test_helpers.TestV2Ve(t, u16, simd.LoadUint16s, simd.Uint16s.TruncToUint8, conv[uint8, uint16])
    91  	test_helpers.TestV2Ve(t, u32, simd.LoadUint32s, simd.Uint32s.TruncToUint16, conv[uint16, uint32])
    92  	test_helpers.TestV2Ve(t, u64, simd.LoadUint64s, simd.Uint64s.TruncToUint32, conv[uint32, uint64])
    93  
    94  	test_helpers.TestV2Ve(t, i16, simd.LoadInt16s, simd.Int16s.SaturateToInt8, sat[int8, int16])
    95  	test_helpers.TestV2Ve(t, i32, simd.LoadInt32s, simd.Int32s.SaturateToInt16, sat[int16, int32])
    96  	test_helpers.TestV2Ve(t, i64, simd.LoadInt64s, simd.Int64s.SaturateToInt32, sat[int32, int64])
    97  	test_helpers.TestV2Ve(t, i16, simd.LoadInt16s, simd.Int16s.SaturateToUint8, sat[uint8, int16])
    98  	test_helpers.TestV2Ve(t, i32, simd.LoadInt32s, simd.Int32s.SaturateToUint16, sat[uint16, int32])
    99  	test_helpers.TestV2Ve(t, i64, simd.LoadInt64s, simd.Int64s.SaturateToUint32, sat[uint32, int64])
   100  	test_helpers.TestV2Ve(t, u16, simd.LoadUint16s, simd.Uint16s.SaturateToUint8, sat[uint8, uint16])
   101  	test_helpers.TestV2Ve(t, u32, simd.LoadUint32s, simd.Uint32s.SaturateToUint16, sat[uint16, uint32])
   102  	test_helpers.TestV2Ve(t, u64, simd.LoadUint64s, simd.Uint64s.SaturateToUint32, sat[uint32, uint64])
   103  
   104  	test_helpers.TestV2Ve(t, test_helpers.Float32s(), simd.LoadFloat32s, simd.Float32s.ConvertToFloat64, conv[float64, float32])
   105  	test_helpers.TestV2Ve(t, test_helpers.Float64s(), simd.LoadFloat64s, simd.Float64s.ConvertToFloat32, conv[float32, float64])
   106  }
   107  

View as plain text