fix(vector): batched Dot in the scalar VectorF32 fallback #2

Closed
jorijnvdgraaf wants to merge 1 commit from claude/scalar-fallback-dot into master

View file

@ -2136,6 +2136,28 @@ namespace Crafter {
return sq;
}
// Batched dot product over BatchSize (a, b) pairs: Dot(a0, b0, a1, b1,
// ...) returns one lane per pair. MatrixRowMajor relies on it, so
// without it this fallback (every target that has no intrinsic
// backend above) does not compile. Only the first Len lanes of each
// input are summed, as in the other backends.
template<typename... Rest>
requires((std::is_same_v<Rest, VectorF32<Len, Packing>> && ...) &&
(1 + sizeof...(Rest) == 2 * VectorBase<Len, Packing, float>::BatchSize))
constexpr static auto Dot(VectorF32<Len, Packing> first, Rest... rest) {
constexpr std::uint8_t N = VectorBase<Len, Packing, float>::BatchSize;
VectorF32<1, static_cast<std::uint8_t>(Packing * N)> r;
std::array<VectorF32<Len, Packing>, 2 * N> args{ first, rest... };
for (std::uint8_t i = 0; i < N; ++i)
for (std::uint8_t p = 0; p < Packing; ++p) {
float acc = 0.0f;
for (std::uint8_t k = 0; k < Len; ++k)
acc += args[2 * i].v[p * Len + k] * args[2 * i + 1].v[p * Len + k];
r.v[i * Packing + p] = acc;
}
return r;
}
template<typename... Rest>
requires((std::is_same_v<Rest, VectorF32<Len, Packing>> && ...) &&
(1 + sizeof...(Rest) == VectorBase<Len, Packing, float>::BatchSize))