import Long from './Long' export default function Double() { } Double.NaN = NaN Double.isNaN = n => Number.isNaN(n) Double.isInfinite = n => !Number.isFinite(n) Double.MAX_VALUE = Number.MAX_VALUE Double.POSITIVE_INFINITY = Number.POSITIVE_INFINITY Double.NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY if (typeof Float64Array === 'function' && typeof Int32Array === 'function') // Simple and fast conversion between double and long bits // using TypedArrays and ArrayViewBuffers. (function() { const EXP_BIT_MASK = 0x7ff00000 const SIGNIF_BIT_MASK = 0xFFFFF const f64buf = new Float64Array(1) const i32buf = new Int32Array(f64buf.buffer) Double.doubleToLongBits = function(value) { f64buf[0] = value let low = i32buf[0] | 0 let high = i32buf[1] | 0 // Check for NaN based on values of bit fields, maximum // exponent and nonzero significand. if (((high & EXP_BIT_MASK) === EXP_BIT_MASK) && ((high & SIGNIF_BIT_MASK) !== 0) && (low !== 0)) { low = 0 | 0 high = 0x7ff80000 | 0 } return new Long(high, low) } Double.longBitsToDouble = function(bits) { i32buf[0] = bits.low i32buf[1] = bits.high return f64buf[0] } })() else // More complex and slower fallback implementation using // math and the divide-by-two and multiply-by-two algorithms. (function() { const BIAS = 1023 const log2 = Math.log2 const floor = Math.floor const pow = Math.pow const MAX_REL_BITS_INTEGER = (function() { for (let i = 53; i > 0; i--) { const bits = pow(2, i) - 1 if (floor(log2(bits)) + 1 === i) return bits } return 0 })() Double.doubleToLongBits = function(value) { let x, y, f, bits, skip let sign, exp, high, low // Get the sign bit and absolute value. if (value < 0 || 1 / value === Number.NEGATIVE_INFINITY) { sign = (1 << 31) value = (-value) } else { sign = 0 } // Handle some special values. if (value === 0) { // Handle zeros (+/-0). low = 0 | 0 high = sign // exponent: 00..00, significand: 00..00 return new Long(high, low) } if (value === Infinity) { // Handle infinity (only positive values for value possible). low = 0 | 0 high = sign | 0x7ff00000 // exponent: 11..11, significand: 00..00 return new Long(high, low) } if (value !== value) { // eslint-disable-line // Handle NaNs (boiled down to only one distinct NaN). low = 0 | 0 high = 0x7ff80000 // exponent: 11..11, significand: 10..00 return new Long(high, low) } // Preinitialize variables, that are not neccessarily set by // the algorithm. bits = 0 low = 0 | 0 // Get the (always positive) integer part of value. x = floor(value) // Process the integer part if it's greater than 1. Zero requires // no bits at all, 1 represents the implicit (hidden) leading bit, // which must not be written as well. if (x > 1) // If we can reliably determine the number of bits required for // the integer part, if (x <= MAX_REL_BITS_INTEGER) { // get the number of bits required to represent it minus 1 bits = floor(log2(x)) /* + 1 - 1 */ // and simply copy/shift the integer bits into low and high. // That's much faster than the divide-by-two algorithm (saves // up to ~60%). // We always need to mask out the most significant bit, which // is the implicit (aka hidden) bit. if (bits <= 20) { // The simple case in which the integer fits into the // lower 20 bits of the high word is worth to be handled // separately (saves ~25%). low = 0 | 0 high = (x << (20 - bits)) & 0xfffff } else { // Here, the integer part is split into low and high. // Since its value may require more than 32 bits, we // cannot use bitwise operators (which implicitly cast // to Int32), but use arithmetic operators % and / to // get low and high parts. The uppper 20 bits go to high, // the remaining bits (in f) to low. f = bits - 20 // Like (1 << f) but safe with even more than 32 bits. y = pow(2, f) low = (x % y) << (32 - f) high = (x / y) & 0xfffff } } else { // For greater values, we must use the much slower divide-by-two // algorithm. Bits are generated from right to left, that is from // least to most significant bit. For each bit, we left-shift both // low and high by one and carry bit #0 from high to #31 in low. // The next bit is then copied into bit #19 in high, the leftmost // bit of the double's significand. // Preserve x for later user, so work with f. f = x low = 0 | 0 for (;;) { y = f / 2 f = floor(y) if (f === 0) // We just found the most signigicant (1-)bit, which // is the implicit bit and so, not stored in the double // value. So, it's time to leave the loop. break // Count this bit, shift low and carry bit #0 from high. bits++ low >>>= 1 low |= (high & 0x1) << 31 // Shift high. high >>>= 1 if (y !== f) // Copy the new bit into bit #19 in high (only required if 1). high |= 0x80000 } } // Bias the exponent. exp = bits + BIAS // If the integer part is zero, we've not yet seen the implicit // leading bit. Variable skip is later used while processing the // fractional part (if any). skip = (x === 0) // Get fraction only into x. x = value - x // If some significand bits are still left to be filled and // the fractional part is not zero, convert the fraction using // the multiply-by-2 algorithm. if (bits < 52 && x !== 0) { // Initialize 'buffer' f, into which newly created bits get // shifted from right to left. f = 0 for (;;) { y = x * 2 if (y >= 1) { // This is a new 1-bit. Add and count this bit, if not // prohibited by skip. x = y - 1 if (!skip) { f <<= 1 f |= 1 bits++ } else { // Otherwise, decrement the exponent and unset // skip, so that all following bits get written. exp-- skip = false } } else { // This is a new 0-bit. Add and count this bit, if not // prohibited by skip. x = y if (!skip) { f <<= 1 bits++ } else if (--exp === 0) { // Otherwise we've just decremented the exponent. If the // biased exponent is zero now (-1023), we process a // subnormal number, which has no impled leading 1-bit. // So, count this 0-bit and unset skip to write out // all the following bits. bits++ skip = false } } if (bits === 20) { // When 20 bits have been created in total, we're done with // the high word. Copy the bits from 'buffer' f into high // and reset 'buffer' f. Following bits will end up in the // low word. high |= f f = 0 } else if (bits === 52) { // When 52 bits have been created in total, we're done with // low word as well. Copy the bits from 'buffer' f into low // and exit the loop. low |= f break } if (y === 1) { // When y is exactly 1, there is no remainder and the process // is complete (the number is finite). Copy the bits from // 'buffer' f into either low or high and exit the loop. if (bits < 20) high |= (f << (20 - bits)) else if (bits < 52) low |= (f << (52 - bits)) break } } } // Copy/shift the exponent and sign bits into the high word. high |= (exp << 20) high |= sign return new Long(high, low) } Double.longBitsToDouble = function(bits) { let i let x, exp, fract const high = bits.high const low = bits.low // Extract the sign. const sign = (high & (1 << 31)) ? -1 : 1 // Extract the unbiased exponent. exp = ((high & 0x7ff00000) >> 20) - BIAS // Calculate the fraction from left to right. Start // off with the 20 lower bits from the high word. fract = 0 x = (1 << 19) for (i = 1; i <= 20; i++) { if (high & x) fract += pow(2, -i) x >>>= 1 } // Continue with all 32 bits from the low word. x = (1 << 31) for (i = 21; i <= 52; i++) { if (low & x) fract += pow(2, -i) x >>>= 1 } // Handle special values. // Check for zero and subnormal values. if (exp === -BIAS) { if (fract === 0) // +/-1.0 * 0.0 => +/-0.0 return sign * 0 exp = -1022 } else if (exp === BIAS + 1) { // Check for +/-Infinity or NaN. if (fract === 0) // +/-1.0 / 0.0 => +/-Infinity return sign / 0 return NaN } else { // Nothing special? Seems to be a normal number. // Add the implicit leading bit (1*2^0). fract += 1 } return sign * fract * pow(2, exp) } })()