Source file src/simd/archsimd/internal/simd_test/reduce_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  package simd_test
     8  
     9  import (
    10  	"math"
    11  	"simd/archsimd"
    12  	"testing"
    13  )
    14  
    15  // testSVEReduceSum checks a float ReduceSum. The values are small integers,
    16  // so every partial sum is exact and the result does not depend on the order
    17  // FADDV adds the lanes in.
    18  func testSVEReduceSum[T float32 | float64, V any](t *testing.T, name string, n int, load func([]T) V, sum func(V) T) {
    19  	t.Helper()
    20  	xs := make([]T, n)
    21  	for start := -20; start <= 20; start += 7 {
    22  		var want T
    23  		for i := range xs {
    24  			xs[i] = T(start + 3*i)
    25  			want += xs[i]
    26  		}
    27  		if got := sum(load(xs)); got != want {
    28  			t.Errorf("%s(%v) = %v, want %v", name, xs, got, want)
    29  		}
    30  	}
    31  
    32  	inf := T(math.Inf(1))
    33  	for _, c := range []struct {
    34  		lane    int
    35  		val     T
    36  		isNaN   bool
    37  		wantInf bool
    38  	}{
    39  		{0, T(math.NaN()), true, false},
    40  		{n - 1, T(math.NaN()), true, false},
    41  		{n / 2, inf, false, true},
    42  	} {
    43  		for i := range xs {
    44  			xs[i] = 1
    45  		}
    46  		xs[c.lane] = c.val
    47  		got := sum(load(xs))
    48  		switch {
    49  		case c.isNaN && got == got:
    50  			t.Errorf("%s with NaN in lane %d = %v, want NaN", name, c.lane, got)
    51  		case c.wantInf && got != inf:
    52  			t.Errorf("%s with +Inf in lane %d = %v, want +Inf", name, c.lane, got)
    53  		}
    54  	}
    55  }
    56  
    57  func TestReduceSumSVE(t *testing.T) {
    58  	if !archsimd.ARM64.SVE() {
    59  		t.Skip("no SVE")
    60  	}
    61  	testSVEReduceSum(t, "Float32s.ReduceSum", archsimd.Float32s{}.Len(), archsimd.LoadFloat32s, archsimd.Float32s.ReduceSum)
    62  	testSVEReduceSum(t, "Float64s.ReduceSum", archsimd.Float64s{}.Len(), archsimd.LoadFloat64s, archsimd.Float64s.ReduceSum)
    63  }
    64  
    65  // testSVEReduceMax checks a float ReduceMax with the maximum in each lane,
    66  // with NaN, and with signed zeros.
    67  func testSVEReduceMax[T float32 | float64, V any](t *testing.T, name string, n int, load func([]T) V, reduce func(V) T) {
    68  	t.Helper()
    69  	xs := make([]T, n)
    70  	for lane := range xs {
    71  		for i := range xs {
    72  			xs[i] = T(-3*i - 1)
    73  		}
    74  		xs[lane] = 5
    75  		if got := reduce(load(xs)); got != 5 {
    76  			t.Errorf("%s(%v) = %v, want 5", name, xs, got)
    77  		}
    78  	}
    79  
    80  	for i := range xs {
    81  		xs[i] = T(math.Inf(-1))
    82  	}
    83  	if got := reduce(load(xs)); got != T(math.Inf(-1)) {
    84  		t.Errorf("%s(all -Inf) = %v, want -Inf", name, got)
    85  	}
    86  
    87  	for _, lane := range []int{0, n / 2, n - 1} {
    88  		for i := range xs {
    89  			xs[i] = T(i)
    90  		}
    91  		xs[lane] = T(math.NaN())
    92  		if got := reduce(load(xs)); got == got {
    93  			t.Errorf("%s with NaN in lane %d = %v, want NaN", name, lane, got)
    94  		}
    95  	}
    96  
    97  	negZero := T(math.Copysign(0, -1))
    98  	for _, lane := range []int{0, n - 1} {
    99  		for i := range xs {
   100  			xs[i] = negZero
   101  		}
   102  		xs[lane] = 0
   103  		if got := reduce(load(xs)); got != 0 || math.Signbit(float64(got)) {
   104  			t.Errorf("%s of signed zeros with +0 in lane %d = %v, want +0", name, lane, got)
   105  		}
   106  	}
   107  }
   108  
   109  func TestReduceMaxSVE(t *testing.T) {
   110  	if !archsimd.ARM64.SVE() {
   111  		t.Skip("no SVE")
   112  	}
   113  	testSVEReduceMax(t, "Float32s.ReduceMax", archsimd.Float32s{}.Len(), archsimd.LoadFloat32s, archsimd.Float32s.ReduceMax)
   114  	testSVEReduceMax(t, "Float64s.ReduceMax", archsimd.Float64s{}.Len(), archsimd.LoadFloat64s, archsimd.Float64s.ReduceMax)
   115  }
   116  

View as plain text