ieee754.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. 'use strict';
  2. // IEEE754 conversions based on https://github.com/feross/ieee754
  3. var sign = require('../internals/math-sign');
  4. var trunc = require('../internals/math-trunc');
  5. var $Array = Array;
  6. var abs = Math.abs;
  7. var pow = Math.pow;
  8. var floor = Math.floor;
  9. var log = Math.log;
  10. var LN2 = Math.LN2;
  11. var roundToEven = function (number) {
  12. var truncated = trunc(number);
  13. var delta = abs(number - truncated);
  14. if (delta > 0.5 || delta === 0.5 && truncated % 2 !== 0) {
  15. return truncated + sign(number);
  16. } return truncated;
  17. };
  18. var pack = function (number, mantissaLength, bytes) {
  19. var buffer = $Array(bytes);
  20. var exponentLength = bytes * 8 - mantissaLength - 1;
  21. var eMax = (1 << exponentLength) - 1;
  22. var eBias = eMax >> 1;
  23. var rt = mantissaLength === 23 ? pow(2, -24) - pow(2, -77) : 0;
  24. var s = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
  25. var index = 0;
  26. var exponent, mantissa, c;
  27. number = abs(number);
  28. // eslint-disable-next-line no-self-compare -- NaN check
  29. if (number !== number || number === Infinity) {
  30. // eslint-disable-next-line no-self-compare -- NaN check
  31. mantissa = number !== number ? 1 : 0;
  32. exponent = eMax;
  33. } else {
  34. exponent = floor(log(number) / LN2);
  35. c = pow(2, -exponent);
  36. if (number * c < 1) {
  37. exponent--;
  38. c *= 2;
  39. }
  40. if (exponent + eBias >= 1) {
  41. number += rt / c;
  42. } else {
  43. number += rt * pow(2, 1 - eBias);
  44. }
  45. if (number * c >= 2) {
  46. exponent++;
  47. c /= 2;
  48. }
  49. if (exponent + eBias >= eMax) {
  50. mantissa = 0;
  51. exponent = eMax;
  52. } else if (exponent + eBias >= 1) {
  53. mantissa = roundToEven((number * c - 1) * pow(2, mantissaLength));
  54. exponent = exponent + eBias;
  55. } else {
  56. mantissa = roundToEven(number * pow(2, eBias - 1) * pow(2, mantissaLength));
  57. exponent = 0;
  58. }
  59. }
  60. while (mantissaLength >= 8) {
  61. buffer[index++] = mantissa & 255;
  62. mantissa /= 256;
  63. mantissaLength -= 8;
  64. }
  65. exponent = exponent << mantissaLength | mantissa;
  66. exponentLength += mantissaLength;
  67. while (exponentLength > 0) {
  68. buffer[index++] = exponent & 255;
  69. exponent /= 256;
  70. exponentLength -= 8;
  71. }
  72. buffer[--index] |= s * 128;
  73. return buffer;
  74. };
  75. var unpack = function (buffer, mantissaLength) {
  76. var bytes = buffer.length;
  77. var exponentLength = bytes * 8 - mantissaLength - 1;
  78. var eMax = (1 << exponentLength) - 1;
  79. var eBias = eMax >> 1;
  80. var nBits = exponentLength - 7;
  81. var index = bytes - 1;
  82. var s = buffer[index--];
  83. var exponent = s & 127;
  84. var mantissa;
  85. s >>= 7;
  86. while (nBits > 0) {
  87. exponent = exponent * 256 + buffer[index--];
  88. nBits -= 8;
  89. }
  90. mantissa = exponent & (1 << -nBits) - 1;
  91. exponent >>= -nBits;
  92. nBits += mantissaLength;
  93. while (nBits > 0) {
  94. mantissa = mantissa * 256 + buffer[index--];
  95. nBits -= 8;
  96. }
  97. if (exponent === 0) {
  98. exponent = 1 - eBias;
  99. } else if (exponent === eMax) {
  100. return mantissa ? NaN : s ? -Infinity : Infinity;
  101. } else {
  102. mantissa = mantissa + pow(2, mantissaLength);
  103. exponent = exponent - eBias;
  104. } return (s ? -1 : 1) * mantissa * pow(2, exponent - mantissaLength);
  105. };
  106. module.exports = {
  107. pack: pack,
  108. unpack: unpack
  109. };