Home Reference Source

src/math/core/BigInteger.js

/**
 * The script is part of konpeito.
 * 
 * AUTHOR:
 *  natade (http://twitter.com/natadea)
 * 
 * LICENSE:
 *  The MIT license https://opensource.org/licenses/MIT
 */

import Polyfill from "../tools/Polyfill.js";
import Random from "./tools/Random.js";
import Fraction from "./Fraction.js";
import BigDecimal from "./BigDecimal.js";
import Complex from "./Complex.js";
import Matrix from "./Matrix.js";
import MathContext from "./context/MathContext.js";
import KonpeitoInteger from "./base/KonpeitoInteger.js";

/**
 * BigInteger type argument.
 * - BigInteger
 * - number
 * - string
 * - Array<string|number>
 * - {toBigInteger:function}
 * - {intValue:number}
 * - {toString:function}
 * 
 * Initialization can be performed as follows.
 * - 1200, "1200", "12e2", "1.2e3", ["1200", 10]
 * - "0xff", ["ff", 16]
 * - "0o01234567", ["01234567", 8]
 * - "0b0110101", ["0110101", 2]
 * @typedef {BigInteger|number|boolean|string|Array<string|number>|{toBigInteger:function}|{intValue:number}|{toString:function}} KBigIntegerInputData
 */

/**
 * Random number class to be used when the random number class is not set.
 * @type {Random}
 * @ignore
 */
let DEFAULT_RANDOM = new Random();

/**
 * Collection of functions used in BigInteger.
 * @ignore
 */
class BigIntegerTool {

	/**
	 * Return a hex array from a string containing numbers.
	 * @param {string} text - String containing a number (remove the negative sign).
	 * @param {number} radix - Base number.
	 * @returns {Array<number>} Hex array.
	 */
	static toHexadecimalArrayFromPlainString(text, radix) {
		// 下の変換をすることで、2進数での変換時に内部のforの繰り返す回数が減る
		// v0.03 出来る限りまとめてn進数変換する
		const max_num = 0x3FFFFFFF;
		const keta = Math.floor( Math.log(max_num) / Math.log(radix) );

		/**
		 * @type {Array<number>}
		 */
		let x = [];
		
		/**
		 * @type {Array<number>}
		 */
		const y = [];
		const len = Math.ceil(text.length / keta);
		let offset = text.length;
		for(let i = 0; i < len; i++ ) {
			offset -= keta;
			if(offset >= 0) {
				x[i] = parseInt(text.substring(offset, offset + keta), radix);
			}
			else {
				x[i] = parseInt(text.substring(0, offset + keta), radix);
			}
		}
		const calcradix = Math.round(Math.pow(radix, keta));
		// v0.03ここまで
		// 2で割っていくアルゴリズムで2進数に変換する
		while(x.length !==  0) {
			// 2で割っていく
			// 隣の桁でたcarryはradix進数をかけて桁上げしてる
			let carry = 0;
			for(let i = x.length - 1; i >= 0; i--) {
				const a = x[i] + carry * calcradix;
				x[i]  = a >>> 1;
				carry = a & 1;
			}
			// 1余るかどうかをテストする
			y[y.length] = carry;
			// xが0になっている部分は削除していく
			if(x[x.length - 1] === 0) {
				x.pop();
			}
		}
		// メモリ節約のため1つの変数(16ビット)に収めるだけ収めていく
		x = [];
		for(let i = 0; i < y.length; i++) {
			x[i >>> 4] |= y[i] << (i & 0xF);
		}
		return x;
	}

	/**
	 * Remove exponent notation in strings representing unsigned numbers.
	 * @param {string} ntext 
	 * @returns {string}
	 */
	static toPlainStringFromString(ntext) {
		let scale = 0;
		let buff;
		// 正規化
		let text = ntext.replace(/\s/g, "").toLowerCase();

		/**
		 * @type {Array<string>}
		 */
		const number_text = [];
		// 整数部を抽出
		buff = text.match(/^[0-9]+/);
		if(buff !== null) {
			buff = buff[0];
			text = text.substr(buff.length);
			number_text.push(buff);
		}
		// 小数部があるか
		buff = text.match(/^\.[0-9]+/);
		if(buff !== null) {
			buff = buff[0];
			text = text.substr(buff.length);
			buff = buff.substr(1);
			scale = scale + buff.length;
			number_text.push(buff);
		}
		// 指数表記があるか
		buff = text.match(/^e[+-]?[0-9]+/);
		if(buff !== null) {
			buff = buff[0].substr(1);
			scale -= parseInt(buff, 10);
		}
		// 出力用の文字を作成
		let output_string;
		if(scale === 0) {
			output_string = number_text.join("");
		}
		if(scale < 0) {
			for(let i = 0; i < -scale; i++) {
				number_text.push("0");
			}
			output_string = number_text.join("");
		}
		else if(scale > 0) {
			output_string = number_text.join("");
			output_string = output_string.substring(0, output_string.length - scale);
			output_string = output_string.length !== 0 ? output_string : "0";
		}
		return output_string;
	}

	/**
	 * Return a hexadecimal array from the number.
	 * @param {number|boolean} number - Target number.
	 * @returns {{element : Array<number>, state : number}} Data for BigInteger.
	 */
	static toBigIntegerFromNumber(number) {
		const value = typeof number !== "boolean" ? number : (number ? 1 : 0);
		if(!isFinite(value)) {
			if(value === Number.POSITIVE_INFINITY) {
				return {
					state : BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY,
					element : []
				};
			}
			if(value === Number.NEGATIVE_INFINITY) {
				return {
					state : BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY,
					element : []
				};
			}
			else {
				return {
					state : BIGINTEGER_NUMBER_STATE.NOT_A_NUMBER,
					element : []
				};
			}
		}
		let x;
		let state;
		if(Math.abs(value) < 1.0 - Number.EPSILON) {
			return {
				element : [],
				state : BIGINTEGER_NUMBER_STATE.ZERO
			};
		}
		else if(value > 0) {
			state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
			x = value;
		}
		else {
			state = BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER;
			x = -value;
		}
		if(x > 0xFFFFFFFF) {
			return {
				element : BigIntegerTool.toHexadecimalArrayFromPlainString(BigIntegerTool.toPlainStringFromString(x.toFixed()), 10),
				state : state
			};
		}
		else {
			if( Math.abs(value - Math.round(value)) <= Number.EPSILON) {
				x = Math.round(x);
			}
			else {
				x = Math.trunc(x);
			}
			/**
			 * @type {Array<number>}
			 */
			const y = [];
			while(x !==  0) {
				y[y.length] = x & 1;
				x >>>= 1;
			}
			/**
			 * @type {Array<number>}
			 */
			const z = [];
			for(let i = 0; i < y.length; i++) {
				z[i >>> 4] |= y[i] << (i & 0xF);
			}
			
			return {
				element : z,
				state : state
			};
		}
	}

	/**
	 * Return string of number from a hexadecimal array.
	 * @param {Array<number>} binary - Hex array.
	 * @param {number} radix - Base number.
	 * @returns {Array<number>} Numeric array for each digit in the specified base number.
	 */
	static toPlainStringFromHexadecimalArray(binary, radix) {

		/**
		 * @param {Array<number>} x1 
		 * @param {Array<number>} x2 
		 * @param {Array<number>} y 
		 */
		const add = function(x1, x2, y) {
			const size = x1.length;
			let carry = 0;
			for(let i = 0; i < size; i++) {
				y[i] = x1[i] + ((x2.length >= (i + 1)) ? x2[i] : 0) + carry;
				if(y[i] >= radix) {
					carry = 1;
					y[i] -= radix;
				}
				else {
					carry = 0;
				}
			}
			if(carry === 1) {
				y[size] = 1;
			}
		};
		const y = [0];
		const t = [1];
		for(let i = 0;i < binary.length;i++) {
			for(let j = 0; j < 16; j++) {
				if((binary[i] >>> j) & 1) {
					add(t, y, y);
				}
				add(t, t, t);
			}
		}
		return y;
	}

	/**
	 * @param {number[]} element
	 * @returns {boolean}
	 * @ignore
	 */
	static isZeroElement(element) {
		if(element.length === 0) {
			return true;
		}
		if((element.length === 1 && element[0] === 0)) {
			return true;
		}
		return false;
	}

