Passed
Push — master ( 4f5e17...a51297 )
by Rafael S.
01:37
created

float.js ➔ decodeFloat64   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 19
rs 8.8571
1
/*
2
 * float: Functions to work with 16, 32 & 64 bit floats.
3
 * Copyright (c) 2017 Rafael da Silva Rocha.
4
 * https://github.com/rochars/byte-data
5
 */
6
7
function getBinary(bytes, rev=false) {
8
    let binary = "";
9
    let bits;
10
    let i = 0;
11
    let bytesLength = bytes.length;
12
    while(i < bytesLength) {
13
        bits = bytes[i].toString(2);
14
        while (bits.length < 8) {
15
            bits = "0" + bits;
16
        }
17
        if (rev) {
18
            binary = binary + bits;
19
        } else {
20
            binary = bits + binary;
21
        }
22
        i++;
23
    }
24
    return binary;
25
}
26
27
/**
28
 * Turn bytes to a float 16..
29
 * Thanks https://stackoverflow.com/a/8796597
30
 * @param {number} bytes 2 bytes representing a float 16.
31
 */
32
function decodeFloat16 (bytes) {
33
    let binary = parseInt(getBinary(bytes, true), 2);
34
    let exponent = (binary & 0x7C00) >> 10,
35
        fraction = binary & 0x03FF;
36
    return (binary >> 15 ? -1 : 1) * (
37
        exponent ?
38
        (
39
            exponent === 0x1F ?
40
            fraction ? NaN : Infinity :
41
            Math.pow(2, exponent - 15) * (1 + fraction / 0x400)
42
        ) :
43
        6.103515625e-5 * (fraction / 0x400)
44
    );
45
}
46
47
/**
48
 * Turn an array of bytes into a float 64.
49
 * Thanks https://gist.github.com/kg/2192799
50
 * @param {!Array<number>} bytes 8 bytes representing a float 64.
51
 */
52
function decodeFloat64(bytes) {
53
    if (bytes.toString() == "0,0,0,0,0,0,0,0") {
54
        return 0;
55
    }
56
    let binary = getBinary(bytes);
57
    let significandBin = "1" + binary.substr(1 + 11, 52);
58
    let val = 1;
59
    let significand = 0;
60
    let i = 0;
61
    while (i < significandBin.length) {
62
        significand += val * parseInt(significandBin.charAt(i), 10);
63
        val = val / 2;
64
        i++;
65
    }
66
    let sign = (binary.charAt(0) == "1") ? -1 : 1;
67
    let doubleValue = sign * significand *
68
        Math.pow(2, parseInt(binary.substr(1, 11), 2) - 1023);
69
    return doubleValue === 2 ? 0 : doubleValue;
70
}
71
72
/**
73
 * Unpack a 64 bit float into two words.
74
 * Thanks https://stackoverflow.com/a/16043259
75
 * @param {number} value A float64 number.
76
 */
77
function toFloat64(value) {
78
    if (value == 0) {
79
        return [0, 0];
80
    }
81
    let hiWord = 0;
82
    let loWord = 0;
83
    if (value <= 0.0) {
84
        hiWord = 0x80000000;
85
        value = -value;
86
    }
87
    let exponent = Math.floor(
88
        Math.log(value) / Math.log(2));
89
    let significand = Math.floor(
90
        (value / Math.pow(2, exponent)) * Math.pow(2, 52));
91
    loWord = significand & 0xFFFFFFFF;
92
    significand /= Math.pow(2, 32);
93
    exponent += 1023;
94
    hiWord = hiWord | (exponent << 20);
95
    hiWord = hiWord | (significand & ~(-1 << 20));
96
    return [hiWord, loWord];
97
}
98
99
let floatView = new Float32Array(1);
100
let int32View = new Int32Array(floatView.buffer);
101
102
/*!
103
 * to-half: int bits of half-precision floating point values
104
 * Based on:
105
 * https://mail.mozilla.org/pipermail/es-discuss/2017-April/047994.html
106
 * https://github.com/rochars/byte-data
107
 */
108
function toHalf(val) {
109
    floatView[0] = val;
110
    let x = int32View[0];
111
    let bits = (x >> 16) & 0x8000;
112
    let m = (x >> 12) & 0x07ff;
113
    let e = (x >> 23) & 0xff;
114
    if (e < 103) {
115
        return bits;
116
    }
117
    bits |= ((e - 112) << 10) | (m >> 1);
118
    bits += m & 1;
119
    return bits;
120
}
121
122
module.exports.getBinary = getBinary;
123
module.exports.decodeFloat16 = decodeFloat16;
124
module.exports.decodeFloat64 = decodeFloat64;
125
module.exports.toFloat64 = toFloat64;
126
module.exports.toHalf = toHalf;
127