// Copyright 2025 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 && amd64 package simd_test import ( "math" ) func less[T number](x, y T) bool { return x < y } func lessEqual[T number](x, y T) bool { return x <= y } func greater[T number](x, y T) bool { return x > y } func greaterEqual[T number](x, y T) bool { return x >= y } func equal[T number](x, y T) bool { return x == y } func notEqual[T number](x, y T) bool { return x != y } func abs[T number](x T) T { // TODO this will need a non-standard FP-equality test. if x == 0 { // true if x is -0. return 0 // this is not a negative zero } if x < 0 { return -x } return x } func ceil[T float](x T) T { return T(math.Ceil(float64(x))) } func floor[T float](x T) T { return T(math.Floor(float64(x))) } func not[T integer](x T) T { return ^x } func round[T float](x T) T { return T(math.RoundToEven(float64(x))) } func sqrt[T float](x T) T { return T(math.Sqrt(float64(x))) } func trunc[T float](x T) T { return T(math.Trunc(float64(x))) } func add[T number](x, y T) T { return x + y } func sub[T number](x, y T) T { return x - y } func max_[T number](x, y T) T { // "max" lands in infinite recursion return max(x, y) } func min_[T number](x, y T) T { // "min" lands in infinite recursion return min(x, y) } // Also mulLow for integers func mul[T number](x, y T) T { return x * y } func div[T number](x, y T) T { return x / y } func and[T integer](x, y T) T { return x & y } func andNotI[T integer](x, y T) T { return x & ^y // order corrected to match expectations } func orI[T integer](x, y T) T { return x | y } func xorI[T integer](x, y T) T { return x ^ y } func ima[T integer](x, y, z T) T { return x*y + z } func fma[T float](x, y, z T) T { return T(math.FMA(float64(x), float64(y), float64(z))) } func toUint8[T number](x T) uint8 { return uint8(x) } func toUint16[T number](x T) uint16 { return uint16(x) } func toUint64[T number](x T) uint64 { return uint64(x) } func toUint32[T number](x T) uint32 { switch y := (any(x)).(type) { case float32: if y < 0 || y > float32(math.MaxUint32) || y != y { return math.MaxUint32 } case float64: if y < 0 || y > float64(math.MaxUint32) || y != y { return math.MaxUint32 } } return uint32(x) } func toInt8[T number](x T) int8 { return int8(x) } func toInt16[T number](x T) int16 { return int16(x) } func toInt32[T number](x T) int32 { return int32(x) } func toInt64[T number](x T) int64 { return int64(x) } func toFloat32[T number](x T) float32 { return float32(x) } func toFloat64[T number](x T) float64 { return float64(x) } func ceilResidueForPrecision[T float](i int) func(T) T { f := 1.0 for i > 0 { f *= 2 i-- } return func(x T) T { y := float64(x) if math.IsInf(float64(x*T(f)), 0) { return 0 } // TODO sort out the rounding issues when T === float32 return T(y - math.Ceil(y*f)/f) } } // Slice versions of all these elementwise operations func addSlice[T number](x, y []T) []T { return map2[T](add)(x, y) } func subSlice[T number](x, y []T) []T { return map2[T](sub)(x, y) } func maxSlice[T number](x, y []T) []T { return map2[T](max_)(x, y) } func minSlice[T number](x, y []T) []T { return map2[T](min_)(x, y) } // mulLow for integers func mulSlice[T number](x, y []T) []T { return map2[T](mul)(x, y) } func divSlice[T number](x, y []T) []T { return map2[T](div)(x, y) } func andSlice[T integer](x, y []T) []T { return map2[T](and)(x, y) } func andNotSlice[T integer](x, y []T) []T { return map2[T](andNotI)(x, y) } func orSlice[T integer](x, y []T) []T { return map2[T](orI)(x, y) } func xorSlice[T integer](x, y []T) []T { return map2[T](xorI)(x, y) } func lessSlice[T number](x, y []T) []int64 { return mapCompare[T](less)(x, y) } func lessEqualSlice[T number](x, y []T) []int64 { return mapCompare[T](lessEqual)(x, y) } func greaterSlice[T number](x, y []T) []int64 { return mapCompare[T](greater)(x, y) } func greaterEqualSlice[T number](x, y []T) []int64 { return mapCompare[T](greaterEqual)(x, y) } func equalSlice[T number](x, y []T) []int64 { return mapCompare[T](equal)(x, y) } func notEqualSlice[T number](x, y []T) []int64 { return mapCompare[T](notEqual)(x, y) } func ceilSlice[T float](x []T) []T { return map1[T](ceil)(x) } func floorSlice[T float](x []T) []T { return map1[T](floor)(x) } func notSlice[T integer](x []T) []T { return map1[T](not)(x) } func roundSlice[T float](x []T) []T { return map1[T](round)(x) } func sqrtSlice[T float](x []T) []T { return map1[T](sqrt)(x) } func truncSlice[T float](x []T) []T { return map1[T](trunc)(x) } func imaSlice[T integer](x, y, z []T) []T { return map3[T](ima)(x, y, z) } func fmaSlice[T float](x, y, z []T) []T { return map3[T](fma)(x, y, z) }