blob: 2e099636c0bd0019eb3ae7546be4b1fc0390aa1e [file]
// 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.
//simdgen:category Shifts
package spec
// ScaleSaturated multiplies x[i] by 2^scale[i], with saturation.
//
// Positive exponents scale up (shift left with saturation); negative exponents
// scale down (shift right; arithmetic for signed types, logical for unsigned types).
//
// z[i] = saturated(x[i] * 2^scale[i])
//
//specgen:require scale=Int{xN}x{xL}
func ScaleSaturated[E Ints | Uints, W Width, yE Ints](x Vec[E, W], scale Vec[yE, W]) (z Vec[E, W]) {
z = makeVec[E, W]()
for i := range z {
z[i] = scaleSaturated(x[i], scale[i])
}
return z
}
// {{if eq .xB "int" -}}
// ShiftAllRight arithmetically shifts each element of x right by shift bits.
// If shift is greater than the element width, the result is 0 or -1.
// {{- else -}}
// ShiftAllRight logically shifts each element of x right by y bits.
// If shift is greater than the element width, the result is 0.
// {{- end}}
//
// z[i] = x[i] >> shift
func ShiftAllRight[E Ints | Uints, W Width](x Vec[E, W], shift uint64) (z Vec[E, W]) {
return map1[E, W, E, W](x, func(v E) E {
return v >> shift
})
}
// ShiftAllLeft shifts each element of x left by y bits.
// If shift is greater than the element width, the result is 0.
//
// z[i] = x[i] << shift
func ShiftAllLeft[E Ints | Uints, W Width](x Vec[E, W], shift uint64) (z Vec[E, W]) {
return map1[E, W, E, W](x, func(v E) E {
return v << shift
})
}
// {{if eq .xB "int" -}}
// ShiftRight arithmetically shifts x[i] right by shift[i] bits.
// If shift[i] is greater than the element width, the result is 0 or -1.
// {{- else -}}
// ShiftRight logically shifts x[i] right by shift[i] bits.
// If shift[i] is greater than the element width, the result is 0.
// {{- end}}
//
// z[i] = x[i] >> shift[i]
//
//specgen:require shift=Uint{xN}x{xL}
func ShiftRight[E Ints | Uints, W Width, yE Uints](x Vec[E, W], shift Vec[yE, W]) (z Vec[E, W]) {
z = makeVec[E, W]()
for i := range z {
z[i] = x[i] >> shift[i]
}
return z
}
// ShiftLeft shifts x[i] left by shift[i] bits.
// If shift[i] is greater than the element width, the result is 0.
//
// z[i] = x[i] << shift[i]
//
//specgen:require shift=Uint{xN}x{xL}
func ShiftLeft[E Ints | Uints, W Width, yE Uints](x Vec[E, W], shift Vec[yE, W]) (z Vec[E, W]) {
z = makeVec[E, W]()
for i := range z {
z[i] = x[i] << shift[i]
}
return z
}