Files
2026-07-13 12:47:42 +08:00

134 lines
4.3 KiB
C++

// Copyright 2025-present the zvec project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cmath>
#include <random>
#include <ailego/math/norm_matrix.h>
#include <gtest/gtest.h>
#include <zvec/ailego/utility/float_helper.h>
using namespace zvec;
TEST(FloatHelper, General) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(0.0f, 0.9f);
std::uniform_int_distribution<int> dist2(1, 250);
for (int i = 0; i < 1000; ++i) {
float fp32 = dist(gen);
float fp16 = ailego::FloatHelper::ToFP32(
ailego::FloatHelper::ToFP16(fp32, 1.0f), 1.0f);
EXPECT_GT(0.00025, std::abs(fp32 - fp16));
}
for (int i = 0; i < 1000; ++i) {
std::vector<float> vec1_fp32, vec2_fp32;
std::vector<ailego::Float16> vec1_fp16, vec2_fp16;
int count = dist2(gen);
vec1_fp32.resize(count);
vec2_fp32.resize(count);
vec1_fp16.resize(count);
vec2_fp16.resize(count);
for (size_t j = 0; j < vec1_fp32.size(); ++j) {
vec1_fp32[j] = dist(gen);
}
float norm1;
ailego::Norm2Matrix<float, 1>::Compute(vec1_fp32.data(), vec1_fp32.size(),
&norm1);
EXPECT_NE(1.0f, norm1);
// Convert to FP16
ailego::FloatHelper::ToFP16(vec1_fp32.data(), vec1_fp32.size(),
(uint16_t *)vec1_fp16.data());
ailego::FloatHelper::ToFP16(vec1_fp32.data(), vec1_fp32.size(), norm1,
(uint16_t *)vec2_fp16.data());
for (size_t j = 0; j < vec1_fp32.size(); ++j) {
EXPECT_GT(0.00025, std::abs(vec1_fp32[j] - vec1_fp16[j]));
// EXPECT_FLOAT_EQ(vec1_fp32[j], vec1_fp16[j]);
}
float norm2;
ailego::Norm2Matrix<ailego::Float16, 1>::Compute(vec1_fp16.data(),
vec1_fp16.size(), &norm2);
EXPECT_NE(1.0f, norm2);
// Convert to FP32
ailego::FloatHelper::ToFP32((const uint16_t *)vec1_fp16.data(),
vec1_fp16.size(), vec1_fp32.data());
ailego::FloatHelper::ToFP32((const uint16_t *)vec1_fp16.data(),
vec1_fp16.size(), norm2, vec2_fp32.data());
for (size_t j = 0; j < vec1_fp32.size(); ++j) {
EXPECT_GT(0.00025, std::abs(vec1_fp32[j] - vec1_fp16[j]));
// EXPECT_FLOAT_EQ(vec1_fp32[j], vec1_fp16[j]);
}
ailego::Norm2Matrix<float, 1>::Compute(vec2_fp32.data(), vec2_fp32.size(),
&norm1);
ailego::Norm2Matrix<ailego::Float16, 1>::Compute(vec2_fp16.data(),
vec2_fp16.size(), &norm2);
// EXPECT_FLOAT_EQ(norm1, norm2);
// EXPECT_FLOAT_EQ(1.0f, norm1);
EXPECT_GT(0.001, std::abs(1.0f - norm1));
// EXPECT_FLOAT_EQ(1.0f, norm2);
EXPECT_GT(0.001, std::abs(1.0f - norm2));
}
}
TEST(Float16, General) {
ailego::Float16 a1;
EXPECT_FLOAT_EQ(0.0f, a1);
ailego::Float16 a2 = 0.33f;
EXPECT_TRUE(0.0f < a2);
EXPECT_TRUE(0.0f <= a2);
EXPECT_TRUE(0.5f > a2);
EXPECT_TRUE(0.5f >= a2);
EXPECT_TRUE(0.0 < a2);
EXPECT_TRUE(0.0 <= a2);
EXPECT_TRUE(0.5 > a2);
EXPECT_TRUE(0.5 >= a2);
EXPECT_TRUE((float)a2 != 0.0);
EXPECT_FALSE((float)a2 == 0.0);
ailego::Float16 a3 = 0.55;
EXPECT_TRUE((double)a3 != 0.0);
EXPECT_FALSE((double)a3 == 0.0);
EXPECT_TRUE(a1 < a2);
EXPECT_TRUE(a2 <= a3);
EXPECT_TRUE(a2 > a1);
EXPECT_TRUE(a3 >= a1);
ailego::Float16 a4 = a2 + a3;
ailego::Float16 a5 = a2 - a3;
ailego::Float16 a6 = a2 * a3;
ailego::Float16 a7 = a2 / a3;
a4 *= 1.0;
a5 /= 1.0;
a6 -= 0.0;
a7 += 0.0;
EXPECT_TRUE(0.0f != a4);
EXPECT_TRUE(0.0f != a5);
EXPECT_TRUE(0.0f != a6);
EXPECT_TRUE(0.0f != a7);
ailego::Float16 one = 1.0;
uint16_t *one_encoded = (uint16_t *)(&one);
printf("One: %f, 0x%x\n", (float)one, *one_encoded);
}