dconv 2.0
C++14 library for printing and parsing floating point numbers
Loading...
Searching...
No Matches
grisu.hpp
Go to the documentation of this file.
1
25#ifndef __DCONV_GRISU_HPP__
26#define __DCONV_GRISU_HPP__
27
28// dconv.
29#include <dconv/grisupow.hpp>
30#include <dconv/format.hpp>
31
32// C.
33#include <cassert>
34#include <cstring>
35#include <cstdint>
36
37namespace dconv
38{
39 namespace grisu
40 {
41 namespace details
42 {
50 inline char* dtoa (char* buffer, double value,
51 void (*generate) (char*, int&, int&, double) noexcept) noexcept
52 {
53 uint64_t bits;
54 memcpy (&bits, &value, sizeof (double));
55 bool is_negative = (bits >> 63) != 0;
56
57 *buffer = '-';
58 buffer += is_negative;
59 value = is_negative ? -value : value;
60
61 if (value == 0.0)
62 {
63 memcpy (buffer, "0.0", 3);
64 return buffer + 3;
65 }
66
67 int length = 0, k = 0;
68 generate (buffer, length, k, value);
69 return dconv::details::prettify (buffer, length, k);
70 }
71 }
72
79 inline const DiyFp& cachedPower (int exponent, int& k) noexcept
80 {
81 const int expr = -59 - (exponent + 64) + 63;
82 const int mk = (expr * 30103 + 99999) / 100000;
83
84 assert (mk + 343 >= 0 && mk + 343 < 687);
85 k = -mk;
86 return dconv::details::grisupow[mk + 343];
87 }
88
96 inline void generate (char* buffer, int& length, int& k, double value) noexcept
97 {
98 DiyFp w (value);
99 w.normalize ();
100 w *= cachedPower (w._exponent, k);
101
102 const DiyFp one (static_cast<uint64_t> (1) << -w._exponent, w._exponent);
103 uint32_t part1 = static_cast<uint32_t> (w._mantissa >> -one._exponent);
104 uint64_t part2 = w._mantissa & (one._mantissa - 1);
105
106 length = 0;
107 for (int kappa = dconv::details::countDigits (part1); kappa > 0; --kappa)
108 {
109 buffer[length++] = static_cast<char> ('0' + part1 / dconv::details::pow10[kappa - 1]);
110 part1 %= dconv::details::pow10[kappa - 1];
111 }
112
113 while ((length < 18) && (part2 != 0))
114 {
115 part2 *= 10;
116 buffer[length++] = static_cast<char> ('0' + (part2 >> -one._exponent));
117 part2 &= one._mantissa - 1;
118 --k;
119 }
120 }
121
128 inline char* dtoa (char* buffer, double value) noexcept
129 {
130 return details::dtoa (buffer, value, generate);
131 }
132 }
133}
134
135#endif
hand made floating point.
Definition diyfp.hpp:41
constexpr DiyFp & normalize() noexcept
normalize floating point.
Definition diyfp.hpp:104
uint64_t _mantissa
mantissa.
Definition diyfp.hpp:223
int _exponent
exponent.
Definition diyfp.hpp:226
constexpr uint32_t pow10[]
powers of ten that fit in 32 bits.
Definition digits.hpp:36
char * prettify(char *buffer, int length, int k) noexcept
lay out decimal digits as a fixed or scientific number.
Definition format.hpp:76
int countDigits(uint64_t digits) noexcept
count the digits of a decimal significand.
Definition digits.hpp:64
constexpr DiyFp grisupow[]
cached powers of ten for the grisu algorithms.
Definition grisupow.hpp:36
char * dtoa(char *buffer, double value, void(*generate)(char *, int &, int &, double) noexcept) noexcept
double to string conversion with the given digits generator.
Definition grisu.hpp:50
const DiyFp & cachedPower(int exponent, int &k) noexcept
get the cached power of ten that scales a binary exponent into the digit generation range.
Definition grisu.hpp:79
void generate(char *buffer, int &length, int &k, double value) noexcept
write the decimal digits of the scaled value.
Definition grisu.hpp:96
char * dtoa(char *buffer, double value) noexcept
double to string conversion using Grisu.
Definition grisu.hpp:128
Definition atod.hpp:47