join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
diyfp.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_DATA_DIYFP_HPP
26#define JOIN_DATA_DIYFP_HPP
27
28// C++.
29#include <limits>
30
31// C.
32#include <cstdint>
33#include <cstring>
34
35namespace join
36{
40 class DiyFp
41 {
42 public:
46 constexpr DiyFp () noexcept = default;
47
52 constexpr DiyFp (const DiyFp& other) noexcept = default;
53
59 constexpr DiyFp& operator= (const DiyFp& other) noexcept = default;
60
65 explicit DiyFp (double value) noexcept
66 {
67 uint64_t u64 = 0;
68 memcpy (&u64, &value, sizeof (double));
69
71 _exponent = static_cast<int> ((u64 & _exponentMask) >> _mantissaSize);
72
73 if (_exponent)
74 {
77 }
78 else
79 {
81 }
82 }
83
89 constexpr DiyFp (uint64_t mantissa, int exponent) noexcept
90 : _mantissa (mantissa)
91 , _exponent (exponent)
92 {
93 }
94
98 ~DiyFp () = default;
99
104 inline constexpr DiyFp& normalize () noexcept
105 {
106 if (_mantissa == 0)
107 {
108 return *this;
109 }
110
111 int shift = __builtin_clzll (_mantissa);
112 _mantissa <<= shift;
113 _exponent -= shift;
114
115 return *this;
116 }
117
118 private:
123 inline constexpr DiyFp& normalizeBoundary () noexcept
124 {
125 if (_mantissa != 0)
126 {
127 int shift = __builtin_clzll (_mantissa) - (64 - _mantissaSize - 2);
128 if (shift > 0)
129 {
130 _mantissa <<= shift;
131 _exponent -= shift;
132 }
133 }
134
135 constexpr int shift = _diyMantissaSize - _mantissaSize - 2;
136 _mantissa <<= shift;
137 _exponent -= shift;
138
139 return *this;
140 }
141
142 public:
147 constexpr void normalizedBoundaries (DiyFp& minus, DiyFp& plus) const noexcept
148 {
149 plus._mantissa = (_mantissa << 1) + 1;
150 plus._exponent = _exponent - 1;
151 plus.normalizeBoundary ();
152
153 const bool special = __builtin_expect (_mantissa == _hiddenBit, 0);
154 minus._mantissa = (_mantissa << (special ? 2 : 1)) - 1;
155 minus._exponent = _exponent - (special ? 2 : 1);
156
157 const int diff = minus._exponent - plus._exponent;
158 minus._mantissa <<= diff;
159 minus._exponent = plus._exponent;
160 }
161
167 inline constexpr DiyFp& operator-= (const DiyFp& rhs) noexcept
168 {
169 _mantissa -= rhs._mantissa;
170 return *this;
171 }
172
178 inline constexpr DiyFp& operator*= (const DiyFp& rhs) noexcept
179 {
180#if defined(__SIZEOF_INT128__)
181 __uint128_t product = static_cast<__uint128_t> (_mantissa) * static_cast<__uint128_t> (rhs._mantissa);
182 _mantissa = static_cast<uint64_t> ((product >> 64) + ((product >> 63) & 1));
183#else
184 uint64_t M32 = 0xFFFFFFFFU;
185
186 uint64_t a = _mantissa >> 32;
187 uint64_t b = _mantissa & M32;
188 uint64_t c = rhs._mantissa >> 32;
189 uint64_t d = rhs._mantissa & M32;
190
191 uint64_t ac = a * c;
192 uint64_t bc = b * c;
193 uint64_t ad = a * d;
194 uint64_t bd = b * d;
195
196 uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32) + (1U << 31);
197 _mantissa = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
198#endif
199 _exponent += rhs._exponent + 64;
200
201 return *this;
202 }
203
205 static constexpr int _diyMantissaSize = std::numeric_limits<uint64_t>::digits;
206
208 static constexpr int _mantissaSize = std::numeric_limits<double>::digits - 1;
209
211 static constexpr int _exponentBias = 0x3FF + _mantissaSize;
212
214 static constexpr uint64_t _mantissaMask = 0x000FFFFFFFFFFFFFLLU;
215
217 static constexpr uint64_t _exponentMask = 0x7FF0000000000000LLU;
218
220 static constexpr uint64_t _hiddenBit = 0x0010000000000000LLU;
221
223 uint64_t _mantissa = 0;
224
226 int _exponent = 0;
227 };
228
235 inline constexpr DiyFp operator- (const DiyFp& lhs, const DiyFp& rhs)
236 {
237 return DiyFp (lhs) -= rhs;
238 }
239
246 inline constexpr DiyFp operator* (const DiyFp& lhs, const DiyFp& rhs)
247 {
248 return DiyFp (lhs) *= rhs;
249 }
250}
251
252#endif
hand made floating point.
Definition diyfp.hpp:41
static constexpr int _exponentBias
exponent bias.
Definition diyfp.hpp:211
static constexpr uint64_t _exponentMask
exponent mask.
Definition diyfp.hpp:217
static constexpr int _mantissaSize
double mantissa size.
Definition diyfp.hpp:208
static constexpr uint64_t _hiddenBit
hidden bit.
Definition diyfp.hpp:220
constexpr DiyFp() noexcept=default
default constructor.
constexpr DiyFp(uint64_t mantissa, int exponent) noexcept
create floating point using mantissa and exponent.
Definition diyfp.hpp:89
int _exponent
exponent.
Definition diyfp.hpp:226
static constexpr int _diyMantissaSize
home made double mantissa size.
Definition diyfp.hpp:205
constexpr DiyFp & operator*=(const DiyFp &rhs) noexcept
multiplication operator.
Definition diyfp.hpp:178
constexpr DiyFp & operator-=(const DiyFp &rhs) noexcept
minus operator
Definition diyfp.hpp:167
uint64_t _mantissa
mantissa.
Definition diyfp.hpp:223
static constexpr uint64_t _mantissaMask
mantissa mask.
Definition diyfp.hpp:214
~DiyFp()=default
destroy instance.
constexpr void normalizedBoundaries(DiyFp &minus, DiyFp &plus) const noexcept
get normalized boundaries.
Definition diyfp.hpp:147
constexpr DiyFp & normalize() noexcept
normalize floating point.
Definition diyfp.hpp:104
Definition acceptor.hpp:32
constexpr DiyFp operator*(const DiyFp &lhs, const DiyFp &rhs)
multiplication operator.
Definition diyfp.hpp:246
constexpr DiyFp operator-(const DiyFp &lhs, const DiyFp &rhs)
minus operator
Definition diyfp.hpp:235