| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_STORAGE_NUMBER_H |
| 4 | #define NETDATA_STORAGE_NUMBER_H 1 |
| 5 | |
| 6 | #include <math.h> |
| 7 | #include "../libnetdata.h" |
| 8 | |
| 9 | #ifdef NETDATA_WITH_LONG_DOUBLE |
| 10 | |
| 11 | typedef long double NETDATA_DOUBLE; |
| 12 | #define NETDATA_DOUBLE_FORMAT "%0.7Lf" |
| 13 | #define NETDATA_DOUBLE_FORMAT_ZERO "%0.0Lf" |
| 14 | #define NETDATA_DOUBLE_FORMAT_AUTO "%Lf" |
| 15 | #define NETDATA_DOUBLE_MODIFIER "Lf" |
| 16 | #define NETDATA_DOUBLE_FORMAT_G "%0.19Le" |
| 17 | |
| 18 | #define NETDATA_DOUBLE_MAX LDBL_MAX |
| 19 | |
| 20 | #define strtondd(s, endptr) strtold(s, endptr) |
| 21 | #define powndd(x, y) powl(x, y) |
| 22 | #define llrintndd(x) llrintl(x) |
| 23 | #define roundndd(x) roundl(x) |
| 24 | #define sqrtndd(x) sqrtl(x) |
| 25 | #define copysignndd(x, y) copysignl(x, y) |
| 26 | #define modfndd(x, y) modfl(x, y) |
| 27 | #define fabsndd(x) fabsl(x) |
| 28 | #define floorndd(x) floorl(x) |
| 29 | #define ceilndd(x) ceill(x) |
| 30 | #define log10ndd(x) log10l(x) |
| 31 | |
| 32 | #else // NETDATA_WITH_LONG_DOUBLE |
| 33 | |
| 34 | typedef double NETDATA_DOUBLE; |
| 35 | #define NETDATA_DOUBLE_FORMAT "%0.7f" |
| 36 | #define NETDATA_DOUBLE_FORMAT_ZERO "%0.0f" |
| 37 | #define NETDATA_DOUBLE_FORMAT_AUTO "%f" |
| 38 | #define NETDATA_DOUBLE_MODIFIER "f" |
| 39 | #define NETDATA_DOUBLE_FORMAT_G "%0.19e" |
| 40 | |
| 41 | #define NETDATA_DOUBLE_MAX DBL_MAX |
| 42 | |
| 43 | #define strtondd(s, endptr) strtod(s, endptr) |
| 44 | #define powndd(x, y) pow(x, y) |
| 45 | #define llrintndd(x) llrint(x) |
| 46 | #define roundndd(x) round(x) |
| 47 | #define sqrtndd(x) sqrt(x) |
| 48 | #define copysignndd(x, y) copysign(x, y) |
| 49 | #define modfndd(x, y) modf(x, y) |
| 50 | #define fabsndd(x) fabs(x) |
| 51 | #define floorndd(x) floor(x) |
| 52 | #define ceilndd(x) ceil(x) |
| 53 | #define log10ndd(x) log10(x) |
| 54 | |
| 55 | #endif // NETDATA_WITH_LONG_DOUBLE |
| 56 | |
| 57 | typedef long long collected_number; |
| 58 | #define COLLECTED_NUMBER_FORMAT "%lld" |
| 59 | |
| 60 | #define epsilonndd (NETDATA_DOUBLE)0.0000001 |
| 61 | #define considered_equal_ndd(a, b) (fabsndd((a) - (b)) < epsilonndd) |
| 62 | |
| 63 | #if defined(HAVE_ISFINITE) || defined(isfinite) |
| 64 | // The isfinite() macro shall determine whether its argument has a |
| 65 | // finite value (zero, subnormal, or normal, and not infinite or NaN). |
| 66 | #define netdata_double_isnumber(a) (isfinite(a)) |
| 67 | #elif defined(HAVE_FINITE) || defined(finite) |
| 68 | #define netdata_double_isnumber(a) (finite(a)) |
| 69 | #else |
| 70 | #define netdata_double_isnumber(a) (fpclassify(a) != FP_NAN && fpclassify(a) != FP_INFINITE) |
| 71 | #endif |
| 72 | |
| 73 | #define netdata_double_is_zero(a) (!netdata_double_isnumber(a) || considered_equal_ndd(a, 0.0)) |
| 74 | #define netdata_double_is_nonzero(a) (!netdata_double_is_zero(a)) |
| 75 | |
| 76 | typedef uint32_t storage_number; |
| 77 | |
| 78 | typedef struct storage_number_tier1 { |
| 79 | float sum_value; |
| 80 | float min_value; |
| 81 | float max_value; |
| 82 | uint16_t count; |
| 83 | uint16_t anomaly_count; |
| 84 | } storage_number_tier1_t; |
| 85 | |
| 86 | #define STORAGE_NUMBER_FORMAT "%u" |
| 87 | |
| 88 | typedef enum { |
| 89 | SN_FLAG_NONE = 0, |
| 90 | SN_FLAG_NOT_ANOMALOUS = (1 << 24), // the anomaly bit of the value (0:anomalous, 1:not anomalous) |
| 91 | SN_FLAG_RESET = (1 << 25), // the value has been overflown |
| 92 | SN_FLAG_NOT_EXISTS_MUL100 = (1 << 26), // very large value (multiplier is 100 instead of 10) |
| 93 | SN_FLAG_MULTIPLY = (1 << 30), // multiply, else divide |
| 94 | SN_FLAG_NEGATIVE = (1 << 31), // negative, else positive |
| 95 | } SN_FLAGS; |
| 96 | |
| 97 | #define SN_USER_FLAGS (SN_FLAG_NOT_ANOMALOUS | SN_FLAG_RESET) |
| 98 | |
| 99 | // default flags for all storage numbers |
| 100 | // anomaly bit is reversed, so we set it by default |
| 101 | #define SN_DEFAULT_FLAGS SN_FLAG_NOT_ANOMALOUS |
| 102 | |
| 103 | // When the calculated number is zero and the value is anomalous (ie. it's bit |
| 104 | // is zero) we want to return a storage_number representation that is |
| 105 | // different from the empty slot. We achieve this by mapping zero to |
| 106 | // SN_EXISTS_100. Unpacking the SN_EXISTS_100 value will return zero because |
| 107 | // its fraction field (as well as its exponent factor field) will be zero. |
| 108 | #define SN_EMPTY_SLOT SN_FLAG_NOT_EXISTS_MUL100 |
| 109 | |
| 110 | // checks |
| 111 | #define does_storage_number_exist(value) (((storage_number)(value)) != SN_EMPTY_SLOT) |
| 112 | #define did_storage_number_reset(value) ((((storage_number)(value)) & SN_FLAG_RESET)) |
| 113 | #define is_storage_number_anomalous(value) (does_storage_number_exist(value) && !(((storage_number)(value)) & SN_FLAG_NOT_ANOMALOUS)) |
| 114 | |
| 115 | storage_number pack_storage_number(NETDATA_DOUBLE value, SN_FLAGS flags) __attribute__((const)); |
| 116 | static inline NETDATA_DOUBLE unpack_storage_number(storage_number value) __attribute__((const)); |
| 117 | |
| 118 | // sign div/mul <--- multiplier / divider ---> 10/100 RESET EXISTS VALUE |
| 119 | #define STORAGE_NUMBER_POSITIVE_MAX_RAW (storage_number)( (0U << 31) | (1U << 30) | (1U << 29) | (1U << 28) | (1U << 27) | (1U << 26) | (0U << 25) | (1U << 24) | 0x00ffffff ) |
| 120 | #define STORAGE_NUMBER_POSITIVE_MIN_RAW (storage_number)( (0U << 31) | (0U << 30) | (1U << 29) | (1U << 28) | (1U << 27) | (0U << 26) | (0U << 25) | (1U << 24) | 0x00000001 ) |
| 121 | #define STORAGE_NUMBER_NEGATIVE_MAX_RAW (storage_number)( (1U << 31) | (0U << 30) | (1U << 29) | (1U << 28) | (1U << 27) | (0U << 26) | (0U << 25) | (1U << 24) | 0x00000001 ) |
| 122 | #define STORAGE_NUMBER_NEGATIVE_MIN_RAW (storage_number)( (1U << 31) | (1U << 30) | (1U << 29) | (1U << 28) | (1U << 27) | (1U << 26) | (0U << 25) | (1U << 24) | 0x00ffffff ) |
| 123 | |
| 124 | // accepted accuracy loss |
| 125 | #define ACCURACY_LOSS_ACCEPTED_PERCENT 0.0001 |
| 126 | #define accuracy_loss(t1, t2) (((t1) == (t2) || (t1) == 0.0 || (t2) == 0.0) ? 0.0 : (100.0 - (((t1) > (t2)) ? ((t2) * 100.0 / (t1) ) : ((t1) * 100.0 / (t2))))) |
| 127 | |
| 128 | // Maximum acceptable rate of increase for counters. With a rate of 10% netdata can safely detect overflows with a |
| 129 | // period of at least every other 10 samples. |
| 130 | #define MAX_INCREMENTAL_PERCENT_RATE 10 |
| 131 | |
| 132 | |
| 133 | ALWAYS_INLINE_HOT_FLATTEN |
| 134 | static NETDATA_DOUBLE unpack_storage_number(storage_number value) { |
| 135 | extern NETDATA_DOUBLE unpack_storage_number_lut10x[4 * 8]; |
| 136 | |
| 137 | if(unlikely(value == SN_EMPTY_SLOT)) |
| 138 | return NAN; |
| 139 | |
| 140 | int sign = 1, exp = 0; |
| 141 | int factor = 0; |
| 142 | |
| 143 | // bit 32 = 0:positive, 1:negative |
| 144 | if(unlikely(value & SN_FLAG_NEGATIVE)) |
| 145 | sign = -1; |
| 146 | |
| 147 | // bit 31 = 0:divide, 1:multiply |
| 148 | if(unlikely(value & SN_FLAG_MULTIPLY)) |
| 149 | exp = 1; |
| 150 | |
| 151 | // bit 27 SN_FLAG_NOT_EXISTS_MUL100 |
| 152 | if(unlikely(value & SN_FLAG_NOT_EXISTS_MUL100)) |
| 153 | factor = 1; |
| 154 | |
| 155 | // bit 26 SN_FLAG_RESET |
| 156 | // bit 25 SN_FLAG_NOT_ANOMALOUS |
| 157 | |
| 158 | // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total) |
| 159 | int mul = (int)((value & ((1U<<29)|(1U<<28)|(1U<<27))) >> 27); |
| 160 | |
| 161 | // bit 24 to bit 1 = the value, so remove all other bits |
| 162 | value ^= value & ((1U <<31)|(1U <<30)|(1U <<29)|(1U <<28)|(1U <<27)|(1U <<26)|(1U <<25)|(1U<<24)); |
| 163 | |
| 164 | NETDATA_DOUBLE n = value; |
| 165 | |
| 166 | // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, factor = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, factor, n); |
| 167 | |
| 168 | return sign * unpack_storage_number_lut10x[(factor * 16) + (exp * 8) + mul] * n; |
| 169 | } |
| 170 | |
| 171 | // all these prefixes should use characters that are not allowed in the numbers they represent |
| 172 | #define HEX_PREFIX "0x" // we check 2 characters when parsing |
| 173 | #define IEEE754_UINT64_B64_PREFIX "#" // we check the 1st character during parsing |
| 174 | #define IEEE754_DOUBLE_B64_PREFIX "@" // we check the 1st character during parsing |
| 175 | #define IEEE754_DOUBLE_HEX_PREFIX "%" // we check the 1st character during parsing |
| 176 | |
| 177 | bool is_system_ieee754_double(void); |
| 178 | |
| 179 | #endif /* NETDATA_STORAGE_NUMBER_H */ |