Home | History | Annotate | Download | only in dfp
      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  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package org.apache.commons.math.dfp;
     19 
     20 /** Subclass of {@link Dfp} which hides the radix-10000 artifacts of the superclass.
     21  * This should give outward appearances of being a decimal number with DIGITS*4-3
     22  * decimal digits. This class can be subclassed to appear to be an arbitrary number
     23  * of decimal digits less than DIGITS*4-3.
     24  * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $
     25  * @since 2.2
     26  */
     27 public class DfpDec extends Dfp {
     28 
     29     /** Makes an instance with a value of zero.
     30      * @param factory factory linked to this instance
     31      */
     32     protected DfpDec(final DfpField factory) {
     33         super(factory);
     34     }
     35 
     36     /** Create an instance from a byte value.
     37      * @param factory factory linked to this instance
     38      * @param x value to convert to an instance
     39      */
     40     protected DfpDec(final DfpField factory, byte x) {
     41         super(factory, x);
     42     }
     43 
     44     /** Create an instance from an int value.
     45      * @param factory factory linked to this instance
     46      * @param x value to convert to an instance
     47      */
     48     protected DfpDec(final DfpField factory, int x) {
     49         super(factory, x);
     50     }
     51 
     52     /** Create an instance from a long value.
     53      * @param factory factory linked to this instance
     54      * @param x value to convert to an instance
     55      */
     56     protected DfpDec(final DfpField factory, long x) {
     57         super(factory, x);
     58     }
     59 
     60     /** Create an instance from a double value.
     61      * @param factory factory linked to this instance
     62      * @param x value to convert to an instance
     63      */
     64     protected DfpDec(final DfpField factory, double x) {
     65         super(factory, x);
     66         round(0);
     67     }
     68 
     69     /** Copy constructor.
     70      * @param d instance to copy
     71      */
     72     public DfpDec(final Dfp d) {
     73         super(d);
     74         round(0);
     75     }
     76 
     77     /** Create an instance from a String representation.
     78      * @param factory factory linked to this instance
     79      * @param s string representation of the instance
     80      */
     81     protected DfpDec(final DfpField factory, final String s) {
     82         super(factory, s);
     83         round(0);
     84     }
     85 
     86     /** Creates an instance with a non-finite value.
     87      * @param factory factory linked to this instance
     88      * @param sign sign of the Dfp to create
     89      * @param nans code of the value, must be one of {@link #INFINITE},
     90      * {@link #SNAN},  {@link #QNAN}
     91      */
     92     protected DfpDec(final DfpField factory, final byte sign, final byte nans) {
     93         super(factory, sign, nans);
     94     }
     95 
     96     /** {@inheritDoc} */
     97     @Override
     98     public Dfp newInstance() {
     99         return new DfpDec(getField());
    100     }
    101 
    102     /** {@inheritDoc} */
    103     @Override
    104     public Dfp newInstance(final byte x) {
    105         return new DfpDec(getField(), x);
    106     }
    107 
    108     /** {@inheritDoc} */
    109     @Override
    110     public Dfp newInstance(final int x) {
    111         return new DfpDec(getField(), x);
    112     }
    113 
    114     /** {@inheritDoc} */
    115     @Override
    116     public Dfp newInstance(final long x) {
    117         return new DfpDec(getField(), x);
    118     }
    119 
    120     /** {@inheritDoc} */
    121     @Override
    122     public Dfp newInstance(final double x) {
    123         return new DfpDec(getField(), x);
    124     }
    125 
    126     /** {@inheritDoc} */
    127     @Override
    128     public Dfp newInstance(final Dfp d) {
    129 
    130         // make sure we don't mix number with different precision
    131         if (getField().getRadixDigits() != d.getField().getRadixDigits()) {
    132             getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
    133             final Dfp result = newInstance(getZero());
    134             result.nans = QNAN;
    135             return dotrap(DfpField.FLAG_INVALID, "newInstance", d, result);
    136         }
    137 
    138         return new DfpDec(d);
    139 
    140     }
    141 
    142     /** {@inheritDoc} */
    143     @Override
    144     public Dfp newInstance(final String s) {
    145         return new DfpDec(getField(), s);
    146     }
    147 
    148     /** {@inheritDoc} */
    149     @Override
    150     public Dfp newInstance(final byte sign, final byte nans) {
    151         return new DfpDec(getField(), sign, nans);
    152     }
    153 
    154     /** Get the number of decimal digits this class is going to represent.
    155      * Default implementation returns {@link #getRadixDigits()}*4-3. Subclasses can
    156      * override this to return something less.
    157      * @return number of decimal digits this class is going to represent
    158      */
    159     protected int getDecimalDigits() {
    160         return getRadixDigits() * 4 - 3;
    161     }
    162 
    163     /** {@inheritDoc} */
    164     @Override
    165     protected int round(int in) {
    166 
    167         int msb = mant[mant.length-1];
    168         if (msb == 0) {
    169             // special case -- this == zero
    170             return 0;
    171         }
    172 
    173         int cmaxdigits = mant.length * 4;
    174         int lsbthreshold = 1000;
    175         while (lsbthreshold > msb) {
    176             lsbthreshold /= 10;
    177             cmaxdigits --;
    178         }
    179 
    180 
    181         final int digits = getDecimalDigits();
    182         final int lsbshift = cmaxdigits - digits;
    183         final int lsd = lsbshift / 4;
    184 
    185         lsbthreshold = 1;
    186         for (int i = 0; i < lsbshift % 4; i++) {
    187             lsbthreshold *= 10;
    188         }
    189 
    190         final int lsb = mant[lsd];
    191 
    192         if (lsbthreshold <= 1 && digits == 4 * mant.length - 3) {
    193             return super.round(in);
    194         }
    195 
    196         int discarded = in;  // not looking at this after this point
    197         final int n;
    198         if (lsbthreshold == 1) {
    199             // look to the next digit for rounding
    200             n = (mant[lsd-1] / 1000) % 10;
    201             mant[lsd-1] %= 1000;
    202             discarded |= mant[lsd-1];
    203         } else {
    204             n = (lsb * 10 / lsbthreshold) % 10;
    205             discarded |= lsb % (lsbthreshold/10);
    206         }
    207 
    208         for (int i = 0; i < lsd; i++) {
    209             discarded |= mant[i];    // need to know if there are any discarded bits
    210             mant[i] = 0;
    211         }
    212 
    213         mant[lsd] = lsb / lsbthreshold * lsbthreshold;
    214 
    215         final boolean inc;
    216         switch (getField().getRoundingMode()) {
    217             case ROUND_DOWN:
    218                 inc = false;
    219                 break;
    220 
    221             case ROUND_UP:
    222                 inc = (n != 0) || (discarded != 0); // round up if n!=0
    223                 break;
    224 
    225             case ROUND_HALF_UP:
    226                 inc = n >= 5;  // round half up
    227                 break;
    228 
    229             case ROUND_HALF_DOWN:
    230                 inc = n > 5;  // round half down
    231                 break;
    232 
    233             case ROUND_HALF_EVEN:
    234                 inc = (n > 5) ||
    235                       (n == 5 && discarded != 0) ||
    236                       (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1);  // round half-even
    237                 break;
    238 
    239             case ROUND_HALF_ODD:
    240                 inc = (n > 5) ||
    241                       (n == 5 && discarded != 0) ||
    242                       (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0);  // round half-odd
    243                 break;
    244 
    245             case ROUND_CEIL:
    246                 inc = (sign == 1) && (n != 0 || discarded != 0);  // round ceil
    247                 break;
    248 
    249             case ROUND_FLOOR:
    250             default:
    251                 inc = (sign == -1) && (n != 0 || discarded != 0);  // round floor
    252                 break;
    253         }
    254 
    255         if (inc) {
    256             // increment if necessary
    257             int rh = lsbthreshold;
    258             for (int i = lsd; i < mant.length; i++) {
    259                 final int r = mant[i] + rh;
    260                 rh = r / RADIX;
    261                 mant[i] = r % RADIX;
    262             }
    263 
    264             if (rh != 0) {
    265                 shiftRight();
    266                 mant[mant.length-1]=rh;
    267             }
    268         }
    269 
    270         // Check for exceptional cases and raise signals if necessary
    271         if (exp < MIN_EXP) {
    272             // Gradual Underflow
    273             getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW);
    274             return DfpField.FLAG_UNDERFLOW;
    275         }
    276 
    277         if (exp > MAX_EXP) {
    278             // Overflow
    279             getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW);
    280             return DfpField.FLAG_OVERFLOW;
    281         }
    282 
    283         if (n != 0 || discarded != 0) {
    284             // Inexact
    285             getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
    286             return DfpField.FLAG_INEXACT;
    287         }
    288         return 0;
    289     }
    290 
    291     /** {@inheritDoc} */
    292     @Override
    293     public Dfp nextAfter(Dfp x) {
    294 
    295         final String trapName = "nextAfter";
    296 
    297         // make sure we don't mix number with different precision
    298         if (getField().getRadixDigits() != x.getField().getRadixDigits()) {
    299             getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
    300             final Dfp result = newInstance(getZero());
    301             result.nans = QNAN;
    302             return dotrap(DfpField.FLAG_INVALID, trapName, x, result);
    303         }
    304 
    305         boolean up = false;
    306         Dfp result;
    307         Dfp inc;
    308 
    309         // if this is greater than x
    310         if (this.lessThan(x)) {
    311             up = true;
    312         }
    313 
    314         if (equals(x)) {
    315             return newInstance(x);
    316         }
    317 
    318         if (lessThan(getZero())) {
    319             up = !up;
    320         }
    321 
    322         if (up) {
    323             inc = power10(log10() - getDecimalDigits() + 1);
    324             inc = copysign(inc, this);
    325 
    326             if (this.equals(getZero())) {
    327                 inc = power10K(MIN_EXP-mant.length-1);
    328             }
    329 
    330             if (inc.equals(getZero())) {
    331                 result = copysign(newInstance(getZero()), this);
    332             } else {
    333                 result = add(inc);
    334             }
    335         } else {
    336             inc = power10(log10());
    337             inc = copysign(inc, this);
    338 
    339             if (this.equals(inc)) {
    340                 inc = inc.divide(power10(getDecimalDigits()));
    341             } else {
    342                 inc = inc.divide(power10(getDecimalDigits() - 1));
    343             }
    344 
    345             if (this.equals(getZero())) {
    346                 inc = power10K(MIN_EXP-mant.length-1);
    347             }
    348 
    349             if (inc.equals(getZero())) {
    350                 result = copysign(newInstance(getZero()), this);
    351             } else {
    352                 result = subtract(inc);
    353             }
    354         }
    355 
    356         if (result.classify() == INFINITE && this.classify() != INFINITE) {
    357             getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
    358             result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
    359         }
    360 
    361         if (result.equals(getZero()) && this.equals(getZero()) == false) {
    362             getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
    363             result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
    364         }
    365 
    366         return result;
    367     }
    368 
    369 }
    370