2026-11-03 06:09:06 +11:00
|
|
|
//go:build goexperiment.simd
|
|
|
|
|
|
2026-11-03 09:22:32 +11:00
|
|
|
package obisimilarity
|
2026-11-03 06:09:06 +11:00
|
|
|
|
|
|
|
|
import "simd"
|
|
|
|
|
|
2026-11-03 09:22:32 +11:00
|
|
|
// simdBlockWidth is the number of sequences in a block: one per lane of a
|
2026-11-03 06:09:06 +11:00
|
|
|
// vector of bytes.
|
|
|
|
|
func simdBlockWidth() int {
|
|
|
|
|
var probe simd.Uint8s
|
|
|
|
|
return min(probe.Len(), 64)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// blockCommon computes, for the sequence whose words are given, the sum of
|
|
|
|
|
// the minima of the counters with every lane of the block. It is the value of
|
|
|
|
|
// commonWords without the overflow term, as the sums fit in 8 bits (see
|
2026-11-03 09:22:32 +11:00
|
|
|
// SparseWords). out must hold at least `width` bytes.
|
2026-11-03 06:09:06 +11:00
|
|
|
func blockCommon(data []uint8, width int, words []uint16, out []uint8) {
|
|
|
|
|
acc := simd.BroadcastUint8s(0)
|
|
|
|
|
for _, e := range words {
|
|
|
|
|
w := simd.LoadUint8s(data[int(e>>8)*width:])
|
|
|
|
|
acc = acc.Add(w.Min(simd.BroadcastUint8s(uint8(e))))
|
|
|
|
|
}
|
|
|
|
|
acc.Store(out)
|
|
|
|
|
}
|