Home | History | Annotate | Download | only in math
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.math;
     19 
     20 /**
     21  * The library implements some logical operations over {@code BigInteger}. The
     22  * operations provided are listed below.
     23  * <ul type="circle">
     24  * <li>not</li>
     25  * <li>and</li>
     26  * <li>andNot</li>
     27  * <li>or</li>
     28  * <li>xor</li>
     29  * </ul>
     30  */
     31 class Logical {
     32 
     33     /** Just to denote that this class can't be instantiated. */
     34 
     35     private Logical() {}
     36 
     37 
     38     /** @see BigInteger#not() */
     39     static BigInteger not(BigInteger val) {
     40         if (val.sign == 0) {
     41             return BigInteger.MINUS_ONE;
     42         }
     43         if (val.equals(BigInteger.MINUS_ONE)) {
     44             return BigInteger.ZERO;
     45         }
     46         int[] resDigits = new int[val.numberLength + 1];
     47         int i;
     48 
     49         if (val.sign > 0) {
     50             // ~val = -val + 1
     51             if (val.digits[val.numberLength - 1] != -1) {
     52                 for (i = 0; val.digits[i] == -1; i++) {
     53                     ;
     54                 }
     55             } else {
     56                 for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
     57                     ;
     58                 }
     59                 if (i == val.numberLength) {
     60                     resDigits[i] = 1;
     61                     return new BigInteger(-val.sign, i + 1, resDigits);
     62                 }
     63             }
     64             // Here a carry 1 was generated
     65         } else {// (val.sign < 0)
     66             // ~val = -val - 1
     67             for (i = 0; val.digits[i] == 0; i++) {
     68                 resDigits[i] = -1;
     69             }
     70             // Here a borrow -1 was generated
     71         }
     72         // Now, the carry/borrow can be absorbed
     73         resDigits[i] = val.digits[i] + val.sign;
     74         // Copying the remaining unchanged digit
     75         for (i++; i < val.numberLength; i++) {
     76             resDigits[i] = val.digits[i];
     77         }
     78         return new BigInteger(-val.sign, i, resDigits);
     79     }
     80 
     81     /** @see BigInteger#and(BigInteger) */
     82     static BigInteger and(BigInteger val, BigInteger that) {
     83         if (that.sign == 0 || val.sign == 0) {
     84             return BigInteger.ZERO;
     85         }
     86         if (that.equals(BigInteger.MINUS_ONE)){
     87             return val;
     88         }
     89         if (val.equals(BigInteger.MINUS_ONE)) {
     90             return that;
     91         }
     92 
     93         if (val.sign > 0) {
     94             if (that.sign > 0) {
     95                 return andPositive(val, that);
     96             } else {
     97                 return andDiffSigns(val, that);
     98             }
     99         } else {
    100             if (that.sign > 0) {
    101                 return andDiffSigns(that, val);
    102             } else if (val.numberLength > that.numberLength) {
    103                 return andNegative(val, that);
    104             } else {
    105                 return andNegative(that, val);
    106             }
    107         }
    108     }
    109 
    110     /** @return sign = 1, magnitude = val.magnitude & that.magnitude*/
    111     static BigInteger andPositive(BigInteger val, BigInteger that) {
    112         // PRE: both arguments are positive
    113         int resLength = Math.min(val.numberLength, that.numberLength);
    114         int i = Math.max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit());
    115 
    116         if (i >= resLength) {
    117             return BigInteger.ZERO;
    118         }
    119 
    120         int[] resDigits = new int[resLength];
    121         for ( ; i < resLength; i++) {
    122             resDigits[i] = val.digits[i] & that.digits[i];
    123         }
    124 
    125         return new BigInteger(1, resLength, resDigits);
    126     }
    127 
    128     /** @return sign = positive.magnitude & magnitude = -negative.magnitude */
    129     static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) {
    130         // PRE: positive is positive and negative is negative
    131         int iPos = positive.getFirstNonzeroDigit();
    132         int iNeg = negative.getFirstNonzeroDigit();
    133 
    134         // Look if the trailing zeros of the negative will "blank" all
    135         // the positive digits
    136         if (iNeg >= positive.numberLength) {
    137             return BigInteger.ZERO;
    138         }
    139         int resLength = positive.numberLength;
    140         int[] resDigits = new int[resLength];
    141 
    142         // Must start from max(iPos, iNeg)
    143         int i = Math.max(iPos, iNeg);
    144         if (i == iNeg) {
    145             resDigits[i] = -negative.digits[i] & positive.digits[i];
    146             i++;
    147         }
    148         int limit = Math.min(negative.numberLength, positive.numberLength);
    149         for ( ; i < limit; i++) {
    150             resDigits[i] = ~negative.digits[i] & positive.digits[i];
    151         }
    152         // if the negative was shorter must copy the remaining digits
    153         // from positive
    154         if (i >= negative.numberLength) {
    155             for ( ; i < positive.numberLength; i++) {
    156                 resDigits[i] = positive.digits[i];
    157             }
    158         } // else positive ended and must "copy" virtual 0's, do nothing then
    159 
    160         return new BigInteger(1, resLength, resDigits);
    161     }
    162 
    163     /** @return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude)*/
    164     static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
    165         // PRE: longer and shorter are negative
    166         // PRE: longer has at least as many digits as shorter
    167         int iLonger = longer.getFirstNonzeroDigit();
    168         int iShorter = shorter.getFirstNonzeroDigit();
    169 
    170         // Does shorter matter?
    171         if (iLonger >= shorter.numberLength) {
    172             return longer;
    173         }
    174 
    175         int resLength;
    176         int[] resDigits;
    177         int i = Math.max(iShorter, iLonger);
    178         int digit;
    179         if (iShorter > iLonger) {
    180             digit = -shorter.digits[i] & ~longer.digits[i];
    181         } else if (iShorter < iLonger) {
    182             digit = ~shorter.digits[i] & -longer.digits[i];
    183         } else {
    184             digit = -shorter.digits[i] & -longer.digits[i];
    185         }
    186         if (digit == 0) {
    187             for (i++; i < shorter.numberLength && (digit = ~(longer.digits[i] | shorter.digits[i])) == 0; i++)
    188                 ;  // digit = ~longer.digits[i] & ~shorter.digits[i]
    189             if (digit == 0) {
    190                 // shorter has only the remaining virtual sign bits
    191                 for ( ; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++)
    192                     ;
    193                 if (digit == 0) {
    194                     resLength = longer.numberLength + 1;
    195                     resDigits = new int[resLength];
    196                     resDigits[resLength - 1] = 1;
    197 
    198                     return new BigInteger(-1, resLength, resDigits);
    199                 }
    200             }
    201         }
    202         resLength = longer.numberLength;
    203                 resDigits = new int[resLength];
    204         resDigits[i] = -digit;
    205         for (i++; i < shorter.numberLength; i++){
    206             // resDigits[i] = ~(~longer.digits[i] & ~shorter.digits[i];)
    207             resDigits[i] = longer.digits[i] | shorter.digits[i];
    208         }
    209         // shorter has only the remaining virtual sign bits
    210         for ( ; i < longer.numberLength; i++){
    211             resDigits[i] = longer.digits[i];
    212         }
    213 
    214         return new BigInteger(-1, resLength, resDigits);
    215     }
    216 
    217     /** @see BigInteger#andNot(BigInteger) */
    218     static BigInteger andNot(BigInteger val, BigInteger that) {
    219         if (that.sign == 0 ) {
    220             return val;
    221         }
    222         if (val.sign == 0) {
    223             return BigInteger.ZERO;
    224         }
    225         if (val.equals(BigInteger.MINUS_ONE)) {
    226             return that.not();
    227         }
    228         if (that.equals(BigInteger.MINUS_ONE)){
    229             return BigInteger.ZERO;
    230         }
    231 
    232         //if val == that, return 0
    233 
    234        if (val.sign > 0) {
    235             if (that.sign > 0) {
    236                 return andNotPositive(val, that);
    237             } else {
    238                 return andNotPositiveNegative(val, that);
    239                     }
    240                 } else {
    241             if (that.sign > 0) {
    242                 return andNotNegativePositive(val, that);
    243             } else  {
    244                 return andNotNegative(val, that);
    245             }
    246         }
    247     }
    248 
    249     /** @return sign = 1, magnitude = val.magnitude & ~that.magnitude*/
    250     static BigInteger andNotPositive(BigInteger val, BigInteger that) {
    251         // PRE: both arguments are positive
    252         int[] resDigits = new int[val.numberLength];
    253 
    254         int limit = Math.min(val.numberLength, that.numberLength);
    255         int i;
    256         for (i = val.getFirstNonzeroDigit(); i < limit; i++) {
    257             resDigits[i] = val.digits[i] & ~that.digits[i];
    258         }
    259         for ( ; i < val.numberLength; i++) {
    260             resDigits[i] = val.digits[i];
    261         }
    262 
    263         return new BigInteger(1, val.numberLength, resDigits);
    264     }
    265 
    266     /** @return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude)*/
    267     static BigInteger andNotPositiveNegative(BigInteger positive, BigInteger negative) {
    268         // PRE: positive > 0 && negative < 0
    269         int iNeg = negative.getFirstNonzeroDigit();
    270         int iPos = positive.getFirstNonzeroDigit();
    271 
    272         if (iNeg >= positive.numberLength) {
    273             return positive;
    274         }
    275 
    276         int resLength = Math.min(positive.numberLength, negative.numberLength);
    277         int[] resDigits = new int[resLength];
    278 
    279         // Always start from first non zero of positive
    280         int i = iPos;
    281         for ( ; i < iNeg; i++) {
    282             // resDigits[i] = positive.digits[i] & -1 (~0)
    283             resDigits[i] = positive.digits[i];
    284         }
    285         if (i == iNeg) {
    286             resDigits[i] = positive.digits[i] & (negative.digits[i] - 1);
    287             i++;
    288         }
    289         for ( ; i < resLength; i++) {
    290             // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]);
    291             resDigits[i] = positive.digits[i] & negative.digits[i];
    292         }
    293 
    294         return new BigInteger(1, resLength, resDigits);
    295     }
    296 
    297     /** @return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude)*/
    298     static BigInteger andNotNegativePositive(BigInteger negative, BigInteger positive) {
    299         // PRE: negative < 0 && positive > 0
    300         int resLength;
    301         int[] resDigits;
    302         int limit;
    303         int digit;
    304 
    305         int iNeg = negative.getFirstNonzeroDigit();
    306         int iPos = positive.getFirstNonzeroDigit();
    307 
    308         if (iNeg >= positive.numberLength) {
    309             return negative;
    310         }
    311 
    312         resLength = Math.max(negative.numberLength, positive.numberLength);
    313         int i = iNeg;
    314         if (iPos > iNeg) {
    315             resDigits = new int[resLength];
    316             limit = Math.min(negative.numberLength, iPos);
    317             for ( ; i < limit; i++) {
    318                 // 1st case:  resDigits [i] = -(-negative.digits[i] & (~0))
    319                 // otherwise: resDigits[i] = ~(~negative.digits[i] & ~0)  ;
    320                 resDigits[i] = negative.digits[i];
    321             }
    322             if (i == negative.numberLength) {
    323                 for (i = iPos; i < positive.numberLength; i++) {
    324                     // resDigits[i] = ~(~positive.digits[i] & -1);
    325                     resDigits[i] = positive.digits[i];
    326                 }
    327             }
    328         } else {
    329             digit = -negative.digits[i] & ~positive.digits[i];
    330             if (digit == 0) {
    331                 limit = Math.min(positive.numberLength, negative.numberLength);
    332                 for (i++; i < limit && (digit = ~(negative.digits[i] | positive.digits[i])) == 0; i++)
    333                     ; // digit = ~negative.digits[i] & ~positive.digits[i]
    334                 if (digit == 0) {
    335                     // the shorter has only the remaining virtual sign bits
    336                     for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
    337                         ; // digit = -1 & ~positive.digits[i]
    338                     for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
    339                         ; // digit = ~negative.digits[i] & ~0
    340                     if (digit == 0) {
    341                         resLength++;
    342                         resDigits = new int[resLength];
    343                         resDigits[resLength - 1] = 1;
    344 
    345                         return new BigInteger(-1, resLength, resDigits);
    346                     }
    347                 }
    348             }
    349                         resDigits = new int[resLength];
    350             resDigits[i] = -digit;
    351             i++;
    352                     }
    353 
    354         limit = Math.min(positive.numberLength, negative.numberLength);
    355         for ( ; i < limit; i++) {
    356             //resDigits[i] = ~(~negative.digits[i] & ~positive.digits[i]);
    357             resDigits[i] = negative.digits[i] | positive.digits[i];
    358         }
    359         // Actually one of the next two cycles will be executed
    360         for ( ; i < negative.numberLength; i++) {
    361             resDigits[i] = negative.digits[i];
    362                 }
    363         for ( ; i < positive.numberLength; i++) {
    364             resDigits[i] = positive.digits[i];
    365         }
    366 
    367         return new BigInteger(-1, resLength, resDigits);
    368     }
    369 
    370     /** @return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude)*/
    371     static BigInteger andNotNegative(BigInteger val, BigInteger that) {
    372         // PRE: val < 0 && that < 0
    373         int iVal = val.getFirstNonzeroDigit();
    374         int iThat = that.getFirstNonzeroDigit();
    375 
    376         if (iVal >= that.numberLength) {
    377             return BigInteger.ZERO;
    378         }
    379 
    380         int resLength = that.numberLength;
    381         int[] resDigits = new int[resLength];
    382         int limit;
    383         int i = iVal;
    384         if (iVal < iThat) {
    385             // resDigits[i] = -val.digits[i] & -1;
    386             resDigits[i] = -val.digits[i];
    387             limit = Math.min(val.numberLength, iThat);
    388             for (i++; i < limit; i++) {
    389                 // resDigits[i] = ~val.digits[i] & -1;
    390                 resDigits[i] = ~val.digits[i];
    391             }
    392             if (i == val.numberLength) {
    393                 for ( ; i < iThat; i++) {
    394                     // resDigits[i] = -1 & -1;
    395                     resDigits[i] = -1;
    396                 }
    397                 // resDigits[i] = -1 & ~-that.digits[i];
    398                 resDigits[i] = that.digits[i] - 1;
    399         } else {
    400                 // resDigits[i] = ~val.digits[i] & ~-that.digits[i];
    401                 resDigits[i] = ~val.digits[i] & (that.digits[i] - 1);
    402             }
    403         } else if (iThat < iVal ) {
    404             // resDigits[i] = -val.digits[i] & ~~that.digits[i];
    405             resDigits[i] = -val.digits[i] & that.digits[i];
    406         } else {
    407             // resDigits[i] = -val.digits[i] & ~-that.digits[i];
    408             resDigits[i] = -val.digits[i] & (that.digits[i] - 1);
    409             }
    410 
    411         limit = Math.min(val.numberLength, that.numberLength);
    412         for (i++; i < limit; i++) {
    413             // resDigits[i] = ~val.digits[i] & ~~that.digits[i];
    414             resDigits[i] = ~val.digits[i] & that.digits[i];
    415         }
    416         for ( ; i < that.numberLength; i++) {
    417             // resDigits[i] = -1 & ~~that.digits[i];
    418             resDigits[i] = that.digits[i];
    419         }
    420 
    421         return new BigInteger(1, resLength, resDigits);
    422     }
    423 
    424     /** @see BigInteger#or(BigInteger) */
    425     static BigInteger or(BigInteger val, BigInteger that) {
    426         if (that.equals(BigInteger.MINUS_ONE) || val.equals(BigInteger.MINUS_ONE)) {
    427             return BigInteger.MINUS_ONE;
    428         }
    429         if (that.sign == 0) {
    430             return val;
    431         }
    432         if (val.sign == 0) {
    433             return that;
    434         }
    435 
    436         if (val.sign > 0) {
    437             if (that.sign > 0) {
    438                 if (val.numberLength > that.numberLength) {
    439                     return orPositive(val, that);
    440                 } else {
    441                     return orPositive(that, val);
    442                 }
    443             } else {
    444                 return orDiffSigns(val, that);
    445             }
    446         } else {
    447             if (that.sign > 0) {
    448                 return orDiffSigns(that, val);
    449             } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
    450                 return orNegative(that, val);
    451             } else {
    452                 return orNegative(val, that);
    453             }
    454         }
    455     }
    456 
    457     /** @return sign = 1, magnitude = longer.magnitude | shorter.magnitude*/
    458     static BigInteger orPositive(BigInteger longer, BigInteger shorter) {
    459         // PRE: longer and shorter are positive;
    460         // PRE: longer has at least as many digits as shorter
    461         int resLength = longer.numberLength;
    462         int[] resDigits = new int[resLength];
    463 
    464         int i;
    465         for (i = 0; i < shorter.numberLength; i++) {
    466             resDigits[i] = longer.digits[i] | shorter.digits[i];
    467         }
    468         for ( ; i < resLength; i++) {
    469             resDigits[i] = longer.digits[i];
    470         }
    471 
    472         return new BigInteger(1, resLength, resDigits);
    473     }
    474 
    475     /** @return sign = -1, magnitude = -(-val.magnitude | -that.magnitude) */
    476     static BigInteger orNegative(BigInteger val, BigInteger that){
    477         // PRE: val and that are negative;
    478         // PRE: val has at least as many trailing zeros digits as that
    479         int iThat = that.getFirstNonzeroDigit();
    480         int iVal = val.getFirstNonzeroDigit();
    481         int i;
    482 
    483         if (iVal >= that.numberLength) {
    484             return that;
    485         }else if (iThat >= val.numberLength) {
    486             return val;
    487         }
    488 
    489         int resLength = Math.min(val.numberLength, that.numberLength);
    490         int[] resDigits = new int[resLength];
    491 
    492         //Looking for the first non-zero digit of the result
    493         if (iThat == iVal) {
    494             resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]);
    495             i = iVal;
    496         } else {
    497             for (i = iThat; i < iVal; i++) {
    498                 resDigits[i] = that.digits[i];
    499             }
    500             resDigits[i] = that.digits[i] & (val.digits[i] - 1);
    501         }
    502 
    503         for (i++; i < resLength; i++) {
    504             resDigits[i] = val.digits[i] & that.digits[i];
    505         }
    506 
    507         return new BigInteger(-1, resLength, resDigits);
    508     }
    509 
    510     /** @return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude) */
    511     static BigInteger orDiffSigns(BigInteger positive, BigInteger negative){
    512         // Jumping over the least significant zero bits
    513         int iNeg = negative.getFirstNonzeroDigit();
    514         int iPos = positive.getFirstNonzeroDigit();
    515         int i;
    516         int limit;
    517 
    518         // Look if the trailing zeros of the positive will "copy" all
    519         // the negative digits
    520         if (iPos >= negative.numberLength) {
    521             return negative;
    522         }
    523         int resLength = negative.numberLength;
    524         int[] resDigits = new int[resLength];
    525 
    526         if (iNeg < iPos ) {
    527             // We know for sure that this will
    528             // be the first non zero digit in the result
    529             for (i = iNeg; i < iPos; i++) {
    530             resDigits[i] = negative.digits[i];
    531             }
    532         } else if (iPos < iNeg) {
    533             i = iPos;
    534             resDigits[i] = -positive.digits[i];
    535             limit = Math.min(positive.numberLength, iNeg);
    536             for (i++; i < limit; i++ ) {
    537                 resDigits[i] = ~positive.digits[i];
    538             }
    539             if (i != positive.numberLength) {
    540                 resDigits[i] = ~(-negative.digits[i] | positive.digits[i]);
    541             } else{
    542                   for (; i<iNeg; i++) {
    543                       resDigits[i] = -1;
    544                   }
    545                   // resDigits[i] = ~(-negative.digits[i] | 0);
    546                   resDigits[i] = negative.digits[i] - 1;
    547             }
    548             i++;
    549         } else {// iNeg == iPos
    550             // Applying two complement to negative and to result
    551             i = iPos;
    552             resDigits[i] = -(-negative.digits[i] | positive.digits[i]);
    553             i++;
    554         }
    555         limit = Math.min(negative.numberLength, positive.numberLength);
    556         for (; i < limit; i++) {
    557             // Applying two complement to negative and to result
    558             // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] );
    559             resDigits[i] = negative.digits[i] & ~positive.digits[i];
    560         }
    561         for ( ; i < negative.numberLength; i++) {
    562             resDigits[i] = negative.digits[i];
    563         }
    564 
    565         return new BigInteger(-1, resLength, resDigits);
    566     }
    567 
    568     /** @see BigInteger#xor(BigInteger) */
    569     static BigInteger xor(BigInteger val, BigInteger that) {
    570         if (that.sign == 0) {
    571             return val;
    572         }
    573         if (val.sign == 0) {
    574             return that;
    575         }
    576         if (that.equals(BigInteger.MINUS_ONE)) {
    577             return val.not();
    578         }
    579         if (val.equals(BigInteger.MINUS_ONE)) {
    580             return that.not();
    581         }
    582 
    583         if (val.sign > 0) {
    584             if (that.sign > 0) {
    585                 if (val.numberLength > that.numberLength) {
    586                     return xorPositive(val, that);
    587                 } else {
    588                     return xorPositive(that, val);
    589                 }
    590             } else {
    591                 return xorDiffSigns(val, that);
    592             }
    593         } else {
    594             if (that.sign > 0) {
    595                 return xorDiffSigns(that, val);
    596             } else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
    597                 return xorNegative(that, val);
    598             } else {
    599                 return xorNegative(val, that);
    600             }
    601         }
    602     }
    603 
    604     /** @return sign = 0, magnitude = longer.magnitude | shorter.magnitude */
    605     static BigInteger xorPositive(BigInteger longer, BigInteger shorter) {
    606         // PRE: longer and shorter are positive;
    607         // PRE: longer has at least as many digits as shorter
    608         int resLength = longer.numberLength;
    609         int[] resDigits = new int[resLength];
    610         int i = Math.min(longer.getFirstNonzeroDigit(), shorter.getFirstNonzeroDigit());
    611         for ( ; i < shorter.numberLength; i++) {
    612             resDigits[i] = longer.digits[i] ^ shorter.digits[i];
    613         }
    614         for ( ; i < longer.numberLength; i++ ){
    615             resDigits[i] = longer.digits[i];
    616         }
    617 
    618         return new BigInteger(1, resLength, resDigits);
    619     }
    620 
    621     /** @return sign = 0, magnitude = -val.magnitude ^ -that.magnitude */
    622     static BigInteger xorNegative(BigInteger val, BigInteger that){
    623         // PRE: val and that are negative
    624         // PRE: val has at least as many trailing zero digits as that
    625         int resLength = Math.max(val.numberLength, that.numberLength);
    626         int[] resDigits = new int[resLength];
    627         int iVal = val.getFirstNonzeroDigit();
    628         int iThat = that.getFirstNonzeroDigit();
    629         int i = iThat;
    630         int limit;
    631 
    632 
    633         if (iVal == iThat) {
    634             resDigits[i] = -val.digits[i] ^ -that.digits[i];
    635         } else {
    636             resDigits[i] = -that.digits[i];
    637             limit = Math.min(that.numberLength, iVal);
    638             for (i++; i < limit; i++) {
    639                 resDigits[i] = ~that.digits[i];
    640             }
    641             // Remains digits in that?
    642             if (i == that.numberLength) {
    643                 //Jumping over the remaining zero to the first non one
    644                 for ( ;i < iVal; i++) {
    645                     //resDigits[i] = 0 ^ -1;
    646                     resDigits[i] = -1;
    647                 }
    648                 //resDigits[i] = -val.digits[i] ^ -1;
    649                 resDigits[i] = val.digits[i] - 1;
    650             } else {
    651                 resDigits[i] = -val.digits[i] ^ ~that.digits[i];
    652             }
    653         }
    654 
    655         limit = Math.min(val.numberLength, that.numberLength);
    656         //Perform ^ between that al val until that ends
    657         for (i++; i < limit; i++) {
    658             //resDigits[i] = ~val.digits[i] ^ ~that.digits[i];
    659             resDigits[i] = val.digits[i] ^ that.digits[i];
    660         }
    661         //Perform ^ between val digits and -1 until val ends
    662         for ( ; i < val.numberLength; i++) {
    663             //resDigits[i] = ~val.digits[i] ^ -1  ;
    664             resDigits[i] = val.digits[i] ;
    665         }
    666         for ( ; i < that.numberLength; i++) {
    667             //resDigits[i] = -1 ^ ~that.digits[i] ;
    668             resDigits[i] = that.digits[i];
    669         }
    670 
    671         return new BigInteger(1, resLength, resDigits);
    672     }
    673 
    674     /** @return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude)*/
    675     static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative){
    676         int resLength = Math.max(negative.numberLength, positive.numberLength);
    677         int[] resDigits;
    678         int iNeg = negative.getFirstNonzeroDigit();
    679         int iPos = positive.getFirstNonzeroDigit();
    680         int i;
    681         int limit;
    682 
    683         //The first
    684         if (iNeg < iPos) {
    685             resDigits = new int[resLength];
    686             i = iNeg;
    687             //resDigits[i] = -(-negative.digits[i]);
    688             resDigits[i] = negative.digits[i];
    689             limit = Math.min(negative.numberLength, iPos);
    690             //Skip the positive digits while they are zeros
    691             for (i++; i < limit; i++) {
    692                 //resDigits[i] = ~(~negative.digits[i]);
    693                 resDigits[i] = negative.digits[i];
    694             }
    695             //if the negative has no more elements, must fill the
    696             //result with the remaining digits of the positive
    697             if (i == negative.numberLength) {
    698                 for ( ; i < positive.numberLength; i++) {
    699                     //resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i])
    700                     resDigits[i] = positive.digits[i];
    701                 }
    702             }
    703         } else if (iPos < iNeg) {
    704             resDigits = new int[resLength];
    705             i = iPos;
    706             //Applying two complement to the first non-zero digit of the result
    707             resDigits[i] = -positive.digits[i];
    708             limit = Math.min(positive.numberLength, iNeg);
    709             for (i++; i < limit; i++) {
    710                 //Continue applying two complement the result
    711                 resDigits[i] = ~positive.digits[i];
    712             }
    713             //When the first non-zero digit of the negative is reached, must apply
    714             //two complement (arithmetic negation) to it, and then operate
    715             if (i == iNeg) {
    716                 resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]);
    717                 i++;
    718             } else {
    719                 //if the positive has no more elements must fill the remaining digits with
    720                 //the negative ones
    721                 for ( ; i < iNeg; i++) {
    722                     // resDigits[i] = ~(0 ^ 0)
    723                     resDigits[i] = -1;
    724                 }
    725                 for ( ; i < negative.numberLength; i++) {
    726                     //resDigits[i] = ~(~negative.digits[i] ^ 0)
    727                     resDigits[i] = negative.digits[i];
    728                 }
    729             }
    730                 } else {
    731             //The first non-zero digit of the positive and negative are the same
    732             i = iNeg;
    733             int digit = positive.digits[i] ^ -negative.digits[i];
    734             if (digit == 0) {
    735                 limit = Math.min(positive.numberLength, negative.numberLength);
    736                 for (i++; i < limit && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++)
    737                     ;
    738                 if (digit == 0) {
    739                     // shorter has only the remaining virtual sign bits
    740                     for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++)
    741                         ;
    742                     for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++)
    743                         ;
    744                     if (digit == 0) {
    745                         resLength = resLength + 1;
    746                         resDigits = new int[resLength];
    747                         resDigits[resLength - 1] = 1;
    748 
    749                         return new BigInteger(-1, resLength, resDigits);
    750                 }
    751             }
    752         }
    753             resDigits = new int[resLength];
    754             resDigits[i] = -digit;
    755             i++;
    756         }
    757 
    758         limit = Math.min(negative.numberLength, positive.numberLength);
    759         for ( ; i < limit; i++) {
    760             resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]);
    761         }
    762         for ( ; i < positive.numberLength; i++) {
    763             // resDigits[i] = ~(positive.digits[i] ^ -1)
    764             resDigits[i] = positive.digits[i];
    765         }
    766         for ( ; i < negative.numberLength; i++) {
    767             // resDigits[i] = ~(0 ^ ~negative.digits[i])
    768             resDigits[i] = negative.digits[i];
    769         }
    770 
    771         return new BigInteger(-1, resLength, resDigits);
    772     }
    773 }
    774