Source file src/simd/internal/simd_test/simulation_helpers_test.go

     1  // Copyright 2025 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 && amd64
     6  
     7  package simd_test
     8  
     9  import (
    10  	"math"
    11  )
    12  
    13  func less[T number](x, y T) bool {
    14  	return x < y
    15  }
    16  func lessEqual[T number](x, y T) bool {
    17  	return x <= y
    18  }
    19  func greater[T number](x, y T) bool {
    20  	return x > y
    21  }
    22  func greaterEqual[T number](x, y T) bool {
    23  	return x >= y
    24  }
    25  func equal[T number](x, y T) bool {
    26  	return x == y
    27  }
    28  func notEqual[T number](x, y T) bool {
    29  	return x != y
    30  }
    31  
    32  func abs[T number](x T) T {
    33  	// TODO this will need a non-standard FP-equality test.
    34  	if x == 0 { // true if x is -0.
    35  		return 0 // this is not a negative zero
    36  	}
    37  	if x < 0 {
    38  		return -x
    39  	}
    40  	return x
    41  }
    42  
    43  func ceil[T float](x T) T {
    44  	return T(math.Ceil(float64(x)))
    45  }
    46  func floor[T float](x T) T {
    47  	return T(math.Floor(float64(x)))
    48  }
    49  func not[T integer](x T) T {
    50  	return ^x
    51  }
    52  func round[T float](x T) T {
    53  	return T(math.RoundToEven(float64(x)))
    54  }
    55  func sqrt[T float](x T) T {
    56  	return T(math.Sqrt(float64(x)))
    57  }
    58  func trunc[T float](x T) T {
    59  	return T(math.Trunc(float64(x)))
    60  }
    61  
    62  func add[T number](x, y T) T {
    63  	return x + y
    64  }
    65  
    66  func sub[T number](x, y T) T {
    67  	return x - y
    68  }
    69  
    70  func max_[T number](x, y T) T { // "max" lands in infinite recursion
    71  	return max(x, y)
    72  }
    73  
    74  func min_[T number](x, y T) T { // "min" lands in infinite recursion
    75  	return min(x, y)
    76  }
    77  
    78  // Also mulLow for integers
    79  func mul[T number](x, y T) T {
    80  	return x * y
    81  }
    82  
    83  func div[T number](x, y T) T {
    84  	return x / y
    85  }
    86  
    87  func and[T integer](x, y T) T {
    88  	return x & y
    89  }
    90  
    91  func andNotI[T integer](x, y T) T {
    92  	return x & ^y // order corrected to match expectations
    93  }
    94  
    95  func orI[T integer](x, y T) T {
    96  	return x | y
    97  }
    98  
    99  func xorI[T integer](x, y T) T {
   100  	return x ^ y
   101  }
   102  
   103  func ima[T integer](x, y, z T) T {
   104  	return x*y + z
   105  }
   106  
   107  func fma[T float](x, y, z T) T {
   108  	return T(math.FMA(float64(x), float64(y), float64(z)))
   109  }
   110  
   111  func toUint8[T number](x T) uint8 {
   112  	return uint8(x)
   113  }
   114  
   115  func toUint16[T number](x T) uint16 {
   116  	return uint16(x)
   117  }
   118  
   119  func toUint64[T number](x T) uint64 {
   120  	return uint64(x)
   121  }
   122  
   123  func toUint32[T number](x T) uint32 {
   124  	switch y := (any(x)).(type) {
   125  	case float32:
   126  		if y < 0 || y > float32(math.MaxUint32) || y != y {
   127  			return math.MaxUint32
   128  		}
   129  	case float64:
   130  		if y < 0 || y > float64(math.MaxUint32) || y != y {
   131  			return math.MaxUint32
   132  		}
   133  	}
   134  	return uint32(x)
   135  }
   136  
   137  func toInt8[T number](x T) int8 {
   138  	return int8(x)
   139  }
   140  
   141  func toInt16[T number](x T) int16 {
   142  	return int16(x)
   143  }
   144  
   145  func toInt32[T number](x T) int32 {
   146  	return int32(x)
   147  }
   148  
   149  func toInt64[T number](x T) int64 {
   150  	return int64(x)
   151  }
   152  
   153  func toFloat32[T number](x T) float32 {
   154  	return float32(x)
   155  }
   156  
   157  func toFloat64[T number](x T) float64 {
   158  	return float64(x)
   159  }
   160  
   161  func ceilResidueForPrecision[T float](i int) func(T) T {
   162  	f := 1.0
   163  	for i > 0 {
   164  		f *= 2
   165  		i--
   166  	}
   167  	return func(x T) T {
   168  		y := float64(x)
   169  		if math.IsInf(float64(x*T(f)), 0) {
   170  			return 0
   171  		}
   172  		// TODO sort out the rounding issues when T === float32
   173  		return T(y - math.Ceil(y*f)/f)
   174  	}
   175  }
   176  
   177  // Slice versions of all these elementwise operations
   178  
   179  func addSlice[T number](x, y []T) []T {
   180  	return map2[T](add)(x, y)
   181  }
   182  
   183  func subSlice[T number](x, y []T) []T {
   184  	return map2[T](sub)(x, y)
   185  }
   186  
   187  func maxSlice[T number](x, y []T) []T {
   188  	return map2[T](max_)(x, y)
   189  }
   190  
   191  func minSlice[T number](x, y []T) []T {
   192  	return map2[T](min_)(x, y)
   193  }
   194  
   195  // mulLow for integers
   196  func mulSlice[T number](x, y []T) []T {
   197  	return map2[T](mul)(x, y)
   198  }
   199  
   200  func divSlice[T number](x, y []T) []T {
   201  	return map2[T](div)(x, y)
   202  }
   203  
   204  func andSlice[T integer](x, y []T) []T {
   205  	return map2[T](and)(x, y)
   206  }
   207  
   208  func andNotSlice[T integer](x, y []T) []T {
   209  	return map2[T](andNotI)(x, y)
   210  }
   211  
   212  func orSlice[T integer](x, y []T) []T {
   213  	return map2[T](orI)(x, y)
   214  }
   215  
   216  func xorSlice[T integer](x, y []T) []T {
   217  	return map2[T](xorI)(x, y)
   218  }
   219  
   220  func lessSlice[T number](x, y []T) []int64 {
   221  	return mapCompare[T](less)(x, y)
   222  }
   223  
   224  func lessEqualSlice[T number](x, y []T) []int64 {
   225  	return mapCompare[T](lessEqual)(x, y)
   226  }
   227  
   228  func greaterSlice[T number](x, y []T) []int64 {
   229  	return mapCompare[T](greater)(x, y)
   230  }
   231  
   232  func greaterEqualSlice[T number](x, y []T) []int64 {
   233  	return mapCompare[T](greaterEqual)(x, y)
   234  }
   235  
   236  func equalSlice[T number](x, y []T) []int64 {
   237  	return mapCompare[T](equal)(x, y)
   238  }
   239  
   240  func notEqualSlice[T number](x, y []T) []int64 {
   241  	return mapCompare[T](notEqual)(x, y)
   242  }
   243  
   244  func ceilSlice[T float](x []T) []T {
   245  	return map1[T](ceil)(x)
   246  }
   247  
   248  func floorSlice[T float](x []T) []T {
   249  	return map1[T](floor)(x)
   250  }
   251  
   252  func notSlice[T integer](x []T) []T {
   253  	return map1[T](not)(x)
   254  }
   255  
   256  func roundSlice[T float](x []T) []T {
   257  	return map1[T](round)(x)
   258  }
   259  
   260  func sqrtSlice[T float](x []T) []T {
   261  	return map1[T](sqrt)(x)
   262  }
   263  
   264  func truncSlice[T float](x []T) []T {
   265  	return map1[T](trunc)(x)
   266  }
   267  
   268  func imaSlice[T integer](x, y, z []T) []T {
   269  	return map3[T](ima)(x, y, z)
   270  }
   271  
   272  func fmaSlice[T float](x, y, z []T) []T {
   273  	return map3[T](fma)(x, y, z)
   274  }
   275  

View as plain text