Bugzilla 47969 - improvements to equals() methods
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@824972 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
af6a4745e2
commit
1833764495
@ -25,8 +25,8 @@ import java.util.Map;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
|
||||
/**
|
||||
* Optimisation - compacts many blank cell references used by a single formula.
|
||||
*
|
||||
* Optimisation - compacts many blank cell references used by a single formula.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class FormulaUsedBlankCellSet {
|
||||
@ -43,6 +43,7 @@ final class FormulaUsedBlankCellSet {
|
||||
return _bookIndex * 17 + _sheetIndex;
|
||||
}
|
||||
public boolean equals(Object obj) {
|
||||
assert obj instanceof BookSheetKey : "these private cache key instances are only compared to themselves";
|
||||
BookSheetKey other = (BookSheetKey) obj;
|
||||
return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ final class PlainCellCache {
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
assert obj instanceof Loc : "these package-private cache key instances are only compared to themselves";
|
||||
Loc other = (Loc) obj;
|
||||
return _bookSheetColumn == other._bookSheetColumn && _rowIndex == other._rowIndex;
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ final class ForkedEvaluationSheet implements EvaluationSheet {
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
assert obj instanceof RowColKey : "these private cache key instances are only compared to themselves";
|
||||
RowColKey other = (RowColKey) obj;
|
||||
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
||||
}
|
||||
|
@ -1,209 +1,201 @@
|
||||
/* ====================================================================
|
||||
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 org.apache.poi.ss.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
final class MutableFPNumber {
|
||||
|
||||
|
||||
// TODO - what about values between (10<sup>14</sup>-0.5) and (10<sup>14</sup>-0.05) ?
|
||||
/**
|
||||
* The minimum value in 'Base-10 normalised form'.<br/>
|
||||
* When {@link #_binaryExponent} == 46 this is the the minimum {@link #_frac} value
|
||||
* (10<sup>14</sup>-0.05) * 2^17
|
||||
* <br/>
|
||||
* Values between (10<sup>14</sup>-0.05) and 10<sup>14</sup> will be represented as '1'
|
||||
* followed by 14 zeros.
|
||||
* Values less than (10<sup>14</sup>-0.05) will get shifted by one more power of 10
|
||||
*
|
||||
* This frac value rounds to '1' followed by fourteen zeros with an incremented decimal exponent
|
||||
*/
|
||||
private static final BigInteger BI_MIN_BASE = new BigInteger("0B5E620F47FFFE666", 16);
|
||||
/**
|
||||
* For 'Base-10 normalised form'<br/>
|
||||
* The maximum {@link #_frac} value when {@link #_binaryExponent} == 49
|
||||
* (10^15-0.5) * 2^14
|
||||
*/
|
||||
private static final BigInteger BI_MAX_BASE = new BigInteger("0E35FA9319FFFE000", 16);
|
||||
|
||||
/**
|
||||
* Width of a long
|
||||
*/
|
||||
private static final int C_64 = 64;
|
||||
|
||||
/**
|
||||
* Minimum precision after discarding whole 32-bit words from the significand
|
||||
*/
|
||||
private static final int MIN_PRECISION = 72;
|
||||
private BigInteger _significand;
|
||||
private int _binaryExponent;
|
||||
public MutableFPNumber(BigInteger frac, int binaryExponent) {
|
||||
_significand = frac;
|
||||
_binaryExponent = binaryExponent;
|
||||
}
|
||||
|
||||
|
||||
public MutableFPNumber copy() {
|
||||
return new MutableFPNumber(_significand, _binaryExponent);
|
||||
}
|
||||
public void normalise64bit() {
|
||||
int oldBitLen = _significand.bitLength();
|
||||
int sc = oldBitLen - C_64;
|
||||
if (sc == 0) {
|
||||
return;
|
||||
}
|
||||
if (sc < 0) {
|
||||
throw new IllegalStateException("Not enough precision");
|
||||
}
|
||||
_binaryExponent += sc;
|
||||
if (sc > 32) {
|
||||
int highShift = (sc-1) & 0xFFFFE0;
|
||||
_significand = _significand.shiftRight(highShift);
|
||||
sc -= highShift;
|
||||
oldBitLen -= highShift;
|
||||
}
|
||||
if (sc < 1) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
_significand = Rounder.round(_significand, sc);
|
||||
if (_significand.bitLength() > oldBitLen) {
|
||||
sc++;
|
||||
_binaryExponent++;
|
||||
}
|
||||
_significand = _significand.shiftRight(sc);
|
||||
}
|
||||
public int get64BitNormalisedExponent() {
|
||||
return _binaryExponent + _significand.bitLength() - C_64;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
MutableFPNumber other = (MutableFPNumber) obj;
|
||||
if (_binaryExponent != other._binaryExponent) {
|
||||
return false;
|
||||
}
|
||||
return _significand.equals(other._significand);
|
||||
}
|
||||
public boolean isBelowMaxRep() {
|
||||
int sc = _significand.bitLength() - C_64;
|
||||
return _significand.compareTo(BI_MAX_BASE.shiftLeft(sc)) < 0;
|
||||
}
|
||||
public boolean isAboveMinRep() {
|
||||
int sc = _significand.bitLength() - C_64;
|
||||
return _significand.compareTo(BI_MIN_BASE.shiftLeft(sc)) > 0;
|
||||
}
|
||||
public NormalisedDecimal createNormalisedDecimal(int pow10) {
|
||||
// missingUnderBits is (0..3)
|
||||
int missingUnderBits = _binaryExponent-39;
|
||||
int fracPart = (_significand.intValue() << missingUnderBits) & 0xFFFF80;
|
||||
long wholePart = _significand.shiftRight(C_64-_binaryExponent-1).longValue();
|
||||
return new NormalisedDecimal(wholePart, fracPart, pow10);
|
||||
}
|
||||
public void multiplyByPowerOfTen(int pow10) {
|
||||
TenPower tp = TenPower.getInstance(Math.abs(pow10));
|
||||
if (pow10 < 0) {
|
||||
mulShift(tp._divisor, tp._divisorShift);
|
||||
} else {
|
||||
mulShift(tp._multiplicand, tp._multiplierShift);
|
||||
}
|
||||
}
|
||||
private void mulShift(BigInteger multiplicand, int multiplierShift) {
|
||||
_significand = _significand.multiply(multiplicand);
|
||||
_binaryExponent += multiplierShift;
|
||||
// check for too much precision
|
||||
int sc = (_significand.bitLength() - MIN_PRECISION) & 0xFFFFFFE0;
|
||||
// mask makes multiples of 32 which optimises BigInteger.shiftRight
|
||||
if (sc > 0) {
|
||||
// no need to round because we have at least 8 bits of extra precision
|
||||
_significand = _significand.shiftRight(sc);
|
||||
_binaryExponent += sc;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Rounder {
|
||||
private static final BigInteger[] HALF_BITS;
|
||||
|
||||
static {
|
||||
BigInteger[] bis = new BigInteger[33];
|
||||
long acc=1;
|
||||
for (int i = 1; i < bis.length; i++) {
|
||||
bis[i] = BigInteger.valueOf(acc);
|
||||
acc <<=1;
|
||||
}
|
||||
HALF_BITS = bis;
|
||||
}
|
||||
/**
|
||||
* @param nBits number of bits to shift right
|
||||
*/
|
||||
public static BigInteger round(BigInteger bi, int nBits) {
|
||||
if (nBits < 1) {
|
||||
return bi;
|
||||
}
|
||||
return bi.add(HALF_BITS[nBits]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds values for quick multiplication and division by 10
|
||||
*/
|
||||
private static final class TenPower {
|
||||
private static final BigInteger FIVE = new BigInteger("5");
|
||||
private static final TenPower[] _cache = new TenPower[350];
|
||||
|
||||
public final BigInteger _multiplicand;
|
||||
public final BigInteger _divisor;
|
||||
public final int _divisorShift;
|
||||
public final int _multiplierShift;
|
||||
|
||||
private TenPower(int index) {
|
||||
BigInteger fivePowIndex = FIVE.pow(index);
|
||||
|
||||
int bitsDueToFiveFactors = fivePowIndex.bitLength();
|
||||
int px = 80 + bitsDueToFiveFactors;
|
||||
BigInteger fx = BigInteger.ONE.shiftLeft(px).divide(fivePowIndex);
|
||||
int adj = fx.bitLength() - 80;
|
||||
_divisor = fx.shiftRight(adj);
|
||||
bitsDueToFiveFactors -= adj;
|
||||
|
||||
_divisorShift = -(bitsDueToFiveFactors+index+80);
|
||||
int sc = fivePowIndex.bitLength() - 68;
|
||||
if (sc > 0) {
|
||||
_multiplierShift = index + sc;
|
||||
_multiplicand = fivePowIndex.shiftRight(sc);
|
||||
} else {
|
||||
_multiplierShift = index;
|
||||
_multiplicand = fivePowIndex;
|
||||
}
|
||||
}
|
||||
|
||||
static TenPower getInstance(int index) {
|
||||
TenPower result = _cache[index];
|
||||
if (result == null) {
|
||||
result = new TenPower(index);
|
||||
_cache[index] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public ExpandedDouble createExpandedDouble() {
|
||||
return new ExpandedDouble(_significand, _binaryExponent);
|
||||
}
|
||||
}
|
||||
/* ====================================================================
|
||||
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 org.apache.poi.ss.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
final class MutableFPNumber {
|
||||
|
||||
|
||||
// TODO - what about values between (10<sup>14</sup>-0.5) and (10<sup>14</sup>-0.05) ?
|
||||
/**
|
||||
* The minimum value in 'Base-10 normalised form'.<br/>
|
||||
* When {@link #_binaryExponent} == 46 this is the the minimum {@link #_frac} value
|
||||
* (10<sup>14</sup>-0.05) * 2^17
|
||||
* <br/>
|
||||
* Values between (10<sup>14</sup>-0.05) and 10<sup>14</sup> will be represented as '1'
|
||||
* followed by 14 zeros.
|
||||
* Values less than (10<sup>14</sup>-0.05) will get shifted by one more power of 10
|
||||
*
|
||||
* This frac value rounds to '1' followed by fourteen zeros with an incremented decimal exponent
|
||||
*/
|
||||
private static final BigInteger BI_MIN_BASE = new BigInteger("0B5E620F47FFFE666", 16);
|
||||
/**
|
||||
* For 'Base-10 normalised form'<br/>
|
||||
* The maximum {@link #_frac} value when {@link #_binaryExponent} == 49
|
||||
* (10^15-0.5) * 2^14
|
||||
*/
|
||||
private static final BigInteger BI_MAX_BASE = new BigInteger("0E35FA9319FFFE000", 16);
|
||||
|
||||
/**
|
||||
* Width of a long
|
||||
*/
|
||||
private static final int C_64 = 64;
|
||||
|
||||
/**
|
||||
* Minimum precision after discarding whole 32-bit words from the significand
|
||||
*/
|
||||
private static final int MIN_PRECISION = 72;
|
||||
private BigInteger _significand;
|
||||
private int _binaryExponent;
|
||||
public MutableFPNumber(BigInteger frac, int binaryExponent) {
|
||||
_significand = frac;
|
||||
_binaryExponent = binaryExponent;
|
||||
}
|
||||
|
||||
|
||||
public MutableFPNumber copy() {
|
||||
return new MutableFPNumber(_significand, _binaryExponent);
|
||||
}
|
||||
public void normalise64bit() {
|
||||
int oldBitLen = _significand.bitLength();
|
||||
int sc = oldBitLen - C_64;
|
||||
if (sc == 0) {
|
||||
return;
|
||||
}
|
||||
if (sc < 0) {
|
||||
throw new IllegalStateException("Not enough precision");
|
||||
}
|
||||
_binaryExponent += sc;
|
||||
if (sc > 32) {
|
||||
int highShift = (sc-1) & 0xFFFFE0;
|
||||
_significand = _significand.shiftRight(highShift);
|
||||
sc -= highShift;
|
||||
oldBitLen -= highShift;
|
||||
}
|
||||
if (sc < 1) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
_significand = Rounder.round(_significand, sc);
|
||||
if (_significand.bitLength() > oldBitLen) {
|
||||
sc++;
|
||||
_binaryExponent++;
|
||||
}
|
||||
_significand = _significand.shiftRight(sc);
|
||||
}
|
||||
public int get64BitNormalisedExponent() {
|
||||
return _binaryExponent + _significand.bitLength() - C_64;
|
||||
|
||||
}
|
||||
|
||||
public boolean isBelowMaxRep() {
|
||||
int sc = _significand.bitLength() - C_64;
|
||||
return _significand.compareTo(BI_MAX_BASE.shiftLeft(sc)) < 0;
|
||||
}
|
||||
public boolean isAboveMinRep() {
|
||||
int sc = _significand.bitLength() - C_64;
|
||||
return _significand.compareTo(BI_MIN_BASE.shiftLeft(sc)) > 0;
|
||||
}
|
||||
public NormalisedDecimal createNormalisedDecimal(int pow10) {
|
||||
// missingUnderBits is (0..3)
|
||||
int missingUnderBits = _binaryExponent-39;
|
||||
int fracPart = (_significand.intValue() << missingUnderBits) & 0xFFFF80;
|
||||
long wholePart = _significand.shiftRight(C_64-_binaryExponent-1).longValue();
|
||||
return new NormalisedDecimal(wholePart, fracPart, pow10);
|
||||
}
|
||||
public void multiplyByPowerOfTen(int pow10) {
|
||||
TenPower tp = TenPower.getInstance(Math.abs(pow10));
|
||||
if (pow10 < 0) {
|
||||
mulShift(tp._divisor, tp._divisorShift);
|
||||
} else {
|
||||
mulShift(tp._multiplicand, tp._multiplierShift);
|
||||
}
|
||||
}
|
||||
private void mulShift(BigInteger multiplicand, int multiplierShift) {
|
||||
_significand = _significand.multiply(multiplicand);
|
||||
_binaryExponent += multiplierShift;
|
||||
// check for too much precision
|
||||
int sc = (_significand.bitLength() - MIN_PRECISION) & 0xFFFFFFE0;
|
||||
// mask makes multiples of 32 which optimises BigInteger.shiftRight
|
||||
if (sc > 0) {
|
||||
// no need to round because we have at least 8 bits of extra precision
|
||||
_significand = _significand.shiftRight(sc);
|
||||
_binaryExponent += sc;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Rounder {
|
||||
private static final BigInteger[] HALF_BITS;
|
||||
|
||||
static {
|
||||
BigInteger[] bis = new BigInteger[33];
|
||||
long acc=1;
|
||||
for (int i = 1; i < bis.length; i++) {
|
||||
bis[i] = BigInteger.valueOf(acc);
|
||||
acc <<=1;
|
||||
}
|
||||
HALF_BITS = bis;
|
||||
}
|
||||
/**
|
||||
* @param nBits number of bits to shift right
|
||||
*/
|
||||
public static BigInteger round(BigInteger bi, int nBits) {
|
||||
if (nBits < 1) {
|
||||
return bi;
|
||||
}
|
||||
return bi.add(HALF_BITS[nBits]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds values for quick multiplication and division by 10
|
||||
*/
|
||||
private static final class TenPower {
|
||||
private static final BigInteger FIVE = new BigInteger("5");
|
||||
private static final TenPower[] _cache = new TenPower[350];
|
||||
|
||||
public final BigInteger _multiplicand;
|
||||
public final BigInteger _divisor;
|
||||
public final int _divisorShift;
|
||||
public final int _multiplierShift;
|
||||
|
||||
private TenPower(int index) {
|
||||
BigInteger fivePowIndex = FIVE.pow(index);
|
||||
|
||||
int bitsDueToFiveFactors = fivePowIndex.bitLength();
|
||||
int px = 80 + bitsDueToFiveFactors;
|
||||
BigInteger fx = BigInteger.ONE.shiftLeft(px).divide(fivePowIndex);
|
||||
int adj = fx.bitLength() - 80;
|
||||
_divisor = fx.shiftRight(adj);
|
||||
bitsDueToFiveFactors -= adj;
|
||||
|
||||
_divisorShift = -(bitsDueToFiveFactors+index+80);
|
||||
int sc = fivePowIndex.bitLength() - 68;
|
||||
if (sc > 0) {
|
||||
_multiplierShift = index + sc;
|
||||
_multiplicand = fivePowIndex.shiftRight(sc);
|
||||
} else {
|
||||
_multiplierShift = index;
|
||||
_multiplicand = fivePowIndex;
|
||||
}
|
||||
}
|
||||
|
||||
static TenPower getInstance(int index) {
|
||||
TenPower result = _cache[index];
|
||||
if (result == null) {
|
||||
result = new TenPower(index);
|
||||
_cache[index] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public ExpandedDouble createExpandedDouble() {
|
||||
return new ExpandedDouble(_significand, _binaryExponent);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user