001/*
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2023 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.arithmetic;
025
026import java.math.BigDecimal;
027import java.math.RoundingMode;
028
029import org.decimal4j.scale.ScaleMetrics;
030import org.decimal4j.truncate.CheckedRounding;
031import org.decimal4j.truncate.DecimalRounding;
032import org.decimal4j.truncate.OverflowMode;
033
034/**
035 * Arithmetic implementation with rounding and overflow check for scales other
036 * than zero. An exception is thrown if an operation leads to an overflow.
037 */
038public final class CheckedScaleNfRoundingArithmetic extends AbstractCheckedScaleNfArithmetic {
039
040        private final DecimalRounding rounding;
041
042        /**
043         * Constructor for decimal arithmetic with given scale, rounding mode and
044         * {@link OverflowMode#CHECKED} overflow mode.
045         * 
046         * @param scaleMetrics
047         *            the scale metrics for this decimal arithmetic
048         * @param roundingMode
049         *            the rounding mode to use for all decimal arithmetic
050         */
051        public CheckedScaleNfRoundingArithmetic(ScaleMetrics scaleMetrics, RoundingMode roundingMode) {
052                this(scaleMetrics, DecimalRounding.valueOf(roundingMode));
053        }
054
055        /**
056         * Constructor for decimal arithmetic with given scale, rounding mode and
057         * {@link OverflowMode#CHECKED} overflow mode.
058         * 
059         * @param scaleMetrics
060         *            the scale metrics for this decimal arithmetic
061         * @param rounding
062         *            the rounding mode to use for all decimal arithmetic
063         */
064        public CheckedScaleNfRoundingArithmetic(ScaleMetrics scaleMetrics, DecimalRounding rounding) {
065                super(scaleMetrics);
066                this.rounding = rounding;
067        }
068
069        @Override
070        public final RoundingMode getRoundingMode() {
071                return rounding.getRoundingMode();
072        }
073
074        @Override
075        public final CheckedRounding getTruncationPolicy() {
076                return CheckedRounding.valueOf(getRoundingMode());
077        }
078
079        @Override
080        public final long addUnscaled(long uDecimal, long unscaled, int scale) {
081                return Add.addUnscaledUnscaledChecked(this, rounding, uDecimal, unscaled, scale);
082        }
083
084        @Override
085        public final long subtractUnscaled(long uDecimal, long unscaled, int scale) {
086                return Sub.subtractUnscaledUnscaledChecked(this, rounding, uDecimal, unscaled, scale);
087        }
088
089        @Override
090        public final long multiplyByUnscaled(long uDecimal, long unscaled, int scale) {
091                return Mul.multiplyByUnscaledChecked(this, rounding, uDecimal, unscaled, scale);
092        }
093
094        @Override
095        public final long divideByUnscaled(long uDecimal, long unscaled, int scale) {
096                return Div.divideByUnscaledChecked(this, rounding, uDecimal, unscaled, scale);
097        }
098
099        @Override
100        public final long avg(long uDecimal1, long uDecimal2) {
101                return Avg.avg(this, rounding, uDecimal1, uDecimal2);
102        }
103
104        @Override
105        public final long invert(long uDecimal) {
106                return Invert.invert(this, rounding, uDecimal);
107        }
108
109        @Override
110        public final long multiply(long uDecimal1, long uDecimal2) {
111                return Mul.multiplyChecked(this, rounding, uDecimal1, uDecimal2);
112        }
113
114        @Override
115        public final long multiplyByPowerOf10(long uDecimal, int n) {
116                return Pow10.multiplyByPowerOf10Checked(this, rounding, uDecimal, n);
117        }
118
119        @Override
120        public final long divide(long uDecimalDividend, long uDecimalDivisor) {
121                return Div.divideChecked(this, rounding, uDecimalDividend, uDecimalDivisor);
122        }
123
124        @Override
125        public final long divideByLong(long uDecimalDividend, long lDivisor) {
126                return Div.divideByLongChecked(this, rounding, uDecimalDividend, lDivisor);
127        }
128
129        @Override
130        public final long divideByPowerOf10(long uDecimal, int n) {
131                return Pow10.divideByPowerOf10Checked(this, rounding, uDecimal, n);
132        }
133
134        @Override
135        public final long square(long uDecimal) {
136                return Square.squareChecked(this, rounding, uDecimal);
137        }
138
139        @Override
140        public final long sqrt(long uDecimal) {
141                return Sqrt.sqrt(this, rounding, uDecimal);
142        }
143
144        @Override
145        public final long pow(long uDecimalBase, int exponent) {
146                return Pow.pow(this, rounding, uDecimalBase, exponent);
147        }
148
149        @Override
150        public final long shiftLeft(long uDecimal, int n) {
151                return Shift.shiftLeftChecked(this, rounding, uDecimal, n);
152        }
153
154        @Override
155        public final long shiftRight(long uDecimal, int n) {
156                return Shift.shiftRightChecked(this, rounding, uDecimal, n);
157        }
158
159        @Override
160        public final long round(long uDecimal, int precision) {
161                return Round.round(this, rounding, uDecimal, precision);
162        }
163
164        @Override
165        public final long fromLong(long value) {
166                return LongConversion.longToUnscaled(getScaleMetrics(), value);
167        }
168
169        @Override
170        public final long fromFloat(float value) {
171                return FloatConversion.floatToUnscaled(this, rounding, value);
172        }
173
174        @Override
175        public final long fromDouble(double value) {
176                return DoubleConversion.doubleToUnscaled(this, rounding, value);
177        }
178
179        @Override
180        public final long fromUnscaled(long unscaledValue, int scale) {
181                return UnscaledConversion.unscaledToUnscaled(this, rounding, unscaledValue, scale);
182        }
183
184        @Override
185        public final long fromBigDecimal(BigDecimal value) {
186                return BigDecimalConversion.bigDecimalToUnscaled(getScaleMetrics(), getRoundingMode(), value);
187        }
188
189        @Override
190        public final long toLong(long uDecimal) {
191                return LongConversion.unscaledToLong(getScaleMetrics(), rounding, uDecimal);
192        }
193
194        @Override
195        public final float toFloat(long uDecimal) {
196                return FloatConversion.unscaledToFloat(this, rounding, uDecimal);
197        }
198
199        @Override
200        public final double toDouble(long uDecimal) {
201                return DoubleConversion.unscaledToDouble(this, rounding, uDecimal);
202        }
203
204        @Override
205        public final long toUnscaled(long uDecimal, int scale) {
206                return UnscaledConversion.unscaledToUnscaled(rounding, scale, this, uDecimal);
207        }
208
209        @Override
210        public final long parse(String value) {
211                return StringConversion.parseUnscaledDecimal(this, rounding, value, 0, value.length());
212        }
213        
214        @Override
215        public final long parse(CharSequence value, int start, int end) {
216                return StringConversion.parseUnscaledDecimal(this, rounding, value, start, end);
217        }
218}