001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.math3.dfp; 019 020/** Subclass of {@link Dfp} which hides the radix-10000 artifacts of the superclass. 021 * This should give outward appearances of being a decimal number with DIGITS*4-3 022 * decimal digits. This class can be subclassed to appear to be an arbitrary number 023 * of decimal digits less than DIGITS*4-3. 024 * @since 2.2 025 */ 026public class DfpDec extends Dfp { 027 028 /** Makes an instance with a value of zero. 029 * @param factory factory linked to this instance 030 */ 031 protected DfpDec(final DfpField factory) { 032 super(factory); 033 } 034 035 /** Create an instance from a byte value. 036 * @param factory factory linked to this instance 037 * @param x value to convert to an instance 038 */ 039 protected DfpDec(final DfpField factory, byte x) { 040 super(factory, x); 041 } 042 043 /** Create an instance from an int value. 044 * @param factory factory linked to this instance 045 * @param x value to convert to an instance 046 */ 047 protected DfpDec(final DfpField factory, int x) { 048 super(factory, x); 049 } 050 051 /** Create an instance from a long value. 052 * @param factory factory linked to this instance 053 * @param x value to convert to an instance 054 */ 055 protected DfpDec(final DfpField factory, long x) { 056 super(factory, x); 057 } 058 059 /** Create an instance from a double value. 060 * @param factory factory linked to this instance 061 * @param x value to convert to an instance 062 */ 063 protected DfpDec(final DfpField factory, double x) { 064 super(factory, x); 065 round(0); 066 } 067 068 /** Copy constructor. 069 * @param d instance to copy 070 */ 071 public DfpDec(final Dfp d) { 072 super(d); 073 round(0); 074 } 075 076 /** Create an instance from a String representation. 077 * @param factory factory linked to this instance 078 * @param s string representation of the instance 079 */ 080 protected DfpDec(final DfpField factory, final String s) { 081 super(factory, s); 082 round(0); 083 } 084 085 /** Creates an instance with a non-finite value. 086 * @param factory factory linked to this instance 087 * @param sign sign of the Dfp to create 088 * @param nans code of the value, must be one of {@link #INFINITE}, 089 * {@link #SNAN}, {@link #QNAN} 090 */ 091 protected DfpDec(final DfpField factory, final byte sign, final byte nans) { 092 super(factory, sign, nans); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public Dfp newInstance() { 098 return new DfpDec(getField()); 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public Dfp newInstance(final byte x) { 104 return new DfpDec(getField(), x); 105 } 106 107 /** {@inheritDoc} */ 108 @Override 109 public Dfp newInstance(final int x) { 110 return new DfpDec(getField(), x); 111 } 112 113 /** {@inheritDoc} */ 114 @Override 115 public Dfp newInstance(final long x) { 116 return new DfpDec(getField(), x); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public Dfp newInstance(final double x) { 122 return new DfpDec(getField(), x); 123 } 124 125 /** {@inheritDoc} */ 126 @Override 127 public Dfp newInstance(final Dfp d) { 128 129 // make sure we don't mix number with different precision 130 if (getField().getRadixDigits() != d.getField().getRadixDigits()) { 131 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 132 final Dfp result = newInstance(getZero()); 133 result.nans = QNAN; 134 return dotrap(DfpField.FLAG_INVALID, "newInstance", d, result); 135 } 136 137 return new DfpDec(d); 138 139 } 140 141 /** {@inheritDoc} */ 142 @Override 143 public Dfp newInstance(final String s) { 144 return new DfpDec(getField(), s); 145 } 146 147 /** {@inheritDoc} */ 148 @Override 149 public Dfp newInstance(final byte sign, final byte nans) { 150 return new DfpDec(getField(), sign, nans); 151 } 152 153 /** Get the number of decimal digits this class is going to represent. 154 * Default implementation returns {@link #getRadixDigits()}*4-3. Subclasses can 155 * override this to return something less. 156 * @return number of decimal digits this class is going to represent 157 */ 158 protected int getDecimalDigits() { 159 return getRadixDigits() * 4 - 3; 160 } 161 162 /** {@inheritDoc} */ 163 @Override 164 protected int round(int in) { 165 166 int msb = mant[mant.length-1]; 167 if (msb == 0) { 168 // special case -- this == zero 169 return 0; 170 } 171 172 int cmaxdigits = mant.length * 4; 173 int lsbthreshold = 1000; 174 while (lsbthreshold > msb) { 175 lsbthreshold /= 10; 176 cmaxdigits --; 177 } 178 179 180 final int digits = getDecimalDigits(); 181 final int lsbshift = cmaxdigits - digits; 182 final int lsd = lsbshift / 4; 183 184 lsbthreshold = 1; 185 for (int i = 0; i < lsbshift % 4; i++) { 186 lsbthreshold *= 10; 187 } 188 189 final int lsb = mant[lsd]; 190 191 if (lsbthreshold <= 1 && digits == 4 * mant.length - 3) { 192 return super.round(in); 193 } 194 195 int discarded = in; // not looking at this after this point 196 final int n; 197 if (lsbthreshold == 1) { 198 // look to the next digit for rounding 199 n = (mant[lsd-1] / 1000) % 10; 200 mant[lsd-1] %= 1000; 201 discarded |= mant[lsd-1]; 202 } else { 203 n = (lsb * 10 / lsbthreshold) % 10; 204 discarded |= lsb % (lsbthreshold/10); 205 } 206 207 for (int i = 0; i < lsd; i++) { 208 discarded |= mant[i]; // need to know if there are any discarded bits 209 mant[i] = 0; 210 } 211 212 mant[lsd] = lsb / lsbthreshold * lsbthreshold; 213 214 final boolean inc; 215 switch (getField().getRoundingMode()) { 216 case ROUND_DOWN: 217 inc = false; 218 break; 219 220 case ROUND_UP: 221 inc = (n != 0) || (discarded != 0); // round up if n!=0 222 break; 223 224 case ROUND_HALF_UP: 225 inc = n >= 5; // round half up 226 break; 227 228 case ROUND_HALF_DOWN: 229 inc = n > 5; // round half down 230 break; 231 232 case ROUND_HALF_EVEN: 233 inc = (n > 5) || 234 (n == 5 && discarded != 0) || 235 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1); // round half-even 236 break; 237 238 case ROUND_HALF_ODD: 239 inc = (n > 5) || 240 (n == 5 && discarded != 0) || 241 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0); // round half-odd 242 break; 243 244 case ROUND_CEIL: 245 inc = (sign == 1) && (n != 0 || discarded != 0); // round ceil 246 break; 247 248 case ROUND_FLOOR: 249 default: 250 inc = (sign == -1) && (n != 0 || discarded != 0); // round floor 251 break; 252 } 253 254 if (inc) { 255 // increment if necessary 256 int rh = lsbthreshold; 257 for (int i = lsd; i < mant.length; i++) { 258 final int r = mant[i] + rh; 259 rh = r / RADIX; 260 mant[i] = r % RADIX; 261 } 262 263 if (rh != 0) { 264 shiftRight(); 265 mant[mant.length-1]=rh; 266 } 267 } 268 269 // Check for exceptional cases and raise signals if necessary 270 if (exp < MIN_EXP) { 271 // Gradual Underflow 272 getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW); 273 return DfpField.FLAG_UNDERFLOW; 274 } 275 276 if (exp > MAX_EXP) { 277 // Overflow 278 getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW); 279 return DfpField.FLAG_OVERFLOW; 280 } 281 282 if (n != 0 || discarded != 0) { 283 // Inexact 284 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT); 285 return DfpField.FLAG_INEXACT; 286 } 287 return 0; 288 } 289 290 /** {@inheritDoc} */ 291 @Override 292 public Dfp nextAfter(Dfp x) { 293 294 final String trapName = "nextAfter"; 295 296 // make sure we don't mix number with different precision 297 if (getField().getRadixDigits() != x.getField().getRadixDigits()) { 298 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 299 final Dfp result = newInstance(getZero()); 300 result.nans = QNAN; 301 return dotrap(DfpField.FLAG_INVALID, trapName, x, result); 302 } 303 304 boolean up = false; 305 Dfp result; 306 Dfp inc; 307 308 // if this is greater than x 309 if (this.lessThan(x)) { 310 up = true; 311 } 312 313 if (equals(x)) { 314 return newInstance(x); 315 } 316 317 if (lessThan(getZero())) { 318 up = !up; 319 } 320 321 if (up) { 322 inc = power10(intLog10() - getDecimalDigits() + 1); 323 inc = copysign(inc, this); 324 325 if (this.equals(getZero())) { 326 inc = power10K(MIN_EXP-mant.length-1); 327 } 328 329 if (inc.equals(getZero())) { 330 result = copysign(newInstance(getZero()), this); 331 } else { 332 result = add(inc); 333 } 334 } else { 335 inc = power10(intLog10()); 336 inc = copysign(inc, this); 337 338 if (this.equals(inc)) { 339 inc = inc.divide(power10(getDecimalDigits())); 340 } else { 341 inc = inc.divide(power10(getDecimalDigits() - 1)); 342 } 343 344 if (this.equals(getZero())) { 345 inc = power10K(MIN_EXP-mant.length-1); 346 } 347 348 if (inc.equals(getZero())) { 349 result = copysign(newInstance(getZero()), this); 350 } else { 351 result = subtract(inc); 352 } 353 } 354 355 if (result.classify() == INFINITE && this.classify() != INFINITE) { 356 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT); 357 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result); 358 } 359 360 if (result.equals(getZero()) && this.equals(getZero()) == false) { 361 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT); 362 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result); 363 } 364 365 return result; 366 } 367 368}