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;
/**
* Static library that provides all the bit level operations for
* {@link TBigInteger}. The operations are:
*
*
Left Shifting
*
Right Shifting
*
Bit clearing
*
Bit setting
*
Bit counting
*
Bit testing
*
Getting of the lowest bit set
*
* All operations are provided in immutable way, and some in both mutable and
* immutable.
*/
class TBitLevel {
/** Just to denote that this class can't be instantiated. */
private TBitLevel() {
}
/** @see TBigInteger#bitLength() */
static int bitLength(TBigInteger val) {
if (val.sign == 0) {
return 0;
}
int bLength = (val.numberLength << 5);
int highDigit = val.digits[val.numberLength - 1];
if (val.sign < 0) {
int i = val.getFirstNonzeroDigit();
// We reduce the problem to the positive case.
if (i == val.numberLength - 1) {
highDigit--;
}
}
// Subtracting all sign bits
bLength -= numberOfLeadingZeros(highDigit);
return bLength;
}
static int numberOfLeadingZeros(int i) {
if (i == 0) {
return 32;
}
int n = 0;
if (i >>> 16 != 0) {
i >>>= 16;
n |= 16;
}
if (i >>> 8 != 0) {
i >>>= 8;
n |= 8;
}
if (i >>> 4 != 0) {
i >>>= 4;
n |= 4;
}
if (i >>> 2 != 0) {
i >>>= 2;
n |= 2;
}
if (i >>> 1 != 0) {
i >>>= 1;
n |= 1;
}
return 32 - n - 1;
}
/** @see TBigInteger#bitCount() */
static int bitCount(TBigInteger val) {
int bCount = 0;
if (val.sign == 0) {
return 0;
}
int i = val.getFirstNonzeroDigit();
if (val.sign > 0) {
for (; i < val.numberLength; i++) {
bCount += TBigDecimal.bitCount(val.digits[i]);
}
} else {// (sign < 0)
// this digit absorbs the carry
bCount += TBigDecimal.bitCount(-val.digits[i]);
for (i++; i < val.numberLength; i++) {
bCount += TBigDecimal.bitCount(~val.digits[i]);
}
// We take the complement sum:
bCount = (val.numberLength << 5) - bCount;
}
return bCount;
}
/**
* Performs a fast bit testing for positive numbers. The bit to to be tested
* must be in the range {@code [0, val.bitLength()-1]}
*/
static boolean testBit(TBigInteger val, int n) {
// PRE: 0 <= n < val.bitLength()
return ((val.digits[n >> 5] & (1 << (n & 31))) != 0);
}
/**
* Check if there are 1s in the lowest bits of this BigInteger
*
* @param numberOfBits
* the number of the lowest bits to check
* @return false if all bits are 0s, true otherwise
*/
static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) {
int intCount = numberOfBits >> 5;
int bitCount = numberOfBits & 31;
int i;
for (i = 0; (i < intCount) && (digits[i] == 0); i++) {
// do nothing
}
return ((i != intCount) || (digits[i] << (32 - bitCount) != 0));
}
/** @see TBigInteger#shiftLeft(int) */
static TBigInteger shiftLeft(TBigInteger source, int count) {
int intCount = count >> 5;
count &= 31; // %= 32
int resLength = source.numberLength + intCount + ((count == 0) ? 0 : 1);
int resDigits[] = new int[resLength];
shiftLeft(resDigits, source.digits, intCount, count);
TBigInteger result = new TBigInteger(source.sign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Performs {@code val <<= count}.
*/
// val should have enough place (and one digit more)
static void inplaceShiftLeft(TBigInteger val, int count) {
int intCount = count >> 5; // count of integers
val.numberLength += intCount +
(TBigDecimal.numberOfLeadingZeros(val.digits[val.numberLength - 1]) - (count & 31) >= 0 ? 0 : 1);
shiftLeft(val.digits, val.digits, intCount, count & 31);
val.cutOffLeadingZeroes();
val.unCache();
}
/**
* Abstractly shifts left an array of integers in little endian (i.e. shift
* it right). Total shift distance in bits is intCount * 32 + count
*
* @param result
* the destination array
* @param source
* the source array
* @param intCount
* the shift distance in integers
* @param count
* an additional shift distance in bits
*/
static void shiftLeft(int result[], int source[], int intCount, int count) {
if (count == 0) {
System.arraycopy(source, 0, result, intCount, result.length - intCount);
} else {
int rightShiftCount = 32 - count;
result[result.length - 1] = 0;
for (int i = result.length - 1; i > intCount; i--) {
result[i] |= source[i - intCount - 1] >>> rightShiftCount;
result[i - 1] = source[i - intCount - 1] << count;
}
}
for (int i = 0; i < intCount; i++) {
result[i] = 0;
}
}
/**
* Shifts the source digits left one bit, creating a value whose magnitude
* is doubled.
*
* @param result
* an array of digits that will hold the computed result when
* this method returns. The size of this array is
* {@code srcLen + 1}, and the format is the same as
* {@link TBigInteger#digits}.
* @param source
* the array of digits to shift left, in the same format as
* {@link TBigInteger#digits}.
* @param srcLen
* the length of {@code source}; may be less than
* {@code source.length}
*/
static void shiftLeftOneBit(int result[], int source[], int srcLen) {
int carry = 0;
for (int i = 0; i < srcLen; i++) {
int val = source[i];
result[i] = (val << 1) | carry;
carry = val >>> 31;
}
if (carry != 0) {
result[srcLen] = carry;
}
}
static TBigInteger shiftLeftOneBit(TBigInteger source) {
int srcLen = source.numberLength;
int resLen = srcLen + 1;
int resDigits[] = new int[resLen];
shiftLeftOneBit(resDigits, source.digits, srcLen);
TBigInteger result = new TBigInteger(source.sign, resLen, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/** @see TBigInteger#shiftRight(int) */
static TBigInteger shiftRight(TBigInteger source, int count) {
int intCount = count >> 5; // count of integers
count &= 31; // count of remaining bits
if (intCount >= source.numberLength) {
return ((source.sign < 0) ? TBigInteger.MINUS_ONE : TBigInteger.ZERO);
}
int i;
int resLength = source.numberLength - intCount;
int resDigits[] = new int[resLength + 1];
shiftRight(resDigits, resLength, source.digits, intCount, count);
if (source.sign < 0) {
// Checking if the dropped bits are zeros (the remainder equals to
// 0)
for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) {
// do nothing
}
// If the remainder is not zero, add 1 to the result
if ((i < intCount) || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) {
resDigits[i] = 0;
}
if (i == resLength) {
resLength++;
}
resDigits[i]++;
}
}
TBigInteger result = new TBigInteger(source.sign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Performs {@code val >>= count} where {@code val} is a positive number.
*/
static void inplaceShiftRight(TBigInteger val, int count) {
int sign = val.signum();
if (count == 0 || val.signum() == 0)
return;
int intCount = count >> 5; // count of integers
val.numberLength -= intCount;
if (!shiftRight(val.digits, val.numberLength, val.digits, intCount, count & 31) && sign < 0) {
// remainder not zero: add one to the result
int i;
for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
val.digits[i] = 0;
}
if (i == val.numberLength) {
val.numberLength++;
}
val.digits[i]++;
}
val.cutOffLeadingZeroes();
val.unCache();
}
/**
* Shifts right an array of integers. Total shift distance in bits is
* intCount * 32 + count.
*
* @param result
* the destination array
* @param resultLen
* the destination array's length
* @param source
* the source array
* @param intCount
* the number of elements to be shifted
* @param count
* the number of bits to be shifted
* @return dropped bit's are all zero (i.e. remaider is zero)
*/
static boolean shiftRight(int result[], int resultLen, int source[], int intCount, int count) {
int i;
boolean allZero = true;
for (i = 0; i < intCount; i++) {
allZero &= source[i] == 0;
}
if (count == 0) {
System.arraycopy(source, intCount, result, 0, resultLen);
i = resultLen;
} else {
int leftShiftCount = 32 - count;
allZero &= (source[i] << leftShiftCount) == 0;
for (i = 0; i < resultLen - 1; i++) {
result[i] = (source[i + intCount] >>> count) | (source[i + intCount + 1] << leftShiftCount);
}
result[i] = (source[i + intCount] >>> count);
i++;
}
return allZero;
}
/**
* Performs a flipBit on the BigInteger, returning a BigInteger with the the
* specified bit flipped.
*
* @param intCount
* : the index of the element of the digits array where the
* operation will be performed
* @param bitNumber
* : the bit's position in the intCount element
*/
static TBigInteger flipBit(TBigInteger val, int n) {
int resSign = (val.sign == 0) ? 1 : val.sign;
int intCount = n >> 5;
int bitN = n & 31;
int resLength = Math.max(intCount + 1, val.numberLength) + 1;
int resDigits[] = new int[resLength];
int i;
int bitNumber = 1 << bitN;
System.arraycopy(val.digits, 0, resDigits, 0, val.numberLength);
if (val.sign < 0) {
if (intCount >= val.numberLength) {
resDigits[intCount] = bitNumber;
} else {
// val.sign<0 y intCount < val.numberLength
int firstNonZeroDigit = val.getFirstNonzeroDigit();
if (intCount > firstNonZeroDigit) {
resDigits[intCount] ^= bitNumber;
} else if (intCount < firstNonZeroDigit) {
resDigits[intCount] = -bitNumber;
for (i = intCount + 1; i < firstNonZeroDigit; i++) {
resDigits[i] = -1;
}
resDigits[i] = resDigits[i]--;
} else {
i = intCount;
resDigits[i] = -((-resDigits[intCount]) ^ bitNumber);
if (resDigits[i] == 0) {
for (i++; resDigits[i] == -1; i++) {
resDigits[i] = 0;
}
resDigits[i]++;
}
}
}
} else {// case where val is positive
resDigits[intCount] ^= bitNumber;
}
TBigInteger result = new TBigInteger(resSign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
}