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.scale;
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.truncate.TruncationPolicy;
033
034/**
035 * <code>ScaleMetrics</code> defines various metrics associated with the scale of a {@link Decimal} number. It is mainly
036 * used internally from code implementing the arithmetic operations of a {@code Decimal}.
037 * <p>
038 * The {@link #getScale() scale} determines the number of fraction digits of the {@code Decimal}. The
039 * {@link #getScaleFactor() scale factor} is the multiplier/divisor for conversions between the {@code Decimal} value
040 * and the unscaled {@code long} value underlying every {@code Decimal}.
041 * <p>
042 * Operations such as {@link #multiplyByScaleFactor(long) multiplyByScaleFactor(..)} are defined here as separate
043 * methods to allow for compiler optimizations. Multiplications and divisions are for instance translated into shifts
044 * and adds by the compiler instead of the more expensive multiplication and division operations with non-constant long
045 * values.
046 * <p>
047 * {@code ScaleMetrics} also provides access to {@link DecimalArithmetic} instances for different rounding modes and
048 * overflow policies. {@code DecimalArithmetic} objects can be used to deal with {@code Decimal} numbers in their
049 * <i>primitive</i> form, meaning that {@code Decimal} numbers are passed to the arithmetic class as unscaled
050 * {@code long} values.
051 */
052public interface ScaleMetrics {
053        /**
054         * Returns the scale, the number of fraction digits to the right of the decimal point of a {@link Decimal} value.
055         * 
056         * @return the scale also known as number of fraction digits
057         */
058        int getScale();
059
060        /**
061         * Returns the scale factor, which is 10<sup>f</sup> where {@code f} stands for the {@link #getScale() scale}.
062         * 
063         * @return the scale factor
064         */
065        long getScaleFactor();
066
067        /**
068         * Returns the {@link #getScaleFactor() scale factor} as a {@link BigInteger} value.
069         * 
070         * @return the scale factor as big integer
071         */
072        BigInteger getScaleFactorAsBigInteger();
073
074        /**
075         * Returns the {@link #getScaleFactor() scale factor} as a {@link BigDecimal} value with scale zero.
076         * 
077         * @return the scale factor as big decimal with scale zero.
078         */
079        BigDecimal getScaleFactorAsBigDecimal();
080
081        /**
082         * Returns the number of leading zeros of the scale factor
083         * 
084         * @return {@link Long#numberOfLeadingZeros(long)} applied to the scale factor
085         */
086        int getScaleFactorNumberOfLeadingZeros();
087
088        /**
089         * Returns the largest integer value that can be represented using this scale.
090         * 
091         * @return {@code Long.MAX_VALUE / scaleFactor}
092         */
093        long getMaxIntegerValue();
094
095        /**
096         * Returns the smallest integer value that can be represented using this scale.
097         * 
098         * @return {@code Long.MIN_VALUE / scaleFactor}
099         */
100        long getMinIntegerValue();
101
102        /**
103         * Returns true if the specified integer {@code value} can be represented using this scale.
104         * 
105         * @param value
106         *            the value to test
107         * @return true if {@code (Long.MIN_VALUE / scaleFactor) <= value <= (Long.MAX_VALUE / scaleFactor)}
108         */
109        boolean isValidIntegerValue(long value);
110
111        /**
112         * Returns {@code factor*scaleFactor}.
113         * 
114         * @param factor
115         *            the factor
116         * @return {@code factor*scaleFactor}
117         */
118        long multiplyByScaleFactor(long factor);
119
120        /**
121         * Returns {@code factor*scaleFactor}, checking for lost information. If the result is out of the range of the
122         * {@code long} type, then an {@code ArithmeticException} is thrown.
123         * 
124         * @param factor
125         *            the factor
126         * @return {@code factor*scaleFactor}
127         * @throws ArithmeticException
128         *             if an overflow occurs
129         */
130        long multiplyByScaleFactorExact(long factor);
131
132        /**
133         * Returns {@code factor*low32(scaleFactor)} where low32 refers to the low 32 bits of the factor.
134         * 
135         * @param factor
136         *            the factor
137         * @return {@code factor*low32(scaleFactor)}
138         */
139        long mulloByScaleFactor(int factor);
140
141        /**
142         * Returns {@code factor*high32(scaleFactor)} where high32 refers to the high 32 bits of the factor.
143         * 
144         * @param factor
145         *            the factor
146         * @return {@code factor*high32(scaleFactor)}
147         */
148        long mulhiByScaleFactor(int factor);
149
150        /**
151         * Returns {@code dividend/scaleFactor}.
152         * 
153         * @param dividend
154         *            the dividend
155         * @return {@code dividend/scaleFactor}
156         */
157        long divideByScaleFactor(long dividend);
158
159        /**
160         * Returns {@code unsignedDividend/scaleFactor} using unsigned division.
161         * 
162         * @param unsignedDividend
163         *            the unsigned dividend
164         * @return {@code unsignedDividend/scaleFactor}
165         */
166        long divideUnsignedByScaleFactor(long unsignedDividend);
167
168        /**
169         * Returns {@code dividend % scaleFactor} also known as reminder.
170         * 
171         * @param dividend
172         *            the dividend
173         * @return {@code dividend % scaleFactor}
174         */
175        long moduloByScaleFactor(long dividend);
176
177        /**
178         * Returns the string representation of the specified {@code value} applying this metric's scale.
179         * 
180         * @param value
181         *            the unscaled decimal to convert to a string
182         * @return a fixed-point string representation of the specified value
183         * @see DecimalArithmetic#toString(long)
184         */
185        String toString(long value);
186
187        /**
188         * Returns the default arithmetic for this scale performing unchecked operations with rounding mode
189         * {@link RoundingMode#HALF_UP HALF_UP}.
190         * 
191         * @return default arithmetic for this scale rounding HALF_UP without overflow checks
192         */
193        DecimalArithmetic getDefaultArithmetic();
194
195        /**
196         * Returns the default arithmetic for this scale performing checked operations with rounding mode
197         * {@link RoundingMode#HALF_UP HALF_UP}.
198         * 
199         * @return default arithmetic for this scale rounding HALF_UP with overflow checks
200         */
201        DecimalArithmetic getDefaultCheckedArithmetic();
202
203        /**
204         * Returns the arithmetic for this scale performing unchecked operations with rounding mode {@link RoundingMode#DOWN
205         * DOWN}.
206         * 
207         * @return arithmetic for this scale rounding DOWN without overflow checks
208         */
209        DecimalArithmetic getRoundingDownArithmetic();
210
211        /**
212         * Returns the arithmetic for this scale performing unchecked operations with rounding mode
213         * {@link RoundingMode#FLOOR FLOOR}.
214         * 
215         * @return arithmetic for this scale rounding FLOOR without overflow checks
216         */
217        DecimalArithmetic getRoundingFloorArithmetic();
218
219        /**
220         * Returns the arithmetic for this scale performing unchecked operations with rounding mode
221         * {@link RoundingMode#HALF_EVEN HALF_EVEN}.
222         * 
223         * @return arithmetic for this scale rounding HALF_EVEN without overflow checks
224         */
225        DecimalArithmetic getRoundingHalfEvenArithmetic();
226
227        /**
228         * Returns the arithmetic for this scale performing unchecked operations with rounding mode
229         * {@link RoundingMode#UNNECESSARY UNNECESSARY}.
230         * 
231         * @return default arithmetic for this scale for rounding UNNECESSARY mode without overflow checks
232         */
233        DecimalArithmetic getRoundingUnnecessaryArithmetic();
234
235        /**
236         * Returns the arithmetic for this scale that performs all operations with the specified {@code roundingMode} and
237         * without overflow checks.
238         *
239         * @param roundingMode
240         *            the rounding mode used by the returned arithmetic
241         * @return arithmetic for this scale with specified rounding mode and without overflow checks
242         */
243        DecimalArithmetic getArithmetic(RoundingMode roundingMode);
244
245        /**
246         * Returns the arithmetic for this scale that performs all operations with the specified {@code roundingMode} and
247         * with overflow checks.
248         *
249         * @param roundingMode
250         *            the rounding mode used by the returned arithmetic
251         * @return arithmetic for this scale with specified rounding mode and with overflow checks
252         */
253        DecimalArithmetic getCheckedArithmetic(RoundingMode roundingMode);
254
255        /**
256         * Returns the arithmetic for this scale that performs all operations with the specified {@code truncationPolicy}.
257         *
258         * @param truncationPolicy
259         *            the truncation policy used by the returned arithmetic
260         * @return arithmetic for this scale with specified truncation policy
261         */
262        DecimalArithmetic getArithmetic(TruncationPolicy truncationPolicy);
263}