// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. // // 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 "fastdeploy/core/fd_tensor.h" #include "fastdeploy/core/float16.h" #include "gtest_utils.h" #include "gtest/gtest.h" #include #include #include namespace fastdeploy { TEST(float16, conversion_cpu) { // Conversion from float EXPECT_EQ(float16(1.0f).x, 0x3c00); EXPECT_EQ(float16(0.5f).x, 0x3800); EXPECT_EQ(float16(0.33333f).x, 0x3555); EXPECT_EQ(float16(0.0f).x, 0x0000); EXPECT_EQ(float16(-0.0f).x, 0x8000); EXPECT_EQ(float16(65504.0f).x, 0x7bff); EXPECT_EQ(float16(65536.0f).x, 0x7c00); // Conversion from double EXPECT_EQ(float16(1.0).x, 0x3c00); EXPECT_EQ(float16(0.5).x, 0x3800); EXPECT_EQ(float16(0.33333).x, 0x3555); EXPECT_EQ(float16(0.0).x, 0x0000); EXPECT_EQ(float16(-0.0).x, 0x8000); EXPECT_EQ(float16(65504.0).x, 0x7bff); EXPECT_EQ(float16(65536.0).x, 0x7c00); // Conversion from int EXPECT_EQ(float16(-1).x, 0xbc00); EXPECT_EQ(float16(0).x, 0x0000); EXPECT_EQ(float16(1).x, 0x3c00); EXPECT_EQ(float16(2).x, 0x4000); EXPECT_EQ(float16(3).x, 0x4200); // Conversion from bool EXPECT_EQ(float16(true).x, 0x3c00); EXPECT_EQ(float16(false).x, 0x0000); // Assignment operator float16 v_assign; v_assign = float16(0); EXPECT_EQ(v_assign.x, 0x0000); v_assign = 0.5f; EXPECT_EQ(v_assign.x, 0x3800); v_assign = 0.33333; EXPECT_EQ(v_assign.x, 0x3555); v_assign = -1; EXPECT_EQ(v_assign.x, 0xbc00); v_assign = true; EXPECT_EQ(v_assign.x, 0x3c00); // Conversion operator EXPECT_EQ(static_cast(float16(0.5f)), 0.5f); EXPECT_NEAR(static_cast(float16(0.33333)), 0.33333, 0.0001); EXPECT_EQ(static_cast(float16(-1)), -1); EXPECT_EQ(static_cast(float16(true)), true); } TEST(float16, arithmetic_cpu) { EXPECT_EQ(static_cast(float16(1) + float16(1)), 2); EXPECT_EQ(static_cast(float16(5) + float16(-5)), 0); EXPECT_NEAR(static_cast(float16(0.33333f) + float16(0.66667f)), 1.0f, 0.001); EXPECT_EQ(static_cast(float16(3) - float16(5)), -2); EXPECT_NEAR(static_cast(float16(0.66667f) - float16(0.33333f)), 0.33334f, 0.001); EXPECT_NEAR(static_cast(float16(3.3f) * float16(2.0f)), 6.6f, 0.01); EXPECT_NEAR(static_cast(float16(-2.1f) * float16(-3.0f)), 6.3f, 0.01); EXPECT_NEAR(static_cast(float16(2.0f) / float16(3.0f)), 0.66667f, 0.001); EXPECT_EQ(static_cast(float16(1.0f) / float16(2.0f)), 0.5f); EXPECT_EQ(static_cast(-float16(512.0f)), -512.0f); EXPECT_EQ(static_cast(-float16(-512.0f)), 512.0f); } TEST(float16, comparison_cpu) { EXPECT_TRUE(float16(1.0f) == float16(1.0f)); EXPECT_FALSE(float16(-1.0f) == float16(-0.5f)); EXPECT_TRUE(float16(1.0f) != float16(0.5f)); EXPECT_FALSE(float16(-1.0f) != float16(-1.0f)); EXPECT_TRUE(float16(1.0f) < float16(2.0f)); EXPECT_FALSE(float16(-1.0f) < float16(-1.0f)); EXPECT_TRUE(float16(1.0f) <= float16(1.0f)); EXPECT_TRUE(float16(2.0f) > float16(1.0f)); EXPECT_FALSE(float16(-2.0f) > float16(-2.0f)); EXPECT_TRUE(float16(2.0f) >= float16(2.0f)); EXPECT_TRUE(float16(0.0f) == float16(-0.0f)); EXPECT_TRUE(float16(0.0f) <= float16(-0.0f)); EXPECT_TRUE(float16(0.0f) >= float16(-0.0f)); EXPECT_FALSE(float16(0.0f) < float16(-0.0f)); EXPECT_FALSE(float16(-0.0f) < float16(0.0f)); EXPECT_FALSE(float16(0.0f) > float16(-0.0f)); EXPECT_FALSE(float16(-0.0f) > float16(0.0f)); } TEST(float16, floating) { // compile time assert. FDASSERT(std::is_floating_point::value, "The float16 support in CPU failed."); } TEST(float16, print) { float16 a = float16(1.0f); std::cout << a << std::endl; } // CPU test TEST(float16, isinf) { float16 a; a.x = 0x7c00; float16 b = float16(INFINITY); float16 c = static_cast(INFINITY); EXPECT_EQ(std::isinf(a), true); EXPECT_EQ(std::isinf(b), true); EXPECT_EQ(std::isinf(c), true); } TEST(float16, isnan) { float16 a; a.x = 0x7fff; float16 b = float16(NAN); float16 c = static_cast(NAN); EXPECT_EQ(std::isnan(a), true); EXPECT_EQ(std::isnan(b), true); EXPECT_EQ(std::isnan(c), true); } TEST(float16, fd_tensor_cpu) { FDTensor tensor; std::vector input_data = {float16(1.0f), float16(0.5f), float16(0.33333f), float16(0.0f)}; EXPECT_EQ(input_data[0].x, 0x3c00); EXPECT_EQ(input_data[1].x, 0x3800); EXPECT_EQ(input_data[2].x, 0x3555); EXPECT_EQ(input_data[3].x, 0x0000); tensor.Resize({4, 1}, FDDataType::FP16); std::memcpy(tensor.Data(), input_data.data(), input_data.size() * sizeof(float16)); float16* data_ptr = reinterpret_cast(tensor.Data()); EXPECT_NE(data_ptr, nullptr); EXPECT_EQ(input_data.size(), static_cast(tensor.Numel())); for (size_t i = 0; i < input_data.size(); ++i) { EXPECT_EQ(data_ptr[i].x, input_data[i].x); } } } // namespace fastdeploy