| 13188 | } |
| 13189 | |
| 13190 | inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, |
| 13191 | std::uint64_t rest, std::uint64_t ten_k) |
| 13192 | { |
| 13193 | assert(len >= 1); |
| 13194 | assert(dist <= delta); |
| 13195 | assert(rest <= delta); |
| 13196 | assert(ten_k > 0); |
| 13197 | |
| 13198 | // <--------------------------- delta ----> |
| 13199 | // <---- dist ---------> |
| 13200 | // --------------[------------------+-------------------]-------------- |
| 13201 | // M- w M+ |
| 13202 | // |
| 13203 | // ten_k |
| 13204 | // <------> |
| 13205 | // <---- rest ----> |
| 13206 | // --------------[------------------+----+--------------]-------------- |
| 13207 | // w V |
| 13208 | // = buf * 10^k |
| 13209 | // |
| 13210 | // ten_k represents a unit-in-the-last-place in the decimal representation |
| 13211 | // stored in buf. |
| 13212 | // Decrement buf by ten_k while this takes buf closer to w. |
| 13213 | |
| 13214 | // The tests are written in this order to avoid overflow in unsigned |
| 13215 | // integer arithmetic. |
| 13216 | |
| 13217 | while (rest < dist |
| 13218 | and delta - rest >= ten_k |
| 13219 | and (rest + ten_k < dist or dist - rest > rest + ten_k - dist)) |
| 13220 | { |
| 13221 | assert(buf[len - 1] != '0'); |
| 13222 | buf[len - 1]--; |
| 13223 | rest += ten_k; |
| 13224 | } |
| 13225 | } |
| 13226 | |
| 13227 | /*! |
| 13228 | Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. |