node-red-contrib-tak-registration
Version:
A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK
302 lines (269 loc) • 9.96 kB
JavaScript
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)
}
})()