@cryptotaxi247 / netdata-1 / commits / ef8994dc6

internal number printing now has 7 digits fractional resolution; fixes #2573

Costa Tsaousis (ktsaou) committed Aug 9, 2017 at 17:38 UTC ef8994dc69e34b7c6ac60b2c324d8b400e527899
5 files changed +99 -18
src/storage_number.c
+65 -11
@@ -2,12 +2,13 @@
2
3 extern char *print_number_lu_r(char *str, unsigned long uvalue);
4 extern char *print_number_llu_r(char *str, unsigned long long uvalue);
5 +extern char *print_number_llu_r_smart(char *str, unsigned long long uvalue);
6
7 storage_number pack_storage_number(calculated_number value, uint32_t flags)
8 {
9 // bit 32 = sign 0:positive, 1:negative
10 // bit 31 = 0:divide, 1:multiply
10 - // bit 30, 29, 28 = (multiplier or divider) 0-6 (7 total)
11 + // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
12 // bit 27, 26, 25 flags
13 // bit 24 to bit 1 = the value
14
@@ -105,6 +106,7 @@ calculated_number unpack_storage_number(storage_number value)
106 return n;
107 }
108
109 +/*
110 int print_calculated_number(char *str, calculated_number value)
111 {
112 char *wstr = str;
@@ -113,21 +115,14 @@ int print_calculated_number(char *str, calculated_number value)
115 if(sign) value = -value;
116
117 #ifdef STORAGE_WITH_MATH
116 - // without llrint() there are rounding problems
118 + // without llrintl() there are rounding problems
119 // for example 0.9 becomes 0.89
118 - unsigned long long uvalue = (unsigned long long int) llrint(value * (calculated_number)100000);
120 + unsigned long long uvalue = (unsigned long long int) llrintl(value * (calculated_number)100000);
121 #else
122 unsigned long long uvalue = value * (calculated_number)100000;
123 #endif
124
123 -#ifdef ENVIRONMENT32
124 - if(uvalue > (unsigned long long)0xffffffff)
125 - wstr = print_number_llu_r(str, uvalue);
126 - else
127 - wstr = print_number_lu_r(str, uvalue);
128 -#else
129 - do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
130 -#endif
125 + wstr = print_number_llu_r_smart(str, uvalue);
126
127 // make sure we have 6 bytes at least
128 while((wstr - str) < 6) *wstr++ = '0';
@@ -166,3 +161,62 @@ int print_calculated_number(char *str, calculated_number value)
161 // return the buffer length
162 return (int) ((wstr - str) + 2 + decimal );
163 }
164 +*/
165 +
166 +int print_calculated_number(char *str, calculated_number value) {
167 + char integral_str[50], fractional_str[50];
168 +
169 + char *wstr = str;
170 +
171 + if(unlikely(value < 0)) {
172 + *wstr++ = '-';
173 + value = -value;
174 + }
175 +
176 + calculated_number integral, fractional;
177 +
178 +#ifdef STORAGE_WITH_MATH
179 + fractional = modfl(value, &integral) * 10000000.0;
180 +#else
181 + fractional = ((unsigned long long)(value * 10000000ULL) % 10000000ULL);
182 +#endif
183 +
184 + char *istre;
185 + if(integral == 0.0) {
186 + integral_str[0] = '0';
187 + istre = &integral_str[1];
188 + }
189 + else
190 + // convert the integral part to string (reversed)
191 + istre = print_number_llu_r_smart(integral_str, (unsigned long long)integral);
192 +
193 + // copy reversed the integral string
194 + istre--;
195 + while( istre >= integral_str ) *wstr++ = *istre--;
196 +
197 + if(fractional != 0.0) {
198 + // add a dot
199 + *wstr++ = '.';
200 +
201 + // convert the fractional part to string (reversed)
202 + char *fstre = print_number_llu_r_smart(fractional_str, (unsigned long long)llrintl(fractional));
203 +
204 + // prepend zeros to reach 7 digits length
205 + int decimal = 7;
206 + int len = (int)(fstre - fractional_str);
207 + while(len < decimal) {
208 + *wstr++ = '0';
209 + len++;
210 + }
211 +
212 + char *begin = fractional_str;
213 + while(*begin == '0' && begin < fstre) begin++;
214 +
215 + // copy reversed the fractional string
216 + fstre--;
217 + while( fstre >= begin ) *wstr++ = *fstre--;
218 + }
219 +
220 + *wstr = '\0';
221 + return (int)(wstr - str);
222 +}
src/storage_number.h
+2 -2
@@ -41,8 +41,8 @@ calculated_number unpack_storage_number(storage_number value);
41 int print_calculated_number(char *str, calculated_number value);
42
43 #define STORAGE_NUMBER_POSITIVE_MAX 167772150000000.0
44 -#define STORAGE_NUMBER_POSITIVE_MIN 0.00001
45 -#define STORAGE_NUMBER_NEGATIVE_MAX -0.00001
44 +#define STORAGE_NUMBER_POSITIVE_MIN 0.0000001
45 +#define STORAGE_NUMBER_NEGATIVE_MAX -0.0000001
46 #define STORAGE_NUMBER_NEGATIVE_MIN -167772150000000.0
47
48 // accepted accuracy loss
src/unit_test.c
+18 -5
@@ -31,8 +31,8 @@ int check_storage_number(calculated_number n, int debug) {
31 CALCULATED_NUMBER_FORMAT " re-parsed from printed (diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n\n",
32 n,
33 d, s, ddiff, dcdiff,
34 - buffer,
35 - len, p, pdiff, pcdiff
34 + buffer, len,
35 + p, pdiff, pcdiff
36 );
37 if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
38 if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, dcdiff);
@@ -45,6 +45,19 @@ int check_storage_number(calculated_number n, int debug) {
45 return 0;
46 }
47
48 +calculated_number storage_number_min(calculated_number n) {
49 + calculated_number r = 1, last;
50 +
51 + do {
52 + last = n;
53 + n /= 2.0;
54 + storage_number t = pack_storage_number(n, SN_EXISTS);
55 + r = unpack_storage_number(t);
56 + } while(r != 0.0 && r != last);
57 +
58 + return last;
59 +}
60 +
61 void benchmark_storage_number(int loop, int multiplier) {
62 int i, j;
63 calculated_number n, d;
@@ -73,10 +86,10 @@ void benchmark_storage_number(int loop, int multiplier) {
86 }
87
88 fprintf(stderr, "\nNETDATA FLOATING POINT\n");
76 - fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MIN);
89 + fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", storage_number_min(1));
90 fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
91 fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
79 - fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MAX);
92 + fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", -storage_number_min(1));
93 fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
94
95 // ------------------------------------------------------------------------
@@ -231,7 +244,7 @@ int unit_test_storage()
244
245 int unit_test_str2ld() {
246 char *values[] = {
234 - "1.234567", "-35.6", "0.00123", "23842384234234.2", ".1", "1.2e-10",
247 + "1.2345678", "-35.6", "0.00123", "23842384234234.2", ".1", "1.2e-10",
248 "hello", "1wrong", "nan", "inf", NULL
249 };
250
src/web_buffer.c
+13
@@ -84,6 +84,19 @@ inline char *print_number_llu_r(char *str, unsigned long long uvalue) {
84 return wstr;
85 }
86
87 +inline char *print_number_llu_r_smart(char *str, unsigned long long uvalue) {
88 +#ifdef ENVIRONMENT32
89 + if(uvalue > (unsigned long long)0xffffffff)
90 + str = print_number_llu_r(str, uvalue);
91 + else
92 + str = print_number_lu_r(str, uvalue);
93 +#else
94 + do *str++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
95 +#endif
96 +
97 + return str;
98 +}
99 +
100 void buffer_print_llu(BUFFER *wb, unsigned long long uvalue)
101 {
102 buffer_need_bytes(wb, 50);
src/web_buffer.h
+1
@@ -71,6 +71,7 @@ extern void buffer_char_replace(BUFFER *wb, char from, char to);
71
72 extern char *print_number_lu_r(char *str, unsigned long uvalue);
73 extern char *print_number_llu_r(char *str, unsigned long long uvalue);
74 +extern char *print_number_llu_r_smart(char *str, unsigned long long uvalue);
75
76 extern void buffer_print_llu(BUFFER *wb, unsigned long long uvalue);
77