	/**
	 * Return data to represent multi-precision numbers from strings.
	 * @param {string} text - String containing a number.
	 * @param {number} [radix=10] - Base number.
	 * @returns {{element : Array<number>, state : number}} Data for BigInteger.
	 */
	static toBigIntegerFromString(text, radix) {
		let x = text.replace(/\s/g, "").toLowerCase();
		// 特殊な状態
		{
			if(/nan/.test(text)) {
				return {
					state : BIGINTEGER_NUMBER_STATE.NOT_A_NUMBER,
					element : []
				};
			}
			else if(/inf/.test(text)) {
				if(!/-/.test(text)) {
					return {
						state : BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY,
						element : []
					};
				}
				else {
					return {
						state : BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY,
						element : []
					};
				}
			}
		}
		const sign_text = x.match(/^[-+]+/);

		/**
		 * @type {Array<number>}
		 */
		let element     = [];
		let state       = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;

		if(sign_text !== null) {
			const hit_text = sign_text[0];
			x = x.substring(hit_text.length, x.length);
			if(hit_text.indexOf("-") !== -1) {
				state = BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER;
			}
		}

		if(radix) {
			element = BigIntegerTool.toHexadecimalArrayFromPlainString(x, radix);
		}
		else if(/^0x/.test(x)) {
			element = BigIntegerTool.toHexadecimalArrayFromPlainString(x.substring(2, x.length), 16);
		}
		else if(/^0b/.test(x)) {
			element = BigIntegerTool.toHexadecimalArrayFromPlainString(x.substring(2, x.length), 2);
		}
		else if(/^0o/.test(x)) {
			element = BigIntegerTool.toHexadecimalArrayFromPlainString(x.substring(2, x.length), 8);
		}
		else {
			x = BigIntegerTool.toPlainStringFromString(x);
			element = BigIntegerTool.toHexadecimalArrayFromPlainString(x, 10);
		}
		// "0"の場合がある為
		if(BigIntegerTool.isZeroElement(element)) {
			element = [];
			state = BIGINTEGER_NUMBER_STATE.ZERO;
		}

		return {
			element : element,
			state : state
		};
	}
}

/**
 * Numeric state.
 * @type {{ZERO:number, POSITIVE_NUMBER:number, NEGATIVE_NUMBER:number, NOT_A_NUMBER:number, POSITIVE_INFINITY:number, NEGATIVE_INFINITY:number}}
 * @ignore
 */
const BIGINTEGER_NUMBER_STATE = {
	ZERO : 0,
	POSITIVE_NUMBER : 1,
	NEGATIVE_NUMBER : 2,
	NOT_A_NUMBER : 3,
	POSITIVE_INFINITY : 4,
	NEGATIVE_INFINITY : 5
};

// 内部では1変数内の中の16ビットごとに管理
// 2変数で16ビット*16ビットで32ビットを表す
// this.element	...	16ビットごとに管理
//
// 本クラスはイミュータブルです。
// 内部の「_」から始まるメソッドは内部計算用で非公開です。またミュータブルです。

/**
 * Arbitrary-precision integer class (immutable).
 */
export default class BigInteger extends KonpeitoInteger {

	/**
	 * Create an arbitrary-precision integer.
	 * 
	 * Initialization can be performed as follows.
	 * - 1200, "1200", "12e2", "1.2e3", ["1200", 10]
	 * - "0xff", ["ff", 16]
	 * - "0o01234567", ["01234567", 8]
	 * - "0b0110101", ["0110101", 2]
	 * @param {KBigIntegerInputData} [number] - Numeric data. See how to use the function.
	 */
	constructor(number) {
		super();
		
		/**
		 * Numeric state.
		 * @private
		 * @type {number}
		 */
		this.state = BIGINTEGER_NUMBER_STATE.ZERO;

		if(arguments.length === 0) {

			/**
			 * An integer consisting of 16 bits per element of the array.
			 * @private
			 * @type {Array<number>}
			 */
			this.element     = [];

		}
		else if(arguments.length === 1) {
			if(number instanceof BigInteger) {
				this.element = number.element.slice(0);
				this.state = number.state;
			}
			else if(typeof number === "number") {
				const x = BigIntegerTool.toBigIntegerFromNumber(number);
				this.element = x.element;
				this.state = x.state;
			}
			else if(typeof number === "string") {
				const x = BigIntegerTool.toBigIntegerFromString(number);
				this.element = x.element;
				this.state = x.state;
			}
			else if(number instanceof Array) {
				if((number.length === 2) && (typeof number[0] === "string" && (typeof number[1] === "number"))) {
					const x = BigIntegerTool.toBigIntegerFromString(number[0], number[1]);
					this.element = x.element;
					this.state = x.state;
				}
				else {
					throw "BigInteger Unsupported argument " + arguments;
				}
			}
			else if(typeof number === "object") {
				if("toBigInteger" in number) {
					const x = number.toBigInteger();
					this.element = x.element;
					this.state = x.state;
				}
				else if("intValue" in number) {
					const x = BigIntegerTool.toBigIntegerFromNumber(number.intValue);
					this.element = x.element;
					this.state = x.state;
				}
				else {
					const x = BigIntegerTool.toBigIntegerFromString(number.toString());
					this.element = x.element;
					this.state = x.state;
				}
			}
			else if(typeof number === "boolean") {
				const x = BigIntegerTool.toBigIntegerFromNumber(number);
				this.element = x.element;
				this.state = x.state;
			}
			else {
				throw "BigInteger Unsupported argument " + number;
			}
		}
		else {
			throw "BigInteger Unsupported argument " + number;
		}
	}

	/**
	 * Create an entity object of this class.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger}
	 */
	static create(number) {
		if(number instanceof BigInteger) {
			return number;
		}
		else {
			return new BigInteger(number);
		}
	}

	/**
	 * Create an arbitrary-precision integer.
	 * - Does not support strings using exponential notation.
	 * - If you want to initialize with the specified base number, please set up with an array ["ff", 16].
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger}
	 */
	static valueOf(number) {
		return BigInteger.create(number);
	}

	/**
	 * Convert to BigInteger.
	 * If type conversion is unnecessary, return the value as it is.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger}
	 * @ignore
	 */
	static _toBigInteger(number) {
		if(number instanceof BigInteger) {
			return number;
		}
		else {
			return new BigInteger(number);
		}
	}

	/**
	 * Convert to real number.
	 * @param {KBigIntegerInputData} number 
	 * @returns {number}
	 * @ignore
	 */
	static _toFloat(number) {
		if(typeof number === "number") {
			return number;
		}
		else if(number instanceof BigInteger) {
			return number.doubleValue;
		}
		else {
			return (new BigInteger(number)).doubleValue;
		}
	}

	/**
	 * Convert to integer.
	 * @param {KBigIntegerInputData} number 
	 * @returns {number}
	 * @ignore
	 */
	static _toInteger(number) {
		if(typeof number === "number") {
			return Math.trunc(number);
		}
		else if(number instanceof BigInteger) {
			return number.intValue;
		}
		else {
			return (new BigInteger(number)).intValue;
		}
	}

	/**
	 * Random number of specified bit length.
	 * @param {KBigIntegerInputData} bitsize - Bit length.
	 * @param {Random} [random] - Class for creating random numbers.
	 * @returns {BigInteger}
	 */
	static createRandomBigInteger(bitsize, random) {
		const rand = (random !== undefined && random instanceof Random) ? random : DEFAULT_RANDOM;
		const x = new BigInteger();
		const bits = BigInteger._toInteger(bitsize);
		const size = ((bits - 1) >> 4) + 1;
		if(bits === 0) {
			return BigInteger.ZERO;
		}
		let r;
		for(let i = 0, j = 0; i < size; i++) {
			if(j === 0) {
				r = rand.nextInt(); // 32ビットずつ作成する
				x.element[i] = r & 0xFFFF;
				j = 1;
			}
			else {
				x.element[i] = (r >>> 16) & 0xFFFF;
				j = 0;
			}
		}
		// 1~15ビット余る場合は、16ビットずつ作成しているので削る
		if((bits % 16) !== 0) {
			x.element[x.element.length - 1] &= (1 << (bits % 16)) - 1;
		}
		// 最後のビットに 0 をたくさん作成していると、
		// 0のみのデータになる可能性があるためメモリを修正
		x.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		x._memory_reduction();
		return x;
	}

	/**
	 * Convert to string.
	 * @param {KBigIntegerInputData} [radix=10] - Base number.
	 * @returns {string}
	 */
	toString(radix) {
		if(!this.isFinite()) {
			return this.isNaN() ? "NaN" : (this.isPositiveInfinity() ? "Infinity" : "-Infinity");
		}
		const radix_ = radix ? BigInteger._toInteger(radix) : 10;

		// int型で扱える数値で toString が可能なので、
		// せっかくだからより大きな進数で計算していけば、あとでtoStringする回数が減るテクニック
		// 2進数であれば、2^n乗で計算しても問題がない 4進数や8進数で計算して、2進数に戻せば巡回少数なし
		// v0.03 出来る限りまとめてn進数変換する
		const max_num = 0x3FFFFFFF;
		//                        max_num > radix^x
		// floor(log max_num / log radix) = x
		const keta = Math.floor( Math.log(max_num) / Math.log(radix_) );
		const calcradix = Math.round(Math.pow(radix_, keta));
		// zeros = "00000000...."
		const zeros_array = [];
		for(let i = 0; i < keta; i++) {
			zeros_array[i] = "0";
		}
		const zeros_string = zeros_array.join("");
		// v0.03ここまで
		const x = BigIntegerTool.toPlainStringFromHexadecimalArray(this.element, calcradix);
		const y = [];
		let z = "";
		if(this.sign() < 0) {
			y[y.length] = "-";
		}
		for(let i = x.length - 1; i >= 0; i--) {
			z = x[i].toString(radix_);
			if(i < (x.length - 1)) {
				y[y.length] = zeros_string.substring(0, keta - z.length);
			}
			y[y.length] = z;
		}
		return y.join("");
	}

