// 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" ) // fcvtzs32 is FCVTZS on one float32: truncate toward zero, saturate out of // range values, and convert NaN to 0. func fcvtzs32(x float32) int32 { switch { case x != x: return 0 case x >= math.MaxInt32: return math.MaxInt32 case x <= math.MinInt32: return math.MinInt32 } return int32(x) } func TestConvertToInt32SVE(t *testing.T) { if !archsimd.ARM64.SVE() { t.Skip("no SVE") } n := archsimd.Float32s{}.Len() vals := []float32{0, 0.5, -0.5, 1.5, -1.5, 2.999, -2.999, 1e9, -1e9, 3e9, -3e9, float32(math.Inf(1)), float32(math.Inf(-1)), float32(math.NaN()), float32(math.Copysign(0, -1))} xs := make([]float32, n) got := make([]int32, n) for start := 0; start < len(vals); start += n { for i := range xs { xs[i] = vals[(start+i)%len(vals)] } archsimd.LoadFloat32s(xs).ConvertToInt32().Store(got) for i, x := range xs { if want := fcvtzs32(x); got[i] != want { t.Errorf("ConvertToInt32(%v) = %d, want %d", x, got[i], want) } } } // A select over the conversion folds into its merging form. ys := make([]int32, n) for i := range xs { xs[i] = float32(i) + 0.75 ys[i] = -int32(i) - 100 } m := archsimd.LoadFloat32s(xs).Greater(archsimd.BroadcastFloat32s(float32(n) / 2)) archsimd.LoadFloat32s(xs).ConvertToInt32().IfElse(m, archsimd.LoadInt32s(ys)).Store(got) for i, x := range xs { want := ys[i] if x > float32(n)/2 { want = int32(i) } if got[i] != want { t.Errorf("ConvertToInt32 under IfElse: lane %d = %d, want %d", i, got[i], want) } } }