/trunk/JavApi/java/math/Logical.cs
# · C# · 802 lines · 596 code · 74 blank · 132 comment · 213 complexity · b6bf95981ad2f0eb50f485e89837a4a0 MD5 · raw file
- /*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- using System;
- using java = biz.ritter.javapi;
- namespace biz.ritter.javapi.math
- {
- /**
- * The library implements some logical operations over {@code BigInteger}. The
- * operations provided are listed below.
- * <ul type="circle">
- * <li>not</li>
- * <li>and</li>
- * <li>andNot</li>
- * <li>or</li>
- * <li>xor</li>
- * </ul>
- */
- internal class Logical {
- /** Just to denote that this class can't be instantiated. */
-
- private Logical() {}
- /** @see BigInteger#not() */
- internal static BigInteger not(BigInteger val) {
- if (val.sign == 0) {
- return BigInteger.MINUS_ONE;
- }
- if (val.equals(BigInteger.MINUS_ONE)) {
- return BigInteger.ZERO;
- }
- int []resDigits = new int[val.numberLength + 1];
- int i;
- if (val.sign > 0) {
- // ~val = -val + 1
- if (val.digits[val.numberLength - 1] != -1) {
- for (i = 0; val.digits[i] == -1; i++) {
- ;
- }
- } else {
- for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
- ;
- }
- if (i == val.numberLength) {
- resDigits[i] = 1;
- return new BigInteger(-val.sign, i + 1, resDigits);
- }
- }
- // Here a carry 1 was generated
- } else {// (val.sign < 0)
- // ~val = -val - 1
- for (i = 0; val.digits[i] == 0; i++) {
- resDigits[i] = -1;
- }
- // Here a borrow -1 was generated
- }
- // Now, the carry/borrow can be absorbed
- resDigits[i] = val.digits[i] + val.sign;
- // Copying the remaining unchanged digit
- for (i++; i < val.numberLength; i++) {
- resDigits[i] = val.digits[i];
- }
- return new BigInteger(-val.sign, i, resDigits);
- }
- /** @see BigInteger#and(BigInteger) */
- internal static BigInteger and(BigInteger val, BigInteger that) {
- if (that.sign == 0 || val.sign == 0) {
- return BigInteger.ZERO;
- }
- if (that.equals(BigInteger.MINUS_ONE)){
- return val;
- }
- if (val.equals(BigInteger.MINUS_ONE)) {
- return that;
- }
-
- if (val.sign > 0) {
- if (that.sign > 0) {
- return andPositive(val, that);
- } else {
- return andDiffSigns(val, that);
- }
- } else {
- if (that.sign > 0) {
- return andDiffSigns(that, val);
- } else if (val.numberLength > that.numberLength) {
- return andNegative(val, that);
- } else {
- return andNegative(that, val);
- }
- }
- }
-
- /** @return sign = 1, magnitude = val.magnitude & that.magnitude*/
- internal static BigInteger andPositive(BigInteger val, BigInteger that) {
- // PRE: both arguments are positive
- int resLength = java.lang.Math.min(val.numberLength, that.numberLength);
- int i = java.lang.Math.max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit());
-
- if (i >= resLength) {
- return BigInteger.ZERO;
- }
-
- int []resDigits = new int[resLength];
- for ( ; i < resLength; i++) {
- resDigits[i] = val.digits[i] & that.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
- /** @return sign = positive.magnitude & magnitude = -negative.magnitude */
- internal static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) {
- // PRE: positive is positive and negative is negative
- int iPos = positive.getFirstNonzeroDigit();
- int iNeg = negative.getFirstNonzeroDigit();
-
- // Look if the trailing zeros of the negative will "blank" all
- // the positive digits
- if (iNeg >= positive.numberLength) {
- return BigInteger.ZERO;
- }
- int resLength = positive.numberLength;
- int[] resDigits = new int[resLength];
-
- // Must start from max(iPos, iNeg)
- int i = java.lang.Math.max(iPos, iNeg);
- if (i == iNeg) {
- resDigits[i] = -negative.digits[i] & positive.digits[i];
- i++;
- }
- int limit = java.lang.Math.min(negative.numberLength, positive.numberLength);
- for ( ; i < limit; i++) {
- resDigits[i] = ~negative.digits[i] & positive.digits[i];
- }
- // if the negative was shorter must copy the remaining digits
- // from positive
- if (i >= negative.numberLength) {
- for ( ; i < positive.numberLength; i++) {
- resDigits[i] = positive.digits[i];
- }
- } // else positive ended and must "copy" virtual 0's, do nothing then
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude)*/
- internal static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
- // PRE: longer and shorter are negative
- // PRE: longer has at least as many digits as shorter
- int iLonger = longer.getFirstNonzeroDigit();
- int iShorter = shorter.getFirstNonzeroDigit();
-
- // Does shorter matter?
- if (iLonger >= shorter.numberLength) {
- return longer;
- }
-
- int resLength;
- int []resDigits;
- int i = java.lang.Math.max(iShorter, iLonger);
- int digit;
- if (iShorter > iLonger) {
- digit = -shorter.digits[i] & ~longer.digits[i];
- } else if (iShorter < iLonger) {
- digit = ~shorter.digits[i] & -longer.digits[i];
- } else {
- digit = -shorter.digits[i] & -longer.digits[i];
- }
- if (digit == 0) {
- for (i++; i < shorter.numberLength && (digit = ~(longer.digits[i] | shorter.digits[i])) == 0; i++)
- ; // digit = ~longer.digits[i] & ~shorter.digits[i]
- if (digit == 0) {
- // shorter has only the remaining virtual sign bits
- for ( ; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++)
- ;
- if (digit == 0) {
- resLength = longer.numberLength + 1;
- resDigits = new int[resLength];
- resDigits[resLength - 1] = 1;
- BigInteger result = new BigInteger(-1, resLength, resDigits);
- return result;
- }
- }
- }
- resLength = longer.numberLength;
- resDigits = new int[resLength];
- resDigits[i] = -digit;
- for (i++; i < shorter.numberLength; i++){
- // resDigits[i] = ~(~longer.digits[i] & ~shorter.digits[i];)
- resDigits[i] = longer.digits[i] | shorter.digits[i];
- }
- // shorter has only the remaining virtual sign bits
- for( ; i < longer.numberLength; i++){
- resDigits[i] = longer.digits[i];
- }
-
- BigInteger result1 = new BigInteger(-1, resLength, resDigits);
- return result1;
- }
-
- /** @see BigInteger#andNot(BigInteger) */
- internal static BigInteger andNot(BigInteger val, BigInteger that) {
- if (that.sign == 0 ) {
- return val;
- }
- if (val.sign == 0) {
- return BigInteger.ZERO;
- }
- if (val.equals(BigInteger.MINUS_ONE)) {
- return that.not();
- }
- if (that.equals(BigInteger.MINUS_ONE)){
- return BigInteger.ZERO;
- }
-
- //if val == that, return 0
-
- if (val.sign > 0) {
- if (that.sign > 0) {
- return andNotPositive(val, that);
- } else {
- return andNotPositiveNegative(val, that);
- }
- } else {
- if (that.sign > 0) {
- return andNotNegativePositive(val, that);
- } else {
- return andNotNegative(val, that);
- }
- }
- }
-
- /** @return sign = 1, magnitude = val.magnitude & ~that.magnitude*/
- internal static BigInteger andNotPositive(BigInteger val, BigInteger that) {
- // PRE: both arguments are positive
- int []resDigits = new int[val.numberLength];
-
- int limit = java.lang.Math.min(val.numberLength, that.numberLength);
- int i;
- for (i = val.getFirstNonzeroDigit(); i < limit; i++) {
- resDigits[i] = val.digits[i] & ~that.digits[i];
- }
- for ( ; i < val.numberLength; i++) {
- resDigits[i] = val.digits[i];
- }
-
- BigInteger result = new BigInteger(1, val.numberLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude)*/
- internal static BigInteger andNotPositiveNegative(BigInteger positive, BigInteger negative) {
- // PRE: positive > 0 && negative < 0
- int iNeg = negative.getFirstNonzeroDigit();
- int iPos = positive.getFirstNonzeroDigit();
-
- if (iNeg >= positive.numberLength) {
- return positive;
- }
-
- int resLength = java.lang.Math.min(positive.numberLength, negative.numberLength);
- int []resDigits = new int[resLength];
-
- // Always start from first non zero of positive
- int i = iPos;
- for ( ; i < iNeg; i++) {
- // resDigits[i] = positive.digits[i] & -1 (~0)
- resDigits[i] = positive.digits[i];
- }
- if (i == iNeg) {
- resDigits[i] = positive.digits[i] & (negative.digits[i] - 1);
- i++;
- }
- for ( ; i < resLength; i++) {
- // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]);
- resDigits[i] = positive.digits[i] & negative.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude)*/
- internal static BigInteger andNotNegativePositive(BigInteger negative, BigInteger positive) {
- // PRE: negative < 0 && positive > 0
- int resLength;
- int [] resDigits;
- int limit;
- int digit;
-
- int iNeg = negative.getFirstNonzeroDigit();
- int iPos = positive.getFirstNonzeroDigit();
-
- if (iNeg >= positive.numberLength) {
- return negative;
- }
-
- resLength = java.lang.Math.max(negative.numberLength, positive.numberLength);
- int i = iNeg;
- if (iPos > iNeg) {
- resDigits = new int[resLength];
- limit = java.lang.Math.min(negative.numberLength, iPos);
- for ( ; i < limit; i++) {
- // 1st case: resDigits [i] = -(-negative.digits[i] & (~0))
- // otherwise: resDigits[i] = ~(~negative.digits[i] & ~0) ;
- resDigits[i] = negative.digits[i];
- }
- if (i == negative.numberLength) {
- for (i = iPos; i < positive.numberLength; i++) {
- // resDigits[i] = ~(~positive.digits[i] & -1);
- resDigits[i] = positive.digits[i];
- }
- }
- } else {
- digit = -negative.digits[i] & ~positive.digits[i];
- if (digit == 0) {
- limit = java.lang.Math.min(positive.numberLength, negative.numberLength);
- for (i++; i < limit && (digit = ~(negative.digits[i] | positive.digits[i])) == 0; i++)
- ; // digit = ~negative.digits[i] & ~positive.digits[i]
- if (digit == 0) {
- // the shorter has only the remaining virtual sign bits
- for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
- ; // digit = -1 & ~positive.digits[i]
- for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
- ; // digit = ~negative.digits[i] & ~0
- if (digit == 0) {
- resLength++;
- resDigits = new int[resLength];
- resDigits[resLength - 1] = 1;
-
- BigInteger result = new BigInteger(-1, resLength, resDigits);
- return result;
- }
- }
- }
- resDigits = new int[resLength];
- resDigits[i] = -digit;
- i++;
- }
-
- limit = java.lang.Math.min(positive.numberLength, negative.numberLength);
- for ( ; i < limit; i++) {
- //resDigits[i] = ~(~negative.digits[i] & ~positive.digits[i]);
- resDigits[i] = negative.digits[i] | positive.digits[i];
- }
- // Actually one of the next two cycles will be executed
- for ( ; i < negative.numberLength; i++) {
- resDigits[i] = negative.digits[i];
- }
- for ( ; i < positive.numberLength; i++) {
- resDigits[i] = positive.digits[i];
- }
-
- BigInteger result1 = new BigInteger(-1, resLength, resDigits);
- return result1;
- }
-
- /** @return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude)*/
- internal static BigInteger andNotNegative(BigInteger val, BigInteger that) {
- // PRE: val < 0 && that < 0
- int iVal = val.getFirstNonzeroDigit();
- int iThat = that.getFirstNonzeroDigit();
-
- if (iVal >= that.numberLength) {
- return BigInteger.ZERO;
- }
-
- int resLength = that.numberLength;
- int[] resDigits = new int[resLength];
- int limit;
- int i = iVal;
- if (iVal < iThat) {
- // resDigits[i] = -val.digits[i] & -1;
- resDigits[i] = -val.digits[i];
- limit = java.lang.Math.min(val.numberLength, iThat);
- for (i++; i < limit; i++) {
- // resDigits[i] = ~val.digits[i] & -1;
- resDigits[i] = ~val.digits[i];
- }
- if (i == val.numberLength) {
- for ( ; i < iThat; i++) {
- // resDigits[i] = -1 & -1;
- resDigits[i] = -1;
- }
- // resDigits[i] = -1 & ~-that.digits[i];
- resDigits[i] = that.digits[i] - 1;
- } else {
- // resDigits[i] = ~val.digits[i] & ~-that.digits[i];
- resDigits[i] = ~val.digits[i] & (that.digits[i] - 1);
- }
- } else if (iThat < iVal ) {
- // resDigits[i] = -val.digits[i] & ~~that.digits[i];
- resDigits[i] = -val.digits[i] & that.digits[i];
- } else {
- // resDigits[i] = -val.digits[i] & ~-that.digits[i];
- resDigits[i] = -val.digits[i] & (that.digits[i] - 1);
- }
-
- limit = java.lang.Math.min(val.numberLength, that.numberLength);
- for (i++; i < limit; i++) {
- // resDigits[i] = ~val.digits[i] & ~~that.digits[i];
- resDigits[i] = ~val.digits[i] & that.digits[i];
- }
- for ( ; i < that.numberLength; i++) {
- // resDigits[i] = -1 & ~~that.digits[i];
- resDigits[i] = that.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
- /** @see BigInteger#or(BigInteger) */
- internal static BigInteger or(BigInteger val, BigInteger that) {
- if (that.equals(BigInteger.MINUS_ONE) || val.equals(BigInteger.MINUS_ONE)) {
- return BigInteger.MINUS_ONE;
- }
- if (that.sign == 0) {
- return val;
- }
- if (val.sign == 0) {
- return that;
- }
- if (val.sign > 0) {
- if (that.sign > 0) {
- if (val.numberLength > that.numberLength) {
- return orPositive(val, that);
- } else {
- return orPositive(that, val);
- }
- } else {
- return orDiffSigns(val, that);
- }
- } else {
- if (that.sign > 0) {
- return orDiffSigns(that, val);
- } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
- return orNegative(that, val);
- } else {
- return orNegative(val, that);
- }
- }
- }
-
- /** @return sign = 1, magnitude = longer.magnitude | shorter.magnitude*/
- internal static BigInteger orPositive(BigInteger longer, BigInteger shorter) {
- // PRE: longer and shorter are positive;
- // PRE: longer has at least as many digits as shorter
- int resLength = longer.numberLength;
- int[] resDigits = new int[resLength];
-
- int i = java.lang.Math.min(longer.getFirstNonzeroDigit(), shorter.getFirstNonzeroDigit());
- for (i = 0; i < shorter.numberLength; i++) {
- resDigits[i] = longer.digits[i] | shorter.digits[i];
- }
- for ( ; i < resLength; i++) {
- resDigits[i] = longer.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- return result;
- }
-
- /** @return sign = -1, magnitude = -(-val.magnitude | -that.magnitude) */
- internal static BigInteger orNegative(BigInteger val, BigInteger that){
- // PRE: val and that are negative;
- // PRE: val has at least as many trailing zeros digits as that
- int iThat = that.getFirstNonzeroDigit();
- int iVal = val.getFirstNonzeroDigit();
- int i;
-
- if (iVal >= that.numberLength) {
- return that;
- }else if (iThat >= val.numberLength) {
- return val;
- }
-
- int resLength = java.lang.Math.min(val.numberLength, that.numberLength);
- int[] resDigits = new int[resLength];
-
- //Looking for the first non-zero digit of the result
- if (iThat == iVal) {
- resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]);
- i = iVal;
- } else {
- for (i = iThat; i < iVal; i++) {
- resDigits[i] = that.digits[i];
- }
- resDigits[i] = that.digits[i] & (val.digits[i] - 1);
- }
-
- for (i++; i < resLength; i++) {
- resDigits[i] = val.digits[i] & that.digits[i];
- }
-
- BigInteger result = new BigInteger(-1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude) */
- internal static BigInteger orDiffSigns(BigInteger positive, BigInteger negative){
- // Jumping over the least significant zero bits
- int iNeg = negative.getFirstNonzeroDigit();
- int iPos = positive.getFirstNonzeroDigit();
- int i;
- int limit;
-
- // Look if the trailing zeros of the positive will "copy" all
- // the negative digits
- if (iPos >= negative.numberLength) {
- return negative;
- }
- int resLength = negative.numberLength;
- int[] resDigits = new int[resLength];
-
- if (iNeg < iPos ) {
- // We know for sure that this will
- // be the first non zero digit in the result
- for (i = iNeg; i < iPos; i++) {
- resDigits[i] = negative.digits[i];
- }
- } else if (iPos < iNeg) {
- i = iPos;
- resDigits[i] = -positive.digits[i];
- limit = java.lang.Math.min(positive.numberLength, iNeg);
- for(i++; i < limit; i++ ) {
- resDigits[i] = ~positive.digits[i];
- }
- if (i != positive.numberLength) {
- resDigits[i] = ~(-negative.digits[i] | positive.digits[i]);
- } else{
- for (; i<iNeg; i++) {
- resDigits[i] = -1;
- }
- // resDigits[i] = ~(-negative.digits[i] | 0);
- resDigits[i] = negative.digits[i] - 1;
- }
- i++;
- } else {// iNeg == iPos
- // Applying two complement to negative and to result
- i = iPos;
- resDigits[i] = -(-negative.digits[i] | positive.digits[i]);
- i++;
- }
- limit = java.lang.Math.min(negative.numberLength, positive.numberLength);
- for (; i < limit; i++) {
- // Applying two complement to negative and to result
- // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] );
- resDigits[i] = negative.digits[i] & ~positive.digits[i];
- }
- for( ; i < negative.numberLength; i++) {
- resDigits[i] = negative.digits[i];
- }
-
- BigInteger result = new BigInteger(-1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
- /** @see BigInteger#xor(BigInteger) */
- internal static BigInteger xor(BigInteger val, BigInteger that) {
- if (that.sign == 0) {
- return val;
- }
- if (val.sign == 0) {
- return that;
- }
- if (that.equals(BigInteger.MINUS_ONE)) {
- return val.not();
- }
- if (val.equals(BigInteger.MINUS_ONE)) {
- return that.not();
- }
-
- if (val.sign > 0) {
- if (that.sign > 0) {
- if (val.numberLength > that.numberLength) {
- return xorPositive(val, that);
- } else {
- return xorPositive(that, val);
- }
- } else {
- return xorDiffSigns(val, that);
- }
- } else {
- if (that.sign > 0) {
- return xorDiffSigns(that, val);
- } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
- return xorNegative(that, val);
- } else {
- return xorNegative(val, that);
- }
- }
- }
-
- /** @return sign = 0, magnitude = longer.magnitude | shorter.magnitude */
- internal static BigInteger xorPositive(BigInteger longer, BigInteger shorter) {
- // PRE: longer and shorter are positive;
- // PRE: longer has at least as many digits as shorter
- int resLength = longer.numberLength;
- int[] resDigits = new int[resLength];
- int i = java.lang.Math.min(longer.getFirstNonzeroDigit(), shorter.getFirstNonzeroDigit());
- for ( ; i < shorter.numberLength; i++) {
- resDigits[i] = longer.digits[i] ^ shorter.digits[i];
- }
- for( ; i < longer.numberLength; i++ ){
- resDigits[i] = longer.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = 0, magnitude = -val.magnitude ^ -that.magnitude */
- internal static BigInteger xorNegative(BigInteger val, BigInteger that){
- // PRE: val and that are negative
- // PRE: val has at least as many trailing zero digits as that
- int resLength = java.lang.Math.max(val.numberLength, that.numberLength);
- int[] resDigits = new int[resLength];
- int iVal = val.getFirstNonzeroDigit();
- int iThat = that.getFirstNonzeroDigit();
- int i = iThat;
- int limit;
-
-
- if (iVal == iThat) {
- resDigits[i] = -val.digits[i] ^ -that.digits[i];
- } else {
- resDigits[i] = -that.digits[i];
- limit = java.lang.Math.min(that.numberLength, iVal);
- for (i++; i < limit; i++) {
- resDigits[i] = ~that.digits[i];
- }
- // Remains digits in that?
- if (i == that.numberLength) {
- //Jumping over the remaining zero to the first non one
- for ( ;i < iVal; i++) {
- //resDigits[i] = 0 ^ -1;
- resDigits[i] = -1;
- }
- //resDigits[i] = -val.digits[i] ^ -1;
- resDigits[i] = val.digits[i] - 1;
- } else {
- resDigits[i] = -val.digits[i] ^ ~that.digits[i];
- }
- }
-
- limit = java.lang.Math.min(val.numberLength, that.numberLength);
- //Perform ^ between that al val until that ends
- for (i++; i < limit; i++) {
- //resDigits[i] = ~val.digits[i] ^ ~that.digits[i];
- resDigits[i] = val.digits[i] ^ that.digits[i];
- }
- //Perform ^ between val digits and -1 until val ends
- for ( ; i < val.numberLength; i++) {
- //resDigits[i] = ~val.digits[i] ^ -1 ;
- resDigits[i] = val.digits[i] ;
- }
- for ( ; i < that.numberLength; i++) {
- //resDigits[i] = -1 ^ ~that.digits[i] ;
- resDigits[i] = that.digits[i];
- }
-
- BigInteger result = new BigInteger(1, resLength, resDigits);
- result.cutOffLeadingZeroes();
- return result;
- }
-
- /** @return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude)*/
- internal static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative){
- int resLength = java.lang.Math.max(negative.numberLength, positive.numberLength);
- int[] resDigits;
- int iNeg = negative.getFirstNonzeroDigit();
- int iPos = positive.getFirstNonzeroDigit();
- int i;
- int limit;
-
- //The first
- if (iNeg < iPos) {
- resDigits = new int[resLength];
- i = iNeg;
- //resDigits[i] = -(-negative.digits[i]);
- resDigits[i] = negative.digits[i];
- limit = java.lang.Math.min(negative.numberLength, iPos);
- //Skip the positive digits while they are zeros
- for (i++; i < limit; i++) {
- //resDigits[i] = ~(~negative.digits[i]);
- resDigits[i] = negative.digits[i];
- }
- //if the negative has no more elements, must fill the
- //result with the remaining digits of the positive
- if (i == negative.numberLength) {
- for ( ; i < positive.numberLength; i++) {
- //resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i])
- resDigits[i] = positive.digits[i];
- }
- }
- } else if (iPos < iNeg) {
- resDigits = new int[resLength];
- i = iPos;
- //Applying two complement to the first non-zero digit of the result
- resDigits[i] = -positive.digits[i];
- limit = java.lang.Math.min(positive.numberLength, iNeg);
- for (i++; i < limit; i++) {
- //Continue applying two complement the result
- resDigits[i] = ~positive.digits[i];
- }
- //When the first non-zero digit of the negative is reached, must apply
- //two complement (arithmetic negation) to it, and then operate
- if (i == iNeg) {
- resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]);
- i++;
- } else {
- //if the positive has no more elements must fill the remaining digits with
- //the negative ones
- for ( ; i < iNeg; i++) {
- // resDigits[i] = ~(0 ^ 0)
- resDigits[i] = -1;
- }
- for ( ; i < negative.numberLength; i++) {
- //resDigits[i] = ~(~negative.digits[i] ^ 0)
- resDigits[i] = negative.digits[i];
- }
- }
- } else {
- int digit;
- //The first non-zero digit of the positive and negative are the same
- i = iNeg;
- digit = positive.digits[i] ^ -negative.digits[i];
- if (digit == 0) {
- limit = java.lang.Math.min(positive.numberLength, negative.numberLength);
- for (i++; i < limit && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++)
- ;
- if (digit == 0) {
- // shorter has only the remaining virtual sign bits
- for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
- ;
- for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
- ;
- if (digit == 0) {
- resLength = resLength + 1;
- resDigits = new int[resLength];
- resDigits[resLength - 1] = 1;
-
- BigInteger result = new BigInteger(-1, resLength, resDigits);
- return result;
- }
- }
- }
- resDigits = new int[resLength];
- resDigits[i] = -digit;
- i++;
- }
-
- limit = java.lang.Math.min(negative.numberLength, positive.numberLength);
- for ( ; i < limit; i++) {
- resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]);
- }
- for ( ; i < positive.numberLength; i++) {
- // resDigits[i] = ~(positive.digits[i] ^ -1)
- resDigits[i] = positive.digits[i];
- }
- for ( ; i < negative.numberLength; i++) {
- // resDigits[i] = ~(0 ^ ~negative.digits[i])
- resDigits[i] = negative.digits[i];
- }
-
- BigInteger result1 = new BigInteger(-1, resLength, resDigits);
- result1.cutOffLeadingZeroes();
- return result1;
- }
- }
- }