/* Crafter® Build Copyright (C) 2026 Catcrafts® Catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3.0 as published by the Free Software Foundation; This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include import Crafter.Math; import std; using namespace Crafter; // Helper function to compare floating point values with tolerance bool FloatEquals(_Float16 a, _Float16 b, _Float16 epsilon = 0.001f) { return std::abs(static_cast(a) - static_cast(b)) < static_cast(epsilon); } template std::string* TestAllCombinations() { if constexpr (Len > MaxSize) { return nullptr; } else if constexpr (Len * Packing > MaxSize) { return TestAllCombinations(); } else { _Float16 floats[VectorF16::Alignment]; _Float16 floats1[VectorF16::Alignment]; _Float16 floats2[VectorF16::Alignment]; for (std::uint32_t i = 0; i < VectorF16::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::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 vec(floats); Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec + vec; Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec - vec; Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec * vec; Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec / vec; Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec + _Float16(2); Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec - _Float16(2); Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec * _Float16(2); Vector<_Float16, Len*Packing, VectorF16::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 vec(floats); vec = vec / _Float16(2); Vector<_Float16, Len*Packing, VectorF16::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 vec1(floats); VectorF16 vec2(floats); if (!(vec1 == vec2)) { return new std::string(std::format("Equality 1 test failed at Len={} Packing={}", Len, Packing)); } } { VectorF16 vec1(floats); VectorF16 vec2(floats); vec2 *= 2; if (vec1 == vec2) { return new std::string(std::format("Equality 2 test failed at Len={} Packing={}", Len, Packing)); } } { VectorF16 vec1(floats); VectorF16 vec2(floats); if ((vec1 != vec2)) { return new std::string(std::format("Inequality 1 test failed at Len={} Packing={}", Len, Packing)); } } { VectorF16 vec1(floats); VectorF16 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::Alignment; i++) { expectedLengthSq += floats[i] * floats[i]; } { VectorF16 vec(floats); _Float16 dot = VectorF16::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 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 vec(floats); _Float16 length = vec.Length(); if (!FloatEquals(length, std::sqrtf(static_cast(expectedLengthSq)))) { return new std::string(std::format("Length mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (std::sqrtf(static_cast(expectedLengthSq))), (float)length)); } } } if constexpr(Len == 3) { { VectorF16 vec1(floats1); VectorF16 vec2(floats2); VectorF16 result = VectorF16::Cross(vec1, vec2); Vector<_Float16, Len*Packing, VectorF16::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(); } } extern "C" { std::string* RunTest() { std::string* err = TestAllCombinations::MaxSize>(); if (err) { return err; } return nullptr; } }