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    
018    package 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     * @version $Id: DfpDec.java 1449529 2013-02-24 19:13:17Z luc $
025     * @since 2.2
026     */
027    public class DfpDec extends Dfp {
028    
029        /** Makes an instance with a value of zero.
030         * @param factory factory linked to this instance
031         */
032        protected DfpDec(final DfpField factory) {
033            super(factory);
034        }
035    
036        /** Create an instance from a byte value.
037         * @param factory factory linked to this instance
038         * @param x value to convert to an instance
039         */
040        protected DfpDec(final DfpField factory, byte x) {
041            super(factory, x);
042        }
043    
044        /** Create an instance from an int value.
045         * @param factory factory linked to this instance
046         * @param x value to convert to an instance
047         */
048        protected DfpDec(final DfpField factory, int x) {
049            super(factory, x);
050        }
051    
052        /** Create an instance from a long value.
053         * @param factory factory linked to this instance
054         * @param x value to convert to an instance
055         */
056        protected DfpDec(final DfpField factory, long x) {
057            super(factory, x);
058        }
059    
060        /** Create an instance from a double value.
061         * @param factory factory linked to this instance
062         * @param x value to convert to an instance
063         */
064        protected DfpDec(final DfpField factory, double x) {
065            super(factory, x);
066            round(0);
067        }
068    
069        /** Copy constructor.
070         * @param d instance to copy
071         */
072        public DfpDec(final Dfp d) {
073            super(d);
074            round(0);
075        }
076    
077        /** Create an instance from a String representation.
078         * @param factory factory linked to this instance
079         * @param s string representation of the instance
080         */
081        protected DfpDec(final DfpField factory, final String s) {
082            super(factory, s);
083            round(0);
084        }
085    
086        /** Creates an instance with a non-finite value.
087         * @param factory factory linked to this instance
088         * @param sign sign of the Dfp to create
089         * @param nans code of the value, must be one of {@link #INFINITE},
090         * {@link #SNAN},  {@link #QNAN}
091         */
092        protected DfpDec(final DfpField factory, final byte sign, final byte nans) {
093            super(factory, sign, nans);
094        }
095    
096        /** {@inheritDoc} */
097        @Override
098        public Dfp newInstance() {
099            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(intLog10() - 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(intLog10());
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    }