decimal128.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Decimal128 = void 0;
  4. var buffer_1 = require("buffer");
  5. var long_1 = require("./long");
  6. var PARSE_STRING_REGEXP = /^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/;
  7. var PARSE_INF_REGEXP = /^(\+|-)?(Infinity|inf)$/i;
  8. var PARSE_NAN_REGEXP = /^(\+|-)?NaN$/i;
  9. var EXPONENT_MAX = 6111;
  10. var EXPONENT_MIN = -6176;
  11. var EXPONENT_BIAS = 6176;
  12. var MAX_DIGITS = 34;
  13. // Nan value bits as 32 bit values (due to lack of longs)
  14. var NAN_BUFFER = [
  15. 0x7c,
  16. 0x00,
  17. 0x00,
  18. 0x00,
  19. 0x00,
  20. 0x00,
  21. 0x00,
  22. 0x00,
  23. 0x00,
  24. 0x00,
  25. 0x00,
  26. 0x00,
  27. 0x00,
  28. 0x00,
  29. 0x00,
  30. 0x00
  31. ].reverse();
  32. // Infinity value bits 32 bit values (due to lack of longs)
  33. var INF_NEGATIVE_BUFFER = [
  34. 0xf8,
  35. 0x00,
  36. 0x00,
  37. 0x00,
  38. 0x00,
  39. 0x00,
  40. 0x00,
  41. 0x00,
  42. 0x00,
  43. 0x00,
  44. 0x00,
  45. 0x00,
  46. 0x00,
  47. 0x00,
  48. 0x00,
  49. 0x00
  50. ].reverse();
  51. var INF_POSITIVE_BUFFER = [
  52. 0x78,
  53. 0x00,
  54. 0x00,
  55. 0x00,
  56. 0x00,
  57. 0x00,
  58. 0x00,
  59. 0x00,
  60. 0x00,
  61. 0x00,
  62. 0x00,
  63. 0x00,
  64. 0x00,
  65. 0x00,
  66. 0x00,
  67. 0x00
  68. ].reverse();
  69. var EXPONENT_REGEX = /^([-+])?(\d+)?$/;
  70. // Extract least significant 5 bits
  71. var COMBINATION_MASK = 0x1f;
  72. // Extract least significant 14 bits
  73. var EXPONENT_MASK = 0x3fff;
  74. // Value of combination field for Inf
  75. var COMBINATION_INFINITY = 30;
  76. // Value of combination field for NaN
  77. var COMBINATION_NAN = 31;
  78. // Detect if the value is a digit
  79. function isDigit(value) {
  80. return !isNaN(parseInt(value, 10));
  81. }
  82. // Divide two uint128 values
  83. function divideu128(value) {
  84. var DIVISOR = long_1.Long.fromNumber(1000 * 1000 * 1000);
  85. var _rem = long_1.Long.fromNumber(0);
  86. if (!value.parts[0] && !value.parts[1] && !value.parts[2] && !value.parts[3]) {
  87. return { quotient: value, rem: _rem };
  88. }
  89. for (var i = 0; i <= 3; i++) {
  90. // Adjust remainder to match value of next dividend
  91. _rem = _rem.shiftLeft(32);
  92. // Add the divided to _rem
  93. _rem = _rem.add(new long_1.Long(value.parts[i], 0));
  94. value.parts[i] = _rem.div(DIVISOR).low;
  95. _rem = _rem.modulo(DIVISOR);
  96. }
  97. return { quotient: value, rem: _rem };
  98. }
  99. // Multiply two Long values and return the 128 bit value
  100. function multiply64x2(left, right) {
  101. if (!left && !right) {
  102. return { high: long_1.Long.fromNumber(0), low: long_1.Long.fromNumber(0) };
  103. }
  104. var leftHigh = left.shiftRightUnsigned(32);
  105. var leftLow = new long_1.Long(left.getLowBits(), 0);
  106. var rightHigh = right.shiftRightUnsigned(32);
  107. var rightLow = new long_1.Long(right.getLowBits(), 0);
  108. var productHigh = leftHigh.multiply(rightHigh);
  109. var productMid = leftHigh.multiply(rightLow);
  110. var productMid2 = leftLow.multiply(rightHigh);
  111. var productLow = leftLow.multiply(rightLow);
  112. productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
  113. productMid = new long_1.Long(productMid.getLowBits(), 0)
  114. .add(productMid2)
  115. .add(productLow.shiftRightUnsigned(32));
  116. productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
  117. productLow = productMid.shiftLeft(32).add(new long_1.Long(productLow.getLowBits(), 0));
  118. // Return the 128 bit result
  119. return { high: productHigh, low: productLow };
  120. }
  121. function lessThan(left, right) {
  122. // Make values unsigned
  123. var uhleft = left.high >>> 0;
  124. var uhright = right.high >>> 0;
  125. // Compare high bits first
  126. if (uhleft < uhright) {
  127. return true;
  128. }
  129. else if (uhleft === uhright) {
  130. var ulleft = left.low >>> 0;
  131. var ulright = right.low >>> 0;
  132. if (ulleft < ulright)
  133. return true;
  134. }
  135. return false;
  136. }
  137. function invalidErr(string, message) {
  138. throw new TypeError("\"" + string + "\" is not a valid Decimal128 string - " + message);
  139. }
  140. /**
  141. * A class representation of the BSON Decimal128 type.
  142. * @public
  143. */
  144. var Decimal128 = /** @class */ (function () {
  145. /**
  146. * @param bytes - a buffer containing the raw Decimal128 bytes in little endian order,
  147. * or a string representation as returned by .toString()
  148. */
  149. function Decimal128(bytes) {
  150. if (!(this instanceof Decimal128))
  151. return new Decimal128(bytes);
  152. if (typeof bytes === 'string') {
  153. this.bytes = Decimal128.fromString(bytes).bytes;
  154. }
  155. else {
  156. this.bytes = bytes;
  157. }
  158. }
  159. /**
  160. * Create a Decimal128 instance from a string representation
  161. *
  162. * @param representation - a numeric string representation.
  163. */
  164. Decimal128.fromString = function (representation) {
  165. // Parse state tracking
  166. var isNegative = false;
  167. var sawRadix = false;
  168. var foundNonZero = false;
  169. // Total number of significant digits (no leading or trailing zero)
  170. var significantDigits = 0;
  171. // Total number of significand digits read
  172. var nDigitsRead = 0;
  173. // Total number of digits (no leading zeros)
  174. var nDigits = 0;
  175. // The number of the digits after radix
  176. var radixPosition = 0;
  177. // The index of the first non-zero in *str*
  178. var firstNonZero = 0;
  179. // Digits Array
  180. var digits = [0];
  181. // The number of digits in digits
  182. var nDigitsStored = 0;
  183. // Insertion pointer for digits
  184. var digitsInsert = 0;
  185. // The index of the first non-zero digit
  186. var firstDigit = 0;
  187. // The index of the last digit
  188. var lastDigit = 0;
  189. // Exponent
  190. var exponent = 0;
  191. // loop index over array
  192. var i = 0;
  193. // The high 17 digits of the significand
  194. var significandHigh = new long_1.Long(0, 0);
  195. // The low 17 digits of the significand
  196. var significandLow = new long_1.Long(0, 0);
  197. // The biased exponent
  198. var biasedExponent = 0;
  199. // Read index
  200. var index = 0;
  201. // Naively prevent against REDOS attacks.
  202. // TODO: implementing a custom parsing for this, or refactoring the regex would yield
  203. // further gains.
  204. if (representation.length >= 7000) {
  205. throw new TypeError('' + representation + ' not a valid Decimal128 string');
  206. }
  207. // Results
  208. var stringMatch = representation.match(PARSE_STRING_REGEXP);
  209. var infMatch = representation.match(PARSE_INF_REGEXP);
  210. var nanMatch = representation.match(PARSE_NAN_REGEXP);
  211. // Validate the string
  212. if ((!stringMatch && !infMatch && !nanMatch) || representation.length === 0) {
  213. throw new TypeError('' + representation + ' not a valid Decimal128 string');
  214. }
  215. if (stringMatch) {
  216. // full_match = stringMatch[0]
  217. // sign = stringMatch[1]
  218. var unsignedNumber = stringMatch[2];
  219. // stringMatch[3] is undefined if a whole number (ex "1", 12")
  220. // but defined if a number w/ decimal in it (ex "1.0, 12.2")
  221. var e = stringMatch[4];
  222. var expSign = stringMatch[5];
  223. var expNumber = stringMatch[6];
  224. // they provided e, but didn't give an exponent number. for ex "1e"
  225. if (e && expNumber === undefined)
  226. invalidErr(representation, 'missing exponent power');
  227. // they provided e, but didn't give a number before it. for ex "e1"
  228. if (e && unsignedNumber === undefined)
  229. invalidErr(representation, 'missing exponent base');
  230. if (e === undefined && (expSign || expNumber)) {
  231. invalidErr(representation, 'missing e before exponent');
  232. }
  233. }
  234. // Get the negative or positive sign
  235. if (representation[index] === '+' || representation[index] === '-') {
  236. isNegative = representation[index++] === '-';
  237. }
  238. // Check if user passed Infinity or NaN
  239. if (!isDigit(representation[index]) && representation[index] !== '.') {
  240. if (representation[index] === 'i' || representation[index] === 'I') {
  241. return new Decimal128(buffer_1.Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
  242. }
  243. else if (representation[index] === 'N') {
  244. return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
  245. }
  246. }
  247. // Read all the digits
  248. while (isDigit(representation[index]) || representation[index] === '.') {
  249. if (representation[index] === '.') {
  250. if (sawRadix)
  251. invalidErr(representation, 'contains multiple periods');
  252. sawRadix = true;
  253. index = index + 1;
  254. continue;
  255. }
  256. if (nDigitsStored < 34) {
  257. if (representation[index] !== '0' || foundNonZero) {
  258. if (!foundNonZero) {
  259. firstNonZero = nDigitsRead;
  260. }
  261. foundNonZero = true;
  262. // Only store 34 digits
  263. digits[digitsInsert++] = parseInt(representation[index], 10);
  264. nDigitsStored = nDigitsStored + 1;
  265. }
  266. }
  267. if (foundNonZero)
  268. nDigits = nDigits + 1;
  269. if (sawRadix)
  270. radixPosition = radixPosition + 1;
  271. nDigitsRead = nDigitsRead + 1;
  272. index = index + 1;
  273. }
  274. if (sawRadix && !nDigitsRead)
  275. throw new TypeError('' + representation + ' not a valid Decimal128 string');
  276. // Read exponent if exists
  277. if (representation[index] === 'e' || representation[index] === 'E') {
  278. // Read exponent digits
  279. var match = representation.substr(++index).match(EXPONENT_REGEX);
  280. // No digits read
  281. if (!match || !match[2])
  282. return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
  283. // Get exponent
  284. exponent = parseInt(match[0], 10);
  285. // Adjust the index
  286. index = index + match[0].length;
  287. }
  288. // Return not a number
  289. if (representation[index])
  290. return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
  291. // Done reading input
  292. // Find first non-zero digit in digits
  293. firstDigit = 0;
  294. if (!nDigitsStored) {
  295. firstDigit = 0;
  296. lastDigit = 0;
  297. digits[0] = 0;
  298. nDigits = 1;
  299. nDigitsStored = 1;
  300. significantDigits = 0;
  301. }
  302. else {
  303. lastDigit = nDigitsStored - 1;
  304. significantDigits = nDigits;
  305. if (significantDigits !== 1) {
  306. while (representation[firstNonZero + significantDigits - 1] === '0') {
  307. significantDigits = significantDigits - 1;
  308. }
  309. }
  310. }
  311. // Normalization of exponent
  312. // Correct exponent based on radix position, and shift significand as needed
  313. // to represent user input
  314. // Overflow prevention
  315. if (exponent <= radixPosition && radixPosition - exponent > 1 << 14) {
  316. exponent = EXPONENT_MIN;
  317. }
  318. else {
  319. exponent = exponent - radixPosition;
  320. }
  321. // Attempt to normalize the exponent
  322. while (exponent > EXPONENT_MAX) {
  323. // Shift exponent to significand and decrease
  324. lastDigit = lastDigit + 1;
  325. if (lastDigit - firstDigit > MAX_DIGITS) {
  326. // Check if we have a zero then just hard clamp, otherwise fail
  327. var digitsString = digits.join('');
  328. if (digitsString.match(/^0+$/)) {
  329. exponent = EXPONENT_MAX;
  330. break;
  331. }
  332. invalidErr(representation, 'overflow');
  333. }
  334. exponent = exponent - 1;
  335. }
  336. while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
  337. // Shift last digit. can only do this if < significant digits than # stored.
  338. if (lastDigit === 0 && significantDigits < nDigitsStored) {
  339. exponent = EXPONENT_MIN;
  340. significantDigits = 0;
  341. break;
  342. }
  343. if (nDigitsStored < nDigits) {
  344. // adjust to match digits not stored
  345. nDigits = nDigits - 1;
  346. }
  347. else {
  348. // adjust to round
  349. lastDigit = lastDigit - 1;
  350. }
  351. if (exponent < EXPONENT_MAX) {
  352. exponent = exponent + 1;
  353. }
  354. else {
  355. // Check if we have a zero then just hard clamp, otherwise fail
  356. var digitsString = digits.join('');
  357. if (digitsString.match(/^0+$/)) {
  358. exponent = EXPONENT_MAX;
  359. break;
  360. }
  361. invalidErr(representation, 'overflow');
  362. }
  363. }
  364. // Round
  365. // We've normalized the exponent, but might still need to round.
  366. if (lastDigit - firstDigit + 1 < significantDigits) {
  367. var endOfString = nDigitsRead;
  368. // If we have seen a radix point, 'string' is 1 longer than we have
  369. // documented with ndigits_read, so inc the position of the first nonzero
  370. // digit and the position that digits are read to.
  371. if (sawRadix) {
  372. firstNonZero = firstNonZero + 1;
  373. endOfString = endOfString + 1;
  374. }
  375. // if negative, we need to increment again to account for - sign at start.
  376. if (isNegative) {
  377. firstNonZero = firstNonZero + 1;
  378. endOfString = endOfString + 1;
  379. }
  380. var roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
  381. var roundBit = 0;
  382. if (roundDigit >= 5) {
  383. roundBit = 1;
  384. if (roundDigit === 5) {
  385. roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
  386. for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
  387. if (parseInt(representation[i], 10)) {
  388. roundBit = 1;
  389. break;
  390. }
  391. }
  392. }
  393. }
  394. if (roundBit) {
  395. var dIdx = lastDigit;
  396. for (; dIdx >= 0; dIdx--) {
  397. if (++digits[dIdx] > 9) {
  398. digits[dIdx] = 0;
  399. // overflowed most significant digit
  400. if (dIdx === 0) {
  401. if (exponent < EXPONENT_MAX) {
  402. exponent = exponent + 1;
  403. digits[dIdx] = 1;
  404. }
  405. else {
  406. return new Decimal128(buffer_1.Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
  407. }
  408. }
  409. }
  410. }
  411. }
  412. }
  413. // Encode significand
  414. // The high 17 digits of the significand
  415. significandHigh = long_1.Long.fromNumber(0);
  416. // The low 17 digits of the significand
  417. significandLow = long_1.Long.fromNumber(0);
  418. // read a zero
  419. if (significantDigits === 0) {
  420. significandHigh = long_1.Long.fromNumber(0);
  421. significandLow = long_1.Long.fromNumber(0);
  422. }
  423. else if (lastDigit - firstDigit < 17) {
  424. var dIdx = firstDigit;
  425. significandLow = long_1.Long.fromNumber(digits[dIdx++]);
  426. significandHigh = new long_1.Long(0, 0);
  427. for (; dIdx <= lastDigit; dIdx++) {
  428. significandLow = significandLow.multiply(long_1.Long.fromNumber(10));
  429. significandLow = significandLow.add(long_1.Long.fromNumber(digits[dIdx]));
  430. }
  431. }
  432. else {
  433. var dIdx = firstDigit;
  434. significandHigh = long_1.Long.fromNumber(digits[dIdx++]);
  435. for (; dIdx <= lastDigit - 17; dIdx++) {
  436. significandHigh = significandHigh.multiply(long_1.Long.fromNumber(10));
  437. significandHigh = significandHigh.add(long_1.Long.fromNumber(digits[dIdx]));
  438. }
  439. significandLow = long_1.Long.fromNumber(digits[dIdx++]);
  440. for (; dIdx <= lastDigit; dIdx++) {
  441. significandLow = significandLow.multiply(long_1.Long.fromNumber(10));
  442. significandLow = significandLow.add(long_1.Long.fromNumber(digits[dIdx]));
  443. }
  444. }
  445. var significand = multiply64x2(significandHigh, long_1.Long.fromString('100000000000000000'));
  446. significand.low = significand.low.add(significandLow);
  447. if (lessThan(significand.low, significandLow)) {
  448. significand.high = significand.high.add(long_1.Long.fromNumber(1));
  449. }
  450. // Biased exponent
  451. biasedExponent = exponent + EXPONENT_BIAS;
  452. var dec = { low: long_1.Long.fromNumber(0), high: long_1.Long.fromNumber(0) };
  453. // Encode combination, exponent, and significand.
  454. if (significand.high.shiftRightUnsigned(49).and(long_1.Long.fromNumber(1)).equals(long_1.Long.fromNumber(1))) {
  455. // Encode '11' into bits 1 to 3
  456. dec.high = dec.high.or(long_1.Long.fromNumber(0x3).shiftLeft(61));
  457. dec.high = dec.high.or(long_1.Long.fromNumber(biasedExponent).and(long_1.Long.fromNumber(0x3fff).shiftLeft(47)));
  458. dec.high = dec.high.or(significand.high.and(long_1.Long.fromNumber(0x7fffffffffff)));
  459. }
  460. else {
  461. dec.high = dec.high.or(long_1.Long.fromNumber(biasedExponent & 0x3fff).shiftLeft(49));
  462. dec.high = dec.high.or(significand.high.and(long_1.Long.fromNumber(0x1ffffffffffff)));
  463. }
  464. dec.low = significand.low;
  465. // Encode sign
  466. if (isNegative) {
  467. dec.high = dec.high.or(long_1.Long.fromString('9223372036854775808'));
  468. }
  469. // Encode into a buffer
  470. var buffer = buffer_1.Buffer.alloc(16);
  471. index = 0;
  472. // Encode the low 64 bits of the decimal
  473. // Encode low bits
  474. buffer[index++] = dec.low.low & 0xff;
  475. buffer[index++] = (dec.low.low >> 8) & 0xff;
  476. buffer[index++] = (dec.low.low >> 16) & 0xff;
  477. buffer[index++] = (dec.low.low >> 24) & 0xff;
  478. // Encode high bits
  479. buffer[index++] = dec.low.high & 0xff;
  480. buffer[index++] = (dec.low.high >> 8) & 0xff;
  481. buffer[index++] = (dec.low.high >> 16) & 0xff;
  482. buffer[index++] = (dec.low.high >> 24) & 0xff;
  483. // Encode the high 64 bits of the decimal
  484. // Encode low bits
  485. buffer[index++] = dec.high.low & 0xff;
  486. buffer[index++] = (dec.high.low >> 8) & 0xff;
  487. buffer[index++] = (dec.high.low >> 16) & 0xff;
  488. buffer[index++] = (dec.high.low >> 24) & 0xff;
  489. // Encode high bits
  490. buffer[index++] = dec.high.high & 0xff;
  491. buffer[index++] = (dec.high.high >> 8) & 0xff;
  492. buffer[index++] = (dec.high.high >> 16) & 0xff;
  493. buffer[index++] = (dec.high.high >> 24) & 0xff;
  494. // Return the new Decimal128
  495. return new Decimal128(buffer);
  496. };
  497. /** Create a string representation of the raw Decimal128 value */
  498. Decimal128.prototype.toString = function () {
  499. // Note: bits in this routine are referred to starting at 0,
  500. // from the sign bit, towards the coefficient.
  501. // decoded biased exponent (14 bits)
  502. var biased_exponent;
  503. // the number of significand digits
  504. var significand_digits = 0;
  505. // the base-10 digits in the significand
  506. var significand = new Array(36);
  507. for (var i = 0; i < significand.length; i++)
  508. significand[i] = 0;
  509. // read pointer into significand
  510. var index = 0;
  511. // true if the number is zero
  512. var is_zero = false;
  513. // the most significant significand bits (50-46)
  514. var significand_msb;
  515. // temporary storage for significand decoding
  516. var significand128 = { parts: [0, 0, 0, 0] };
  517. // indexing variables
  518. var j, k;
  519. // Output string
  520. var string = [];
  521. // Unpack index
  522. index = 0;
  523. // Buffer reference
  524. var buffer = this.bytes;
  525. // Unpack the low 64bits into a long
  526. // bits 96 - 127
  527. var low = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
  528. // bits 64 - 95
  529. var midl = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
  530. // Unpack the high 64bits into a long
  531. // bits 32 - 63
  532. var midh = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
  533. // bits 0 - 31
  534. var high = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
  535. // Unpack index
  536. index = 0;
  537. // Create the state of the decimal
  538. var dec = {
  539. low: new long_1.Long(low, midl),
  540. high: new long_1.Long(midh, high)
  541. };
  542. if (dec.high.lessThan(long_1.Long.ZERO)) {
  543. string.push('-');
  544. }
  545. // Decode combination field and exponent
  546. // bits 1 - 5
  547. var combination = (high >> 26) & COMBINATION_MASK;
  548. if (combination >> 3 === 3) {
  549. // Check for 'special' values
  550. if (combination === COMBINATION_INFINITY) {
  551. return string.join('') + 'Infinity';
  552. }
  553. else if (combination === COMBINATION_NAN) {
  554. return 'NaN';
  555. }
  556. else {
  557. biased_exponent = (high >> 15) & EXPONENT_MASK;
  558. significand_msb = 0x08 + ((high >> 14) & 0x01);
  559. }
  560. }
  561. else {
  562. significand_msb = (high >> 14) & 0x07;
  563. biased_exponent = (high >> 17) & EXPONENT_MASK;
  564. }
  565. // unbiased exponent
  566. var exponent = biased_exponent - EXPONENT_BIAS;
  567. // Create string of significand digits
  568. // Convert the 114-bit binary number represented by
  569. // (significand_high, significand_low) to at most 34 decimal
  570. // digits through modulo and division.
  571. significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
  572. significand128.parts[1] = midh;
  573. significand128.parts[2] = midl;
  574. significand128.parts[3] = low;
  575. if (significand128.parts[0] === 0 &&
  576. significand128.parts[1] === 0 &&
  577. significand128.parts[2] === 0 &&
  578. significand128.parts[3] === 0) {
  579. is_zero = true;
  580. }
  581. else {
  582. for (k = 3; k >= 0; k--) {
  583. var least_digits = 0;
  584. // Perform the divide
  585. var result = divideu128(significand128);
  586. significand128 = result.quotient;
  587. least_digits = result.rem.low;
  588. // We now have the 9 least significant digits (in base 2).
  589. // Convert and output to string.
  590. if (!least_digits)
  591. continue;
  592. for (j = 8; j >= 0; j--) {
  593. // significand[k * 9 + j] = Math.round(least_digits % 10);
  594. significand[k * 9 + j] = least_digits % 10;
  595. // least_digits = Math.round(least_digits / 10);
  596. least_digits = Math.floor(least_digits / 10);
  597. }
  598. }
  599. }
  600. // Output format options:
  601. // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd
  602. // Regular - ddd.ddd
  603. if (is_zero) {
  604. significand_digits = 1;
  605. significand[index] = 0;
  606. }
  607. else {
  608. significand_digits = 36;
  609. while (!significand[index]) {
  610. significand_digits = significand_digits - 1;
  611. index = index + 1;
  612. }
  613. }
  614. // the exponent if scientific notation is used
  615. var scientific_exponent = significand_digits - 1 + exponent;
  616. // The scientific exponent checks are dictated by the string conversion
  617. // specification and are somewhat arbitrary cutoffs.
  618. //
  619. // We must check exponent > 0, because if this is the case, the number
  620. // has trailing zeros. However, we *cannot* output these trailing zeros,
  621. // because doing so would change the precision of the value, and would
  622. // change stored data if the string converted number is round tripped.
  623. if (scientific_exponent >= 34 || scientific_exponent <= -7 || exponent > 0) {
  624. // Scientific format
  625. // if there are too many significant digits, we should just be treating numbers
  626. // as + or - 0 and using the non-scientific exponent (this is for the "invalid
  627. // representation should be treated as 0/-0" spec cases in decimal128-1.json)
  628. if (significand_digits > 34) {
  629. string.push("" + 0);
  630. if (exponent > 0)
  631. string.push('E+' + exponent);
  632. else if (exponent < 0)
  633. string.push('E' + exponent);
  634. return string.join('');
  635. }
  636. string.push("" + significand[index++]);
  637. significand_digits = significand_digits - 1;
  638. if (significand_digits) {
  639. string.push('.');
  640. }
  641. for (var i = 0; i < significand_digits; i++) {
  642. string.push("" + significand[index++]);
  643. }
  644. // Exponent
  645. string.push('E');
  646. if (scientific_exponent > 0) {
  647. string.push('+' + scientific_exponent);
  648. }
  649. else {
  650. string.push("" + scientific_exponent);
  651. }
  652. }
  653. else {
  654. // Regular format with no decimal place
  655. if (exponent >= 0) {
  656. for (var i = 0; i < significand_digits; i++) {
  657. string.push("" + significand[index++]);
  658. }
  659. }
  660. else {
  661. var radix_position = significand_digits + exponent;
  662. // non-zero digits before radix
  663. if (radix_position > 0) {
  664. for (var i = 0; i < radix_position; i++) {
  665. string.push("" + significand[index++]);
  666. }
  667. }
  668. else {
  669. string.push('0');
  670. }
  671. string.push('.');
  672. // add leading zeros after radix
  673. while (radix_position++ < 0) {
  674. string.push('0');
  675. }
  676. for (var i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) {
  677. string.push("" + significand[index++]);
  678. }
  679. }
  680. }
  681. return string.join('');
  682. };
  683. Decimal128.prototype.toJSON = function () {
  684. return { $numberDecimal: this.toString() };
  685. };
  686. /** @internal */
  687. Decimal128.prototype.toExtendedJSON = function () {
  688. return { $numberDecimal: this.toString() };
  689. };
  690. /** @internal */
  691. Decimal128.fromExtendedJSON = function (doc) {
  692. return Decimal128.fromString(doc.$numberDecimal);
  693. };
  694. /** @internal */
  695. Decimal128.prototype[Symbol.for('nodejs.util.inspect.custom')] = function () {
  696. return this.inspect();
  697. };
  698. Decimal128.prototype.inspect = function () {
  699. return "new Decimal128(\"" + this.toString() + "\")";
  700. };
  701. return Decimal128;
  702. }());
  703. exports.Decimal128 = Decimal128;
  704. Object.defineProperty(Decimal128.prototype, '_bsontype', { value: 'Decimal128' });
  705. //# sourceMappingURL=decimal128.js.map