1// Big integer base-10 printing library
2// Copyright (c) 2008-2023 Lapo Luchini <lapo@lapo.it>
3
4// Permission to use, copy, modify, and/or distribute this software for any
5// purpose with or without fee is hereby granted, provided that the above
6// copyright notice and this permission notice appear in all copies.
7//
8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16(typeof define != 'undefined' ? define : function (factory) { 'use strict';
17 if (typeof module == 'object') module.exports = factory();
18 else window.int10 = factory();
19})(function () {
20'use strict';
21
22let max = 10000000000000; // biggest 10^n integer that can still fit 2^53 when multiplied by 256
23
24class Int10 {
25 /**
26 * Arbitrary length base-10 value.
27 * @param {number} value - Optional initial value (will be 0 otherwise).
28 */
29 constructor(value) {
30 this.buf = [+value || 0];
31 }
32
33 /**
34 * Multiply value by m and add c.
35 * @param {number} m - multiplier, must be < =256
36 * @param {number} c - value to add
37 */
38 mulAdd(m, c) {
39 // assert(m <= 256)
40 let b = this.buf,
41 l = b.length,
42 i, t;
43 for (i = 0; i < l; ++i) {
44 t = b[i] * m + c;
45 if (t < max)
46 c = 0;
47 else {
48 c = 0|(t / max);
49 t -= c * max;
50 }
51 b[i] = t;
52 }
53 if (c > 0)
54 b[i] = c;
55 }
56
57 /**
58 * Subtract value.
59 * @param {number} c - value to subtract
60 */
61 sub(c) {
62 let b = this.buf,
63 l = b.length,
64 i, t;
65 for (i = 0; i < l; ++i) {
66 t = b[i] - c;
67 if (t < 0) {
68 t += max;
69 c = 1;
70 } else
71 c = 0;
72 b[i] = t;
73 }
74 while (b[b.length - 1] === 0)
75 b.pop();
76 }
77
78 /**
79 * Convert to decimal string representation.
80 * @param {*} base - optional value, only value accepted is 10
81 */
82 toString(base) {
83 if ((base || 10) != 10)
84 throw 'only base 10 is supported';
85 let b = this.buf,
86 s = b[b.length - 1].toString();
87 for (let i = b.length - 2; i >= 0; --i)
88 s += (max + b[i]).toString().substring(1);
89 return s;
90 }
91
92 /**
93 * Convert to Number value representation.
94 * Will probably overflow 2^53 and thus become approximate.
95 */
96 valueOf() {
97 let b = this.buf,
98 v = 0;
99 for (let i = b.length - 1; i >= 0; --i)
100 v = v * max + b[i];
101 return v;
102 }
103
104 /**
105 * Return value as a simple Number (if it is <= 10000000000000), or return this.
106 */
107 simplify() {
108 let b = this.buf;
109 return (b.length == 1) ? b[0] : this;
110 }
111
112}
113
114return Int10;
115
116});