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

View as plain text