rapidyaml  0.11.0
parse and emit YAML, and do it fast
Get number of digits

Functions

template<class T >
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==1u, unsigned >::type
 decimal digits for 8 bit integers More...
 
template<class T >
unsigned c4::digits_hex (T v) noexcept
 return the number of digits required to encode an hexadecimal number. More...
 
template<class T >
unsigned c4::digits_bin (T v) noexcept
 return the number of digits required to encode a binary number. More...
 
template<class T >
unsigned c4::digits_oct (T v_) noexcept
 return the number of digits required to encode an octal number. More...
 

Detailed Description

Note
At first sight this code may look heavily branchy and therefore inefficient. However, measurements revealed this to be the fastest among the alternatives.
See also
https://github.com/biojppm/c4core/pull/77

Function Documentation

◆ digits_dec()

template<class T >
auto c4::digits_dec ( v) -> typename std::enable_if<sizeof(T) == 1u, unsigned>::type
inlinenoexcept

decimal digits for 8 bit integers

decimal digits for 64 bit integers

decimal digits for 32 bit integers

decimal digits for 16 bit integers

Definition at line 433 of file charconv.hpp.

435 {
436  C4_STATIC_ASSERT(std::is_integral<T>::value);
437  C4_ASSERT(v >= 0);
438  return ((v >= 100) ? 3u : ((v >= 10) ? 2u : 1u));
439 }

◆ digits_hex()

template<class T >
unsigned c4::digits_hex ( v)
inlinenoexcept

return the number of digits required to encode an hexadecimal number.

Definition at line 516 of file charconv.hpp.

517 {
518  C4_STATIC_ASSERT(std::is_integral<T>::value);
519  C4_ASSERT(v >= 0);
520  return v ? 1u + (msb((typename std::make_unsigned<T>::type)v) >> 2u) : 1u;
521 }

◆ digits_bin()

template<class T >
unsigned c4::digits_bin ( v)
inlinenoexcept

return the number of digits required to encode a binary number.

Definition at line 525 of file charconv.hpp.

526 {
527  C4_STATIC_ASSERT(std::is_integral<T>::value);
528  C4_ASSERT(v >= 0);
529  return v ? 1u + msb((typename std::make_unsigned<T>::type)v) : 1u;
530 }

◆ digits_oct()

template<class T >
unsigned c4::digits_oct ( v_)
inlinenoexcept

return the number of digits required to encode an octal number.

Definition at line 534 of file charconv.hpp.

535 {
536  // TODO: is there a better way?
537  C4_STATIC_ASSERT(std::is_integral<T>::value);
538  C4_ASSERT(v_ >= 0);
539  using U = typename std::conditional<sizeof(T) <= sizeof(unsigned),
540  unsigned,
541  typename std::make_unsigned<T>::type>::type;
542  U v = (U) v_; // safe because we require v_ >= 0 // NOLINT
543  uint32_t __n = 1;
544  enum : U {
545  __b2 = 64u,
546  __b3 = 64u * 8u,
547  __b4 = 64u * 8u * 8u,
548  };
549  while(true)
550  {
551  if(v < 8u)
552  return __n;
553  else if(v < __b2)
554  return __n + 1;
555  else if(v < __b3)
556  return __n + 2;
557  else if(v < __b4)
558  return __n + 3;
559  v /= (U) __b4;
560  __n += 4;
561  }
562 }