* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "opdev/fp16_t.h"
#include "gtest/gtest.h"
#define CHECK_FP16_TEST_RESULT(fp16Val, expectSign, expectExp, expectMan) \
op::ExtractFP16(fp16Val.val, &actualSign, &actualExp, &actualMan); \
EXPECT_EQ(actualSign, expectSign); \
EXPECT_EQ(actualExp, expectExp); \
EXPECT_EQ(actualMan, expectMan);
using namespace op;
class TestFp16 : public testing::Test {};
TEST_F(TestFp16, InfNaN)
{
uint16_t actualSign = 0;
int16_t actualExp = 0;
uint16_t actualMan = 0;
fp16_t doubleInfMinus = static_cast<double>(65504);
CHECK_FP16_TEST_RESULT(doubleInfMinus, 0u, 30, 0x7FF);
fp16_t doubleInf = static_cast<double>(65520);
EXPECT_EQ(doubleInf.val, 31744);
fp16_t doubeInfPlus = static_cast<double>(100000.0);
EXPECT_EQ(doubeInfPlus.val, 31744);
fp16_t doubeInfInf = static_cast<double>(INFINITY);
EXPECT_EQ(doubeInfInf.val, 31744);
fp16_t doubeNan = static_cast<double>(NAN);
EXPECT_EQ(doubeNan.val, 32767);
fp16_t floatInfMinus = static_cast<double>(65504);
CHECK_FP16_TEST_RESULT(floatInfMinus, 0u, 30, 0x7FF);
fp16_t floatInf = static_cast<float>(65520);
EXPECT_EQ(floatInf.val, 31744);
fp16_t floatInfPlus = static_cast<float>(100000.0);
EXPECT_EQ(floatInfPlus.val, 31744);
fp16_t floatInfInf = static_cast<float>(INFINITY);
EXPECT_EQ(floatInfInf.val, 31744);
fp16_t floatNan = static_cast<float>(NAN);
EXPECT_EQ(floatNan.val, 32767);
fp16_t int32InfMinus = static_cast<double>(65504);
CHECK_FP16_TEST_RESULT(int32InfMinus, 0u, 30, 0x7FF);
fp16_t int32Inf = static_cast<int32_t>(65520);
EXPECT_EQ(int32Inf.val, 31744);
fp16_t int32InfPlus = static_cast<int32_t>(100000.0);
EXPECT_EQ(int32InfPlus.val, 31744);
fp16_t int64InfMinus = static_cast<double>(65504);
CHECK_FP16_TEST_RESULT(int64InfMinus, 0u, 30, 0x7FF);
fp16_t int64Inf = static_cast<int64_t>(65520);
EXPECT_EQ(int64Inf.val, 31744);
fp16_t int64InfPlus = static_cast<int64_t>(100000.0);
EXPECT_EQ(int64InfPlus.val, 31744);
}
TEST_F(TestFp16, FormatToString)
{
fp16_t val = 8.1;
fp16_t val2 = 9.5;
fp16_t midVal = 35500;
fp16_t largeVal = 65500.0;
double doubleVal = val.toDouble();
int8_t int8Val = val.toInt8();
int8_t midInt8Val = midVal.toInt8();
int8_t largeInt8Val = largeVal.toInt8();
uint8_t uint8Val = val.toUInt8();
int16_t int16Val = val.toInt16();
int16_t midInt16Val = midVal.toInt16();
int16_t largeInt16Val = largeVal.toInt16();
uint16_t uint16Val = val.toUInt16();
int32_t int32Val = val.toInt32();
uint32_t uint32Val = val.toUInt32();
uint32_t largeUint32Val = largeVal.toUInt32();
fp16_t addVal = val + val;
fp16_t mulVal = val * val;
fp16_t divVal = val / val;
fp16_t subVal = val - val;
divVal = val / val2;
divVal = val2 / val;
divVal = val2 / fp16_t(0);
divVal = fp16_t(0) / val;
divVal = fp16_t(0);
divVal += val;
divVal -= val2;
divVal *= fp16_t(1.0);
divVal /= fp16_t(1.0);
fp16_t int8ToFp16 = int8Val;
fp16_t uin8ToFp16 = uint8Val;
fp16_t int16ToFp16 = int16Val;
fp16_t largeInt16ToFp16 = largeInt16Val;
fp16_t uint16ToFp16 = uint16Val;
fp16_t int32ToFp16 = int32Val;
fp16_t uint32ToFp16 = uint32Val;
fp16_t largeUint32ToFp16 = largeUint32Val;
fp16_t resVal = val;
resVal = largeVal;
uint16_t uValue = 1;
resVal = uValue;
uValue = -1;
resVal = uValue;
uValue = 0;
resVal = uValue;
EXPECT_EQ(uint32Val, 8);
EXPECT_TRUE(fp16_t(3.2) > fp16_t(3.1));
EXPECT_TRUE(fp16_t(3.2) < fp16_t(3.3));
EXPECT_TRUE(fp16_t(3.2) <= fp16_t(3.3));
EXPECT_TRUE(fp16_t(3.2) != fp16_t(3.3));
}