You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MutableFPNumber.java 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.util;
  16. import java.math.BigInteger;
  17. final class MutableFPNumber {
  18. // TODO - what about values between (10<sup>14</sup>-0.5) and (10<sup>14</sup>-0.05) ?
  19. /**
  20. * The minimum value in 'Base-10 normalised form'.<br>
  21. * When {@link #_binaryExponent} == 46 this is the the minimum {@link #_frac} value
  22. * (10<sup>14</sup>-0.05) * 2^17
  23. * <br>
  24. * Values between (10<sup>14</sup>-0.05) and 10<sup>14</sup> will be represented as '1'
  25. * followed by 14 zeros.
  26. * Values less than (10<sup>14</sup>-0.05) will get shifted by one more power of 10
  27. *
  28. * This frac value rounds to '1' followed by fourteen zeros with an incremented decimal exponent
  29. */
  30. private static final BigInteger BI_MIN_BASE = new BigInteger("0B5E620F47FFFE666", 16);
  31. /**
  32. * For 'Base-10 normalised form'<br>
  33. * The maximum {@link #_frac} value when {@link #_binaryExponent} == 49
  34. * (10^15-0.5) * 2^14
  35. */
  36. private static final BigInteger BI_MAX_BASE = new BigInteger("0E35FA9319FFFE000", 16);
  37. /**
  38. * Width of a long
  39. */
  40. private static final int C_64 = 64;
  41. /**
  42. * Minimum precision after discarding whole 32-bit words from the significand
  43. */
  44. private static final int MIN_PRECISION = 72;
  45. private BigInteger _significand;
  46. private int _binaryExponent;
  47. public MutableFPNumber(BigInteger frac, int binaryExponent) {
  48. _significand = frac;
  49. _binaryExponent = binaryExponent;
  50. }
  51. public MutableFPNumber copy() {
  52. return new MutableFPNumber(_significand, _binaryExponent);
  53. }
  54. public void normalise64bit() {
  55. int oldBitLen = _significand.bitLength();
  56. int sc = oldBitLen - C_64;
  57. if (sc == 0) {
  58. return;
  59. }
  60. if (sc < 0) {
  61. throw new IllegalStateException("Not enough precision");
  62. }
  63. _binaryExponent += sc;
  64. if (sc > 32) {
  65. int highShift = (sc-1) & 0xFFFFE0;
  66. _significand = _significand.shiftRight(highShift);
  67. sc -= highShift;
  68. oldBitLen -= highShift;
  69. }
  70. if (sc < 1) {
  71. throw new IllegalStateException();
  72. }
  73. _significand = Rounder.round(_significand, sc);
  74. if (_significand.bitLength() > oldBitLen) {
  75. sc++;
  76. _binaryExponent++;
  77. }
  78. _significand = _significand.shiftRight(sc);
  79. }
  80. public int get64BitNormalisedExponent() {
  81. return _binaryExponent + _significand.bitLength() - C_64;
  82. }
  83. public boolean isBelowMaxRep() {
  84. int sc = _significand.bitLength() - C_64;
  85. return _significand.compareTo(BI_MAX_BASE.shiftLeft(sc)) < 0;
  86. }
  87. public boolean isAboveMinRep() {
  88. int sc = _significand.bitLength() - C_64;
  89. return _significand.compareTo(BI_MIN_BASE.shiftLeft(sc)) > 0;
  90. }
  91. public NormalisedDecimal createNormalisedDecimal(int pow10) {
  92. // missingUnderBits is (0..3)
  93. int missingUnderBits = _binaryExponent-39;
  94. int fracPart = (_significand.intValue() << missingUnderBits) & 0xFFFF80;
  95. long wholePart = _significand.shiftRight(C_64-_binaryExponent-1).longValue();
  96. return new NormalisedDecimal(wholePart, fracPart, pow10);
  97. }
  98. public void multiplyByPowerOfTen(int pow10) {
  99. TenPower tp = TenPower.getInstance(Math.abs(pow10));
  100. if (pow10 < 0) {
  101. mulShift(tp._divisor, tp._divisorShift);
  102. } else {
  103. mulShift(tp._multiplicand, tp._multiplierShift);
  104. }
  105. }
  106. private void mulShift(BigInteger multiplicand, int multiplierShift) {
  107. _significand = _significand.multiply(multiplicand);
  108. _binaryExponent += multiplierShift;
  109. // check for too much precision
  110. int sc = (_significand.bitLength() - MIN_PRECISION) & 0xFFFFFFE0;
  111. // mask makes multiples of 32 which optimises BigInteger.shiftRight
  112. if (sc > 0) {
  113. // no need to round because we have at least 8 bits of extra precision
  114. _significand = _significand.shiftRight(sc);
  115. _binaryExponent += sc;
  116. }
  117. }
  118. private static final class Rounder {
  119. private static final BigInteger[] HALF_BITS;
  120. static {
  121. BigInteger[] bis = new BigInteger[33];
  122. long acc=1;
  123. for (int i = 1; i < bis.length; i++) {
  124. bis[i] = BigInteger.valueOf(acc);
  125. acc <<=1;
  126. }
  127. HALF_BITS = bis;
  128. }
  129. /**
  130. * @param nBits number of bits to shift right
  131. */
  132. public static BigInteger round(BigInteger bi, int nBits) {
  133. if (nBits < 1) {
  134. return bi;
  135. }
  136. return bi.add(HALF_BITS[nBits]);
  137. }
  138. }
  139. /**
  140. * Holds values for quick multiplication and division by 10
  141. */
  142. private static final class TenPower {
  143. private static final BigInteger FIVE = BigInteger.valueOf(5);
  144. private static final TenPower[] _cache = new TenPower[350];
  145. public final BigInteger _multiplicand;
  146. public final BigInteger _divisor;
  147. public final int _divisorShift;
  148. public final int _multiplierShift;
  149. private TenPower(int index) {
  150. BigInteger fivePowIndex = FIVE.pow(index);
  151. int bitsDueToFiveFactors = fivePowIndex.bitLength();
  152. int px = 80 + bitsDueToFiveFactors;
  153. BigInteger fx = BigInteger.ONE.shiftLeft(px).divide(fivePowIndex);
  154. int adj = fx.bitLength() - 80;
  155. _divisor = fx.shiftRight(adj);
  156. bitsDueToFiveFactors -= adj;
  157. _divisorShift = -(bitsDueToFiveFactors+index+80);
  158. int sc = fivePowIndex.bitLength() - 68;
  159. if (sc > 0) {
  160. _multiplierShift = index + sc;
  161. _multiplicand = fivePowIndex.shiftRight(sc);
  162. } else {
  163. _multiplierShift = index;
  164. _multiplicand = fivePowIndex;
  165. }
  166. }
  167. static TenPower getInstance(int index) {
  168. TenPower result = _cache[index];
  169. if (result == null) {
  170. result = new TenPower(index);
  171. _cache[index] = result;
  172. }
  173. return result;
  174. }
  175. }
  176. public ExpandedDouble createExpandedDouble() {
  177. return new ExpandedDouble(_significand, _binaryExponent);
  178. }
  179. }