	/**
	 * Convert to JSON.
	 * @returns {string} 
	 */
	toJSON() {
		return this.toString(10);
	}

	/**
	 * Deep copy.
	 * @returns {BigInteger}
	 */
	clone() {
		return new BigInteger(this);
	}

	/**
	 * Create a numerical value for addition. If negative, two's complement.
	 * @param {number} [bit_length] - Bit length. If not set, it will be calculated automatically.
	 * @returns {BigInteger}
	 * @private
	 */
	getTwosComplement(bit_length) {
		const y = this.clone();
		if(!this.isFinite()) {
			return y;
		}
		if(y.isNotNegative()) {
			return y;
		}
		else {
			// 正にする
			y.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
			// ビットの数が存在しない場合は数える
			const len = (bit_length !== undefined) ? bit_length : y.bitLength();
			const e = y.element;
			// ビット反転後
			for(let i = 0; i < e.length; i++) {
				e[i] ^= 0xFFFF;
			}
			// 1~15ビット余る場合は、16ビットずつ作成しているので削る
			// nビットのマスク(なお負の値を表す最上位ビットは削除する)
			if((len % 16) !== 0) {
				e[e.length - 1] &= (1 << (len % 16)) - 1;
			}
			// 1を加算
			y._add(new BigInteger(1));
			return y;
		}
	}

	/**
	 * Expand memory to specified bit length. (mutable)
	 * @param {number} bit_length - Bit length.
	 * @ignore
	 */
	_memory_allocation(bit_length) {
		if(!this.isFinite()) {
			return;
		}
		const n = BigInteger._toInteger(bit_length);
		const elementsize = this.element.length << 4;
		if(elementsize < n) {
			const addsize = (((n - elementsize - 1) & 0xFFFFFFF0) >>> 4) + 1;
			for(let i = 0;i < addsize;i++) {
				this.element[this.element.length] = 0;
			}
		}
	}

	/**
	 * Normalization of the internal data. (mutable)
	 * @ignore
	 */
	_memory_reduction() {
		if(!this.isFinite()) {
			return;
		}
		for(let i = this.element.length - 1;i >= 0;i--) {
			if(this.element[i] !==  0) {
				// 最終行以外で見つかったら、上の領域を削除する
				if(i < this.element.length - 1) {
					this.element.splice(i + 1, this.element.length - i - 1);
				}
				return;
			}
		}
		// 全て0だった場合
		this.state = BIGINTEGER_NUMBER_STATE.ZERO;
		this.element = [];
	}

