mirror of
https://github.com/isar/libmdbx.git
synced 2025-04-28 07:42:26 +08:00
mdbx: avoud int64-to-double conversion key_from_jsonInteger().
More for https://github.com/leo-yuriev/libmdbx/issues/76 This is expected to be a workaround for the MSVC2019 bug "MSVCRT.lib(ftol3.obj) : error LNK2001: unresolved external symbol __except1". https://ci.appveyor.com/project/leo-yuriev/libmdbx/builds/30273569/job/lurrftum1nkbu5a3#L109 Change-Id: Ie6da02b14d0b973c7172af063caf4fdc44bf89ac
This commit is contained in:
parent
b77f4faadd
commit
ebcbcbfe31
@ -17377,8 +17377,7 @@ uint32_t mdbx_key_from_ptrfloat(const float *const ieee754_32bit) {
|
|||||||
#define IEEE754_DOUBLE_MAX 0x7FF
|
#define IEEE754_DOUBLE_MAX 0x7FF
|
||||||
#define IEEE754_DOUBLE_IMPLICIT_LEAD UINT64_C(0x0010000000000000)
|
#define IEEE754_DOUBLE_IMPLICIT_LEAD UINT64_C(0x0010000000000000)
|
||||||
#define IEEE754_DOUBLE_MANTISSA_MASK UINT64_C(0x000FFFFFFFFFFFFF)
|
#define IEEE754_DOUBLE_MANTISSA_MASK UINT64_C(0x000FFFFFFFFFFFFF)
|
||||||
#define JSON_MAX_SAFE_INTEGER ((INT64_C(1) << 53) - 1)
|
#define IEEE754_DOUBLE_MANTISSA_AMAX UINT64_C(0x001FFFFFFFFFFFFF)
|
||||||
#define JSON_MIN_SAFE_INTEGER (-JSON_MAX_SAFE_INTEGER)
|
|
||||||
|
|
||||||
static __inline int clz64(uint64_t value) {
|
static __inline int clz64(uint64_t value) {
|
||||||
#if __GNUC_PREREQ(4, 1) || __has_builtin(__builtin_clzl)
|
#if __GNUC_PREREQ(4, 1) || __has_builtin(__builtin_clzl)
|
||||||
@ -17421,21 +17420,31 @@ static __inline int clz64(uint64_t value) {
|
|||||||
return debruijn_clz64[value * UINT64_C(0x03F79D71B4CB0A89) >> 58];
|
return debruijn_clz64[value * UINT64_C(0x03F79D71B4CB0A89) >> 58];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t round_mantissa(const uint64_t u64, int shift) {
|
||||||
|
assert(shift < 0 && u64 > 0);
|
||||||
|
shift = -shift;
|
||||||
|
const unsigned half = 1 << (shift - 1);
|
||||||
|
const unsigned lsb = 1 & (unsigned)(u64 >> shift);
|
||||||
|
const unsigned tie2even = 1 ^ lsb;
|
||||||
|
return (u64 + half - tie2even) >> shift;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t mdbx_key_from_jsonInteger(const int64_t json_integer) {
|
uint64_t mdbx_key_from_jsonInteger(const int64_t json_integer) {
|
||||||
const uint64_t biased_zero = UINT64_C(0x8000000000000000);
|
const uint64_t biased_zero = UINT64_C(0x8000000000000000);
|
||||||
if (json_integer > 0) {
|
if (json_integer > 0) {
|
||||||
if (unlikely(json_integer > JSON_MAX_SAFE_INTEGER))
|
|
||||||
goto fallback;
|
|
||||||
const uint64_t u64 = json_integer;
|
const uint64_t u64 = json_integer;
|
||||||
const int extra_zeros =
|
int shift = clz64(u64) - (64 - IEEE754_DOUBLE_MANTISSA_SIZE - 1);
|
||||||
clz64(u64) - (64 - IEEE754_DOUBLE_MANTISSA_SIZE - 1);
|
uint64_t mantissa = u64 << shift;
|
||||||
assert(extra_zeros >= 0);
|
if (unlikely(shift < 0)) {
|
||||||
const uint64_t mantissa = u64 << extra_zeros;
|
mantissa = round_mantissa(u64, shift);
|
||||||
assert(mantissa >= IEEE754_DOUBLE_IMPLICIT_LEAD);
|
if (mantissa > IEEE754_DOUBLE_MANTISSA_AMAX)
|
||||||
assert(mantissa <=
|
mantissa = round_mantissa(u64, --shift);
|
||||||
IEEE754_DOUBLE_MANTISSA_MASK + IEEE754_DOUBLE_IMPLICIT_LEAD);
|
}
|
||||||
|
|
||||||
|
assert(mantissa >= IEEE754_DOUBLE_IMPLICIT_LEAD &&
|
||||||
|
mantissa <= IEEE754_DOUBLE_MANTISSA_AMAX);
|
||||||
const uint64_t exponent =
|
const uint64_t exponent =
|
||||||
IEEE754_DOUBLE_BIAS + IEEE754_DOUBLE_MANTISSA_SIZE - extra_zeros;
|
IEEE754_DOUBLE_BIAS + IEEE754_DOUBLE_MANTISSA_SIZE - shift;
|
||||||
assert(exponent > 0 && exponent <= IEEE754_DOUBLE_MAX);
|
assert(exponent > 0 && exponent <= IEEE754_DOUBLE_MAX);
|
||||||
const uint64_t key = biased_zero +
|
const uint64_t key = biased_zero +
|
||||||
(exponent << IEEE754_DOUBLE_MANTISSA_SIZE) +
|
(exponent << IEEE754_DOUBLE_MANTISSA_SIZE) +
|
||||||
@ -17445,18 +17454,19 @@ uint64_t mdbx_key_from_jsonInteger(const int64_t json_integer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (json_integer < 0) {
|
if (json_integer < 0) {
|
||||||
if (unlikely(json_integer < JSON_MIN_SAFE_INTEGER))
|
|
||||||
goto fallback;
|
|
||||||
const uint64_t u64 = -json_integer;
|
const uint64_t u64 = -json_integer;
|
||||||
const int extra_zeros =
|
int shift = clz64(u64) - (64 - IEEE754_DOUBLE_MANTISSA_SIZE - 1);
|
||||||
clz64(u64) - (64 - IEEE754_DOUBLE_MANTISSA_SIZE - 1);
|
uint64_t mantissa = u64 << shift;
|
||||||
assert(extra_zeros >= 0);
|
if (unlikely(shift < 0)) {
|
||||||
const uint64_t mantissa = u64 << extra_zeros;
|
mantissa = round_mantissa(u64, shift);
|
||||||
assert(mantissa >= IEEE754_DOUBLE_IMPLICIT_LEAD);
|
if (mantissa > IEEE754_DOUBLE_MANTISSA_AMAX)
|
||||||
assert(mantissa <=
|
mantissa = round_mantissa(u64, --shift);
|
||||||
IEEE754_DOUBLE_MANTISSA_MASK + IEEE754_DOUBLE_IMPLICIT_LEAD);
|
}
|
||||||
|
|
||||||
|
assert(mantissa >= IEEE754_DOUBLE_IMPLICIT_LEAD &&
|
||||||
|
mantissa <= IEEE754_DOUBLE_MANTISSA_AMAX);
|
||||||
const uint64_t exponent =
|
const uint64_t exponent =
|
||||||
IEEE754_DOUBLE_BIAS + IEEE754_DOUBLE_MANTISSA_SIZE - extra_zeros;
|
IEEE754_DOUBLE_BIAS + IEEE754_DOUBLE_MANTISSA_SIZE - shift;
|
||||||
assert(exponent > 0 && exponent <= IEEE754_DOUBLE_MAX);
|
assert(exponent > 0 && exponent <= IEEE754_DOUBLE_MAX);
|
||||||
const uint64_t key = biased_zero -
|
const uint64_t key = biased_zero -
|
||||||
(exponent << IEEE754_DOUBLE_MANTISSA_SIZE) -
|
(exponent << IEEE754_DOUBLE_MANTISSA_SIZE) -
|
||||||
@ -17466,10 +17476,6 @@ uint64_t mdbx_key_from_jsonInteger(const int64_t json_integer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return biased_zero;
|
return biased_zero;
|
||||||
|
|
||||||
fallback:;
|
|
||||||
const double ieee754_64bit = (double)json_integer;
|
|
||||||
return double2key(&ieee754_64bit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** Attribute support functions for Nexenta **********************************/
|
/*** Attribute support functions for Nexenta **********************************/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user