Source Code
/**
* Infinite Precision Javascript Library
*
* Author: Kyle W T Sherman
*/
/**
* Infinite Precision Number Class
*/
var IpNum = function() {
this.base = new Array();
this.radix = new Array();
this.sign = 1;
this.removeZeros = function() {
while (this.base.length > 1 && this.base[0] == 0) this.base.shift();
while (this.radix.length > 0 && this.radix[this.radix.length - 1] == 0) this.radix.pop();
}
this.getArray = function() {
var r = new Array();
r[0] = new Array();
r[1] = new Array();
r[2] = new Array();
for (var i = 0; i < this.base.length; i++) {
r[0][i] = this.base[i];
}
for (var i = 0; i < this.radix.length; i++) {
r[1][i] = this.radix[i];
}
r[2] = this.sign;
return r;
}
this.setArray = function(parts) {
this.base = parts[0];
this.radix = parts[1];
this.sign = parts[2];
this.removeZeros();
}
this.getString = function() {
var r = '';
if (this.sign == -1) r += '-';
if (this.base.length > 0) {
for (var i = 0; i < this.base.length; i++) {
r += this.base[i];
}
}
if (this.radix.length > 0) {
r += '.';
for (var i = 0; i < this.radix.length; i++) {
r += this.radix[i];
}
}
return r;
}
this.setString = function (str) {
this.base = new Array();
this.radix = new Array();
this.sign = 1;
var loc = 0;
var len = str.length;
if (len > 0 && str.charAt(loc) == '-') {
this.sign = -1;
loc++;
}
while (loc < len && str.charAt(loc) !== '.') {
this.base.push(parseInt(str.charAt(loc)));
loc++;
}
if (loc < len) {
loc++;
while (loc < len) {
this.radix.push(parseInt(str.charAt(loc)));
loc++;
}
}
this.removeZeros();
}
this.equals = function (num) {
if (this.sign !== num.sign) return false;
if (this.base.length !== num.base.length) return false;
if (this.radix.length !== num.radix.length) return false;
for (var i = 0; i < this.base.length; i++) {
if (this.base[i] !== num.base[i]) return false;
}
for (var i = 0; i < this.radix.length; i++) {
if (this.radix[i] !== num.radix[i]) return false;
}
return true;
}
this.abs = function () {
var r = new IpNum();
r.base = this.base;
r.radix = this.radix;
r.sign = 1;
return r;
}
this.gt = function (num) {
if (this.sign !== num.sign) {
if (this.sign == 1) return true;
else return false;
} else if (this.sign == -1) {
if (this.equals(num)) return false;
else if (this.abs().gt(num.abs())) return false;
else return true;
} else {
if (this.base.length > num.base.length) return true;
if (this.base.length < num.base.length) return false;
for (var i = 0; i < this.base.length; i++) {
if (this.base[i] > num.base[i]) return true;
if (this.base[i] < num.base[i]) return false;
}
for (var i = 0; i < this.radix.length; i++) {
if ((this.radix[i] || 0) > (num.radix[i] || 0)) return true;
if ((this.radix[i] || 0) < (num.radix[i] || 0)) return false;
}
return false;
}
}
this.lt = function (num) {
return num.gt(this);
}
this.gte = function (num) {
if (this.gt(num)) return true;
if (this.equals(num)) return true;
return false;
}
this.lte = function (num) {
if (this.lt(num)) return true;
if (this.equals(num)) return true;
return false;
}
this.add = function (num) {
var result = new IpNum();
var r = new Array(3);
r[0] = new Array();
r[1] = new Array();
var n1;
var n2;
var c = 0;
var len = 0;
var sign = 1;
if (this.sign !== num.sign) {
if (this.abs().gt(num.abs())) {
sign = this.sign;
n1 = this.getArray();
n2 = num.getArray();
} else {
sign = num.sign;
n1 = num.getArray();
n2 = this.getArray();
}
while (n1[1].length > n2[1].length) {
n2[1].push(0);
}
while (n2[1].length > n1[1].length) {
n1[1].push(0);
}
len = n1[1].length;
for (var i = len - 1; i >= 0; i--) {
var d = n1[1][i] - n2[1][i] - c;
if (d < 0) {
d += 10;
c = 1;
} else {
c = 0;
}
r[1].unshift(d);
}
while (n1[0].length > n2[0].length) {
n2[0].unshift(0);
}
while (n2[0].length > n1[0].length) {
n1[0].unshift(0);
}
len = n1[0].length;
for (var i = len - 1; i >= 0; i--) {
var d = n1[0][i] - n2[0][i] - c;
if (d < 0) {
d = d + 10;
c = 1;
} else {
c = 0;
}
r[0].unshift(d);
}
} else {
if (this.sign == 1) sign = 1;
else sign = -1;
n1 = this.getArray();
n2 = num.getArray();
while (n1[1].length > n2[1].length) {
n2[1].push(0);
}
while (n2[1].length > n1[1].length) {
n1[1].push(0);
}
len = n1[1].length;
for (var i = len - 1; i >= 0; i--) {
var d = n1[1][i] + n2[1][i] + c;
if (d < 10) {
c = 0;
} else {
d = d - 10;
c = 1;
}
r[1].unshift(d);
}
while (n1[0].length > n2[0].length) {
n2[0].unshift(0);
}
while (n2[0].length > n1[0].length) {
n1[0].unshift(0);
}
len = n1[0].length;
for (var i = len - 1; i >= 0; i--) {
var d = n1[0][i] + n2[0][i] + c;
if (d < 10) {
c = 0;
} else {
d = d - 10;
c = 1;
}
r[0].unshift(d);
}
if (c !== 0) r[0].unshift(c);
}
r[2] = sign;
result.setArray(r);
return result;
}
this.sub = function (num) {
var n = new IpNum();
n.setArray(num.getArray());
if (n.sign == 1) n.sign = -1;
else n.sign = 1;
return this.add(n);
}
var mulAdd = function (num1, num2) {
var r = new Array();
var c = 0;
while (num1.length > num2.length) {
num2.unshift(0);
}
while (num2.length > num1.length) {
num1.unshift(0);
}
for (var i=num1.length - 1; i >= 0; i--) {
var d = num1[i] + num2[i] + c;
if (d < 10) {
c = 0;
} else {
d = d - 10;
c = 1;
}
r.unshift(d);
}
return r;
}
this.mul = function (num) {
var result = new IpNum();
var r = new Array(3);
r[0] = new Array();
r[1] = new Array();
var n1 = this.getArray();
var n2 = num.getArray();
var sign = 1;
if (n1[2] !== n2[2]) sign = -1;
var m1 = n1[0];
m1 = m1.concat(n1[1]);
var m2 = n2[0];
m2 = m2.concat(n2[1]);
var d = n1[1].length + n2[1].length;
var m3 = new Array();
for (var i = m1.length - 1; i >= 0; i--) {
var c = 0;
var os = m1.length - 1 - i;
var m = new Array();
for (var j = m2.length - 1; j >= 0; j--) {
var n = m1[i] * m2[j] + c;
c = (n - (n % 10)) / 10;
n = n - (c * 10);
m.unshift(n);
}
if (c !== 0) m.unshift(c);
for (var j = 0; j < os; j++) {
m.push(0);
}
m3 = mulAdd(m3, m);
}
for (i = 0; i < d; i++) r[1].unshift(m3.pop());
var len = m3.length;
for (i = 0; i < len; i++) r[0].unshift(m3.pop());
r[2] = sign;
result.setArray(r);
return result;
}
this.div = function (num) {
var result = new IpNum();
var r = new Array(3);
r[0] = new Array();
r[1] = new Array();
var n1 = this.getArray();
var n2 = num.getArray();
var sign = 1;
if (n1[2] !== n2[2]) sign = -1;
var m1 = n1[0];
m1 = m1.concat(n1[1]);
var m2 = n2[0];
m2 = m2.concat(n2[1]);
var d = n1[1].length + n2[1].length;
var m3 = new Array();
for (var i = m1.length - 1; i >= 0; i--) {
var c = 0;
var os = m1.length - 1 - i;
var m = new Array();
for (var j = m2.length - 1; j >= 0; j--) {
var n = m1[i] * m2[j] + c;
c = (n - (n % 10)) / 10;
n = n - (c * 10);
m.unshift(n);
}
if (c !== 0) m.unshift(c);
for (var j = 0; j < os; j++) {
m.push(0);
}
m3 = mulAdd(m3, m);
}
for (i = 0; i < d; i++) r[1].unshift(m3.pop());
var len = m3.length;
for (i = 0; i < len; i++) r[0].unshift(m3.pop());
r[2] = sign;
result.setArray(r);
return result;
}
this.fact = function () {
var num = new IpNum();
num.setArray(this.getArray());
var n = num.getArray();
var zero = new IpNum();
zero.setString('0');
var one = new IpNum();
one.setString('1');
var r;
if (n[2] == 1 && n[1].length == 0) {
r = new IpNum();
r.setString('1');
while (num.gt(zero)) {
r = r.mul(num);
num = num.sub(one);
}
}
return r;
}
this.floor = function () {
var r = new IpNum();
r.setArray(this.getArray());
r.radix = new Array();
return r;
}
this.ceil = function () {
var r = new IpNum();
r.setArray(this.getArray());
if (r.radix.length > 0) {
var one = new IpNum();
if (r.sign == 1) {
one.setString('1');
} else {
one.setString('-1');
}
r = r.add(one);
}
r.radix = new Array();
return r;
}
this.round = function() {
if (this.radix.length > 0 && this.radix[0] >= 5) return this.ceil();
else return this.floor();
}
}