rapidyaml 0.14.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
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
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==2u, unsigned >::type
 decimal digits for 16 bit integers
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==4u, unsigned >::type
 decimal digits for 32 bit integers
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==8u, unsigned >::type
 decimal digits for 64 bit integers
template<class T>
unsigned c4::digits_hex (T v) noexcept
 return the number of digits required to encode an hexadecimal number.
template<class T>
unsigned c4::digits_bin (T v) noexcept
 return the number of digits required to encode a binary number.
template<class T>
unsigned c4::digits_oct (T v_) noexcept
 return the number of digits required to encode an octal number.

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() [1/4]

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

decimal digits for 8 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_dec() [2/4]

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

decimal digits for 16 bit integers

Definition at line 444 of file charconv.hpp.

446{
447 C4_STATIC_ASSERT(std::is_integral<T>::value);
448 C4_ASSERT(v >= 0);
449 return ((v >= 10000) ? 5u : (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);
450}

◆ digits_dec() [3/4]

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

decimal digits for 32 bit integers

Definition at line 455 of file charconv.hpp.

457{
458 C4_STATIC_ASSERT(std::is_integral<T>::value);
459 C4_ASSERT(v >= 0);
460 return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u :
461 (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u :
462 (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);
463}

◆ digits_dec() [4/4]

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

decimal digits for 64 bit integers

Definition at line 468 of file charconv.hpp.

470{
471 // thanks @fargies!!!
472 // https://github.com/biojppm/c4core/pull/77#issuecomment-1063753568
473 C4_STATIC_ASSERT(std::is_integral<T>::value);
474 C4_ASSERT(v >= 0);
475 if(v >= 1000000000) // 10
476 {
477 if(v >= 100000000000000) // 15 [15-20] range
478 {
479 if(v >= 100000000000000000) // 18 (15 + (20 - 15) / 2)
480 {
481 if((typename std::make_unsigned<T>::type)v >= 10000000000000000000u) // 20
482 return 20u;
483 else
484 return (v >= 1000000000000000000) ? 19u : 18u;
485 }
486 else if(v >= 10000000000000000) // 17
487 {
488 return 17u;
489 }
490 else
491 {
492 return(v >= 1000000000000000) ? 16u : 15u;
493 }
494 }
495 else if(v >= 1000000000000) // 13
496 {
497 return (v >= 10000000000000) ? 14u : 13u;
498 }
499 else if(v >= 100000000000) // 12
500 {
501 return 12;
502 }
503 else
504 {
505 return(v >= 10000000000) ? 11u : 10u;
506 }
507 }
508 else if(v >= 10000) // 5 [5-9] range
509 {
510 if(v >= 10000000) // 8
511 return (v >= 100000000) ? 9u : 8u;
512 else if(v >= 1000000) // 7
513 return 7;
514 else
515 return (v >= 100000) ? 6u : 5u;
516 }
517 else if(v >= 100)
518 {
519 return (v >= 1000) ? 4u : 3u;
520 }
521 else
522 {
523 return (v >= 10) ? 2u : 1u;
524 }
525}

◆ digits_hex()

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

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

Definition at line 530 of file charconv.hpp.

531{
532 C4_STATIC_ASSERT(std::is_integral<T>::value);
533 C4_ASSERT(v >= 0);
534 return v ? 1u + (msb((typename std::make_unsigned<T>::type)v) >> 2u) : 1u;
535}

◆ digits_bin()

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

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

Definition at line 539 of file charconv.hpp.

540{
541 C4_STATIC_ASSERT(std::is_integral<T>::value);
542 C4_ASSERT(v >= 0);
543 return v ? 1u + msb((typename std::make_unsigned<T>::type)v) : 1u;
544}

◆ digits_oct()

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

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

Definition at line 548 of file charconv.hpp.

549{
550 // TODO: is there a better way?
551 C4_STATIC_ASSERT(std::is_integral<T>::value);
552 C4_ASSERT(v_ >= 0);
553 using U = typename std::conditional<sizeof(T) <= sizeof(unsigned),
554 unsigned,
555 typename std::make_unsigned<T>::type>::type;
556 U v = (U) v_; // safe because we require v_ >= 0 // NOLINT
557 uint32_t __n = 1;
558 enum : U {
559 __b2 = 64u,
560 __b3 = 64u * 8u,
561 __b4 = 64u * 8u * 8u,
562 };
563 while(true)
564 {
565 if(v < 8u)
566 return __n;
567 else if(v < __b2)
568 return __n + 1;
569 else if(v < __b3)
570 return __n + 2;
571 else if(v < __b4)
572 return __n + 3;
573 v /= (U) __b4;
574 __n += 4;
575 }
576}