more tests
This commit is contained in:
parent
6b15089e24
commit
b582e168e3
6 changed files with 460 additions and 288 deletions
|
|
@ -29,11 +29,10 @@ namespace Crafter {
|
||||||
return degrees * (std::numbers::pi / 180);
|
return degrees * (std::numbers::pi / 180);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __AVX512FP16__
|
#ifdef __x86_64
|
||||||
|
#ifndef __AVX512FP16__
|
||||||
export template <std::uint32_t Len, std::uint32_t Packing>
|
export template <std::uint32_t Len, std::uint32_t Packing>
|
||||||
using VectorF16L = VectorF16<Len, Packing>;
|
using VectorF16 = VectorF32<Len, Packing>;
|
||||||
#else
|
#endif
|
||||||
export template <std::uint32_t Len, std::uint32_t Packing>
|
|
||||||
using VectorF16L = VectorF32<Len, Packing>;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -439,13 +439,13 @@ namespace Crafter {
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static Vector<T, 4, Aligment> QuanternionFromEuler(T roll, T pitch, T yaw) {
|
constexpr static Vector<T, 4, Aligment> QuanternionFromEuler(T rollHalf, T pitchHalf, T yawHalf) {
|
||||||
T cr = std::cos(roll * 0.5);
|
T cr = std::cos(rollHalf);
|
||||||
T sr = std::sin(roll * 0.5);
|
T sr = std::sin(rollHalf);
|
||||||
T cp = std::cos(pitch * 0.5);
|
T cp = std::cos(pitchHalf);
|
||||||
T sp = std::sin(pitch * 0.5);
|
T sp = std::sin(pitchHalf);
|
||||||
T cy = std::cos(yaw * 0.5);
|
T cy = std::cos(yawHalf);
|
||||||
T sy = std::sin(yaw * 0.5);
|
T sy = std::sin(yawHalf);
|
||||||
|
|
||||||
return Vector<T, 4, Aligment>(
|
return Vector<T, 4, Aligment>(
|
||||||
sr * cp * cy - cr * sp * sy,
|
sr * cp * cy - cr * sp * sy,
|
||||||
|
|
|
||||||
|
|
@ -92,20 +92,24 @@ namespace Crafter {
|
||||||
|
|
||||||
template <std::uint32_t BLen, std::uint32_t BPacking>
|
template <std::uint32_t BLen, std::uint32_t BPacking>
|
||||||
constexpr operator VectorF16<BLen, BPacking>() const {
|
constexpr operator VectorF16<BLen, BPacking>() const {
|
||||||
if constexpr(std::is_same_v<VectorType, __m256h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m128h>) {
|
if(constexpr Len == Blen) {
|
||||||
return VectorF16<BLen, BPacking>(_mm256_castph256_ph128(v));
|
if constexpr(std::is_same_v<VectorType, __m256h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m128h>) {
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m512h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m128h>) {
|
return VectorF16<BLen, BPacking>(_mm256_castph256_ph128(v));
|
||||||
return VectorF16<BLen, BPacking>(_mm512_castph512_ph128(v));
|
} else if constexpr(std::is_same_v<VectorType, __m512h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m128h>) {
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m512h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m256h>) {
|
return VectorF16<BLen, BPacking>(_mm512_castph512_ph128(v));
|
||||||
return VectorF16<BLen, BPacking>(_mm512_castph512_ph256(v));
|
} else if constexpr(std::is_same_v<VectorType, __m512h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m256h>) {
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m128h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m256h>) {
|
return VectorF16<BLen, BPacking>(_mm512_castph512_ph256(v));
|
||||||
return VectorF16<BLen, BPacking>(_mm256_castph128_ph256(v));
|
} else if constexpr(std::is_same_v<VectorType, __m128h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m256h>) {
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m128h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m512h>) {
|
return VectorF16<BLen, BPacking>(_mm256_castph128_ph256(v));
|
||||||
return VectorF16<BLen, BPacking>(_mm512_castph128_ph512(v));
|
} else if constexpr(std::is_same_v<VectorType, __m128h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m512h>) {
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m256h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m512h>) {
|
return VectorF16<BLen, BPacking>(_mm512_castph128_ph512(v));
|
||||||
return VectorF16<BLen, BPacking>(_mm512_castph256_ph512(v));
|
} else if constexpr(std::is_same_v<VectorType, __m256h> && std::is_same_v<typename VectorF16<BLen, BPacking>::VectorType, __m512h>) {
|
||||||
|
return VectorF16<BLen, BPacking>(_mm512_castph256_ph512(v));
|
||||||
|
} else {
|
||||||
|
return VectorF16<BLen, BPacking>(v);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return VectorF16<BLen, BPacking>(v);
|
return ExtractLo<BLen>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,13 +368,14 @@ namespace Crafter {
|
||||||
|
|
||||||
template <std::array<bool, Len> values>
|
template <std::array<bool, Len> values>
|
||||||
constexpr VectorF16<Len, Packing> Negate() {
|
constexpr VectorF16<Len, Packing> Negate() {
|
||||||
std::array<std::uint16_t, Len> mask = GetNegateMask<values>();
|
std::array<std::uint16_t, Alignment> mask = GetNegateMask<values>();
|
||||||
|
std::println("{}", mask);
|
||||||
if constexpr(std::is_same_v<VectorType, __m128h>) {
|
if constexpr(std::is_same_v<VectorType, __m128h>) {
|
||||||
return VectorF16<Len, Packing>(_mm_castsi128_ph(_mm_xor_si128(_mm_castph_si128(v), _mm_loadu_epi16(mask.data()))));
|
return VectorF16<Len, Packing>(_mm_castsi128_ph(_mm_xor_si128(_mm_castph_si128(v), _mm_loadu_epi16(mask.data()))));
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m256h>) {
|
} else if constexpr(std::is_same_v<VectorType, __m256h>) {
|
||||||
return VectorF16<Len, Packing>(_mm256_castsi2568_ph(_mm256_xor_si256(_mm256_castph_si256(v), _mm_loadu_epi16(mask.data()))));
|
return VectorF16<Len, Packing>(_mm256_castsi256_ph(_mm256_xor_si256(_mm256_castph_si256(v), _mm256_loadu_epi16(mask.data()))));
|
||||||
} else {
|
} else {
|
||||||
return VectorF16<Len, Packing>(_mm512_castsi512_ph(_mm512_xor_si256(_mm512_castph_si512(v), _mm_loadu_epi16(mask.data()))));
|
return VectorF16<Len, Packing>(_mm512_castsi512_ph(_mm512_xor_si512(_mm512_castph_si512(v), _mm512_loadu_epi16(mask.data()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1170,14 +1175,14 @@ namespace Crafter {
|
||||||
static_assert(false, "No __AVX512BW__ and __AVX512VL__ support");
|
static_assert(false, "No __AVX512BW__ and __AVX512VL__ support");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return _mm256_castsi256_ph(_mm256_mask_blend_epi16(_mm256_castph_si256(a.v), _mm256_castph_si256(b.v), GetBlendMaskEpi16<ShuffleValues>()));
|
return _mm256_castsi256_ph(_mm256_mask_blend_epi16(GetBlendMaskEpi16<ShuffleValues>(), _mm256_castph_si256(a.v), _mm256_castph_si256(b.v)));
|
||||||
} else {
|
} else {
|
||||||
return _mm512_castsi512_ph(_mm512_blend_epi16(GetBlendMaskEpi16<ShuffleValues>(), _mm512_castph_si512(a.v), _mm512_castph_si512(b.v)));
|
return _mm512_castsi512_ph(_mm512_mask_blend_epi16(GetBlendMaskEpi16<ShuffleValues>(), _mm512_castph_si512(a.v), _mm512_castph_si512(b.v)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static VectorF16<Len, Packing> Rotate(VectorF16<3, Packing> v, VectorF16<4, Packing> q) requires(Len == 3) {
|
constexpr static VectorF16<Len, Packing> Rotate(VectorF16<3, Packing> v, VectorF16<4, Packing> q) requires(Len == 3) {
|
||||||
VectorF16<3, Packing> qv(q.v);
|
VectorF16<3, Packing> qv(q);
|
||||||
VectorF16<Len, Packing> t = Cross(qv, v) * _Float16(2);
|
VectorF16<Len, Packing> t = Cross(qv, v) * _Float16(2);
|
||||||
return v + t * q.template Shuffle<{{3,3,3,3}}>() + Cross(qv, t);
|
return v + t * q.template Shuffle<{{3,3,3,3}}>() + Cross(qv, t);
|
||||||
}
|
}
|
||||||
|
|
@ -1226,21 +1231,23 @@ namespace Crafter {
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
template <std::array<bool, Len> values>
|
template <std::array<bool, Len> values>
|
||||||
static consteval std::array<std::uint16_t, Len> GetNegateMask() {
|
static consteval std::array<std::uint16_t, Alignment> GetNegateMask() {
|
||||||
std::array<std::uint16_t, Len> mask;
|
std::array<std::uint16_t, Alignment> mask{0};
|
||||||
for(std::uint8_t i = 0; i < Len; i++) {
|
for(std::uint8_t i2 = 0; i2 < Packing; i2++) {
|
||||||
if(values[i]) {
|
for(std::uint8_t i = 0; i < Len; i++) {
|
||||||
mask[i] = 0b1000000000000000;
|
if(values[i]) {
|
||||||
} else {
|
mask[i2*Len+i] = 0b1000000000000000;
|
||||||
mask[i] = 0;
|
} else {
|
||||||
|
mask[i2*Len+i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static consteval std::array<std::uint16_t, Len> GetNegateMaskAll() {
|
static consteval std::array<std::uint16_t, Alignment> GetNegateMaskAll() {
|
||||||
std::array<std::uint16_t, Len> mask;
|
std::array<std::uint16_t, Alignment> mask{0};
|
||||||
for(std::uint8_t i = 0; i < Len; i++) {
|
for(std::uint8_t i = 0; i < Packing*Len; i++) {
|
||||||
mask[i] = 0b1000000000000000;
|
mask[i] = 0b1000000000000000;
|
||||||
}
|
}
|
||||||
return mask;
|
return mask;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
"tests":[
|
"tests":[
|
||||||
{
|
{
|
||||||
"name": "F16-x86-64-sapphirerapids",
|
"name": "F16-x86-64-sapphirerapids",
|
||||||
"implementations": ["tests/VectorF16"],
|
"implementations": ["tests/Vector"],
|
||||||
"march": "sapphirerapids",
|
"march": "sapphirerapids",
|
||||||
"extends": ["lib-shared"]
|
"extends": ["lib-shared"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
412
tests/Vector.cpp
Normal file
412
tests/Vector.cpp
Normal file
|
|
@ -0,0 +1,412 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool FloatEquals(T a, T b, T epsilon = 0.001f) {
|
||||||
|
return std::abs(static_cast<float>(a) - static_cast<float>(b)) < static_cast<float>(epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::uint8_t Len>
|
||||||
|
consteval std::array<bool, Len> AlternateTrueFalse() {
|
||||||
|
std::array<bool, Len> result = {};
|
||||||
|
for (std::uint8_t i = 0; i < Len; ++i) {
|
||||||
|
result[i] = (i % 2 == 0); // Set true for even indices, false for odd indices
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, template<std::uint32_t, std::uint32_t> class VectorType, 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<T, VectorType, MaxSize, Len + 1, 1>();
|
||||||
|
} else {
|
||||||
|
T floats[VectorType<Len, Packing>::Alignment];
|
||||||
|
T floats1[VectorType<Len, Packing>::Alignment];
|
||||||
|
T floats2[VectorType<Len, Packing>::Alignment];
|
||||||
|
for (std::uint32_t i = 0; i < VectorType<Len, Packing>::Alignment; i++) {
|
||||||
|
floats[i] = static_cast<T>(i+1);
|
||||||
|
}
|
||||||
|
for (std::uint32_t i = 0; i < Packing*Len; i++) {
|
||||||
|
floats1[i] = static_cast<T>(i+1);
|
||||||
|
}
|
||||||
|
for (std::uint32_t i = 0; i < Packing*Len; i++) {
|
||||||
|
floats2[i] = static_cast<T>(i+1+Len);
|
||||||
|
}
|
||||||
|
for (std::uint32_t i = Len*Packing; i < VectorType<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) {
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
Vector<T, Len*Packing, VectorType<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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec + vec;
|
||||||
|
Vector<T, Len*Packing, VectorType<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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec - vec;
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], T(0))) {
|
||||||
|
return new std::string(std::format("Subtract mismatch at Len={} Packing={}, Expected: 0, Got: {}", Len, Packing, (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec * vec;
|
||||||
|
Vector<T, Len*Packing, VectorType<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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec / vec;
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], T(1))) {
|
||||||
|
return new std::string(std::format("Divide mismatch at Len={} Packing={}, Expected: 1, Got: {}", Len, Packing, (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec + T(2);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], floats[i] + T(2))) {
|
||||||
|
return new std::string(std::format("Scalar add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + T(2)), (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec - T(2);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], floats[i] - T(2))) {
|
||||||
|
return new std::string(std::format("Scalar add mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] + T(2)), (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec * T(2);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], floats[i] * T(2))) {
|
||||||
|
return new std::string(std::format("Scalar multiply mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] * T(2)), (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = vec / T(2);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], floats[i] / T(2))) {
|
||||||
|
return new std::string(std::format("Scalar multiply mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(floats[i] * T(2)), (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec1(floats);
|
||||||
|
VectorType<Len, Packing> vec2(floats);
|
||||||
|
|
||||||
|
if (!(vec1 == vec2)) {
|
||||||
|
return new std::string(std::format("Equality 1 test failed at Len={} Packing={}", Len, Packing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec1(floats);
|
||||||
|
VectorType<Len, Packing> vec2(floats);
|
||||||
|
vec2 *= 2;
|
||||||
|
if (vec1 == vec2) {
|
||||||
|
return new std::string(std::format("Equality 2 test failed at Len={} Packing={}", Len, Packing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec1(floats);
|
||||||
|
VectorType<Len, Packing> vec2(floats);
|
||||||
|
|
||||||
|
if ((vec1 != vec2)) {
|
||||||
|
return new std::string(std::format("Inequality 1 test failed at Len={} Packing={}", Len, Packing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec1(floats);
|
||||||
|
VectorType<Len, Packing> vec2(floats);
|
||||||
|
vec2 *= 2;
|
||||||
|
if (!(vec1 != vec2)) {
|
||||||
|
return new std::string(std::format("Inequality 2 test failed at Len={} Packing={}", Len, Packing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec = -vec;
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> result = vec.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
||||||
|
if (!FloatEquals(result.v[i], -floats[i])) {
|
||||||
|
return new std::string(std::format("Negate mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, (float)(-floats[i]), (float)result.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vecA(floats1);
|
||||||
|
VectorType<Len, Packing> vecB(floats2);
|
||||||
|
VectorType<Len, Packing> result = VectorType<Len, Packing>::template Blend<AlternateTrueFalse<Len>()>(vecA, vecB);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = result.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len; i++) {
|
||||||
|
bool useB = (i % 2 == 0);
|
||||||
|
T expected = useB ? floats2[i]: floats1[i];
|
||||||
|
if (!FloatEquals(stored.v[i], expected)) {
|
||||||
|
return new std::string(std::format("Blend mismatch at Len={} Packing={}, Index={}, Expected: {}, Got: {}", Len, Packing, i, (float)expected, (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vecA(floats);
|
||||||
|
VectorType<Len, Packing> vecB(floats);
|
||||||
|
VectorType<Len, Packing> vecAdd(floats);
|
||||||
|
VectorType<Len, Packing> result = VectorType<Len, Packing>::MulitplyAdd(vecA, vecB, vecAdd);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = result.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len; i++) {
|
||||||
|
T expected = floats[i] * floats[i] + floats[i];
|
||||||
|
if (!FloatEquals(stored.v[i], expected)) {
|
||||||
|
return new std::string(std::format("MulitplyAdd mismatch at Len={} Packing={}, Index={}, Expected: {}, Got: {}", Len, Packing, i, (float)expected, (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vecA(floats);
|
||||||
|
VectorType<Len, Packing> vecB(floats);
|
||||||
|
VectorType<Len, Packing> vecSub(floats);
|
||||||
|
VectorType<Len, Packing> result = VectorType<Len, Packing>::MulitplySub(vecA, vecB, vecSub);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = result.Store();
|
||||||
|
for (std::uint32_t i = 0; i < Len; i++) {
|
||||||
|
T expected = floats[i] * floats[i] - floats[i];
|
||||||
|
if (!FloatEquals(stored.v[i], expected)) {
|
||||||
|
return new std::string(std::format("MulitplySub mismatch at Len={} Packing={}, Index={}, Expected: {}, Got: {}", Len, Packing, i, (float)expected, (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr(Packing == 1) {
|
||||||
|
T expectedLengthSq = T(0);
|
||||||
|
for (std::uint32_t i = 0; i < VectorType<Len, Packing>::Alignment; i++) {
|
||||||
|
expectedLengthSq += floats[i] * floats[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
T dot = VectorType<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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
T 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
T length = vec.Length();
|
||||||
|
if (!FloatEquals(length, static_cast<T>(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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec(floats);
|
||||||
|
vec.Normalize();
|
||||||
|
T length = vec.Length();
|
||||||
|
if (!FloatEquals(length, static_cast<T>(1))) {
|
||||||
|
return new std::string(std::format("Normalize mismatch at Len={} Packing={}, Expected: {}, Got: {}", Len, Packing, 1, (float)length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr(Len == 3) {
|
||||||
|
{
|
||||||
|
VectorType<Len, Packing> vec1(floats1);
|
||||||
|
VectorType<Len, Packing> vec2(floats2);
|
||||||
|
VectorType<Len, Packing> result = VectorType<Len, Packing>::Cross(vec1, vec2);
|
||||||
|
Vector<T, Len*Packing, VectorType<Len, Packing>::Alignment> stored = result.Store();
|
||||||
|
if (!FloatEquals(stored.v[0], T(-3)) || !FloatEquals(stored.v[1], T(6)) || !FloatEquals(stored.v[2], T(-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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if constexpr(4 * Packing < VectorType<1, 1>::MaxSize) {
|
||||||
|
T qData[4];
|
||||||
|
qData[0] = T(1);
|
||||||
|
qData[1] = T(0);
|
||||||
|
qData[2] = T(0);
|
||||||
|
qData[3] = T(0);
|
||||||
|
|
||||||
|
VectorType<3, Packing> vecV(floats);
|
||||||
|
VectorType<4, Packing> vecQ(qData);
|
||||||
|
VectorType<3, Packing> result = VectorType<3, Packing>::Rotate(vecV, vecQ);
|
||||||
|
Vector<T, 3*Packing, VectorType<3, Packing>::Alignment> stored = result.Store();
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < 3; i++) {
|
||||||
|
if (!FloatEquals(stored.v[i], floats[i])) {
|
||||||
|
return new std::string(std::format("Rotate mismatch at Len={} Packing={}, Index={}, Expected: {}, Got: {}", Len, Packing, i, (float)floats[i], (float)stored.v[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// // Test QuanternionFromEuler() static method (Len == 4 only)
|
||||||
|
// if constexpr(Len == 4) {
|
||||||
|
// T eulerData[3] = {T(0), T(0), T(0)}; // Zero rotation
|
||||||
|
// VectorType<3, 1> eulerVec(eulerData);
|
||||||
|
// VectorType<4, 1> result = VectorType<4, 1>::QuanternionFromEuler(eulerVec);
|
||||||
|
// Vector<T, 4, 8> stored = result.Store();
|
||||||
|
|
||||||
|
// // Identity quaternion should be (1, 0, 0, 0)
|
||||||
|
// if (!FloatEquals(stored.v[0], T(1)) || !FloatEquals(stored.v[1], T(0)) ||
|
||||||
|
// !FloatEquals(stored.v[2], T(0)) || !FloatEquals(stored.v[3], T(0))) {
|
||||||
|
// return new std::string(std::format("QuanternionFromEuler mismatch at Len={} Packing={}, Expected: 1,0,0,0, Got: {},{},{},{}", Len, Packing, (float)stored.v[0], (float)stored.v[1], (float)stored.v[2], (float)stored.v[3]));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Test batch Normalize() for 2 vectors (Len == 2)
|
||||||
|
// if constexpr(Len == 2) {
|
||||||
|
// T aData[2] = {T(3), T(4)};
|
||||||
|
// T eData[2] = {T(6), T(8)};
|
||||||
|
// VectorType<2, 1> vecA(aData);
|
||||||
|
// VectorType<2, 1> vecE(eData);
|
||||||
|
// auto result = VectorType<2, 1>::Normalize(vecA, vecE);
|
||||||
|
// Vector<T, 2, 8> storedA = std::get<0>(result).Store();
|
||||||
|
// Vector<T, 2, 8> storedE = std::get<1>(result).Store();
|
||||||
|
|
||||||
|
// // Normalize (3,4) -> (0.6, 0.8)
|
||||||
|
// for (std::uint32_t i = 0; i < 2; i++) {
|
||||||
|
// if (!FloatEquals(storedA.v[i], static_cast<T>(0.6f + i * 0.2f))) {
|
||||||
|
// return new std::string(std::format("Normalize 2 vec test failed (A) at index {}, Expected: {}, Got: {}", i, (float)(0.6f + i * 0.2f), (float)storedA.v[i]));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Normalize (6,8) -> (0.6, 0.8)
|
||||||
|
// for (std::uint32_t i = 0; i < 2; i++) {
|
||||||
|
// if (!FloatEquals(storedE.v[i], static_cast<T>(0.6f + i * 0.2f))) {
|
||||||
|
// return new std::string(std::format("Normalize 2 vec test failed (E) at index {}, Expected: {}, Got: {}", i, (float)(0.6f + i * 0.2f), (float)storedE.v[i]));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Test batch LengthSq() for 2 vectors (Len == 2)
|
||||||
|
// if constexpr(Len == 2) {
|
||||||
|
// T aData[2] = {T(3), T(4)};
|
||||||
|
// T eData[2] = {T(5), T(12)};
|
||||||
|
// VectorType<2, 1> vecA(aData);
|
||||||
|
// VectorType<2, 1> vecE(eData);
|
||||||
|
// VectorType<2, 1> result = VectorType<2, 1>::LengthSq(vecA, vecE);
|
||||||
|
// Vector<T, 2, 8> stored = result.Store();
|
||||||
|
|
||||||
|
// // LengthSq of (3,4) = 9+16 = 25
|
||||||
|
// // LengthSq of (5,12) = 25+144 = 169
|
||||||
|
// if (!FloatEquals(stored.v[0], T(25)) || !FloatEquals(stored.v[1], T(169))) {
|
||||||
|
// return new std::string(std::format("LengthSq 2 vec test failed at Len={} Packing={}, Expected: 25,169, Got: {},{}", Len, Packing, (float)stored.v[0], (float)stored.v[1]));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Test batch Dot() for 2 vectors (Len == 2)
|
||||||
|
// if constexpr(Len == 2) {
|
||||||
|
// T a0Data[2] = {T(1), T(2)};
|
||||||
|
// T a1Data[2] = {T(3), T(4)};
|
||||||
|
// T e0Data[2] = {T(5), T(6)};
|
||||||
|
// T e1Data[2] = {T(7), T(8)};
|
||||||
|
// VectorType<2, 1> vecA0(a0Data);
|
||||||
|
// VectorType<2, 1> vecA1(a1Data);
|
||||||
|
// VectorType<2, 1> vecE0(e0Data);
|
||||||
|
// VectorType<2, 1> vecE1(e1Data);
|
||||||
|
// VectorType<2, 1> result = VectorType<2, 1>::Dot(vecA0, vecA1, vecE0, vecE1);
|
||||||
|
// Vector<T, 2, 8> stored = result.Store();
|
||||||
|
|
||||||
|
// // Dot (1,2) with (3,4) = 3+8=11
|
||||||
|
// // Dot (5,6) with (7,8) = 35+48=83
|
||||||
|
// if (!FloatEquals(stored.v[0], T(11)) || !FloatEquals(stored.v[1], T(83))) {
|
||||||
|
// return new std::string(std::format("Dot 2 vec test failed at Len={} Packing={}, Expected: 11,83, Got: {},{}", Len, Packing, (float)stored.v[0], (float)stored.v[1]));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return TestAllCombinations<T, VectorType, MaxSize, Len, Packing + 1>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
std::string* RunTest() {
|
||||||
|
std::string* err = TestAllCombinations<_Float16, VectorF16, VectorF16<1, 1>::MaxSize>();
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue