1
0
mirror of https://github.com/MikeMcl/decimal.js.git synced 2024-10-27 20:34:12 +00:00

Fixed bitwise gate ops. Will test NOT soon, and will finish the shifts.

This commit is contained in:
Favian Contreras 2014-12-04 21:21:54 -08:00
parent c0ca644b6b
commit b9287583e6
4 changed files with 400575 additions and 59 deletions

View File

@ -69,8 +69,10 @@
/* /*
* n & n = n * n & n = n
* n & 0 = 0 * n & 0 = 0
* n & -1 = n
* N & n = N * N & n = N
* I & n = n * I & n = n
* I & -n = I
* I & I = I * I & I = I
* I & -I = 0 * I & -I = 0
* -I & n = 0 * -I & n = 0
@ -81,18 +83,36 @@
*/ */
P['and'] = function (n) { P['and'] = function (n) {
var Decimal = this['constructor'], var Decimal = this['constructor'],
n = new Decimal(n); x = this['trunc'](),
y = new Decimal(n)['trunc']();
if (this && n && (!this['c'] || !n['c'])) { // Is either NaN?
if (!this['c'] && !n['c']) { if (!x['s'] || !y['s']) {
return new Decimal((this['s'] == n['s']) ? this : 0); return new Decimal(NaN);
}
if (this['s'] < 0 || n['s'] < 0) {
return new Decimal(0);
}
return new Decimal(this['c'] ? c['trunc']() : n['trunc']());
} }
return bitwise(this, n, function (a, b) { return a & b });
// Is either 0 or -1?
if (x['isZero']() || y['eq'](-1)) {
return x;
}
if (y['isZero']() || x['eq'](-1)) {
return y;
}
// Is either Infinity?
if (!x['c'] || !y['c']) {
if (!x['c'] && !y['c']) {
return new Decimal((x['s'] == y['s']) ? x : 0);
}
if (x['s'] < 0) {
return new Decimal((x['c'] && !y['c'] && y['s'] > 0) ? y : 0);
}
if (y['s'] < 0) {
return new Decimal((y['c'] && !x['c'] && x['s'] > 0) ? x : 0);
}
return new Decimal(x['c'] ? x : y);
}
return bitwise(x, y, function (a, b) { return a & b });
}; };
@ -815,20 +835,27 @@
/* /*
* Return a new Decimal whose value is the value of ~(this Decimal). * Return a new Decimal whose value is the value of ~(this Decimal).
* The final digit adjustment may get lost out the precision bound.
* *
*/ */
P['not'] = function () { P['not'] = function () {
var x = new this['constructor'](this['trunc']()); var tmpExternal = external,
Decimal = this['constructor'],
x = x['plus'](x['constructor']['ONE']); prevPrec = Decimal['precision'];
external = false;
Decimal['precision'] = MAX_DIGITS;
var x = this['plus'](Decimal['ONE']);
x['s'] = -x['s'] || null; x['s'] = -x['s'] || null;
Decimal['precision'] = prevPrec;
external = tmpExternal;
return x; return x;
}; };
/* /*
* n | 0 = n * n | 0 = n
* n | -1 = -1
* n | n = n * n | n = n
* I | n = I * I | n = I
* I | -n = -1 * I | -n = -1
@ -842,16 +869,30 @@
*/ */
P['or'] = function (n) { P['or'] = function (n) {
var Decimal = this['constructor'], var Decimal = this['constructor'],
n = new Decimal(n); x = this['trunc'](),
y = new Decimal(n)['trunc']();
if (this && n && this['s'] && n['s'] && (!this['c'] || !n['c'])) { // Is either NaN?
if ((!this['c'] && this['s'] > 0 && n['lt'](0)) || (this['lt'](0) && n['s'] > 0 && !n['c']) || if (!x['s'] || !y['s']) {
this['eq'](-1) || n['eq'](-1)) { return new Decimal(NaN);
}
// Is either 0 or -1?
if (x['isZero']() || y['eq'](-1)) {
return y;
}
if (y['isZero']() || x['eq'](-1)) {
return x;
}
// Is either Infinity?
if (x['s'] && y['s'] && (!x['c'] || !y['c'])) {
if ((!x['c'] && x['s'] > 0 && y['lt'](0)) || (x['lt'](0) && y['s'] > 0 && !y['c'])) {
return new Decimal(-1); return new Decimal(-1);
} }
return new Decimal(this['c'] ? n : this); return new Decimal(x['c'] ? y : x);
} }
return bitwise(this, n, function (a, b) { return a | b }); return bitwise(x, y, function (a, b) { return a | b });
}; };
@ -1957,6 +1998,7 @@
/* /*
* n ^ n = 0 * n ^ n = 0
* n ^ 0 = n * n ^ 0 = n
* n ^ -1 = ~n
* N ^ n = N * N ^ n = N
* I ^ -I = -1 * I ^ -I = -1
* I ^ n = I * I ^ n = I
@ -1967,15 +2009,46 @@
*/ */
P['xor'] = function (n) { P['xor'] = function (n) {
var Decimal = this['constructor'], var Decimal = this['constructor'],
n = new Decimal(n); x = this['trunc'](),
y = new Decimal(n)['trunc']();
if (this && n && (!this['c'] || !n['c'])) { // Is either NaN?
if (!this['c'] && !n['c']) { if (!x['s'] || !y['s']) {
return new Decimal((this['s'] == n['s']) ? 0 : -1); return new Decimal(NaN);
}
return new Decimal(this['c'] ? n : this);
} }
return bitwise(this, n, function (a, b) { return a ^ b });
// Is either 0?
if (x['isZero']()) {
return y;
}
if (y['isZero']()) {
return x;
}
// Are they equal?
if (x['eq'](y)) {
return new Decimal(0);
}
// Is either -1?
if (x['eq'](-1)) {
return y['not']();
}
if (y['eq'](-1)) {
return x['not']();
}
// Is either Infinity?
if (!x['c'] || !y['c']) {
if (!x['c'] && !y['c']) {
return new Decimal(-1);
}
if (x['s'] != y['s']) {
return new Decimal(-Infinity);
}
return new Decimal(x['c'] ? y : x);
}
return bitwise(x, y, function (a, b) { return a ^ b });
}; };
@ -2020,28 +2093,6 @@
return str; return str;
} }
/* Want to test the speed of this in comparison after testing.
// Reference: http://en.wikipedia.org/wiki/Bitwise_operation#Mathematical_equivalents
function posBitwise(x, y, fn) {
var tmp_external = external,
n = 0,
cap = max(x, y),
Decimal = x['constructor'],
sum = new Decimal(0),
twoPower = Decimal['ONE'];
external = false;
while (twoPower['lte'](cap)) {
var xMod = div( x, twoPower, 0, 1, 1 )['mod'](2)['toNumber']();
var yMod = div( y, twoPower, 0, 1, 1 )['mod'](2)['toNumber']();
sum = sum['plus'](twoPower['times'](fn(xMod, yMod)));
twoPower = twoPower['times'](2);
}
external = tmp_external;
return sum;
}*/
function bitwise(x, y, func) { function bitwise(x, y, func) {
var Decimal = x['constructor']; var Decimal = x['constructor'];
@ -2055,21 +2106,18 @@
external = false; external = false;
var xBits, yBits, var xBits, yBits,
xTrunc = x['trunc'](), xLtZero = x['lt'](0),
yTrunc = y['trunc'](), yLtZero = y['lt'](0);
xLtZero = xTrunc['lt'](0),
yLtZero = yTrunc['lt'](0);
if (xLtZero) { if (xLtZero) {
xBits = '1' + xTrunc['not']()['toString'](2).replace(/[01]/g, function (d) { return +!+d }); xBits = '1' + x['not']()['toString'](2).replace(/[01]/g, function (d) { return +!+d });
} else { } else {
xBits = '0' + xTrunc['toString'](2); xBits = '0' + x['toString'](2);
} }
if (yLtZero) { if (yLtZero) {
yBits = '1' + yTrunc['not']()['toString'](2).replace(/[01]/g, function (d) { return +!+d }); yBits = '1' + y['not']()['toString'](2).replace(/[01]/g, function (d) { return +!+d });
} else { } else {
yBits = '0' + yTrunc['toString'](2); yBits = '0' + y['toString'](2);
} }
if (xBits.length > yBits.length) { if (xBits.length > yBits.length) {
@ -2090,6 +2138,7 @@
if (expFuncVal == 0) { if (expFuncVal == 0) {
outVal = outVal['plus'](Decimal['ONE'])['neg'](); outVal = outVal['plus'](Decimal['ONE'])['neg']();
} }
external = tmpExternal; external = tmpExternal;
return outVal; return outVal;
} }

200188
test/and.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
import random import random
from decimal import * from decimal import *
header_str = """var count = (function plus(Decimal) { header_str = """var count = (function or(Decimal) {
var start = +new Date(), var start = +new Date(),
log, log,
error, error,
@ -107,7 +107,89 @@ header_str = """var count = (function plus(Decimal) {
T(1, '0144', '145'); T(1, '0144', '145');
T(1, '6.1915', '7'); T(1, '6.1915', '7');
T(1, '-1.02', '-1'); T(1, '-1.02', '-1');
T(1, '0.09', '1');
T(1, '-0.0001', '1');
T(1, '8e5', '800001');
T(1, '9E12', '9000000000001');
T(1, '1e-14', '1');
T(1, '3.345E-9', '1');
T(1, '-345.43e+4', '-3454299');
T(1, '-94.12E+0', '-93');
T(1, '', N);
T(1, ' ', N);
T(1, '\\t\\t', N);
T(1, 'ertgrt546', N);
T(1, 'qweqwdewee', N);
T(1, true, N);
T(1, false, N);
T(1, 'e 4.3', N);
T(1, '4 .3', N);
T(1, '4.0 01e', N);
T(1, ' 4.001', '5');
T(1, '4.001 ', '5');
T(1, ' 4.001 ', '5');
T(1, ' 4.001', '5');
T(1, ' 4.0 01', N);
T(1, '4. 001', N);
T(1, '4. 001 ', N);
T(1, ' 4.001e ', N);
T(1, ' 4 .001 e ', N);
T(1, undefined, N);
T(1, null, N);
T(1, Number.POSITIVE_INFINITY, I);
T(1, Number.NEGATIVE_INFINITY, -I);
T(1, new Date(2012, 11, 4), N);
T(1, new Object(), N);
T(1, function () {}, N);
T('0', 0, '0');
T(0, '+0', '0');
T('0', '0', '0');
T(3, -0, '3');
T(9.654, 0, '9');
T(0, '0.001', '0');
T(0, '111.1111111110000', '111');
T(N, '0', N);
T(-1, 1, '-1');
T(-0.01, 0.01, '0');
T(54, -54, '-2');
T(9.99, '-9.99', '-1');
T('0.0000023432495704937', '-0.0000023432495704937', '0');
T(NaN, NaN, N);
T(NaN, N, N);
T(N, NaN, N);
T(N, 4, N);
T(N, '4534534.45435435', N);
T(N, 99999.999, N);
T(Infinity, '354.345341', I);
T(3, -I, -I);
T(-Infinity, -I, -I);
T(-I, -Infinity, -I);
T(I, '-999e999', -1);
T('1.21123e43', -I, -I);
T('-999.0', I, -1);
T('657.342e-45', -I, -I);
T(I, 123, I);
T(100, 100, '100');
T(-999.99, '0.01', '-999');
T('10 ', 4, '14');
T('03.333', -4, '-1');
T(-1, -0.1, '-1');
T(43534.5435, '0.054645', '43534');
T('99999', '1', '99999');
T('3e', 8, N);
T('-3..0', 13, N);
T('0 0', -0.4, N);
T(' +3e0', 4, '7');
T(9.9806, '+ 1', N);
T(' +2 0', '1e1', N);
T('e3', 4, N);
T(' ', 0, N);
T(323, null, N);
T(undefined, undefined, N);
T('undefined', undefined, N);
T(null, null, N);
Decimal.errors = true;
""" """
modes = [ modes = [

200197
test/xor.js Normal file

File diff suppressed because it is too large Load Diff