Source file src/simd/internal/spec/math.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 //simdgen:category Math 6 7 package spec 8 9 // Add adds corresponding elements of two vectors. 10 // 11 // z[i] = x[i] + y[i] 12 // 13 //specgen:commutative 14 func Add[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 15 return map2[E, W, E, W](x, y, func(x, y E) E { return x + y }) 16 } 17 18 // DotProductPairs multiplies corresponding elements of x and y, and sums 19 // adjacent pairs, yielding a vector of half as many elements with twice the 20 // input element size. 21 // 22 // w[i] = x[i] * y[i] // Double width 23 // z[i] = w[2*i] + w[2*i+1] 24 // 25 //specgen:commutative 26 //specgen:require z={xB}{xN*2}x{xL/2} 27 func DotProductPairs[E Nums, W Width, zE Nums](x, y Vec[E, W]) (z Vec[zE, W]) { 28 // TODO: How do we handle/specify overflow? x86 only supports this on signed 29 // types, and the only case that can overflow is if all four elements are 30 // MinInt16 (in which case the true result is MaxInt32+1, which wraps around 31 // to MinInt32). Unsigned types can overflow much more readily. 32 // 33 // Maybe we just leave overflow unspecified (or "architecture dependent"). 34 // In which case, we probably need a way to communicate that in the spec 35 // (designated panic?). 36 // 37 // We might also need a way to constraint this to same-signed E and zE, 38 // which the constraint language doesn't currently have a way to say, but we 39 // could add as a built-in projection function in the syntax. 40 z = makeVec[zE, W]() 41 for i := range z { 42 z[i] = zE(x[2*i])*zE(y[2*i]) + zE(x[2*i+1])*zE(y[2*i+1]) 43 } 44 return z 45 } 46 47 // DotProductPairsSaturated multiplies corresponding elements of x and y, and 48 // sums adjacent pairs, all with saturation. It yields a vector of half as many 49 // elements with twice the input element size. 50 // 51 // w[i] = x[i] * y[i] // Double width, saturated 52 // z[i] = w[2*i] + w[2*i+1] // Saturated 53 // 54 //specgen:commutative 55 //specgen:require y=Int{xN}x{xL} z=Int{xN*2}x{xL/2} 56 func DotProductPairsSaturated[xE Uints, xW Width, yE Ints, zE Ints](x Vec[xE, xW], y Vec[yE, xW]) (z Vec[zE, xW]) { 57 z = makeVec[zE, xW]() 58 for i := range z { 59 a := mulSaturatedUSS64(uint64(x[2*i]), int64(y[2*i])) 60 b := mulSaturatedUSS64(uint64(x[2*i+1]), int64(y[2*i+1])) 61 z[i] = saturateS[zE](addSaturatedSSS64(a, b)) 62 } 63 return z 64 } 65