more F16 tests
This commit is contained in:
parent
6e6530290b
commit
6b15089e24
2 changed files with 203 additions and 40 deletions
|
|
@ -467,11 +467,12 @@ namespace Crafter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static _Float16 Dot(VectorF16<Len, 1> a, VectorF16<Len, 1> b) {
|
constexpr static _Float16 Dot(VectorF16<Len, Packing> a, VectorF16<Len, Packing> b) requires(Packing == 1) {
|
||||||
if constexpr(std::is_same_v<VectorType, __m128h>) {
|
if constexpr(std::is_same_v<VectorType, __m128h>) {
|
||||||
__m128h mul = _mm_mul_ph(a.v, b.v);
|
__m128h mul = _mm_mul_ph(a.v, b.v);
|
||||||
return _mm_reduce_add_ph(mul);
|
return _mm_reduce_add_ph(mul);
|
||||||
} else if constexpr(std::is_same_v<VectorType, __m256h>) {
|
} else if constexpr(std::is_same_v<VectorType, __m256h>) {
|
||||||
|
static_assert(std::is_same_v<decltype(a.v), VectorType>, "a.v is NOT VectorType");
|
||||||
__m256h mul = _mm256_mul_ph(a.v, b.v);
|
__m256h mul = _mm256_mul_ph(a.v, b.v);
|
||||||
return _mm256_reduce_add_ph(mul);
|
return _mm256_reduce_add_ph(mul);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -21,42 +21,11 @@ import Crafter.Math;
|
||||||
import std;
|
import std;
|
||||||
using namespace Crafter;
|
using namespace Crafter;
|
||||||
|
|
||||||
template <std::uint32_t MaxSize, std::uint32_t Len, std::uint32_t Packing>
|
// Helper function to compare floating point values with tolerance
|
||||||
std::string* TestLoadStore() {
|
bool FloatEquals(_Float16 a, _Float16 b, _Float16 epsilon = 0.001f) {
|
||||||
_Float16 floats[Len * Packing];
|
return std::abs(static_cast<float>(a) - static_cast<float>(b)) < static_cast<float>(epsilon);
|
||||||
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
|
||||||
floats[i] = static_cast<_Float16>(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorF16<Len, Packing> vec(floats);
|
|
||||||
auto stored = vec.Store();
|
|
||||||
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
|
||||||
if (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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::uint32_t MaxSize, std::uint32_t Len, std::uint32_t Packing>
|
|
||||||
std::string* TestAdd() {
|
|
||||||
_Float16 floats[Len * Packing];
|
|
||||||
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
|
||||||
floats[i] = static_cast<_Float16>(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorF16<Len, Packing> vec(floats);
|
|
||||||
vec = vec + vec;
|
|
||||||
auto stored = vec.Store();
|
|
||||||
for (std::uint32_t i = 0; i < Len * Packing; i++) {
|
|
||||||
if (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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <std::uint32_t MaxSize, std::uint32_t Len = 1, std::uint32_t Packing = 1>
|
template <std::uint32_t MaxSize, std::uint32_t Len = 1, std::uint32_t Packing = 1>
|
||||||
std::string* TestAllCombinations() {
|
std::string* TestAllCombinations() {
|
||||||
if constexpr (Len > MaxSize) {
|
if constexpr (Len > MaxSize) {
|
||||||
|
|
@ -64,15 +33,208 @@ std::string* TestAllCombinations() {
|
||||||
} else if constexpr (Len * Packing > MaxSize) {
|
} else if constexpr (Len * Packing > MaxSize) {
|
||||||
return TestAllCombinations<MaxSize, Len + 1, 1>();
|
return TestAllCombinations<MaxSize, Len + 1, 1>();
|
||||||
} else {
|
} else {
|
||||||
std::string* result = TestLoadStore<MaxSize, Len, Packing>();
|
_Float16 floats[VectorF16<Len, Packing>::Alignment];
|
||||||
if (result) return result;
|
_Float16 floats1[VectorF16<Len, Packing>::Alignment];
|
||||||
result = TestAdd<MaxSize, Len, Packing>();
|
_Float16 floats2[VectorF16<Len, Packing>::Alignment];
|
||||||
if (result) return result;
|
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>();
|
return TestAllCombinations<MaxSize, Len, Packing + 1>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
std::string* RunTest() {
|
std::string* RunTest() {
|
||||||
std::string* err = TestAllCombinations<VectorF16<1, 1>::MaxSize>();
|
std::string* err = TestAllCombinations<VectorF16<1, 1>::MaxSize>();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue