Source file src/simd/archsimd/internal/simd_test/binary_128_test.go

     1  // Copyright 2025 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 && (amd64 || wasm || arm64)
     6  
     7  package simd_test
     8  
     9  import (
    10  	"runtime"
    11  	"simd/archsimd"
    12  	"testing"
    13  )
    14  
    15  func TestAdd(t *testing.T) {
    16  	testFloat32x4Binary(t, archsimd.Float32x4.Add, addSlice[float32])
    17  	testFloat64x2Binary(t, archsimd.Float64x2.Add, addSlice[float64])
    18  
    19  	testInt16x8Binary(t, archsimd.Int16x8.Add, addSlice[int16])
    20  	testInt32x4Binary(t, archsimd.Int32x4.Add, addSlice[int32])
    21  	testInt64x2Binary(t, archsimd.Int64x2.Add, addSlice[int64])
    22  	testInt8x16Binary(t, archsimd.Int8x16.Add, addSlice[int8])
    23  
    24  	testUint32x4Binary(t, archsimd.Uint32x4.Add, addSlice[uint32])
    25  	testUint64x2Binary(t, archsimd.Uint64x2.Add, addSlice[uint64])
    26  	testUint16x8Binary(t, archsimd.Uint16x8.Add, addSlice[uint16])
    27  	testUint8x16Binary(t, archsimd.Uint8x16.Add, addSlice[uint8])
    28  }
    29  
    30  func TestSub(t *testing.T) {
    31  	testFloat32x4Binary(t, archsimd.Float32x4.Sub, subSlice[float32])
    32  	testFloat64x2Binary(t, archsimd.Float64x2.Sub, subSlice[float64])
    33  
    34  	testInt32x4Binary(t, archsimd.Int32x4.Sub, subSlice[int32])
    35  	testInt16x8Binary(t, archsimd.Int16x8.Sub, subSlice[int16])
    36  	testInt64x2Binary(t, archsimd.Int64x2.Sub, subSlice[int64])
    37  	testInt8x16Binary(t, archsimd.Int8x16.Sub, subSlice[int8])
    38  
    39  	testUint32x4Binary(t, archsimd.Uint32x4.Sub, subSlice[uint32])
    40  	testUint16x8Binary(t, archsimd.Uint16x8.Sub, subSlice[uint16])
    41  	testUint64x2Binary(t, archsimd.Uint64x2.Sub, subSlice[uint64])
    42  	testUint8x16Binary(t, archsimd.Uint8x16.Sub, subSlice[uint8])
    43  }
    44  
    45  func TestMax(t *testing.T) {
    46  	if runtime.GOARCH != "amd64" {
    47  		// skip in AMD64 as NaN behavior is different
    48  		testFloat32x4Binary(t, archsimd.Float32x4.Max, maxSlice[float32])
    49  		testFloat64x2Binary(t, archsimd.Float64x2.Max, maxSlice[float64])
    50  	}
    51  	testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8])
    52  	testInt16x8Binary(t, archsimd.Int16x8.Max, maxSlice[int16])
    53  	testInt32x4Binary(t, archsimd.Int32x4.Max, maxSlice[int32])
    54  
    55  	testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8])
    56  	testUint16x8Binary(t, archsimd.Uint16x8.Max, maxSlice[uint16])
    57  	testUint32x4Binary(t, archsimd.Uint32x4.Max, maxSlice[uint32])
    58  }
    59  
    60  func TestMin(t *testing.T) {
    61  	if runtime.GOARCH != "amd64" {
    62  		// skip in AMD64 as NaN behavior is different
    63  		testFloat32x4Binary(t, archsimd.Float32x4.Min, minSlice[float32])
    64  		testFloat64x2Binary(t, archsimd.Float64x2.Min, minSlice[float64])
    65  	}
    66  	testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8])
    67  	testInt16x8Binary(t, archsimd.Int16x8.Min, minSlice[int16])
    68  	testInt32x4Binary(t, archsimd.Int32x4.Min, minSlice[int32])
    69  
    70  	testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8])
    71  	testUint16x8Binary(t, archsimd.Uint16x8.Min, minSlice[uint16])
    72  	testUint32x4Binary(t, archsimd.Uint32x4.Min, minSlice[uint32])
    73  }
    74  
    75  func TestAnd(t *testing.T) {
    76  	testInt16x8Binary(t, archsimd.Int16x8.And, andSlice[int16])
    77  	testInt32x4Binary(t, archsimd.Int32x4.And, andSlice[int32])
    78  	testInt64x2Binary(t, archsimd.Int64x2.And, andSlice[int64])
    79  	testInt8x16Binary(t, archsimd.Int8x16.And, andSlice[int8])
    80  
    81  	testUint16x8Binary(t, archsimd.Uint16x8.And, andSlice[uint16])
    82  	testUint32x4Binary(t, archsimd.Uint32x4.And, andSlice[uint32])
    83  	testUint64x2Binary(t, archsimd.Uint64x2.And, andSlice[uint64])
    84  	testUint8x16Binary(t, archsimd.Uint8x16.And, andSlice[uint8])
    85  }
    86  
    87  func TestAndNot(t *testing.T) {
    88  	testInt16x8Binary(t, archsimd.Int16x8.AndNot, andNotSlice[int16])
    89  	testInt32x4Binary(t, archsimd.Int32x4.AndNot, andNotSlice[int32])
    90  	testInt64x2Binary(t, archsimd.Int64x2.AndNot, andNotSlice[int64])
    91  	testInt8x16Binary(t, archsimd.Int8x16.AndNot, andNotSlice[int8])
    92  
    93  	testUint8x16Binary(t, archsimd.Uint8x16.AndNot, andNotSlice[uint8])
    94  	testUint16x8Binary(t, archsimd.Uint16x8.AndNot, andNotSlice[uint16])
    95  	testUint32x4Binary(t, archsimd.Uint32x4.AndNot, andNotSlice[uint32])
    96  	testUint64x2Binary(t, archsimd.Uint64x2.AndNot, andNotSlice[uint64])
    97  }
    98  
    99  func TestXor(t *testing.T) {
   100  	testInt16x8Binary(t, archsimd.Int16x8.Xor, xorSlice[int16])
   101  	testInt32x4Binary(t, archsimd.Int32x4.Xor, xorSlice[int32])
   102  	testInt64x2Binary(t, archsimd.Int64x2.Xor, xorSlice[int64])
   103  	testInt8x16Binary(t, archsimd.Int8x16.Xor, xorSlice[int8])
   104  
   105  	testUint16x8Binary(t, archsimd.Uint16x8.Xor, xorSlice[uint16])
   106  	testUint32x4Binary(t, archsimd.Uint32x4.Xor, xorSlice[uint32])
   107  	testUint64x2Binary(t, archsimd.Uint64x2.Xor, xorSlice[uint64])
   108  	testUint8x16Binary(t, archsimd.Uint8x16.Xor, xorSlice[uint8])
   109  }
   110  
   111  func TestOr(t *testing.T) {
   112  	testInt16x8Binary(t, archsimd.Int16x8.Or, orSlice[int16])
   113  	testInt32x4Binary(t, archsimd.Int32x4.Or, orSlice[int32])
   114  	testInt64x2Binary(t, archsimd.Int64x2.Or, orSlice[int64])
   115  	testInt8x16Binary(t, archsimd.Int8x16.Or, orSlice[int8])
   116  
   117  	testUint16x8Binary(t, archsimd.Uint16x8.Or, orSlice[uint16])
   118  	testUint32x4Binary(t, archsimd.Uint32x4.Or, orSlice[uint32])
   119  	testUint64x2Binary(t, archsimd.Uint64x2.Or, orSlice[uint64])
   120  	testUint8x16Binary(t, archsimd.Uint8x16.Or, orSlice[uint8])
   121  }
   122  
   123  func TestMul(t *testing.T) {
   124  	testFloat32x4Binary(t, archsimd.Float32x4.Mul, mulSlice[float32])
   125  	testFloat64x2Binary(t, archsimd.Float64x2.Mul, mulSlice[float64])
   126  
   127  	testInt8x16Binary(t, archsimd.Int8x16.Mul, mulSlice[int8])
   128  	testUint8x16Binary(t, archsimd.Uint8x16.Mul, mulSlice[uint8])
   129  	testInt16x8Binary(t, archsimd.Int16x8.Mul, mulSlice[int16])
   130  	testInt32x4Binary(t, archsimd.Int32x4.Mul, mulSlice[int32])
   131  }
   132  
   133  func TestDiv(t *testing.T) {
   134  	testFloat32x4Binary(t, archsimd.Float32x4.Div, divSlice[float32])
   135  	testFloat64x2Binary(t, archsimd.Float64x2.Div, divSlice[float64])
   136  }
   137  
   138  func TestGetElem(t *testing.T) {
   139  	// Int8x16
   140  	{
   141  		a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
   142  		v := archsimd.LoadInt8x16(a)
   143  		if e := v.GetElem(2); e != a[2] {
   144  			t.Errorf("Int8x16.GetElem(2) = %d, want %d", e, a[2])
   145  		}
   146  	}
   147  	// Int16x8
   148  	{
   149  		a := []int16{10, 20, 30, 40, 50, 60, 70, 80}
   150  		v := archsimd.LoadInt16x8(a)
   151  		if e := v.GetElem(3); e != a[3] {
   152  			t.Errorf("Int16x8.GetElem(3) = %d, want %d", e, a[3])
   153  		}
   154  	}
   155  	// Int32x4
   156  	{
   157  		a := []int32{100, 200, 300, 400}
   158  		v := archsimd.LoadInt32x4(a)
   159  		if e := v.GetElem(1); e != a[1] {
   160  			t.Errorf("Int32x4.GetElem(1) = %d, want %d", e, a[1])
   161  		}
   162  	}
   163  	// Int64x2
   164  	{
   165  		a := []int64{1000, 2000}
   166  		v := archsimd.LoadInt64x2(a)
   167  		if e := v.GetElem(0); e != a[0] {
   168  			t.Errorf("Int64x2.GetElem(0) = %d, want %d", e, a[0])
   169  		}
   170  	}
   171  	// Uint8x16
   172  	{
   173  		a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
   174  		v := archsimd.LoadUint8x16(a)
   175  		if e := v.GetElem(5); e != a[5] {
   176  			t.Errorf("Uint8x16.GetElem(5) = %d, want %d", e, a[5])
   177  		}
   178  	}
   179  	// Uint16x8
   180  	{
   181  		a := []uint16{100, 200, 300, 400, 500, 600, 700, 800}
   182  		v := archsimd.LoadUint16x8(a)
   183  		if e := v.GetElem(7); e != a[7] {
   184  			t.Errorf("Uint16x8.GetElem(7) = %d, want %d", e, a[7])
   185  		}
   186  	}
   187  	// Uint32x4
   188  	{
   189  		a := []uint32{1000, 2000, 3000, 4000}
   190  		v := archsimd.LoadUint32x4(a)
   191  		if e := v.GetElem(2); e != a[2] {
   192  			t.Errorf("Uint32x4.GetElem(2) = %d, want %d", e, a[2])
   193  		}
   194  	}
   195  	// Uint64x2
   196  	{
   197  		a := []uint64{10000, 20000}
   198  		v := archsimd.LoadUint64x2(a)
   199  		if e := v.GetElem(1); e != a[1] {
   200  			t.Errorf("Uint64x2.GetElem(1) = %d, want %d", e, a[1])
   201  		}
   202  	}
   203  	// Float32x4
   204  	{
   205  		a := []float32{1.0, 2.0, 3.0, 4.0}
   206  		v := archsimd.LoadFloat32x4(a)
   207  		if e := v.GetElem(3); e != a[3] {
   208  			t.Errorf("Float32x4.GetElem(3) = %f, want %f", e, a[3])
   209  		}
   210  	}
   211  	// Float64x2
   212  	{
   213  		a := []float64{10.5, 20.5}
   214  		v := archsimd.LoadFloat64x2(a)
   215  		if e := v.GetElem(0); e != a[0] {
   216  			t.Errorf("Float64x2.GetElem(0) = %f, want %f", e, a[0])
   217  		}
   218  	}
   219  }
   220  
   221  func TestSetElem(t *testing.T) {
   222  	// Int8x16
   223  	{
   224  		a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
   225  		v := archsimd.LoadInt8x16(a)
   226  		v = v.SetElem(3, int8(99))
   227  		a[3] = 99
   228  		b := make([]int8, 16)
   229  		v.Store(b)
   230  		checkSlices(t, b, a)
   231  	}
   232  	// Int16x8
   233  	{
   234  		a := []int16{10, 20, 30, 40, 50, 60, 70, 80}
   235  		v := archsimd.LoadInt16x8(a)
   236  		v = v.SetElem(5, int16(123))
   237  		a[5] = 123
   238  		b := make([]int16, 8)
   239  		v.Store(b)
   240  		checkSlices(t, b, a)
   241  	}
   242  	// Int32x4
   243  	{
   244  		a := []int32{100, 200, 300, 400}
   245  		v := archsimd.LoadInt32x4(a)
   246  		v = v.SetElem(2, int32(999))
   247  		a[2] = 999
   248  		b := make([]int32, 4)
   249  		v.Store(b)
   250  		checkSlices(t, b, a)
   251  	}
   252  	// Int64x2
   253  	{
   254  		a := []int64{1000, 2000}
   255  		v := archsimd.LoadInt64x2(a)
   256  		v = v.SetElem(1, int64(5555))
   257  		a[1] = 5555
   258  		b := make([]int64, 2)
   259  		v.Store(b)
   260  		checkSlices(t, b, a)
   261  	}
   262  	// Uint8x16
   263  	{
   264  		a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
   265  		v := archsimd.LoadUint8x16(a)
   266  		v = v.SetElem(7, uint8(200))
   267  		a[7] = 200
   268  		b := make([]uint8, 16)
   269  		v.Store(b)
   270  		checkSlices(t, b, a)
   271  	}
   272  	// Uint16x8
   273  	{
   274  		a := []uint16{100, 200, 300, 400, 500, 600, 700, 800}
   275  		v := archsimd.LoadUint16x8(a)
   276  		v = v.SetElem(0, uint16(1111))
   277  		a[0] = 1111
   278  		b := make([]uint16, 8)
   279  		v.Store(b)
   280  		checkSlices(t, b, a)
   281  	}
   282  	// Uint32x4
   283  	{
   284  		a := []uint32{1000, 2000, 3000, 4000}
   285  		v := archsimd.LoadUint32x4(a)
   286  		v = v.SetElem(3, uint32(9999))
   287  		a[3] = 9999
   288  		b := make([]uint32, 4)
   289  		v.Store(b)
   290  		checkSlices(t, b, a)
   291  	}
   292  	// Uint64x2
   293  	{
   294  		a := []uint64{10000, 20000}
   295  		v := archsimd.LoadUint64x2(a)
   296  		v = v.SetElem(0, uint64(55555))
   297  		a[0] = 55555
   298  		b := make([]uint64, 2)
   299  		v.Store(b)
   300  		checkSlices(t, b, a)
   301  	}
   302  	// Float32x4
   303  	{
   304  		a := []float32{1.0, 2.0, 3.0, 4.0}
   305  		v := archsimd.LoadFloat32x4(a)
   306  		v = v.SetElem(1, float32(42.5))
   307  		a[1] = 42.5
   308  		b := make([]float32, 4)
   309  		v.Store(b)
   310  		checkSlices(t, b, a)
   311  	}
   312  	// Float64x2
   313  	{
   314  		a := []float64{10.5, 20.5}
   315  		v := archsimd.LoadFloat64x2(a)
   316  		v = v.SetElem(0, float64(99.9))
   317  		a[0] = 99.9
   318  		b := make([]float64, 2)
   319  		v.Store(b)
   320  		checkSlices(t, b, a)
   321  	}
   322  }
   323  

View as plain text