'use strict'; var GetIntrinsic = require('get-intrinsic'); var $parseInt = GetIntrinsic('%parseInt%'); var $abs = GetIntrinsic('%Math.abs%'); var $floor = GetIntrinsic('%Math.floor%'); var callBound = require('call-bind/callBound'); var $strIndexOf = callBound('String.prototype.indexOf'); var $strSlice = callBound('String.prototype.slice'); var fractionToBitString = require('../helpers/fractionToBinaryString'); var intToBinString = require('../helpers/intToBinaryString'); var isNegativeZero = require('./isNegativeZero'); var float64bias = 1023; var elevenOnes = '11111111111'; var elevenZeroes = '00000000000'; var fiftyOneZeroes = elevenZeroes + elevenZeroes + elevenZeroes + elevenZeroes + '0000000'; // IEEE 754-1985 module.exports = function valueToFloat64Bytes(value, isLittleEndian) { var signBit = value < 0 || isNegativeZero(value) ? '1' : '0'; var exponentBits; var significandBits; if (isNaN(value)) { exponentBits = elevenOnes; significandBits = '1' + fiftyOneZeroes; } else if (!isFinite(value)) { exponentBits = elevenOnes; significandBits = '0' + fiftyOneZeroes; } else if (value === 0) { exponentBits = elevenZeroes; significandBits = '0' + fiftyOneZeroes; } else { value = $abs(value); // eslint-disable-line no-param-reassign // Isolate the integer part (digits before the decimal): var integerPart = $floor(value); var intBinString = intToBinString(integerPart); // bit string for integer part var fracBinString = fractionToBitString(value - integerPart); // bit string for fractional part var numberOfBits; // find exponent needed to normalize integer+fractional parts if (intBinString) { exponentBits = intBinString.length - 1; // move the decimal to the left } else { var first1 = $strIndexOf(fracBinString, '1'); if (first1 > -1) { numberOfBits = first1 + 1; } exponentBits = -numberOfBits; // move the decimal to the right } significandBits = intBinString + fracBinString; if (exponentBits < 0) { // subnormals if (exponentBits <= -float64bias) { numberOfBits = float64bias - 1; // limit number of removed bits } significandBits = $strSlice(significandBits, numberOfBits); // remove all leading 0s and the first 1 for normal values; for subnormals, remove up to `float64bias - 1` leading bits } else { significandBits = $strSlice(significandBits, 1); // remove the leading '1' (implicit/hidden bit) } exponentBits = $strSlice(elevenZeroes + intToBinString(exponentBits + float64bias), -11); // Convert the exponent to a bit string significandBits = $strSlice(significandBits + fiftyOneZeroes + '0', 0, 52); // fill in any trailing zeros and ensure we have only 52 fraction bits } var bits = signBit + exponentBits + significandBits; var rawBytes = []; for (var i = 0; i < 8; i++) { var targetIndex = isLittleEndian ? 8 - i - 1 : i; rawBytes[targetIndex] = $parseInt($strSlice(bits, i * 8, (i + 1) * 8), 2); } return rawBytes; };