UNPKG

9.46 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.bitAndBigNumber = bitAndBigNumber;
7exports.bitNotBigNumber = bitNotBigNumber;
8exports.bitOrBigNumber = bitOrBigNumber;
9exports.bitwise = bitwise;
10exports.bitXor = bitXor;
11exports.leftShiftBigNumber = leftShiftBigNumber;
12exports.rightArithShiftBigNumber = rightArithShiftBigNumber;
13
14/**
15 * Bitwise and for Bignumbers
16 *
17 * Special Cases:
18 * N & n = N
19 * n & 0 = 0
20 * n & -1 = n
21 * n & n = n
22 * I & I = I
23 * -I & -I = -I
24 * I & -I = 0
25 * I & n = n
26 * I & -n = I
27 * -I & n = 0
28 * -I & -n = -I
29 *
30 * @param {BigNumber} x
31 * @param {BigNumber} y
32 * @return {BigNumber} Result of `x` & `y`, is fully precise
33 * @private
34 */
35function bitAndBigNumber(x, y) {
36 if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
37 throw new Error('Integers expected in function bitAnd');
38 }
39
40 var BigNumber = x.constructor;
41
42 if (x.isNaN() || y.isNaN()) {
43 return new BigNumber(NaN);
44 }
45
46 if (x.isZero() || y.eq(-1) || x.eq(y)) {
47 return x;
48 }
49
50 if (y.isZero() || x.eq(-1)) {
51 return y;
52 }
53
54 if (!x.isFinite() || !y.isFinite()) {
55 if (!x.isFinite() && !y.isFinite()) {
56 if (x.isNegative() === y.isNegative()) {
57 return x;
58 }
59
60 return new BigNumber(0);
61 }
62
63 if (!x.isFinite()) {
64 if (y.isNegative()) {
65 return x;
66 }
67
68 if (x.isNegative()) {
69 return new BigNumber(0);
70 }
71
72 return y;
73 }
74
75 if (!y.isFinite()) {
76 if (x.isNegative()) {
77 return y;
78 }
79
80 if (y.isNegative()) {
81 return new BigNumber(0);
82 }
83
84 return x;
85 }
86 }
87
88 return bitwise(x, y, function (a, b) {
89 return a & b;
90 });
91}
92/**
93 * Bitwise not
94 * @param {BigNumber} x
95 * @return {BigNumber} Result of ~`x`, fully precise
96 *
97 */
98
99
100function bitNotBigNumber(x) {
101 if (x.isFinite() && !x.isInteger()) {
102 throw new Error('Integer expected in function bitNot');
103 }
104
105 var BigNumber = x.constructor;
106 var prevPrec = BigNumber.precision;
107 BigNumber.config({
108 precision: 1E9
109 });
110 var result = x.plus(new BigNumber(1));
111 result.s = -result.s || null;
112 BigNumber.config({
113 precision: prevPrec
114 });
115 return result;
116}
117/**
118 * Bitwise OR for BigNumbers
119 *
120 * Special Cases:
121 * N | n = N
122 * n | 0 = n
123 * n | -1 = -1
124 * n | n = n
125 * I | I = I
126 * -I | -I = -I
127 * I | -n = -1
128 * I | -I = -1
129 * I | n = I
130 * -I | n = -I
131 * -I | -n = -n
132 *
133 * @param {BigNumber} x
134 * @param {BigNumber} y
135 * @return {BigNumber} Result of `x` | `y`, fully precise
136 */
137
138
139function bitOrBigNumber(x, y) {
140 if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
141 throw new Error('Integers expected in function bitOr');
142 }
143
144 var BigNumber = x.constructor;
145
146 if (x.isNaN() || y.isNaN()) {
147 return new BigNumber(NaN);
148 }
149
150 var negOne = new BigNumber(-1);
151
152 if (x.isZero() || y.eq(negOne) || x.eq(y)) {
153 return y;
154 }
155
156 if (y.isZero() || x.eq(negOne)) {
157 return x;
158 }
159
160 if (!x.isFinite() || !y.isFinite()) {
161 if (!x.isFinite() && !x.isNegative() && y.isNegative() || x.isNegative() && !y.isNegative() && !y.isFinite()) {
162 return negOne;
163 }
164
165 if (x.isNegative() && y.isNegative()) {
166 return x.isFinite() ? x : y;
167 }
168
169 return x.isFinite() ? y : x;
170 }
171
172 return bitwise(x, y, function (a, b) {
173 return a | b;
174 });
175}
176/**
177 * Applies bitwise function to numbers
178 * @param {BigNumber} x
179 * @param {BigNumber} y
180 * @param {function (a, b)} func
181 * @return {BigNumber}
182 */
183
184
185function bitwise(x, y, func) {
186 var BigNumber = x.constructor;
187 var xBits, yBits;
188 var xSign = +(x.s < 0);
189 var ySign = +(y.s < 0);
190
191 if (xSign) {
192 xBits = decCoefficientToBinaryString(bitNotBigNumber(x));
193
194 for (var i = 0; i < xBits.length; ++i) {
195 xBits[i] ^= 1;
196 }
197 } else {
198 xBits = decCoefficientToBinaryString(x);
199 }
200
201 if (ySign) {
202 yBits = decCoefficientToBinaryString(bitNotBigNumber(y));
203
204 for (var _i = 0; _i < yBits.length; ++_i) {
205 yBits[_i] ^= 1;
206 }
207 } else {
208 yBits = decCoefficientToBinaryString(y);
209 }
210
211 var minBits, maxBits, minSign;
212
213 if (xBits.length <= yBits.length) {
214 minBits = xBits;
215 maxBits = yBits;
216 minSign = xSign;
217 } else {
218 minBits = yBits;
219 maxBits = xBits;
220 minSign = ySign;
221 }
222
223 var shortLen = minBits.length;
224 var longLen = maxBits.length;
225 var expFuncVal = func(xSign, ySign) ^ 1;
226 var outVal = new BigNumber(expFuncVal ^ 1);
227 var twoPower = new BigNumber(1);
228 var two = new BigNumber(2);
229 var prevPrec = BigNumber.precision;
230 BigNumber.config({
231 precision: 1E9
232 });
233
234 while (shortLen > 0) {
235 if (func(minBits[--shortLen], maxBits[--longLen]) === expFuncVal) {
236 outVal = outVal.plus(twoPower);
237 }
238
239 twoPower = twoPower.times(two);
240 }
241
242 while (longLen > 0) {
243 if (func(minSign, maxBits[--longLen]) === expFuncVal) {
244 outVal = outVal.plus(twoPower);
245 }
246
247 twoPower = twoPower.times(two);
248 }
249
250 BigNumber.config({
251 precision: prevPrec
252 });
253
254 if (expFuncVal === 0) {
255 outVal.s = -outVal.s;
256 }
257
258 return outVal;
259}
260/* Extracted from decimal.js, and edited to specialize. */
261
262
263function decCoefficientToBinaryString(x) {
264 // Convert to string
265 var a = x.d; // array with digits
266
267 var r = a[0] + '';
268
269 for (var i = 1; i < a.length; ++i) {
270 var s = a[i] + '';
271
272 for (var z = 7 - s.length; z--;) {
273 s = '0' + s;
274 }
275
276 r += s;
277 }
278
279 var j = r.length;
280
281 while (r.charAt(j) === '0') {
282 j--;
283 }
284
285 var xe = x.e;
286 var str = r.slice(0, j + 1 || 1);
287 var strL = str.length;
288
289 if (xe > 0) {
290 if (++xe > strL) {
291 // Append zeros.
292 xe -= strL;
293
294 while (xe--) {
295 str += '0';
296 }
297 } else if (xe < strL) {
298 str = str.slice(0, xe) + '.' + str.slice(xe);
299 }
300 } // Convert from base 10 (decimal) to base 2
301
302
303 var arr = [0];
304
305 for (var _i2 = 0; _i2 < str.length;) {
306 var arrL = arr.length;
307
308 while (arrL--) {
309 arr[arrL] *= 10;
310 }
311
312 arr[0] += parseInt(str.charAt(_i2++)); // convert to int
313
314 for (var _j = 0; _j < arr.length; ++_j) {
315 if (arr[_j] > 1) {
316 if (arr[_j + 1] === null || arr[_j + 1] === undefined) {
317 arr[_j + 1] = 0;
318 }
319
320 arr[_j + 1] += arr[_j] >> 1;
321 arr[_j] &= 1;
322 }
323 }
324 }
325
326 return arr.reverse();
327}
328/**
329 * Bitwise XOR for BigNumbers
330 *
331 * Special Cases:
332 * N ^ n = N
333 * n ^ 0 = n
334 * n ^ n = 0
335 * n ^ -1 = ~n
336 * I ^ n = I
337 * I ^ -n = -I
338 * I ^ -I = -1
339 * -I ^ n = -I
340 * -I ^ -n = I
341 *
342 * @param {BigNumber} x
343 * @param {BigNumber} y
344 * @return {BigNumber} Result of `x` ^ `y`, fully precise
345 *
346 */
347
348
349function bitXor(x, y) {
350 if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
351 throw new Error('Integers expected in function bitXor');
352 }
353
354 var BigNumber = x.constructor;
355
356 if (x.isNaN() || y.isNaN()) {
357 return new BigNumber(NaN);
358 }
359
360 if (x.isZero()) {
361 return y;
362 }
363
364 if (y.isZero()) {
365 return x;
366 }
367
368 if (x.eq(y)) {
369 return new BigNumber(0);
370 }
371
372 var negOne = new BigNumber(-1);
373
374 if (x.eq(negOne)) {
375 return bitNotBigNumber(y);
376 }
377
378 if (y.eq(negOne)) {
379 return bitNotBigNumber(x);
380 }
381
382 if (!x.isFinite() || !y.isFinite()) {
383 if (!x.isFinite() && !y.isFinite()) {
384 return negOne;
385 }
386
387 return new BigNumber(x.isNegative() === y.isNegative() ? Infinity : -Infinity);
388 }
389
390 return bitwise(x, y, function (a, b) {
391 return a ^ b;
392 });
393}
394/**
395 * Bitwise left shift
396 *
397 * Special Cases:
398 * n << -n = N
399 * n << N = N
400 * N << n = N
401 * n << 0 = n
402 * 0 << n = 0
403 * I << I = N
404 * I << n = I
405 * n << I = I
406 *
407 * @param {BigNumber} x
408 * @param {BigNumber} y
409 * @return {BigNumber} Result of `x` << `y`
410 *
411 */
412
413
414function leftShiftBigNumber(x, y) {
415 if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
416 throw new Error('Integers expected in function leftShift');
417 }
418
419 var BigNumber = x.constructor;
420
421 if (x.isNaN() || y.isNaN() || y.isNegative() && !y.isZero()) {
422 return new BigNumber(NaN);
423 }
424
425 if (x.isZero() || y.isZero()) {
426 return x;
427 }
428
429 if (!x.isFinite() && !y.isFinite()) {
430 return new BigNumber(NaN);
431 } // Math.pow(2, y) is fully precise for y < 55, and fast
432
433
434 if (y.lt(55)) {
435 return x.times(Math.pow(2, y.toNumber()) + '');
436 }
437
438 return x.times(new BigNumber(2).pow(y));
439}
440/*
441 * Special Cases:
442 * n >> -n = N
443 * n >> N = N
444 * N >> n = N
445 * I >> I = N
446 * n >> 0 = n
447 * I >> n = I
448 * -I >> n = -I
449 * -I >> I = -I
450 * n >> I = I
451 * -n >> I = -1
452 * 0 >> n = 0
453 *
454 * @param {BigNumber} value
455 * @param {BigNumber} value
456 * @return {BigNumber} Result of `x` >> `y`
457 *
458 */
459
460
461function rightArithShiftBigNumber(x, y) {
462 if (x.isFinite() && !x.isInteger() || y.isFinite() && !y.isInteger()) {
463 throw new Error('Integers expected in function rightArithShift');
464 }
465
466 var BigNumber = x.constructor;
467
468 if (x.isNaN() || y.isNaN() || y.isNegative() && !y.isZero()) {
469 return new BigNumber(NaN);
470 }
471
472 if (x.isZero() || y.isZero()) {
473 return x;
474 }
475
476 if (!y.isFinite()) {
477 if (x.isNegative()) {
478 return new BigNumber(-1);
479 }
480
481 if (!x.isFinite()) {
482 return new BigNumber(NaN);
483 }
484
485 return new BigNumber(0);
486 } // Math.pow(2, y) is fully precise for y < 55, and fast
487
488
489 if (y.lt(55)) {
490 return x.div(Math.pow(2, y.toNumber()) + '').floor();
491 }
492
493 return x.div(new BigNumber(2).pow(y)).floor();
494}
\No newline at end of file