Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | List of all members
internal::dtoa_impl::diyfp Struct Reference

Public Member Functions

constexpr diyfp (std::uint64_t f_, int e_) noexcept
 

Static Public Member Functions

static diyfp sub (const diyfp &x, const diyfp &y) noexcept
 returns x - y More...
 
static diyfp mul (const diyfp &x, const diyfp &y) noexcept
 returns x * y More...
 
static diyfp normalize (diyfp x) noexcept
 normalize x such that the significand is >= 2^(q-1) More...
 
static diyfp normalize_to (const diyfp &x, const int target_exponent) noexcept
 normalize x such that the result has the exponent E More...
 

Public Attributes

std::uint64_t f = 0
 
int e = 0
 

Static Public Attributes

static constexpr int kPrecision = 64
 

Detailed Description

Definition at line 163 of file ToChars.cpp.

Constructor & Destructor Documentation

◆ diyfp()

constexpr internal::dtoa_impl::diyfp::diyfp ( std::uint64_t  f_,
int  e_ 
)
inlineconstexprnoexcept

Definition at line 170 of file ToChars.cpp.

171 : f(f_)
172 , e(e_)
173 {
174 }

Member Function Documentation

◆ mul()

static diyfp internal::dtoa_impl::diyfp::mul ( const diyfp x,
const diyfp y 
)
inlinestaticnoexcept

returns x * y

Note
The result is rounded. (Only the upper q bits are returned.)

Definition at line 190 of file ToChars.cpp.

191 {
192 static_assert(kPrecision == 64, "internal error");
193
194 // Computes:
195 // f = round((x.f * y.f) / 2^q)
196 // e = x.e + y.e + q
197
198#if defined(_MSC_VER) && defined(_M_X64)
199
200 uint64_t h = 0;
201 uint64_t l = _umul128(x.f, y.f, &h);
202 h += l >> 63; // round, ties up: [h, l] += 2^q / 2
203
204 return { h, x.e + y.e + 64 };
205
206#elif defined(__GNUC__) && defined(__SIZEOF_INT128__)
207
208 __extension__ using Uint128 = unsigned __int128;
209
210 Uint128 const p = Uint128{x.f} * Uint128{y.f};
211
212 uint64_t h = static_cast<uint64_t>(p >> 64);
213 uint64_t l = static_cast<uint64_t>(p);
214 h += l >> 63; // round, ties up: [h, l] += 2^q / 2
215
216 return { h, x.e + y.e + 64 };
217
218#else
219
220 // Emulate the 64-bit * 64-bit multiplication:
221 //
222 // p = u * v
223 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
224 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) +
225 // 2^64 (u_hi v_hi ) = (p0 ) + 2^32 ((p1 ) + (p2
226 // ))
227 // + 2^64 (p3 ) = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo +
228 // 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) =
229 // (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi +
230 // p2_hi + p3) = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) = (p0_lo )
231 // + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
232 //
233 // (Since Q might be larger than 2^32 - 1)
234 //
235 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
236 //
237 // (Q_hi + H does not overflow a 64-bit int)
238 //
239 // = p_lo + 2^64 p_hi
240
241 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
242 const std::uint64_t u_hi = x.f >> 32u;
243 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
244 const std::uint64_t v_hi = y.f >> 32u;
245
246 const std::uint64_t p0 = u_lo * v_lo;
247 const std::uint64_t p1 = u_lo * v_hi;
248 const std::uint64_t p2 = u_hi * v_lo;
249 const std::uint64_t p3 = u_hi * v_hi;
250
251 const std::uint64_t p0_hi = p0 >> 32u;
252 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
253 const std::uint64_t p1_hi = p1 >> 32u;
254 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
255 const std::uint64_t p2_hi = p2 >> 32u;
256
257 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
258
259 // The full product might now be computed as
260 //
261 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
262 // p_lo = p0_lo + (Q << 32)
263 //
264 // But in this particular case here, the full p_lo is not required.
265 // Effectively we only need to add the highest bit in p_lo to p_hi (and
266 // Q_hi + 1 does not overflow).
267
268 Q += std::uint64_t { 1 } << (64u - 32u - 1u); // round, ties up
269
270 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
271
272 return { h, x.e + y.e + 64 };
273#endif
274 }
static constexpr int kPrecision
Definition: ToChars.cpp:165

References kPrecision.

Referenced by internal::dtoa_impl::grisu2().

Here is the caller graph for this function:

◆ normalize()

static diyfp internal::dtoa_impl::diyfp::normalize ( diyfp  x)
inlinestaticnoexcept

normalize x such that the significand is >= 2^(q-1)

Precondition
x.f != 0

Definition at line 280 of file ToChars.cpp.

281 {
282
283 while ((x.f >> 63u) == 0)
284 {
285 x.f <<= 1u;
286 x.e--;
287 }
288
289 return x;
290 }

References f.

Referenced by internal::dtoa_impl::compute_boundaries().

Here is the caller graph for this function:

◆ normalize_to()

static diyfp internal::dtoa_impl::diyfp::normalize_to ( const diyfp x,
const int  target_exponent 
)
inlinestaticnoexcept

normalize x such that the result has the exponent E

Precondition
e >= x.e and the upper e - x.e bits of x.f must be zero.

Definition at line 296 of file ToChars.cpp.

297 {
298 const int delta = x.e - target_exponent;
299
300 return { x.f << delta, target_exponent };
301 }

References e.

Referenced by internal::dtoa_impl::compute_boundaries().

Here is the caller graph for this function:

◆ sub()

static diyfp internal::dtoa_impl::diyfp::sub ( const diyfp x,
const diyfp y 
)
inlinestaticnoexcept

returns x - y

Precondition
x.e == y.e and x.f >= y.f

Definition at line 180 of file ToChars.cpp.

181 {
182
183 return { x.f - y.f, x.e };
184 }

References f.

Referenced by internal::dtoa_impl::grisu2_digit_gen().

Here is the caller graph for this function:

Member Data Documentation

◆ e

int internal::dtoa_impl::diyfp::e = 0

◆ f

std::uint64_t internal::dtoa_impl::diyfp::f = 0

◆ kPrecision

constexpr int internal::dtoa_impl::diyfp::kPrecision = 64
staticconstexpr

Definition at line 165 of file ToChars.cpp.

Referenced by internal::dtoa_impl::grisu2(), and mul().


The documentation for this struct was generated from the following file: