Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/simd/archsimd/internal/simd_test/binary_sve_arm64_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  // SVE binary-op tests. Unlike amd64, SVE has only a handful of (scalable)
     8  // vector types, so there is nothing to generate — these drivers are hand-written
     9  // in the same shape as the generated testXxxBinary helpers. Each loads two input
    10  // windows via the fixed-array API, runs the op, stores the result, and compares
    11  // the lanes the hardware actually populated: the vector's runtime Len() (VL is
    12  // <= the 32-byte backing, enforced at package init).
    13  
    14  package simd_test
    15  
    16  import (
    17  	"simd/archsimd"
    18  	"testing"
    19  )
    20  
    21  // sveMaxBytes is the fixed backing-array size for a scalable vector: the maximum
    22  // vector length simd supports (256 bits).
    23  const sveMaxBytes = 32
    24  
    25  // testSVEBinary drives a scalable binary op like the generated testXxxBinary
    26  // helpers. active is the runtime number of live lanes (from the vector's Len()).
    27  func testSVEBinary[T number, V any](t *testing.T, pool []T, elemBytes, active int,
    28  	load func([]T) V, f func(V, V) V, store func(V, []T), want func([]T, []T) []T) {
    29  	t.Helper()
    30  	count := sveMaxBytes / elemBytes // lanes in the fixed backing array
    31  	forSlicePair(t, pool, count, func(x, y []T) bool {
    32  		t.Helper()
    33  		g := make([]T, count)
    34  		store(f(load(x), load(y)), g)
    35  		w := want(x, y)
    36  		return checkSlicesLogInput(t, g[:active], w[:active], 0.0, func() {
    37  			t.Helper()
    38  			t.Logf("x=%v", x)
    39  			t.Logf("y=%v", y)
    40  		})
    41  	})
    42  }
    43  
    44  func testInt8sBinary(t *testing.T, f func(_, _ archsimd.Int8s) archsimd.Int8s, want func(_, _ []int8) []int8) {
    45  	var z archsimd.Int8s
    46  	testSVEBinary(t, int8s, 1, z.Len(), archsimd.LoadInt8s, f, archsimd.Int8s.Store, want)
    47  }
    48  
    49  func testInt16sBinary(t *testing.T, f func(_, _ archsimd.Int16s) archsimd.Int16s, want func(_, _ []int16) []int16) {
    50  	var z archsimd.Int16s
    51  	testSVEBinary(t, int16s, 2, z.Len(), archsimd.LoadInt16s, f, archsimd.Int16s.Store, want)
    52  }
    53  
    54  func testInt32sBinary(t *testing.T, f func(_, _ archsimd.Int32s) archsimd.Int32s, want func(_, _ []int32) []int32) {
    55  	var z archsimd.Int32s
    56  	testSVEBinary(t, int32s, 4, z.Len(), archsimd.LoadInt32s, f, archsimd.Int32s.Store, want)
    57  }
    58  
    59  func testInt64sBinary(t *testing.T, f func(_, _ archsimd.Int64s) archsimd.Int64s, want func(_, _ []int64) []int64) {
    60  	var z archsimd.Int64s
    61  	testSVEBinary(t, int64s, 8, z.Len(), archsimd.LoadInt64s, f, archsimd.Int64s.Store, want)
    62  }
    63  
    64  func testUint8sBinary(t *testing.T, f func(_, _ archsimd.Uint8s) archsimd.Uint8s, want func(_, _ []uint8) []uint8) {
    65  	var z archsimd.Uint8s
    66  	testSVEBinary(t, uint8s, 1, z.Len(), archsimd.LoadUint8s, f, archsimd.Uint8s.Store, want)
    67  }
    68  
    69  func testFloat32sBinary(t *testing.T, f func(_, _ archsimd.Float32s) archsimd.Float32s, want func(_, _ []float32) []float32) {
    70  	var z archsimd.Float32s
    71  	testSVEBinary(t, float32s, 4, z.Len(), archsimd.LoadFloat32s, f, archsimd.Float32s.Store, want)
    72  }
    73  
    74  func testFloat64sBinary(t *testing.T, f func(_, _ archsimd.Float64s) archsimd.Float64s, want func(_, _ []float64) []float64) {
    75  	var z archsimd.Float64s
    76  	testSVEBinary(t, float64s, 8, z.Len(), archsimd.LoadFloat64s, f, archsimd.Float64s.Store, want)
    77  }
    78  
    79  func testUint16sBinary(t *testing.T, f func(_, _ archsimd.Uint16s) archsimd.Uint16s, want func(_, _ []uint16) []uint16) {
    80  	var z archsimd.Uint16s
    81  	testSVEBinary(t, uint16s, 2, z.Len(), archsimd.LoadUint16s, f, archsimd.Uint16s.Store, want)
    82  }
    83  
    84  func testUint32sBinary(t *testing.T, f func(_, _ archsimd.Uint32s) archsimd.Uint32s, want func(_, _ []uint32) []uint32) {
    85  	var z archsimd.Uint32s
    86  	testSVEBinary(t, uint32s, 4, z.Len(), archsimd.LoadUint32s, f, archsimd.Uint32s.Store, want)
    87  }
    88  
    89  func testUint64sBinary(t *testing.T, f func(_, _ archsimd.Uint64s) archsimd.Uint64s, want func(_, _ []uint64) []uint64) {
    90  	var z archsimd.Uint64s
    91  	testSVEBinary(t, uint64s, 8, z.Len(), archsimd.LoadUint64s, f, archsimd.Uint64s.Store, want)
    92  }
    93  
    94  func testInt8sUnary(t *testing.T, f func(archsimd.Int8s) archsimd.Int8s, want func([]int8) []int8) {
    95  	var z archsimd.Int8s
    96  	testSVEUnary(t, int8s, 1, z.Len(), archsimd.LoadInt8s, f, archsimd.Int8s.Store, want)
    97  }
    98  
    99  func testInt16sUnary(t *testing.T, f func(archsimd.Int16s) archsimd.Int16s, want func([]int16) []int16) {
   100  	var z archsimd.Int16s
   101  	testSVEUnary(t, int16s, 2, z.Len(), archsimd.LoadInt16s, f, archsimd.Int16s.Store, want)
   102  }
   103  
   104  func testInt32sUnary(t *testing.T, f func(archsimd.Int32s) archsimd.Int32s, want func([]int32) []int32) {
   105  	var z archsimd.Int32s
   106  	testSVEUnary(t, int32s, 4, z.Len(), archsimd.LoadInt32s, f, archsimd.Int32s.Store, want)
   107  }
   108  
   109  func testInt64sUnary(t *testing.T, f func(archsimd.Int64s) archsimd.Int64s, want func([]int64) []int64) {
   110  	var z archsimd.Int64s
   111  	testSVEUnary(t, int64s, 8, z.Len(), archsimd.LoadInt64s, f, archsimd.Int64s.Store, want)
   112  }
   113  
   114  func testUint8sUnary(t *testing.T, f func(archsimd.Uint8s) archsimd.Uint8s, want func([]uint8) []uint8) {
   115  	var z archsimd.Uint8s
   116  	testSVEUnary(t, uint8s, 1, z.Len(), archsimd.LoadUint8s, f, archsimd.Uint8s.Store, want)
   117  }
   118  
   119  func testUint16sUnary(t *testing.T, f func(archsimd.Uint16s) archsimd.Uint16s, want func([]uint16) []uint16) {
   120  	var z archsimd.Uint16s
   121  	testSVEUnary(t, uint16s, 2, z.Len(), archsimd.LoadUint16s, f, archsimd.Uint16s.Store, want)
   122  }
   123  
   124  func testUint32sUnary(t *testing.T, f func(archsimd.Uint32s) archsimd.Uint32s, want func([]uint32) []uint32) {
   125  	var z archsimd.Uint32s
   126  	testSVEUnary(t, uint32s, 4, z.Len(), archsimd.LoadUint32s, f, archsimd.Uint32s.Store, want)
   127  }
   128  
   129  func testUint64sUnary(t *testing.T, f func(archsimd.Uint64s) archsimd.Uint64s, want func([]uint64) []uint64) {
   130  	var z archsimd.Uint64s
   131  	testSVEUnary(t, uint64s, 8, z.Len(), archsimd.LoadUint64s, f, archsimd.Uint64s.Store, want)
   132  }
   133  
   134  func testFloat32sUnary(t *testing.T, f func(archsimd.Float32s) archsimd.Float32s, want func([]float32) []float32) {
   135  	var z archsimd.Float32s
   136  	testSVEUnary(t, float32s, 4, z.Len(), archsimd.LoadFloat32s, f, archsimd.Float32s.Store, want)
   137  }
   138  
   139  func testFloat64sUnary(t *testing.T, f func(archsimd.Float64s) archsimd.Float64s, want func([]float64) []float64) {
   140  	var z archsimd.Float64s
   141  	testSVEUnary(t, float64s, 8, z.Len(), archsimd.LoadFloat64s, f, archsimd.Float64s.Store, want)
   142  }
   143  
   144  func TestAddSVE(t *testing.T) {
   145  	if !archsimd.ARM64.SVE() {
   146  		t.Skip("no SVE")
   147  	}
   148  	testInt8sBinary(t, archsimd.Int8s.Add, addSlice[int8])
   149  	testInt16sBinary(t, archsimd.Int16s.Add, addSlice[int16])
   150  	testInt32sBinary(t, archsimd.Int32s.Add, addSlice[int32])
   151  	testInt64sBinary(t, archsimd.Int64s.Add, addSlice[int64])
   152  	testUint8sBinary(t, archsimd.Uint8s.Add, addSlice[uint8])
   153  	testUint16sBinary(t, archsimd.Uint16s.Add, addSlice[uint16])
   154  	testUint32sBinary(t, archsimd.Uint32s.Add, addSlice[uint32])
   155  	testUint64sBinary(t, archsimd.Uint64s.Add, addSlice[uint64])
   156  	testFloat32sBinary(t, archsimd.Float32s.Add, addSlice[float32])
   157  	testFloat64sBinary(t, archsimd.Float64s.Add, addSlice[float64])
   158  }
   159  
   160  func TestSubSVE(t *testing.T) {
   161  	if !archsimd.ARM64.SVE() {
   162  		t.Skip("no SVE")
   163  	}
   164  	testInt8sBinary(t, archsimd.Int8s.Sub, subSlice[int8])
   165  	testInt16sBinary(t, archsimd.Int16s.Sub, subSlice[int16])
   166  	testInt32sBinary(t, archsimd.Int32s.Sub, subSlice[int32])
   167  	testInt64sBinary(t, archsimd.Int64s.Sub, subSlice[int64])
   168  	testUint8sBinary(t, archsimd.Uint8s.Sub, subSlice[uint8])
   169  	testUint16sBinary(t, archsimd.Uint16s.Sub, subSlice[uint16])
   170  	testUint32sBinary(t, archsimd.Uint32s.Sub, subSlice[uint32])
   171  	testUint64sBinary(t, archsimd.Uint64s.Sub, subSlice[uint64])
   172  	testFloat32sBinary(t, archsimd.Float32s.Sub, subSlice[float32])
   173  	testFloat64sBinary(t, archsimd.Float64s.Sub, subSlice[float64])
   174  }
   175  
   176  // testSVEUnary drives a scalable unary op, the one-input counterpart of
   177  // testSVEBinary.
   178  func testSVEUnary[T number, V any](t *testing.T, pool []T, elemBytes, active int,
   179  	load func([]T) V, f func(V) V, store func(V, []T), want func([]T) []T) {
   180  	t.Helper()
   181  	count := sveMaxBytes / elemBytes
   182  	forSlice(t, pool, count, func(x []T) bool {
   183  		t.Helper()
   184  		g := make([]T, count)
   185  		store(f(load(x)), g)
   186  		w := want(x)
   187  		return checkSlicesLogInput(t, g[:active], w[:active], 0.0, func() {
   188  			t.Helper()
   189  			t.Logf("x=%v", x)
   190  		})
   191  	})
   192  }
   193  
   194  func TestAbsSVE(t *testing.T) {
   195  	if !archsimd.ARM64.SVE() {
   196  		t.Skip("no SVE")
   197  	}
   198  	testFloat32sUnary(t, archsimd.Float32s.Abs, absSlice[float32])
   199  	testFloat64sUnary(t, archsimd.Float64s.Abs, absSlice[float64])
   200  }
   201  
   202  func TestNegSVE(t *testing.T) {
   203  	if !archsimd.ARM64.SVE() {
   204  		t.Skip("no SVE")
   205  	}
   206  	testInt8sUnary(t, archsimd.Int8s.Neg, negSlice[int8])
   207  	testInt16sUnary(t, archsimd.Int16s.Neg, negSlice[int16])
   208  	testInt32sUnary(t, archsimd.Int32s.Neg, negSlice[int32])
   209  	testInt64sUnary(t, archsimd.Int64s.Neg, negSlice[int64])
   210  	testFloat32sUnary(t, archsimd.Float32s.Neg, negSlice[float32])
   211  	testFloat64sUnary(t, archsimd.Float64s.Neg, negSlice[float64])
   212  }
   213  
   214  func TestSqrtSVE(t *testing.T) {
   215  	if !archsimd.ARM64.SVE() {
   216  		t.Skip("no SVE")
   217  	}
   218  	testFloat32sUnary(t, archsimd.Float32s.Sqrt, sqrtSlice[float32])
   219  	testFloat64sUnary(t, archsimd.Float64s.Sqrt, sqrtSlice[float64])
   220  }
   221  
   222  func TestCeilSVE(t *testing.T) {
   223  	if !archsimd.ARM64.SVE() {
   224  		t.Skip("no SVE")
   225  	}
   226  	testFloat32sUnary(t, archsimd.Float32s.Ceil, ceilSlice[float32])
   227  	testFloat64sUnary(t, archsimd.Float64s.Ceil, ceilSlice[float64])
   228  }
   229  
   230  func TestFloorSVE(t *testing.T) {
   231  	if !archsimd.ARM64.SVE() {
   232  		t.Skip("no SVE")
   233  	}
   234  	testFloat32sUnary(t, archsimd.Float32s.Floor, floorSlice[float32])
   235  	testFloat64sUnary(t, archsimd.Float64s.Floor, floorSlice[float64])
   236  }
   237  
   238  func TestTruncSVE(t *testing.T) {
   239  	if !archsimd.ARM64.SVE() {
   240  		t.Skip("no SVE")
   241  	}
   242  	testFloat32sUnary(t, archsimd.Float32s.Trunc, truncSlice[float32])
   243  	testFloat64sUnary(t, archsimd.Float64s.Trunc, truncSlice[float64])
   244  }
   245  
   246  func TestRoundSVE(t *testing.T) {
   247  	if !archsimd.ARM64.SVE() {
   248  		t.Skip("no SVE")
   249  	}
   250  	testFloat32sUnary(t, archsimd.Float32s.Round, roundSlice[float32])
   251  	testFloat64sUnary(t, archsimd.Float64s.Round, roundSlice[float64])
   252  }
   253  
   254  // ifElseSlice returns, lane by lane, op(x) where x > y and y elsewhere.
   255  func ifElseSlice[T float32 | float64](op func([]T) []T) func(x, y []T) []T {
   256  	return func(x, y []T) []T {
   257  		r := op(x)
   258  		for i := range r {
   259  			if !(x[i] > y[i]) {
   260  				r[i] = y[i]
   261  			}
   262  		}
   263  		return r
   264  	}
   265  }
   266  
   267  // TestRoundingIfElseSVE checks the rounding operations under a select, which
   268  // folds into their merging-predicated forms.
   269  func TestRoundingIfElseSVE(t *testing.T) {
   270  	if !archsimd.ARM64.SVE() {
   271  		t.Skip("no SVE")
   272  	}
   273  	testFloat32sBinary(t, func(x, y archsimd.Float32s) archsimd.Float32s { return x.Ceil().IfElse(x.Greater(y), y) }, ifElseSlice(ceilSlice[float32]))
   274  	testFloat64sBinary(t, func(x, y archsimd.Float64s) archsimd.Float64s { return x.Ceil().IfElse(x.Greater(y), y) }, ifElseSlice(ceilSlice[float64]))
   275  	testFloat32sBinary(t, func(x, y archsimd.Float32s) archsimd.Float32s { return x.Floor().IfElse(x.Greater(y), y) }, ifElseSlice(floorSlice[float32]))
   276  	testFloat64sBinary(t, func(x, y archsimd.Float64s) archsimd.Float64s { return x.Floor().IfElse(x.Greater(y), y) }, ifElseSlice(floorSlice[float64]))
   277  	testFloat32sBinary(t, func(x, y archsimd.Float32s) archsimd.Float32s { return x.Trunc().IfElse(x.Greater(y), y) }, ifElseSlice(truncSlice[float32]))
   278  	testFloat64sBinary(t, func(x, y archsimd.Float64s) archsimd.Float64s { return x.Trunc().IfElse(x.Greater(y), y) }, ifElseSlice(truncSlice[float64]))
   279  	testFloat32sBinary(t, func(x, y archsimd.Float32s) archsimd.Float32s { return x.Round().IfElse(x.Greater(y), y) }, ifElseSlice(roundSlice[float32]))
   280  	testFloat64sBinary(t, func(x, y archsimd.Float64s) archsimd.Float64s { return x.Round().IfElse(x.Greater(y), y) }, ifElseSlice(roundSlice[float64]))
   281  }
   282  
   283  func TestAndSVE(t *testing.T) {
   284  	if !archsimd.ARM64.SVE() {
   285  		t.Skip("no SVE")
   286  	}
   287  	testInt8sBinary(t, archsimd.Int8s.And, andSlice[int8])
   288  	testInt16sBinary(t, archsimd.Int16s.And, andSlice[int16])
   289  	testInt32sBinary(t, archsimd.Int32s.And, andSlice[int32])
   290  	testInt64sBinary(t, archsimd.Int64s.And, andSlice[int64])
   291  	testUint8sBinary(t, archsimd.Uint8s.And, andSlice[uint8])
   292  	testUint16sBinary(t, archsimd.Uint16s.And, andSlice[uint16])
   293  	testUint32sBinary(t, archsimd.Uint32s.And, andSlice[uint32])
   294  	testUint64sBinary(t, archsimd.Uint64s.And, andSlice[uint64])
   295  }
   296  
   297  func TestOrSVE(t *testing.T) {
   298  	if !archsimd.ARM64.SVE() {
   299  		t.Skip("no SVE")
   300  	}
   301  	testInt8sBinary(t, archsimd.Int8s.Or, orSlice[int8])
   302  	testInt16sBinary(t, archsimd.Int16s.Or, orSlice[int16])
   303  	testInt32sBinary(t, archsimd.Int32s.Or, orSlice[int32])
   304  	testInt64sBinary(t, archsimd.Int64s.Or, orSlice[int64])
   305  	testUint8sBinary(t, archsimd.Uint8s.Or, orSlice[uint8])
   306  	testUint16sBinary(t, archsimd.Uint16s.Or, orSlice[uint16])
   307  	testUint32sBinary(t, archsimd.Uint32s.Or, orSlice[uint32])
   308  	testUint64sBinary(t, archsimd.Uint64s.Or, orSlice[uint64])
   309  }
   310  
   311  func TestXorSVE(t *testing.T) {
   312  	if !archsimd.ARM64.SVE() {
   313  		t.Skip("no SVE")
   314  	}
   315  	testInt8sBinary(t, archsimd.Int8s.Xor, xorSlice[int8])
   316  	testInt16sBinary(t, archsimd.Int16s.Xor, xorSlice[int16])
   317  	testInt32sBinary(t, archsimd.Int32s.Xor, xorSlice[int32])
   318  	testInt64sBinary(t, archsimd.Int64s.Xor, xorSlice[int64])
   319  	testUint8sBinary(t, archsimd.Uint8s.Xor, xorSlice[uint8])
   320  	testUint16sBinary(t, archsimd.Uint16s.Xor, xorSlice[uint16])
   321  	testUint32sBinary(t, archsimd.Uint32s.Xor, xorSlice[uint32])
   322  	testUint64sBinary(t, archsimd.Uint64s.Xor, xorSlice[uint64])
   323  }
   324  
   325  func TestAndNotSVE(t *testing.T) {
   326  	if !archsimd.ARM64.SVE() {
   327  		t.Skip("no SVE")
   328  	}
   329  	testInt8sBinary(t, archsimd.Int8s.AndNot, andNotSlice[int8])
   330  	testInt16sBinary(t, archsimd.Int16s.AndNot, andNotSlice[int16])
   331  	testInt32sBinary(t, archsimd.Int32s.AndNot, andNotSlice[int32])
   332  	testInt64sBinary(t, archsimd.Int64s.AndNot, andNotSlice[int64])
   333  	testUint8sBinary(t, archsimd.Uint8s.AndNot, andNotSlice[uint8])
   334  	testUint16sBinary(t, archsimd.Uint16s.AndNot, andNotSlice[uint16])
   335  	testUint32sBinary(t, archsimd.Uint32s.AndNot, andNotSlice[uint32])
   336  	testUint64sBinary(t, archsimd.Uint64s.AndNot, andNotSlice[uint64])
   337  }
   338  
   339  func TestMulSVE(t *testing.T) {
   340  	if !archsimd.ARM64.SVE() {
   341  		t.Skip("no SVE")
   342  	}
   343  	testFloat32sBinary(t, archsimd.Float32s.Mul, mulSlice[float32])
   344  	testFloat64sBinary(t, archsimd.Float64s.Mul, mulSlice[float64])
   345  	// Ungated: integer Mul compiles to the merging-predicated fallback,
   346  	// correct on any SVE.
   347  	testInt8sBinary(t, archsimd.Int8s.Mul, mulSlice[int8])
   348  	testInt16sBinary(t, archsimd.Int16s.Mul, mulSlice[int16])
   349  	testInt32sBinary(t, archsimd.Int32s.Mul, mulSlice[int32])
   350  	testInt64sBinary(t, archsimd.Int64s.Mul, mulSlice[int64])
   351  	testUint8sBinary(t, archsimd.Uint8s.Mul, mulSlice[uint8])
   352  	testUint16sBinary(t, archsimd.Uint16s.Mul, mulSlice[uint16])
   353  	testUint32sBinary(t, archsimd.Uint32s.Mul, mulSlice[uint32])
   354  	testUint64sBinary(t, archsimd.Uint64s.Mul, mulSlice[uint64])
   355  	if archsimd.ARM64.SVE2() {
   356  		// Gated: this block compiles to the unpredicated SVE2 encoding.
   357  		testInt8sBinary(t, archsimd.Int8s.Mul, mulSlice[int8])
   358  		testInt16sBinary(t, archsimd.Int16s.Mul, mulSlice[int16])
   359  		testInt32sBinary(t, archsimd.Int32s.Mul, mulSlice[int32])
   360  		testInt64sBinary(t, archsimd.Int64s.Mul, mulSlice[int64])
   361  		testUint8sBinary(t, archsimd.Uint8s.Mul, mulSlice[uint8])
   362  		testUint16sBinary(t, archsimd.Uint16s.Mul, mulSlice[uint16])
   363  		testUint32sBinary(t, archsimd.Uint32s.Mul, mulSlice[uint32])
   364  		testUint64sBinary(t, archsimd.Uint64s.Mul, mulSlice[uint64])
   365  	}
   366  }
   367  
   368  func TestMulHighSVE(t *testing.T) {
   369  	if !archsimd.ARM64.SVE() {
   370  		t.Skip("no SVE")
   371  	}
   372  	// Ungated: compiles to the merging-predicated fallback, correct on any SVE.
   373  	testInt8sBinary(t, archsimd.Int8s.MulHigh, mulHighSlice[int8])
   374  	testInt16sBinary(t, archsimd.Int16s.MulHigh, mulHighSlice[int16])
   375  	testInt32sBinary(t, archsimd.Int32s.MulHigh, mulHighSlice[int32])
   376  	testInt64sBinary(t, archsimd.Int64s.MulHigh, mulHighSlice[int64])
   377  	testUint8sBinary(t, archsimd.Uint8s.MulHigh, mulHighSlice[uint8])
   378  	testUint16sBinary(t, archsimd.Uint16s.MulHigh, mulHighSlice[uint16])
   379  	testUint32sBinary(t, archsimd.Uint32s.MulHigh, mulHighSlice[uint32])
   380  	testUint64sBinary(t, archsimd.Uint64s.MulHigh, mulHighSlice[uint64])
   381  	if archsimd.ARM64.SVE2() {
   382  		// Gated: this block compiles to the unpredicated SVE2 encodings.
   383  		testInt8sBinary(t, archsimd.Int8s.MulHigh, mulHighSlice[int8])
   384  		testInt16sBinary(t, archsimd.Int16s.MulHigh, mulHighSlice[int16])
   385  		testInt32sBinary(t, archsimd.Int32s.MulHigh, mulHighSlice[int32])
   386  		testInt64sBinary(t, archsimd.Int64s.MulHigh, mulHighSlice[int64])
   387  		testUint8sBinary(t, archsimd.Uint8s.MulHigh, mulHighSlice[uint8])
   388  		testUint16sBinary(t, archsimd.Uint16s.MulHigh, mulHighSlice[uint16])
   389  		testUint32sBinary(t, archsimd.Uint32s.MulHigh, mulHighSlice[uint32])
   390  		testUint64sBinary(t, archsimd.Uint64s.MulHigh, mulHighSlice[uint64])
   391  	}
   392  }
   393  
   394  func TestMaxSVE(t *testing.T) {
   395  	if !archsimd.ARM64.SVE() {
   396  		t.Skip("no SVE")
   397  	}
   398  	testInt8sBinary(t, archsimd.Int8s.Max, maxSlice[int8])
   399  	testInt16sBinary(t, archsimd.Int16s.Max, maxSlice[int16])
   400  	testInt32sBinary(t, archsimd.Int32s.Max, maxSlice[int32])
   401  	testInt64sBinary(t, archsimd.Int64s.Max, maxSlice[int64])
   402  	testUint8sBinary(t, archsimd.Uint8s.Max, maxSlice[uint8])
   403  	testUint16sBinary(t, archsimd.Uint16s.Max, maxSlice[uint16])
   404  	testUint32sBinary(t, archsimd.Uint32s.Max, maxSlice[uint32])
   405  	testUint64sBinary(t, archsimd.Uint64s.Max, maxSlice[uint64])
   406  	testFloat32sBinary(t, archsimd.Float32s.Max, maxSlice[float32])
   407  	testFloat64sBinary(t, archsimd.Float64s.Max, maxSlice[float64])
   408  }
   409  
   410  func TestMinSVE(t *testing.T) {
   411  	if !archsimd.ARM64.SVE() {
   412  		t.Skip("no SVE")
   413  	}
   414  	testInt8sBinary(t, archsimd.Int8s.Min, minSlice[int8])
   415  	testInt16sBinary(t, archsimd.Int16s.Min, minSlice[int16])
   416  	testInt32sBinary(t, archsimd.Int32s.Min, minSlice[int32])
   417  	testInt64sBinary(t, archsimd.Int64s.Min, minSlice[int64])
   418  	testUint8sBinary(t, archsimd.Uint8s.Min, minSlice[uint8])
   419  	testUint16sBinary(t, archsimd.Uint16s.Min, minSlice[uint16])
   420  	testUint32sBinary(t, archsimd.Uint32s.Min, minSlice[uint32])
   421  	testUint64sBinary(t, archsimd.Uint64s.Min, minSlice[uint64])
   422  	testFloat32sBinary(t, archsimd.Float32s.Min, minSlice[float32])
   423  	testFloat64sBinary(t, archsimd.Float64s.Min, minSlice[float64])
   424  }
   425  
   426  func TestDivSVE(t *testing.T) {
   427  	if !archsimd.ARM64.SVE() {
   428  		t.Skip("no SVE")
   429  	}
   430  	// Integer division exists only for 32- and 64-bit elements.
   431  	testInt32sBinary(t, archsimd.Int32s.Div, intDivSlice[int32])
   432  	testInt64sBinary(t, archsimd.Int64s.Div, intDivSlice[int64])
   433  	testUint32sBinary(t, archsimd.Uint32s.Div, intDivSlice[uint32])
   434  	testUint64sBinary(t, archsimd.Uint64s.Div, intDivSlice[uint64])
   435  	testFloat32sBinary(t, archsimd.Float32s.Div, divSlice[float32])
   436  	testFloat64sBinary(t, archsimd.Float64s.Div, divSlice[float64])
   437  }
   438  

View as plain text