Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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 com.codename1.util;
/**
* The library implements some logical operations over {@code BigInteger}. The
* operations provided are listed below.
*
*
not
*
and
*
andNot
*
or
*
xor
*
*/
class TLogical {
/** Just to denote that this class can't be instantiated. */
private TLogical() {}
/** @see TBigInteger#not() */
static TBigInteger not(TBigInteger val) {
if (val.sign == 0) {
return TBigInteger.MINUS_ONE;
}
if (val.equals(TBigInteger.MINUS_ONE)) {
return TBigInteger.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++) {
// do nothing
}
} else {
for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
// do nothing
}
if (i == val.numberLength) {
resDigits[i] = 1;
return new TBigInteger(-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 TBigInteger(-val.sign, i, resDigits);
}
/** @see TBigInteger#and(TBigInteger) */
static TBigInteger and(TBigInteger val, TBigInteger that) {
if (that.sign == 0 || val.sign == 0) {
return TBigInteger.ZERO;
}
if (that.equals(TBigInteger.MINUS_ONE)){
return val;
}
if (val.equals(TBigInteger.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 TBigInteger andPositive(TBigInteger val, TBigInteger 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 TBigInteger.ZERO;
}
int resDigits[] = new int[resLength];
for ( ; i < resLength; i++) {
resDigits[i] = val.digits[i] & that.digits[i];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = positive.magnitude & magnitude = -negative.magnitude */
static TBigInteger andDiffSigns(TBigInteger positive, TBigInteger 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 TBigInteger.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
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude)*/
static TBigInteger andNegative(TBigInteger longer, TBigInteger 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++) {
// do nothing
}
if (digit == 0) {
// shorter has only the remaining virtual sign bits
for ( ; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++) {
// do nothing
}
if (digit == 0) {
resLength = longer.numberLength + 1;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
TBigInteger result = new TBigInteger(-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];
}
TBigInteger result = new TBigInteger(-1, resLength, resDigits);
return result;
}
/** @see TBigInteger#andNot(TBigInteger) */
static TBigInteger andNot(TBigInteger val, TBigInteger that) {
if (that.sign == 0 ) {
return val;
}
if (val.sign == 0) {
return TBigInteger.ZERO;
}
if (val.equals(TBigInteger.MINUS_ONE)) {
return that.not();
}
if (that.equals(TBigInteger.MINUS_ONE)){
return TBigInteger.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 TBigInteger andNotPositive(TBigInteger val, TBigInteger 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];
}
TBigInteger result = new TBigInteger(1, val.numberLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude)*/
static TBigInteger andNotPositiveNegative(TBigInteger positive, TBigInteger 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];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude)*/
static TBigInteger andNotNegativePositive(TBigInteger negative, TBigInteger 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++) {
// do nothing
}
if (digit == 0) {
// the shorter has only the remaining virtual sign bits
for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++) {
// do nothing
}
for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++) {
// do nothing
}
if (digit == 0) {
resLength++;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
TBigInteger result = new TBigInteger(-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];
}
TBigInteger result = new TBigInteger(-1, resLength, resDigits);
return result;
}
/** @return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude)*/
static TBigInteger andNotNegative(TBigInteger val, TBigInteger that) {
// PRE: val < 0 && that < 0
int iVal = val.getFirstNonzeroDigit();
int iThat = that.getFirstNonzeroDigit();
if (iVal >= that.numberLength) {
return TBigInteger.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];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @see TBigInteger#or(TBigInteger) */
static TBigInteger or(TBigInteger val, TBigInteger that) {
if (that.equals(TBigInteger.MINUS_ONE) || val.equals(TBigInteger.MINUS_ONE)) {
return TBigInteger.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 TBigInteger orPositive(TBigInteger longer, TBigInteger 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];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
return result;
}
/** @return sign = -1, magnitude = -(-val.magnitude | -that.magnitude) */
static TBigInteger orNegative(TBigInteger val, TBigInteger 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];
}
TBigInteger result = new TBigInteger(-1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude) */
static TBigInteger orDiffSigns(TBigInteger positive, TBigInteger 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 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 TBigInteger xorPositive(TBigInteger longer, TBigInteger 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];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = 0, magnitude = -val.magnitude ^ -that.magnitude */
static TBigInteger xorNegative(TBigInteger val, TBigInteger 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];
}
TBigInteger result = new TBigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude)*/
static TBigInteger xorDiffSigns(TBigInteger positive, TBigInteger 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++) {
// do nothing
}
if (digit == 0) {
// shorter has only the remaining virtual sign bits
for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++) {
// do nothing
}
for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++) {
// do nothing
}
if (digit == 0) {
resLength = resLength + 1;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
TBigInteger result = new TBigInteger(-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];
}
TBigInteger result = new TBigInteger(-1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
}