join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
dtoa.hpp
Go to the documentation of this file.
1
25#ifndef __JOIN_DTOA_HPP__
26#define __JOIN_DTOA_HPP__
27
28// libjoin.
29#include <join/dtoapow.hpp>
30
31// C.
32#include <cstring>
33#include <cmath>
34
35namespace join
36{
37 namespace details
38 {
39 inline char* writeExponent (char* buffer, int k)
40 {
41 *buffer = '-';
42 buffer += (k < 0);
43 k = (k < 0) ? -k : k;
44 if (k >= 100)
45 {
46 *buffer++ = '0' + k / 100;
47 k %= 100;
48 *buffer++ = '0' + k / 10;
49 k %= 10;
50 }
51 else if (k >= 10)
52 {
53 *buffer++ = '0' + k / 10;
54 k %= 10;
55 }
56 *buffer++ = '0' + k;
57 return buffer;
58 }
59
60 inline char* prettify (char* buffer, int length, int k)
61 {
62 int kk = length + k;
63
64 if ((length <= kk) && (kk <= 21))
65 {
66 memset (buffer + length, '0', kk - length);
67 buffer[kk] = '.';
68 buffer[kk + 1] = '0';
69 return &buffer[kk + 2];
70 }
71 else if ((0 < kk) && (kk <= 21))
72 {
73 memmove (&buffer[kk + 1], &buffer[kk], length - kk);
74 buffer[kk] = '.';
75 return &buffer[length + 1];
76 }
77 else if ((-6 < kk) && (kk <= 0))
78 {
79 int offset = 2 - kk;
80 memmove (&buffer[offset], &buffer[0], length);
81 buffer[0] = '0';
82 buffer[1] = '.';
83 memset (&buffer[2], '0', offset - 2);
84 return &buffer[length + offset];
85 }
86 else if (length == 1)
87 {
88 buffer[1] = 'e';
89 return writeExponent (&buffer[2], kk - 1);
90 }
91 else
92 {
93 memmove (&buffer[2], &buffer[1], length - 1);
94 buffer[1] = '.';
95 buffer[length + 1] = 'e';
96 return writeExponent (&buffer[length + 2], kk - 1);
97 }
98 }
99
100 inline void grisuRound (char* buffer, int length, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w)
101 {
102 while (rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || wp_w - rest > rest + ten_kappa - wp_w))
103 {
104 --buffer[length - 1];
105 rest += ten_kappa;
106 }
107 }
108
109 inline size_t digitsCount (uint32_t n)
110 {
111 if (n < 10) return 1;
112 if (n < 100) return 2;
113 if (n < 1000) return 3;
114 if (n < 10000) return 4;
115 if (n < 100000) return 5;
116 if (n < 1000000) return 6;
117 if (n < 10000000) return 7;
118 if (n < 100000000) return 8;
119 if (n < 1000000000) return 9;
120 return 10;
121 }
122
123 inline void digitsGen (DiyFp W, DiyFp Mp, uint64_t delta, char* buffer, int& length, int& k)
124 {
125 static const uint32_t kPow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
126 DiyFp one (static_cast <uint64_t> (1) << -Mp._exponent, Mp._exponent);
127 DiyFp wp_w = Mp - W;
128 uint32_t p1 = static_cast <uint32_t> (Mp._mantissa >> -one._exponent);
129 uint64_t p2 = Mp._mantissa & (one._mantissa - 1);
130 int kappa = static_cast <int> (digitsCount (p1));
131 length = 0;
132
133 while (kappa > 0)
134 {
135 uint32_t d = 0;
136 switch (kappa)
137 {
138 case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
139 case 9: d = p1 / 100000000; p1 %= 100000000; break;
140 case 8: d = p1 / 10000000; p1 %= 10000000; break;
141 case 7: d = p1 / 1000000; p1 %= 1000000; break;
142 case 6: d = p1 / 100000; p1 %= 100000; break;
143 case 5: d = p1 / 10000; p1 %= 10000; break;
144 case 4: d = p1 / 1000; p1 %= 1000; break;
145 case 3: d = p1 / 100; p1 %= 100; break;
146 case 2: d = p1 / 10; p1 %= 10; break;
147 case 1: d = p1; p1 = 0; break;
148 default: break;
149 }
150 if (d || length)
151 {
152 buffer[length++] = '0' + d;
153 }
154 --kappa;
155 uint64_t tmp = (static_cast <uint64_t> (p1) << -one._exponent) + p2;
156 if (tmp <= delta)
157 {
158 k += kappa;
159 grisuRound (buffer, length, delta, tmp, static_cast <uint64_t> (kPow10[kappa]) << -one._exponent, wp_w._mantissa);
160 return;
161 }
162 }
163
164 uint64_t unit = 1;
165 for (;;)
166 {
167 p2 *= 10; delta *= 10; unit *= 10;
168 char d = static_cast <char> (p2 >> -one._exponent);
169 if (d || length)
170 {
171 buffer[length++] = '0' + d;
172 }
173 p2 &= one._mantissa - 1;
174 --kappa;
175 if (p2 < delta)
176 {
177 k += kappa;
178 grisuRound (buffer, length, delta, p2, one._mantissa, wp_w._mantissa * unit);
179 return;
180 }
181 }
182 }
183
184 inline int kComputation (int exp, int alpha)
185 {
186 return static_cast <int> (::ceil ((alpha - exp + 63) * 0.30102999566398114));
187 }
188
189 inline void grisu2 (char* buffer, int& length, int& k, double value)
190 {
191 DiyFp val (value), minus, plus;
192 val.normalizedBoundaries (minus, plus);
193
194 int mk = kComputation (plus._exponent + 64, -59);
195 const DiyFp& c_mk = dtoapow[mk + 343];
196
197 minus *= c_mk;
198 plus *= c_mk;
199
200 ++minus._mantissa;
201 --plus._mantissa;
202
203 k = -mk;
204
205 digitsGen (val.normalize () * c_mk, plus, plus._mantissa - minus._mantissa, buffer, length, k);
206 }
207 }
208
215 inline char* dtoa (char* buffer, double value)
216 {
217 uint64_t bits;
218 memcpy (&bits, &value, sizeof(double));
219 bool is_negative = (bits >> 63) != 0;
220
221 *buffer = '-';
222 buffer += is_negative;
223 value = is_negative ? -value : value;
224
225 if (value == 0.0)
226 {
227 memcpy (buffer, "0.0", 3);
228 return buffer + 3;
229 }
230
231 int length = 0, k = 0;
232 details::grisu2 (buffer, length, k, value);
233 return details::prettify (buffer, length, k);
234 }
235}
236
237#endif
hand made floating point.
Definition diyfp.hpp:42
int _exponent
exponent.
Definition diyfp.hpp:227
uint64_t _mantissa
mantissa.
Definition diyfp.hpp:224
constexpr void normalizedBoundaries(DiyFp &minus, DiyFp &plus) const noexcept
get normalized boundaries.
Definition diyfp.hpp:148
void digitsGen(DiyFp W, DiyFp Mp, uint64_t delta, char *buffer, int &length, int &k)
Definition dtoa.hpp:123
int kComputation(int exp, int alpha)
Definition dtoa.hpp:184
char * prettify(char *buffer, int length, int k)
Definition dtoa.hpp:60
size_t digitsCount(uint32_t n)
Definition dtoa.hpp:109
constexpr DiyFp dtoapow[]
Definition dtoapow.hpp:35
void grisuRound(char *buffer, int length, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w)
Definition dtoa.hpp:100
void grisu2(char *buffer, int &length, int &k, double value)
Definition dtoa.hpp:189
char * writeExponent(char *buffer, int k)
Definition dtoa.hpp:39
Definition acceptor.hpp:32
char * dtoa(char *buffer, double value)
double to string conversion.
Definition dtoa.hpp:215