273 lines · c
1//===-- A class to store a normalized floating point number -----*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_NORMALFLOAT_H10#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_NORMALFLOAT_H11 12#include "FPBits.h"13 14#include "hdr/stdint_proxy.h"15#include "src/__support/CPP/type_traits.h"16#include "src/__support/common.h"17#include "src/__support/macros/config.h"18 19namespace LIBC_NAMESPACE_DECL {20namespace fputil {21 22// A class which stores the normalized form of a floating point value.23// The special IEEE-754 bits patterns of Zero, infinity and NaNs are24// are not handled by this class.25//26// A normalized floating point number is of this form:27// (-1)*sign * 2^exponent * <mantissa>28// where <mantissa> is of the form 1.<...>.29template <typename T> struct NormalFloat {30 static_assert(31 cpp::is_floating_point_v<T>,32 "NormalFloat template parameter has to be a floating point type.");33 34 using StorageType = typename FPBits<T>::StorageType;35 static constexpr StorageType ONE =36 (StorageType(1) << FPBits<T>::FRACTION_LEN);37 38 // Unbiased exponent value.39 int32_t exponent;40 41 StorageType mantissa;42 // We want |StorageType| to have atleast one bit more than the actual mantissa43 // bit width to accommodate the implicit 1 value.44 static_assert(sizeof(StorageType) * 8 >= FPBits<T>::FRACTION_LEN + 1,45 "Bad type for mantissa in NormalFloat.");46 47 Sign sign = Sign::POS;48 49 LIBC_INLINE NormalFloat(Sign s, int32_t e, StorageType m)50 : exponent(e), mantissa(m), sign(s) {51 if (mantissa >= ONE)52 return;53 54 unsigned normalization_shift = evaluate_normalization_shift(mantissa);55 mantissa <<= normalization_shift;56 exponent -= normalization_shift;57 }58 59 LIBC_INLINE explicit NormalFloat(T x) { init_from_bits(FPBits<T>(x)); }60 61 LIBC_INLINE explicit NormalFloat(FPBits<T> bits) { init_from_bits(bits); }62 63 // Compares this normalized number with another normalized number.64 // Returns -1 is this number is less than |other|, 0 if this number is equal65 // to |other|, and 1 if this number is greater than |other|.66 LIBC_INLINE int cmp(const NormalFloat<T> &other) const {67 const int result = sign.is_neg() ? -1 : 1;68 if (sign != other.sign)69 return result;70 71 if (exponent > other.exponent) {72 return result;73 } else if (exponent == other.exponent) {74 if (mantissa > other.mantissa)75 return result;76 else if (mantissa == other.mantissa)77 return 0;78 else79 return -result;80 } else {81 return -result;82 }83 }84 85 // Returns a new normalized floating point number which is equal in value86 // to this number multiplied by 2^e. That is:87 // new = this * 2^e88 LIBC_INLINE NormalFloat<T> mul2(int e) const {89 NormalFloat<T> result = *this;90 result.exponent += e;91 return result;92 }93 94 LIBC_INLINE operator T() const {95 int biased_exponent = exponent + FPBits<T>::EXP_BIAS;96 // Max exponent is of the form 0xFF...E. That is why -2 and not -1.97 constexpr int MAX_EXPONENT_VALUE = (1 << FPBits<T>::EXP_LEN) - 2;98 if (biased_exponent > MAX_EXPONENT_VALUE) {99 return FPBits<T>::inf(sign).get_val();100 }101 102 FPBits<T> result(T(0.0));103 result.set_sign(sign);104 105 constexpr int SUBNORMAL_EXPONENT = -FPBits<T>::EXP_BIAS + 1;106 if (exponent < SUBNORMAL_EXPONENT) {107 unsigned shift = static_cast<unsigned>(SUBNORMAL_EXPONENT - exponent);108 // Since exponent > subnormalExponent, shift is strictly greater than109 // zero.110 if (shift <= FPBits<T>::FRACTION_LEN + 1) {111 // Generate a subnormal number. Might lead to loss of precision.112 // We round to nearest and round halfway cases to even.113 const StorageType shift_out_mask =114 static_cast<StorageType>(StorageType(1) << shift) - 1;115 const StorageType shift_out_value = mantissa & shift_out_mask;116 const StorageType halfway_value =117 static_cast<StorageType>(StorageType(1) << (shift - 1));118 result.set_biased_exponent(0);119 result.set_mantissa(mantissa >> shift);120 StorageType new_mantissa = result.get_mantissa();121 if (shift_out_value > halfway_value) {122 new_mantissa += 1;123 } else if (shift_out_value == halfway_value) {124 // Round to even.125 if (result.get_mantissa() & 0x1)126 new_mantissa += 1;127 }128 result.set_mantissa(new_mantissa);129 // Adding 1 to mantissa can lead to overflow. This can only happen if130 // mantissa was all ones (0b111..11). For such a case, we will carry131 // the overflow into the exponent.132 if (new_mantissa == ONE)133 result.set_biased_exponent(1);134 return result.get_val();135 } else {136 return result.get_val();137 }138 }139 140 result.set_biased_exponent(141 static_cast<StorageType>(exponent + FPBits<T>::EXP_BIAS));142 result.set_mantissa(mantissa);143 return result.get_val();144 }145 146private:147 LIBC_INLINE void init_from_bits(FPBits<T> bits) {148 sign = bits.sign();149 150 if (bits.is_inf_or_nan() || bits.is_zero()) {151 // Ignore special bit patterns. Implementations deal with them separately152 // anyway so this should not be a problem.153 exponent = 0;154 mantissa = 0;155 return;156 }157 158 // Normalize subnormal numbers.159 if (bits.is_subnormal()) {160 unsigned shift = evaluate_normalization_shift(bits.get_mantissa());161 mantissa = static_cast<StorageType>(bits.get_mantissa() << shift);162 exponent = 1 - FPBits<T>::EXP_BIAS - static_cast<int32_t>(shift);163 } else {164 exponent = bits.get_biased_exponent() - FPBits<T>::EXP_BIAS;165 mantissa = ONE | bits.get_mantissa();166 }167 }168 169 LIBC_INLINE unsigned evaluate_normalization_shift(StorageType m) {170 unsigned shift = 0;171 for (; (ONE & m) == 0 && (shift < FPBits<T>::FRACTION_LEN);172 m <<= 1, ++shift)173 ;174 return shift;175 }176};177 178#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80179template <>180LIBC_INLINE void181NormalFloat<long double>::init_from_bits(FPBits<long double> bits) {182 sign = bits.sign();183 184 if (bits.is_inf_or_nan() || bits.is_zero()) {185 // Ignore special bit patterns. Implementations deal with them separately186 // anyway so this should not be a problem.187 exponent = 0;188 mantissa = 0;189 return;190 }191 192 if (bits.is_subnormal()) {193 if (bits.get_implicit_bit() == 0) {194 // Since we ignore zero value, the mantissa in this case is non-zero.195 int normalization_shift =196 evaluate_normalization_shift(bits.get_mantissa());197 exponent = -16382 - normalization_shift;198 mantissa = (bits.get_mantissa() << normalization_shift);199 } else {200 exponent = -16382;201 mantissa = ONE | bits.get_mantissa();202 }203 } else {204 if (bits.get_implicit_bit() == 0) {205 // Invalid number so just store 0 similar to a NaN.206 exponent = 0;207 mantissa = 0;208 } else {209 exponent = bits.get_biased_exponent() - 16383;210 mantissa = ONE | bits.get_mantissa();211 }212 }213}214 215template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {216 using LDBits = FPBits<long double>;217 int biased_exponent = exponent + LDBits::EXP_BIAS;218 // Max exponent is of the form 0xFF...E. That is why -2 and not -1.219 constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2;220 if (biased_exponent > MAX_EXPONENT_VALUE) {221 return LDBits::inf(sign).get_val();222 }223 224 FPBits<long double> result(0.0l);225 result.set_sign(sign);226 227 constexpr int SUBNORMAL_EXPONENT = -LDBits::EXP_BIAS + 1;228 if (exponent < SUBNORMAL_EXPONENT) {229 unsigned shift = SUBNORMAL_EXPONENT - exponent;230 if (shift <= LDBits::FRACTION_LEN + 1) {231 // Generate a subnormal number. Might lead to loss of precision.232 // We round to nearest and round halfway cases to even.233 const StorageType shift_out_mask = (StorageType(1) << shift) - 1;234 const StorageType shift_out_value = mantissa & shift_out_mask;235 const StorageType halfway_value = StorageType(1) << (shift - 1);236 result.set_biased_exponent(0);237 result.set_mantissa(mantissa >> shift);238 StorageType new_mantissa = result.get_mantissa();239 if (shift_out_value > halfway_value) {240 new_mantissa += 1;241 } else if (shift_out_value == halfway_value) {242 // Round to even.243 if (result.get_mantissa() & 0x1)244 new_mantissa += 1;245 }246 result.set_mantissa(new_mantissa);247 // Adding 1 to mantissa can lead to overflow. This can only happen if248 // mantissa was all ones (0b111..11). For such a case, we will carry249 // the overflow into the exponent and set the implicit bit to 1.250 if (new_mantissa == ONE) {251 result.set_biased_exponent(1);252 result.set_implicit_bit(1);253 } else {254 result.set_implicit_bit(0);255 }256 return result.get_val();257 } else {258 return result.get_val();259 }260 }261 262 result.set_biased_exponent(biased_exponent);263 result.set_mantissa(mantissa);264 result.set_implicit_bit(1);265 return result.get_val();266}267#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80268 269} // namespace fputil270} // namespace LIBC_NAMESPACE_DECL271 272#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_NORMALFLOAT_H273