# Integer

#####

declaration
Integer

MathLib.Integer is the MathLib implementation of (arbitrary precision) integers.

#### Simple example:

    // Create the integer
    var int = new MathLib.Integer('123456789');

    var Integer = (function () {
    		function Integer (integer, options) {
    			if (typeof options === 'undefined') { options = {}; }
    			this.type = 'integer';
    			var i, res, factor, blocksize, inputBase = options.base || 10, base = Math.pow(2, 26), data = [], sign = '+';

    			if (Array.isArray(integer)) {
    				i = integer.length - 1;
    				while (integer[i] === 0) {
    					i--;
    				}
    				data = integer.slice(0, i + 1);
    			}

    			if (typeof integer === 'number') {
    				if (integer === 0) {
    					sign = MathLib.isPosZero(integer) ? '+' : '-';
    					data.push(0);
    				}
    				else {
    					if (integer < 0) {
    						sign = '-';
    						integer = -integer;
    					}
    					while (integer) {
    						data.push(integer % base);
    						integer = Math.floor(integer / base);
    					}
    				}
    			}
    			else if (typeof integer === 'string') {
    				if (integer[0] === '+' || integer[0] === '-') {
    					sign = integer[0];
    					integer = integer.slice(1);
    				}

    				data = [];
    				blocksize = Math.floor(Math.log(Math.pow(2, 53)) / Math.log(inputBase));

    				while (integer.length > blocksize) {
    					data.push(new MathLib.Integer(parseInt(integer.slice(-blocksize), inputBase)));
    					integer = integer.slice(0, -blocksize);
    				}
    				data.push(new MathLib.Integer(parseInt(integer, inputBase)));

    				res = data[data.length - 1];
    				factor = new MathLib.Integer(Math.pow(inputBase, blocksize));
    				for (i = data.length - 2; i >= 0; i--) {
    					res = res.times(factor).plus(data[i]);
    				}

    				data = res.data;

data.push(
Number(
Array.prototype.reduceRight.call(integer, function (old, cur) {
if (old.length === blocksize) {
data.push(Number(cur + old));
return '';
}
return cur + old;
})
)
)

    }

    			if ('sign' in options) {
    				sign = options.sign;
    			}

    			this.data = data;
    			this.sign = sign;
    		}

# toContentMathML

#####

method
Integer.toContentMathML() → string

A content MathML string representation

    Integer.toContentMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			if (options.strict) {
    				return '<csymbol cd="setname1">Z</csymbol>';
    			}
    			return '<integers/>';
    		};

# toLaTeX

#####

method
Integer.toLaTeX() → string

A LaTeX string representation

    Integer.toLaTeX = function () {
    			return 'Integer Ring $\\mathbb{Z}$';
    		};

# toMathML

#####

method
Integer.toMathML() → string

A presentation MathML string representation

    Integer.toMathML = function () {
    			return '<mrow><mtext>Integer Ring</mtext><mi mathvariant="double-struck">Z</mi></mrow>';
    		};

# toString

#####

method
Integer.toString() → string

Custom toString function

    Integer.toString = function () {
    			return 'Integer Ring ℤ';
    		};

# abs

#####

method
Integer.prototype.abs() → Integer

Calculates the absolute value of the integer

    Integer.prototype.abs = function () {
    			return new MathLib.Integer(this.data, {sign: '+'});
    		};

# coerceTo

#####

method
Integer.prototype.coerceTo() → Integer Rational number Complex

Coerces the integer to some other data type

    Integer.prototype.coerceTo = function (type) {
    			var num;

    			if (type === 'integer') {
    				return this.copy();
    			}

    			if (type === 'rational') {
    				return new MathLib.Rational(this, 1);
    			}

    			if (type === 'number') {
    				//TODO Warn when the number is bigger that 2^53
    				num = this.data.reduce(function (old, cur, i) {
    					return old + cur * Math.pow(1e7, i);
    				}, 0);

    				if (this.sign === '-') {
    					num = -num;
    				}

    				return num;
    			}

    			if (type === 'complex') {
    				return new MathLib.Complex(this, 0);
    			}
    		};

# compare

#####

method
Integer.prototype.compare() → Integer

Compares the integer

    Integer.prototype.compare = function (n) {
    			var i;
    			if (this.sign !== n.sign) {
    				if (this.isZero() && n.isZero()) {
    					return 0;
    				}
    				if (this.sign === '+') {
    					return 1;
    				}
    				return -1;
    			}

    			if (this.data.length !== n.data.length) {
    				if (this.sign === '+') {
    					return MathLib.sign(this.data.length - n.data.length);
    				}
    				else {
    					return MathLib.sign(n.data.length - this.data.length);
    				}
    			}
    			else {
    				for (i = this.data.length - 1; i >= 0; i--) {
    					if (this.data[i] !== n.data[i]) {
    						if (this.sign === '+') {
    							return MathLib.sign(this.data[i] - n.data[i]);
    						}
    						else {
    							return MathLib.sign(n.data[i] - this.data[i]);
    						}
    					}
    				}
    				return 0;
    			}
    		};

# conjugate

#####

method
Integer.prototype.conjugate() → Integer

Calculates the complex conjugate of the integer

    Integer.prototype.conjugate = function () {
    			return this.copy();
    		};

# copy

#####

method
Integer.prototype.copy() → Integer

Copy the integer

    Integer.prototype.copy = function () {
    			return new MathLib.Integer(this.data, {sign: this.sign});
    		};

# divide

#####

method
Integer.prototype.divide() → Integer Rational number Complex

Option name | Type | Description
--- | --- | ---
divisor | Integer Rational number Complex | - The divisor

Divides the integer by some other number.

    Integer.prototype.divide = function (divisor) {
    			var divrem;

    			if (divisor.type !== 'integer') {
    				return MathLib.divide.apply(null, MathLib.coerce(this, divisor));
    			}
    			else {
    				divrem = this.divrem(divisor);

    				if (divrem[1].isZero()) {
    					return divrem[0];
    				}

    				return new MathLib.Rational(this, divisor);
    			}
    		};

# divrem

#####

method
Integer.prototype.divrem() → Integer[]

Option name | Type | Description
--- | --- | ---
divisor | Integer | - The divisor

Returns an array containing the quotient and the remainder of the division.

Based on the "Schoolbook Division" in
Karl Hasselström's "Fast Division of Large Integers"
http://www.treskal.com/kalle/exjobb/original-report.pdf

    Integer.prototype.divrem = function (divisor) {
    			var main, subroutine, quot, mult, temp, rem, base = Math.pow(2, 26);

    			// Algorithm 3.1 Schoolbook division subroutine
    			subroutine = function (A, B) {
    				var q, T, temp, B1, n = A.data.length - 1;

    				// Step 1
    				if (A.data[n] >= B.data[n - 1]) {
    					B1 = B.copy();
    					B1.data.unshift(0);
    					temp = subroutine(A.minus(B1), B);
    					return [temp[0].plus(new MathLib.Integer(base)), temp[1]];
    				}

    				// Step 2
    				// nothing to do
    				// Step 3
    				q = new MathLib.Integer(Math.min(Math.floor((A.data[n] * base + A.data[n - 1]) / B.data[n - 1]), base - 1));

    				// Step 4
    				T = B.times(q);

    				// Step 5
    				if (T.compare(A) === 1) {
    					q = q.minus(new MathLib.Integer(1));
    					T = T.minus(B);
    				}

    				// Step 6
    				if (T.compare(A) === 1) {
    					q = q.minus(new MathLib.Integer(1));
    					T = T.minus(B);
    				}

    				// Step 7
    				return [q, A.minus(T)];
    			};

    			// Algorithm 3.2 Schoolbook division
    			main = function (A, B) {
    				var q, r, q1, r1, temp, A1, s, m = A.data.length - 1, n = B.data.length - 1;

    				// Step 1
    				if (m < n) {
    					return [new MathLib.Integer(0), A.copy()];
    				}

    				// Step 2
    				if (m === n) {
    					if (A.compare(B) === -1) {
    						return [new MathLib.Integer(0), A.copy()];
    					}
    					else {
    						return [new MathLib.Integer(1), A.minus(B)];
    					}
    				}

    				// Step 3
    				if (m === n + 1) {
    					return subroutine(A, B);
    				}

    				// Step 4
    				// A1 = floor(A / base^(m-n-1))
    				A1 = new MathLib.Integer(A.data.slice(m - n - 1));
    				s = new MathLib.Integer(A.data.slice(0, m - n - 1));

    				// Step 5
    				temp = subroutine(A1, B);
    				q1 = temp[0];
    				r1 = temp[1];

    				// Step 6
    				temp = main(new MathLib.Integer(s.data.concat(r1.data)), B);
    				q = temp[0];
    				r = temp[1];

    				// Step 7
    				return [new MathLib.Integer(q.data.concat(q1.data)), r];
    			};

    			if (this.isZero()) {
    				return [new MathLib.Integer(0), new MathLib.Integer(0)];
    			}

    			if (divisor.data[divisor.data.length - 1] < base / 2) {
    				mult = new MathLib.Integer(Math.ceil(base / (2 * divisor.data[divisor.data.length - 1])));
    				temp = main(this.abs().times(mult), divisor.abs().times(mult));
    				quot = temp[0];
    				rem = new MathLib.Integer(temp[1].data[0] / mult.data[0]);
    			}
    			else {
    				temp = main(this.abs(), divisor.abs());
    				quot = temp[0];
    				rem = temp[1];
    			}

    			if (this.sign === '-' && !rem.isZero()) {
    				quot = quot.plus(new MathLib.Integer(1));
    				rem = divisor.abs().minus(rem);
    			}

    			if (this.sign !== divisor.sign) {
    				quot = quot.negative();
    			}

    			return [quot, rem];
    		};

# isEqual

#####

method
Integer.prototype.isEqual() → boolean

Option name | Type | Description
--- | --- | ---
n | any | The number to check

Checks if the current integer is equal to some other number

    Integer.prototype.isEqual = function (n) {
    			var i, ii;

    			if (n.type !== 'integer') {
    				return MathLib.isEqual(MathLib.coerce(this, n));
    			}
    			else {
    				if (this.sign !== n.sign) {
    					if (this.isZero() && n.isZero()) {
    						return true;
    					}
    					return false;
    				}

    				if (this.data.length !== n.data.length) {
    					return false;
    				}

    				for (i = 0, ii = this.data.length; i < ii; i++) {
    					if (this.data[i] !== n.data[i]) {
    						return false;
    					}
    				}

    				return true;
    			}
    		};

# isFinite

#####

method
Integer.prototype.isFinite() → boolean

All integers are finite

    Integer.prototype.isFinite = function () {
    			return true;
    		};

# isNaN

#####

method
Integer.prototype.isNaN() → boolean

No Integer is NaN

    Integer.prototype.isNaN = function () {
    			return false;
    		};

# isUnit

#####

method
Integer.prototype.isUnit() → boolean

Checks if the integer is a unit in the ring of integers or not

    Integer.prototype.isUnit = function () {
    			var i, ii;

    			for (i = 1, ii = this.data.length; i < ii; i++) {
    				if (this.data[i] !== 0) {
    					return false;
    				}
    			}

    			if (this.data[0] === 1) {
    				return true;
    			}

    			return false;
    		};

# isZero

#####

method
Integer.prototype.isZero() → boolean

Checks if the integer is zero or not

    Integer.prototype.isZero = function () {
    			return this.data.every(function (x) {
    				return x === 0;
    			});
    		};

# minus

#####

method
Integer.prototype.minus() → Integer

Option name | Type | Description
--- | --- | ---
n | Integer Rational number Complex | - The number to subtract

Subtracts a number from the current integer

    Integer.prototype.minus = function (n) {
    			var i, ii, temp, resPos, A, B, data = [], carry = 0, sign = '+', base = Math.pow(2, 26);

    			if (n.type !== 'integer') {
    				return MathLib.minus.apply(null, MathLib.coerce(this, n));
    			}
    			else {
    				if (this.sign === '-') {
    					if (n.sign === '-') {
    						return n.negative().minus(this.negative());
    					}
    					else {
    						temp = this.negative().plus(n);
    						temp.sign = '-';
    						return temp;
    					}
    				}
    				else {
    					if (n.sign === '-') {
    						return this.plus(n.negative());
    					}
    				}

    				if (this.data.length !== n.data.length) {
    					resPos = this.data.length > n.data.length;

    					while (this.data.length < n.data.length) {
    						this.data.push(0);
    					}
    					while (this.data.length > n.data.length) {
    						n.data.push(0);
    					}
    				}
    				else {
    					for (i = this.data.length - 1; i >= 0; i--) {
    						if (this.data[i] !== n.data[i]) {
    							resPos = this.data[i] > n.data[i];
    							break;
    						}
    					}
    					if (typeof resPos === 'undefined') {
    						return new MathLib.Integer(0);
    					}
    				}

    				if (resPos) {
    					A = this;
    					B = n;
    					sign = '+';
    				}
    				else {
    					A = n;
    					B = this;
    					sign = '-';
    				}

    				for (i = 0, ii = A.data.length; i < ii; i++) {
    					temp = A.data[i] - B.data[i] + carry;
    					carry = Math.floor(temp / base);
    					data[i] = MathLib.mod(temp, base);
    				}

    				return new MathLib.Integer(data, {sign: sign});
    			}
    		};

# mod

#####

method
Integer.prototype.mod() → Integer number

Option name | Type | Description
--- | --- | ---
n | Integer number | - The number with which the current integer should be reduced

Reduces the integer modulo an other number.

    Integer.prototype.mod = function (n) {
    			if (n.type !== 'integer') {
    				return MathLib.mod.apply(null, MathLib.coerce(this, n));
    			}
    			else {
    				return this.divrem(n)[1];
    			}
    		};

# negative

#####

method
Integer.prototype.negative() → Integer

Calculates the negative integer

    Integer.prototype.negative = function () {
    			return new MathLib.Integer(this.data, {sign: this.sign === '-' ? '+' : '-'});
    		};

# plus

#####

method
Integer.prototype.plus() → Integer

Option name | Type | Description
--- | --- | ---
n | Integer Rational number Complex | - The number to add

Adds a number to the current integer

    Integer.prototype.plus = function (n) {
    			var i, ii, temp, data = [], carry = 0, base = Math.pow(2, 26);

    			if (n.type !== 'integer') {
    				return MathLib.plus(MathLib.coerce(this, n));
    			}
    			else {
    				if (this.sign === '-') {
    					if (n.sign === '+') {
    						this.sign = '+';
    						return n.minus(this);
    					}
    				}
    				else if (n.sign === '-') {
    					n.sign = '+';
    					return this.minus(n);
    				}

    				if (this.data.length !== n.data.length) {
    					while (this.data.length < n.data.length) {
    						this.data.push(0);
    					}
    					while (this.data.length > n.data.length) {
    						n.data.push(0);
    					}
    				}

    				for (i = 0, ii = this.data.length; i < ii; i++) {
    					temp = this.data[i] + n.data[i] + carry;

    					data[i] = temp % base;
    					carry = Math.floor(temp / base);
    				}

    				if (carry !== 0) {
    					data[i] = carry;
    				}

    				return new MathLib.Integer(data, {sign: this.sign});
    			}
    		};

# pow

#####

method
Integer.prototype.pow() → Integer Rational

Option name | Type | Description
--- | --- | ---
exponent | Integer Rational number Complex | - The exponent

Raises the integer to a certain power.

    Integer.prototype.pow = function (exponent) {
    			var powInt, result;

    			if (exponent.type !== 'integer') {
    				return MathLib.pow.apply(null, MathLib.coerce(this, exponent));
    			}
    			else {
    				powInt = function (b, e) {
    					var res, i, half = [], carry = 0;

    					if (e.data.length === 1 && e.data[0] === 1) {
    						return b;
    					}

    					for (i = e.data.length - 1; i >= 0; i--) {
    						half[i] = Math.floor(e.data[i] / 2) + carry;

    						if (e.data[i] % 2) {
    							carry = 5e6;
    						}
    						else {
    							carry = 0;
    						}
    					}

    					res = powInt(b, new MathLib.Integer(half));
    					res = res.times(res);

    					if (e.data[0] % 2) {
    						res = res.times(b);
    					}

    					return res;
    				};

    				result = powInt(this, exponent);

    				if (exponent.sign === '-') {
    					return new MathLib.Rational(new MathLib.Integer('1'), result);
    				}

    				return result;
    			}
    		};

# times

#####

method
Integer.prototype.times() → Integer

Option name | Type | Description
--- | --- | ---
n | Integer Rational number Complex | - The number to multiply

Multiplies a number to the current integer

    Integer.prototype.times = function (n) {
    			var i, ii, j, jj, temp, data = [], carry = 0, base = Math.pow(2, 26);

    			if (n.type !== 'integer') {
    				return MathLib.times(MathLib.coerce(this, n));
    			}
    			else {
    				for (i = 0, ii = this.data.length; i < ii; i++) {
    					for (j = 0, jj = n.data.length; j < jj; j++) {
    						if (data[i + j] === undefined) {
    							data[i + j] = this.data[i] * n.data[j];
    						}
    						else {
    							data[i + j] += this.data[i] * n.data[j];
    						}
    					}
    				}

    				for (i = 0, ii = this.data.length + n.data.length - 1; i < ii; i++) {
    					temp = data[i] + carry;
    					carry = Math.floor(temp / base);
    					data[i] = temp % base;
    				}
    				data[i] = carry;

    				return new MathLib.Integer(data, {sign: this.sign === n.sign ? '+' : '-'});
    			}
    		};

# toContentMathML

#####

method
Integer.prototype.toContentMathML() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

A content MathML string representation

    Integer.prototype.toContentMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var base = options.base || 10;

    			// In section 4.2.1.3 in the MathML 3 specification
    			// under "Rewrite: cn based_integer" it says
    			// "A base attribute with value 10 is simply removed"
    			if (base === 10) {
    				return '<cn type="integer">' + this.toString() + '</cn>';
    			}
    			else if (options.strict) {
    				return '<apply><csymbol cd="nums1">based_integer</csymbol><cn>' + base + '</cn><cs>' + this.toString({base: base}) + '</cs></apply>';
    			}
    			else {
    				return '<cn type="integer" base="' + base + '">' + this.toString({base: base}) + '</cn>';
    			}
    		};

