mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
478ada3bf4
When sprintf is called with a precision larger than the double's significand width (e.g. "%.51g"), fixed_width() indexed pow10 tables out of bounds and produced a negative shift exponent. Cap the internal digit count to 18 in the %g branch, matching the existing %e and %f branches; downstream loops already zero-pad to the caller's precision so visible output is unchanged. Co-authored-by: Claude <noreply@anthropic.com>
1515 lines
52 KiB
C
1515 lines
52 KiB
C
/*
|
|
** fp_uscale.c - Unrounded Scaling float conversion
|
|
**
|
|
** Unified float formatting and parsing using the uscale algorithm.
|
|
** Based on Russ Cox's "Unrounded Scaling" approach.
|
|
** See https://research.swtch.com/fp
|
|
**
|
|
** Replaces fmt_fp.c (formatting) and readfloat.c (parsing).
|
|
*/
|
|
|
|
#include <mruby.h>
|
|
|
|
#ifndef MRB_NO_FLOAT
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
|
|
/* ======== Platform support ======== */
|
|
|
|
#if defined(__SIZEOF_INT128__)
|
|
static inline void mul64(uint64_t a, uint64_t b, uint64_t *hi, uint64_t *lo)
|
|
{
|
|
__uint128_t r = (__uint128_t)a * b;
|
|
*hi = (uint64_t)(r >> 64);
|
|
*lo = (uint64_t)r;
|
|
}
|
|
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
#include <intrin.h>
|
|
static inline void mul64(uint64_t a, uint64_t b, uint64_t *hi, uint64_t *lo)
|
|
{
|
|
*lo = _umul128(a, b, hi);
|
|
}
|
|
#else
|
|
static inline void mul64(uint64_t a, uint64_t b, uint64_t *hi, uint64_t *lo)
|
|
{
|
|
uint64_t a_lo = (uint32_t)a, a_hi = a >> 32;
|
|
uint64_t b_lo = (uint32_t)b, b_hi = b >> 32;
|
|
uint64_t p0 = a_lo * b_lo;
|
|
uint64_t p1 = a_lo * b_hi;
|
|
uint64_t p2 = a_hi * b_lo;
|
|
uint64_t p3 = a_hi * b_hi;
|
|
uint64_t mid = (p0 >> 32) + (uint32_t)p1 + (uint32_t)p2;
|
|
*lo = (p0 & 0xFFFFFFFFULL) | (mid << 32);
|
|
*hi = p3 + (p1 >> 32) + (p2 >> 32) + (mid >> 32);
|
|
}
|
|
#endif
|
|
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define clz64(x) __builtin_clzll(x)
|
|
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
static inline int clz64(uint64_t x)
|
|
{
|
|
unsigned long idx;
|
|
_BitScanReverse64(&idx, x);
|
|
return 63 - (int)idx;
|
|
}
|
|
#else
|
|
static inline int clz64(uint64_t x)
|
|
{
|
|
int n = 0;
|
|
if (x <= 0x00000000FFFFFFFFULL) { n += 32; x <<= 32; }
|
|
if (x <= 0x0000FFFFFFFFFFFFULL) { n += 16; x <<= 16; }
|
|
if (x <= 0x00FFFFFFFFFFFFFFULL) { n += 8; x <<= 8; }
|
|
if (x <= 0x0FFFFFFFFFFFFFFFULL) { n += 4; x <<= 4; }
|
|
if (x <= 0x3FFFFFFFFFFFFFFFULL) { n += 2; x <<= 2; }
|
|
if (x <= 0x7FFFFFFFFFFFFFFFULL) { n += 1; }
|
|
return n;
|
|
}
|
|
#endif
|
|
|
|
#define bits_len64(x) (64 - clz64(x))
|
|
|
|
/* ======== pow10 table ======== */
|
|
|
|
typedef struct {
|
|
uint64_t hi;
|
|
uint64_t lo;
|
|
} pow10_entry;
|
|
|
|
#define POW10_MIN (-343)
|
|
#define POW10_MAX 341
|
|
#define POW10_TAB_SIZE (POW10_MAX - POW10_MIN + 1)
|
|
|
|
/* generated by tools/gen_pow10_tab.rb */
|
|
static const pow10_entry pow10_tab[POW10_TAB_SIZE] = {
|
|
{0xbf29dcaba82fdeafULL, 0x8bcd1178c77f03ccULL},
|
|
{0xeef453d6923bd65bULL, 0xeec055d6f95ec4c0ULL},
|
|
{0x9558b4661b6565f9ULL, 0xb53835a65bdb3af8ULL},
|
|
{0xbaaee17fa23ebf77ULL, 0xa286430ff2d209b6ULL},
|
|
{0xe95a99df8ace6f54ULL, 0x0b27d3d3ef868c23ULL},
|
|
{0x91d8a02bb6c10595ULL, 0x86f8e46475b41796ULL},
|
|
{0xb64ec836a47146faULL, 0x68b71d7d93211d7bULL},
|
|
{0xe3e27a444d8d98b8ULL, 0x02e4e4dcf7e964daULL},
|
|
{0x8e6d8c6ab0787f73ULL, 0x01cf0f0a1af1df08ULL},
|
|
{0xb208ef855c969f50ULL, 0x4242d2cca1ae56caULL},
|
|
{0xde8b2b66b3bc4724ULL, 0x52d3877fca19ec7dULL},
|
|
{0x8b16fb203055ac77ULL, 0xb3c434afde5033ceULL},
|
|
{0xaddcb9e83c6b1794ULL, 0x20b541dbd5e440c2ULL},
|
|
{0xd953e8624b85dd79ULL, 0x28e29252cb5d50f2ULL},
|
|
{0x87d4713d6f33aa6cULL, 0x798d9b73bf1a5297ULL},
|
|
{0xa9c98d8ccb009507ULL, 0x97f10250aee0e73dULL},
|
|
{0xd43bf0effdc0ba49ULL, 0xfded42e4da99210dULL},
|
|
{0x84a57695fe98746eULL, 0xfeb449cf089fb4a8ULL},
|
|
{0xa5ced43b7e3e9189ULL, 0xbe615c42cac7a1d2ULL},
|
|
{0xcf42894a5dce35ebULL, 0xadf9b3537d798a46ULL},
|
|
{0x818995ce7aa0e1b3ULL, 0x8cbc10142e6bf66cULL},
|
|
{0xa1ebfb4219491a20ULL, 0xefeb14193a06f407ULL},
|
|
{0xca66fa129f9b60a7ULL, 0x2be5d91f8888b109ULL},
|
|
{0xfd00b897478238d1ULL, 0x76df4f676aaadd4bULL},
|
|
{0x9e20735e8cb16383ULL, 0xaa4b91a0a2aaca4fULL},
|
|
{0xc5a890362fddbc63ULL, 0x14de7608cb557ce2ULL},
|
|
{0xf712b443bbd52b7cULL, 0x5a16138afe2adc1bULL},
|
|
{0x9a6bb0aa55653b2eULL, 0xb84dcc36dedac991ULL},
|
|
{0xc1069cd4eabe89f9ULL, 0x66613f4496917bf5ULL},
|
|
{0xf148440a256e2c77ULL, 0x3ff98f15bc35daf2ULL},
|
|
{0x96cd2a865764dbcbULL, 0xc7fbf96d95a1a8d7ULL},
|
|
{0xbc807527ed3e12bdULL, 0x39faf7c8fb0a130dULL},
|
|
{0xeba09271e88d976cULL, 0x0879b5bb39cc97d1ULL},
|
|
{0x93445b8731587ea4ULL, 0x854c1195041fdee2ULL},
|
|
{0xb8157268fdae9e4dULL, 0xa69f15fa4527d69bULL},
|
|
{0xe61acf033d1a45e0ULL, 0x9046db78d671cc42ULL},
|
|
{0x8fd0c16206306bacULL, 0x5a2c492b86071fa9ULL},
|
|
{0xb3c4f1ba87bc8697ULL, 0x70b75b766788e793ULL},
|
|
{0xe0b62e2929aba83dULL, 0xcce53254016b2178ULL},
|
|
{0x8c71dcd9ba0b4926ULL, 0x600f3f7480e2f4ebULL},
|
|
{0xaf8e5410288e1b70ULL, 0xf8130f51a11bb226ULL},
|
|
{0xdb71e91432b1a24bULL, 0x3617d32609629eafULL},
|
|
{0x892731ac9faf056fULL, 0x41cee3f7c5dda32dULL},
|
|
{0xab70fe17c79ac6cbULL, 0x92429cf5b7550bf9ULL},
|
|
{0xd64d3d9db981787eULL, 0xf6d34433252a4ef7ULL},
|
|
{0x85f0468293f0eb4fULL, 0xda440a9ff73a715aULL},
|
|
{0xa76c582338ed2622ULL, 0x50d50d47f5090db1ULL},
|
|
{0xd1476e2c07286fabULL, 0xe50a5099f24b511eULL},
|
|
{0x82cca4db847945cbULL, 0xaf267260376f12b2ULL},
|
|
{0xa37fce126597973dULL, 0x1af00ef8454ad75fULL},
|
|
{0xcc5fc196fefd7d0dULL, 0xe1ac12b6569d8d37ULL},
|
|
{0xff77b1fcbebcdc50ULL, 0xda171763ec44f085ULL},
|
|
{0x9faacf3df73609b2ULL, 0x884e6e9e73ab1653ULL},
|
|
{0xc795830d75038c1eULL, 0x2a620a461095dbe8ULL},
|
|
{0xf97ae3d0d2446f26ULL, 0xb4fa8cd794bb52e2ULL},
|
|
{0x9becce62836ac578ULL, 0xb11c9806bcf513cdULL},
|
|
{0xc2e801fb244576d6ULL, 0xdd63be086c3258c0ULL},
|
|
{0xf3a20279ed56d48bULL, 0x94bcad8a873eeef0ULL},
|
|
{0x9845418c345644d7ULL, 0x7cf5ec7694875556ULL},
|
|
{0xbe5691ef416bd60dULL, 0xdc33679439a92aacULL},
|
|
{0xedec366b11c6cb90ULL, 0xd340417948137557ULL},
|
|
{0x94b3a202eb1c3f3aULL, 0x840828ebcd0c2956ULL},
|
|
{0xb9e08a83a5e34f08ULL, 0x250a3326c04f33acULL},
|
|
{0xe858ad248f5c22caULL, 0x2e4cbff070630097ULL},
|
|
{0x91376c36d99995bfULL, 0xdceff7f6463de05eULL},
|
|
{0xb58547448ffffb2eULL, 0x542bf5f3d7cd5875ULL},
|
|
{0xe2e69915b3fff9faULL, 0xe936f370cdc0ae93ULL},
|
|
{0x8dd01fad907ffc3cULL, 0x51c2582680986d1cULL},
|
|
{0xb1442798f49ffb4bULL, 0x6632ee3020be8863ULL},
|
|
{0xdd95317f31c7fa1eULL, 0xbfbfa9bc28ee2a7cULL},
|
|
{0x8a7d3eef7f1cfc53ULL, 0xb7d7ca159994da8dULL},
|
|
{0xad1c8eab5ee43b67ULL, 0x25cdbc9afffa1130ULL},
|
|
{0xd863b256369d4a41ULL, 0x6f412bc1bff8957dULL},
|
|
{0x873e4f75e2224e69ULL, 0xa588bb5917fb5d6eULL},
|
|
{0xa90de3535aaae203ULL, 0x8eeaea2f5dfa34c9ULL},
|
|
{0xd3515c2831559a84ULL, 0xf2a5a4bb3578c1fcULL},
|
|
{0x8412d9991ed58092ULL, 0x17a786f5016b793dULL},
|
|
{0xa5178fff668ae0b7ULL, 0x9d9168b241c6578dULL},
|
|
{0xce5d73ff402d98e4ULL, 0x04f5c2ded237ed70ULL},
|
|
{0x80fa687f881c7f8fULL, 0x831999cb4362f466ULL},
|
|
{0xa139029f6a239f73ULL, 0xe3e0003e143bb17fULL},
|
|
{0xc987434744ac874fULL, 0x5cd8004d994a9ddfULL},
|
|
{0xfbe9141915d7a923ULL, 0xb40e0060ff9d4557ULL},
|
|
{0x9d71ac8fada6c9b6ULL, 0x9088c03c9fc24b56ULL},
|
|
{0xc4ce17b399107c23ULL, 0x34aaf04bc7b2de2cULL},
|
|
{0xf6019da07f549b2cULL, 0x81d5ac5eb99f95b7ULL},
|
|
{0x99c102844f94e0fcULL, 0xd1258bbb3403bd92ULL},
|
|
{0xc0314325637a193aULL, 0x056eeeaa0104acf7ULL},
|
|
{0xf03d93eebc589f89ULL, 0x86caaa548145d835ULL},
|
|
{0x96267c7535b763b6ULL, 0xb43eaa74d0cba721ULL},
|
|
{0xbbb01b9283253ca3ULL, 0x614e551204fe90e9ULL},
|
|
{0xea9c227723ee8bccULL, 0xb9a1ea56863e3523ULL},
|
|
{0x92a1958a76751760ULL, 0xf405327613e6e136ULL},
|
|
{0xb749faed14125d37ULL, 0x31067f1398e09984ULL},
|
|
{0xe51c79a85916f485ULL, 0x7d481ed87f18bfe5ULL},
|
|
{0x8f31cc0937ae58d3ULL, 0x2e4d13474f6f77efULL},
|
|
{0xb2fe3f0b8599ef08ULL, 0x79e05819234b55eaULL},
|
|
{0xdfbdcece67006acaULL, 0x98586e1f6c1e2b65ULL},
|
|
{0x8bd6a141006042beULL, 0x1f3744d3a392db1fULL},
|
|
{0xaecc49914078536eULL, 0xa70516088c7791e7ULL},
|
|
{0xda7f5bf590966849ULL, 0x50c65b8aaf957661ULL},
|
|
{0x888f99797a5e012eULL, 0x927bf936adbd69fcULL},
|
|
{0xaab37fd7d8f58179ULL, 0x371af784592cc47cULL},
|
|
{0xd5605fcdcf32e1d7ULL, 0x04e1b5656f77f59bULL},
|
|
{0x855c3be0a17fcd27ULL, 0xa30d115f65aaf980ULL},
|
|
{0xa6b34ad8c9dfc070ULL, 0x0bd055b73f15b7e1ULL},
|
|
{0xd0601d8efc57b08cULL, 0x0ec46b250edb25d9ULL},
|
|
{0x823c12795db6ce58ULL, 0x893ac2f72948f7a7ULL},
|
|
{0xa2cb1717b52481eeULL, 0xab8973b4f39b3591ULL},
|
|
{0xcb7ddcdda26da269ULL, 0x566bd0a2308202f6ULL},
|
|
{0xfe5d54150b090b03ULL, 0x2c06c4cabca283b3ULL},
|
|
{0x9efa548d26e5a6e2ULL, 0x3b843afeb5e59250ULL},
|
|
{0xc6b8e9b0709f109bULL, 0xca6549be635ef6e4ULL},
|
|
{0xf867241c8cc6d4c1ULL, 0x3cfe9c2dfc36b49dULL},
|
|
{0x9b407691d7fc44f9ULL, 0x861f219cbda230e2ULL},
|
|
{0xc21094364dfb5637ULL, 0x67a6ea03ed0abd1bULL},
|
|
{0xf294b943e17a2bc5ULL, 0xc190a484e84d6c62ULL},
|
|
{0x979cf3ca6cec5b5bULL, 0x58fa66d3113063bdULL},
|
|
{0xbd8430bd08277232ULL, 0xaf390087d57c7cacULL},
|
|
{0xece53cec4a314ebeULL, 0x5b0740a9cadb9bd7ULL},
|
|
{0x940f4613ae5ed137ULL, 0x78e4886a1ec94166ULL},
|
|
{0xb913179899f68585ULL, 0xd71daa84a67b91c0ULL},
|
|
{0xe757dd7ec07426e6ULL, 0xcce51525d01a7630ULL},
|
|
{0x9096ea6f38489850ULL, 0xc00f2d37a21089deULL},
|
|
{0xb4bca50b065abe64ULL, 0xf012f8858a94ac56ULL},
|
|
{0xe1ebce4dc7f16dfcULL, 0x2c17b6a6ed39d76bULL},
|
|
{0x8d3360f09cf6e4beULL, 0x9b8ed228544426a3ULL},
|
|
{0xb080392cc4349dedULL, 0x427286b26955304cULL},
|
|
{0xdca04777f541c568ULL, 0x130f285f03aa7c5fULL},
|
|
{0x89e42caaf9491b61ULL, 0x0be9793b624a8dbbULL},
|
|
{0xac5d37d5b79b623aULL, 0xcee3d78a3add312aULL},
|
|
{0xd77485cb25823ac8ULL, 0x829ccd6cc9947d74ULL},
|
|
{0x86a8d39ef77164bdULL, 0x51a20063fdfcce68ULL},
|
|
{0xa8530886b54dbdecULL, 0x260a807cfd7c0203ULL},
|
|
{0xd267caa862a12d67ULL, 0x2f8d209c3cdb0284ULL},
|
|
{0x8380dea93da4bc61ULL, 0xbdb83461a608e192ULL},
|
|
{0xa46116538d0deb79ULL, 0xad26417a0f8b19f7ULL},
|
|
{0xcd795be870516657ULL, 0x986fd1d8936de074ULL},
|
|
{0x806bd9714632dff7ULL, 0xff45e3275c24ac49ULL},
|
|
{0xa086cfcd97bf97f4ULL, 0x7f175bf1332dd75bULL},
|
|
{0xc8a883c0fdaf7df1ULL, 0x9edd32ed7ff94d32ULL},
|
|
{0xfad2a4b13d1b5d6dULL, 0x86947fa8dff7a07eULL},
|
|
{0x9cc3a6eec6311a64ULL, 0x341ccfc98bfac44fULL},
|
|
{0xc3f490aa77bd60fdULL, 0x412403bbeef97563ULL},
|
|
{0xf4f1b4d515acb93cULL, 0x116d04aaeab7d2bbULL},
|
|
{0x991711052d8bf3c6ULL, 0x8ae422ead2b2e3b5ULL},
|
|
{0xbf5cd54678eef0b7ULL, 0x2d9d2ba5875f9ca2ULL},
|
|
{0xef340a98172aace5ULL, 0x7904768ee93783cbULL},
|
|
{0x9580869f0e7aac0fULL, 0x2ba2ca1951c2b25fULL},
|
|
{0xbae0a846d2195713ULL, 0x768b7c9fa6335ef6ULL},
|
|
{0xe998d258869facd8ULL, 0xd42e5bc78fc036b4ULL},
|
|
{0x91ff83775423cc07ULL, 0x849cf95cb9d82230ULL},
|
|
{0xb67f6455292cbf09ULL, 0xe5c437b3e84e2abdULL},
|
|
{0xe41f3d6a7377eecbULL, 0xdf3545a0e261b56cULL},
|
|
{0x8e938662882af53fULL, 0xab814b848d7d1163ULL},
|
|
{0xb23867fb2a35b28eULL, 0x16619e65b0dc55bcULL},
|
|
{0xdec681f9f4c31f32ULL, 0x9bfa05ff1d136b2bULL},
|
|
{0x8b3c113c38f9f37fULL, 0x217c43bf722c22fbULL},
|
|
{0xae0b158b4738705fULL, 0x69db54af4eb72bbaULL},
|
|
{0xd98ddaee19068c77ULL, 0xc45229db2264f6a8ULL},
|
|
{0x87f8a8d4cfa417caULL, 0x1ab35a28f57f1a29ULL},
|
|
{0xa9f6d30a038d1dbdULL, 0xa16030b332dee0b3ULL},
|
|
{0xd47487cc8470652cULL, 0x89b83cdfff9698e0ULL},
|
|
{0x84c8d4dfd2c63f3cULL, 0xd613260bffbe1f8cULL},
|
|
{0xa5fb0a17c777cf0aULL, 0x0b97ef8effada76fULL},
|
|
{0xcf79cc9db955c2cdULL, 0x8e7deb72bf99114bULL},
|
|
{0x81ac1fe293d599c0ULL, 0x390eb327b7bfaacfULL},
|
|
{0xa21727db38cb0030ULL, 0x47525ff1a5af9583ULL},
|
|
{0xca9cf1d206fdc03cULL, 0x5926f7ee0f1b7ae3ULL},
|
|
{0xfd442e4688bd304bULL, 0x6f70b5e992e2599cULL},
|
|
{0x9e4a9cec15763e2fULL, 0x65a671b1fbcd7801ULL},
|
|
{0xc5dd44271ad3cdbbULL, 0xbf100e1e7ac0d602ULL},
|
|
{0xf7549530e188c129ULL, 0x2ed411a619710b83ULL},
|
|
{0x9a94dd3e8cf578baULL, 0x7d448b07cfe6a731ULL},
|
|
{0xc13a148e3032d6e8ULL, 0x1c95adc9c3e050feULL},
|
|
{0xf18899b1bc3f8ca2ULL, 0x23bb193c34d8653eULL},
|
|
{0x96f5600f15a7b7e6ULL, 0xd654efc5a1073f46ULL},
|
|
{0xbcb2b812db11a5dfULL, 0x8bea2bb709490f18ULL},
|
|
{0xebdf661791d60f57ULL, 0xeee4b6a4cb9b52deULL},
|
|
{0x936b9fcebb25c996ULL, 0x354ef226ff4113cbULL},
|
|
{0xb84687c269ef3bfcULL, 0xc2a2aeb0bf1158bdULL},
|
|
{0xe65829b3046b0afbULL, 0xf34b5a5ceed5aeedULL},
|
|
{0x8ff71a0fe2c2e6ddULL, 0xb80f187a15458d54ULL},
|
|
{0xb3f4e093db73a094ULL, 0xa612de989a96f0a9ULL},
|
|
{0xe0f218b8d25088b9ULL, 0xcf97963ec13cacd3ULL},
|
|
{0x8c974f7383725574ULL, 0xe1bebde738c5ec04ULL},
|
|
{0xafbd2350644eead0ULL, 0x1a2e6d6106f76705ULL},
|
|
{0xdbac6c247d62a584ULL, 0x20ba08b948b540c6ULL},
|
|
{0x894bc396ce5da773ULL, 0x94744573cd71487cULL},
|
|
{0xab9eb47c81f51150ULL, 0xf99156d0c0cd9a9bULL},
|
|
{0xd686619ba27255a3ULL, 0x37f5ac84f1010142ULL},
|
|
{0x8613fd0145877586ULL, 0x42f98bd316a0a0c9ULL},
|
|
{0xa798fc4196e952e8ULL, 0xd3b7eec7dc48c8fbULL},
|
|
{0xd17f3b51fca3a7a1ULL, 0x08a5ea79d35afb3aULL},
|
|
{0x82ef85133de648c5ULL, 0x6567b28c2418dd04ULL},
|
|
{0xa3ab66580d5fdaf6ULL, 0x3ec19f2f2d1f1445ULL},
|
|
{0xcc963fee10b7d1b4ULL, 0xce7206faf866d957ULL},
|
|
{0xffbbcfe994e5c620ULL, 0x020e88b9b6808fadULL},
|
|
{0x9fd561f1fd0f9bd4ULL, 0x01491574121059ccULL},
|
|
{0xc7caba6e7c5382c9ULL, 0x019b5ad11694703fULL},
|
|
{0xf9bd690a1b68637cULL, 0xc20231855c398c4fULL},
|
|
{0x9c1661a651213e2eULL, 0xf9415ef359a3f7b1ULL},
|
|
{0xc31bfa0fe5698db9ULL, 0xb791b6b0300cf59dULL},
|
|
{0xf3e2f893dec3f127ULL, 0xa576245c3c103305ULL},
|
|
{0x986ddb5c6b3a76b8ULL, 0x0769d6b9a58a1fe3ULL},
|
|
{0xbe89523386091466ULL, 0x09444c680eeca7dcULL},
|
|
{0xee2ba6c0678b5980ULL, 0x8b955f8212a7d1d3ULL},
|
|
{0x94db483840b717f0ULL, 0x573d5bb14ba8e323ULL},
|
|
{0xba121a4650e4ddecULL, 0x6d0cb29d9e931becULL},
|
|
{0xe896a0d7e51e1567ULL, 0x884fdf450637e2e8ULL},
|
|
{0x915e2486ef32cd61ULL, 0xf531eb8b23e2edd1ULL},
|
|
{0xb5b5ada8aaff80b9ULL, 0xf27e666decdba945ULL},
|
|
{0xe3231912d5bf60e7ULL, 0xef1e000968129396ULL},
|
|
{0x8df5efabc5979c90ULL, 0x3572c005e10b9c3eULL},
|
|
{0xb1736b96b6fd83b4ULL, 0x42cf7007594e834dULL},
|
|
{0xddd0467c64bce4a1ULL, 0x53834c092fa22421ULL},
|
|
{0x8aa22c0dbef60ee5ULL, 0x94320f85bdc55694ULL},
|
|
{0xad4ab7112eb3929eULL, 0x793e93672d36ac39ULL},
|
|
{0xd89d64d57a607745ULL, 0x178e3840f8845748ULL},
|
|
{0x87625f056c7c4a8cULL, 0xeeb8e3289b52b68dULL},
|
|
{0xa93af6c6c79b5d2eULL, 0x2a671bf2c2276430ULL},
|
|
{0xd389b4787982347aULL, 0xb500e2ef72b13d3cULL},
|
|
{0x843610cb4bf160ccULL, 0x31208dd5a7aec645ULL},
|
|
{0xa54394fe1eedb8ffULL, 0x3d68b14b119a77d7ULL},
|
|
{0xce947a3da6a9273fULL, 0x8cc2dd9dd60115cdULL},
|
|
{0x811ccc668829b888ULL, 0xf7f9ca82a5c0ada0ULL},
|
|
{0xa163ff802a3426a9ULL, 0x35f83d234f30d908ULL},
|
|
{0xc9bcff6034c13053ULL, 0x03764c6c22fd0f4aULL},
|
|
{0xfc2c3f3841f17c68ULL, 0x4453df872bbc531dULL},
|
|
{0x9d9ba7832936edc1ULL, 0x2ab46bb47b55b3f2ULL},
|
|
{0xc5029163f384a932ULL, 0xf56186a19a2b20eeULL},
|
|
{0xf64335bcf065d37eULL, 0xb2b9e84a00b5e92aULL},
|
|
{0x99ea0196163fa42fULL, 0xafb4312e4071b1baULL},
|
|
{0xc06481fb9bcf8d3aULL, 0x1ba13d79d08e1e29ULL},
|
|
{0xf07da27a82c37089ULL, 0xa2898cd844b1a5b3ULL},
|
|
{0x964e858c91ba2656ULL, 0xc595f8072aef0790ULL},
|
|
{0xbbe226efb628afebULL, 0x76fb7608f5aac974ULL},
|
|
{0xeadab0aba3b2dbe6ULL, 0xd4ba538b33157bd1ULL},
|
|
{0x92c8ae6b464fc970ULL, 0xc4f47436ffed6d62ULL},
|
|
{0xb77ada0617e3bbccULL, 0xf6319144bfe8c8bbULL},
|
|
{0xe55990879ddcaabeULL, 0x33bdf595efe2faeaULL},
|
|
{0x8f57fa54c2a9eab7ULL, 0x6056b97db5eddcd2ULL},
|
|
{0xb32df8e9f3546565ULL, 0xb86c67dd23695406ULL},
|
|
{0xdff9772470297ebeULL, 0xa68781d46c43a908ULL},
|
|
{0x8bfbea76c619ef37ULL, 0xa814b124c3aa49a5ULL},
|
|
{0xaefae51477a06b04ULL, 0x1219dd6df494dc0eULL},
|
|
{0xdab99e59958885c5ULL, 0x16a054c971ba1312ULL},
|
|
{0x88b402f7fd75539cULL, 0xee2434fde7144bebULL},
|
|
{0xaae103b5fcd2a882ULL, 0x29ad423d60d95ee6ULL},
|
|
{0xd59944a37c0752a3ULL, 0xb41892ccb90fb6a0ULL},
|
|
{0x857fcae62d8493a6ULL, 0x908f5bbff3a9d224ULL},
|
|
{0xa6dfbd9fb8e5b88fULL, 0x34b332aff09446adULL},
|
|
{0xd097ad07a71f26b3ULL, 0x81dfff5becb95858ULL},
|
|
{0x825ecc24c8737830ULL, 0x712bff9973f3d737ULL},
|
|
{0xa2f67f2dfa90563cULL, 0x8d76ff7fd0f0cd05ULL},
|
|
{0xcbb41ef979346bcbULL, 0xb0d4bf5fc52d0046ULL},
|
|
{0xfea126b7d78186bdULL, 0x1d09ef37b6784057ULL},
|
|
{0x9f24b832e6b0f437ULL, 0xf2263582d20b2836ULL},
|
|
{0xc6ede63fa05d3144ULL, 0x6eafc2e3868df244ULL},
|
|
{0xf8a95fcf88747d95ULL, 0x8a5bb39c68316ed5ULL},
|
|
{0x9b69dbe1b548ce7dULL, 0x36795041c11ee545ULL},
|
|
{0xc24452da229b021cULL, 0x0417a45231669e97ULL},
|
|
{0xf2d56790ab41c2a3ULL, 0x051d8d66bdc0463cULL},
|
|
{0x97c560ba6b0919a6ULL, 0x2332786036982be5ULL},
|
|
{0xbdb6b8e905cb6010ULL, 0xabff1678443e36dfULL},
|
|
{0xed246723473e3814ULL, 0xd6fedc16554dc497ULL},
|
|
{0x9436c0760c86e30cULL, 0x065f498df5509adeULL},
|
|
{0xb94470938fa89bcfULL, 0x07f71bf172a4c196ULL},
|
|
{0xe7958cb87392c2c3ULL, 0x49f4e2edcf4df1fbULL},
|
|
{0x90bd77f3483bb9baULL, 0x4e390dd4a190b73dULL},
|
|
{0xb4ecd5f01a4aa829ULL, 0xe1c75149c9f4e50cULL},
|
|
{0xe2280b6c20dd5233ULL, 0xda39259c3c721e4fULL},
|
|
{0x8d590723948a5360ULL, 0xa863b781a5c752f1ULL},
|
|
{0xb0af48ec79ace838ULL, 0xd27ca5620f3927aeULL},
|
|
{0xdcdb1b2798182245ULL, 0x071bceba9307719aULL},
|
|
{0x8a08f0f8bf0f156cULL, 0xe47161349be4a700ULL},
|
|
{0xac8b2d36eed2dac6ULL, 0x1d8db981c2ddd0c0ULL},
|
|
{0xd7adf884aa879178ULL, 0xa4f127e2339544f0ULL},
|
|
{0x86ccbb52ea94baebULL, 0x6716b8ed603d4b16ULL},
|
|
{0xa87fea27a539e9a6ULL, 0xc0dc6728b84c9ddbULL},
|
|
{0xd29fe4b18e88640fULL, 0x711380f2e65fc552ULL},
|
|
{0x83a3eeeef9153e8aULL, 0xe6ac3097cffbdb53ULL},
|
|
{0xa48ceaaab75a8e2cULL, 0xa0573cbdc3fad228ULL},
|
|
{0xcdb02555653131b7ULL, 0xc86d0bed34f986b2ULL},
|
|
{0x808e17555f3ebf12ULL, 0x1d442774411bf42fULL},
|
|
{0xa0b19d2ab70e6ed7ULL, 0xa49531515162f13bULL},
|
|
{0xc8de047564d20a8cULL, 0x0dba7da5a5bbad8aULL},
|
|
{0xfb158592be068d2fULL, 0x11291d0f0f2a98edULL},
|
|
{0x9ced737bb6c4183eULL, 0xaab9b229697a9f94ULL},
|
|
{0xc428d05aa4751e4dULL, 0x55681eb3c3d94779ULL},
|
|
{0xf53304714d9265e0ULL, 0x2ac22660b4cf9957ULL},
|
|
{0x993fe2c6d07b7facULL, 0x1ab957fc7101bfd6ULL},
|
|
{0xbf8fdb78849a5f97ULL, 0x2167adfb8d422fccULL},
|
|
{0xef73d256a5c0f77dULL, 0x69c1997a7092bbbfULL},
|
|
{0x95a8637627989aaeULL, 0x2218ffec865bb557ULL},
|
|
{0xbb127c53b17ec15aULL, 0xaa9f3fe7a7f2a2adULL},
|
|
{0xe9d71b689dde71b0ULL, 0x55470fe191ef4b59ULL},
|
|
{0x9226712162ab070eULL, 0x354c69ecfb358f17ULL},
|
|
{0xb6b00d69bb55c8d2ULL, 0xc29f84683a02f2ddULL},
|
|
{0xe45c10c42a2b3b06ULL, 0x734765824883af95ULL},
|
|
{0x8eb98a7a9a5b04e4ULL, 0x880c9f716d524dbdULL},
|
|
{0xb267ed1940f1c61dULL, 0xaa0fc74dc8a6e12cULL},
|
|
{0xdf01e85f912e37a4ULL, 0x9493b9213ad09977ULL},
|
|
{0x8b61313bbabce2c7ULL, 0xdcdc53b4c4c25feaULL},
|
|
{0xae397d8aa96c1b78ULL, 0x541368a1f5f2f7e5ULL},
|
|
{0xd9c7dced53c72256ULL, 0x691842ca736fb5deULL},
|
|
{0x881cea14545c7576ULL, 0x81af29be8825d1abULL},
|
|
{0xaa242499697392d3ULL, 0x221af42e2a2f4616ULL},
|
|
{0xd4ad2dbfc3d07788ULL, 0x6aa1b139b4bb179bULL},
|
|
{0x84ec3c97da624ab5ULL, 0x42a50ec410f4eec1ULL},
|
|
{0xa6274bbdd0fadd62ULL, 0x134e527515322a71ULL},
|
|
{0xcfb11ead453994bbULL, 0x9821e7125a7eb50dULL},
|
|
{0x81ceb32c4b43fcf5ULL, 0x7f15306b788f3128ULL},
|
|
{0xa2425ff75e14fc32ULL, 0x5eda7c8656b2fd72ULL},
|
|
{0xcad2f7f5359a3b3fULL, 0xf6911ba7ec5fbccfULL},
|
|
{0xfd87b5f28300ca0eULL, 0x74356291e777ac03ULL},
|
|
{0x9e74d1b791e07e49ULL, 0x88a15d9b30aacb82ULL},
|
|
{0xc612062576589ddbULL, 0x6ac9b501fcd57e62ULL},
|
|
{0xf79687aed3eec552ULL, 0xc57c22427c0addfbULL},
|
|
{0x9abe14cd44753b53ULL, 0x3b6d95698d86cabdULL},
|
|
{0xc16d9a0095928a28ULL, 0x8a48fac3f0e87d6cULL},
|
|
{0xf1c90080baf72cb2ULL, 0xacdb3974ed229cc7ULL},
|
|
{0x971da05074da7befULL, 0x2c0903e91435a1fcULL},
|
|
{0xbce5086492111aebULL, 0x770b44e359430a7bULL},
|
|
{0xec1e4a7db69561a6ULL, 0xd4ce161c2f93cd1aULL},
|
|
{0x9392ee8e921d5d08ULL, 0xc500cdd19dbc6030ULL},
|
|
{0xb877aa3236a4b44aULL, 0xf6410146052b783dULL},
|
|
{0xe69594bec44de15cULL, 0xb3d141978676564cULL},
|
|
{0x901d7cf73ab0acdaULL, 0xf062c8feb409f5efULL},
|
|
{0xb424dc35095cd810ULL, 0xac7b7b3e610c736bULL},
|
|
{0xe12e13424bb40e14ULL, 0xd79a5a0df94f9046ULL},
|
|
{0x8cbccc096f5088ccULL, 0x06c07848bbd1ba2cULL},
|
|
{0xafebff0bcb24aaffULL, 0x0870965aeac628b7ULL},
|
|
{0xdbe6fecebdedd5bfULL, 0x4a8cbbf1a577b2e4ULL},
|
|
{0x89705f4136b4a598ULL, 0xce97f577076acfcfULL},
|
|
{0xabcc77118461cefdULL, 0x023df2d4c94583c2ULL},
|
|
{0xd6bf94d5e57a42bdULL, 0xc2cd6f89fb96e4b3ULL},
|
|
{0x8637bd05af6c69b6ULL, 0x59c065b63d3e4ef0ULL},
|
|
{0xa7c5ac471b478424ULL, 0xf0307f23cc8de2acULL},
|
|
{0xd1b71758e219652cULL, 0x2c3c9eecbfb15b57ULL},
|
|
{0x83126e978d4fdf3cULL, 0x9ba5e353f7ced916ULL},
|
|
{0xa3d70a3d70a3d70bULL, 0xc28f5c28f5c28f5cULL},
|
|
{0xcccccccccccccccdULL, 0x3333333333333333ULL},
|
|
{0x8000000000000000ULL, 0x0000000000000000ULL},
|
|
{0xa000000000000000ULL, 0x0000000000000000ULL},
|
|
{0xc800000000000000ULL, 0x0000000000000000ULL},
|
|
{0xfa00000000000000ULL, 0x0000000000000000ULL},
|
|
{0x9c40000000000000ULL, 0x0000000000000000ULL},
|
|
{0xc350000000000000ULL, 0x0000000000000000ULL},
|
|
{0xf424000000000000ULL, 0x0000000000000000ULL},
|
|
{0x9896800000000000ULL, 0x0000000000000000ULL},
|
|
{0xbebc200000000000ULL, 0x0000000000000000ULL},
|
|
{0xee6b280000000000ULL, 0x0000000000000000ULL},
|
|
{0x9502f90000000000ULL, 0x0000000000000000ULL},
|
|
{0xba43b74000000000ULL, 0x0000000000000000ULL},
|
|
{0xe8d4a51000000000ULL, 0x0000000000000000ULL},
|
|
{0x9184e72a00000000ULL, 0x0000000000000000ULL},
|
|
{0xb5e620f480000000ULL, 0x0000000000000000ULL},
|
|
{0xe35fa931a0000000ULL, 0x0000000000000000ULL},
|
|
{0x8e1bc9bf04000000ULL, 0x0000000000000000ULL},
|
|
{0xb1a2bc2ec5000000ULL, 0x0000000000000000ULL},
|
|
{0xde0b6b3a76400000ULL, 0x0000000000000000ULL},
|
|
{0x8ac7230489e80000ULL, 0x0000000000000000ULL},
|
|
{0xad78ebc5ac620000ULL, 0x0000000000000000ULL},
|
|
{0xd8d726b7177a8000ULL, 0x0000000000000000ULL},
|
|
{0x878678326eac9000ULL, 0x0000000000000000ULL},
|
|
{0xa968163f0a57b400ULL, 0x0000000000000000ULL},
|
|
{0xd3c21bcecceda100ULL, 0x0000000000000000ULL},
|
|
{0x84595161401484a0ULL, 0x0000000000000000ULL},
|
|
{0xa56fa5b99019a5c8ULL, 0x0000000000000000ULL},
|
|
{0xcecb8f27f4200f3aULL, 0x0000000000000000ULL},
|
|
{0x813f3978f8940985ULL, 0xc000000000000000ULL},
|
|
{0xa18f07d736b90be6ULL, 0xb000000000000000ULL},
|
|
{0xc9f2c9cd04674edfULL, 0x5c00000000000000ULL},
|
|
{0xfc6f7c4045812297ULL, 0xb300000000000000ULL},
|
|
{0x9dc5ada82b70b59eULL, 0x0fe0000000000000ULL},
|
|
{0xc5371912364ce306ULL, 0x93d8000000000000ULL},
|
|
{0xf684df56c3e01bc7ULL, 0x38ce000000000000ULL},
|
|
{0x9a130b963a6c115dULL, 0xc380c00000000000ULL},
|
|
{0xc097ce7bc90715b4ULL, 0xb460f00000000000ULL},
|
|
{0xf0bdc21abb48db21ULL, 0xe1792c0000000000ULL},
|
|
{0x96769950b50d88f5ULL, 0xecebbb8000000000ULL},
|
|
{0xbc143fa4e250eb32ULL, 0xe826aa6000000000ULL},
|
|
{0xeb194f8e1ae525feULL, 0xa23054f800000000ULL},
|
|
{0x92efd1b8d0cf37bfULL, 0xa55e351b00000000ULL},
|
|
{0xb7abc627050305aeULL, 0x0eb5c261c0000000ULL},
|
|
{0xe596b7b0c643c71aULL, 0x926332fa30000000ULL},
|
|
{0x8f7e32ce7bea5c70ULL, 0x1b7dffdc5e000000ULL},
|
|
{0xb35dbf821ae4f38cULL, 0x225d7fd375800000ULL},
|
|
{0xe0352f62a19e306fULL, 0x2af4dfc852e00000ULL},
|
|
{0x8c213d9da502de46ULL, 0xbad90bdd33cc0000ULL},
|
|
{0xaf298d050e4395d7ULL, 0x698f4ed480bf0000ULL},
|
|
{0xdaf3f04651d47b4dULL, 0xc3f32289a0eec000ULL},
|
|
{0x88d8762bf324cd10ULL, 0x5a77f59604953800ULL},
|
|
{0xab0e93b6efee0054ULL, 0x7115f2fb85ba8600ULL},
|
|
{0xd5d238a4abe98069ULL, 0x8d5b6fba67292780ULL},
|
|
{0x85a36366eb71f042ULL, 0xb85925d48079b8b0ULL},
|
|
{0xa70c3c40a64e6c52ULL, 0x666f6f49a09826dcULL},
|
|
{0xd0cf4b50cfe20766ULL, 0x000b4b1c08be3093ULL},
|
|
{0x82818f1281ed44a0ULL, 0x40070ef18576de5bULL},
|
|
{0xa321f2d7226895c8ULL, 0x5008d2ade6d495f2ULL},
|
|
{0xcbea6f8ceb02bb3aULL, 0x640b07596089bb6fULL},
|
|
{0xfee50b7025c36a09ULL, 0xfd0dc92fb8ac2a4bULL},
|
|
{0x9f4f2726179a2246ULL, 0xfe289dbdd36b9a6fULL},
|
|
{0xc722f0ef9d80aad7ULL, 0xbdb2c52d4846810aULL},
|
|
{0xf8ebad2b84e0d58cULL, 0x2d1f76789a58214dULL},
|
|
{0x9b934c3b330c8578ULL, 0x9c33aa0b607714d0ULL},
|
|
{0xc2781f49ffcfa6d6ULL, 0xc340948e3894da04ULL},
|
|
{0xf316271c7fc3908bULL, 0x7410b9b1c6ba1085ULL},
|
|
{0x97edd871cfda3a57ULL, 0x688a740f1c344a53ULL},
|
|
{0xbde94e8e43d0c8edULL, 0xc2ad1112e3415ce8ULL},
|
|
{0xed63a231d4c4fb28ULL, 0xb35855579c11b422ULL},
|
|
{0x945e455f24fb1cf9ULL, 0x70173556c18b1095ULL},
|
|
{0xb975d6b6ee39e437ULL, 0x4c1d02ac71edd4bbULL},
|
|
{0xe7d34c64a9c85d45ULL, 0x9f2443578e6949e9ULL},
|
|
{0x90e40fbeea1d3a4bULL, 0x4376aa16b901ce32ULL},
|
|
{0xb51d13aea4a488deULL, 0x9454549c674241beULL},
|
|
{0xe264589a4dcdab15ULL, 0x396969c38112d22eULL},
|
|
{0x8d7eb76070a08aedULL, 0x03e1e21a30abc35dULL},
|
|
{0xb0de65388cc8ada9ULL, 0xc4da5aa0bcd6b434ULL},
|
|
{0xdd15fe86affad913ULL, 0xb610f148ec0c6141ULL},
|
|
{0x8a2dbf142dfcc7acULL, 0x91ca96cd9387bcc8ULL},
|
|
{0xacb92ed9397bf997ULL, 0xb63d3c80f869abfbULL},
|
|
{0xd7e77a8f87daf7fcULL, 0x23cc8ba1368416f9ULL},
|
|
{0x86f0ac99b4e8dafeULL, 0x965fd744c2128e5cULL},
|
|
{0xa8acd7c0222311bdULL, 0x3bf7cd15f29731f3ULL},
|
|
{0xd2d80db02aabd62cULL, 0x0af5c05b6f3cfe6fULL},
|
|
{0x83c7088e1aab65dcULL, 0x86d9983925861f05ULL},
|
|
{0xa4b8cab1a1563f53ULL, 0xa88ffe476ee7a6c7ULL},
|
|
{0xcde6fd5e09abcf27ULL, 0x12b3fdd94aa19079ULL},
|
|
{0x80b05e5ac60b6179ULL, 0xabb07ea7cea4fa4bULL},
|
|
{0xa0dc75f1778e39d7ULL, 0x969c9e51c24e38deULL},
|
|
{0xc913936dd571c84dULL, 0xfc43c5e632e1c716ULL},
|
|
{0xfb5878494ace3a60ULL, 0xfb54b75fbf9a38dcULL},
|
|
{0x9d174b2dcec0e47cULL, 0x9d14f29bd7c06389ULL},
|
|
{0xc45d1df942711d9bULL, 0xc45a2f42cdb07c6bULL},
|
|
{0xf5746577930d6501ULL, 0x3570bb13811c9b86ULL},
|
|
{0x9968bf6abbe85f21ULL, 0x816674ec30b1e134ULL},
|
|
{0xbfc2ef456ae276e9ULL, 0x61c012273cde5981ULL},
|
|
{0xefb3ab16c59b14a3ULL, 0x3a3016b10c15efe1ULL},
|
|
{0x95d04aee3b80ece6ULL, 0x445e0e2ea78db5edULL},
|
|
{0xbb445da9ca612820ULL, 0xd57591ba51712368ULL},
|
|
{0xea1575143cf97227ULL, 0x0ad2f628e5cd6c42ULL},
|
|
{0x924d692ca61be759ULL, 0xa6c3d9d98fa063a9ULL},
|
|
{0xb6e0c377cfa2e12fULL, 0x9074d04ff3887c93ULL},
|
|
{0xe498f455c38b997bULL, 0xf4920463f06a9bb8ULL},
|
|
{0x8edf98b59a373fedULL, 0xb8db42be7642a153ULL},
|
|
{0xb2977ee300c50fe8ULL, 0xa712136e13d349a8ULL},
|
|
{0xdf3d5e9bc0f653e2ULL, 0xd0d6984998c81c12ULL},
|
|
{0x8b865b215899f46dULL, 0x42861f2dff7d118bULL},
|
|
{0xae67f1e9aec07188ULL, 0x1327a6f97f5c55eeULL},
|
|
{0xda01ee641a708deaULL, 0x17f190b7df336b6aULL},
|
|
{0x884134fe908658b3ULL, 0xcef6fa72eb802322ULL},
|
|
{0xaa51823e34a7eedfULL, 0x42b4b90fa6602beaULL},
|
|
{0xd4e5e2cdc1d1ea97ULL, 0x9361e7538ff836e5ULL},
|
|
{0x850fadc09923329fULL, 0xfc1d309439fb224fULL},
|
|
{0xa6539930bf6bff46ULL, 0x7b247cb94879eae3ULL},
|
|
{0xcfe87f7cef46ff17ULL, 0x19ed9be79a98659cULL},
|
|
{0x81f14fae158c5f6fULL, 0xb0348170c09f3f81ULL},
|
|
{0xa26da3999aef774aULL, 0x1c41a1ccf0c70f62ULL},
|
|
{0xcb090c8001ab551dULL, 0xa3520a402cf8d33aULL},
|
|
{0xfdcb4fa002162a64ULL, 0x8c268cd038370809ULL},
|
|
{0x9e9f11c4014dda7fULL, 0xd798180223226505ULL},
|
|
{0xc646d63501a1511eULL, 0x4d7e1e02abeafe47ULL},
|
|
{0xf7d88bc24209a566ULL, 0xe0dda58356e5bdd9ULL},
|
|
{0x9ae7575969460760ULL, 0xcc8a8772164f96a7ULL},
|
|
{0xc1a12d2fc3978938ULL, 0xffad294e9be37c51ULL},
|
|
{0xf209787bb47d6b85ULL, 0x3f9873a242dc5b65ULL},
|
|
{0x9745eb4d50ce6333ULL, 0x07bf484569c9b91fULL},
|
|
{0xbd176620a501fc00ULL, 0x49af1a56c43c2767ULL},
|
|
{0xec5d3fa8ce427b00ULL, 0x5c1ae0ec754b3141ULL},
|
|
{0x93ba47c980e98ce0ULL, 0x3990cc93c94efec8ULL},
|
|
{0xb8a8d9bbe123f018ULL, 0x47f4ffb8bba2be7bULL},
|
|
{0xe6d3102ad96cec1eULL, 0x59f23fa6ea8b6e1aULL},
|
|
{0x9043ea1ac7e41393ULL, 0x783767c8529724d0ULL},
|
|
{0xb454e4a179dd1878ULL, 0xd64541ba673cee04ULL},
|
|
{0xe16a1dc9d8545e95ULL, 0x0bd69229010c2985ULL},
|
|
{0x8ce2529e2734bb1eULL, 0xe7661b59a0a799f3ULL},
|
|
{0xb01ae745b101e9e5ULL, 0xa13fa23008d18070ULL},
|
|
{0xdc21a1171d42645eULL, 0x898f8abc0b05e08cULL},
|
|
{0x899504ae72497ebbULL, 0x95f9b6b586e3ac57ULL},
|
|
{0xabfa45da0edbde6aULL, 0xfb782462e89c976dULL},
|
|
{0xd6f8d7509292d604ULL, 0xba562d7ba2c3bd49ULL},
|
|
{0x865b86925b9bc5c3ULL, 0xf475dc6d45ba564dULL},
|
|
{0xa7f26836f282b733ULL, 0x719353889728ebe1ULL},
|
|
{0xd1ef0244af236500ULL, 0xcdf8286abcf326d9ULL},
|
|
{0x8335616aed761f20ULL, 0x80bb1942b617f847ULL},
|
|
{0xa402b9c5a8d3a6e8ULL, 0xa0e9df93639df659ULL},
|
|
{0xcd036837130890a2ULL, 0xc92457783c8573f0ULL},
|
|
{0x802221226be55a65ULL, 0x3db6b6ab25d36876ULL},
|
|
{0xa02aa96b06deb0feULL, 0x0d246455ef484293ULL},
|
|
{0xc83553c5c8965d3eULL, 0x906d7d6b6b1a5338ULL},
|
|
{0xfa42a8b73abbf48dULL, 0x3488dcc645e0e806ULL},
|
|
{0x9c69a97284b578d8ULL, 0x00d589fbebac9104ULL},
|
|
{0xc38413cf25e2d70eULL, 0x010aec7ae697b545ULL},
|
|
{0xf46518c2ef5b8cd2ULL, 0x814da799a03da296ULL},
|
|
{0x98bf2f79d5993803ULL, 0x10d088c00426859eULL},
|
|
{0xbeeefb584aff8604ULL, 0x5504aaf005302705ULL},
|
|
{0xeeaaba2e5dbf6785ULL, 0x6a45d5ac067c30c7ULL},
|
|
{0x952ab45cfa97a0b3ULL, 0x226ba58b840d9e7cULL},
|
|
{0xba756174393d88e0ULL, 0x6b068eee6511061bULL},
|
|
{0xe912b9d1478ceb18ULL, 0x85c832a9fe5547a2ULL},
|
|
{0x91abb422ccb812efULL, 0x539d1faa3ef54cc5ULL},
|
|
{0xb616a12b7fe617abULL, 0xa8846794ceb29ff6ULL},
|
|
{0xe39c49765fdf9d95ULL, 0x12a5817a025f47f4ULL},
|
|
{0x8e41ade9fbebc27eULL, 0xeba770ec417b8cf8ULL},
|
|
{0xb1d219647ae6b31dULL, 0xa6914d2751da7037ULL},
|
|
{0xde469fbd99a05fe4ULL, 0x9035a07126510c44ULL},
|
|
{0x8aec23d680043befULL, 0xda218446b7f2a7abULL},
|
|
{0xada72ccc20054aeaULL, 0x50a9e55865ef5195ULL},
|
|
{0xd910f7ff28069da5ULL, 0xe4d45eae7f6b25fbULL},
|
|
{0x87aa9aff79042287ULL, 0x6f04bb2d0fa2f7bdULL},
|
|
{0xa99541bf57452b29ULL, 0xcac5e9f8538bb5acULL},
|
|
{0xd3fa922f2d1675f3ULL, 0xbd776476686ea317ULL},
|
|
{0x847c9b5d7c2e09b8ULL, 0x966a9eca014525eeULL},
|
|
{0xa59bc234db398c26ULL, 0xbc05467c81966f6aULL},
|
|
{0xcf02b2c21207ef2fULL, 0x6b06981ba1fc0b44ULL},
|
|
{0x8161afb94b44f57eULL, 0xe2e41f11453d870aULL},
|
|
{0xa1ba1ba79e1632ddULL, 0x9b9d26d5968ce8cdULL},
|
|
{0xca28a291859bbf94ULL, 0x8284708afc302301ULL},
|
|
{0xfcb2cb35e702af79ULL, 0xa3258cadbb3c2bc1ULL},
|
|
{0x9defbf01b061adacULL, 0xc5f777ec95059b58ULL},
|
|
{0xc56baec21c7a1917ULL, 0xf77555e7ba47022fULL},
|
|
{0xf6c69a72a3989f5cULL, 0x7552ab61a8d8c2baULL},
|
|
{0x9a3c2087a63f639aULL, 0xc953ab1d098779b4ULL},
|
|
{0xc0cb28a98fcf3c80ULL, 0x7ba895e44be95822ULL},
|
|
{0xf0fdf2d3f3c30ba0ULL, 0x9a92bb5d5ee3ae2aULL},
|
|
{0x969eb7c47859e744ULL, 0x609bb51a5b4e4cdaULL},
|
|
{0xbc4665b596706115ULL, 0x78c2a260f221e011ULL},
|
|
{0xeb57ff22fc0c795aULL, 0x56f34af92eaa5815ULL},
|
|
{0x9316ff75dd87cbd9ULL, 0xf6580edbbd2a770dULL},
|
|
{0xb7dcbf5354e9becfULL, 0xf3ee1292ac7514d0ULL},
|
|
{0xe5d3ef282a242e82ULL, 0x70e9973757925a05ULL},
|
|
{0x8fa475791a569d11ULL, 0x0691fe8296bb7843ULL},
|
|
{0xb38d92d760ec4456ULL, 0xc8367e233c6a5653ULL},
|
|
{0xe070f78d3927556bULL, 0x7a441dac0b84ebe8ULL},
|
|
{0x8c469ab843b89563ULL, 0x6c6a928b87331371ULL},
|
|
{0xaf58416654a6babcULL, 0xc785372e68ffd84dULL},
|
|
{0xdb2e51bfe9d0696bULL, 0xf96684fa033fce61ULL},
|
|
{0x88fcf317f22241e3ULL, 0xbbe0131c4207e0fcULL},
|
|
{0xab3c2fddeeaad25bULL, 0x2ad817e35289d93cULL},
|
|
{0xd60b3bd56a5586f2ULL, 0x758e1ddc272c4f8bULL},
|
|
{0x85c7056562757457ULL, 0x0978d2a9987bb1b6ULL},
|
|
{0xa738c6bebb12d16dULL, 0x4bd70753fe9a9e24ULL},
|
|
{0xd106f86e69d785c8ULL, 0x1eccc928fe4145adULL},
|
|
{0x82a45b450226b39dULL, 0x133ffdb99ee8cb8cULL},
|
|
{0xa34d721642b06085ULL, 0xd80ffd2806a2fe6fULL},
|
|
{0xcc20ce9bd35c78a6ULL, 0xce13fc72084bbe0bULL},
|
|
{0xff290242c83396cfULL, 0x8198fb8e8a5ead8eULL},
|
|
{0x9f79a169bd203e42ULL, 0xf0ff9d39167b2c79ULL},
|
|
{0xc75809c42c684dd2ULL, 0xad3f84875c19f797ULL},
|
|
{0xf92e0c3537826146ULL, 0x588f65a93320757dULL},
|
|
{0x9bbcc7a142b17cccULL, 0x77599f89bff4496eULL},
|
|
{0xc2abf989935ddbffULL, 0x9530076c2ff15bcaULL},
|
|
{0xf356f7ebf83552ffULL, 0xfa7c09473bedb2bcULL},
|
|
{0x98165af37b2153dfULL, 0x3c8d85cc85748fb5ULL},
|
|
{0xbe1bf1b059e9a8d7ULL, 0x8bb0e73fa6d1b3a3ULL},
|
|
{0xeda2ee1c7064130dULL, 0xee9d210f9086208cULL},
|
|
{0x9485d4d1c63e8be8ULL, 0x752234a9ba53d457ULL},
|
|
{0xb9a74a0637ce2ee2ULL, 0x926ac1d428e8c96dULL},
|
|
{0xe8111c87c5c1ba9aULL, 0x370572493322fbc8ULL},
|
|
{0x910ab1d4db9914a1ULL, 0xe263676dbff5dd5dULL},
|
|
{0xb54d5e4a127f59c9ULL, 0xdafc41492ff354b4ULL},
|
|
{0xe2a0b5dc971f303bULL, 0xd1bb519b7bf029e2ULL},
|
|
{0x8da471a9de737e25ULL, 0xa31513012d761a2dULL},
|
|
{0xb10d8e1456105daeULL, 0x8bda57c178d3a0b8ULL},
|
|
{0xdd50f1996b947519ULL, 0x2ed0edb1d70888e6ULL},
|
|
{0x8a5296ffe33cc930ULL, 0x7d42948f26655590ULL},
|
|
{0xace73cbfdc0bfb7cULL, 0x9c9339b2effeaaf4ULL},
|
|
{0xd8210befd30efa5bULL, 0xc3b8081fabfe55b1ULL},
|
|
{0x8714a775e3e95c79ULL, 0x9a530513cb7ef58eULL},
|
|
{0xa8d9d1535ce3b397ULL, 0x80e7c658be5eb2f2ULL},
|
|
{0xd31045a8341ca07dULL, 0xe121b7eeedf65fafULL},
|
|
{0x83ea2b892091e44eULL, 0x6cb512f554b9fbcdULL},
|
|
{0xa4e4b66b68b65d61ULL, 0x07e257b2a9e87ac0ULL},
|
|
{0xce1de40642e3f4baULL, 0xc9daed9f54629971ULL},
|
|
{0x80d2ae83e9ce78f4ULL, 0x3e28d48394bd9fe6ULL},
|
|
{0xa1075a24e4421731ULL, 0x4db309a479ed07e0ULL},
|
|
{0xc94930ae1d529cfdULL, 0x211fcc0d986849d8ULL},
|
|
{0xfb9b7cd9a4a7443dULL, 0xe967bf10fe825c4eULL},
|
|
{0x9d412e0806e88aa6ULL, 0x71e0d76a9f1179b1ULL},
|
|
{0xc491798a08a2ad4fULL, 0x0e590d4546d5d81dULL},
|
|
{0xf5b5d7ec8acb58a3ULL, 0x51ef5096988b4e24ULL},
|
|
{0x9991a6f3d6bf1766ULL, 0x5335925e1f5710d6ULL},
|
|
{0xbff610b0cc6edd40ULL, 0xe802f6f5a72cd50cULL},
|
|
{0xeff394dcff8a948fULL, 0x2203b4b310f80a4fULL},
|
|
{0x95f83d0a1fb69cdaULL, 0xb54250efea9b0671ULL},
|
|
{0xbb764c4ca7a44410ULL, 0x6292e52be541c80eULL},
|
|
{0xea53df5fd18d5514ULL, 0x7b379e76de923a12ULL},
|
|
{0x92746b9be2f8552dULL, 0xcd02c30a4b1b644bULL},
|
|
{0xb7118682dbb66a78ULL, 0xc04373ccdde23d5eULL},
|
|
{0xe4d5e82392a40516ULL, 0xf05450c0155accb5ULL},
|
|
{0x8f05b1163ba6832eULL, 0xd634b2780d58bff1ULL},
|
|
{0xb2c71d5bca9023f9ULL, 0x8bc1df1610aeefedULL},
|
|
{0xdf78e4b2bd342cf7ULL, 0x6eb256db94daabe9ULL},
|
|
{0x8bab8eefb6409c1bULL, 0xe52f76493d08ab71ULL},
|
|
{0xae9672aba3d0c321ULL, 0x5e7b53db8c4ad64eULL},
|
|
{0xda3c0f568cc4f3e9ULL, 0x361a28d26f5d8be1ULL},
|
|
{0x8865899617fb1872ULL, 0x81d05983859a776dULL},
|
|
{0xaa7eebfb9df9de8eULL, 0x22446fe467011548ULL},
|
|
{0xd51ea6fa85785632ULL, 0xaad58bdd80c15a9aULL},
|
|
{0x8533285c936b35dfULL, 0x2ac5776a7078d8a0ULL},
|
|
{0xa67ff273b8460357ULL, 0x7576d5450c970ec8ULL},
|
|
{0xd01fef10a657842dULL, 0xd2d48a964fbcd27aULL},
|
|
{0x8213f56a67f6b29cULL, 0x63c4d69df1d6038cULL},
|
|
{0xa298f2c501f45f43ULL, 0x7cb60c456e4b8470ULL},
|
|
{0xcb3f2f7642717714ULL, 0xdbe38f56c9de658cULL},
|
|
{0xfe0efb53d30dd4d8ULL, 0x12dc732c7c55feefULL},
|
|
{0x9ec95d1463e8a507ULL, 0x0bc9c7fbcdb5bf55ULL},
|
|
{0xc67bb4597ce2ce49ULL, 0x4ebc39fac1232f2aULL},
|
|
{0xf81aa16fdc1b81dbULL, 0x226b4879716bfaf5ULL},
|
|
{0x9b10a4e5e9913129ULL, 0x35830d4be6e37cd9ULL},
|
|
{0xc1d4ce1f63f57d73ULL, 0x02e3d09ee09c5c0fULL},
|
|
{0xf24a01a73cf2dcd0ULL, 0x439cc4c698c37313ULL},
|
|
{0x976e41088617ca02ULL, 0x2a41fafc1f7a27ecULL},
|
|
{0xbd49d14aa79dbc83ULL, 0xb4d279bb2758b1e7ULL},
|
|
{0xec9c459d51852ba3ULL, 0x22071829f12ede61ULL},
|
|
{0x93e1ab8252f33b46ULL, 0x35446f1a36bd4afcULL},
|
|
{0xb8da1662e7b00a18ULL, 0xc2958ae0c46c9dbcULL},
|
|
{0xe7109bfba19c0c9eULL, 0xf33aed98f587c52bULL},
|
|
{0x906a617d450187e3ULL, 0xd804d47f9974db3aULL},
|
|
{0xb484f9dc9641e9dbULL, 0x4e06099f7fd21209ULL},
|
|
{0xe1a63853bbd26452ULL, 0xa1878c075fc6968cULL},
|
|
{0x8d07e33455637eb3ULL, 0x24f4b7849bdc1e17ULL},
|
|
{0xb049dc016abc5e60ULL, 0x6e31e565c2d3259dULL},
|
|
{0xdc5c5301c56b75f8ULL, 0x89be5ebf3387ef04ULL},
|
|
{0x89b9b3e11b6329bbULL, 0x5616fb378034f562ULL},
|
|
{0xac2820d9623bf42aULL, 0xab9cba05604232bbULL},
|
|
{0xd732290fbacaf134ULL, 0x5683e886b852bf6aULL},
|
|
{0x867f59a9d4bed6c1ULL, 0xb61271543333b7a2ULL},
|
|
{0xa81f301449ee8c71ULL, 0xa3970da94000a58bULL},
|
|
{0xd226fc195c6a2f8dULL, 0x8c7cd1139000ceeeULL},
|
|
{0x83585d8fd9c25db8ULL, 0x37ce02ac3a008154ULL},
|
|
{0xa42e74f3d032f526ULL, 0x45c183574880a1aaULL},
|
|
{0xcd3a1230c43fb270ULL, 0xd731e42d1aa0ca14ULL},
|
|
{0x80444b5e7aa7cf86ULL, 0x867f2e9c30a47e4cULL},
|
|
{0xa0555e361951c367ULL, 0x281efa433ccd9de0ULL},
|
|
{0xc86ab5c39fa63441ULL, 0x7226b8d40c010558ULL},
|
|
{0xfa856334878fc151ULL, 0x4eb067090f0146aeULL},
|
|
{0x9c935e00d4b9d8d3ULL, 0x912e4065a960cc2cULL},
|
|
{0xc3b8358109e84f08ULL, 0xf579d07f13b8ff37ULL},
|
|
{0xf4a642e14c6262c9ULL, 0x32d8449ed8a73f05ULL},
|
|
{0x98e7e9cccfbd7dbeULL, 0x7fc72ae347688763ULL},
|
|
{0xbf21e44003acdd2dULL, 0x1fb8f59c1942a93cULL},
|
|
{0xeeea5d5004981479ULL, 0xe7a733031f93538bULL},
|
|
{0x95527a5202df0cccULL, 0xf0c87fe1f3bc1437ULL},
|
|
{0xbaa718e68396cffeULL, 0x2cfa9fda70ab1945ULL},
|
|
{0xe950df20247c83feULL, 0xb83947d10cd5df96ULL},
|
|
{0x91d28b7416cdd27fULL, 0xb323cce2a805abbeULL},
|
|
{0xb6472e511c81471eULL, 0x1fecc01b520716adULL},
|
|
{0xe3d8f9e563a198e6ULL, 0xa7e7f0222688dc59ULL},
|
|
{0x8e679c2f5e44ff90ULL, 0xa8f0f615581589b7ULL},
|
|
{0xb201833b35d63f74ULL, 0xd32d339aae1aec25ULL},
|
|
{0xde81e40a034bcf50ULL, 0x07f8808159a1a72eULL},
|
|
{0x8b112e86420f6192ULL, 0x04fb5050d805087dULL},
|
|
{0xadd57a27d29339f7ULL, 0x863a24650e064a9cULL},
|
|
{0xd94ad8b1c7380875ULL, 0xe7c8ad7e5187dd43ULL},
|
|
{0x87cec76f1c830549ULL, 0x70dd6c6ef2f4ea4aULL},
|
|
{0xa9c2794ae3a3c69bULL, 0x4d14c78aafb224ddULL},
|
|
{0xd433179d9c8cb842ULL, 0xa059f96d5b9eae14ULL},
|
|
{0x849feec281d7f329ULL, 0x24383be459432cccULL},
|
|
{0xa5c7ea73224deff4ULL, 0xed464add6f93f7ffULL},
|
|
{0xcf39e50feae16bf0ULL, 0x2897dd94cb78f5ffULL},
|
|
{0x81842f29f2cce376ULL, 0x195eea7cff2b99bfULL},
|
|
{0xa1e53af46f801c54ULL, 0x9fb6a51c3ef6802fULL},
|
|
{0xca5e89b18b602369ULL, 0xc7a44e634eb4203bULL},
|
|
{0xfcf62c1dee382c43ULL, 0xb98d61fc2261284aULL},
|
|
{0x9e19db92b4e31baaULL, 0x93f85d3d957cb92eULL},
|
|
{0xc5a05277621be294ULL, 0x38f6748cfadbe77aULL},
|
|
{0xf70867153aa2db39ULL, 0x473411b03992e158ULL},
|
|
{0x9a65406d44a5c904ULL, 0x8c808b0e23fbccd7ULL},
|
|
{0xc0fe908895cf3b45ULL, 0xafa0add1acfac00dULL},
|
|
{0xf13e34aabb430a16ULL, 0x9b88d94618397010ULL},
|
|
{0x96c6e0eab509e64eULL, 0xa13587cbcf23e60aULL},
|
|
{0xbc789925624c5fe1ULL, 0x4982e9bec2ecdf8dULL},
|
|
{0xeb96bf6ebadf77d9ULL, 0x1be3a42e73a81770ULL},
|
|
{0x933e37a534cbaae8ULL, 0x716e469d08490ea6ULL},
|
|
{0xb80dc58e81fe95a2ULL, 0x8dc9d8444a5b524fULL},
|
|
{0xe61136f2227e3b0aULL, 0x313c4e555cf226e3ULL},
|
|
{0x8fcac257558ee4e7ULL, 0xdec5b0f55a17584eULL},
|
|
{0xb3bd72ed2af29e20ULL, 0x56771d32b09d2e62ULL},
|
|
{0xe0accfa875af45a8ULL, 0x6c14e47f5cc479faULL},
|
|
{0x8c6c01c9498d8b89ULL, 0x438d0ecf99facc3cULL},
|
|
{0xaf87023b9bf0ee6bULL, 0x1470528380797f4bULL},
|
|
{0xdb68c2ca82ed2a06ULL, 0x598c67246097df1eULL},
|
|
};
|
|
|
|
/* ======== Uscale core ======== */
|
|
|
|
static inline int log10_pow2(int x)
|
|
{
|
|
return (x * 78913) >> 18;
|
|
}
|
|
|
|
static inline int log2_pow10(int x)
|
|
{
|
|
return (x * 108853) >> 15;
|
|
}
|
|
|
|
typedef struct {
|
|
pow10_entry pm;
|
|
int s;
|
|
} scaler;
|
|
|
|
static inline scaler prescale(int e, int p, int lp)
|
|
{
|
|
scaler c;
|
|
c.pm = pow10_tab[p - POW10_MIN];
|
|
c.s = -(e + lp + 3);
|
|
return c;
|
|
}
|
|
|
|
typedef uint64_t unrounded;
|
|
|
|
static inline uint64_t ur_floor(unrounded u) { return (u + 0) >> 2; }
|
|
static inline uint64_t ur_round(unrounded u) { return (u + 1 + ((u >> 2) & 1)) >> 2; }
|
|
static inline uint64_t ur_ceil(unrounded u) { return (u + 3) >> 2; }
|
|
|
|
static inline unrounded ur_div(unrounded u, uint64_t d)
|
|
{
|
|
return (u / d) | (u & 1) | (u % d != 0 ? 1 : 0);
|
|
}
|
|
|
|
static inline unrounded ur_nudge(unrounded u, int delta)
|
|
{
|
|
return u + delta;
|
|
}
|
|
|
|
static unrounded uscale(uint64_t x, scaler c)
|
|
{
|
|
uint64_t hi, mid, mid2, lo_unused;
|
|
mul64(x, c.pm.hi, &hi, &mid);
|
|
|
|
uint64_t sticky = 1;
|
|
|
|
if (c.s >= 64) {
|
|
/* x * 10^p < 2^(c.s-64), i.e. < 1 in the unrounded "1.0 = 4" encoding;
|
|
rounds to 0 with sticky=1 */
|
|
return sticky;
|
|
}
|
|
|
|
uint64_t mask = (1ULL << c.s) - 1;
|
|
|
|
if ((hi & mask) == 0) {
|
|
mul64(x, c.pm.lo, &mid2, &lo_unused);
|
|
sticky = (mid - mid2) > 1 ? 1 : 0;
|
|
hi -= (mid < mid2) ? 1 : 0;
|
|
}
|
|
|
|
return (hi >> c.s) | sticky;
|
|
}
|
|
|
|
static void unpack64(double f, uint64_t *m, int *e)
|
|
{
|
|
const int shift = 64 - 53;
|
|
const int min_exp = -(1074 + shift);
|
|
union { double d; uint64_t u; } u;
|
|
u.d = f;
|
|
uint64_t bits = u.u;
|
|
int exp;
|
|
|
|
*m = (1ULL << 63) | ((bits & ((1ULL << 52) - 1)) << shift);
|
|
exp = (int)((bits >> 52) & ((1 << shift) - 1));
|
|
|
|
if (exp == 0) {
|
|
int s;
|
|
*m &= ~(1ULL << 63);
|
|
*e = min_exp;
|
|
s = clz64(*m);
|
|
*m <<= s;
|
|
*e -= s;
|
|
}
|
|
else {
|
|
*e = (exp - 1) + min_exp;
|
|
}
|
|
}
|
|
|
|
static double pack64(uint64_t m, int e)
|
|
{
|
|
union { double d; uint64_t u; } u;
|
|
if ((m & (1ULL << 52)) == 0) {
|
|
/* subnormal */
|
|
u.u = m;
|
|
}
|
|
else {
|
|
int biased = 1075 + e;
|
|
if (biased >= 2047) {
|
|
/* exponent overflow -> infinity */
|
|
u.u = 0x7FF0000000000000ULL;
|
|
}
|
|
else {
|
|
u.u = (m & ~(1ULL << 52)) | ((uint64_t)biased << 52);
|
|
}
|
|
}
|
|
return u.d;
|
|
}
|
|
|
|
/* ======== Algorithm helpers ======== */
|
|
|
|
static const uint64_t uint64_pow10[20] = {
|
|
1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL,
|
|
100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, 1000000000ULL,
|
|
10000000000ULL, 100000000000ULL, 1000000000000ULL, 10000000000000ULL,
|
|
100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL,
|
|
100000000000000000ULL, 1000000000000000000ULL, 10000000000000000000ULL,
|
|
};
|
|
|
|
static int count_digits(uint64_t d)
|
|
{
|
|
if (d == 0) return 1; /* clz64(0) is UB; "0" is one digit */
|
|
int nd = log10_pow2(bits_len64(d));
|
|
return nd + (d >= uint64_pow10[nd] ? 1 : 0);
|
|
}
|
|
|
|
static void fixed_width(double f, int n, uint64_t *d, int *p)
|
|
{
|
|
uint64_t m;
|
|
int e;
|
|
unrounded u;
|
|
|
|
unpack64(f, &m, &e);
|
|
*p = n - 1 - log10_pow2(e + 63);
|
|
u = uscale(m, prescale(e, *p, log2_pow10(*p)));
|
|
*d = ur_round(u);
|
|
|
|
if (*d >= uint64_pow10[n]) {
|
|
*d = ur_round(ur_div(u, 10));
|
|
(*p)--;
|
|
}
|
|
*p = -(*p);
|
|
}
|
|
|
|
/*
|
|
* skewed returns floor(log10(3/4 * 2^e))
|
|
* Used for shortest-width printing at powers of 2
|
|
*/
|
|
static inline int skewed(int e)
|
|
{
|
|
return (e * 631305 - 261663) >> 21;
|
|
}
|
|
|
|
/*
|
|
* trim_zeros removes trailing zeros from x * 10^p
|
|
*/
|
|
static void trim_zeros(uint64_t *x, int *p)
|
|
{
|
|
const uint64_t inv5 = 0xcccccccccccccccdULL;
|
|
const uint64_t inv5p2 = 0x8f5c28f5c28f5c29ULL;
|
|
const uint64_t inv5p4 = 0xd288ce703afb7e91ULL;
|
|
const uint64_t inv5p8 = 0xc767074b22e90e21ULL;
|
|
uint64_t d;
|
|
|
|
/* cut 1 zero, or else return */
|
|
d = (*x * inv5);
|
|
d = (d >> 1) | (d << 63);
|
|
if (d <= UINT64_MAX / 10) {
|
|
*x = d;
|
|
(*p)++;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
|
|
/* cut 8 zeros */
|
|
d = (*x * inv5p8);
|
|
d = (d >> 8) | (d << 56);
|
|
if (d <= UINT64_MAX / 100000000ULL) {
|
|
*x = d;
|
|
*p += 8;
|
|
}
|
|
|
|
/* cut 4 zeros */
|
|
d = (*x * inv5p4);
|
|
d = (d >> 4) | (d << 60);
|
|
if (d <= UINT64_MAX / 10000) {
|
|
*x = d;
|
|
*p += 4;
|
|
}
|
|
|
|
/* cut 2 zeros */
|
|
d = (*x * inv5p2);
|
|
d = (d >> 2) | (d << 62);
|
|
if (d <= UINT64_MAX / 100) {
|
|
*x = d;
|
|
*p += 2;
|
|
}
|
|
|
|
/* cut 1 zero */
|
|
d = (*x * inv5);
|
|
d = (d >> 1) | (d << 63);
|
|
if (d <= UINT64_MAX / 10) {
|
|
*x = d;
|
|
(*p)++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* shortest computes the shortest formatting of f
|
|
* Returns d and p such that d * 10^p equals f when parsed
|
|
*/
|
|
static void shortest(double f, uint64_t *d, int *p)
|
|
{
|
|
const int min_exp = -1085;
|
|
uint64_t m, min, max;
|
|
int e, z, odd, lp;
|
|
scaler pre;
|
|
uint64_t dmin, dmax;
|
|
|
|
unpack64(f, &m, &e);
|
|
z = 11;
|
|
|
|
if (m == (1ULL << 63) && e > min_exp) {
|
|
*p = -skewed(e + z);
|
|
min = m - (1ULL << (z - 2));
|
|
}
|
|
else {
|
|
if (e < min_exp) {
|
|
z = 11 + (min_exp - e);
|
|
}
|
|
*p = -log10_pow2(e + z);
|
|
min = m - (1ULL << (z - 1));
|
|
}
|
|
max = m + (1ULL << (z - 1));
|
|
odd = (int)((m >> z) & 1);
|
|
|
|
lp = log2_pow10(*p);
|
|
pre = prescale(e, *p, lp);
|
|
|
|
dmin = ur_ceil(ur_nudge(uscale(min, pre), +odd));
|
|
dmax = ur_floor(ur_nudge(uscale(max, pre), -odd));
|
|
|
|
/* check if a multiple of 10 is in range */
|
|
*d = dmax / 10;
|
|
if (*d * 10 >= dmin) {
|
|
int new_p = -(*p - 1);
|
|
trim_zeros(d, &new_p);
|
|
*p = new_p;
|
|
return;
|
|
}
|
|
|
|
/* multiple valid values: pick the rounded one */
|
|
if (dmin < dmax) {
|
|
*d = ur_round(uscale(m, pre));
|
|
}
|
|
else {
|
|
*d = dmin;
|
|
}
|
|
*p = -(*p);
|
|
}
|
|
|
|
static double parse_decimal(uint64_t d, int p)
|
|
{
|
|
int b, lp, e;
|
|
unrounded u;
|
|
uint64_t m;
|
|
|
|
if (d == 0) return 0.0;
|
|
|
|
b = bits_len64(d);
|
|
lp = log2_pow10(p);
|
|
e = 53 - b - lp;
|
|
if (e > 1074) e = 1074;
|
|
|
|
u = uscale(d << (64 - b), prescale(e - (64 - b), p, lp));
|
|
m = ur_round(u);
|
|
|
|
if (m >= (1ULL << 53)) {
|
|
u = (u >> 1) | (u & 1);
|
|
m = ur_round(u);
|
|
e--;
|
|
}
|
|
|
|
return pack64(m, -e);
|
|
}
|
|
|
|
/* ======== Formatting helpers ======== */
|
|
|
|
static const char i2a[] =
|
|
"00010203040506070809"
|
|
"10111213141516171819"
|
|
"20212223242526272829"
|
|
"30313233343536373839"
|
|
"40414243444546474849"
|
|
"50515253545556575859"
|
|
"60616263646566676869"
|
|
"70717273747576777879"
|
|
"80818283848586878889"
|
|
"90919293949596979899";
|
|
|
|
static void format_base10(char *buf, int nd, uint64_t u)
|
|
{
|
|
int idx;
|
|
while (nd >= 2) {
|
|
nd -= 2;
|
|
idx = (int)(u % 100) * 2;
|
|
u /= 100;
|
|
buf[nd] = i2a[idx];
|
|
buf[nd + 1] = i2a[idx + 1];
|
|
}
|
|
if (nd > 0) {
|
|
buf[0] = '0' + (char)u;
|
|
}
|
|
}
|
|
|
|
static int
|
|
emit_exp(char *s, char e_char, int exp)
|
|
{
|
|
char *p = s;
|
|
*p++ = e_char;
|
|
if (exp < 0) {
|
|
*p++ = '-';
|
|
exp = -exp;
|
|
}
|
|
else {
|
|
*p++ = '+';
|
|
}
|
|
if (exp >= 100) {
|
|
*p++ = '0' + exp / 100;
|
|
exp %= 100;
|
|
}
|
|
*p++ = '0' + exp / 10;
|
|
*p++ = '0' + exp % 10;
|
|
return (int)(p - s);
|
|
}
|
|
|
|
/* ======== mrb_format_float ======== */
|
|
|
|
#ifdef MRB_USE_FLOAT32
|
|
#define FLT_MIN_BUF_SIZE 6
|
|
#else
|
|
#define FLT_MIN_BUF_SIZE 7
|
|
#endif
|
|
|
|
int
|
|
mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, char sign)
|
|
{
|
|
char *s = buf;
|
|
int buf_remaining = (int)buf_size - 1;
|
|
int alt_form = 0;
|
|
char e_char;
|
|
|
|
if ((uint8_t)fmt & 0x80) {
|
|
fmt &= 0x7f;
|
|
alt_form = 1;
|
|
}
|
|
if (buf_size <= (size_t)FLT_MIN_BUF_SIZE) {
|
|
if (buf_size >= 2) *s++ = '?';
|
|
if (buf_size >= 1) *s = '\0';
|
|
return buf_size >= 2;
|
|
}
|
|
if (signbit(f)) {
|
|
*s++ = '-';
|
|
f = -f;
|
|
}
|
|
else if (sign) {
|
|
*s++ = sign;
|
|
}
|
|
buf_remaining -= (int)(s - buf);
|
|
|
|
{
|
|
char uc = fmt & 0x20;
|
|
if (isinf(f)) {
|
|
*s++ = 'I' ^ uc;
|
|
*s++ = 'N' ^ uc;
|
|
*s++ = 'F' ^ uc;
|
|
goto done;
|
|
}
|
|
if (isnan(f)) {
|
|
*s++ = 'N' ^ uc;
|
|
*s++ = 'A' ^ uc;
|
|
*s++ = 'N' ^ uc;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
{
|
|
int use_shortest = (prec == -2);
|
|
if (prec < 0) prec = 6;
|
|
e_char = 'E' | (fmt & 0x20);
|
|
fmt |= 0x20;
|
|
if (fmt == 'g') {
|
|
if (use_shortest) fmt = 'S'; /* shortest mode */
|
|
else if (prec == 0) prec = 1;
|
|
}
|
|
}
|
|
|
|
if (f == 0.0) {
|
|
/* zero */
|
|
if (fmt == 'e') {
|
|
*s++ = '0';
|
|
if (prec > 0 || alt_form) {
|
|
int i;
|
|
if (prec > buf_remaining - 5) prec = buf_remaining - 5;
|
|
*s++ = '.';
|
|
for (i = 0; i < prec; i++) *s++ = '0';
|
|
}
|
|
s += emit_exp(s, e_char, 0);
|
|
}
|
|
else if (fmt == 'f') {
|
|
int i;
|
|
if (prec > buf_remaining - 2) prec = buf_remaining - 2;
|
|
*s++ = '0';
|
|
if (prec > 0 || alt_form) {
|
|
*s++ = '.';
|
|
for (i = 0; i < prec; i++) *s++ = '0';
|
|
}
|
|
}
|
|
else { /* g */
|
|
*s++ = '0';
|
|
if (alt_form && prec > 1) {
|
|
int i;
|
|
*s++ = '.';
|
|
for (i = 1; i < prec; i++) *s++ = '0';
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* nonzero finite */
|
|
uint64_t d;
|
|
int p, nd, exp;
|
|
char digs[20] = {0}; /* gcc -Wmaybe-uninitialized false positive: count_digits() always returns >= 1 */
|
|
|
|
if (fmt == 'S') {
|
|
/* shortest representation for to_s */
|
|
int i;
|
|
shortest((double)f, &d, &p);
|
|
nd = count_digits(d);
|
|
exp = p + nd - 1;
|
|
format_base10(digs, nd, d);
|
|
|
|
#ifdef MRB_USE_FLOAT32
|
|
if (exp < -4 || exp >= 7) {
|
|
#else
|
|
if (exp < -4 || exp >= 15) {
|
|
#endif
|
|
/* e format */
|
|
*s++ = digs[0];
|
|
if (nd > 1) {
|
|
*s++ = '.';
|
|
for (i = 1; i < nd; i++) *s++ = digs[i];
|
|
}
|
|
s += emit_exp(s, e_char, exp);
|
|
}
|
|
else {
|
|
/* f format */
|
|
if (exp < 0) {
|
|
*s++ = '0';
|
|
*s++ = '.';
|
|
for (i = 0; i < -(exp + 1); i++) *s++ = '0';
|
|
for (i = 0; i < nd; i++) *s++ = digs[i];
|
|
}
|
|
else {
|
|
for (i = 0; i <= exp && i < nd; i++) *s++ = digs[i];
|
|
for (; i <= exp; i++) *s++ = '0';
|
|
if (nd > exp + 1) {
|
|
*s++ = '.';
|
|
for (i = exp + 1; i < nd; i++) *s++ = digs[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (fmt == 'g') {
|
|
/* g/G format */
|
|
int fprec, n = prec;
|
|
if (n > 18) n = 18;
|
|
if (n < 1) n = 1;
|
|
fixed_width((double)f, n, &d, &p);
|
|
nd = count_digits(d);
|
|
exp = p + nd - 1;
|
|
|
|
if (exp < -4 || exp >= prec) {
|
|
/* use e format with prec-1 fractional digits */
|
|
fprec = prec - 1;
|
|
format_base10(digs, nd, d);
|
|
*s++ = digs[0];
|
|
if (fprec > 0 || alt_form) {
|
|
int i, end = fprec < nd - 1 ? fprec : nd - 1;
|
|
*s++ = '.';
|
|
for (i = 0; i < end; i++) *s++ = digs[1 + i];
|
|
for (; i < fprec; i++) *s++ = '0';
|
|
}
|
|
if (!alt_form) {
|
|
/* strip trailing zeros */
|
|
while (s > buf && s[-1] == '0') s--;
|
|
if (s > buf && s[-1] == '.') s--;
|
|
}
|
|
s += emit_exp(s, e_char, exp);
|
|
}
|
|
else {
|
|
/* use f format with prec-(exp+1) fractional digits */
|
|
int i;
|
|
fprec = prec - (exp + 1);
|
|
format_base10(digs, nd, d);
|
|
/* integer part */
|
|
if (exp < 0) {
|
|
*s++ = '0';
|
|
}
|
|
else {
|
|
for (i = 0; i <= exp && i < nd; i++) *s++ = digs[i];
|
|
for (; i <= exp; i++) *s++ = '0';
|
|
}
|
|
if (fprec > 0 || alt_form) {
|
|
int frac_avail;
|
|
*s++ = '.';
|
|
if (exp < 0) {
|
|
int zeros = -(exp + 1);
|
|
for (i = 0; i < zeros && i < fprec; i++) *s++ = '0';
|
|
frac_avail = fprec - zeros;
|
|
for (i = 0; i < frac_avail && i < nd; i++) *s++ = digs[i];
|
|
for (; i < frac_avail; i++) *s++ = '0';
|
|
}
|
|
else {
|
|
frac_avail = nd - exp - 1;
|
|
if (frac_avail < 0) frac_avail = 0;
|
|
for (i = 0; i < frac_avail && i < fprec; i++) *s++ = digs[exp + 1 + i];
|
|
for (; i < fprec; i++) *s++ = '0';
|
|
}
|
|
}
|
|
if (!alt_form && fprec > 0) {
|
|
while (s[-1] == '0') s--;
|
|
if (s[-1] == '.') s--;
|
|
}
|
|
}
|
|
}
|
|
else if (fmt == 'e') {
|
|
/* e/E format */
|
|
int n = prec + 1;
|
|
int i;
|
|
if (n > 18) n = 18;
|
|
if (n < 1) n = 1;
|
|
fixed_width((double)f, n, &d, &p);
|
|
nd = count_digits(d);
|
|
exp = p + nd - 1;
|
|
format_base10(digs, nd, d);
|
|
*s++ = digs[0];
|
|
if (prec > 0 || alt_form) {
|
|
*s++ = '.';
|
|
for (i = 1; i < nd; i++) *s++ = digs[i];
|
|
for (i = nd - 1; i < prec; i++) *s++ = '0';
|
|
}
|
|
s += emit_exp(s, e_char, exp);
|
|
}
|
|
else {
|
|
/* f/F format */
|
|
int exp_est, i;
|
|
union { double d; uint64_t u; } uf;
|
|
uf.d = (double)f;
|
|
exp_est = log10_pow2((int)((uf.u >> 52) & 0x7FF) - 1023);
|
|
|
|
if (exp_est >= buf_remaining) {
|
|
/* too big for f, use e */
|
|
int n = prec + 1;
|
|
if (n > 18) n = 18;
|
|
if (n < 1) n = 1;
|
|
fixed_width((double)f, n, &d, &p);
|
|
nd = count_digits(d);
|
|
exp = p + nd - 1;
|
|
format_base10(digs, nd, d);
|
|
*s++ = digs[0];
|
|
if (prec > 0 || alt_form) {
|
|
*s++ = '.';
|
|
for (i = 1; i < nd; i++) *s++ = digs[i];
|
|
for (i = nd - 1; i < prec; i++) *s++ = '0';
|
|
}
|
|
s += emit_exp(s, e_char, exp);
|
|
}
|
|
else {
|
|
if ((exp_est + prec + 2) > buf_remaining) {
|
|
prec = buf_remaining - exp_est - 2;
|
|
if (prec < 0) prec = 0;
|
|
}
|
|
|
|
if (exp_est + prec <= 17) {
|
|
/* Direct uscale: compute round(f * 10^prec) */
|
|
uint64_t m;
|
|
int e, lp;
|
|
unrounded u;
|
|
unpack64((double)f, &m, &e);
|
|
lp = log2_pow10(prec);
|
|
u = uscale(m, prescale(e, prec, lp));
|
|
d = ur_round(u);
|
|
nd = count_digits(d);
|
|
exp = nd - prec - 1;
|
|
}
|
|
else {
|
|
/* Large number: use fixed_width, pad with zeros */
|
|
int n = 18;
|
|
fixed_width((double)f, n, &d, &p);
|
|
nd = count_digits(d);
|
|
exp = p + nd - 1;
|
|
}
|
|
format_base10(digs, nd, d);
|
|
|
|
if (exp >= 0) {
|
|
for (i = 0; i < nd && i <= exp; i++) *s++ = digs[i];
|
|
for (; i <= exp; i++) *s++ = '0';
|
|
if (prec > 0 || alt_form) {
|
|
int frac_avail = nd - exp - 1;
|
|
if (frac_avail < 0) frac_avail = 0;
|
|
*s++ = '.';
|
|
for (i = 0; i < frac_avail && i < prec; i++) *s++ = digs[exp + 1 + i];
|
|
for (; i < prec; i++) *s++ = '0';
|
|
}
|
|
}
|
|
else {
|
|
int zeros, frac_avail;
|
|
*s++ = '0';
|
|
if (prec > 0 || alt_form) {
|
|
*s++ = '.';
|
|
zeros = -(exp + 1);
|
|
for (i = 0; i < zeros && i < prec; i++) *s++ = '0';
|
|
frac_avail = prec - zeros;
|
|
for (i = 0; i < frac_avail && i < nd; i++) *s++ = digs[i];
|
|
for (; i < frac_avail; i++) *s++ = '0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
*s = '\0';
|
|
return (int)(s - buf);
|
|
}
|
|
|
|
/* ======== mrb_read_float ======== */
|
|
|
|
MRB_API mrb_bool
|
|
mrb_read_float(const char *str, char **endp, double *fp)
|
|
{
|
|
const char *p = str;
|
|
const char *a = p;
|
|
uint64_t d = 0;
|
|
int nd = 0;
|
|
int dp = 0;
|
|
int trunc = 0;
|
|
int sign = 1;
|
|
int any_digits = 0;
|
|
|
|
while (ISSPACE((unsigned char)*p)) p++;
|
|
|
|
if (*p == '-') { sign = -1; p++; }
|
|
else if (*p == '+') p++;
|
|
|
|
/* skip leading zeros */
|
|
while (*p == '0') { p++; any_digits = 1; }
|
|
|
|
/* integer part */
|
|
while (ISDIGIT(*p)) {
|
|
if (nd < 19) {
|
|
d = d * 10 + (*p - '0');
|
|
nd++;
|
|
}
|
|
else {
|
|
trunc++;
|
|
}
|
|
any_digits = 1;
|
|
a = ++p;
|
|
}
|
|
|
|
/* fractional part */
|
|
if (*p == '.') {
|
|
p++;
|
|
if (nd == 0) {
|
|
while (*p == '0') { dp++; p++; any_digits = 1; }
|
|
}
|
|
while (ISDIGIT(*p)) {
|
|
if (nd < 19) {
|
|
d = d * 10 + (*p - '0');
|
|
nd++;
|
|
dp++;
|
|
}
|
|
any_digits = 1;
|
|
p++;
|
|
}
|
|
a = p;
|
|
}
|
|
|
|
if (!any_digits) {
|
|
if (endp) *endp = (char*)str;
|
|
*fp = 0.0;
|
|
return FALSE;
|
|
}
|
|
|
|
/* exponent (optional). On malformed exponent ("5e", "5e+"), keep `a`
|
|
pointing at the 'e' so the caller's *endp reflects where parsing
|
|
stopped, and fall through using the mantissa-only result. */
|
|
int final_p = trunc - dp;
|
|
if ((*p | 32) == 'e') {
|
|
int e = 0;
|
|
int exp_sign = 1;
|
|
p++;
|
|
if (*p == '-') { exp_sign = -1; p++; }
|
|
else if (*p == '+') p++;
|
|
|
|
if (ISDIGIT(*p)) {
|
|
while (ISDIGIT(*p)) {
|
|
if (e < 10000) e = e * 10 + (*p - '0');
|
|
p++;
|
|
}
|
|
final_p += e * exp_sign;
|
|
a = p;
|
|
}
|
|
}
|
|
|
|
{
|
|
double res;
|
|
if (d == 0) {
|
|
res = 0.0;
|
|
}
|
|
else if (final_p > 308) {
|
|
res = HUGE_VAL;
|
|
}
|
|
else if (final_p < -342 - nd) {
|
|
res = 0.0;
|
|
}
|
|
else {
|
|
res = parse_decimal(d, final_p);
|
|
}
|
|
if (sign < 0) res = -res;
|
|
*fp = res;
|
|
}
|
|
|
|
if (endp) *endp = (char*)a;
|
|
return TRUE;
|
|
}
|
|
|
|
#endif /* MRB_NO_FLOAT */
|