001/*
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2024 decimal4j (tools4j), Marco Terzer
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in all
014 * copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022 * SOFTWARE.
023 */
024package org.decimal4j.immutable;
025
026import java.math.BigDecimal;
027import java.math.BigInteger;
028import java.math.RoundingMode;
029
030import org.decimal4j.api.Decimal;
031import org.decimal4j.api.DecimalArithmetic;
032import org.decimal4j.base.AbstractImmutableDecimal;
033import org.decimal4j.exact.Multipliable0f;
034import org.decimal4j.factory.Factory0f;
035import org.decimal4j.mutable.MutableDecimal0f;
036import org.decimal4j.scale.Scale0f;
037
038/**
039 * <code>Decimal0f</code> represents an immutable decimal number with a fixed
040 * number of 0 digits to the right of the decimal point.
041 * <p>
042 * All methods for this class throw {@code NullPointerException} when passed a
043 * {@code null} object reference for any input parameter.
044 */
045public final class Decimal0f extends AbstractImmutableDecimal<Scale0f, Decimal0f> {
046
047        private static final long serialVersionUID = 1L;
048
049        /** Scale value 0 for {@code Decimal0f} returned by {@link #getScale()}.*/
050        public static final int SCALE = 0;
051
052        /** Scale metrics constant for {@code Decimal0f} returned by {@link #getScaleMetrics()}.*/
053        public static final Scale0f METRICS = Scale0f.INSTANCE;
054
055        /** Factory constant for {@code Decimal0f} returned by {@link #getFactory()}.*/
056        public static final Factory0f FACTORY = Factory0f.INSTANCE;
057        
058        /**
059         * Default arithmetic for {@code Decimal0f} performing unchecked operations with rounding mode 
060         * {@link RoundingMode#HALF_UP HALF_UP}.
061         */
062        public static final DecimalArithmetic DEFAULT_ARITHMETIC = METRICS.getDefaultArithmetic();
063        
064        /**
065         * Default arithmetic for {@code Decimal0f} performing checked operations with rounding mode 
066         * {@link RoundingMode#HALF_UP HALF_UP}.
067         */
068        public static final DecimalArithmetic DEFAULT_CHECKED_ARITHMETIC = METRICS.getDefaultCheckedArithmetic();
069
070        /** The unscaled long value that represents one.*/
071        public static final long ONE_UNSCALED = METRICS.getScaleFactor();
072
073        /** The {@code Decimal0f} constant zero.*/
074        public static final Decimal0f ZERO = new Decimal0f(0);
075    /**
076     * A constant holding the smallest positive value a {@code Decimal0f}
077     * can have, 10<sup>-0</sup>=1.
078     */
079        public static final Decimal0f ULP = new Decimal0f(1);
080
081    /**
082     * Initialize static constant array when class is loaded.
083     */
084    private static final int MAX_CONSTANT = 10;
085    private static final Decimal0f POS_CONST[] = new Decimal0f[MAX_CONSTANT+1];
086    private static final Decimal0f NEG_CONST[] = new Decimal0f[MAX_CONSTANT+1];
087
088    static {
089        for (int i = 1; i <= MAX_CONSTANT; i++) {
090            POS_CONST[i] = new Decimal0f(ONE_UNSCALED * i);
091            NEG_CONST[i] = new Decimal0f(-ONE_UNSCALED * i);
092        }
093    }
094
095        /** The {@code Decimal0f} constant 1.*/
096        public static final Decimal0f ONE = valueOf(1);
097        /** The {@code Decimal0f} constant 2.*/
098        public static final Decimal0f TWO = valueOf(2);
099        /** The {@code Decimal0f} constant 3.*/
100        public static final Decimal0f THREE = valueOf(3);
101        /** The {@code Decimal0f} constant 4.*/
102        public static final Decimal0f FOUR = valueOf(4);
103        /** The {@code Decimal0f} constant 5.*/
104        public static final Decimal0f FIVE = valueOf(5);
105        /** The {@code Decimal0f} constant 6.*/
106        public static final Decimal0f SIX = valueOf(6);
107        /** The {@code Decimal0f} constant 7.*/
108        public static final Decimal0f SEVEN = valueOf(7);
109        /** The {@code Decimal0f} constant 8.*/
110        public static final Decimal0f EIGHT = valueOf(8);
111        /** The {@code Decimal0f} constant 9.*/
112        public static final Decimal0f NINE = valueOf(9);
113        /** The {@code Decimal0f} constant 10.*/
114        public static final Decimal0f TEN = valueOf(10);
115        /** The {@code Decimal0f} constant 100.*/
116        public static final Decimal0f HUNDRED = new Decimal0f(100 * ONE_UNSCALED);
117        /** The {@code Decimal0f} constant 1000.*/
118        public static final Decimal0f THOUSAND = new Decimal0f(1000 * ONE_UNSCALED);
119        /** The {@code Decimal0f} constant 10<sup>6</sup>.*/
120        public static final Decimal0f MILLION = new Decimal0f(1000000 * ONE_UNSCALED);
121        /** The {@code Decimal0f} constant 10<sup>9</sup>.*/
122        public static final Decimal0f BILLION = new Decimal0f(1000000000 * ONE_UNSCALED);
123        /** The {@code Decimal0f} constant 10<sup>12</sup>.*/
124        public static final Decimal0f TRILLION = new Decimal0f(1000000000000L * ONE_UNSCALED);
125        /** The {@code Decimal0f} constant 10<sup>15</sup>.*/
126        public static final Decimal0f QUADRILLION = new Decimal0f(1000000000000000L * ONE_UNSCALED);
127        /** The {@code Decimal0f} constant 10<sup>18</sup>.*/
128        public static final Decimal0f QUINTILLION = new Decimal0f(1000000000000000000L * ONE_UNSCALED);
129
130        /** The {@code Decimal0f} constant -1.*/
131        public static final Decimal0f MINUS_ONE = valueOf(-1);
132
133
134    /**
135     * A constant holding the maximum value a {@code Decimal0f} can have,
136     * 9223372036854775807.
137     */
138        public static final Decimal0f MAX_VALUE = new Decimal0f(Long.MAX_VALUE);
139    /**
140     * A constant holding the maximum integer value a {@code Decimal0f}
141     * can have, 9223372036854775807.
142     */
143        public static final Decimal0f MAX_INTEGER_VALUE = new Decimal0f((Long.MAX_VALUE / ONE_UNSCALED) * ONE_UNSCALED);
144    /**
145     * A constant holding the minimum value a {@code Decimal0f} can have,
146     * -9223372036854775807.
147     */
148        public static final Decimal0f MIN_VALUE = new Decimal0f(Long.MIN_VALUE);
149    /**
150     * A constant holding the minimum integer value a {@code Decimal0f}
151     * can have, -9223372036854775808.
152     */
153        public static final Decimal0f MIN_INTEGER_VALUE = new Decimal0f((Long.MIN_VALUE / ONE_UNSCALED) * ONE_UNSCALED);
154
155        /**
156         * Private constructor with unscaled value.
157         *
158         * @param unscaled the unscaled value
159         */
160        private Decimal0f(long unscaled) {
161                super(unscaled);
162        }
163
164        /**
165         * Translates the string representation of a {@code Decimal} into a
166         * {@code Decimal0f}. The string representation consists of an
167         * optional sign, {@code '+'} or {@code '-'} , followed by a sequence of
168         * zero or more decimal digits ("the integer"), optionally followed by a
169         * fraction.
170         * <p>
171         * The fraction consists of a decimal point followed by zero or more decimal
172         * digits. The string must contain at least one digit in either the integer
173         * or the fraction. If the fraction contains more than 0 digits, the 
174         * value is rounded using {@link RoundingMode#HALF_UP HALF_UP} rounding. An 
175         * exception is thrown if the value is too large to be represented as a 
176         * {@code Decimal0f}.
177         *
178         * @param value
179         *            String value to convert into a {@code Decimal0f}
180         * @throws NumberFormatException
181         *             if {@code value} does not represent a valid {@code Decimal}
182         *             or if the value is too large to be represented as a 
183         *             {@code Decimal0f}
184         */
185        public Decimal0f(String value) {
186                super(DEFAULT_CHECKED_ARITHMETIC.parse(value));
187        }
188        
189        @Override
190        public final Scale0f getScaleMetrics() {
191                return METRICS;
192        }
193
194        @Override
195        public final int getScale() {
196                return SCALE;
197        }
198
199        @Override
200        public final Factory0f getFactory() {
201                return FACTORY;
202        }
203
204        @Override
205        protected final Decimal0f self() {
206                return this;
207        }
208
209        @Override
210        protected final DecimalArithmetic getDefaultArithmetic() {
211                return DEFAULT_ARITHMETIC;
212        }
213        
214        @Override
215        protected final DecimalArithmetic getDefaultCheckedArithmetic() {
216                return DEFAULT_CHECKED_ARITHMETIC;
217        }
218        
219        @Override
220        protected final DecimalArithmetic getRoundingDownArithmetic() {
221                return METRICS.getRoundingDownArithmetic();
222        }
223        
224        @Override
225        protected final DecimalArithmetic getRoundingFloorArithmetic() {
226                return METRICS.getRoundingFloorArithmetic();
227        }
228        
229        @Override
230        protected final DecimalArithmetic getRoundingHalfEvenArithmetic() {
231                return METRICS.getRoundingHalfEvenArithmetic();
232        }
233        
234        @Override
235        protected final DecimalArithmetic getRoundingUnnecessaryArithmetic() {
236                return METRICS.getRoundingUnnecessaryArithmetic();
237        }
238
239        /**
240         * Returns a {@code Decimal0f} whose value is numerically equal to
241         * that of the specified {@code long} value. An exception is thrown if the
242         * specified value is too large to be represented as a {@code Decimal0f}.
243         *
244         * @param value
245         *            long value to convert into a {@code Decimal0f}
246         * @return a {@code Decimal0f} value numerically equal to the specified 
247         *            {@code long} value
248         * @throws IllegalArgumentException
249         *            if {@code value} is too large to be represented as a 
250         *            {@code Decimal0f}
251         */
252        public static Decimal0f valueOf(long value) {
253        if (value == 0)
254            return ZERO;
255        if (value > 0 & value <= MAX_CONSTANT)
256            return POS_CONST[(int) value];
257        else if (value < 0 & value >= -MAX_CONSTANT)
258            return NEG_CONST[(int) -value];
259                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromLong(value));
260        }
261
262        /**
263         * Returns a {@code Decimal0f} whose value is calculated by
264         * rounding the specified {@code float} argument to scale 0
265         * using {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown
266         * if the specified value is too large to be represented as a {@code Decimal0f}. 
267         *
268         * @param value
269         *            float value to convert into a {@code Decimal0f}
270         * @return a {@code Decimal0f} calculated as: <code>round<sub>HALF_UP</sub>(value)</code>
271         * @throws IllegalArgumentException
272         *             if {@code value} is NaN or infinite or if the magnitude is
273         *             too large for the float to be represented as a {@code Decimal0f}
274         */
275        public static Decimal0f valueOf(float value) {
276                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromFloat(value));
277        }
278
279        /**
280         * Returns a {@code Decimal0f} whose value is calculated by
281         * rounding the specified {@code float} argument to scale 0
282         * using the specified {@code roundingMode}. An exception is thrown
283         * if the specified value is too large to be represented as a {@code Decimal0f}. 
284         *
285         * @param value
286         *            float value to convert into a {@code Decimal0f}
287         * @param roundingMode
288         *            the rounding mode to apply during the conversion if necessary
289         * @return a {@code Decimal0f} calculated as: <code>round(value)</code>
290         * @throws IllegalArgumentException
291         *             if {@code value} is NaN or infinite or if the magnitude is
292         *             too large for the float to be represented as a {@code Decimal0f}
293         * @throws ArithmeticException
294         *             if {@code roundingMode==UNNECESSARY} and rounding is
295         *             necessary
296         */
297        public static Decimal0f valueOf(float value, RoundingMode roundingMode) {
298                return valueOfUnscaled(METRICS.getCheckedArithmetic(roundingMode).fromFloat(value));
299        }
300
301        /**
302         * Returns a {@code Decimal0f} whose value is calculated by
303         * rounding the specified {@code double} argument to scale 0
304         * using {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown
305         * if the specified value is too large to be represented as a {@code Decimal0f}. 
306         *
307         * @param value
308         *            double value to convert into a {@code Decimal0f}
309         * @return a {@code Decimal0f} calculated as: <code>round<sub>HALF_UP</sub>(value)</code>
310         * @throws IllegalArgumentException
311         *             if {@code value} is NaN or infinite or if the magnitude is
312         *             too large for the double to be represented as a {@code Decimal0f}
313         */
314        public static Decimal0f valueOf(double value) {
315                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromDouble(value));
316        }
317
318        /**
319         * Returns a {@code Decimal0f} whose value is calculated by
320         * rounding the specified {@code double} argument to scale 0
321         * using the specified {@code roundingMode}. An exception is thrown
322         * if the specified value is too large to be represented as a {@code Decimal0f}. 
323         *
324         * @param value
325         *            double value to convert into a {@code Decimal0f}
326         * @param roundingMode
327         *            the rounding mode to apply during the conversion if necessary
328         * @return a {@code Decimal0f} calculated as: <code>round(value)</code>
329         * @throws IllegalArgumentException
330         *             if {@code value} is NaN or infinite or if the magnitude is
331         *             too large for the double to be represented as a {@code Decimal0f}
332         * @throws ArithmeticException
333         *             if {@code roundingMode==UNNECESSARY} and rounding is
334         *             necessary
335         */
336        public static Decimal0f valueOf(double value, RoundingMode roundingMode) {
337                return valueOfUnscaled(METRICS.getCheckedArithmetic(roundingMode).fromDouble(value));
338        }
339
340        /**
341         * Returns a {@code Decimal0f} whose value is numerically equal to that of
342         * the specified {@link BigInteger} value. An exception is thrown if the
343         * specified value is too large to be represented as a {@code Decimal0f}.
344         *
345         * @param value
346         *            {@code BigInteger} value to convert into a {@code Decimal0f}
347         * @return a {@code Decimal0f} value numerically equal to the specified big 
348         *         integer value
349         * @throws IllegalArgumentException
350         *             if {@code value} is too large to be represented as a {@code Decimal0f}
351         */
352        public static Decimal0f valueOf(BigInteger value) {
353                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromBigInteger(value));
354        }
355
356        /**
357         * Returns a {@code Decimal0f} whose value is calculated by rounding
358         * the specified {@link BigDecimal} argument to scale 0 using
359         * {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown if the 
360         * specified value is too large to be represented as a {@code Decimal0f}.
361         *
362         * @param value
363         *            {@code BigDecimal} value to convert into a {@code Decimal0f}
364         * @return a {@code Decimal0f} calculated as: <code>round<sub>HALF_UP</sub>(value)</code>
365         * @throws IllegalArgumentException
366         *             if {@code value} is too large to be represented as a {@code Decimal0f}
367         */
368        public static Decimal0f valueOf(BigDecimal value) {
369                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromBigDecimal(value));
370        }
371
372        /**
373         * Returns a {@code Decimal0f} whose value is calculated by rounding
374         * the specified {@link BigDecimal} argument to scale 0 using 
375         * the specified {@code roundingMode}. An exception is thrown if the 
376         * specified value is too large to be represented as a {@code Decimal0f}.
377         *
378         * @param value
379         *            {@code BigDecimal} value to convert into a {@code Decimal0f}
380         * @param roundingMode
381         *            the rounding mode to apply during the conversion if necessary
382         * @return a {@code Decimal0f} calculated as: <code>round(value)</code>
383         * @throws IllegalArgumentException
384         *             if {@code value} is too large to be represented as a {@code Decimal0f}
385         * @throws ArithmeticException
386         *             if {@code roundingMode==UNNECESSARY} and rounding is
387         *             necessary
388         */
389        public static Decimal0f valueOf(BigDecimal value, RoundingMode roundingMode) {
390                return valueOfUnscaled(METRICS.getCheckedArithmetic(roundingMode).fromBigDecimal(value));
391        }
392
393        /**
394         * Returns a {@code Decimal0f} whose value is calculated by rounding
395         * the specified {@link Decimal} argument to scale 0 using
396         * {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown if the
397         * specified value is too large to be represented as a {@code Decimal0f}. 
398         *
399         * @param value
400         *            Decimal value to convert into a {@code Decimal0f} 
401         * @return a {@code Decimal0f} calculated as: <code>round<sub>HALF_UP</sub>(value)</code>
402         * @throws IllegalArgumentException
403         *             if {@code value} is too large to be represented as a {@code Decimal0f}
404         */
405        public static Decimal0f valueOf(Decimal<?> value) {
406                if (value instanceof Decimal0f) {
407                        return (Decimal0f)value;
408                }
409                return valueOfUnscaled(value.unscaledValue(), value.getScale());
410        }
411
412        /**
413         * Returns a {@code Decimal0f} whose value is calculated by rounding
414         * the specified {@link Decimal} argument to scale 0 using
415         * the specified {@code roundingMode}. An exception is thrown if the
416         * specified value is too large to be represented as a {@code Decimal0f}. 
417         *
418         * @param value
419         *            Decimal value to convert into a {@code Decimal0f} 
420         * @param roundingMode
421         *            the rounding mode to apply during the conversion if necessary
422         * @return a {@code Decimal0f} calculated as: <code>round(value)</code>
423         * @throws IllegalArgumentException
424         *             if {@code value} is too large to be represented as a {@code Decimal0f}
425         * @throws ArithmeticException
426         *             if {@code roundingMode==UNNECESSARY} and rounding is
427         *             necessary
428         */
429        public static Decimal0f valueOf(Decimal<?> value, RoundingMode roundingMode) {
430                if (value instanceof Decimal0f) {
431                        return (Decimal0f)value;
432                }
433                return valueOfUnscaled(value.unscaledValue(), value.getScale(), roundingMode);
434        }
435
436        /**
437         * Translates the string representation of a {@code Decimal} into a
438         * {@code Decimal0f}. The string representation consists of an
439         * optional sign, {@code '+'} or {@code '-'} , followed by a sequence of
440         * zero or more decimal digits ("the integer"), optionally followed by a
441         * fraction.
442         * <p>
443         * The fraction consists of a decimal point followed by zero or more decimal
444         * digits. The string must contain at least one digit in either the integer
445         * or the fraction. If the fraction contains more than 0 digits, the 
446         * value is rounded using {@link RoundingMode#HALF_UP HALF_UP} rounding. An 
447         * exception is thrown if the value is too large to be represented as a 
448         * {@code Decimal0f}.
449         *
450         * @param value
451         *            String value to convert into a {@code Decimal0f}
452         * @return a {@code Decimal0f} calculated as: <code>round<sub>HALF_UP</sub>(value)</code>
453         * @throws NumberFormatException
454         *             if {@code value} does not represent a valid {@code Decimal}
455         *             or if the value is too large to be represented as a 
456         *             {@code Decimal0f}
457         */
458        public static Decimal0f valueOf(String value) {
459                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.parse(value));
460        }
461
462        /**
463         * Translates the string representation of a {@code Decimal} into a
464         * {@code Decimal0f}. The string representation consists of an
465         * optional sign, {@code '+'} or {@code '-'} , followed by a sequence of
466         * zero or more decimal digits ("the integer"), optionally followed by a
467         * fraction.
468         * <p>
469         * The fraction consists of a decimal point followed by zero or more decimal
470         * digits. The string must contain at least one digit in either the integer
471         * or the fraction. If the fraction contains more than 0 digits, the 
472         * value is rounded using the specified {@code roundingMode}. An exception 
473         * is thrown if the value is too large to be represented as a {@code Decimal0f}.
474         *
475         * @param value
476         *            String value to convert into a {@code Decimal0f}
477         * @param roundingMode
478         *            the rounding mode to apply if the fraction contains more than
479         *            0 digits
480         * @return a {@code Decimal0f} calculated as: <code>round(value)</code>
481         * @throws NumberFormatException
482         *             if {@code value} does not represent a valid {@code Decimal}
483         *             or if the value is too large to be represented as a 
484         *             {@code Decimal0f}
485         * @throws ArithmeticException
486         *             if {@code roundingMode==UNNECESSARY} and rounding is
487         *             necessary
488         */
489        public static Decimal0f valueOf(String value, RoundingMode roundingMode) {
490                return valueOfUnscaled(METRICS.getCheckedArithmetic(roundingMode).parse(value));
491        }
492
493        /**
494         * Returns a {@code Decimal0f} whose value is numerically equal to
495         * <code>(unscaledValue &times; 10<sup>-0</sup>)</code>.
496         *
497         * @param unscaledValue
498         *            unscaled value to convert into a {@code Decimal0f}
499         * @return a {@code Decimal0f} calculated as:
500         *         <code>unscaledValue &times; 10<sup>-0</sup></code>
501         */
502        public static Decimal0f valueOfUnscaled(long unscaledValue) {
503                if (unscaledValue == 0) {
504                        return ZERO;
505                }
506                if (unscaledValue == 1) {
507                        return ULP;
508                }
509                if (unscaledValue == ONE_UNSCALED) {
510                        return ONE;
511                }
512                if (unscaledValue == -ONE_UNSCALED) {
513                        return MINUS_ONE;
514                }
515                return new Decimal0f(unscaledValue);
516        }
517
518        /**
519         * Returns a {@code Decimal0f} whose value is numerically equal to
520         * <code>(unscaledValue &times; 10<sup>-scale</sup>)</code>. The result is
521         * rounded to scale 0 using {@link RoundingMode#HALF_UP HALF_UP} 
522         * rounding. An exception is thrown if the specified value is too large 
523         * to be represented as a {@code Decimal0f}.
524         *
525         * @param unscaledValue
526         *            unscaled value to convert into a {@code Decimal0f}
527         * @param scale
528         *            the scale to apply to {@code unscaledValue}
529         * @return a {@code Decimal0f} calculated as:
530         *         <code>round<sub>HALF_UP</sub>(unscaledValue &times; 10<sup>-scale</sup>)</code>
531         * @throws IllegalArgumentException
532         *             if the specified value is too large to be represented as a 
533         *             {@code Decimal0f}
534         */
535        public static Decimal0f valueOfUnscaled(long unscaledValue, int scale) {
536                return valueOfUnscaled(DEFAULT_CHECKED_ARITHMETIC.fromUnscaled(unscaledValue, scale));
537        }
538
539        /**
540         * Returns a {@code Decimal0f} whose value is numerically equal to
541         * <code>(unscaledValue &times; 10<sup>-scale</sup>)</code>. The result
542         * is rounded to scale 0 using the specified {@code roundingMode}. 
543         * An exception is thrown if the specified value is too large to be 
544         * represented as a {@code Decimal0f}.
545         *
546         * @param unscaledValue
547         *            unscaled value to convert into a Decimal0
548         * @param scale
549         *            the scale to apply to {@code unscaledValue}
550         * @param roundingMode
551         *            the rounding mode to apply during the conversion if necessary
552         * @return a {@code Decimal0f} calculated as:
553         *         <code>round(unscaledValue &times; 10<sup>-scale</sup>)</code>
554         * @throws IllegalArgumentException
555         *             if the specified value is too large to be represented as a {@code Decimal0f}
556         */
557        public static Decimal0f valueOfUnscaled(long unscaledValue, int scale, RoundingMode roundingMode) {
558                return valueOfUnscaled(METRICS.getCheckedArithmetic(roundingMode).fromUnscaled(unscaledValue, scale));
559        }
560
561        @Override
562        protected Decimal0f createOrAssign(long unscaled) {
563                return valueOfUnscaled(unscaled);
564        }
565        
566        @Override
567        protected Decimal0f create(long unscaled) {
568                return valueOfUnscaled(unscaled);
569        }
570        
571        @Override
572        protected Decimal0f[] createArray(int length) {
573                return new Decimal0f[length];
574        }
575        
576        /**
577         * Returns this {@code Decimal} as a multipliable factor for typed 
578         * exact multiplication. The second factor is passed to one of the
579         * {@code by(..)} methods of the returned multiplier. The scale of
580         * the result is the sum of the scales of {@code this} Decimal and the
581         * second factor passed to the {@code by(..)} method.
582         * <p>
583         * The method is similar to {@link #multiplyExact(Decimal) multiplyExact(Decimal)} but the result
584         * is retrieved in exact typed form with the correct result scale. 
585         * <p>
586         * For instance one can write:
587         * <pre>
588         * Decimal2f product = this.multiplyExact().by(Decimal2f.FIVE);
589         * </pre>
590         * 
591         * @return a multipliable object encapsulating this Decimal as first factor
592         *             of an exact multiplication
593         */
594        public Multipliable0f multiplyExact() {
595                return new Multipliable0f(this);
596        }
597
598        @Override
599        public MutableDecimal0f toMutableDecimal() {
600                return new MutableDecimal0f(this);
601        }
602
603        @Override
604        public Decimal0f toImmutableDecimal() {
605                return this;
606        }
607}