summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/math/Logical.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/math/Logical.java')
-rw-r--r--luni/src/main/java/java/math/Logical.java800
1 files changed, 800 insertions, 0 deletions
diff --git a/luni/src/main/java/java/math/Logical.java b/luni/src/main/java/java/math/Logical.java
new file mode 100644
index 0000000..677f7f0
--- /dev/null
+++ b/luni/src/main/java/java/math/Logical.java
@@ -0,0 +1,800 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.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>
+ */
+class Logical {
+
+ /** Just to denote that this class can't be instantiated. */
+
+ private Logical() {}
+
+
+ /** @see BigInteger#not() */
+ 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) */
+ 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*/
+ static BigInteger andPositive(BigInteger val, BigInteger that) {
+ // PRE: both arguments are positive
+ int resLength = Math.min(val.numberLength, that.numberLength);
+ int i = 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 */
+ 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 = Math.max(iPos, iNeg);
+ if (i == iNeg) {
+ resDigits[i] = -negative.digits[i] & positive.digits[i];
+ i++;
+ }
+ int limit = 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)*/
+ 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 = 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 result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+
+ /** @see BigInteger#andNot(BigInteger) */
+ 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*/
+ static BigInteger andNotPositive(BigInteger val, BigInteger that) {
+ // PRE: both arguments are positive
+ int resDigits[] = new int[val.numberLength];
+
+ int limit = 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)*/
+ 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 = 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)*/
+ 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 = Math.max(negative.numberLength, positive.numberLength);
+ int i = iNeg;
+ if (iPos > iNeg) {
+ resDigits = new int[resLength];
+ limit = 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 = 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 = 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 result = new BigInteger(-1, resLength, resDigits);
+ return result;
+ }
+
+ /** @return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude)*/
+ 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 = 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 = 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) */
+ 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*/
+ 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 = 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) */
+ 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 = 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) */
+ 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 = 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 = 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) */
+ 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 */
+ 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 = 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 */
+ 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 = 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 = 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 = 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)*/
+ static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative){
+ int resLength = 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 = 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 = 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 = 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 = 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 result = new BigInteger(-1, resLength, resDigits);
+ result.cutOffLeadingZeroes();
+ return result;
+ }
+}