Source: binary64.js

/***
 * @license
 * https://github.com/ealmansi/elen
 * Copyright (c) 2017 Emilio Almansi
 * Distributed under the MIT software license, see the accompanying
 * file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 */

const MAX_EXPONENT = 2047
const MAX_MANTISSA = 4503599627370495

/**
 * Constructs a JavaScript number given the values for the sign, exponent,
 * and mantissa in its binary64 representation.
 * 
 * @param {object} - Containing: sign, exponent, mantissa.  
 */
function construct({ sign, exponent, mantissa }) {
  const buffer = new ArrayBuffer(8)
  const floatArray = new Float64Array(buffer)
  const intArray = new Uint8Array(buffer)
  set_sign(sign, intArray)
  set_exponent(exponent, intArray)
  set_mantissa(mantissa, intArray)
  return floatArray[0]
}

/**
 * Returns an object with the values for the sign, exponent, and mantissa
 * in the binary64 representation of the number n.
 * 
 * @param {number} n 
 * @returns {object}
 * @throws {InvalidArgumentException}
 */
function deconstruct(n) {
  const buffer = new ArrayBuffer(8)
  const floatArray = new Float64Array(buffer)
  const intArray = new Uint8Array(buffer)
  floatArray[0] = n
  return {
    sign: getSign(intArray),
    exponent: getExponent(intArray),
    mantissa: getMantissa(intArray),
  }
}

function getSign(intArray) {
  return intArray[7] >> 7
}

function set_sign(sign, intArray) {
  intArray[7] |= (sign << 7)
}

function getExponent(intArray) {
  let r = 0
  r += (intArray[7] & 0x7F) << 4
  r += intArray[6] >> 4
  return r
}

function set_exponent(exponent, intArray) {
  intArray[7] |= exponent >> 4
  intArray[6] |= (exponent & 0xF) << 4
}

function getMantissa(intArray) {
  let r = 0
  r += (intArray[6] & 0x0F) * Math.pow(2, 48)
  r += intArray[5] * Math.pow(2, 40)
  r += intArray[4] * Math.pow(2, 32)
  r += intArray[3] * Math.pow(2, 24)
  r += intArray[2] * Math.pow(2, 16)
  r += intArray[1] * Math.pow(2, 8)
  r += intArray[0]
  return r
}

function set_mantissa(mantissa, intArray) {
  intArray[6] |= (mantissa / Math.pow(2, 48)) & 0xFF
  intArray[5] |= (mantissa / Math.pow(2, 40)) & 0xFF
  intArray[4] |= (mantissa / Math.pow(2, 32)) & 0xFF
  intArray[3] |= (mantissa / Math.pow(2, 24)) & 0xFF
  intArray[2] |= (mantissa / Math.pow(2, 16)) & 0xFF
  intArray[1] |= (mantissa / Math.pow(2, 8)) & 0xFF
  intArray[0] |= mantissa & 0xFF
}

module.exports = { MAX_EXPONENT, MAX_MANTISSA, construct, deconstruct }