mirror of
https://github.com/josdejong/mathjs.git
synced 2026-02-01 16:07:46 +00:00
Splitted the bignumber bitwise functions into separate files
This commit is contained in:
parent
c7651def20
commit
5e4ed8c1c7
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigBitAnd = require('../../util/bignumber').and;
|
||||
var bigBitAnd = require('../../type/bignumber/util/bitAnd');
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var deepMap = require('../../type/matrix/util/deepMap');
|
||||
var bigBitNot = require('../../type/bignumber/util/bitNot');
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigBitNot = require('../../util/bignumber').not;
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigBitOr = require('../../util/bignumber').or;
|
||||
var bigBitOr = require('../../type/bignumber/util/bitOr');
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigBitXor = require('../../util/bignumber').xor;
|
||||
var bigBitXor = require('../../type/bignumber/util/bitXor');
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigLeftShift = require('../../util/bignumber').leftShift;
|
||||
var bigLeftShift = require('../../type/bignumber/util/leftShift');
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var bigRightArithShift = require('../../util/bignumber').rightArithShift;
|
||||
var bigRightArithShift = require('../../type/bignumber/util/rightArithShift');
|
||||
|
||||
function factory (type, config, load, typed) {
|
||||
var latex = require('../../util/latex');
|
||||
|
||||
68
lib/type/bignumber/util/bitAnd.js
Normal file
68
lib/type/bignumber/util/bitAnd.js
Normal file
@ -0,0 +1,68 @@
|
||||
var bitwise = require('./bitwise');
|
||||
|
||||
/**
|
||||
* Bitwise and for Bignumbers
|
||||
*
|
||||
* Special Cases:
|
||||
* N & n = N
|
||||
* n & 0 = 0
|
||||
* n & -1 = n
|
||||
* n & n = n
|
||||
* I & I = I
|
||||
* -I & -I = -I
|
||||
* I & -I = 0
|
||||
* I & n = n
|
||||
* I & -n = I
|
||||
* -I & n = 0
|
||||
* -I & -n = -I
|
||||
*
|
||||
* @param {BigNumber} x
|
||||
* @param {BigNumber} y
|
||||
* @return {BigNumber} Result of `x` & `y`, is fully precise
|
||||
* @private
|
||||
*/
|
||||
module.exports = function bitAnd(x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitAnd');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
if (x.isZero() || y.eq(-1) || x.eq(y)) {
|
||||
return x;
|
||||
}
|
||||
if (y.isZero() || x.eq(-1)) {
|
||||
return y;
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
if (x.isNegative() == y.isNegative()) {
|
||||
return x;
|
||||
}
|
||||
return new BigNumber(0);
|
||||
}
|
||||
if (!x.isFinite()) {
|
||||
if (y.isNegative()) {
|
||||
return x;
|
||||
}
|
||||
if (x.isNegative()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
if (!y.isFinite()) {
|
||||
if (x.isNegative()) {
|
||||
return y;
|
||||
}
|
||||
if (y.isNegative()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return bitwise(x, y, function (a, b) { return a & b });
|
||||
};
|
||||
21
lib/type/bignumber/util/bitNot.js
Normal file
21
lib/type/bignumber/util/bitNot.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Bitwise not
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of ~`x`, fully precise
|
||||
*
|
||||
*/
|
||||
module.exports = function bitNot (x) {
|
||||
if (x.isFinite() && !x.isInteger()) {
|
||||
throw new Error('Integer expected in function bitNot');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
var prevPrec = BigNumber.precision;
|
||||
BigNumber.config({precision: 1E9});
|
||||
|
||||
var x = x.plus(BigNumber.ONE);
|
||||
x.s = -x.s || null;
|
||||
|
||||
BigNumber.config({precision: prevPrec});
|
||||
return x;
|
||||
};
|
||||
53
lib/type/bignumber/util/bitOr.js
Normal file
53
lib/type/bignumber/util/bitOr.js
Normal file
@ -0,0 +1,53 @@
|
||||
var bitwise = require('./bitwise');
|
||||
|
||||
/**
|
||||
* Bitwise OR for BigNumbers
|
||||
*
|
||||
* Special Cases:
|
||||
* N | n = N
|
||||
* n | 0 = n
|
||||
* n | -1 = -1
|
||||
* n | n = n
|
||||
* I | I = I
|
||||
* -I | -I = -I
|
||||
* I | -n = -1
|
||||
* I | -I = -1
|
||||
* I | n = I
|
||||
* -I | n = -I
|
||||
* -I | -n = -n
|
||||
*
|
||||
* @param {BigNumber} x
|
||||
* @param {BigNumber} y
|
||||
* @return {BigNumber} Result of `x` | `y`, fully precise
|
||||
*/
|
||||
module.exports = function bitOr (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitOr');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
var negOne = new BigNumber(-1);
|
||||
if (x.isZero() || y.eq(negOne) || x.eq(y)) {
|
||||
return y;
|
||||
}
|
||||
if (y.isZero() || x.eq(negOne)) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if ((!x.isFinite() && !x.isNegative() && y.isNegative()) ||
|
||||
(x.isNegative() && !y.isNegative() && !y.isFinite())) {
|
||||
return negOne;
|
||||
}
|
||||
if (x.isNegative() && y.isNegative()) {
|
||||
return x.isFinite() ? x : y;
|
||||
}
|
||||
return x.isFinite() ? y : x;
|
||||
}
|
||||
|
||||
return bitwise(x, y, function (a, b) { return a | b });
|
||||
};
|
||||
60
lib/type/bignumber/util/bitXor.js
Normal file
60
lib/type/bignumber/util/bitXor.js
Normal file
@ -0,0 +1,60 @@
|
||||
var bitwise = require('./bitwise');
|
||||
var bitNot = require('./bitNot');
|
||||
|
||||
/**
|
||||
* Bitwise XOR for BigNumbers
|
||||
*
|
||||
* Special Cases:
|
||||
* N ^ n = N
|
||||
* n ^ 0 = n
|
||||
* n ^ n = 0
|
||||
* n ^ -1 = ~n
|
||||
* I ^ n = I
|
||||
* I ^ -n = -I
|
||||
* I ^ -I = -1
|
||||
* -I ^ n = -I
|
||||
* -I ^ -n = I
|
||||
*
|
||||
* @param {BigNumber} x
|
||||
* @param {BigNumber} y
|
||||
* @return {BigNumber} Result of `x` ^ `y`, fully precise
|
||||
*
|
||||
*/
|
||||
module.exports = function bitXor(x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitXor');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero()) {
|
||||
return y;
|
||||
}
|
||||
if (y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (x.eq(y)) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
|
||||
var negOne = new BigNumber(-1);
|
||||
if (x.eq(negOne)) {
|
||||
return bitNot(y);
|
||||
}
|
||||
if (y.eq(negOne)) {
|
||||
return bitNot(x);
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
return negOne;
|
||||
}
|
||||
return new BigNumber(x.isNegative() == y.isNegative()
|
||||
? Infinity
|
||||
: -Infinity);
|
||||
}
|
||||
return bitwise(x, y, function (a, b) { return a ^ b });
|
||||
};
|
||||
124
lib/type/bignumber/util/bitwise.js
Normal file
124
lib/type/bignumber/util/bitwise.js
Normal file
@ -0,0 +1,124 @@
|
||||
var bitNot = require('./bitNot');
|
||||
|
||||
/**
|
||||
* Applies bitwise function to numbers
|
||||
* @param {BigNumber} x
|
||||
* @param {BigNumber} y
|
||||
* @param {function (a, b)} func
|
||||
* @return {BigNumber}
|
||||
*/
|
||||
module.exports = function bitwise(x, y, func) {
|
||||
var BigNumber = x.constructor;
|
||||
|
||||
var xBits, yBits;
|
||||
var xSign = +(x.s < 0);
|
||||
var ySign = +(y.s < 0);
|
||||
if (xSign) {
|
||||
xBits = decCoefficientToBinaryString(bitNot(x));
|
||||
for (var i = 0; i < xBits.length; ++i) {
|
||||
xBits[i] ^= 1;
|
||||
}
|
||||
} else {
|
||||
xBits = decCoefficientToBinaryString(x);
|
||||
}
|
||||
if (ySign) {
|
||||
yBits = decCoefficientToBinaryString(bitNot(y));
|
||||
for (var i = 0; i < yBits.length; ++i) {
|
||||
yBits[i] ^= 1;
|
||||
}
|
||||
} else {
|
||||
yBits = decCoefficientToBinaryString(y);
|
||||
}
|
||||
|
||||
var minBits, maxBits, minSign;
|
||||
if (xBits.length <= yBits.length) {
|
||||
minBits = xBits;
|
||||
maxBits = yBits;
|
||||
minSign = xSign;
|
||||
} else {
|
||||
minBits = yBits;
|
||||
maxBits = xBits;
|
||||
minSign = ySign;
|
||||
}
|
||||
|
||||
var shortLen = minBits.length;
|
||||
var longLen = maxBits.length;
|
||||
var expFuncVal = func(xSign, ySign) ^ 1;
|
||||
var outVal = new BigNumber(expFuncVal ^ 1);
|
||||
var twoPower = BigNumber.ONE;
|
||||
var two = new BigNumber(2);
|
||||
|
||||
var prevPrec = BigNumber.precision;
|
||||
BigNumber.config({precision: 1E9});
|
||||
|
||||
while (shortLen > 0) {
|
||||
if (func(minBits[--shortLen], maxBits[--longLen]) == expFuncVal) {
|
||||
outVal = outVal.plus(twoPower);
|
||||
}
|
||||
twoPower = twoPower.times(two);
|
||||
}
|
||||
while (longLen > 0) {
|
||||
if (func(minSign, maxBits[--longLen]) == expFuncVal) {
|
||||
outVal = outVal.plus(twoPower);
|
||||
}
|
||||
twoPower = twoPower.times(two);
|
||||
}
|
||||
|
||||
BigNumber.config({precision: prevPrec});
|
||||
|
||||
if (expFuncVal == 0) {
|
||||
outVal.s = -outVal.s;
|
||||
}
|
||||
return outVal;
|
||||
};
|
||||
|
||||
/* Extracted from decimal.js, and edited to specialize. */
|
||||
function decCoefficientToBinaryString (x) {
|
||||
// Convert to string
|
||||
var a = x.c;
|
||||
var r = a[0] + '';
|
||||
|
||||
for (var i = 1; i < a.length; ++i) {
|
||||
var s = a[i] + '';
|
||||
for (var z = 7 - s.length; z--; ) {
|
||||
s = '0' + s;
|
||||
}
|
||||
|
||||
r += s;
|
||||
}
|
||||
|
||||
var j;
|
||||
for (j = r.length - 1; r.charAt(j) == '0'; --j);
|
||||
|
||||
var xe = x.e;
|
||||
var str = r.slice(0, j + 1 || 1);
|
||||
var strL = str.length;
|
||||
if (xe > 0) {
|
||||
if (++xe > strL) {
|
||||
// Append zeros.
|
||||
for (xe -= strL; xe--; str += '0');
|
||||
} else if (xe < strL) {
|
||||
str = str.slice(0, xe) + '.' + str.slice(xe);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from base 10 (decimal) to base 2
|
||||
var arr = [0];
|
||||
for (var i = 0; i < str.length; ) {
|
||||
for (var arrL = arr.length; arrL--; arr[arrL] *= 10);
|
||||
|
||||
arr[0] += str.charAt(i++) << 0; // convert to int
|
||||
for (var j = 0; j < arr.length; ++j) {
|
||||
if (arr[j] > 1) {
|
||||
if (arr[j + 1] == null) {
|
||||
arr[j + 1] = 0;
|
||||
}
|
||||
|
||||
arr[j + 1] += arr[j] >> 1;
|
||||
arr[j] &= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return arr.reverse();
|
||||
}
|
||||
41
lib/type/bignumber/util/leftShift.js
Normal file
41
lib/type/bignumber/util/leftShift.js
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
/**
|
||||
* Bitwise left shift
|
||||
*
|
||||
* Special Cases:
|
||||
* n << -n = N
|
||||
* n << N = N
|
||||
* N << n = N
|
||||
* n << 0 = n
|
||||
* 0 << n = 0
|
||||
* I << I = N
|
||||
* I << n = I
|
||||
* n << I = I
|
||||
*
|
||||
* @param {BigNumber} x
|
||||
* @param {BigNumber} y
|
||||
* @return {BigNumber} Result of `x` << `y`
|
||||
*
|
||||
*/
|
||||
module.exports = function leftShift (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function leftShift');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN() || (y.isNegative() && !y.isZero())) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero() || y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
// Math.pow(2, y) is fully precise for y < 55, and fast
|
||||
if (y.lt(55)) {
|
||||
return x.times(Math.pow(2, y.toNumber()) + '');
|
||||
}
|
||||
return x.times(new BigNumber(2).pow(y));
|
||||
};
|
||||
47
lib/type/bignumber/util/rightArithShift.js
Normal file
47
lib/type/bignumber/util/rightArithShift.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Special Cases:
|
||||
* n >> -n = N
|
||||
* n >> N = N
|
||||
* N >> n = N
|
||||
* I >> I = N
|
||||
* n >> 0 = n
|
||||
* I >> n = I
|
||||
* -I >> n = -I
|
||||
* -I >> I = -I
|
||||
* n >> I = I
|
||||
* -n >> I = -1
|
||||
* 0 >> n = 0
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` >> `y`
|
||||
*
|
||||
*/
|
||||
module.exports = function rightArithShift (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function rightArithShift');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN() || (y.isNegative() && !y.isZero())) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero() || y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
if (!y.isFinite()) {
|
||||
if (x.isNegative()) {
|
||||
return new BigNumber(-1);
|
||||
}
|
||||
if (!x.isFinite()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
return new BigNumber(0);
|
||||
}
|
||||
|
||||
// Math.pow(2, y) is fully precise for y < 55, and fast
|
||||
if (y.lt(55)) {
|
||||
return x.div(Math.pow(2, y.toNumber()) + '').floor();
|
||||
}
|
||||
return x.div(new BigNumber(2).pow(y)).floor();
|
||||
};
|
||||
@ -94,407 +94,6 @@ exports.tau = memoize(function (precision) {
|
||||
});
|
||||
|
||||
|
||||
/*************************************
|
||||
* Bitwise functions *
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
* Special Cases:
|
||||
* N & n = N
|
||||
* n & 0 = 0
|
||||
* n & -1 = n
|
||||
* n & n = n
|
||||
* I & I = I
|
||||
* -I & -I = -I
|
||||
* I & -I = 0
|
||||
* I & n = n
|
||||
* I & -n = I
|
||||
* -I & n = 0
|
||||
* -I & -n = -I
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` & `y`, is fully precise
|
||||
*
|
||||
*/
|
||||
exports.and = function(x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitAnd');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
if (x.isZero() || y.eq(-1) || x.eq(y)) {
|
||||
return x;
|
||||
}
|
||||
if (y.isZero() || x.eq(-1)) {
|
||||
return y;
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
if (x.isNegative() == y.isNegative()) {
|
||||
return x;
|
||||
}
|
||||
return new BigNumber(0);
|
||||
}
|
||||
if (!x.isFinite()) {
|
||||
if (y.isNegative()) {
|
||||
return x;
|
||||
}
|
||||
if (x.isNegative()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
if (!y.isFinite()) {
|
||||
if (x.isNegative()) {
|
||||
return y;
|
||||
}
|
||||
if (y.isNegative()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return bitwise(x, y, function (a, b) { return a & b });
|
||||
};
|
||||
|
||||
/*
|
||||
* Special Cases:
|
||||
* n << -n = N
|
||||
* n << N = N
|
||||
* N << n = N
|
||||
* n << 0 = n
|
||||
* 0 << n = 0
|
||||
* I << I = N
|
||||
* I << n = I
|
||||
* n << I = I
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` << `y`
|
||||
*
|
||||
*/
|
||||
exports.leftShift = function (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function leftShift');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN() || (y.isNegative() && !y.isZero())) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero() || y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
// Math.pow(2, y) is fully precise for y < 55, and fast
|
||||
if (y.lt(55)) {
|
||||
return x.times(Math.pow(2, y.toNumber()) + '');
|
||||
}
|
||||
return x.times(new BigNumber(2).pow(y));
|
||||
};
|
||||
|
||||
/*
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of ~`x`, fully precise
|
||||
*
|
||||
*/
|
||||
exports.not = function (x) {
|
||||
if (x.isFinite() && !x.isInteger()) {
|
||||
throw new Error('Integer expected in function bitNot');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
var prevPrec = BigNumber.precision;
|
||||
BigNumber.config({precision: 1E9});
|
||||
|
||||
var x = x.plus(BigNumber.ONE);
|
||||
x.s = -x.s || null;
|
||||
|
||||
BigNumber.config({precision: prevPrec});
|
||||
return x;
|
||||
};
|
||||
|
||||
/*
|
||||
* Special Cases:
|
||||
* N | n = N
|
||||
* n | 0 = n
|
||||
* n | -1 = -1
|
||||
* n | n = n
|
||||
* I | I = I
|
||||
* -I | -I = -I
|
||||
* I | -n = -1
|
||||
* I | -I = -1
|
||||
* I | n = I
|
||||
* -I | n = -I
|
||||
* -I | -n = -n
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` | `y`, fully precise
|
||||
*
|
||||
*/
|
||||
exports.or = function (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitOr');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
|
||||
var negOne = new BigNumber(-1);
|
||||
if (x.isZero() || y.eq(negOne) || x.eq(y)) {
|
||||
return y;
|
||||
}
|
||||
if (y.isZero() || x.eq(negOne)) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if ((!x.isFinite() && !x.isNegative() && y.isNegative()) ||
|
||||
(x.isNegative() && !y.isNegative() && !y.isFinite())) {
|
||||
return negOne;
|
||||
}
|
||||
if (x.isNegative() && y.isNegative()) {
|
||||
return x.isFinite() ? x : y;
|
||||
}
|
||||
return x.isFinite() ? y : x;
|
||||
}
|
||||
return bitwise(x, y, function (a, b) { return a | b });
|
||||
};
|
||||
|
||||
/*
|
||||
* Special Cases:
|
||||
* n >> -n = N
|
||||
* n >> N = N
|
||||
* N >> n = N
|
||||
* I >> I = N
|
||||
* n >> 0 = n
|
||||
* I >> n = I
|
||||
* -I >> n = -I
|
||||
* -I >> I = -I
|
||||
* n >> I = I
|
||||
* -n >> I = -1
|
||||
* 0 >> n = 0
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` >> `y`
|
||||
*
|
||||
*/
|
||||
exports.rightArithShift = function (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function rightArithShift');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN() || (y.isNegative() && !y.isZero())) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero() || y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
if (!y.isFinite()) {
|
||||
if (x.isNegative()) {
|
||||
return new BigNumber(-1);
|
||||
}
|
||||
if (!x.isFinite()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
return new BigNumber(0);
|
||||
}
|
||||
|
||||
// Math.pow(2, y) is fully precise for y < 55, and fast
|
||||
if (y.lt(55)) {
|
||||
return x.div(Math.pow(2, y.toNumber()) + '').floor();
|
||||
}
|
||||
return x.div(new BigNumber(2).pow(y)).floor();
|
||||
};
|
||||
|
||||
/*
|
||||
* Special Cases:
|
||||
* N ^ n = N
|
||||
* n ^ 0 = n
|
||||
* n ^ n = 0
|
||||
* n ^ -1 = ~n
|
||||
* I ^ n = I
|
||||
* I ^ -n = -I
|
||||
* I ^ -I = -1
|
||||
* -I ^ n = -I
|
||||
* -I ^ -n = I
|
||||
*
|
||||
* @param {BigNumber} value
|
||||
* @param {BigNumber} value
|
||||
* @return {BigNumber} Result of `x` ^ `y`, fully precise
|
||||
*
|
||||
*/
|
||||
exports.xor = function (x, y) {
|
||||
if ((x.isFinite() && !x.isInteger()) || (y.isFinite() && !y.isInteger())) {
|
||||
throw new Error('Integers expected in function bitXor');
|
||||
}
|
||||
|
||||
var BigNumber = x.constructor;
|
||||
if (x.isNaN() || y.isNaN()) {
|
||||
return new BigNumber(NaN);
|
||||
}
|
||||
if (x.isZero()) {
|
||||
return y;
|
||||
}
|
||||
if (y.isZero()) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (x.eq(y)) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
|
||||
var negOne = new BigNumber(-1);
|
||||
if (x.eq(negOne)) {
|
||||
return exports.not(y);
|
||||
}
|
||||
if (y.eq(negOne)) {
|
||||
return exports.not(x);
|
||||
}
|
||||
|
||||
if (!x.isFinite() || !y.isFinite()) {
|
||||
if (!x.isFinite() && !y.isFinite()) {
|
||||
return negOne;
|
||||
}
|
||||
return new BigNumber(x.isNegative() == y.isNegative()
|
||||
? Infinity
|
||||
: -Infinity);
|
||||
}
|
||||
return bitwise(x, y, function (a, b) { return a ^ b });
|
||||
};
|
||||
|
||||
/* Applies bitwise function to numbers. */
|
||||
function bitwise(x, y, func) {
|
||||
var BigNumber = x.constructor;
|
||||
|
||||
var xBits, yBits;
|
||||
var xSign = +(x.s < 0);
|
||||
var ySign = +(y.s < 0);
|
||||
if (xSign) {
|
||||
xBits = decCoefficientToBinaryString(exports.not(x));
|
||||
for (var i = 0; i < xBits.length; ++i) {
|
||||
xBits[i] ^= 1;
|
||||
}
|
||||
} else {
|
||||
xBits = decCoefficientToBinaryString(x);
|
||||
}
|
||||
if (ySign) {
|
||||
yBits = decCoefficientToBinaryString(exports.not(y));
|
||||
for (var i = 0; i < yBits.length; ++i) {
|
||||
yBits[i] ^= 1;
|
||||
}
|
||||
} else {
|
||||
yBits = decCoefficientToBinaryString(y);
|
||||
}
|
||||
|
||||
var minBits, maxBits, minSign;
|
||||
if (xBits.length <= yBits.length) {
|
||||
minBits = xBits;
|
||||
maxBits = yBits;
|
||||
minSign = xSign;
|
||||
} else {
|
||||
minBits = yBits;
|
||||
maxBits = xBits;
|
||||
minSign = ySign;
|
||||
}
|
||||
|
||||
var shortLen = minBits.length;
|
||||
var longLen = maxBits.length;
|
||||
var expFuncVal = func(xSign, ySign) ^ 1;
|
||||
var outVal = new BigNumber(expFuncVal ^ 1);
|
||||
var twoPower = BigNumber.ONE;
|
||||
var two = new BigNumber(2);
|
||||
|
||||
var prevPrec = BigNumber.precision;
|
||||
BigNumber.config({precision: 1E9});
|
||||
|
||||
while (shortLen > 0) {
|
||||
if (func(minBits[--shortLen], maxBits[--longLen]) == expFuncVal) {
|
||||
outVal = outVal.plus(twoPower);
|
||||
}
|
||||
twoPower = twoPower.times(two);
|
||||
}
|
||||
while (longLen > 0) {
|
||||
if (func(minSign, maxBits[--longLen]) == expFuncVal) {
|
||||
outVal = outVal.plus(twoPower);
|
||||
}
|
||||
twoPower = twoPower.times(two);
|
||||
}
|
||||
|
||||
BigNumber.config({precision: prevPrec});
|
||||
|
||||
if (expFuncVal == 0) {
|
||||
outVal.s = -outVal.s;
|
||||
}
|
||||
return outVal;
|
||||
}
|
||||
|
||||
/* Extracted from decimal.js, and edited to specialize. */
|
||||
function decCoefficientToBinaryString(x) {
|
||||
// Convert to string
|
||||
var a = x.c;
|
||||
var r = a[0] + '';
|
||||
|
||||
for (var i = 1; i < a.length; ++i) {
|
||||
var s = a[i] + '';
|
||||
for (var z = 7 - s.length; z--; ) {
|
||||
s = '0' + s;
|
||||
}
|
||||
|
||||
r += s;
|
||||
}
|
||||
|
||||
var j;
|
||||
for (j = r.length - 1; r.charAt(j) == '0'; --j);
|
||||
|
||||
var xe = x.e;
|
||||
var str = r.slice(0, j + 1 || 1);
|
||||
var strL = str.length;
|
||||
if (xe > 0) {
|
||||
if (++xe > strL) {
|
||||
// Append zeros.
|
||||
for (xe -= strL; xe--; str += '0');
|
||||
} else if (xe < strL) {
|
||||
str = str.slice(0, xe) + '.' + str.slice(xe);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from base 10 (decimal) to base 2
|
||||
var arr = [0];
|
||||
for (var i = 0; i < str.length; ) {
|
||||
for (var arrL = arr.length; arrL--; arr[arrL] *= 10);
|
||||
|
||||
arr[0] += str.charAt(i++) << 0; // convert to int
|
||||
for (var j = 0; j < arr.length; ++j) {
|
||||
if (arr[j] > 1) {
|
||||
if (arr[j + 1] == null) {
|
||||
arr[j + 1] = 0;
|
||||
}
|
||||
|
||||
arr[j + 1] += arr[j] >> 1;
|
||||
arr[j] &= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return arr.reverse();
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Trigonometric functions *
|
||||
*************************************/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user