

__BIGINT_THIS_FILE_IS( "sub.js", "v0.5 beta 9", "2003-12-28" );


//////////////////////////////////////////////////////////////////////////////////////

Bigint.sub = function( number1, number2 ) {
	var bigNumber1 = Bigint.serio( number1 );
	var bigNumber2 = Bigint.serio( number2 );

	var cmp;
	var bigResult;

	if( bigNumber1.sign >= 0 ) {
		if( bigNumber2.sign >= 0 ) {
			cmp = Bigint._tablecmp( bigNumber1.table, bigNumber2.table );
			if( cmp > 0 ) {
				bigResult = Bigint._sub( bigNumber1, bigNumber2 );
				bigResult.sign = bigResult.isZero()? 0 : (+1) ;
			} else if( cmp === 0 ) {
				return new Bigint(0);
			} else {
				bigResult = Bigint._sub( bigNumber2, bigNumber1 );
				bigResult.sign = (-1);
			}
		} else {
			bigResult = Bigint._add( bigNumber1, bigNumber2 );
			bigResult.sign = (+1);
		}
	} else { // bigNumber1 is negative
		if( bigNumber2.sign > 0 ) {
			bigResult = Bigint._add( bigNumber1, bigNumber2 );
			bigResult.sign = (-1);
		} else {
			cmp = Bigint._tablecmp( bigNumber1.table, bigNumber2.table );
			if( cmp > 0 ) {
				bigResult = Bigint._sub( bigNumber1, bigNumber2 );
				bigResult.sign = (-1);
			} else if( cmp === 0 ) {
				return new Bigint(0);
			} else {
				bigResult = Bigint._sub( bigNumber2, bigNumber1 );
				bigResult.sign = (+1);
			}
		}
	}
	
	return bigResult;
}

Bigint._sub = function( bigNumber1, bigNumber2 ) {
	var tableSize = bigNumber1.table.length;
	var flag = 0;
	var bigResult = new Bigint();

	for( var i = 0; i < tableSize; i++ ) {
		bigResult.table[i] = bigNumber1.table[i] - flag;
		if( bigNumber2.table[i] ) bigResult.table[i] -= bigNumber2.table[i];
		if( bigResult.table[i] < 0 ) {
			flag = 1;
			bigResult.table[i] += __BIGINT_BIG_UNIT;
		} else {
			flag = 0;
		}
	}
	
	while( bigResult.table.length > 1 ) {
		var lastIndex = bigResult.table.length - 1;
		if( bigResult.table[ lastIndex ] === 0 ) bigResult.table.length--;
		else break;
	}

	return bigResult;
}

Bigint._sub_typeN = function( bigNumber, smallNumber ) {
	var bigResult = bigNumber.copy();
	var flag = 0;
	bigResult.table[0] -= smallNumber;
	
	if( bigResult.table[0] >= 0 ) {
		return bigResult;
	} else {
		bigResult.table[0] += __BIGINT_BIG_UNIT;
		flag = 1;
	}

	for( var i=1; i<bigResult.table.length; i++ ) {
		bigResult.table[i] -= flag;
		if( bigResult.table[i] < 0 ) {
			bigResult.table[i] += __BIGINT_BIG_UNIT;
			flag = 1;
		} else {
			break;
		}
	}

	var lastIndex = bigResult.table.length - 1;
	if( bigResult.table[ lastIndex ] === 0 ) bigResult.table.length--;

	return bigResult;
}

Bigint.prototype.decrement = function( input ) {
	if( input === void 0 ) {
		this._decrement( 1 );
	} else if( input.isBigint || input >= __BIGINT_BIG_UNIT || input < 0 || this.sign < 0 ) {
		var bigResult = Bigint.sub( this , input );
		this.sign = bigResult.sign;
		this.table = bigResult.table;
	} else {
		var n = Math.floor( input - 0 );
		if( isNaN( n ) ) {
			Bigint._error( "decrement" , "Bad input: " + input );
			this.setNaB();
		} else if( this.table.length === 1 ) {
			if( this.table[0] > n ) this.table[0] -= n;
			else if( this.table[0] === n ) this.table[0] = 0, this.sign = 0;
			else this.table[0] = n - this.table[0], this.sign = (-1);
		} else {
			this._decrement( n );
		}
	}
}

Bigint.prototype._decrement = function( n ) {
	if( n === void 0 ) n = 1;
	this.table[0] -= n;
	var i = 0;
	var flag = 0;
	for( ; i < this.table.length; i++ ) {
		this.table[i] -= flag;
		if( this.table[i] < 0 ) {
			this.table[i] += __BIGINT_BIG_UNIT;
			flag = 1;
		} else {
			flag = 0;
			break;
		}
	}

	if( this.table[ this.table.length - 1 ] === 0 ) {
		if( this.table.length === 1 ) this.sign = 0;
		else this.table.length--;
	}
}


Bigint._strsub = function ( strNumber1 , strNumber2 ) {
	var biggerTable = new Array();

	var pos1 = strNumber1.length;
	var pos2 = strNumber2.length;

	var n1, n2;
	var flag = 0;

	for( var i = 0; i < 1000 ; i++ ) {
		n1 = strNumber1.substring( pos1 - __BIGINT_BIGGER_POWER, pos1 ) - 0;

		if( pos2 >= 0 ) n2 = strNumber2.substring( pos2 - __BIGINT_BIGGER_POWER, pos2 ) - 0;
		else n2 = 0;

		var nResult = n1 - ( n2 + flag );
		if( nResult >= 0 ) {
			biggerTable[i] = nResult;
			flag = 0;
		} else {
			biggerTable[i] = nResult + __BIGINT_BIGGER_UNIT;
			flag = 1;
		}

		pos1 -= __BIGINT_BIGGER_POWER;
		pos2 -= __BIGINT_BIGGER_POWER;

		if( pos1 <= 0 ) break;
	}

	if( pos2 > 0 || flag ) {
//		Bigint._debug( "<em style='background:yellow'>_strsub: strNumber2 is bigger: " + strNumber1 + " - " + strNumber2 + "<\/em>");
		return void 0;
	}

	var lastIndex;

	while( biggerTable.length > 1 ) {
		lastIndex = biggerTable.length - 1;
		if( biggerTable[ lastIndex ] === 0 ) biggerTable.length--;
		else break;
	}

	lastIndex = biggerTable.length - 1;

	var strResult = biggerTable[ lastIndex ] + "";

	for( var i = lastIndex - 1; i >= 0; i-- ) {
		strResult += Bigint._paddingBigger( biggerTable[ i ] );
	}
	return strResult;
}

//_sqmod_sub = Bigint._strsub;
