Source file src/simd/internal/spec/math-concat.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 //specgen:category Math (concatenated) 6 7 package spec 8 9 // ConcatAddPairs horizontally adds adjacent pairs of elements in x and y and 10 // returns the concatenated result. 11 // 12 // {{if eq .xL 2}} 13 // 14 // z = {x[0]+x[1], y[0]+y[1]} 15 // 16 // {{else if eq .xL 4}} 17 // 18 // z = {x[0]+x[1], x[2]+x[3], y[0]+y[1], y[2]+y[3]} 19 // 20 // {{else}} 21 // 22 // z = {x[0]+x[1], x[2]+x[3], ..., y[0]+y[1], y[2]+y[3], ...} 23 // 24 // {{end}} 25 func ConcatAddPairs[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 26 z = makeVec[E, W]() 27 half := z.len() / 2 28 for i := 0; i < half; i++ { 29 z[i] = x[2*i] + x[2*i+1] 30 z[half+i] = y[2*i] + y[2*i+1] 31 } 32 return z 33 } 34 35 // ConcatSubPairs horizontally subtracts adjacent pairs of elements in x and y 36 // and returns the concatenated result. 37 // 38 // {{if eq .xL 2}} 39 // 40 // z = {x[0]-x[1], y[0]-y[1]} 41 // 42 // {{else if eq .xL 4}} 43 // 44 // z = {x[0]-x[1], x[2]-x[3], y[0]-y[1], y[2]-y[3]} 45 // 46 // {{else}} 47 // 48 // z = {x[0]-x[1], x[2]-x[3], ..., y[0]-y[1], y[2]-y[3], ...} 49 // 50 // {{end}} 51 func ConcatSubPairs[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 52 z = makeVec[E, W]() 53 half := z.len() / 2 54 for i := 0; i < half; i++ { 55 z[i] = x[2*i] - x[2*i+1] 56 z[half+i] = y[2*i] - y[2*i+1] 57 } 58 return z 59 } 60 61 // ConcatMaxPairs horizontally takes the maximum of adjacent pairs of elements 62 // in x and y and returns the concatenated result. 63 // 64 // {{if eq .xL 2}} 65 // 66 // z = {max(x[0], x[1]), max(y[0], y[1])} 67 // 68 // {{else if eq .xL 4}} 69 // 70 // z = {max(x[0], x[1]), max(x[2], x[3]), max(y[0], y[1]), max(y[2], y[3])} 71 // 72 // {{else}} 73 // 74 // z = {max(x[0], x[1]), max(x[2], x[3]), ..., max(y[0], y[1]), max(y[2], y[3]), ...} 75 // 76 // {{end}} 77 // 78 // For floats, max is Go's max built-in: it returns NaN if either element is 79 // NaN, and orders -0 before +0. 80 func ConcatMaxPairs[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 81 // Only ARM64 implements this (FMAXP, SMAXP, UMAXP), and its float form 82 // follows IEEE 754-2019 maximum like Go's max. If another platform 83 // implements it with its own Max, see MaxFloats about AMD64. 84 z = makeVec[E, W]() 85 half := z.len() / 2 86 for i := 0; i < half; i++ { 87 z[i] = max(x[2*i], x[2*i+1]) 88 z[half+i] = max(y[2*i], y[2*i+1]) 89 } 90 return z 91 } 92 93 // ConcatMinPairs horizontally takes the minimum of adjacent pairs of elements 94 // in x and y and returns the concatenated result. 95 // 96 // {{if eq .xL 2}} 97 // 98 // z = {min(x[0], x[1]), min(y[0], y[1])} 99 // 100 // {{else if eq .xL 4}} 101 // 102 // z = {min(x[0], x[1]), min(x[2], x[3]), min(y[0], y[1]), min(y[2], y[3])} 103 // 104 // {{else}} 105 // 106 // z = {min(x[0], x[1]), min(x[2], x[3]), ..., min(y[0], y[1]), min(y[2], y[3]), ...} 107 // 108 // {{end}} 109 // 110 // For floats, min is Go's min built-in: it returns NaN if either element is 111 // NaN, and orders -0 before +0. 112 func ConcatMinPairs[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 113 // See ConcatMaxPairs about platforms. 114 z = makeVec[E, W]() 115 half := z.len() / 2 116 for i := 0; i < half; i++ { 117 z[i] = min(x[2*i], x[2*i+1]) 118 z[half+i] = min(y[2*i], y[2*i+1]) 119 } 120 return z 121 } 122 123 // ConcatAddPairsSaturated horizontally adds adjacent pairs of elements in x and 124 // y with saturation and returns the concatenated result. 125 // 126 // {{if eq .xL 2}} 127 // 128 // z = {sat(x[0]+x[1]), sat(y[0]+y[1])} 129 // 130 // {{else if eq .xL 4}} 131 // 132 // z = {sat(x[0]+x[1]), sat(x[2]+x[3]), sat(y[0]+y[1]), sat(y[2]+y[3])} 133 // 134 // {{else}} 135 // 136 // z = {sat(x[0]+x[1]), sat(x[2]+x[3]), ..., sat(y[0]+y[1]), sat(y[2]+y[3]), ...} 137 // 138 // {{end}} 139 func ConcatAddPairsSaturated[E Ints | Uints, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 140 z = makeVec[E, W]() 141 half := z.len() / 2 142 for i := 0; i < half; i++ { 143 z[i] = addSaturated(x[2*i], x[2*i+1]) 144 z[half+i] = addSaturated(y[2*i], y[2*i+1]) 145 } 146 return z 147 } 148 149 // ConcatSubPairsSaturated horizontally subtracts adjacent pairs of elements in 150 // x and y with saturation and returns the concatenated result. 151 // 152 // {{if eq .xL 2}} 153 // 154 // z = {sat(x[0]-x[1]), sat(y[0]-y[1])} 155 // 156 // {{else if eq .xL 4}} 157 // 158 // z = {sat(x[0]-x[1]), sat(x[2]-x[3]), sat(y[0]-y[1]), sat(y[2]-y[3])} 159 // 160 // {{else}} 161 // 162 // z = {sat(x[0]-x[1]), sat(x[2]-x[3]), ..., sat(y[0]-y[1]), sat(y[2]-y[3]), ...} 163 // 164 // {{end}} 165 func ConcatSubPairsSaturated[E Ints | Uints, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 166 z = makeVec[E, W]() 167 half := z.len() / 2 168 for i := 0; i < half; i++ { 169 z[i] = subSaturated(x[2*i], x[2*i+1]) 170 z[half+i] = subSaturated(y[2*i], y[2*i+1]) 171 } 172 return z 173 } 174 175 // ConcatAddPairsGrouped divides x, y, and z into groups of 128 bits and 176 // performs [ConcatAddPairs] on each group. 177 func ConcatAddPairsGrouped[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 178 return grouped128(ConcatAddPairs, x, y) 179 } 180 181 // ConcatSubPairsGrouped divides x, y, and z into groups of 128 bits and 182 // performs [ConcatSubPairs] on each group. 183 func ConcatSubPairsGrouped[E Nums, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 184 return grouped128(ConcatSubPairs, x, y) 185 } 186 187 // ConcatAddPairsSaturatedGrouped divides x, y, and z into groups of 128 bits 188 // and performs [ConcatAddPairsSaturated] on each group. 189 func ConcatAddPairsSaturatedGrouped[E Ints | Uints, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 190 return grouped128(ConcatAddPairsSaturated, x, y) 191 } 192 193 // ConcatSubPairsSaturatedGrouped divides x, y, and z into groups of 128 bits 194 // and performs [ConcatSubPairsSaturated] on each group. 195 func ConcatSubPairsSaturatedGrouped[E Ints | Uints, W Width](x, y Vec[E, W]) (z Vec[E, W]) { 196 return grouped128(ConcatSubPairsSaturated, x, y) 197 } 198