# toLaTeX

#####

method
Integer.prototype.toLaTeX() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

A LaTeX string representation

    Integer.prototype.toLaTeX = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var base = options.base || 10, str = this.toString({base: base, sign: options.sign});

    			if (options.baseSubscript) {
    				str += '_{' + base + '}';
    			}

    			return str;
    		};

# toMathML

#####

method
Integer.prototype.toMathML() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

A presentation MathML string representation

    Integer.prototype.toMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var base = options.base || 10, str = '<mn>' + this.toString({base: base, sign: options.sign}) + '</mn>';

    			if (options.baseSubscript) {
    				str = '<msub>' + str + '<mn>' + base + '</mn></msub>';
    			}

    			return str;
    		};

# toString

#####

method
Integer.prototype.toString() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Custom toString function

    Integer.prototype.toString = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var div, rem, temp, base = options.base || 10, blocksize = Math.floor(Math.log(Math.pow(2, 26) - 1) / Math.log(base)), factor = new MathLib.Integer(Math.pow(base, blocksize)), n = this.abs(), str = '';

    			if (n.isZero()) {
    				str = '0';
    			}
    			else {
    				while (!n.isZero()) {
    					temp = n.divrem(factor);
    					div = temp[0];
    					rem = temp[1];

    					str = ('000000' + rem.data[0].toString(base)).slice(-blocksize) + str;
    					n = div;
    				}

    				str = str.replace(/^0+/, '');

    				if (this.sign === '-') {
    					str = '-' + str;
    				}
    			}

    			if (options.sign && (this.sign === '+' || this.isZero())) {
    				str = '+' + str;
    			}

    			if (options.baseSubscript) {
    				if (base > 9) {
    					str += '&#x208' + Math.floor(base / 10) + ';';
    				}
    				str += '&#x208' + (base % 10) + ';';
    			}

    			return str;
    		};
    		return Integer;
    	})();
    	MathLib.Integer = Integer;
    })(MathLib || (MathLib = {}));