	/**
	 * Absolute value. (mutable)
	 * @returns {BigInteger} A = abs(A)
	 * @ignore
	 */
	_abs() {
		// -1 -> 1, 0 -> 0, 1 -> 1
		if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER) {
			this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		}
		else if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY) {
			this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY;
		}
		return this;
	}

	/**
	 * Absolute value.
	 * @returns {BigInteger} abs(A)
	 */
	abs() {
		return this.clone()._abs();
	}

	/**
	 * this *= -1
	 * @returns {BigInteger} A = -A
	 * @ignore
	 */
	_negate() {
		if(this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER) {
			this.state = BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER;
		}
		else if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER) {
			this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		}
		else if(this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY) {
			this.state = BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY;
		}
		else if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY) {
			this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY;
		}
		return this;
	}

	/**
	 * this * -1
	 * @returns {BigInteger} -A
	 */
	negate() {
		return this.clone()._negate();
	}

	/**
	 * The positive or negative sign of this number.
	 * - +1 if positive, -1 if negative, 0 if 0.
	 * @returns {number}
	 */
	sign() {
		if(this.isNaN()) {
			return NaN;
		}
		else if(this.isZero()) {
			return 0;
		}
		else if(this.isPositive()) {
			return 1;
		}
		else {
			return -1;
		}
	}

	// ----------------------
	// 四則演算
	// ----------------------
	
	/**
	 * Add. (mutable)
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A += B
	 * @ignore
	 */
	_add(number) {
		const val = BigInteger._toBigInteger(number);
		const o1 = this;
		const o2 = val;
		if(!o1.isFinite() || !o2.isFinite()) {
			let ret;
			if(o1.isNaN() || o2.isNaN() || (o1.isInfinite() && o2.isInfinite() && !o1.equalsState(o2))) {
				ret = BigInteger.NaN.clone();
			}
			else if(o1.isPositiveInfinity() || o2.isPositiveInfinity()) {
				ret = BigInteger.POSITIVE_INFINITY.clone();
			}
			else {
				ret = BigInteger.NEGATIVE_INFINITY.clone();
			}
			this.element = ret.element;
			this.state = ret.state;
			return this;
		}
		let x1 = o1.element;
		let x2 = o2.element;
		if(o1.sign() === o2.sign()) {
			//足し算
			this._memory_allocation(x2.length << 4);
			let carry = 0;
			for(let i = 0; i < x1.length; i++) {
				x1[i] += ((x2.length >= (i + 1)) ? x2[i] : 0) + carry;
				if(x1[i] > 0xFFFF) {
					carry = 1;
					x1[i] &= 0xFFFF;
				}
				else {
					carry = 0;
				}
			}
			if(carry !== 0) {
				x1[x1.length] = carry;
			}
		}
		else {
			// 引き算
			const compare = o1.compareToAbs(o2);
			if(compare === 0) {
				this.element = [];
				this.state = BIGINTEGER_NUMBER_STATE.ZERO;
				return this;
			}
			else if(compare === -1) {
				this.state = o2.state;
				const swap = x1;
				x1 = x2.slice(0);
				x2 = swap;
			}
			let carry = 0;
			for(let i = 0; i < x1.length; i++) {
				x1[i] -= ((x2.length >= (i + 1)) ? x2[i] : 0) + carry;
				if(x1[i] < 0) {
					x1[i] += 0x10000;
					carry  = 1;
				}
				else {
					carry  = 0;
				}
			}
			this.element = x1;
			this._memory_reduction();
		}
		return this;
	}

	/**
	 * Add.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A + B
	 */
	add(number) {
		return this.clone()._add(number);
	}

	/**
	 * Subtract. (mutable)
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A -= B
	 * @ignore
	 */
	_sub(number) {
		// 一時的に記録しておいて引数の情報は書き換えないようにする
		const val = BigInteger._toBigInteger(number);
		const state = val.state;
		const out  = this._add(val._negate());
		val.state = state;
		return out;
	}

	/**
	 * Subtract.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A - B
	 */
	sub(number) {
		return this.clone()._sub(number);
	}

	/**
	 * Multiply. (mutable)
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A *= B
	 * @ignore
	 */
	_mul(number) {
		const x = this.mul(number);
		this.element = x.element;
		this.state   = x.state;
		return this;
	}

	/**
	 * Multiply.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A * B
	 */
	mul(number) {
		const val = BigInteger._toBigInteger(number);
		const o1 = this;
		const o2 = val;
		if(!o1.isFinite() || !o2.isFinite()) {
			if(o1.isNaN() || o2.isNaN() || (o1.isZero() || o2.isZero())) {
				return BigInteger.NaN.clone();
			}
			else if(o1.sign() * o2.sign() > 0) {
				return BigInteger.POSITIVE_INFINITY.clone();
			}
			else {
				return BigInteger.NEGATIVE_INFINITY.clone();
			}
		}
		const x1 = o1.element;
		const x2 = o2.element;
		const out  = new BigInteger();
		const buff = new BigInteger();
		const y  = out.element;
		for(let i = 0; i < x1.length; i++) {
			buff.element = [];
			// x3 = x1[i] * x2
			const x3 = buff.element;
			let carry = 0;
			for(let j = 0; j < x2.length; j++) {
				x3[j] = x1[i] * x2[j] + carry;
				if(x3[j] > 0xFFFF) {
					carry = x3[j] >>> 16;
					x3[j] &= 0xFFFF;
				}
				else {
					carry = 0;
				}
			}
			if(carry !== 0) {
				x3[x3.length] = carry;
			}
			// x3 = x3 << (i * 16)
			//buff._shift(i << 4);
			for(let j = x3.length - 1; j >= 0; j--) {
				x3[j + i] = x3[j];
			}
			for(let j = i - 1; j >= 0; j--) {
				x3[j] = 0;
			}
			// y = y + x3 (out._add(buff))
			//out._add(buff);
			carry = 0;
			out._memory_allocation(x3.length << 4);
			for(let j = i; j < y.length; j++) {
				y[j] += ((x3.length >= (j + 1)) ? x3[j] : 0) + carry;
				if(y[j] > 0xFFFF) {
					carry = 1;
					y[j] &= 0xFFFF;
				}
				else {
					carry = 0;
				}
			}
			if(carry !== 0) {
				y[y.length] = carry;
			}
		}
		const sign = this.sign() * val.sign();
		out.state = sign === 0 ? BIGINTEGER_NUMBER_STATE.ZERO :	(sign === 1 ? BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER : BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER);
		return out;
	}

	/**
	 * Divide and rem. (mutable)
	 * @param {KBigIntegerInputData} number
	 * @returns {Array<BigInteger>} [C = fix(A / B), A - C * B]
	 * @ignore
	 */
	_divideAndRemainder(number) {
		const o1 = this;
		const o2 = BigInteger._toBigInteger(number);
		if(!o1.isFinite() || !o2.isFinite()) {
			if(o1.isNaN() || o2.isNaN() || (o1.isInfinite() && o2.isInfinite())) {
				return [BigInteger.NaN, BigInteger.NaN];
			}
			else if(o1.isInfinite()) {
				if(o1.sign() * o2.sign() >= 0) {
					return [BigInteger.POSITIVE_INFINITY, BigInteger.NaN];
				}
				else {
					return [BigInteger.NEGATIVE_INFINITY, BigInteger.NaN];
				}
			}
			else {
				return [BigInteger.ZERO, BigInteger.NaN];
			}
		}
		else if(o2.isZero()) {
			if(o1.isZero()) {
				return [BigInteger.NaN, BigInteger.NaN];
			}
			else {
				return [o1.sign() >= 0 ? BigInteger.POSITIVE_INFINITY : BigInteger.NEGATIVE_INFINITY, BigInteger.NaN];
			}
		}
		const out = [];
		const compare = o1.compareToAbs(o2);
		const sign = o1.sign() * o2.sign();
		if(compare < 0) {
			out[0] = new BigInteger(0);
			out[1] = o1.clone();
			return out;
		}
		else if(compare === 0) {
			out[0] = new BigInteger(1);
			out[0].state = sign === 1 ? BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER : BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER;
			out[1] = new BigInteger(0);
			return out;
		}
		const ONE = new BigInteger(1);
		const size = o1.bitLength() - o2.bitLength();
		const x1 = o1.clone()._abs();
		const x2 = o2.shift(size)._abs();
		const y  = new BigInteger();
		for(let i = 0; i <= size; i++) {
			if(x1.compareToAbs(x2) >= 0) {
				x1._sub(x2);
				y._add(ONE);
			}
			if(i === size) {
				break;
			}
			x2._shift(-1);
			y._shift(1);
		}
		out[0] = y;
		out[0].state = sign === 1 ? BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER : BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER;
		out[1] = x1;
		out[1].state = x1.state !== BIGINTEGER_NUMBER_STATE.ZERO ? o1.state : x1.state;
		return out;
	}

	/**
	 * Divide and rem.
	 * @param {KBigIntegerInputData} number
	 * @returns {Array<BigInteger>} [C = fix(A / B), A - C * B]
	 */
	divideAndRemainder(number) {
		return this.clone()._divideAndRemainder(number);
	}

	/**
	 * Divide. (mutable)
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} fix(A / B)
	 * @ignore
	 */
	_div(number) {
		return this._divideAndRemainder(number)[0];
	}

	/**
	 * Divide.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} fix(A / B)
	 */
	div(number) {
		return this.clone()._div(number);
	}

	/**
	 * Inverse number of this value.
	 * @returns {BigInteger} 1 / A
	 */
	inv() {
		{
			if(!this.isFinite()) {
				return this.isNaN() ? BigInteger.NaN : BigInteger.ZERO;
			}
			if(this.isZero()) {
				return BigInteger.NaN;
			}
		}
		return BigInteger.ZERO;
	}

	/**
	 * Remainder of division. (mutable)
	 * - Result has same sign as the Dividend.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A %= B
	 * @ignore
	 */
	_rem(number) {
		const y = this._divideAndRemainder(number)[1];
		this.element = y.element;
		this.state = y.state;
		return this;
	}

	/**
	 * Remainder of division.
	 * - Result has same sign as the Dividend.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A % B
	 */
	rem(number) {
		return this.clone()._rem(number);
	}

	/**
	 * Modulo, positive rem of division. (mutable)
	 * - Result has same sign as the Divisor.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A = A mod B
	 * @ignore
	 */
	_mod(number) {
		const o1 = this;
		const o2 = BigInteger._toBigInteger(number);
		if(o2.isZero()) {
			return o1;
		}
		const y = o1._divideAndRemainder(o2)[1];
		if(o1.state !== o2.state) {
			y._add(o2);
		}
		this.element = y.element;
		this.state = y.state;
		return this;
	}

	/**
	 * Modulo, positive rem of division.
	 * - Result has same sign as the Divisor.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A mod B
	 */
	mod(number) {
		return this.clone()._mod(number);
	}

	/**
	 * Modular exponentiation.
	 * @param {KBigIntegerInputData} exponent
	 * @param {KBigIntegerInputData} m 
	 * @returns {BigInteger} A^B mod m
	 */
	modPow(exponent, m) {
		const m_ = BigInteger._toBigInteger(m);
		let x = new BigInteger(this);
		let y = new BigInteger(1);
		const e = new BigInteger(exponent);
		if(!x.isFinite() || !e.isFinite()) {
			return BigInteger.NaN;
		}
		while(e.element.length !== 0) {
			if((e.element[0] & 1) !== 0) {
				y = y.multiply(x).mod(m_);
			}
			x = x.multiply(x).mod(m_);
			e._shift(-1);
		}
		return y;
	}

	/**
	 * Modular multiplicative inverse.
	 * @param {KBigIntegerInputData} m
	 * @returns {BigInteger} A^(-1) mod m
	 */
	modInverse(m) {
		const m_ = BigInteger._toBigInteger(m);
		if(!this.isFinite() || !m_.isFinite()) {
			return BigInteger.NaN;
		}
		const y = this.extgcd(m);
		const ONE  = new BigInteger(1);
		if(y[2].compareTo(ONE) !== 0) {
			return BigInteger.NaN;
		}
		// 正にするため rem ではなく mod を使用する
		return y[0]._add(m_).rem(m_);
	}

	// ----------------------
	// その他の演算
	// ----------------------
	
	/**
	 * Factorial function, x!.
	 * @returns {BigInteger} n!
	 */
	factorial() {
		{
			if(!this.isFinite()) {
				return this;
			}
			else if(this.isNegative()) {
				return BigInteger.NaN;
			}
		}
		const loop_max = BigInteger._toInteger(this);
		let x = BigInteger.ONE;
		for(let i = 2; i <= loop_max; i++) {
			x = x.multiply(i);
		}
		return x;
	}

	/**
	 * Multiply a multiple of ten.
	 * @param {KBigIntegerInputData} n
	 * @returns {BigInteger} x * 10^n
	 */
	scaleByPowerOfTen(n) {
		const x = BigInteger._toInteger(n);
		if(x === 0) {
			return this;
		}
		if(x > 0) {
			return this.mul(BigInteger.TEN.pow(x));
		}
		else {
			return this.div(BigInteger.TEN.pow(x));
		}
	}

	// ----------------------
	// 指数
	// ----------------------
	
	/**
	 * Power function.
	 * @param {KBigIntegerInputData} exponent
	 * @returns {BigInteger} pow(A, B)
	 */
	pow(exponent) {
		const e = new BigInteger(exponent);
		{
			if(this.isNaN() || e.isNaN()) {
				return BigInteger.NaN;
			}
			if(e.isZero()) {
				return BigInteger.ONE;
			}
			else if(this.isZero()) {
				if(e.isNegativeInfinity()) {
					return BigInteger.POSITIVE_INFINITY;
				}
				else {
					return BigInteger.ZERO;
				}
			}
			else if(this.isOne()) {
				return this;
			}
			else if(this.isInfinite()) {
				if(this.isPositiveInfinity()) {
					return BigInteger.POSITIVE_INFINITY;
				}
				else {
					if(e.isPositiveInfinity()) {
						return BigInteger.NaN;
					}
					else {
						return BigInteger.create(Infinity * Math.pow(-1, Math.round(e.doubleValue)));
					}
				}
			}
			else if(e.isInfinite()) {
				if(this.isNegative()) {
					// 複素数
					return BigInteger.NaN;
				}
				if(this.compareTo(BigInteger.ONE) < 0) {
					if(e.isPositiveInfinity()) {
						return BigInteger.ZERO;
					}
					else if(e.isNegativeInfinity()) {
						return BigInteger.POSITIVE_INFINITY;
					}
				}
				else {
					if(e.isPositiveInfinity()) {
						return BigInteger.POSITIVE_INFINITY;
					}
					else if(e.isNegativeInfinity()) {
						return BigInteger.ZERO;
					}
				}
			}
		}
		let x = BigInteger._toBigInteger(this);
		let y = BigInteger._toBigInteger(1);
		while(e.element.length !== 0) {
			if((e.element[0] & 1) !== 0) {
				y = y.multiply(x);
			}
			x = x.multiply(x);
			e._shift(-1);
		}
		return y;
	}

	/**
	 * Square.
	 * @returns {BigInteger} A^2
	 */
	square() {
		return this.mul(this);
	}

	/**
	 * Square root.
	 * @returns {BigInteger} floor(sqrt(A))
	 */
	sqrt() {
		{
			if(this.isZero()) {
				return BigInteger.ZERO;
			}
			else if(this.isNaN()) {
				return BigInteger.NaN;
			}
			else if(this.isNegative()) {
				return BigInteger.NaN; // 複素数
			}
			else if(this.isInfinite()) {
				return BigInteger.POSITIVE_INFINITY;
			}
		}
		// ニュートン法によって求める
		// 参考:奥村晴彦 (1991). C言語による最新アルゴリズム事典.
		// A^0.5  = x
		//     A  = x^2
		//     0  = x^2 - A
		//   f(x) = x^2 - A
		//   f'(x) = 2x
		// x_(n+1) = x_n - f(x_n)/f'(x_n)
		//         = x_n - (x_n^2 - A)/2x_n
		//         = (2*x_n^2 - x_n^2 + A)/2x_n
		//         = (x_n^2 + A)/2x_n
		//         = (x_n + (A/x_n)) / 2
		let s = BigInteger.ONE;
		/**
		 * @type {BigInteger}
		 */
		let t = this;
		while(s.compareToAbs(t) === -1) {
			s = s.shiftLeft(1);
			t = t.shiftRight(1);
		}
		const x0 = t;
		let xn = x0;
		for(let i = 0; i < 300; i++) {
			const xn1 = xn.add(this.div(xn)).shiftRight(1);
			const delta = xn1.sub(xn);
			if(delta.isZero()) {
				break;
			}
			xn = xn1;
		}
		return xn;
	}
	
	/**
	 * Cube root.
	 * @returns {BigInteger} floor(cbrt(A))
	 */
	cbrt() {
		{
			if(this.isZero()) {
				return BigInteger.ZERO;
			}
			else if(this.isNaN()) {
				return BigInteger.NaN;
			}
			else if(this.isInfinite()) {
				return this;
			}
		}
		// ニュートン法によって求める
		// 参考:奥村晴彦 (1991). C言語による最新アルゴリズム事典.
		let s = BigInteger.ONE;
		/**
		 * @type {BigInteger}
		 */
		let t = this;
		while(s.compareToAbs(t) === -1) {
			s = s.shiftLeft(1);
			t = t.shiftRight(2);
		}
		const x0 = t;
		let xn = x0;
		for(let i = 0; i < 300; i++) {
			const xn_2 = xn.mul(xn);
			const xn1 = xn.shiftLeft(1).add(this.div(xn_2)).div(3);
			const delta = xn1.sub(xn);
			if(delta.isZero()) {
				break;
			}
			xn = xn1;
		}
		return xn;
	}

	/**
	 * log_2(x)
	 * @returns {BigInteger} log2(A)
	 */
	log2() {
		{
			if(this.isZero()) {
				return BigInteger.ZERO;
			}
			else if(this.isNaN()) {
				return BigInteger.NaN;
			}
			else if(this.isNegative()) {
				return BigInteger.NaN;
			}
			else if(this.isInfinite()) {
				return BigInteger.POSITIVE_INFINITY;
			}
		}
		return BigInteger.create(this.bitLength() - 1);
	}

	/**
	 * log_10(x)
	 * @returns {BigInteger} log10(A)
	 */
	log10() {
		{
			if(this.isZero()) {
				return BigInteger.ZERO;
			}
			else if(this.isNaN()) {
				return BigInteger.NaN;
			}
			else if(this.isNegative()) {
				return BigInteger.NaN;
			}
			else if(this.isInfinite()) {
				return BigInteger.POSITIVE_INFINITY;
			}
		}
		return BigInteger.create(this.toString(10).length - 1);
	}

	// ----------------------
	// 環境設定用
	// ----------------------
	
	/**
	 * Set default class of random.
	 * This is used if you do not specify a random number.
	 * @param {Random} random
	 */
	static setDefaultRandom(random) {
		DEFAULT_RANDOM = random;
	}

	/**
	 * Return default Random class.
	 * Used when Random not specified explicitly.
	 * @returns {Random}
	 */
	static getDefaultRandom() {
		return DEFAULT_RANDOM;
	}

	// ----------------------
	// 他の型に変換用
	// ----------------------
	
	/**
	 * Value at the specified position of the internally used array that composed of hexadecimal numbers.
	 * @param {KBigIntegerInputData} point - Array address.
	 * @returns {number}
	 */
	getShort(point) {
		if(this.isZero()) {
			return 0;
		}
		const n = BigInteger._toInteger(point);
		return ((0 <= n) && (n <= this.element.length)) ? this.element[n] : NaN;
	}

	/**
	 * boolean value.
	 * @returns {boolean}
	 */
	get booleanValue() {
		return !this.isZero() && !this.isNaN();
	}

	/**
	 * 64-bit integer value.
	 * - If it is outside the range of JavaScript Number, it will not be an accurate number.
	 * @returns {number}
	 */
	get intValue() {
		if(!this.isFinite()) {
			return this.isNaN() ? NaN : (this.isPositiveInfinity() ? Infinity : -Infinity);
		}
		let x = 0;
		for(let i = Math.min(3, this.element.length - 1); i >= 0; i--) {
			// ビット演算にすると、32ビットに収まる可能性があるため掛け算で計算している
			x *= 65536;
			x += this.element[i];
		}
		if(this.isNegative()) {
			x = -x;
		}
		return x;
	}

	/**
	 * 64-bit floating point.
	 * - If it is outside the range of JavaScript Number, it will not be an accurate number.
	 * @returns {number}
	 */
	get doubleValue() {
		if(!this.isFinite()) {
			return this.isNaN() ? NaN : (this.isPositiveInfinity() ? Infinity : -Infinity);
		}
		return parseFloat(this.toString());
	}
	
	// ----------------------
	// konpeito で扱う数値型へ変換
	// ----------------------
	
	/**
	 * return BigInteger.
	 * @returns {BigInteger}
	 */
	toBigInteger() {
		return this;
	}

	/**
	 * return BigDecimal.
	 * @param {MathContext} [mc] - MathContext setting after calculation. 
	 * @returns {BigDecimal}
	 */
	toBigDecimal(mc) {
		if(mc) {
			return new BigDecimal([this, mc]);
		}
		else {
			return new BigDecimal(this);
		}
	}
	
	/**
	 * return Fraction.
	 * @returns {Fraction}
	 */
	toFraction() {
		return new Fraction(this);
	}
	
	/**
	 * return Complex.
	 * @returns {Complex}
	 */
	toComplex() {
		return new Complex(this);
	}
	
	/**
	 * return Matrix.
	 * @returns {Matrix}
	 */
	toMatrix() {
		return new Matrix(this);
	}

	// ----------------------
	// 比較
	// ----------------------
	
	/**
	 * Equals.
	 * @param {KBigIntegerInputData} number
	 * @returns {boolean} A === B
	 */
	equals(number) {
		const x = this;
		const y = BigInteger._toBigInteger(number);
		if(!x.isFinite() || !y.isFinite()) {
			if(x.isNaN() || y.isNaN()) {
				return false;
			}
			else if(x.state === y.state) {
				return true;
			}
			else {
				return false;
			}
		}
		if(x.state !== y.state) {
			return false;
		}
		if(x.element.length !== y.element.length) {
			return false;
		}
		for(let i = 0; i < y.element.length; i++) {
			if(x.element[i] !==  y.element[i]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Compare values without sign.
	 * @param {KBigIntegerInputData} number 
	 * @returns {number} abs(A) > abs(B) ? 1 : (abs(A) === abs(B) ? 0 : -1)
	 */
	compareToAbs(number) {
		const x = this;
		const y = BigInteger._toBigInteger(number);
		if(!x.isFinite() || !y.isFinite()) {
			if(x.isNaN() || y.isNaN()) {
				return NaN;
			}
			else if(x.isInfinite() || y.isInfinite()) {
				return 0;
			}
			else if(y.isInfinite()) {
				return -1;
			}
			else {
				return 1;
			}
		}
		if(x.element.length < y.element.length) {
			return -1;
		}
		else if(x.element.length > y.element.length) {
			return 1;
		}
		for(let i = x.element.length - 1;i >= 0;i--) {
			if(x.element[i] !== y.element[i]) {
				const val = x.element[i] - y.element[i];
				return ( (val === 0) ? 0 : ((val > 0) ? 1 : -1) );
			}
		}
		return 0;
	}

	/**
	 * Compare values.
	 * @param {KBigIntegerInputData} number 
	 * @returns {number} A > B ? 1 : (A === B ? 0 : -1)
	 */
	compareTo(number) {
		const x = this;
		const y = BigInteger._toBigInteger(number);
		if(!x.isFinite() || !y.isFinite()) {
			if(x.isNaN() || y.isNaN()) {
				return NaN;
			}
			if(x.state === y.state) {
				return 0;
			}
			if(x.isPositiveInfinity() || y.isNegativeInfinity()) {
				return 1;
			}
			else {
				return -1;
			}
		}
		const x_sign = x.sign();
		const y_sign = y.sign();
		if(x_sign !== y_sign) {
			if(x_sign > y_sign) {
				return 1;
			}
			else {
				return -1;
			}
		}
		else if(x_sign === 0) {
			return 0;
		}
		return x.compareToAbs(y) * x_sign;
	}

	/**
	 * Numeric type match.
	 * @param {KBigIntegerInputData} number 
	 * @returns {boolean}
	 */
	equalsState(number) {
		const x = this;
		const y = BigInteger._toBigInteger(number);
		return x.state === y.state;
	}

	/**
	 * Maximum number.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} max([A, B])
	 */
	max(number) {
		const val = BigInteger._toBigInteger(number);
		if(this.compareTo(val) >= 0) {
			return this.clone();
		}
		else {
			return val.clone();
		}
	}

	/**
	 * Minimum number.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} min([A, B])
	 */
	min(number) {
		const val = BigInteger._toBigInteger(number);
		if(this.compareTo(val) >= 0) {
			return val.clone();
		}
		else {
			return this.clone();
		}
	}

	/**
	 * Clip number within range.
	 * @param {KBigIntegerInputData} min 
	 * @param {KBigIntegerInputData} max
	 * @returns {BigInteger} min(max(x, min), max)
	 */
	clip(min, max) {
		const min_ = BigInteger._toBigInteger(min);
		const max_ = BigInteger._toBigInteger(max);
		if(this.isNaN() || min_.isNaN() || max_.isNaN()) {
			return BigInteger.NaN;
		}
		const arg_check = min_.compareTo(max_);
		if(arg_check === 1) {
			throw "clip(min, max) error. (min > max)->(" + min_ + " > " + max_ + ")";
		}
		else if(arg_check === 0) {
			return min_;
		}
		if(this.compareTo(max_) === 1) {
			return max_;
		}
		else if(this.compareTo(min_) === -1) {
			return min_;
		}
		return this;
	}

	// ----------------------
	// 丸め
	// ----------------------
	
	/**
	 * Floor.
	 * @returns {BigInteger} floor(A)
	 */
	floor() {
		return this;
	}

	/**
	 * Ceil.
	 * @returns {BigInteger} ceil(A)
	 */
	ceil() {
		return this;
	}
	
	/**
	 * Rounding to the nearest integer.
	 * @returns {BigInteger} round(A)
	 */
	round() {
		return this;
	}

	/**
	 * To integer rounded down to the nearest.
	 * @returns {BigInteger} fix(A), trunc(A)
	 */
	fix() {
		return this;
	}

	/**
	 * Fraction.
	 * @returns {BigInteger} fract(A)
	 */
	fract() {
		return BigInteger.ZERO;
	}

	// ----------------------
	// factor
	// ----------------------

	/**
	 * Factorization.
	 * - Calculate up to `9007199254740991`.
	 * @returns {BigInteger[]} factor
	 */
	factor() {
		// 参考:奥村,"C言語による最新アルゴリズム事典",p154,技術評論社,1991
		if(!this.isFinite()) {
			return [BigInteger.NaN];
		}
		if(this.isZero()) {
			return [BigInteger.ZERO];
		}
		if(this.isNegative()) {
			return [this];
		}
		/**
		 * @type {BigInteger[]}
		 */
		const output = [];
		let x = this.intValue;
		if(x > Number.MAX_SAFE_INTEGER) {
			return [];
		}
		while(x >= 4 && x % 2 === 0) {
			output.push(BigInteger.TWO);
			x = Math.floor(x / 2);
		}
		let d = 3;
		let q = Math.floor(x / d);
		while(q >= d) {
			if(x % d === 0) {
				output.push(BigInteger.create(d));
				x = q;
			}
			else {
				d += 2;
			}
			q = Math.floor(x / d);
		}
		output.push(BigInteger.create(x));
		return output;
	}

	// ----------------------
	// gcd, lcm
	// ----------------------
	
	/**
	 * Euclidean algorithm.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} gcd(x, y)
	 */
	gcd(number) {
		const val = BigInteger._toBigInteger(number);
		if(!this.isFinite() || !val.isFinite()) {
			return BigInteger.NaN;
		}
		/**
		 * @type {any}
		 */
		let x = this, y = val, z;
		while(y.sign() !== 0) {
			z = x.rem(y);
			x = y;
			y = z;
		}
		return x;
	}

	/**
	 * Extended Euclidean algorithm.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger[]} [a, b, gcd(x, y)], Result of calculating a*x + b*y = gcd(x, y).
	 */
	extgcd(number) {
		const val = BigInteger._toBigInteger(number);
		if(!this.isFinite() || !val.isFinite()) {
			return [BigInteger.NaN, BigInteger.NaN, BigInteger.NaN];
		}
		// 非再帰
		const ONE  = new BigInteger(1);
		const ZERO = new BigInteger(0);
		/**
		 * @type {any}
		 */
		let r0 = this, r1 = val, r2, q1;
		let a0 = ONE,  a1 = ZERO, a2;
		let b0 = ZERO, b1 = ONE,  b2;
		while(r1.sign() !== 0) {
			const y = r0.divideAndRemainder(r1);
			q1 = y[0];
			r2 = y[1];
			a2 = a0.subtract(q1.multiply(a1));
			b2 = b0.subtract(q1.multiply(b1));
			a0 = a1;
			a1 = a2;
			b0 = b1;
			b1 = b2;
			r0 = r1;
			r1 = r2;
		}
		return [a0, b0, r0];
	}

	/**
	 * Least common multiple.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} lcm(x, y)
	 */
	lcm(number) {
		const val = BigInteger._toBigInteger(number);
		if(!this.isFinite() || !val.isFinite()) {
			return BigInteger.NaN;
		}
		return this.mul(val).div(this.gcd(val));
	}

	// ----------------------
	// 素数系
	// ----------------------
	
	/**
	 * Prime represented within the specified bit length.
	 * @param {KBigIntegerInputData} bits - Bit length.
	 * @param {Random} [random] - Class for creating random numbers.
	 * @param {KBigIntegerInputData} [certainty=100] - Repeat count (prime precision).
	 * @param {KBigIntegerInputData} [create_count=500] - Number of times to retry if prime generation fails.
	 * @returns {BigInteger}
	 */
	static probablePrime(bits, random, certainty, create_count ) {
		const certainty_ = certainty ? BigInteger._toInteger(certainty) : 100;
		const create_count_ = create_count ? BigInteger._toInteger(create_count) : 500;
		for(let i = 0; i < create_count_; i++) {
			const x = BigInteger.createRandomBigInteger(bits, random);
			if(x.isProbablePrime(certainty_)) {
				return x;
			}
		}
		console.log("probablePrime " + create_count);
		return BigInteger.NaN;
	}

	/**
	 * Return true if the value is prime number.
	 * - Calculate up to `9007199254740991`.
	 * @returns {boolean} - If the calculation range is exceeded, null is returned.
	 */
	isPrime() {
		if(!this.isFinite()) {
			return false;
		}
		// 0や負の値は、素数ではない
		if(this.sign() <= 0) {
			return false;
		}
		const limit = Math.sqrt(Number.MAX_SAFE_INTEGER);
		const target_number = this.doubleValue;
		const count_max = Math.ceil(Math.sqrt(target_number));
		// 1, 2 -> true
		if(target_number <= 2) {
			return true;
		}
		// 指定した値より大きい場合は計算不可能として null を返す
		if(count_max >= limit) {
			return null;
		}
		for(let i = 2; i <= count_max; i++) {
			if((target_number % i) === 0) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Return true if the value is prime number by Miller-Labin prime number determination method.
	 * 
	 * Attention : it takes a very long time to process.
	 * @param {KBigIntegerInputData} [certainty=100] - Repeat count (prime precision).
	 * @returns {boolean}
	 */
	isProbablePrime(certainty) {
		if(!this.isFinite()) {
			return false;
		}
		const e = this.element;
		// 0や負の値は、素数ではない
		if(this.sign() <= 0) {
			return false;
		}
		// 1, 2 -> true
		if((e.length === 1)&&(e[0] <= 2)) {
			return true;
		}
		// even number -> false
		else if((e[0] & 1) === 0) {
			return false;
		}
		// ミラーラビン素数判定法
		// かなり処理が重たいです。まあお遊び程度に使用という感じで。
		const loop	= certainty !== undefined ? BigInteger._toInteger(certainty) : 100;
		const ZERO	= BigInteger.ZERO;
		const ONE	= BigInteger.ONE;
		const n		= this;
		const LEN	= n.bitLength();
		const n_1	= n.subtract(ONE);
		const s 	= n_1.getLowestSetBit();
		const d 	= n_1.shift(-s);

		if(loop <= 0) {
			return false;
		}

		for(let i = 0; i < loop; i++ ) {
			//[ 1, n - 1] の範囲から a を選択
			let a;
			do {
				a = BigInteger.createRandomBigInteger(LEN);
			} while(( a.compareTo(ZERO) === 0 )||( a.compareTo(n) !== -1 ));

			let t = d;
			// a^t != 1 mod n
			let y = a.modPow(t, n);
			
			while(true) {
				if((t.equals(n_1)) || (y.equals(ONE)) || (y.equals(n_1))) {
					break;
				}
				y = y.mul(y)._mod(n);
				t = t.shiftLeft(1);
			}

			if((!y.equals(n_1)) && ((t.element[0] & 1) === 0)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Next prime.
	 * @param {KBigIntegerInputData} [certainty=100] - Repeat count (prime precision).
	 * @param {KBigIntegerInputData} [search_max=100000] - Search range of next prime.
	 * @returns {BigInteger}
	 */
	nextProbablePrime(certainty, search_max) {
		if(!this.isFinite()) {
			return BigInteger.NaN;
		}
		const loop	= certainty !== undefined ? (BigInteger._toInteger(certainty) >> 1) : 100 / 2;
		const search_max_ = search_max !== undefined ? BigInteger._toInteger(search_max) : 100000;
		const x = this.clone();
		for(let i = 0; i < search_max_; i++) {
			x._add(BigInteger.ONE);
			if(x.isProbablePrime(loop)) {
				return x;
			}
		}
		throw "nextProbablePrime [" + search_max_ +"]";
	}

	// ----------------------
	// シフト演算系
	// ----------------------
	
	/**
	 * this <<= n
	 * @param {KBigIntegerInputData} shift_length - Bit shift size.
	 * @returns {BigInteger} A <<= n
	 * @private
	 */
	_shift(shift_length) {
		if(!this.isFinite()) {
			return this;
		}
		let n = BigInteger._toInteger(shift_length);
		if(n === 0) {
			return this;
		}
		const x = this.element;
		// 1ビットなら専用コードで高速計算
		if(n === 1) {
			let i = x.length - 1;
			if((x[i] & 0x8000) !==  0) {
				x[x.length] = 1;
			}
			for(;i >= 0;i--) {
				x[i] <<= 1;
				x[i]  &= 0xFFFF;
				if((i > 0) && ((x[i - 1] & 0x8000) !==  0)) {
					x[i] += 1;
				}
			}
		}
		else if(n === -1) {
			for(let i = 0;i < x.length;i++) {
				x[i] >>>= 1;
				if((i < x.length - 1) && ((x[i + 1] & 1) !==  0)) {
					x[i] |= 0x8000;
				}
			}
			if(x[x.length - 1] === 0) {
				x.pop();
			}
		}
		else {
			// 16ビット単位なら配列を追加削除する高速計算
			if(n >= 16) {
				const m = n >>> 4;
				for(let i = x.length - 1; i >= 0; i--) {
					x[i + m] = x[i];
				}
				for(let i = m - 1; i >= 0; i--) {
					x[i] = 0;
				}
				n &= 0xF;
			}
			else if(n <= -16){
				const m = (-n) >>> 4;
				x.splice(0, m);
				n += m << 4;
			}
			if(n !== 0) {
				// 15ビット以内ならビット演算でまとめて操作
				if(0 < n) {
					let carry = 0;
					for(let i = 0; i < x.length; i++) {
						x[i] = (x[i] << n) + carry;
						if(x[i] > 0xFFFF) {
							carry = x[i] >>> 16;
							x[i] &= 0xFFFF;
						}
						else {
							carry = 0;
						}
					}
					if(carry !== 0) {
						x[x.length] = carry;
					}
				}
				else {
					n = -n;
					for(let i = 0; i < x.length; i++) {
						if(i !== x.length - 1) {
							x[i] += x[i + 1] << 16;
							x[i] >>>= n;
							x[i] &= 0xFFFF;
						}
						else {
							x[i] >>>= n;
						}
					}
					if(x[x.length - 1] === 0) {
						x.pop();
					}
				}
			}
		}
		if(x.length === 0) {
			this.state = BIGINTEGER_NUMBER_STATE.ZERO;
		}
		return this;
	}

	/**
	 * this << n
	 * @param {KBigIntegerInputData} n
	 * @returns {BigInteger} A << n
	 */
	shift(n) {
		return this.clone()._shift(n);
	}

	/**
	 * this << n
	 * @param {KBigIntegerInputData} n
	 * @returns {BigInteger} A << n
	 */
	shiftLeft(n) {
		return this.shift(n);
	}

	/**
	 * this >> n
	 * @param {KBigIntegerInputData} n
	 * @returns {BigInteger} A >> n
	 */
	shiftRight(n) {
		return this.shift(-n);
	}

	// ----------------------
	// ビット演算系
	// ----------------------
	
	/**
	 * Number of digits in which the number "1" appears first when expressed in binary.
	 * - Return -1 If 1 is not found it.
	 * @returns {number}
	 */
	getLowestSetBit() {
		if(!this.isFinite()) {
			return NaN;
		}
		for(let i = 0; i < this.element.length; i++) {
			if(this.element[i] !==  0) {
				const x = this.element[i];
				for(let j = 0; j < 16; j++) {
					if(((x >>> j) & 1) !==  0) {
						return i * 16 + j;
					}
				}
			}
		}
		return -1;
	}

	/**
	 * Length when the number is binary.
	 * @returns {number}
	 */
	bitLength() {
		if(!this.isFinite()) {
			return NaN;
		}
		for(let i = this.element.length - 1; i >= 0; i--) {
			if(this.element[i] !==  0) {
				const x = this.element[i];
				for(let j = 15; j >= 0; j--) {
					if(((x >>> j) & 1) !==  0) {
						return i * 16 + j + 1;
					}
				}
			}
		}
		return 0;
	}

	/**
	 * Sum that the bit is 1 when represented in the two's complement.
	 * @returns {number}
	 */
	bitCount() {
		if(!this.isFinite()) {
			return NaN;
		}
		let target;
		if(this.sign() >= 0) {
			target = this;
		}
		else {
			target = this.add(new BigInteger(1));
		}
		const len = target.bitLength();
		let bit = 0;
		let count = 0;
		for(let i = 0;bit < len;i++) {
			const x = target.element[i];
			for(let j = 0;((j < 16) && (bit < len));j++, bit++) {
				if(((x >>> j) & 1) !==  0) {
					count = count + 1;
				}
			}
		}
		return count;
	}

	/**
	 * Logical AND. (mutable)
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A &= B
	 * @ignore
	 */
	_and(number) {
		const val = BigInteger._toBigInteger(number);
		const e1 = this;
		const e2 = val;
		if((!e1.isFinite()) || (!e2.isFinite())) {
			let ret;
			if(e1.isNaN() || e2.isNaN()) {
				ret = BigInteger.NaN;
			}
			else {
				ret = BigInteger.ZERO;
			}
			ret = ret.clone();
			this.element = ret.element;
			this.state = ret.state;
			return this;
		}
		const s1  = e1.sign(), s2 = e2.sign();
		const len = Math.max(e1.bitLength(), e2.bitLength());
		// 引数が負の場合は、2の補数
		const e1_array = e1.getTwosComplement(len).element;
		const e2_array = e2.getTwosComplement(len).element;
		const size = Math.max(e1_array.length, e2_array.length);
		this.element = [];
		for(let i = 0;i < size;i++) {
			const x1 = (i >= e1_array.length) ? 0 : e1_array[i];
			const x2 = (i >= e2_array.length) ? 0 : e2_array[i];
			this.element[i] = x1 & x2;
		}
		// 配列の上位が空になる可能性があるためノーマライズが必要
		this._memory_reduction();
		// 符号を計算
		if(this.state !== BIGINTEGER_NUMBER_STATE.ZERO && ((s1 === 1)||(s2 === 1))) {
			this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		}
		// 出力が負の場合は、2の補数
		else if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER) {
			this.element = this.getTwosComplement(len).element;
			// 反転させたことで配列の上位が空になる可能性があるためノーマライズが必要
			this._memory_reduction();
		}
		return this;
	}

	/**
	 * Logical AND.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A & B
	 */
	and(number) {
		return this.clone()._and(number);
	}

	/**
	 * Logical OR. (mutable)
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A |= B
	 * @ignore
	 */
	_or(number) {
		const val = BigInteger._toBigInteger(number);
		const e1 = this;
		const e2 = val;
		if((!e1.isFinite()) || (!e2.isFinite())) {
			let ret;
			if(e1.isNaN() || e2.isNaN()) {
				ret = BigInteger.NaN.clone();
			}
			else if(e1.isInfinite() || e2.isInfinite()) {
				ret = BigInteger.ZERO;
			}
			else {
				ret = e1.isInfinite() ? e2 : e1;
			}
			ret = ret.clone();
			this.element = ret.element;
			this.state = ret.state;
			return this;
		}

		const s1  = e1.sign(), s2 = e2.sign();
		const len = Math.max(e1.bitLength(), e2.bitLength());
		// 引数が負の場合は、2の補数
		const e1_array = e1.getTwosComplement(len).element;
		const e2_array = e2.getTwosComplement(len).element;
		const size = Math.max(e1_array.length, e2_array.length);
		this.element = [];
		for(let i = 0;i < size;i++) {
			const x1 = (i >= e1_array.length) ? 0 : e1_array[i];
			const x2 = (i >= e2_array.length) ? 0 : e2_array[i];
			this.element[i] = x1 | x2;
		}
		// 符号を計算
		this.state = ((s1 === -1)||(s2 === -1)) ?
			BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER :
			(Math.max(s1, s2) === 0 ? BIGINTEGER_NUMBER_STATE.ZERO : BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER);
		// 出力が負の場合は、2の補数
		if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER) {
			this.element = this.getTwosComplement(len).element;
			// 反転させたことで配列の上位が空になる可能性があるためノーマライズが必要
			this._memory_reduction();
		}
		return this;
	}

	/**
	 * Logical OR.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A | B
	 */
	or(number) {
		return this.clone()._or(number);
	}

	/**
	 * Logical Exclusive-OR. (mutable)
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A ^= B
	 * @ignore
	 */
	_xor(number) {
		const val = BigInteger._toBigInteger(number);
		const e1 = this;
		const e2 = val;
		if((!e1.isFinite()) || (!e2.isFinite())) {
			let ret;
			if(e1.isNaN() || e2.isNaN()) {
				ret = BigInteger.NaN;
			}
			else if(e1.isInfinite() || e2.isInfinite()) {
				ret = BigInteger.ZERO;
			}
			else {
				ret = e1.isInfinite() ? e2 : e1; 
			}
			ret = ret.clone();
			this.element = ret.element;
			this.state = ret.state;
			return this;
		}
		const s1  = e1.sign(), s2 = e2.sign();
		const len = Math.max(e1.bitLength(), e2.bitLength());
		// 引数が負の場合は、2の補数
		const e1_array = e1.getTwosComplement(len).element;
		const e2_array = e2.getTwosComplement(len).element;
		const size = Math.max(e1_array.length, e2_array.length);
		this.element = [];
		for(let i = 0;i < size;i++) {
			const x1 = (i >= e1_array.length) ? 0 : e1_array[i];
			const x2 = (i >= e2_array.length) ? 0 : e2_array[i];
			this.element[i] = x1 ^ x2;
		}
		// 配列の上位が空になる可能性があるためノーマライズが必要
		this._memory_reduction();
		// 符号を計算
		this.state = ((s1 !== 0)&&(s1 !== s2)) ? BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER : BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		// 出力が負の場合は、2の補数
		if(this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER) {
			this.element = this.getTwosComplement(len).element;
			// 反転したことでさらに空になる可能性がある
			this._memory_reduction();
		}
		return this;
	}

	/**
	 * Logical Exclusive-OR.
	 * @param {KBigIntegerInputData} number 
	 * @returns {BigInteger} A ^ B
	 */
	xor(number) {
		return(this.clone()._xor(number));
	}

	/**
	 * Logical Not.
	 * @returns {BigInteger} A = !A
	 * @ignore
	 */
	_not() {
		return(this._add(new BigInteger(1))._negate());
	}

	/**
	 * Logical Not. (mutable)
	 * @returns {BigInteger} !A
	 */
	not() {
		return(this.clone()._not());
	}

	/**
	 * this | (1 << n) (mutable)
	 * @param {KBigIntegerInputData} bit
	 * @returns {BigInteger}
	 * @ignore
	 */
	_setBit(bit) {
		const n = BigInteger._toInteger(bit);
		this._memory_allocation(n + 1);
		this.element[n >>> 4] |= 1 << (n & 0xF);
		this.state = BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER;
		return this;
	}

	/**
	 * this | (1 << n)
	 * @param {KBigIntegerInputData} bit
	 * @returns {BigInteger}
	 */
	setBit(bit) {
		const n = BigInteger._toInteger(bit);
		return this.clone()._setBit(n);
	}

	/**
	 * Invert a specific bit.) (mutable)
	 * @param {KBigIntegerInputData} bit
	 * @returns {BigInteger}
	 * @ignore
	 */
	_flipBit(bit) {
		const n = BigInteger._toInteger(bit);
		this._memory_allocation(n + 1);
		this.element[n >>> 4] ^= 1 << (n & 0xF);
		this._memory_reduction();
		return this;
	}

	/**
	 * Invert a specific bit.
	 * @param {KBigIntegerInputData} bit
	 * @returns {BigInteger}
	 */
	flipBit(bit) {
		const n = BigInteger._toInteger(bit);
		return this.clone()._flipBit(n);
	}

	/**
	 * Lower a specific bit.
	 * @param {KBigIntegerInputData} bit 
	 * @returns {BigInteger}
	 */
	clearBit(bit) {
		const n = BigInteger._toInteger(bit);
		const y = this.clone();
		y.element[n >>> 4] &= ~(1 << (n & 0xF));
		y._memory_reduction();
		return y;
	}

	/**
	 * Test if a particular bit is on.
	 * @param {KBigIntegerInputData} bit
	 * @returns {boolean}
	 */
	testBit(bit) {
		const n = BigInteger._toInteger(bit);
		return ((this.element[n >>> 4] >>> (n & 0xF)) & 1) !== 0;
	}

	// ----------------------
	// テスト系
	// ----------------------
	
	/**
	 * this === 0
	 * @returns {boolean}
	 */
	isZero() {
		return this.state === BIGINTEGER_NUMBER_STATE.ZERO;
	}
	
	/**
	 * this === 1
	 * @returns {boolean}
	 */
	isOne() {
		return this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER && this.element.length === 1 && this.element[0] === 1;
	}
	
	/**
	 * this > 0
	 * @returns {boolean}
	 */
	isPositive() {
		return this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER || this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY;
	}

	/**
	 * this < 0
	 * @returns {boolean}
	 */
	isNegative() {
		return this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_NUMBER || this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY;
	}

	/**
	 * this >= 0
	 * @returns {boolean}
	 */
	isNotNegative() {
		return this.state === BIGINTEGER_NUMBER_STATE.ZERO || this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_NUMBER || this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY;
	}
	
	/**
	 * this === NaN
	 * @returns {boolean} isNaN(A)
	 */
	isNaN() {
		return this.state === BIGINTEGER_NUMBER_STATE.NOT_A_NUMBER;
	}
	
	/**
	 * this === Infinity
	 * @returns {boolean} isPositiveInfinity(A)
	 */
	isPositiveInfinity() {
		return this.state === BIGINTEGER_NUMBER_STATE.POSITIVE_INFINITY;
	}

	/**
	 * this === -Infinity
	 * @returns {boolean} isNegativeInfinity(A)
	 */
	isNegativeInfinity() {
		return this.state === BIGINTEGER_NUMBER_STATE.NEGATIVE_INFINITY;
	}

	/**
	 * this === Infinity or -Infinity
	 * @returns {boolean} isPositiveInfinity(A) || isNegativeInfinity(A)
	 */
	isInfinite() {
		return this.isPositiveInfinity() || this.isNegativeInfinity();
	}
	
	/**
	 * Return true if the value is finite number.
	 * @returns {boolean} !isNaN(A) && !isInfinite(A)
	 */
	isFinite() {
		return !this.isNaN() && !this.isInfinite();
	}

	// ----------------------
	// 定数
	// ----------------------
	
	/**
	 * -1
	 * @returns {BigInteger} -1
	 */
	static get MINUS_ONE() {
		return DEFINE.MINUS_ONE;
	}
	
	/**
	 * 0
	 * @returns {BigInteger} 0
	 */
	static get ZERO() {
		return DEFINE.ZERO;
	}

	/**
	 * 1
	 * @returns {BigInteger} 1
	 */
	static get ONE() {
		return DEFINE.ONE;
	}
	
	/**
	 * 2
	 * @returns {BigInteger} 2
	 */
	static get TWO() {
		return DEFINE.TWO;
	}
	
	/**
	 * 10
	 * @returns {BigInteger} 10
	 */
	static get TEN() {
		return DEFINE.TEN;
	}

	/**
	 * Positive infinity.
	 * @returns {BigInteger} Infinity
	 */
	static get POSITIVE_INFINITY() {
		return DEFINE.POSITIVE_INFINITY;
	}
	
	/**
	 * Negative Infinity.
	 * @returns {BigInteger} -Infinity
	 */
	static get NEGATIVE_INFINITY() {
		return DEFINE.NEGATIVE_INFINITY;
	}

	/**
	 * Not a Number.
	 * @returns {BigInteger} NaN
	 */
	static get NaN() {
		return DEFINE.NaN;
	}

	// ----------------------
	// 互換性
	// ----------------------
	
	/**
	 * The positive or negative sign of this number.
	 * - +1 if positive, -1 if negative, 0 if 0.
	 * @returns {number}
	 */
	signum() {
		return this.sign();
	}

	/**
	 * Subtract.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A - B
	 */
	subtract(number) {
		return this.sub(number);
	}

	/**
	 * Multiply.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A * B
	 */
	multiply(number) {
		return this.mul(number);
	}

	/**
	 * Divide.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} fix(A / B)
	 */
	divide(number) {
		return this.div(number);
	}

	/**
	 * Remainder of division.
	 * - Result has same sign as the Dividend.
	 * @param {KBigIntegerInputData} number
	 * @returns {BigInteger} A % B
	 */
	remainder(number) {
		return this.rem(number);
	}

}

/**
 * Collection of constant values used in the class.
 * @ignore
 */
const DEFINE = {

	/**
	 * -1
	 */
	MINUS_ONE : new BigInteger(-1),

	/**
	 * 0
	 */
	ZERO : new BigInteger(0),
	
	/**
	 * 1
	 */
	ONE : new BigInteger(1),

	/**
	 * 2
	 */
	TWO : new BigInteger(2),

	/**
	 * 10
	 */
	TEN : new BigInteger(10),

	/**
	 * Positive infinity.
	 */
	POSITIVE_INFINITY : new BigInteger(Number.POSITIVE_INFINITY),

	/**
	 * Negative Infinity.
	 */
	NEGATIVE_INFINITY : new BigInteger(Number.NEGATIVE_INFINITY),

	/**
	 * Not a Number.
	 */
	NaN : new BigInteger(Number.NaN)
};