-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-\r
-package org.apache.poi.ss.util;\r
-\r
-import java.math.BigInteger;\r
-\r
-final class MutableFPNumber {\r
-\r
-\r
- // TODO - what about values between (10<sup>14</sup>-0.5) and (10<sup>14</sup>-0.05) ?\r
- /**\r
- * The minimum value in 'Base-10 normalised form'.<br/>\r
- * When {@link #_binaryExponent} == 46 this is the the minimum {@link #_frac} value\r
- * (10<sup>14</sup>-0.05) * 2^17\r
- * <br/>\r
- * Values between (10<sup>14</sup>-0.05) and 10<sup>14</sup> will be represented as '1'\r
- * followed by 14 zeros.\r
- * Values less than (10<sup>14</sup>-0.05) will get shifted by one more power of 10\r
- *\r
- * This frac value rounds to '1' followed by fourteen zeros with an incremented decimal exponent\r
- */\r
- private static final BigInteger BI_MIN_BASE = new BigInteger("0B5E620F47FFFE666", 16);\r
- /**\r
- * For 'Base-10 normalised form'<br/>\r
- * The maximum {@link #_frac} value when {@link #_binaryExponent} == 49\r
- * (10^15-0.5) * 2^14\r
- */\r
- private static final BigInteger BI_MAX_BASE = new BigInteger("0E35FA9319FFFE000", 16);\r
-\r
- /**\r
- * Width of a long\r
- */\r
- private static final int C_64 = 64;\r
-\r
- /**\r
- * Minimum precision after discarding whole 32-bit words from the significand\r
- */\r
- private static final int MIN_PRECISION = 72;\r
- private BigInteger _significand;\r
- private int _binaryExponent;\r
- public MutableFPNumber(BigInteger frac, int binaryExponent) {\r
- _significand = frac;\r
- _binaryExponent = binaryExponent;\r
- }\r
-\r
-\r
- public MutableFPNumber copy() {\r
- return new MutableFPNumber(_significand, _binaryExponent);\r
- }\r
- public void normalise64bit() {\r
- int oldBitLen = _significand.bitLength();\r
- int sc = oldBitLen - C_64;\r
- if (sc == 0) {\r
- return;\r
- }\r
- if (sc < 0) {\r
- throw new IllegalStateException("Not enough precision");\r
- }\r
- _binaryExponent += sc;\r
- if (sc > 32) {\r
- int highShift = (sc-1) & 0xFFFFE0;\r
- _significand = _significand.shiftRight(highShift);\r
- sc -= highShift;\r
- oldBitLen -= highShift;\r
- }\r
- if (sc < 1) {\r
- throw new IllegalStateException();\r
- }\r
- _significand = Rounder.round(_significand, sc);\r
- if (_significand.bitLength() > oldBitLen) {\r
- sc++;\r
- _binaryExponent++;\r
- }\r
- _significand = _significand.shiftRight(sc);\r
- }\r
- public int get64BitNormalisedExponent() {\r
- return _binaryExponent + _significand.bitLength() - C_64;\r
-\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- MutableFPNumber other = (MutableFPNumber) obj;\r
- if (_binaryExponent != other._binaryExponent) {\r
- return false;\r
- }\r
- return _significand.equals(other._significand);\r
- }\r
- public boolean isBelowMaxRep() {\r
- int sc = _significand.bitLength() - C_64;\r
- return _significand.compareTo(BI_MAX_BASE.shiftLeft(sc)) < 0;\r
- }\r
- public boolean isAboveMinRep() {\r
- int sc = _significand.bitLength() - C_64;\r
- return _significand.compareTo(BI_MIN_BASE.shiftLeft(sc)) > 0;\r
- }\r
- public NormalisedDecimal createNormalisedDecimal(int pow10) {\r
- // missingUnderBits is (0..3)\r
- int missingUnderBits = _binaryExponent-39;\r
- int fracPart = (_significand.intValue() << missingUnderBits) & 0xFFFF80;\r
- long wholePart = _significand.shiftRight(C_64-_binaryExponent-1).longValue();\r
- return new NormalisedDecimal(wholePart, fracPart, pow10);\r
- }\r
- public void multiplyByPowerOfTen(int pow10) {\r
- TenPower tp = TenPower.getInstance(Math.abs(pow10));\r
- if (pow10 < 0) {\r
- mulShift(tp._divisor, tp._divisorShift);\r
- } else {\r
- mulShift(tp._multiplicand, tp._multiplierShift);\r
- }\r
- }\r
- private void mulShift(BigInteger multiplicand, int multiplierShift) {\r
- _significand = _significand.multiply(multiplicand);\r
- _binaryExponent += multiplierShift;\r
- // check for too much precision\r
- int sc = (_significand.bitLength() - MIN_PRECISION) & 0xFFFFFFE0;\r
- // mask makes multiples of 32 which optimises BigInteger.shiftRight\r
- if (sc > 0) {\r
- // no need to round because we have at least 8 bits of extra precision\r
- _significand = _significand.shiftRight(sc);\r
- _binaryExponent += sc;\r
- }\r
- }\r
-\r
- private static final class Rounder {\r
- private static final BigInteger[] HALF_BITS;\r
-\r
- static {\r
- BigInteger[] bis = new BigInteger[33];\r
- long acc=1;\r
- for (int i = 1; i < bis.length; i++) {\r
- bis[i] = BigInteger.valueOf(acc);\r
- acc <<=1;\r
- }\r
- HALF_BITS = bis;\r
- }\r
- /**\r
- * @param nBits number of bits to shift right\r
- */\r
- public static BigInteger round(BigInteger bi, int nBits) {\r
- if (nBits < 1) {\r
- return bi;\r
- }\r
- return bi.add(HALF_BITS[nBits]);\r
- }\r
- }\r
-\r
- /**\r
- * Holds values for quick multiplication and division by 10\r
- */\r
- private static final class TenPower {\r
- private static final BigInteger FIVE = new BigInteger("5");\r
- private static final TenPower[] _cache = new TenPower[350];\r
-\r
- public final BigInteger _multiplicand;\r
- public final BigInteger _divisor;\r
- public final int _divisorShift;\r
- public final int _multiplierShift;\r
-\r
- private TenPower(int index) {\r
- BigInteger fivePowIndex = FIVE.pow(index);\r
-\r
- int bitsDueToFiveFactors = fivePowIndex.bitLength();\r
- int px = 80 + bitsDueToFiveFactors;\r
- BigInteger fx = BigInteger.ONE.shiftLeft(px).divide(fivePowIndex);\r
- int adj = fx.bitLength() - 80;\r
- _divisor = fx.shiftRight(adj);\r
- bitsDueToFiveFactors -= adj;\r
-\r
- _divisorShift = -(bitsDueToFiveFactors+index+80);\r
- int sc = fivePowIndex.bitLength() - 68;\r
- if (sc > 0) {\r
- _multiplierShift = index + sc;\r
- _multiplicand = fivePowIndex.shiftRight(sc);\r
- } else {\r
- _multiplierShift = index;\r
- _multiplicand = fivePowIndex;\r
- }\r
- }\r
-\r
- static TenPower getInstance(int index) {\r
- TenPower result = _cache[index];\r
- if (result == null) {\r
- result = new TenPower(index);\r
- _cache[index] = result;\r
- }\r
- return result;\r
- }\r
- }\r
-\r
- public ExpandedDouble createExpandedDouble() {\r
- return new ExpandedDouble(_significand, _binaryExponent);\r
- }\r
-}\r
+/* ====================================================================
+ 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);
+ }
+}