diff options
Diffstat (limited to 'examples/redis-unstable/deps/fpconv')
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/LICENSE.txt | 23 | ||||
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/Makefile | 27 | ||||
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/README.md | 9 | ||||
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/fpconv_dtoa.c | 373 | ||||
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/fpconv_dtoa.h | 45 | ||||
| -rw-r--r-- | examples/redis-unstable/deps/fpconv/fpconv_powers.h | 133 |
6 files changed, 610 insertions, 0 deletions
diff --git a/examples/redis-unstable/deps/fpconv/LICENSE.txt b/examples/redis-unstable/deps/fpconv/LICENSE.txt new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/LICENSE.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | Boost Software License - Version 1.0 - August 17th, 2003 | ||
| 2 | |||
| 3 | Permission is hereby granted, free of charge, to any person or organization | ||
| 4 | obtaining a copy of the software and accompanying documentation covered by | ||
| 5 | this license (the "Software") to use, reproduce, display, distribute, | ||
| 6 | execute, and transmit the Software, and to prepare derivative works of the | ||
| 7 | Software, and to permit third-parties to whom the Software is furnished to | ||
| 8 | do so, all subject to the following: | ||
| 9 | |||
| 10 | The copyright notices in the Software and this entire statement, including | ||
| 11 | the above license grant, this restriction and the following disclaimer, | ||
| 12 | must be included in all copies of the Software, in whole or in part, and | ||
| 13 | all derivative works of the Software, unless such copies or derivative | ||
| 14 | works are solely in the form of machine-executable object code generated by | ||
| 15 | a source language processor. | ||
| 16 | |||
| 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 23 | DEALINGS IN THE SOFTWARE. | ||
diff --git a/examples/redis-unstable/deps/fpconv/Makefile b/examples/redis-unstable/deps/fpconv/Makefile new file mode 100644 index 0000000..2654888 --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/Makefile | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | STD= | ||
| 2 | WARN= -Wall | ||
| 3 | OPT= -Os | ||
| 4 | |||
| 5 | R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) | ||
| 6 | R_LDFLAGS= $(LDFLAGS) | ||
| 7 | DEBUG= -g | ||
| 8 | |||
| 9 | R_CC=$(CC) $(R_CFLAGS) | ||
| 10 | R_LD=$(CC) $(R_LDFLAGS) | ||
| 11 | |||
| 12 | AR= ar | ||
| 13 | ARFLAGS= rcs | ||
| 14 | |||
| 15 | libfpconv.a: fpconv_dtoa.o | ||
| 16 | $(AR) $(ARFLAGS) $@ $+ | ||
| 17 | |||
| 18 | fpconv_dtoa.o: fpconv_dtoa.h fpconv_dtoa.c | ||
| 19 | |||
| 20 | .c.o: | ||
| 21 | $(R_CC) -c $< | ||
| 22 | |||
| 23 | clean: | ||
| 24 | rm -f *.o | ||
| 25 | rm -f *.a | ||
| 26 | |||
| 27 | |||
diff --git a/examples/redis-unstable/deps/fpconv/README.md b/examples/redis-unstable/deps/fpconv/README.md new file mode 100644 index 0000000..d64ca68 --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/README.md | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | libfpconv | ||
| 2 | |||
| 3 | ---------------------------------------------- | ||
| 4 | |||
| 5 | Fast and accurate double to string conversion based on Florian Loitsch's Grisu-algorithm[1]. | ||
| 6 | |||
| 7 | This port contains a subset of the 'C' version of Fast and accurate double to string conversion based on Florian Loitsch's Grisu-algorithm available at [github.com/night-shift/fpconv](https://github.com/night-shift/fpconv)). | ||
| 8 | |||
| 9 | [1] https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf | ||
diff --git a/examples/redis-unstable/deps/fpconv/fpconv_dtoa.c b/examples/redis-unstable/deps/fpconv/fpconv_dtoa.c new file mode 100644 index 0000000..ad2f2de --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/fpconv_dtoa.c | |||
| @@ -0,0 +1,373 @@ | |||
| 1 | /* fpconv_dtoa.c -- floating point conversion utilities. | ||
| 2 | * | ||
| 3 | * Fast and accurate double to string conversion based on Florian Loitsch's | ||
| 4 | * Grisu-algorithm[1]. | ||
| 5 | * | ||
| 6 | * [1] https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf | ||
| 7 | * ---------------------------------------------------------------------------- | ||
| 8 | * | ||
| 9 | * Copyright (c) 2013-2019, night-shift <as.smljk at gmail dot com> | ||
| 10 | * Copyright (c) 2009, Florian Loitsch < florian.loitsch at inria dot fr > | ||
| 11 | * All rights reserved. | ||
| 12 | * | ||
| 13 | * Boost Software License - Version 1.0 - August 17th, 2003 | ||
| 14 | * | ||
| 15 | * Permission is hereby granted, free of charge, to any person or organization | ||
| 16 | * obtaining a copy of the software and accompanying documentation covered by | ||
| 17 | * this license (the "Software") to use, reproduce, display, distribute, | ||
| 18 | * execute, and transmit the Software, and to prepare derivative works of the | ||
| 19 | * Software, and to permit third-parties to whom the Software is furnished to | ||
| 20 | * do so, all subject to the following: | ||
| 21 | * | ||
| 22 | * The copyright notices in the Software and this entire statement, including | ||
| 23 | * the above license grant, this restriction and the following disclaimer, | ||
| 24 | * must be included in all copies of the Software, in whole or in part, and | ||
| 25 | * all derivative works of the Software, unless such copies or derivative | ||
| 26 | * works are solely in the form of machine-executable object code generated by | ||
| 27 | * a source language processor. | ||
| 28 | * | ||
| 29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 31 | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| 32 | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| 33 | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| 34 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 35 | * DEALINGS IN THE SOFTWARE. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #include "fpconv_dtoa.h" | ||
| 39 | |||
| 40 | #include "fpconv_powers.h" | ||
| 41 | |||
| 42 | #include <stdbool.h> | ||
| 43 | #include <string.h> | ||
| 44 | |||
| 45 | #define fracmask 0x000FFFFFFFFFFFFFU | ||
| 46 | #define expmask 0x7FF0000000000000U | ||
| 47 | #define hiddenbit 0x0010000000000000U | ||
| 48 | #define signmask 0x8000000000000000U | ||
| 49 | #define expbias (1023 + 52) | ||
| 50 | |||
| 51 | #define absv(n) ((n) < 0 ? -(n) : (n)) | ||
| 52 | #define minv(a, b) ((a) < (b) ? (a) : (b)) | ||
| 53 | |||
| 54 | static uint64_t tens[] = { 10000000000000000000U, | ||
| 55 | 1000000000000000000U, | ||
| 56 | 100000000000000000U, | ||
| 57 | 10000000000000000U, | ||
| 58 | 1000000000000000U, | ||
| 59 | 100000000000000U, | ||
| 60 | 10000000000000U, | ||
| 61 | 1000000000000U, | ||
| 62 | 100000000000U, | ||
| 63 | 10000000000U, | ||
| 64 | 1000000000U, | ||
| 65 | 100000000U, | ||
| 66 | 10000000U, | ||
| 67 | 1000000U, | ||
| 68 | 100000U, | ||
| 69 | 10000U, | ||
| 70 | 1000U, | ||
| 71 | 100U, | ||
| 72 | 10U, | ||
| 73 | 1U }; | ||
| 74 | |||
| 75 | static inline uint64_t get_dbits(double d) { | ||
| 76 | union | ||
| 77 | { | ||
| 78 | double dbl; | ||
| 79 | uint64_t i; | ||
| 80 | } dbl_bits = { d }; | ||
| 81 | |||
| 82 | return dbl_bits.i; | ||
| 83 | } | ||
| 84 | |||
| 85 | static Fp build_fp(double d) { | ||
| 86 | uint64_t bits = get_dbits(d); | ||
| 87 | |||
| 88 | Fp fp; | ||
| 89 | fp.frac = bits & fracmask; | ||
| 90 | fp.exp = (bits & expmask) >> 52; | ||
| 91 | |||
| 92 | if (fp.exp) { | ||
| 93 | fp.frac += hiddenbit; | ||
| 94 | fp.exp -= expbias; | ||
| 95 | |||
| 96 | } else { | ||
| 97 | fp.exp = -expbias + 1; | ||
| 98 | } | ||
| 99 | |||
| 100 | return fp; | ||
| 101 | } | ||
| 102 | |||
| 103 | static void normalize(Fp *fp) { | ||
| 104 | while ((fp->frac & hiddenbit) == 0) { | ||
| 105 | fp->frac <<= 1; | ||
| 106 | fp->exp--; | ||
| 107 | } | ||
| 108 | |||
| 109 | int shift = 64 - 52 - 1; | ||
| 110 | fp->frac <<= shift; | ||
| 111 | fp->exp -= shift; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void get_normalized_boundaries(Fp *fp, Fp *lower, Fp *upper) { | ||
| 115 | upper->frac = (fp->frac << 1) + 1; | ||
| 116 | upper->exp = fp->exp - 1; | ||
| 117 | |||
| 118 | while ((upper->frac & (hiddenbit << 1)) == 0) { | ||
| 119 | upper->frac <<= 1; | ||
| 120 | upper->exp--; | ||
| 121 | } | ||
| 122 | |||
| 123 | int u_shift = 64 - 52 - 2; | ||
| 124 | |||
| 125 | upper->frac <<= u_shift; | ||
| 126 | upper->exp = upper->exp - u_shift; | ||
| 127 | |||
| 128 | int l_shift = fp->frac == hiddenbit ? 2 : 1; | ||
| 129 | |||
| 130 | lower->frac = (fp->frac << l_shift) - 1; | ||
| 131 | lower->exp = fp->exp - l_shift; | ||
| 132 | |||
| 133 | lower->frac <<= lower->exp - upper->exp; | ||
| 134 | lower->exp = upper->exp; | ||
| 135 | } | ||
| 136 | |||
| 137 | static Fp multiply(Fp *a, Fp *b) { | ||
| 138 | const uint64_t lomask = 0x00000000FFFFFFFF; | ||
| 139 | |||
| 140 | uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask); | ||
| 141 | uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32); | ||
| 142 | uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask); | ||
| 143 | uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32); | ||
| 144 | |||
| 145 | uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32); | ||
| 146 | /* round up */ | ||
| 147 | tmp += 1U << 31; | ||
| 148 | |||
| 149 | Fp fp = { ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32), a->exp + b->exp + 64 }; | ||
| 150 | |||
| 151 | return fp; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void round_digit(char *digits, | ||
| 155 | int ndigits, | ||
| 156 | uint64_t delta, | ||
| 157 | uint64_t rem, | ||
| 158 | uint64_t kappa, | ||
| 159 | uint64_t frac) { | ||
| 160 | while (rem < frac && delta - rem >= kappa && | ||
| 161 | (rem + kappa < frac || frac - rem > rem + kappa - frac)) { | ||
| 162 | digits[ndigits - 1]--; | ||
| 163 | rem += kappa; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int generate_digits(Fp *fp, Fp *upper, Fp *lower, char *digits, int *K) { | ||
| 168 | uint64_t wfrac = upper->frac - fp->frac; | ||
| 169 | uint64_t delta = upper->frac - lower->frac; | ||
| 170 | |||
| 171 | Fp one; | ||
| 172 | one.frac = 1ULL << -upper->exp; | ||
| 173 | one.exp = upper->exp; | ||
| 174 | |||
| 175 | uint64_t part1 = upper->frac >> -one.exp; | ||
| 176 | uint64_t part2 = upper->frac & (one.frac - 1); | ||
| 177 | |||
| 178 | int idx = 0, kappa = 10; | ||
| 179 | uint64_t *divp; | ||
| 180 | /* 1000000000 */ | ||
| 181 | for (divp = tens + 10; kappa > 0; divp++) { | ||
| 182 | uint64_t div = *divp; | ||
| 183 | unsigned digit = part1 / div; | ||
| 184 | |||
| 185 | if (digit || idx) { | ||
| 186 | digits[idx++] = digit + '0'; | ||
| 187 | } | ||
| 188 | |||
| 189 | part1 -= digit * div; | ||
| 190 | kappa--; | ||
| 191 | |||
| 192 | uint64_t tmp = (part1 << -one.exp) + part2; | ||
| 193 | if (tmp <= delta) { | ||
| 194 | *K += kappa; | ||
| 195 | round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac); | ||
| 196 | |||
| 197 | return idx; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /* 10 */ | ||
| 202 | uint64_t *unit = tens + 18; | ||
| 203 | |||
| 204 | while (true) { | ||
| 205 | part2 *= 10; | ||
| 206 | delta *= 10; | ||
| 207 | kappa--; | ||
| 208 | |||
| 209 | unsigned digit = part2 >> -one.exp; | ||
| 210 | if (digit || idx) { | ||
| 211 | digits[idx++] = digit + '0'; | ||
| 212 | } | ||
| 213 | |||
| 214 | part2 &= one.frac - 1; | ||
| 215 | if (part2 < delta) { | ||
| 216 | *K += kappa; | ||
| 217 | round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit); | ||
| 218 | |||
| 219 | return idx; | ||
| 220 | } | ||
| 221 | |||
| 222 | unit--; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | static int grisu2(double d, char *digits, int *K) { | ||
| 227 | Fp w = build_fp(d); | ||
| 228 | |||
| 229 | Fp lower, upper; | ||
| 230 | get_normalized_boundaries(&w, &lower, &upper); | ||
| 231 | |||
| 232 | normalize(&w); | ||
| 233 | |||
| 234 | int k; | ||
| 235 | Fp cp = find_cachedpow10(upper.exp, &k); | ||
| 236 | |||
| 237 | w = multiply(&w, &cp); | ||
| 238 | upper = multiply(&upper, &cp); | ||
| 239 | lower = multiply(&lower, &cp); | ||
| 240 | |||
| 241 | lower.frac++; | ||
| 242 | upper.frac--; | ||
| 243 | |||
| 244 | *K = -k; | ||
| 245 | |||
| 246 | return generate_digits(&w, &upper, &lower, digits, K); | ||
| 247 | } | ||
| 248 | |||
| 249 | static int emit_digits(char *digits, int ndigits, char *dest, int K, bool neg) { | ||
| 250 | int exp = absv(K + ndigits - 1); | ||
| 251 | |||
| 252 | /* write plain integer */ | ||
| 253 | if (K >= 0 && (exp < (ndigits + 7))) { | ||
| 254 | memcpy(dest, digits, ndigits); | ||
| 255 | memset(dest + ndigits, '0', K); | ||
| 256 | |||
| 257 | return ndigits + K; | ||
| 258 | } | ||
| 259 | |||
| 260 | /* write decimal w/o scientific notation */ | ||
| 261 | if (K < 0 && (K > -7 || exp < 4)) { | ||
| 262 | int offset = ndigits - absv(K); | ||
| 263 | /* fp < 1.0 -> write leading zero */ | ||
| 264 | if (offset <= 0) { | ||
| 265 | offset = -offset; | ||
| 266 | dest[0] = '0'; | ||
| 267 | dest[1] = '.'; | ||
| 268 | memset(dest + 2, '0', offset); | ||
| 269 | memcpy(dest + offset + 2, digits, ndigits); | ||
| 270 | |||
| 271 | return ndigits + 2 + offset; | ||
| 272 | |||
| 273 | /* fp > 1.0 */ | ||
| 274 | } else { | ||
| 275 | memcpy(dest, digits, offset); | ||
| 276 | dest[offset] = '.'; | ||
| 277 | memcpy(dest + offset + 1, digits + offset, ndigits - offset); | ||
| 278 | |||
| 279 | return ndigits + 1; | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | /* write decimal w/ scientific notation */ | ||
| 284 | ndigits = minv(ndigits, 18 - neg); | ||
| 285 | |||
| 286 | int idx = 0; | ||
| 287 | dest[idx++] = digits[0]; | ||
| 288 | |||
| 289 | if (ndigits > 1) { | ||
| 290 | dest[idx++] = '.'; | ||
| 291 | memcpy(dest + idx, digits + 1, ndigits - 1); | ||
| 292 | idx += ndigits - 1; | ||
| 293 | } | ||
| 294 | |||
| 295 | dest[idx++] = 'e'; | ||
| 296 | |||
| 297 | char sign = K + ndigits - 1 < 0 ? '-' : '+'; | ||
| 298 | dest[idx++] = sign; | ||
| 299 | |||
| 300 | int cent = 0; | ||
| 301 | |||
| 302 | if (exp > 99) { | ||
| 303 | cent = exp / 100; | ||
| 304 | dest[idx++] = cent + '0'; | ||
| 305 | exp -= cent * 100; | ||
| 306 | } | ||
| 307 | if (exp > 9) { | ||
| 308 | int dec = exp / 10; | ||
| 309 | dest[idx++] = dec + '0'; | ||
| 310 | exp -= dec * 10; | ||
| 311 | |||
| 312 | } else if (cent) { | ||
| 313 | dest[idx++] = '0'; | ||
| 314 | } | ||
| 315 | |||
| 316 | dest[idx++] = exp % 10 + '0'; | ||
| 317 | |||
| 318 | return idx; | ||
| 319 | } | ||
| 320 | |||
| 321 | static int filter_special(double fp, char *dest) { | ||
| 322 | if (fp == 0.0) { | ||
| 323 | dest[0] = '0'; | ||
| 324 | return 1; | ||
| 325 | } | ||
| 326 | |||
| 327 | uint64_t bits = get_dbits(fp); | ||
| 328 | |||
| 329 | bool nan = (bits & expmask) == expmask; | ||
| 330 | |||
| 331 | if (!nan) { | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (bits & fracmask) { | ||
| 336 | dest[0] = 'n'; | ||
| 337 | dest[1] = 'a'; | ||
| 338 | dest[2] = 'n'; | ||
| 339 | |||
| 340 | } else { | ||
| 341 | dest[0] = 'i'; | ||
| 342 | dest[1] = 'n'; | ||
| 343 | dest[2] = 'f'; | ||
| 344 | } | ||
| 345 | |||
| 346 | return 3; | ||
| 347 | } | ||
| 348 | |||
| 349 | int fpconv_dtoa(double d, char dest[24]) { | ||
| 350 | char digits[18]; | ||
| 351 | |||
| 352 | int str_len = 0; | ||
| 353 | bool neg = false; | ||
| 354 | |||
| 355 | if (get_dbits(d) & signmask) { | ||
| 356 | dest[0] = '-'; | ||
| 357 | str_len++; | ||
| 358 | neg = true; | ||
| 359 | } | ||
| 360 | |||
| 361 | int spec = filter_special(d, dest + str_len); | ||
| 362 | |||
| 363 | if (spec) { | ||
| 364 | return str_len + spec; | ||
| 365 | } | ||
| 366 | |||
| 367 | int K = 0; | ||
| 368 | int ndigits = grisu2(d, digits, &K); | ||
| 369 | |||
| 370 | str_len += emit_digits(digits, ndigits, dest + str_len, K, neg); | ||
| 371 | |||
| 372 | return str_len; | ||
| 373 | } | ||
diff --git a/examples/redis-unstable/deps/fpconv/fpconv_dtoa.h b/examples/redis-unstable/deps/fpconv/fpconv_dtoa.h new file mode 100644 index 0000000..328ed83 --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/fpconv_dtoa.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* fpconv_dtoa.h -- floating point conversion utilities. | ||
| 2 | * | ||
| 3 | * Fast and accurate double to string conversion based on Florian Loitsch's | ||
| 4 | * Grisu-algorithm[1]. | ||
| 5 | * | ||
| 6 | * [1] https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf | ||
| 7 | * ---------------------------------------------------------------------------- | ||
| 8 | * | ||
| 9 | * Copyright (c) 2013-2019, night-shift <as.smljk at gmail dot com> | ||
| 10 | * Copyright (c) 2009, Florian Loitsch < florian.loitsch at inria dot fr > | ||
| 11 | * All rights reserved. | ||
| 12 | * | ||
| 13 | * Boost Software License - Version 1.0 - August 17th, 2003 | ||
| 14 | * | ||
| 15 | * Permission is hereby granted, free of charge, to any person or organization | ||
| 16 | * obtaining a copy of the software and accompanying documentation covered by | ||
| 17 | * this license (the "Software") to use, reproduce, display, distribute, | ||
| 18 | * execute, and transmit the Software, and to prepare derivative works of the | ||
| 19 | * Software, and to permit third-parties to whom the Software is furnished to | ||
| 20 | * do so, all subject to the following: | ||
| 21 | * | ||
| 22 | * The copyright notices in the Software and this entire statement, including | ||
| 23 | * the above license grant, this restriction and the following disclaimer, | ||
| 24 | * must be included in all copies of the Software, in whole or in part, and | ||
| 25 | * all derivative works of the Software, unless such copies or derivative | ||
| 26 | * works are solely in the form of machine-executable object code generated by | ||
| 27 | * a source language processor. | ||
| 28 | * | ||
| 29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 31 | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| 32 | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| 33 | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| 34 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 35 | * DEALINGS IN THE SOFTWARE. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #ifndef FPCONV_DTOA_H | ||
| 39 | #define FPCONV_DTOA_H | ||
| 40 | |||
| 41 | int fpconv_dtoa(double fp, char dest[24]); | ||
| 42 | |||
| 43 | #endif | ||
| 44 | |||
| 45 | /* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */ | ||
diff --git a/examples/redis-unstable/deps/fpconv/fpconv_powers.h b/examples/redis-unstable/deps/fpconv/fpconv_powers.h new file mode 100644 index 0000000..bc488f6 --- /dev/null +++ b/examples/redis-unstable/deps/fpconv/fpconv_powers.h | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* fpconv_powers.h -- floating point conversion utilities. | ||
| 2 | * | ||
| 3 | * Fast and accurate double to string conversion based on Florian Loitsch's | ||
| 4 | * Grisu-algorithm[1]. | ||
| 5 | * | ||
| 6 | * [1] https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf | ||
| 7 | * ---------------------------------------------------------------------------- | ||
| 8 | * | ||
| 9 | * Copyright (c) 2021, Redis Labs | ||
| 10 | * Copyright (c) 2013-2019, night-shift <as.smljk at gmail dot com> | ||
| 11 | * Copyright (c) 2009, Florian Loitsch < florian.loitsch at inria dot fr > | ||
| 12 | * All rights reserved. | ||
| 13 | * | ||
| 14 | * Boost Software License - Version 1.0 - August 17th, 2003 | ||
| 15 | * | ||
| 16 | * Permission is hereby granted, free of charge, to any person or organization | ||
| 17 | * obtaining a copy of the software and accompanying documentation covered by | ||
| 18 | * this license (the "Software") to use, reproduce, display, distribute, | ||
| 19 | * execute, and transmit the Software, and to prepare derivative works of the | ||
| 20 | * Software, and to permit third-parties to whom the Software is furnished to | ||
| 21 | * do so, all subject to the following: | ||
| 22 | * | ||
| 23 | * The copyright notices in the Software and this entire statement, including | ||
| 24 | * the above license grant, this restriction and the following disclaimer, | ||
| 25 | * must be included in all copies of the Software, in whole or in part, and | ||
| 26 | * all derivative works of the Software, unless such copies or derivative | ||
| 27 | * works are solely in the form of machine-executable object code generated by | ||
| 28 | * a source language processor. | ||
| 29 | * | ||
| 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 31 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 32 | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| 33 | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| 34 | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| 35 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 36 | * DEALINGS IN THE SOFTWARE. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #include <stdint.h> | ||
| 40 | |||
| 41 | #define npowers 87 | ||
| 42 | #define steppowers 8 | ||
| 43 | #define firstpower -348 /* 10 ^ -348 */ | ||
| 44 | |||
| 45 | #define expmax -32 | ||
| 46 | #define expmin -60 | ||
| 47 | |||
| 48 | |||
| 49 | typedef struct Fp { | ||
| 50 | uint64_t frac; | ||
| 51 | int exp; | ||
| 52 | } Fp; | ||
| 53 | |||
| 54 | static Fp powers_ten[] = { | ||
| 55 | { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 }, | ||
| 56 | { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 }, | ||
| 57 | { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 }, | ||
| 58 | { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 }, | ||
| 59 | { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 }, | ||
| 60 | { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 }, | ||
| 61 | { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 }, | ||
| 62 | { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 }, | ||
| 63 | { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 }, | ||
| 64 | { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 }, | ||
| 65 | { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 }, | ||
| 66 | { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 }, | ||
| 67 | { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 }, | ||
| 68 | { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 }, | ||
| 69 | { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 }, | ||
| 70 | { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 }, | ||
| 71 | { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 }, | ||
| 72 | { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 }, | ||
| 73 | { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 }, | ||
| 74 | { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 }, | ||
| 75 | { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 }, | ||
| 76 | { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 }, | ||
| 77 | { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 }, | ||
| 78 | { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 }, | ||
| 79 | { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 }, | ||
| 80 | { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 }, | ||
| 81 | { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 }, | ||
| 82 | { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 }, | ||
| 83 | { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 }, | ||
| 84 | { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 }, | ||
| 85 | { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 }, | ||
| 86 | { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 }, | ||
| 87 | { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 }, | ||
| 88 | { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 }, | ||
| 89 | { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 }, | ||
| 90 | { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 }, | ||
| 91 | { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 }, | ||
| 92 | { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 }, | ||
| 93 | { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 }, | ||
| 94 | { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 }, | ||
| 95 | { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 }, | ||
| 96 | { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 }, | ||
| 97 | { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 }, | ||
| 98 | { 12648080533535911531U, 1066 } | ||
| 99 | }; | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Grisu needs a cache of precomputed powers-of-ten. | ||
| 103 | * This function, given an exponent and an integer k | ||
| 104 | * return the normalized floating-point approximation of the power of 10. | ||
| 105 | * @param exp | ||
| 106 | * @param k | ||
| 107 | * @return | ||
| 108 | */ | ||
| 109 | static Fp find_cachedpow10(int exp, int* k) | ||
| 110 | { | ||
| 111 | const double one_log_ten = 0.30102999566398114; | ||
| 112 | |||
| 113 | const int approx = -(exp + npowers) * one_log_ten; | ||
| 114 | int idx = (approx - firstpower) / steppowers; | ||
| 115 | |||
| 116 | while(1) { | ||
| 117 | int current = exp + powers_ten[idx].exp + 64; | ||
| 118 | |||
| 119 | if(current < expmin) { | ||
| 120 | idx++; | ||
| 121 | continue; | ||
| 122 | } | ||
| 123 | |||
| 124 | if(current > expmax) { | ||
| 125 | idx--; | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | |||
| 129 | *k = (firstpower + idx * steppowers); | ||
| 130 | |||
| 131 | return powers_ten[idx]; | ||
| 132 | } | ||
| 133 | } | ||
