| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- 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)
- }
- })()
|