more F16 tests

This commit is contained in:
Jorijn van der Graaf 2026-03-24 04:41:03 +01:00
commit 6b15089e24
2 changed files with 203 additions and 40 deletions

View file

@ -467,11 +467,12 @@ namespace Crafter {
} }
} }
constexpr static _Float16 Dot(VectorF16<Len, 1> a, VectorF16<Len, 1> b) { constexpr static _Float16 Dot(VectorF16<Len, Packing> a, VectorF16<Len, Packing> b) requires(Packing == 1) {
if constexpr(std::is_same_v<VectorType, __m128h>) { if constexpr(std::is_same_v<VectorType, __m128h>) {
__m128h mul = _mm_mul_ph(a.v, b.v); __m128h mul = _mm_mul_ph(a.v, b.v);
return _mm_reduce_add_ph(mul); return _mm_reduce_add_ph(mul);
} else if constexpr(std::is_same_v<VectorType, __m256h>) { } else if constexpr(std::is_same_v<VectorType, __m256h>) {
static_assert(std::is_same_v<decltype(a.v), VectorType>, "a.v is NOT VectorType");
__m256h mul = _mm256_mul_ph(a.v, b.v); __m256h mul = _mm256_mul_ph(a.v, b.v);
return _mm256_reduce_add_ph(mul); return _mm256_reduce_add_ph(mul);
} else { } else {

View file

@ -21,42 +21,11 @@ import Crafter.Math;
import std; import std;
using namespace Crafter; using namespace Crafter;
template <std::uint32_t MaxSize, std::uint32_t Len, std::uint32_t Packing> // Helper function to compare floating point values with tolerance
std::string* TestLoadStore() { bool FloatEquals(_Float16 a, _Float16 b, _Float16 epsilon = 0.001f) {
_Float16 floats[Len * Packing]; return std::abs(static_cast<float>(a) - static_cast<float>(b)) < static_cast<float>(epsilon);
for (std::uint32_t i = 0; i < Len * Packing; i++) {
floats[i] = static_cast<_Float16>(i);
}
VectorF16<Len, Packing> vec(floats);
auto stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (stored.v[i] != floats[i]) {
return new std::string(std::format("Load/Store mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i]), (float)stored.v[i]));
}
}
return nullptr;
} }
template <std::uint32_t MaxSize, std::uint32_t Len, std::uint32_t Packing>
std::string* TestAdd() {
_Float16 floats[Len * Packing];
for (std::uint32_t i = 0; i < Len * Packing; i++) {
floats[i] = static_cast<_Float16>(i);
}
VectorF16<Len, Packing> vec(floats);
vec = vec + vec;
auto stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (stored.v[i] != floats[i] + floats[i]) {
return new std::string(std::format("Add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + floats[i]), (float)stored.v[i]));
}
}
return nullptr;
}
template <std::uint32_t MaxSize, std::uint32_t Len = 1, std::uint32_t Packing = 1> template <std::uint32_t MaxSize, std::uint32_t Len = 1, std::uint32_t Packing = 1>
std::string* TestAllCombinations() { std::string* TestAllCombinations() {
if constexpr (Len > MaxSize) { if constexpr (Len > MaxSize) {
@ -64,15 +33,208 @@ std::string* TestAllCombinations() {
} else if constexpr (Len * Packing > MaxSize) { } else if constexpr (Len * Packing > MaxSize) {
return TestAllCombinations<MaxSize, Len + 1, 1>(); return TestAllCombinations<MaxSize, Len + 1, 1>();
} else { } else {
std::string* result = TestLoadStore<MaxSize, Len, Packing>(); _Float16 floats[VectorF16<Len, Packing>::Alignment];
if (result) return result; _Float16 floats1[VectorF16<Len, Packing>::Alignment];
result = TestAdd<MaxSize, Len, Packing>(); _Float16 floats2[VectorF16<Len, Packing>::Alignment];
if (result) return result; for (std::uint32_t i = 0; i < VectorF16<Len, Packing>::Alignment; i++) {
floats[i] = static_cast<_Float16>(i+1);
}
for (std::uint32_t i = 0; i < Packing*Len; i++) {
floats1[i] = static_cast<_Float16>(i+1);
}
for (std::uint32_t i = 0; i < Packing*Len; i++) {
floats2[i] = static_cast<_Float16>(i+1+Len);
}
for (std::uint32_t i = Len*Packing; i < VectorF16<Len, Packing>::Alignment; i++) {
floats1[i] = 0;
floats2[i] = 0;
}
std::string* result = nullptr;
constexpr auto total = Len * Packing;
if constexpr(total > 0 && (total & (total - 1)) == 0) {
{
VectorF16<Len, Packing> vec(floats);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i])) {
return new std::string(std::format("Load/Store mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i]), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec + vec;
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] + floats[i])) {
return new std::string(std::format("Add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + floats[i]), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec - vec;
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], _Float16(0))) {
return new std::string(std::format("Subtract mismatch at Len={} Packing={}, Expected: 0, Got: {}", Len, Packing, (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec * vec;
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] * floats[i])) {
return new std::string(std::format("Multiply mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] * floats[i]), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec / vec;
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], _Float16(1))) {
return new std::string(std::format("Divide mismatch at Len={} Packing={}, Expected: 1, Got: {}", Len, Packing, (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec + _Float16(2);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] + _Float16(2))) {
return new std::string(std::format("Scalar add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + _Float16(2)), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec - _Float16(2);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] - _Float16(2))) {
return new std::string(std::format("Scalar add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + _Float16(2)), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec * _Float16(2);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] * _Float16(2))) {
return new std::string(std::format("Scalar multiply mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] * _Float16(2)), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec(floats);
vec = vec / _Float16(2);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = vec.Store();
for (std::uint32_t i = 0; i < Len * Packing; i++) {
if (!FloatEquals(stored.v[i], floats[i] / _Float16(2))) {
return new std::string(std::format("Scalar multiply mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] * _Float16(2)), (float)stored.v[i]));
}
}
}
{
VectorF16<Len, Packing> vec1(floats);
VectorF16<Len, Packing> vec2(floats);
if (!(vec1 == vec2)) {
return new std::string(std::format("Equality 1 test failed at Len={} Packing={}", Len, Packing));
}
}
{
VectorF16<Len, Packing> vec1(floats);
VectorF16<Len, Packing> vec2(floats);
vec2 *= 2;
if (vec1 == vec2) {
return new std::string(std::format("Equality 2 test failed at Len={} Packing={}", Len, Packing));
}
}
{
VectorF16<Len, Packing> vec1(floats);
VectorF16<Len, Packing> vec2(floats);
if ((vec1 != vec2)) {
return new std::string(std::format("Inequality 1 test failed at Len={} Packing={}", Len, Packing));
}
}
{
VectorF16<Len, Packing> vec1(floats);
VectorF16<Len, Packing> vec2(floats);
vec2 *= 2;
if (!(vec1 != vec2)) {
return new std::string(std::format("Inequality 2 test failed at Len={} Packing={}", Len, Packing));
}
}
}
if constexpr(Packing == 1) {
_Float16 expectedLengthSq = _Float16(0);
for (std::uint32_t i = 0; i < VectorF16<Len, Packing>::Alignment; i++) {
expectedLengthSq += floats[i] * floats[i];
}
{
VectorF16<Len, Packing> vec(floats);
_Float16 dot = VectorF16<Len, Packing>::Dot(vec, vec);
if (!FloatEquals(dot, expectedLengthSq)) {
return new std::string(std::format("Dot product mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)expectedLengthSq, (float)dot));
}
}
{
VectorF16<Len, Packing> vec(floats);
_Float16 lengthSq = vec.LengthSq();
if (!FloatEquals(lengthSq, expectedLengthSq)) {
return new std::string(std::format("LengthSq mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)expectedLengthSq, (float)lengthSq));
}
}
{
VectorF16<Len, Packing> vec(floats);
_Float16 length = vec.Length();
if (!FloatEquals(length, std::sqrtf(static_cast<float>(expectedLengthSq)))) {
return new std::string(std::format("Length mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (std::sqrtf(static_cast<float>(expectedLengthSq))), (float)length));
}
}
}
if constexpr(Len == 3) {
{
VectorF16<Len, Packing> vec1(floats1);
VectorF16<Len, Packing> vec2(floats2);
VectorF16<Len, Packing> result = VectorF16<Len, Packing>::Cross(vec1, vec2);
Vector<_Float16, Len*Packing, VectorF16<Len, Packing>::Alignment> stored = result.Store();
if (!FloatEquals(stored.v[0], -3) || !FloatEquals(stored.v[1], 6) || !FloatEquals(stored.v[2], -3)) {
return new std::string(std::format("Cross mismatch at Len={} Packing={}, Expected: -3,6,-3, Got: {},{},{}", Len, Packing, (float)stored.v[0], (float)stored.v[1], (float)stored.v[2]));
}
}
}
return TestAllCombinations<MaxSize, Len, Packing + 1>(); return TestAllCombinations<MaxSize, Len, Packing + 1>();
} }
} }
extern "C" { extern "C" {
std::string* RunTest() { std::string* RunTest() {
std::string* err = TestAllCombinations<VectorF16<1, 1>::MaxSize>(); std::string* err = TestAllCombinations<VectorF16<1, 1>::MaxSize>();