dconv 2.0
C++14 library for printing and parsing floating point numbers
Loading...
Searching...
No Matches
digits.hpp
Go to the documentation of this file.
1
25#ifndef __DCONV_DIGITS_HPP__
26#define __DCONV_DIGITS_HPP__
27
28// C.
29#include <cstdint>
30
31namespace dconv
32{
33 namespace details
34 {
36 constexpr uint32_t pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
37
39 alignas (64) constexpr char digitPairs[] =
40 "0001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152"
41 "5354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899";
42
44 alignas (64) constexpr uint8_t pairZeros[] = {
45 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
48
54 inline int countTrailingZeros (uint32_t group) noexcept
55 {
56 return pairZeros[group % 100] + ((group % 100 == 0) ? pairZeros[group / 100] : 0);
57 }
58
64 inline int countDigits (uint64_t digits) noexcept
65 {
66 if (digits < 100000000)
67 {
68 if (digits < 10000)
69 {
70 if (digits < 100)
71 {
72 return (digits < 10) ? 1 : 2;
73 }
74 return (digits < 1000) ? 3 : 4;
75 }
76 if (digits < 1000000)
77 {
78 return (digits < 100000) ? 5 : 6;
79 }
80 return (digits < 10000000) ? 7 : 8;
81 }
82 if (digits >= 10000000000000000)
83 {
84 return 17;
85 }
86 if (digits >= 1000000000000000)
87 {
88 return 16;
89 }
90 if (digits >= 1000000000000)
91 {
92 return (digits >= 100000000000000) ? 15 : ((digits >= 10000000000000) ? 14 : 13);
93 }
94 if (digits >= 10000000000)
95 {
96 return (digits >= 100000000000) ? 12 : 11;
97 }
98 return (digits >= 1000000000) ? 10 : 9;
99 }
100
108 inline int writeDigits (char* buffer, uint64_t digits, int length) noexcept
109 {
110 uint32_t high = static_cast<uint32_t> (digits);
111 uint32_t low = 0;
112 if (digits >= 100000000)
113 {
114 high = static_cast<uint32_t> (digits / 100000000);
115 low = static_cast<uint32_t> (digits % 100000000);
116 }
117
118 char* const end = buffer + length;
119 char* cur = end;
120 int zeros = 0;
121 if (digits >= 100000000)
122 {
123 cur -= 8;
124 if (low == 0)
125 {
126 __builtin_memcpy (cur, "00000000", 8);
127 zeros = 8;
128 }
129 else
130 {
131 const uint32_t upper = low / 10000;
132 const uint32_t lower = low % 10000;
133 __builtin_memcpy (cur, &digitPairs[(upper / 100) * 2], 2);
134 __builtin_memcpy (cur + 2, &digitPairs[(upper % 100) * 2], 2);
135 __builtin_memcpy (cur + 4, &digitPairs[(lower / 100) * 2], 2);
136 __builtin_memcpy (cur + 6, &digitPairs[(lower % 100) * 2], 2);
137 zeros = (lower != 0) ? countTrailingZeros (lower) : 4 + countTrailingZeros (upper);
138 }
139 }
140
141 if (high >= 10000)
142 {
143 const uint32_t lower = high % 10000;
144 high /= 10000;
145 cur -= 4;
146 __builtin_memcpy (cur, &digitPairs[(lower / 100) * 2], 2);
147 __builtin_memcpy (cur + 2, &digitPairs[(lower % 100) * 2], 2);
148 if (zeros == end - cur - 4)
149 {
150 zeros += countTrailingZeros (lower);
151 }
152 }
153
154 while (high >= 100)
155 {
156 cur -= 2;
157 __builtin_memcpy (cur, &digitPairs[(high % 100) * 2], 2);
158 if (zeros == end - cur - 2)
159 {
160 zeros += pairZeros[high % 100];
161 }
162 high /= 100;
163 }
164
165 if (high >= 10)
166 {
167 cur -= 2;
168 __builtin_memcpy (cur, &digitPairs[high * 2], 2);
169 if (zeros == end - cur - 2)
170 {
171 zeros += pairZeros[high];
172 }
173 }
174 else
175 {
176 *--cur = static_cast<char> ('0' + high);
177 }
178
179 return zeros;
180 }
181 }
182}
183
184#endif
constexpr uint32_t pow10[]
powers of ten that fit in 32 bits.
Definition digits.hpp:36
int countDigits(uint64_t digits) noexcept
count the digits of a decimal significand.
Definition digits.hpp:64
int countTrailingZeros(uint32_t group) noexcept
count the trailing zeros of a four digits group.
Definition digits.hpp:54
int writeDigits(char *buffer, uint64_t digits, int length) noexcept
write the digits of a decimal significand.
Definition digits.hpp:108
constexpr char digitPairs[]
two digits decimal representations of 0 to 99.
Definition digits.hpp:39
constexpr uint8_t pairZeros[]
trailing zeros of the two digits decimal representations of 0 to 99.
Definition digits.hpp:44
Definition atod.hpp:47