diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-05-08 16:27:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-05-08 16:27:04 +0000 |
commit | a836a244a3d2bdd4da1ee2641e3e957850668cea (patch) | |
tree | cb87c75b3677fab7144f868435243f864048a1e6 /libnetdata/storage_number | |
parent | Adding upstream version 1.38.1. (diff) | |
download | netdata-a836a244a3d2bdd4da1ee2641e3e957850668cea.tar.xz netdata-a836a244a3d2bdd4da1ee2641e3e957850668cea.zip |
Adding upstream version 1.39.0.upstream/1.39.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libnetdata/storage_number')
-rw-r--r-- | libnetdata/storage_number/README.md | 2 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.c | 142 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.h | 90 |
3 files changed, 91 insertions, 143 deletions
diff --git a/libnetdata/storage_number/README.md b/libnetdata/storage_number/README.md index da2c3ccf..2dd6df6c 100644 --- a/libnetdata/storage_number/README.md +++ b/libnetdata/storage_number/README.md @@ -4,7 +4,7 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/libnetdata/stora sidebar_label: "Storage number" learn_status: "Published" learn_topic_type: "Tasks" -learn_rel_path: "Developers/libnetdata libraries" +learn_rel_path: "Developers/libnetdata" --> # Netdata storage number diff --git a/libnetdata/storage_number/storage_number.c b/libnetdata/storage_number/storage_number.c index 7511f3a7..ebae71d8 100644 --- a/libnetdata/storage_number/storage_number.c +++ b/libnetdata/storage_number/storage_number.c @@ -2,6 +2,78 @@ #include "../libnetdata.h" +bool is_system_ieee754_double(void) { + static bool logged = false; + + struct { + NETDATA_DOUBLE original; + + union { + uint64_t i; + NETDATA_DOUBLE d; + }; + } tests[] = { + { .original = 1.25, .i = 0x3FF4000000000000 }, + { .original = 1.0, .i = 0x3FF0000000000000 }, + { .original = 2.0, .i = 0x4000000000000000 }, + { .original = 4.0, .i = 0x4010000000000000 }, + { .original = 8.8, .i = 0x402199999999999A }, + { .original = 16.16, .i = 0x403028F5C28F5C29 }, + { .original = 32.32, .i = 0x404028F5C28F5C29 }, + { .original = 64.64, .i = 0x405028F5C28F5C29 }, + { .original = 128.128, .i = 0x406004189374BC6A }, + { .original = 32768.32768, .i = 0x40E0000A7C5AC472 }, + { .original = 65536.65536, .i = 0x40F0000A7C5AC472 }, + { .original = -65536.65536, .i = 0xC0F0000A7C5AC472 }, + { .original = 65535.65535, .i = 0x40EFFFF4F8A0902E }, + { .original = -65535.65535, .i = 0xC0EFFFF4F8A0902E }, + { .original = 4.503599627e15, .i = 0x432FFFFFFFF4B180 }, + { .original = -4.503599627e15, .i = 0xC32FFFFFFFF4B180 }, + { .original = 1.25e25, .i = 0x4524ADF4B7320335 }, + { .original = 1.25e307, .i = 0x7FB1CCF385EBC8A0 }, + { .original = 1.25e-25, .i = 0x3AC357C299A88EA7 }, + { .original = 1.25e-100, .i = 0x2B317F7D4ED8C33E }, + { .original = NAN, .i = 0x7FF8000000000000 }, + { .original = -INFINITY, .i = 0xFFF0000000000000 }, + { .original = INFINITY, .i = 0x7FF0000000000000 }, + { .original = 1.25e-132, .i = 0x248C6463225AB7EC }, + { .original = 0.0, .i = 0x0000000000000000 }, + { .original = -0.0, .i = 0x8000000000000000 }, + { .original = DBL_MIN, .i = 0x0010000000000000 }, + { .original = DBL_MAX, .i = 0x7FEFFFFFFFFFFFFF }, + { .original = -DBL_MIN, .i = 0x8010000000000000 }, + { .original = -DBL_MAX, .i = 0xFFEFFFFFFFFFFFFF }, + }; + + size_t errors = 0; + size_t elements = sizeof(tests) / sizeof(tests[0]); + for(size_t i = 0; i < elements ; i++) { + uint64_t *ptr = (uint64_t *)&tests[i].original; + + if(*ptr != tests[i].i && (tests[i].original == tests[i].d || (isnan(tests[i].original) && isnan(tests[i].d)))) { + if(!logged) + info("IEEE754: test #%zu, value " NETDATA_DOUBLE_FORMAT_G " is represented in this system as %lX, but it was expected as %lX", + i+1, tests[i].original, *ptr, tests[i].i); + errors++; + } + } + + if(!errors && sizeof(NETDATA_DOUBLE) == sizeof(uint64_t)) { + if(!logged) + info("IEEE754: system is using IEEE754 DOUBLE PRECISION values"); + + logged = true; + return true; + } + else { + if(!logged) + info("IEEE754: system is NOT compatible with IEEE754 DOUBLE PRECISION values"); + + logged = true; + return false; + } +} + storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) { // bit 32 = sign 0:positive, 1:negative // bit 31 = 0:divide, 1:multiply @@ -159,73 +231,3 @@ int print_netdata_double(char *str, NETDATA_DOUBLE value) return (int) ((wstr - str) + 2 + decimal ); } */ - -int print_netdata_double(char *str, NETDATA_DOUBLE value) { - // info("printing number " NETDATA_DOUBLE_FORMAT, value); - char integral_str[50], fractional_str[50]; - - char *wstr = str; - - if(unlikely(value < 0)) { - *wstr++ = '-'; - value = -value; - } - - NETDATA_DOUBLE integral, fractional; - -#ifdef STORAGE_WITH_MATH - fractional = modfndd(value, &integral) * 10000000.0; -#else - integral = (NETDATA_DOUBLE)((unsigned long long)(value * 10000000ULL) / 10000000ULL); - fractional = (NETDATA_DOUBLE)((unsigned long long)(value * 10000000ULL) % 10000000ULL); -#endif - - unsigned long long integral_int = (unsigned long long)integral; - unsigned long long fractional_int = (unsigned long long)llrintndd(fractional); - if(unlikely(fractional_int >= 10000000)) { - integral_int += 1; - fractional_int -= 10000000; - } - - // info("integral " NETDATA_DOUBLE_FORMAT " (%llu), fractional " NETDATA_DOUBLE_FORMAT " (%llu)", integral, integral_int, fractional, fractional_int); - - char *istre; - if(unlikely(integral_int == 0)) { - integral_str[0] = '0'; - istre = &integral_str[1]; - } - else - // convert the integral part to string (reversed) - istre = print_number_llu_r_smart(integral_str, integral_int); - - // copy reversed the integral string - istre--; - while( istre >= integral_str ) *wstr++ = *istre--; - - if(likely(fractional_int != 0)) { - // add a dot - *wstr++ = '.'; - - // convert the fractional part to string (reversed) - char *fstre = print_number_llu_r_smart(fractional_str, fractional_int); - - // prepend zeros to reach 7 digits length - int decimal = 7; - int len = (int)(fstre - fractional_str); - while(len < decimal) { - *wstr++ = '0'; - len++; - } - - char *begin = fractional_str; - while(begin < fstre && *begin == '0') begin++; - - // copy reversed the fractional string - fstre--; - while( fstre >= begin ) *wstr++ = *fstre--; - } - - *wstr = '\0'; - // info("printed number '%s'", str); - return (int)(wstr - str); -} diff --git a/libnetdata/storage_number/storage_number.h b/libnetdata/storage_number/storage_number.h index faea4775..82c870d6 100644 --- a/libnetdata/storage_number/storage_number.h +++ b/libnetdata/storage_number/storage_number.h @@ -13,6 +13,7 @@ typedef long double NETDATA_DOUBLE; #define NETDATA_DOUBLE_FORMAT_ZERO "%0.0Lf" #define NETDATA_DOUBLE_FORMAT_AUTO "%Lf" #define NETDATA_DOUBLE_MODIFIER "Lf" +#define NETDATA_DOUBLE_FORMAT_G "%0.19Le" #define NETDATA_DOUBLE_MAX LDBL_MAX @@ -24,6 +25,9 @@ typedef long double NETDATA_DOUBLE; #define copysignndd(x, y) copysignl(x, y) #define modfndd(x, y) modfl(x, y) #define fabsndd(x) fabsl(x) +#define floorndd(x) floorl(x) +#define ceilndd(x) ceill(x) +#define log10ndd(x) log10l(x) #else // NETDATA_WITH_LONG_DOUBLE @@ -32,6 +36,7 @@ typedef double NETDATA_DOUBLE; #define NETDATA_DOUBLE_FORMAT_ZERO "%0.0f" #define NETDATA_DOUBLE_FORMAT_AUTO "%f" #define NETDATA_DOUBLE_MODIFIER "f" +#define NETDATA_DOUBLE_FORMAT_G "%0.19e" #define NETDATA_DOUBLE_MAX DBL_MAX @@ -43,6 +48,9 @@ typedef double NETDATA_DOUBLE; #define copysignndd(x, y) copysign(x, y) #define modfndd(x, y) modf(x, y) #define fabsndd(x) fabs(x) +#define floorndd(x) floor(x) +#define ceilndd(x) ceil(x) +#define log10ndd(x) log10(x) #endif // NETDATA_WITH_LONG_DOUBLE @@ -62,6 +70,9 @@ typedef long long collected_number; #define netdata_double_isnumber(a) (fpclassify(a) != FP_NAN && fpclassify(a) != FP_INFINITE) #endif +#define netdata_double_is_zero(a) (!netdata_double_isnumber(a) || considered_equal_ndd(a, 0.0)) +#define netdata_double_is_nonzero(a) (!netdata_double_is_zero(a)) + typedef uint32_t storage_number; typedef struct storage_number_tier1 { @@ -104,8 +115,6 @@ typedef enum { storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) __attribute__((const)); static inline NETDATA_DOUBLE unpack_storage_number(storage_number value) __attribute__((const)); -int print_netdata_double(char *str, NETDATA_DOUBLE value); - // sign div/mul <--- multiplier / divider ---> 10/100 RESET EXISTS VALUE #define STORAGE_NUMBER_POSITIVE_MAX_RAW (storage_number)( (0 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff ) #define STORAGE_NUMBER_POSITIVE_MIN_RAW (storage_number)( (0 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 ) @@ -158,75 +167,12 @@ static inline NETDATA_DOUBLE unpack_storage_number(storage_number value) { return sign * unpack_storage_number_lut10x[(factor * 16) + (exp * 8) + mul] * n; } -static inline NETDATA_DOUBLE str2ndd(const char *s, char **endptr) { - int negative = 0; - const char *start = s; - unsigned long long integer_part = 0; - unsigned long decimal_part = 0; - size_t decimal_digits = 0; - - switch(*s) { - case '-': - s++; - negative = 1; - break; - - case '+': - s++; - break; - - case 'n': - if(s[1] == 'a' && s[2] == 'n') { - if(endptr) *endptr = (char *)&s[3]; - return NAN; - } - break; - - case 'i': - if(s[1] == 'n' && s[2] == 'f') { - if(endptr) *endptr = (char *)&s[3]; - return INFINITY; - } - break; - - default: - break; - } - - while (*s >= '0' && *s <= '9') { - integer_part = (integer_part * 10) + (*s - '0'); - s++; - } - - if(unlikely(*s == '.')) { - decimal_part = 0; - s++; - - while (*s >= '0' && *s <= '9') { - decimal_part = (decimal_part * 10) + (*s - '0'); - s++; - decimal_digits++; - } - } - - if(unlikely(*s == 'e' || *s == 'E')) - return strtondd(start, endptr); - - if(unlikely(endptr)) - *endptr = (char *)s; - - if(unlikely(negative)) { - if(unlikely(decimal_digits)) - return -((NETDATA_DOUBLE)integer_part + (NETDATA_DOUBLE)decimal_part / powndd(10.0, decimal_digits)); - else - return -((NETDATA_DOUBLE)integer_part); - } - else { - if(unlikely(decimal_digits)) - return (NETDATA_DOUBLE)integer_part + (NETDATA_DOUBLE)decimal_part / powndd(10.0, decimal_digits); - else - return (NETDATA_DOUBLE)integer_part; - } -} +// all these prefixes should use characters that are not allowed in the numbers they represent +#define HEX_PREFIX "0x" // we check 2 characters when parsing +#define IEEE754_UINT64_B64_PREFIX "#" // we check the 1st character during parsing +#define IEEE754_DOUBLE_B64_PREFIX "@" // we check the 1st character during parsing +#define IEEE754_DOUBLE_HEX_PREFIX "%" // we check the 1st character during parsing + +bool is_system_ieee754_double(void); #endif /* NETDATA_STORAGE_NUMBER_H */ |