| 1 | 'use strict';
|
|---|
| 2 |
|
|---|
| 3 | var $abs = require('math-intrinsics/abs');
|
|---|
| 4 | var $floor = require('math-intrinsics/floor');
|
|---|
| 5 | var $pow = require('math-intrinsics/pow');
|
|---|
| 6 |
|
|---|
| 7 | var isFinite = require('math-intrinsics/isFinite');
|
|---|
| 8 | var isNaN = require('math-intrinsics/isNaN');
|
|---|
| 9 | var isNegativeZero = require('math-intrinsics/isNegativeZero');
|
|---|
| 10 |
|
|---|
| 11 | var maxFiniteFloat16 = 65504; // 2**16 - 2**5
|
|---|
| 12 |
|
|---|
| 13 | module.exports = function valueToFloat16Bytes(value, isLittleEndian) {
|
|---|
| 14 | // NaN → exponent=all-ones, mantissa MSB=1 → 0x7e00
|
|---|
| 15 | if (isNaN(value)) {
|
|---|
| 16 | return isLittleEndian
|
|---|
| 17 | ? [0x00, 0x7e]
|
|---|
| 18 | : [0x7e, 0x00];
|
|---|
| 19 | }
|
|---|
| 20 |
|
|---|
| 21 | var leastSig;
|
|---|
| 22 |
|
|---|
| 23 | // ±0 → just the sign bit
|
|---|
| 24 | if (value === 0) {
|
|---|
| 25 | leastSig = isNegativeZero(value) ? 0x80 : 0x00;
|
|---|
| 26 | return isLittleEndian
|
|---|
| 27 | ? [0x00, leastSig]
|
|---|
| 28 | : [leastSig, 0x00];
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | // ±∞ → exponent=all-ones, mantissa=0 → 0x7c00 or 0xfc00
|
|---|
| 32 | if ($abs(value) > maxFiniteFloat16 || !isFinite(value)) {
|
|---|
| 33 | leastSig = value < 0 ? 0xfc : 0x7c;
|
|---|
| 34 | return isLittleEndian
|
|---|
| 35 | ? [0x00, leastSig]
|
|---|
| 36 | : [leastSig, 0x00];
|
|---|
| 37 | }
|
|---|
| 38 |
|
|---|
| 39 | var sign = value < 0 ? 1 : 0;
|
|---|
| 40 | value = $abs(value); // eslint-disable-line no-param-reassign
|
|---|
| 41 |
|
|---|
| 42 | // normalize to [1,2)
|
|---|
| 43 | var exponent = 0;
|
|---|
| 44 | while (value >= 2) {
|
|---|
| 45 | exponent += 1;
|
|---|
| 46 | value /= 2; // eslint-disable-line no-param-reassign
|
|---|
| 47 | }
|
|---|
| 48 | while (value < 1) {
|
|---|
| 49 | exponent -= 1;
|
|---|
| 50 | value *= 2; // eslint-disable-line no-param-reassign
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 | // build mantissa (10 bits)
|
|---|
| 54 | var mantissa = value - 1;
|
|---|
| 55 | mantissa *= $pow(2, 10) + 0.5;
|
|---|
| 56 | mantissa = $floor(mantissa);
|
|---|
| 57 |
|
|---|
| 58 | // apply bias (15) and shift into place
|
|---|
| 59 | exponent += 15;
|
|---|
| 60 | exponent <<= 10;
|
|---|
| 61 |
|
|---|
| 62 | // pack sign, exponent, mantissa
|
|---|
| 63 | var result = (sign << 15) | exponent | mantissa;
|
|---|
| 64 |
|
|---|
| 65 | // split into two bytes
|
|---|
| 66 | var byte0 = result & 0xFF;
|
|---|
| 67 | result >>= 8;
|
|---|
| 68 | var byte1 = result & 0xFF;
|
|---|
| 69 |
|
|---|
| 70 | return isLittleEndian
|
|---|
| 71 | ? [byte0, byte1]
|
|---|
| 72 | : [byte1, byte0];
|
|---|
| 73 | };
|
|---|