Crafter.Math/tests/VectorF16.cpp
2026-03-24 02:09:28 +01:00

394 lines
No EOL
15 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
*/
import Crafter.Math;
import std;
using namespace Crafter;
extern "C" {
std::string* RunTest() {
// Test 1: Load/Store functionality
{
_Float16 floats[] {0,1,2,3,4,5,6,7};
VectorF16<8, 1> vec1(floats);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i]) {
return new std::string("Load Store does not match");
}
}
}
// Test 2: Addition operator
{
_Float16 floats[] {0,1,2,3,4,5,6,7};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 + vec1;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] + floats[i]) {
return new std::string("Add does not match");
}
}
}
// Test 3: Subtraction operator
{
_Float16 floats[] {0,1,2,3,4,5,6,7};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 - vec1;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] - floats[i]) {
return new std::string("Subtract does not match");
}
}
}
// Test 4: Multiplication operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 * vec1;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] * floats[i]) {
return new std::string("Multiply does not match");
}
}
}
// Test 5: Division operator
{
_Float16 floats[] {2,4,6,8,10,12,14,16};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 / vec1;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] / floats[i]) {
return new std::string("Divide does not match");
}
}
}
// Test 6: Compound addition operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> vec2(floats);
vec1 += vec2;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] + floats[i]) {
return new std::string("Compound Add does not match");
}
}
}
// Test 7: Compound subtraction operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> vec2(floats);
vec1 -= vec2;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] - floats[i]) {
return new std::string("Compound Subtract does not match");
}
}
}
// Test 8: Compound multiplication operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> vec2(floats);
vec1 *= vec2;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] * floats[i]) {
return new std::string("Compound Multiply does not match");
}
}
}
// Test 9: Compound division operator
{
_Float16 floats[] {2,4,6,8,10,12,14,16};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> vec2(floats);
vec1 /= vec2;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] / floats[i]) {
return new std::string("Compound Divide does not match");
}
}
}
// Test 10: Scalar addition
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 + _Float16(1.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] + 1.0) {
return new std::string("Scalar Add does not match");
}
}
}
// Test 11: Scalar subtraction
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 - _Float16(1.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] - 1.0) {
return new std::string("Scalar Subtract does not match");
}
}
}
// Test 12: Scalar multiplication
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 * _Float16(2.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] * 2.0) {
return new std::string("Scalar Multiply does not match");
}
}
}
// Test 13: Scalar division
{
_Float16 floats[] {2,4,6,8,10,12,14,16};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = vec1 / _Float16(2.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] / 2.0) {
return new std::string("Scalar Divide does not match");
}
}
}
// Test 14: Compound scalar addition
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
vec1 += _Float16(1.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] + 1.0) {
return new std::string("Compound Scalar Add does not match");
}
}
}
// Test 15: Compound scalar subtraction
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
vec1 -= _Float16(1.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] - 1.0) {
return new std::string("Compound Scalar Subtract does not match");
}
}
}
// Test 16: Compound scalar multiplication
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
vec1 *= _Float16(2.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] * 2.0) {
return new std::string("Compound Scalar Multiply does not match");
}
}
}
// Test 17: Compound scalar division
{
_Float16 floats[] {2,4,6,8,10,12,14,16};
VectorF16<8, 1> vec1(floats);
vec1 /= _Float16(2.0);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != floats[i] / 2.0) {
return new std::string("Compound Scalar Divide does not match");
}
}
}
// Test 18: Equality operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> vec2(floats);
if (!(vec1 == vec2)) {
return new std::string("Equality operator does not match");
}
}
// Test 19: Inequality operator
{
_Float16 floats1[] {1,2,3,4,5,6,7,8};
_Float16 floats2[] {2,3,4,5,6,7,8,9};
VectorF16<8, 1> vec1(floats1);
VectorF16<8, 1> vec2(floats2);
if (!(vec1 != vec2)) {
return new std::string("Inequality operator does not match");
}
}
// Test 20: Negation operator
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
VectorF16<8, 1> result = -vec1;
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != -floats[i]) {
return new std::string("Negation operator does not match");
}
}
}
// Test 21: Length calculation
{
_Float16 floats[] {3,4,0,0,0,0,0,0};
VectorF16<8, 1> vec1(floats);
_Float16 length = vec1.Length();
_Float16 expectedLength = 5.0; // sqrt(3^2 + 4^2)
if (std::abs((float)length - (float)expectedLength) > 0.001) {
return new std::string("Length calculation does not match");
}
}
// Test 22: Length squared calculation
{
_Float16 floats[] {3,4,0,0,0,0,0,0};
VectorF16<8, 1> vec1(floats);
_Float16 lengthSq = vec1.LengthSq();
_Float16 expectedLengthSq = 25.0; // 3^2 + 4^2
if (std::abs((float)lengthSq - (float)expectedLengthSq) > 0.001) {
return new std::string("Length squared calculation does not match");
}
}
// Test 25: Shuffle operation
{
_Float16 floats[] {1,2,3,4,5,6,7,8};
VectorF16<8, 1> vec1(floats);
// Shuffle indices 0,1,2,3 -> 3,2,1,0 (reverse first 4 elements)
VectorF16<8, 1> result = vec1.template Shuffle<{{3,2,1,0,7,6,5,4}}>();
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
if (stored.v[0] != 4 || stored.v[1] != 3 || stored.v[2] != 2 || stored.v[3] != 1) {
return new std::string("Shuffle operation does not match");
}
}
// Test 26: Dot product
{
_Float16 floats1[] {1,2,3,4,0,0,0,0};
_Float16 floats2[] {2,3,4,5,0,0,0,0};
VectorF16<8, 1> vec1(floats1);
VectorF16<8, 1> vec2(floats2);
_Float16 dot = VectorF16<8, 1>::Dot(vec1, vec2);
_Float16 expectedDot = 1*2 + 2*3 + 3*4 + 4*5; // 2 + 6 + 12 + 20 = 40
if (std::abs((float)dot - (float)expectedDot) > 0.001) {
return new std::string("Dot product does not match");
}
}
// Test 27: Cross product (for 3D vectors)
{
_Float16 floats1[] {1,2,3,0,0,0,0,0};
_Float16 floats2[] {4,5,6,0,0,0,0,0};
VectorF16<3, 1> vec1(floats1);
VectorF16<3, 1> vec2(floats2);
VectorF16<3, 1> result = VectorF16<3, 1>::Cross(vec1, vec2);
Vector<_Float16, 3, VectorF16<3, 1>::Alignment> stored = result.Store();
// Cross product: (1,2,3) x (4,5,6) = (2*6-3*5, 3*4-1*6, 1*5-2*4) = (-3, 6, -3)
if (stored.v[0] != -3 || stored.v[1] != 6 || stored.v[2] != -3) {
return new std::string("Cross product does not match");
}
}
// Test 28: Multiply-Add operation
{
_Float16 floats1[] {1,2,3,4,0,0,0,0};
_Float16 floats2[] {2,3,4,5,0,0,0,0};
_Float16 floats3[] {1,1,1,1,0,0,0,0};
VectorF16<8, 1> vec1(floats1);
VectorF16<8, 1> vec2(floats2);
VectorF16<8, 1> vec3(floats3);
VectorF16<8, 1> result = VectorF16<8, 1>::MulitplyAdd(vec1, vec2, vec3);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
// Should compute (1*2 + 1, 2*3 + 1, 3*4 + 1, 4*5 + 1, ...) = (3, 7, 13, 21, ...)
for(std::uint8_t i = 0; i < 4; i++) {
if(stored.v[i] != floats1[i]*floats2[i] + floats3[i]) {
return new std::string("Multiply-Add operation does not match");
}
}
}
// Test 29: Multiply-Subtract operation
{
_Float16 floats1[] {1,2,3,4,0,0,0,0};
_Float16 floats2[] {2,3,4,5,0,0,0,0};
_Float16 floats3[] {1,1,1,1,0,0,0,0};
VectorF16<8, 1> vec1(floats1);
VectorF16<8, 1> vec2(floats2);
VectorF16<8, 1> vec3(floats3);
VectorF16<8, 1> result = VectorF16<8, 1>::MulitplySub(vec1, vec2, vec3);
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = result.Store();
// Should compute (1*2 - 1, 2*3 - 1, 3*4 - 1, 4*5 - 1, ...) = (1, 5, 11, 19, ...)
for(std::uint8_t i = 0; i < 4; i++) {
if(stored.v[i] != floats1[i]*floats2[i] - floats3[i]) {
return new std::string("Multiply-Subtract operation does not match");
}
}
}
// Test 30: Constructor with single value
{
VectorF16<8, 1> vec1(_Float16(5.0));
Vector<_Float16, 8, VectorF16<8, 1>::Alignment> stored = vec1.Store();
for(std::uint8_t i = 0; i < 8; i++) {
if(stored.v[i] != 5.0) {
return new std::string("Single value constructor does not match");
}
}
}
return nullptr;
}
}