1 | 'use strict';
|
---|
2 |
|
---|
3 | var GetIntrinsic = require('get-intrinsic');
|
---|
4 |
|
---|
5 | var $parseInt = GetIntrinsic('%parseInt%');
|
---|
6 | var $abs = GetIntrinsic('%Math.abs%');
|
---|
7 | var $floor = GetIntrinsic('%Math.floor%');
|
---|
8 |
|
---|
9 | var callBound = require('call-bind/callBound');
|
---|
10 |
|
---|
11 | var $strIndexOf = callBound('String.prototype.indexOf');
|
---|
12 | var $strSlice = callBound('String.prototype.slice');
|
---|
13 |
|
---|
14 | var fractionToBitString = require('../helpers/fractionToBinaryString');
|
---|
15 | var intToBinString = require('../helpers/intToBinaryString');
|
---|
16 | var isNegativeZero = require('./isNegativeZero');
|
---|
17 |
|
---|
18 | var float64bias = 1023;
|
---|
19 |
|
---|
20 | var elevenOnes = '11111111111';
|
---|
21 | var elevenZeroes = '00000000000';
|
---|
22 | var fiftyOneZeroes = elevenZeroes + elevenZeroes + elevenZeroes + elevenZeroes + '0000000';
|
---|
23 |
|
---|
24 | // IEEE 754-1985
|
---|
25 | module.exports = function valueToFloat64Bytes(value, isLittleEndian) {
|
---|
26 | var signBit = value < 0 || isNegativeZero(value) ? '1' : '0';
|
---|
27 | var exponentBits;
|
---|
28 | var significandBits;
|
---|
29 |
|
---|
30 | if (isNaN(value)) {
|
---|
31 | exponentBits = elevenOnes;
|
---|
32 | significandBits = '1' + fiftyOneZeroes;
|
---|
33 | } else if (!isFinite(value)) {
|
---|
34 | exponentBits = elevenOnes;
|
---|
35 | significandBits = '0' + fiftyOneZeroes;
|
---|
36 | } else if (value === 0) {
|
---|
37 | exponentBits = elevenZeroes;
|
---|
38 | significandBits = '0' + fiftyOneZeroes;
|
---|
39 | } else {
|
---|
40 | value = $abs(value); // eslint-disable-line no-param-reassign
|
---|
41 |
|
---|
42 | // Isolate the integer part (digits before the decimal):
|
---|
43 | var integerPart = $floor(value);
|
---|
44 |
|
---|
45 | var intBinString = intToBinString(integerPart); // bit string for integer part
|
---|
46 | var fracBinString = fractionToBitString(value - integerPart); // bit string for fractional part
|
---|
47 |
|
---|
48 | var numberOfBits;
|
---|
49 | // find exponent needed to normalize integer+fractional parts
|
---|
50 | if (intBinString) {
|
---|
51 | exponentBits = intBinString.length - 1; // move the decimal to the left
|
---|
52 | } else {
|
---|
53 | var first1 = $strIndexOf(fracBinString, '1');
|
---|
54 | if (first1 > -1) {
|
---|
55 | numberOfBits = first1 + 1;
|
---|
56 | }
|
---|
57 | exponentBits = -numberOfBits; // move the decimal to the right
|
---|
58 | }
|
---|
59 |
|
---|
60 | significandBits = intBinString + fracBinString;
|
---|
61 | if (exponentBits < 0) {
|
---|
62 | // subnormals
|
---|
63 | if (exponentBits <= -float64bias) {
|
---|
64 | numberOfBits = float64bias - 1; // limit number of removed bits
|
---|
65 | }
|
---|
66 | significandBits = $strSlice(significandBits, numberOfBits); // remove all leading 0s and the first 1 for normal values; for subnormals, remove up to `float64bias - 1` leading bits
|
---|
67 | } else {
|
---|
68 | significandBits = $strSlice(significandBits, 1); // remove the leading '1' (implicit/hidden bit)
|
---|
69 | }
|
---|
70 | exponentBits = $strSlice(elevenZeroes + intToBinString(exponentBits + float64bias), -11); // Convert the exponent to a bit string
|
---|
71 |
|
---|
72 | significandBits = $strSlice(significandBits + fiftyOneZeroes + '0', 0, 52); // fill in any trailing zeros and ensure we have only 52 fraction bits
|
---|
73 | }
|
---|
74 |
|
---|
75 | var bits = signBit + exponentBits + significandBits;
|
---|
76 | var rawBytes = [];
|
---|
77 | for (var i = 0; i < 8; i++) {
|
---|
78 | var targetIndex = isLittleEndian ? 8 - i - 1 : i;
|
---|
79 | rawBytes[targetIndex] = $parseInt($strSlice(bits, i * 8, (i + 1) * 8), 2);
|
---|
80 | }
|
---|
81 |
|
---|
82 | return rawBytes;
|
---|
83 | };
|
---|