1//===-- Definition for Float128 data type -----------------------*- C++ -*-===//
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#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
10#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
11
12#include "hdr/stdint_proxy.h"
13#include "src/__support/CPP/limits.h"
14#include "src/__support/CPP/type_traits.h"
15#include "src/__support/FPUtil/cast.h"
16#include "src/__support/FPUtil/comparison_operations.h"
17#include "src/__support/FPUtil/dyadic_float.h"
18#include "src/__support/FPUtil/generic/add_sub.h"
19#include "src/__support/FPUtil/generic/div.h"
20#include "src/__support/FPUtil/generic/mul.h"
21#include "src/__support/macros/attributes.h"
22#include "src/__support/macros/config.h"
23#include "src/__support/uint128.h"
24
25namespace LIBC_NAMESPACE_DECL {
26namespace fputil {
27
28struct Float128 {
29 UInt128 bits;
30
31 LIBC_INLINE Float128() = default;
32 LIBC_INLINE constexpr Float128(const Float128 &) = default;
33 LIBC_INLINE constexpr Float128(Float128 &&) = default;
34 LIBC_INLINE constexpr Float128 &operator=(const Float128 &) = default;
35 LIBC_INLINE constexpr Float128 &operator=(Float128 &&) = default;
36
37 // Floating point type and integer type
38 template <typename T>
39 LIBC_INLINE constexpr explicit Float128(T value) : bits(0U) {
40 if constexpr (cpp::is_floating_point_v<T>) {
41 bits = fputil::cast<Float128>(value).bits;
42 } else if constexpr (cpp::is_integral_v<T>) {
43 Sign sign = Sign::POS;
44 auto unsigned_value = static_cast<cpp::make_unsigned_t<T>>(value);
45
46 if constexpr (cpp::is_signed_v<T>) {
47 if (value < 0) {
48 sign = Sign::NEG;
49 unsigned_value = -unsigned_value;
50 }
51 }
52
53 fputil::DyadicFloat<FPBits<Float128>::STORAGE_LEN> xd(sign, 0,
54 unsigned_value);
55 bits = xd.template as<Float128, /*ShouldSignalExceptions=*/true>().bits;
56
57 } else if constexpr (cpp::is_convertible_v<T, Float128>) {
58 bits = value.operator Float128().bits;
59 } else {
60 bits = fputil::cast<Float128>(x: static_cast<float>(value)).bits;
61 }
62 }
63
64 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T> &&
65 !cpp::is_same_v<T, Float128>,
66 int> = 0>
67 LIBC_INLINE LIBC_CONSTEXPR_DEFAULT operator T() const {
68 return fputil::cast<T>(*this);
69 }
70
71 template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
72 LIBC_INLINE constexpr explicit operator T() const {
73 constexpr T MIN_T = cpp::numeric_limits<T>::min();
74 constexpr T MAX_T = cpp::numeric_limits<T>::max();
75 FPBits<Float128> x_bits(*this);
76 // Raise FE_INVALID for inf and NaN
77 if (x_bits.is_inf_or_nan()) {
78 raise_except_if_required(FE_INVALID);
79 return x_bits.is_neg() ? MIN_T : MAX_T;
80 }
81 int exponent = x_bits.get_explicit_exponent();
82 constexpr int EXPONENT_LIMIT = cpp::numeric_limits<T>::digits;
83 if (exponent > EXPONENT_LIMIT) {
84 raise_except_if_required(FE_INVALID);
85 return x_bits.is_neg() ? MIN_T : MAX_T;
86 } else if (exponent == EXPONENT_LIMIT) {
87 if (x_bits.is_pos() || x_bits.get_mantissa() != 0) {
88 raise_except_if_required(FE_INVALID);
89 return x_bits.is_neg() ? MIN_T : MAX_T;
90 }
91 }
92
93 int x_bits_exp = exponent - FPBits<Float128>::FRACTION_LEN;
94 // sign * 2^(exp-bias) * mantissa
95 DyadicFloat<FPBits<Float128>::STORAGE_LEN> xd(
96 x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
97 return static_cast<T>(xd.as_mantissa_type());
98 }
99
100 // unary
101 LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float128 operator-() const {
102 fputil::FPBits<Float128> result(*this);
103 result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
104 return result.get_val();
105 }
106 // operator overloads
107 LIBC_INLINE constexpr Float128 operator+(const Float128 &other) const {
108 return fputil::generic::add<Float128>(x: *this, y: other);
109 }
110
111 LIBC_INLINE constexpr Float128 operator-(const Float128 &other) const {
112 return fputil::generic::sub<Float128>(x: *this, y: other);
113 }
114
115 LIBC_INLINE constexpr Float128 operator*(const Float128 &other) const {
116 return fputil::generic::mul<Float128>(x: *this, y: other);
117 }
118
119 LIBC_INLINE constexpr Float128 operator/(const Float128 &other) const {
120 return fputil::generic::div<Float128>(x: *this, y: other);
121 }
122
123 LIBC_INLINE constexpr Float128 &operator*=(const Float128 &other) {
124 *this = *this * other;
125 return *this;
126 }
127
128 LIBC_INLINE constexpr Float128 &operator+=(const Float128 &other) {
129 *this = *this + other;
130 return *this;
131 }
132
133 LIBC_INLINE constexpr Float128 &operator-=(const Float128 &other) {
134 *this = *this - other;
135 return *this;
136 }
137
138 LIBC_INLINE constexpr Float128 &operator/=(const Float128 &other) {
139 *this = *this / other;
140 return *this;
141 }
142
143 LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
144 return fputil::equals(x: *this, y: other);
145 }
146
147 LIBC_INLINE constexpr bool operator!=(const Float128 &other) const {
148 return !fputil::equals(x: *this, y: other);
149 }
150
151 LIBC_INLINE constexpr bool operator<(const Float128 &other) const {
152 return fputil::less_than(x: *this, y: other);
153 }
154
155 LIBC_INLINE constexpr bool operator<=(const Float128 &other) const {
156 return fputil::less_than_or_equals(x: *this, y: other);
157 }
158
159 LIBC_INLINE constexpr bool operator>(const Float128 &other) const {
160 return fputil::greater_than(x: *this, y: other);
161 }
162
163 LIBC_INLINE constexpr bool operator>=(const Float128 &other) const {
164 return fputil::greater_than_or_equals(x: *this, y: other);
165 }
166};
167
168static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
169 LIBC_NAMESPACE::fputil::Float128>::value);
170static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
171 LIBC_NAMESPACE::fputil::Float128>::value);
172
173} // namespace fputil
174} // namespace LIBC_NAMESPACE_DECL
175
176#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
177