1//===-- Unittests for the DyadicFloat class -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/__support/FPUtil/dyadic_float.h"
10#include "src/__support/big_int.h"
11#include "test/UnitTest/FPMatcher.h"
12#include "test/UnitTest/Test.h"
13#include "utils/MPFRWrapper/MPFRUtils.h"
14
15using Float128 = LIBC_NAMESPACE::fputil::DyadicFloat<128>;
16using Float192 = LIBC_NAMESPACE::fputil::DyadicFloat<192>;
17using Float256 = LIBC_NAMESPACE::fputil::DyadicFloat<256>;
18
19TEST(LlvmLibcDyadicFloatTest, BasicConversions) {
20 Float128 x(Sign::POS, /*exponent*/ 0,
21 /*mantissa*/ Float128::MantissaType(1));
22 ASSERT_FP_EQ(1.0f, float(x));
23 ASSERT_FP_EQ(1.0, double(x));
24
25 Float128 y(0x1.0p-53);
26 ASSERT_FP_EQ(0x1.0p-53f, float(y));
27 ASSERT_FP_EQ(0x1.0p-53, double(y));
28
29 Float128 z = quick_add(a: x, b: y);
30
31 EXPECT_FP_EQ_ALL_ROUNDING(float(x) + float(y), float(z));
32 EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z));
33}
34
35TEST(LlvmLibcDyadicFloatTest, QuickAdd) {
36 Float192 x(Sign::POS, /*exponent*/ 0,
37 /*mantissa*/ Float192::MantissaType(0x123456));
38 ASSERT_FP_EQ(0x1.23456p20, double(x));
39
40 Float192 y(0x1.abcdefp-20);
41 ASSERT_FP_EQ(0x1.abcdefp-20, double(y));
42
43 Float192 z = quick_add(a: x, b: y);
44 EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z));
45}
46
47TEST(LlvmLibcDyadicFloatTest, QuickMul) {
48 Float256 x(Sign::POS, /*exponent*/ 0,
49 /*mantissa*/ Float256::MantissaType(0x123456));
50 ASSERT_FP_EQ(0x1.23456p20, double(x));
51
52 Float256 y(0x1.abcdefp-25);
53 ASSERT_FP_EQ(0x1.abcdefp-25, double(y));
54
55 Float256 z = quick_mul(a: x, b: y);
56 EXPECT_FP_EQ_ALL_ROUNDING(double(x) * double(y), double(z));
57}
58
59#define TEST_EDGE_RANGES(Name, Type) \
60 TEST(LlvmLibcDyadicFloatTest, EdgeRanges##Name) { \
61 using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>; \
62 using DFType = LIBC_NAMESPACE::fputil::DyadicFloat<Bits::STORAGE_LEN>; \
63 Type max_normal = Bits::max_normal().get_val(); \
64 Type min_normal = Bits::min_normal().get_val(); \
65 Type min_subnormal = Bits::min_subnormal().get_val(); \
66 Type two(2); \
67 \
68 DFType x(min_normal); \
69 EXPECT_FP_EQ_ALL_ROUNDING(min_normal, static_cast<Type>(x)); \
70 --x.exponent; \
71 EXPECT_FP_EQ(min_normal / two, static_cast<Type>(x)); \
72 \
73 DFType y(two *min_normal - min_subnormal); \
74 --y.exponent; \
75 EXPECT_FP_EQ(min_normal, static_cast<Type>(y)); \
76 \
77 DFType z(min_subnormal); \
78 EXPECT_FP_EQ_ALL_ROUNDING(min_subnormal, static_cast<Type>(z)); \
79 --z.exponent; \
80 EXPECT_FP_EQ(Bits::zero().get_val(), static_cast<Type>(z)); \
81 \
82 DFType t(max_normal); \
83 EXPECT_FP_EQ_ALL_ROUNDING(max_normal, static_cast<Type>(t)); \
84 ++t.exponent; \
85 EXPECT_FP_EQ(Bits::inf().get_val(), static_cast<Type>(t)); \
86 } \
87 static_assert(true, "Require semicolon.")
88
89TEST_EDGE_RANGES(Float, float);
90TEST_EDGE_RANGES(Double, double);
91TEST_EDGE_RANGES(LongDouble, long double);
92

source code of libc/test/src/__support/FPUtil/dyadic_float_test.cpp