Documentation
¶
Index ¶
- Constants
- func VectorAccumulateUnrolled(dst, src []float64)
- func VectorCosineParts(a, b []float64) (dot, normA2, normB2 float64)
- func VectorCosineUnrolled(a, b []float64) (dot, normA2, normB2 float64)
- func VectorDistance(metric string, a, b []float64, normA, normB float64) (float64, bool)
- func VectorDot(a, b []float64) float64
- func VectorDotUnrolled(a, b []float64) float64
- func VectorFinalizeDistance(metric string, rankingDistance float64) float64
- func VectorHammingDistance(a, b []float64) int
- func VectorHammingUnrolled(a, b []float64) int
- func VectorL1Distance(a, b []float64) float64
- func VectorL1Unrolled(a, b []float64) float64
- func VectorL2Squared(a, b []float64) float64
- func VectorL2SquaredUnrolled(a, b []float64) float64
- func VectorRankingDistance(metric string, a, b []float64, normA, normB float64) (float64, bool)
Constants ¶
const VectorMathBackend = "portable-unrolled"
Variables ¶
This section is empty.
Functions ¶
func VectorAccumulateUnrolled ¶
func VectorAccumulateUnrolled(dst, src []float64)
VectorAccumulateUnrolled adds src into dst elementwise, in place. Used by VEC_CENTROID's running sum. This is an accumulation, not a pairwise reduction, so it doesn't fit the existing dot/L2/L1/cosine kernel shape — a portable unrolled loop only, no new SIMD assembly (same reasoning as VectorHammingUnrolled above: unconfirmed hot path, not worth new asm risk).
func VectorCosineParts ¶
VectorCosineParts computes dot(a,b), dot(a,a) and dot(b,b) in a single pass over both vectors, dispatching to a fused SIMD kernel where one exists. Cosine similarity needs all three quantities; when no cached norm is available (the scalar VEC_COSINE_SIMILARITY path), one fused pass costs the same memory traffic as a plain dot product instead of three separate loops.
func VectorCosineUnrolled ¶
func VectorDistance ¶
func VectorDotUnrolled ¶
func VectorFinalizeDistance ¶
VectorFinalizeDistance converts a VectorRankingDistance value back into the real distance VectorDistance would have returned for the same inputs.
func VectorHammingDistance ¶
VectorHammingDistance counts the positions where the (a[i] > 0) sign bit of a differs from that of b, clamped to the shorter of the two lengths.
Unlike Dot/L2Squared/L1/Cosine above, this is a comparison-and-count reduction rather than an arithmetic multiply-accumulate or subtract-accumulate, so it doesn't fit the existing AVX2/SSE2/NEON kernel template those metrics share — a real SIMD kernel would need genuinely new instruction selection (packed compare + popcount-style reduction), not a mirror of an existing one. Given VEC_HAMMING_DISTANCE isn't confirmed to sit on any per-row hot path today, and given the same caution vector_math_arm64.go already applies to vectorL1Kernel — hand-derived SIMD bit patterns that can't be validated on real hardware risk silently corrupting results instead of failing to build — the deliberate choice here is to ship a portable scalar Go implementation on every architecture (amd64 included), leaving a real SIMD kernel as a future improvement.
func VectorHammingUnrolled ¶
func VectorL1Distance ¶
VectorL1Distance computes the Manhattan (L1) distance, dispatching to a SIMD kernel where one exists (see vectorL1Kernel in the per-arch files) — mirroring how VectorDot/VectorL2Squared dispatch. Previously this metric had no SIMD path at all, unlike Dot and L2Squared.
func VectorL1Unrolled ¶
func VectorL2Squared ¶
func VectorL2SquaredUnrolled ¶
func VectorRankingDistance ¶
VectorRankingDistance is VectorDistance for every purpose except deciding which rows rank best: for "l2" it skips the sqrt and returns the squared distance instead. Since sqrt is monotonic over non-negative reals, ranking by squared distance produces the identical ordering (and therefore identical top-k selection) as ranking by real distance — the real value is only needed once, on the small set of final results a query returns, not on every candidate a flat scan, IVF list, or HNSW graph traversal considers. Every other metric already avoids unnecessary sqrt calls (cosine needs none at all; manhattan/dot don't involve one), so this is identical to VectorDistance for them.
Callers must run the result through VectorFinalizeDistance exactly once, at the point a value crosses from "internal ranking" to "exposed to the caller" (e.g. VEC_SEARCH's _vec_distance column) — see vecSearchTopKWithIndex, the single choke point every index mode's search funnels through, for where that happens today.
Types ¶
This section is empty.