Crafter.Math/tests/VectorF16.cpp
2026-03-24 04:41:03 +01:00

246 lines
No EOL
11 KiB
C++

/*
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 <cmath>
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<float>(a) - static_cast<float>(b)) < static_cast<float>(epsilon);
}
template <std::uint32_t MaxSize, std::uint32_t Len = 1, std::uint32_t Packing = 1>
std::string* TestAllCombinations() {
if constexpr (Len > MaxSize) {
return nullptr;
} else if constexpr (Len * Packing > MaxSize) {
return TestAllCombinations<MaxSize, Len + 1, 1>();
} else {
_Float16 floats[VectorF16<Len, Packing>::Alignment];
_Float16 floats1[VectorF16<Len, Packing>::Alignment];
_Float16 floats2[VectorF16<Len, Packing>::Alignment];
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>();
}
}
extern "C" {
std::string* RunTest() {
std::string* err = TestAllCombinations<VectorF16<1, 1>::MaxSize>();
if (err) {
return err;
}
return nullptr;
}
}