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