394 lines
No EOL
15 KiB
C++
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;
|
|
}
|
|
} |