FLANG

binary-floating-point.h
1 //===-- include/flang/Decimal/binary-floating-point.h -----------*- 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 FORTRAN_DECIMAL_BINARY_FLOATING_POINT_H_
10 #define FORTRAN_DECIMAL_BINARY_FLOATING_POINT_H_
11
12 // Access and manipulate the fields of an IEEE-754 binary
13 // floating-point value via a generalized template.
14
15 #include "flang/Common/real.h"
16 #include "flang/Common/uint128.h"
17 #include <cinttypes>
18 #include <climits>
19 #include <cstring>
20 #include <type_traits>
21
22 namespace Fortran::decimal {
23
24 template <int BINARY_PRECISION>
25 class BinaryFloatingPointNumber : public common::RealDetails<BINARY_PRECISION> {
26 public:
27 using Details = common::RealDetails<BINARY_PRECISION>;
28 using Details::bits;
29 using Details::decimalPrecision;
30 using Details::decimalRange;
31 using Details::exponentBias;
32 using Details::exponentBits;
33 using Details::isImplicitMSB;
34 using Details::maxDecimalConversionDigits;
35 using Details::maxExponent;
36 using Details::significandBits;
37
38 using RawType = common::HostUnsignedIntType<bits>;
39 static_assert(CHAR_BIT * sizeof(RawType) >= bits);
40 static constexpr RawType significandMask{(RawType{1} << significandBits) - 1};
41
42 constexpr BinaryFloatingPointNumber() {} // zero
43 constexpr BinaryFloatingPointNumber(
44 const BinaryFloatingPointNumber &that) = default;
45 constexpr BinaryFloatingPointNumber(
46 BinaryFloatingPointNumber &&that) = default;
47 constexpr BinaryFloatingPointNumber &operator=(
48 const BinaryFloatingPointNumber &that) = default;
49 constexpr BinaryFloatingPointNumber &operator=(
50 BinaryFloatingPointNumber &&that) = default;
51
52 RawType raw() const { return raw_; }
53
54 template <typename A> explicit constexpr BinaryFloatingPointNumber(A x) {
55 static_assert(sizeof raw_ <= sizeof x);
56 std::memcpy(reinterpret_cast<void *>(&raw_),
57 reinterpret_cast<const void *>(&x), sizeof raw_);
58 }
59
60 constexpr int BiasedExponent() const {
61 return static_cast<int>(
62 (raw_ >> significandBits) & ((1 << exponentBits) - 1));
63 }
64 constexpr int UnbiasedExponent() const {
65 int biased{BiasedExponent()};
66 return biased - exponentBias + (biased == 0);
67 }
68 constexpr RawType Significand() const { return raw_ & significandMask; }
69 constexpr RawType Fraction() const {
70 RawType sig{Significand()};
71 if (isImplicitMSB && BiasedExponent() > 0) {
72 sig |= RawType{1} << significandBits;
73 }
74 return sig;
75 }
76
77 constexpr bool IsZero() const {
78 return (raw_ & ((RawType{1} << (bits - 1)) - 1)) == 0;
79 }
80 constexpr bool IsNaN() const {
81 return BiasedExponent() == maxExponent && Significand() != 0;
82 }
83 constexpr bool IsInfinite() const {
84 return BiasedExponent() == maxExponent && Significand() == 0;
85 }
86 constexpr bool IsMaximalFiniteMagnitude() const {
87 return BiasedExponent() == maxExponent - 1 &&
88 Significand() == significandMask;
89 }
90 constexpr bool IsNegative() const { return ((raw_ >> (bits - 1)) & 1) != 0; }
91
92 constexpr void Negate() { raw_ ^= RawType{1} << (bits - 1); }
93
94 // For calculating the nearest neighbors of a floating-point value
95 constexpr void Previous() {
96 RemoveExplicitMSB();
97 --raw_;
98 InsertExplicitMSB();
99 }
100 constexpr void Next() {
101 RemoveExplicitMSB();
102 ++raw_;
103 InsertExplicitMSB();
104 }
105
106 private:
107 constexpr void RemoveExplicitMSB() {
108 if constexpr (!isImplicitMSB) {
109 raw_ = (raw_ & (significandMask >> 1)) | ((raw_ & ~significandMask) >> 1);
110 }
111 }
112 constexpr void InsertExplicitMSB() {
113 if constexpr (!isImplicitMSB) {
114 constexpr RawType mask{significandMask >> 1};
115 raw_ = (raw_ & mask) | ((raw_ & ~mask) << 1);
116 if (BiasedExponent() > 0) {
117 raw_ |= RawType{1} << (significandBits - 1);
118 }
119 }
120 }
121
122 RawType raw_{0};
123 };
124 } // namespace Fortran::decimal
125 #endif
Fortran::decimal::BinaryFloatingPointNumber
Definition: binary-floating-point.h:25
Fortran::common::RealDetails
Definition: real.h:67