Audacity  3.0.3
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  }

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:
internal::dtoa_impl::diyfp::kPrecision
static constexpr int kPrecision
Definition: ToChars.cpp:165
internal::dtoa_impl::diyfp::e
int e
Definition: ToChars.cpp:168
internal::dtoa_impl::diyfp::f
std::uint64_t f
Definition: ToChars.cpp:167