fix(vector): batched Dot in the scalar VectorF32 fallback #2
1 changed files with 22 additions and 0 deletions
|
|
@ -2136,6 +2136,28 @@ namespace Crafter {
|
||||||
return sq;
|
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>
|
template<typename... Rest>
|
||||||
requires((std::is_same_v<Rest, VectorF32<Len, Packing>> && ...) &&
|
requires((std::is_same_v<Rest, VectorF32<Len, Packing>> && ...) &&
|
||||||
(1 + sizeof...(Rest) == VectorBase<Len, Packing, float>::BatchSize))
|
(1 + sizeof...(Rest) == VectorBase<Len, Packing, float>::BatchSize))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue