| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| //go:build goexperiment.simd && arm64 | |
| package simd_test | |
| import ( | |
| "math" | |
| "simd/archsimd" | |
| "testing" | |
| ) | |
| type sveShiftCase[V any] struct { | |
| shift uint64 | |
| f func(V) V // x.ShiftAllLeft(shift) with shift a constant | |
| } | |
| // testSVEShiftAllLeft checks ShiftAllLeft by every amount in amounts, passed | |
| // as a variable, and by the constant amounts in consts, against Go's <<. | |
| func testSVEShiftAllLeft[T int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64, V any]( | |
| t *testing.T, name string, n int, load func([]T) V, store func(V, []T), | |
| shift func(V, uint64) V, consts []sveShiftCase[V]) { | |
| t.Helper() | |
| xs := make([]T, n) | |
| for i := range xs { | |
| xs[i] = T(i*37 - 5) // mixes signs and high bits | |
| } | |
| got := make([]T, n) | |
| check := func(s uint64, how string) { | |
| t.Helper() | |
| for i, x := range xs { | |
| if want := x << s; got[i] != want { | |
| t.Errorf("%s.ShiftAllLeft(%d) %s: lane %d = %v, want %v", name, s, how, i, got[i], want) | |
| return | |
| } | |
| } | |
| } | |
| for _, s := range []uint64{0, 1, 3, 7, 8, 15, 16, 31, 32, 63, 64, 65, 255, 256, 1 << 40, math.MaxUint64} { | |
| store(shift(load(xs), s), got) | |
| check(s, "by variable") | |
| } | |
| for _, c := range consts { | |
| store(c.f(load(xs)), got) | |
| check(c.shift, "by constant") | |
| } | |
| } | |
| func TestShiftAllLeftSVE(t *testing.T) { | |
| if !archsimd.ARM64.SVE() { | |
| t.Skip("no SVE") | |
| } | |
| testSVEShiftAllLeft(t, "Int8s", archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.Store, archsimd.Int8s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Int8s]{ | |
| {3, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(3) }}, | |
| {7, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(7) }}, | |
| {8, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(8) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Uint8s", archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.Store, archsimd.Uint8s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Uint8s]{ | |
| {1, func(x archsimd.Uint8s) archsimd.Uint8s { return x.ShiftAllLeft(1) }}, | |
| {200, func(x archsimd.Uint8s) archsimd.Uint8s { return x.ShiftAllLeft(200) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Int16s", archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.Store, archsimd.Int16s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Int16s]{ | |
| {15, func(x archsimd.Int16s) archsimd.Int16s { return x.ShiftAllLeft(15) }}, | |
| {16, func(x archsimd.Int16s) archsimd.Int16s { return x.ShiftAllLeft(16) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Uint16s", archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.Store, archsimd.Uint16s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Uint16s]{ | |
| {4, func(x archsimd.Uint16s) archsimd.Uint16s { return x.ShiftAllLeft(4) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Int32s", archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.Store, archsimd.Int32s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Int32s]{ | |
| {23, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(23) }}, | |
| {31, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(31) }}, | |
| {32, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(32) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Uint32s", archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.Store, archsimd.Uint32s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Uint32s]{ | |
| {0, func(x archsimd.Uint32s) archsimd.Uint32s { return x.ShiftAllLeft(0) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Int64s", archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.Store, archsimd.Int64s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Int64s]{ | |
| {52, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(52) }}, | |
| {63, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(63) }}, | |
| {64, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(64) }}, | |
| }) | |
| testSVEShiftAllLeft(t, "Uint64s", archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.Store, archsimd.Uint64s.ShiftAllLeft, | |
| []sveShiftCase[archsimd.Uint64s]{ | |
| {33, func(x archsimd.Uint64s) archsimd.Uint64s { return x.ShiftAllLeft(33) }}, | |
| }) | |
| } |