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.api;
025
026import java.io.IOException;
027import java.math.BigDecimal;
028import java.math.BigInteger;
029import java.math.RoundingMode;
030
031import org.decimal4j.scale.ScaleMetrics;
032import org.decimal4j.scale.Scales;
033import org.decimal4j.truncate.OverflowMode;
034import org.decimal4j.truncate.TruncationPolicy;
035
036/**
037 * <code>DecimalArithmetic</code> defines the basic primitive operations for {@link Decimal} numbers for one particular
038 * combination of {@link #getScale() scale}, {@link #getRoundingMode() rounding mode} and {@link #getOverflowMode()
039 * overflow mode}. Primitive here means that <code>Decimal</code> values are simply represented by their underlying unscaled
040 * <code>long</code> value. All operations therefore use unscaled longs for <code>Decimal</code> arguments and return longs for
041 * <code>Decimal</code> number results.
042 * <p>
043 * Application code does not usually need to use <code>DecimalArithmetic</code> directly. It may be appropriate however for
044 * very specialized applications with low latency, high frequency or zero garbage requirements. All operations of
045 * <code>DecimalArithmetic</code> do not allocate any objects (zero garbage) unless otherwise indicated.
046 */
047public interface DecimalArithmetic {
048        /**
049         * Returns the scale {@code f} applied to all unscaled decimal values passed to and returned by this
050         * {@code DecimalArithmetic}. Corresponds to the number of digits to the right of the decimal point (cannot be
051         * negative).
052         * <p>
053         * A given {@link Decimal} value multiplied with <code>10<sup>f</sup></code> results in an unscaled long value.
054         * Conversely, a {@code Decimal} value {@code d} can be computed from the unscaled value {@code u} as
055         * <code>d = u*10<sup>-f</sup></code>.
056         * 
057         * @return the non-negative scale {@code f} applied to unscaled decimal values within this {@code DecimalArithmetic}
058         *         object
059         * @see ScaleMetrics#getScale()
060         */
061        int getScale();
062
063        /**
064         * Returns the scale metrics associated with this decimal arithmetic object.
065         * 
066         * @return the scale metrics
067         */
068        ScaleMetrics getScaleMetrics();
069
070        /**
071         * Returns the <i>rounding mode</i> applied to operations of this {@code DecimalArithmetic} object if rounding is
072         * necessary.
073         * 
074         * @return the rounding mode applied to operations of this {@code DecimalArithmetic} object if rounding is necessary
075         */
076        RoundingMode getRoundingMode();
077
078        /**
079         * Returns the <i>overflow mode</i> applied to operations of this {@code DecimalArithmetic} object if an overflow
080         * occurs. The overflow mode defines whether an operation should throw an exception if an overflow occurs.
081         * 
082         * @return the overflow mode applied to operations of this {@code DecimalArithmetic} object if an overflow occurs
083         */
084        OverflowMode getOverflowMode();
085
086        /**
087         * Returns the <i>truncation policy</i> defining how to handle truncation due to overflow or rounding. The
088         * {@code TruncationPolicy} is defined by the {@link #getOverflowMode() overflow mode} and the
089         * {@link #getRoundingMode() rounding mode}.
090         * 
091         * @return the truncation policy defining how this {@code DecimalArithmetic} handles truncation
092         */
093        TruncationPolicy getTruncationPolicy();
094
095        /**
096         * Derives an arithmetic instance for the specified {@code scale} using this arithmetic's {@link #getRoundingMode()
097         * rounding mode} and {@link #getOverflowMode() overflow mode}.
098         * 
099         * @param scale
100         *            the scale for the new arithmetic; must be in {@code [0,18]} both ends inclusive
101         * @return an arithmetic instance with the given scale and this arithmetic's rounding and overflow mode
102         * @throws IllegalArgumentException
103         *             if scale is not in {@code [0, 18]}
104         * @see Scales#getScaleMetrics(int)
105         * @see ScaleMetrics#getArithmetic(RoundingMode)
106         * @see ScaleMetrics#getArithmetic(TruncationPolicy)
107         */
108        DecimalArithmetic deriveArithmetic(int scale);
109
110        /**
111         * Derives an arithmetic instance for the same {@link #getScale() scale} as this arithmetic but for the specified
112         * {@code roundingMode}. The returned arithmetic uses the same {@link #getOverflowMode() overflow mode} as this
113         * arithmetic.
114         * 
115         * @param roundingMode
116         *            the rounding mode for the new arithmetic
117         * @return an arithmetic instance with the given rounding mode and this arithmetic's scale and overflow mode
118         * @throws NullPointerException
119         *             if rounding mode is null
120         */
121        DecimalArithmetic deriveArithmetic(RoundingMode roundingMode);
122
123        /**
124         * Derives an arithmetic instance for the same {@link #getScale() scale} as this arithmetic but for the specified
125         * {@code roundingMode} and {@code overflowMode}.
126         * 
127         * @param roundingMode
128         *            the rounding mode for the new arithmetic
129         * @param overflowMode
130         *            the overflow mode for the new arithmetic
131         * @return an arithmetic instance with the given rounding and overflow mode and this arithmetic's scale
132         * @throws NullPointerException
133         *             if any of the arguments is null
134         */
135        DecimalArithmetic deriveArithmetic(RoundingMode roundingMode, OverflowMode overflowMode);
136
137        /**
138         * Derives an arithmetic instance for the same {@link #getScale() scale} as this arithmetic but for the specified
139         * {@code overflowMode}. The returned arithmetic uses the same {@link #getRoundingMode() rounding mode} as this
140         * arithmetic.
141         * 
142         * @param overflowMode
143         *            the overflow mode for the new arithmetic
144         * @return an arithmetic instance with the given overflow mode and this arithmetic's scale and rounding mode
145         * @throws NullPointerException
146         *             if overflow mode is null
147         */
148        DecimalArithmetic deriveArithmetic(OverflowMode overflowMode);
149
150        /**
151         * Derives an arithmetic instance for the same {@link #getScale() scale} as this arithmetic but with rounding and
152         * overflow mode specified by the given {@code truncationPolicy}.
153         * 
154         * @param truncationPolicy
155         *            the truncation policy specifying rounding and overflow mode for the new arithmetic
156         * @return an arithmetic instance with rounding and overflow mode specified by the truncation policy using this
157         *         arithmetic's scale
158         * @throws NullPointerException
159         *             if truncation policy is null
160         */
161        DecimalArithmetic deriveArithmetic(TruncationPolicy truncationPolicy);
162
163        /**
164         * Returns the unscaled decimal for the decimal value {@code 1}. One is the value <code>10<sup>scale</sup></code> which
165         * is also the multiplier used to get the unscaled decimal from the true decimal value.
166         * 
167         * @return the unscaled decimal representing the decimal value 1
168         */
169        long one();
170
171        /**
172         * Returns the signum function of the specified unscaled decimal.
173         * 
174         * @param uDecimal
175         *            the unscaled decimal
176         * @return -1, 0, or 1 as the value of the specified unscaled decimal is negative, zero, or positive.
177         */
178        int signum(long uDecimal);
179
180        /**
181         * Compares two unscaled decimal values numerically.
182         * 
183         * @param uDecimal1
184         *            the first unscaled decimal to compare
185         * @param uDecimal2
186         *            the second unscaled decimal to compare
187         * @return the value {@code 0} if {@code unscaled1 == unscaled2}; a value less than {@code 0} if
188         *         {@code unscaled1 < unscaled2}; and a value greater than {@code 0} if {@code unscaled1 > unscaled2}
189         */
190        int compare(long uDecimal1, long uDecimal2);
191
192        /**
193         * Compares two unscaled decimal values numerically. Note that scale of the first operand is determined by this
194         * arithmetic's {@link #getScale() scale} whereas the scale of the second {@code unscaled} value is explicitly
195         * specified by the {@code scale} argument.
196         * 
197         * @param uDecimal
198         *            the first unscaled decimal to compare
199         * @param unscaled
200         *            the second unscaled decimal to compare
201         * @param scale
202         *            the scale of {@code unscaled}
203         * @return the value {@code 0} if {@code unscaled1 == unscaled2}; a value less than {@code 0} if
204         *         {@code unscaled1 < unscaled2}; and a value greater than {@code 0} if {@code unscaled1 > unscaled2}
205         */
206        int compareToUnscaled(long uDecimal, long unscaled, int scale);
207
208        /**
209         * Returns an unscaled decimal whose value is {@code (uDecimal1 + uDecimal2)}.
210         * 
211         * @param uDecimal1
212         *            first unscaled decimal value to be added
213         * @param uDecimal2
214         *            second unscaled decimal value to be added
215         * @return {@code uDecimal1 + uDecimal2}
216         * @throws ArithmeticException
217         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
218         */
219        long add(long uDecimal1, long uDecimal2);
220
221        /**
222         * Returns an unscaled decimal whose value is the sum of the specified arguments: {@code (uDecimal + lValue)}.
223         * <p>
224         * Mathematically the method calculates <code>(uDecimal + lValue * 10<sup>scale</sup>)</code> avoiding information loss
225         * due to overflow of intermediary results.
226         * 
227         * @param uDecimal
228         *            unscaled decimal value to be added
229         * @param lValue
230         *            long value to be added
231         * @return <code>(uDecimal + lValue * 10<sup>scale</sup>)</code>
232         * @throws ArithmeticException
233         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
234         */
235        long addLong(long uDecimal, long lValue);
236
237        /**
238         * Returns an unscaled decimal whose value is <code>(uDecimal + unscaled * 10<sup>-scale</sup>)</code>. If rounding must
239         * be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied. Note that scale of the first
240         * operand is determined by this arithmetic's {@link #getScale() scale} whereas the scale of the second
241         * {@code unscaled} value is explicitly specified by the {@code scale} argument.
242         * <p>
243         * Mathematically the method calculates <code>round(uDecimal + lValue * 10<sup>-scale + s</sup>)</code> where {@code s}
244         * refers to this arithetic's scale. The method avoids information loss due to overflow of intermediary results.
245         * 
246         * @param uDecimal
247         *            unscaled decimal value to be added to
248         * @param unscaled
249         *            unscaled value to add
250         * @param scale
251         *            scale associated with the {@code unscaled} value
252         * @return <code>round(uDecimal + unscaled * 10<sup>-scale</sup>)</code>
253         * @throws ArithmeticException
254         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
255         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
256         */
257        long addUnscaled(long uDecimal, long unscaled, int scale);
258
259        /**
260         * Returns an unscaled decimal whose value is {@code (uDecimalMinuend -
261         * uDecimalSubtrahend)}.
262         * 
263         * @param uDecimalMinuend
264         *            unscaled decimal value to subtract from
265         * @param uDecimalSubtrahend
266         *            unscaled decimal value to subtract from the minuend
267         * @return {@code uDecimalMinuend - uDecimalSubtrahend}
268         * @throws ArithmeticException
269         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
270         */
271        long subtract(long uDecimalMinuend, long uDecimalSubtrahend);
272
273        /**
274         * Returns an unscaled decimal whose value is the difference of the specified arguments: {@code (uDecimal - lValue)}
275         * .
276         * <p>
277         * Mathematically the method calculates <code>(uDecimal - lValue * 10<sup>scale</sup>)</code> avoiding information loss
278         * due to overflow of intermediary results.
279         * 
280         * @param uDecimal
281         *            unscaled decimal value to subtract from
282         * @param lValue
283         *            long value to subtract
284         * @return <code>(uDecimal - lValue * 10<sup>scale</sup>)</code>
285         * @throws ArithmeticException
286         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
287         */
288        long subtractLong(long uDecimal, long lValue);
289
290        /**
291         * Returns an unscaled decimal whose value is <code>(uDecimal - unscaled * 10<sup>-scale</sup>)</code>. If rounding must
292         * be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied. Note that scale of the first
293         * operand is determined by this arithmetic's {@link #getScale() scale} whereas the scale of the second
294         * {@code unscaled} value is explicitly specified by the {@code scale} argument.
295         * <p>
296         * Mathematically the method calculates <code>round(uDecimal - lValue * 10<sup>-scale + s</sup>)</code> where {@code s}
297         * refers to this arithetic's scale. The method avoids information loss due to overflow of intermediary results.
298         * 
299         * @param uDecimal
300         *            unscaled decimal value to subtract from
301         * @param unscaled
302         *            unscaled value to subtract
303         * @param scale
304         *            scale associated with the {@code unscaled} value
305         * @return <code>round(uDecimal - unscaled * 10<sup>-scale</sup>)</code> as unscaled decimal
306         * @throws ArithmeticException
307         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
308         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
309         */
310        long subtractUnscaled(long uDecimal, long unscaled, int scale);
311
312        /**
313         * Returns an unscaled decimal whose value is the product of the specified arguments:
314         * {@code (uDecimal1 * uDecimal2)}. If rounding must be performed, this arithmetic's {@link #getRoundingMode()
315         * rounding mode} is applied.
316         * <p>
317         * Mathematically the method calculates <code>round((uDecimal1 * uDecimal2) * 10<sup>-scale</sup>)</code> avoiding
318         * information loss due to overflow of intermediary results.
319         * 
320         * @param uDecimal1
321         *            first unscaled decimal value to be multiplied
322         * @param uDecimal2
323         *            second unscaled decimal value to be multiplied
324         * @return {@code round(uDecimal1 * uDecimal2)}
325         * @throws ArithmeticException
326         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
327         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
328         */
329        long multiply(long uDecimal1, long uDecimal2);
330
331        /**
332         * Returns an unscaled decimal whose value is {@code (uDecimal * lValue)} where the second argument is a true long
333         * value instead of an unscaled decimal.
334         * 
335         * @param uDecimal
336         *            unscaled decimal value to be multiplied
337         * @param lValue
338         *            long value to be multiplied
339         * @return {@code uDecimal * lValue}
340         * @throws ArithmeticException
341         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
342         */
343        long multiplyByLong(long uDecimal, long lValue);
344
345        /**
346         * Returns an unscaled decimal whose value is <code>(uDecimal * unscaled * 10<sup>-scale</sup>)</code>. If rounding must
347         * be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied. Note that scale of the first
348         * operand is determined by this arithmetic's {@link #getScale() scale} whereas the scale of the second
349         * {@code unscaled} value is explicitly specified by the {@code scale} argument.
350         * <p>
351         * Mathematically the method calculates <code>round((uDecimal * unscaled) * 10<sup>-scale</sup>)</code> avoiding
352         * information loss due to overflow of intermediary results.
353         * 
354         * @param uDecimal
355         *            unscaled decimal value to be multiplied
356         * @param unscaled
357         *            unscaled value to be multiplied
358         * @param scale
359         *            scale associated with the {@code unscaled} value
360         * @return <code>round(uDecimal * (unscaled * 10<sup>-scale</sup>))</code>
361         * @throws ArithmeticException
362         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
363         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
364         */
365        long multiplyByUnscaled(long uDecimal, long unscaled, int scale);
366
367        /**
368         * Returns an unscaled decimal whose value is <code>(uDecimal * 10<sup>n</sup>)</code>.
369         * <p>
370         * The power, {@code n}, may be negative, in which case this method performs a division by a power of ten. If
371         * rounding must be performed (for negative n), this arithmetic's {@link #getRoundingMode() rounding mode} is
372         * applied.
373         * 
374         * @param uDecimal
375         *            value to be multiplied
376         * @param n
377         *            the power of ten
378         * @return <code>round(uDecimal &times; 10<sup>n</sup>)</code>
379         * @throws ArithmeticException
380         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
381         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
382         */
383        long multiplyByPowerOf10(long uDecimal, int n);
384
385        /**
386         * Returns an unscaled decimal whose value is the quotient of the specified arguments:
387         * {@code (uDecimalDividend / uDecimalDivisor)}. If rounding must be performed, this arithmetic's
388         * {@link #getRoundingMode() rounding mode} is applied.
389         * <p>
390         * Mathematically the method calculates <code>round((uDecimalDividend * 10<sup>scale</sup>) / uDecimalDivisor)</code>
391         * avoiding information loss due to overflow of intermediary results.
392         * 
393         * @param uDecimalDividend
394         *            value to be divided.
395         * @param uDecimalDivisor
396         *            value by which the dividend is to be divided.
397         * @return {@code round(uDecimalDividend / uDecimalDivisor)}
398         * @throws ArithmeticException
399         *             if {@code uDecimalDividend} is zero, if {@link #getRoundingMode() rounding mode} is UNNECESSARY and
400         *             rounding is necessary or if an overflow occurs and the {@link #getOverflowMode() overflow mode} is
401         *             set to throw an exception
402         */
403        long divide(long uDecimalDividend, long uDecimalDivisor);
404
405        /**
406         * Returns an unscaled decimal whose value is {@code (uDecimalDividend / lDivisor)} where the second argument is a
407         * true long value instead of an unscaled decimal. If rounding must be performed, this arithmetic's
408         * {@link #getRoundingMode() rounding mode} is applied.
409         * 
410         * @param uDecimalDividend
411         *            value to be divided.
412         * @param lDivisor
413         *            long value by which the dividend is to be divided.
414         * @return {@code round(uDecimalDividend / lDivisor)}
415         * @throws ArithmeticException
416         *             if {@code uDecimalDividend} is zero, if {@link #getRoundingMode() rounding mode} is UNNECESSARY and
417         *             rounding is necessary or if an overflow occurs and the {@link #getOverflowMode() overflow mode} is
418         *             set to throw an exception
419         */
420        long divideByLong(long uDecimalDividend, long lDivisor);
421
422        /**
423         * Returns an unscaled decimal whose value is <code>(uDecimal / (unscaled * 10<sup>-scale</sup>))</code>. If rounding
424         * must be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied. Note that scale of the
425         * first operand is determined by this arithmetic's {@link #getScale() scale} whereas the scale of the second
426         * {@code unscaled} value is explicitly specified by the {@code scale} argument.
427         * <p>
428         * Mathematically the method calculates <code>round((uDecimal * 10<sup>scale</sup>) / unscaled)</code> avoiding
429         * information loss due to overflow of intermediary results.
430         * 
431         * @param uDecimal
432         *            value to be divided.
433         * @param unscaled
434         *            unscaled value by which the dividend is to be divided.
435         * @param scale
436         *            scale associated with the {@code unscaled} value
437         * @return <code>round(uDecimal / (unscaled * 10<sup>-scale</sup>))</code>
438         * @throws ArithmeticException
439         *             if {@code uDecimal} is zero, if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding
440         *             is necessary or if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to
441         *             throw an exception
442         */
443        long divideByUnscaled(long uDecimal, long unscaled, int scale);
444
445        /**
446         * Returns an unscaled decimal whose value is <code>(uDecimal / 10<sup>n</sup>)</code>. If rounding must be performed,
447         * this arithmetic's {@link #getRoundingMode() rounding mode} is applied.
448         * <p>
449         * The power, {@code n}, may be negative, in which case this method performs a multiplication by a power of ten.
450         * 
451         * @param uDecimal
452         *            value to be divided.
453         * @param n
454         *            the power of ten
455         * @return <code>round(uDecimal / 10<sup>n</sup>)</code>
456         * @throws ArithmeticException
457         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
458         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
459         */
460        long divideByPowerOf10(long uDecimal, int n);
461
462        /**
463         * Returns an unscaled decimal whose value is the average of {@code uDecimal1} and {@code uDecimal2}. The method is
464         * much more efficient than an addition and subsequent long division and is guaranteed not to overflow. If rounding
465         * must be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied.
466         *
467         * @param uDecimal1
468         *            the first unscaled decimal value to average
469         * @param uDecimal2
470         *            the second unscaled decimal value to average
471         * @return {@code round((uDecimal1 + uDecimal2) / 2)}
472         * @throws ArithmeticException
473         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
474         */
475        long avg(long uDecimal1, long uDecimal2);
476
477        /**
478         * Returns an unscaled decimal whose value is {@code abs(uDecimal)}, which is the value itself if
479         * {@code uDecimal>=0} and {@code -uDecimal} if the given value is negative.
480         * 
481         * @param uDecimal
482         *            the unscaled decimal value
483         * @return {@code abs(uDecimal)}
484         * @throws ArithmeticException
485         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
486         */
487        long abs(long uDecimal);
488
489        /**
490         * Returns an unscaled decimal whose value is {@code -uDecimal}.
491         * 
492         * @param uDecimal
493         *            the unscaled decimal value to negate
494         * @return {@code -uDecimal}
495         * @throws ArithmeticException
496         *             if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
497         */
498        long negate(long uDecimal);
499
500        /**
501         * Returns an unscaled decimal whose value is the inverse of the argument: {@code 1/uDecimal}. If rounding must be
502         * performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied.
503         * <p>
504         * Mathematically the method calculates <code>round((10<sup>scale</sup> * 10<sup>scale</sup>) / uDecimalDivisor)</code>
505         * avoiding information loss due to overflow of intermediary results.
506         * 
507         * @param uDecimal
508         *            the unscaled decimal value to invert
509         * @return {@code round(1/uDecimal)}
510         * @throws ArithmeticException
511         *             if {@code uDecimal} is zero, if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding
512         *             is necessary or if an overflow occurs and the {@link #getOverflowMode() overflow mode} is set to
513         *             throw an exception
514         */
515        long invert(long uDecimal);
516
517        /**
518         * Returns an unscaled decimal whose value is the square of the specified argument: <code>uDecimal<sup>2</sup></code>.
519         * If rounding must be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied.
520         * <p>
521         * Mathematically the method calculates <code>round((uDecimal * uDecimal) * 10<sup>-scale</sup>)</code> avoiding
522         * information loss due to overflow of intermediary results.
523         * 
524         * @param uDecimal
525         *            the unscaled decimal value to be squared
526         * @return {@code round(uDecimal * uDecimal)}
527         * @throws ArithmeticException
528         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
529         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
530         */
531        long square(long uDecimal);
532
533        /**
534         * Returns an unscaled decimal whose value is the square root of the specified argument: <code>sqrt(uDecimal)</code>. If
535         * rounding must be performed, this arithmetic's {@link #getRoundingMode() rounding mode} is applied.
536         * <p>
537         * Mathematically the method calculates <code>round(sqrt(uDecimal * 10<sup>scale</sup>))</code> avoiding information
538         * loss due to overflow of intermediary results.
539         * 
540         * @param uDecimal
541         *            the unscaled decimal value
542         * @return {@code round(sqrt(uDecimal))}
543         * @throws ArithmeticException
544         *             if {@code uDecimal} is negative or if {@link #getRoundingMode() rounding mode} is UNNECESSARY and
545         *             rounding is necessary
546         */
547        long sqrt(long uDecimal);
548
549        /**
550         * Returns an unscaled decimal whose value is <code>(uDecimalBase<sup>exponent</sup>)</code>. Note that {@code exponent}
551         * is an integer rather than a decimal. If rounding must be performed, this arithmetic's {@link #getRoundingMode()
552         * rounding mode} is applied.
553         * <p>
554         * The current implementation uses the core algorithm defined in ANSI standard X3.274-1996. For {@code exponent >= 0}, the
555         * returned numerical value is within 1 ULP of the exact numerical value; the result is actually exact for all
556         * rounding modes other than HALF_UP, HALF_EVEN and HALF_DOWN. No precision is guaranteed for {@code exponent < 0} but the
557         * result is usually exact up to 10-20 ULP.
558         * <p>
559         * Properties of the X3.274-1996 algorithm are:
560         * <ul>
561         * <li>An {@code IllegalArgumentException} is thrown if {@code abs(n) > 999999999}</li>
562         * <li>if {@code exponent} is zero, one is returned even if {@code uDecimalBase} is zero, otherwise
563         * <ul>
564         * <li>if {@code exponent} is positive, the result is calculated via the repeated squaring technique into a single
565         * accumulator</li>
566         * <li>if {@code exponent} is negative, the result is calculated as if {@code exponent} were positive; this value is then divided
567         * into one</li>
568         * <li>The final value from either the positive or negative case is then rounded using this arithmetic's
569         * {@link #getRoundingMode() rounding mode}</li>
570         * </ul>
571         * </li>
572         * </ul>
573         * <p>
574         * Note: this operation is <b>not</b> strictly garbage free since internally, two {@link ThreadLocal} objects are
575         * used to calculate the result. The {@code ThreadLocal} values may become garbage if the thread becomes garbage.
576         * 
577         * @param uDecimalBase
578         *            the unscaled decimal base value
579         * @param exponent
580         *            exponent to which {@code uDecimalBase} is to be raised.
581         * @return <code>uDecimalBase<sup>exponent</sup></code>
582         * @throws IllegalArgumentException
583         *             if {@code abs(exponent) > 999999999}
584         * @throws ArithmeticException
585         *             if {@code uDecimalBase==0} and {@code exponent} is negative. (This would cause a division by zero.),
586         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
587         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
588         */
589        long pow(long uDecimalBase, int exponent);
590
591        /**
592         * Returns an unscaled decimal whose value is {@code (uDecimal << n)}. The shift distance, {@code n}, may be
593         * negative, in which case this method performs a right shift. The result is equal to
594         * <code>round(uDecimal * 2<sup>n</sup>)</code> using this arithmetic's {@link #getRoundingMode() rounding mode} if
595         * rounding is necessary.
596         * 
597         * @param uDecimal
598         *            the unscaled decimal value to shift
599         * @param n
600         *            shift distance, in bits.
601         * @return {@code round(uDecimal << n)}
602         * @throws ArithmeticException
603         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
604         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
605         * @see #shiftRight(long, int)
606         */
607        long shiftLeft(long uDecimal, int n);
608
609        /**
610         * Returns an unscaled decimal whose value is {@code (uDecimal >> n)}. The shift distance, {@code n}, may be
611         * negative, in which case this method performs a left shift. The result is equal to
612         * <code>round(uDecimal / 2<sup>n</sup>)</code> using this arithmetic's {@link #getRoundingMode() rounding mode} if
613         * rounding is necessary.
614         * 
615         * @param uDecimal
616         *            the unscaled decimal value to shift
617         * @param n
618         *            shift distance, in bits.
619         * @return {@code round(uDecimal >> n)}
620         * @throws ArithmeticException
621         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
622         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
623         * @see #shiftLeft(long, int)
624         */
625        long shiftRight(long uDecimal, int n);
626
627        /**
628         * Returns an unscaled decimal whose value is rounded to the specified {@code precision} using the
629         * {@link #getRoundingMode() rounding mode} of this arithmetic.
630         * <p>
631         * Note that this method does not change the scale of the value --- extra digits are simply zeroised.
632         * <p>
633         * <i>Examples and special cases:</i>
634         * <ul>
635         * <li><b>precision = 0</b><br>
636         * value is rounded to an integer value</li>
637         * <li><b>precision = 2</b><br>
638         * value is rounded to the second digit after the decimal point</li>
639         * <li><b>precision = -3</b><br>
640         * value is rounded to the thousands</li>
641         * <li><b>precision &ge; scale</b><br>
642         * values is returned unchanged</li>
643         * <li><b>precision &lt; scale - 18</b><br>
644         * {@code IllegalArgumentException} is thrown</li>
645         * </ul>
646         * 
647         * @param uDecimal
648         *            the unscaled decimal value to round
649         * @param precision
650         *            the precision to use for the rounding, for instance 2 to round to the second digit after the decimal
651         *            point; must be at least {@code (scale - 18)}
652         * @return an unsigned decimal rounded to the given precision
653         * @throws IllegalArgumentException
654         *             if {@code precision < scale - 18}
655         * @throws ArithmeticException
656         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary or if an
657         *             overflow occurs and the {@link #getOverflowMode() overflow mode} is set to throw an exception
658         */
659        long round(long uDecimal, int precision);
660
661        /**
662         * Converts the specified long value to an unscaled decimal. An exception is thrown if the specified value is too
663         * large to be represented as a Decimal of this arithmetic's {@link #getScale() scale}.
664         * 
665         * @param value
666         *            the value to convert
667         * @return the unscaled decimal representing the same value as the given long value
668         * @throws IllegalArgumentException
669         *             if {@code value} is too large to be represented as a Decimal with the scale of this arithmetic
670         */
671        long fromLong(long value);
672
673        /**
674         * Converts the specified float value to an unscaled decimal. An exception is thrown if the specified value is too
675         * large to be represented as a Decimal of this arithmetic's {@link #getScale() scale}.
676         * 
677         * @param value
678         *            the value to convert
679         * @return the unscaled decimal representing the same value as the given float value
680         * @throws IllegalArgumentException
681         *             if {@code value} is NaN or infinite or if the magnitude is too large for the float to be represented
682         *             as a {@code Decimal} with the scale of this arithmetic
683         * @throws ArithmeticException
684         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
685         */
686        long fromFloat(float value);
687
688        /**
689         * Converts the specified double value to an unscaled decimal. An exception is thrown if the specified value is too
690         * large to be represented as a Decimal of this arithmetic's {@link #getScale() scale}.
691         * 
692         * @param value
693         *            the value to convert
694         * @return the unscaled decimal representing the same value as the given double value
695         * @throws IllegalArgumentException
696         *             if {@code value} is NaN or infinite or if the magnitude is too large for the double to be represented
697         *             as a {@code Decimal} with the scale of this arithmetic
698         * @throws ArithmeticException
699         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
700         */
701        long fromDouble(double value);
702
703        /**
704         * Converts the specified {@link BigInteger} value to an unscaled decimal. An exception is thrown if the specified
705         * value is too large to be represented as a Decimal of this arithmetic's {@link #getScale() scale}.
706         * 
707         * @param value
708         *            the value to convert
709         * @return the unscaled decimal representing the same value as the given big integer value
710         * @throws IllegalArgumentException
711         *             if {@code value} is too large to be represented as a Decimal with the scale of this arithmetic
712         */
713        long fromBigInteger(BigInteger value);
714
715        /**
716         * Converts the specified {@link BigDecimal} value to an unscaled decimal. An exception is thrown if the specified
717         * value is too large to be represented as a Decimal of this arithmetic's {@link #getScale() scale}.
718         * <p>
719         * Note: this operation is <b>not</b> garbage free, meaning that new temporary objects may be allocated during the
720         * conversion.
721         * 
722         * @param value
723         *            the value to convert
724         * @return the unscaled decimal representing the same value as the given big decimal value
725         * @throws IllegalArgumentException
726         *             if {@code value} is too large to be represented as a Decimal with the scale of this arithmetic
727         * @throws ArithmeticException
728         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
729         */
730        long fromBigDecimal(BigDecimal value);
731
732        /**
733         * Converts the specified unscaled decimal with the given scale to another unscaled decimal of the scale of this
734         * arithmetic.
735         * 
736         * @param unscaledValue
737         *            the unscaled decimal value to convert
738         * @param scale
739         *            the scale associated with {@code unscaledValue}
740         * @return the unscaled decimal representing the same value as the given unscaled decimal with the new scale defined
741         *         by this arithmetic
742         * @throws IllegalArgumentException
743         *             if the unscaled value with the specified scale is too large to be represented as a Decimal with the
744         *             scale of this arithmetic
745         * @throws ArithmeticException
746         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
747         */
748        long fromUnscaled(long unscaledValue, int scale);
749
750        /**
751         * Translates the string representation of a {@code Decimal} into an unscaled Decimal. The string representation
752         * consists of an optional sign, {@code '+'} or {@code '-'} , followed by a sequence of zero or more decimal digits
753         * ("the integer"), optionally followed by a fraction.
754         * <p>
755         * The fraction consists of a decimal point followed by zero or more decimal digits. The string must contain at
756         * least one digit in either the integer or the fraction. If the fraction contains more digits than this
757         * arithmetic's {@link #getScale() scale}, the value is rounded using the arithmetic's {@link #getRoundingMode()
758         * rounding mode}. An exception is thrown if the value is too large to be represented as a Decimal of this
759         * arithmetic's scale.
760         * 
761         * @param value
762         *            a {@code String} containing the decimal value representation to be parsed
763         * @return the decimal as unscaled {@code long} value
764         * @throws NumberFormatException
765         *             if {@code value} does not represent a valid {@code Decimal} or if the value is too large to be
766         *             represented as a Decimal with the scale of this arithmetic
767         * @throws ArithmeticException
768         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
769         */
770        long parse(String value);
771
772        /**
773         * Translates the string representation of a {@code Decimal} into an unscaled Decimal. The string representation
774         * consists of an optional sign, {@code '+'} or {@code '-'} , followed by a sequence of zero or more decimal digits
775         * ("the integer"), optionally followed by a fraction.
776         * <p>
777         * The fraction consists of a decimal point followed by zero or more decimal digits. The string must contain at
778         * least one digit in either the integer or the fraction. If the fraction contains more digits than this
779         * arithmetic's {@link #getScale() scale}, the value is rounded using the arithmetic's {@link #getRoundingMode()
780         * rounding mode}. An exception is thrown if the value is too large to be represented as a Decimal of this
781         * arithmetic's scale.
782         * 
783         * @param value
784         *            a character sequence such as a {@code String} containing the decimal value representation to be parsed
785         * @param start
786         *            the start index to read characters in {@code value}, inclusive
787         * @param end
788         *            the end index where to stop reading in characters in {@code value}, exclusive
789         * @return the decimal as unscaled {@code long} value
790         * @throws IndexOutOfBoundsException
791         *             if {@code start < 0} or {@code end > value.length()}
792         * @throws NumberFormatException
793         *             if {@code value} does not represent a valid {@code Decimal} or if the value is too large to be
794         *             represented as a Decimal with the scale of this arithmetic
795         * @throws ArithmeticException
796         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
797         */
798        long parse(CharSequence value, int start, int end);
799
800        /**
801         * Converts the specified unscaled decimal value into a long value and returns it. The arithmetic's
802         * {@link #getRoundingMode() rounding mode} is applied if rounding is necessary.
803         * 
804         * @param uDecimal
805         *            the unscaled decimal value to convert into a long value
806         * @return the {@code uDecimal} value converted into a long value, possibly rounded or truncated
807         * @throws ArithmeticException
808         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
809         */
810        long toLong(long uDecimal);
811
812        /**
813         * Converts the specified unscaled decimal value into an unscaled value of the given scale. The arithmetic's
814         * {@link #getRoundingMode() rounding mode} is applied if rounding is necessary.
815         * 
816         * @param uDecimal
817         *            the unscaled decimal value to convert into an unscaled value of the specified scale
818         * @param scale
819         *            the target scale for the result value
820         * @return the {@code uDecimal} value converted into an unscaled value of the specified scale, possibly rounded or
821         *         truncated
822         * @throws IllegalArgumentException
823         *             if the unscaled value with this arithmetic's scale is too large to be represented as an unscaled
824         *             decimal with the specified scale
825         * @throws ArithmeticException
826         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
827         */
828        long toUnscaled(long uDecimal, int scale);
829
830        /**
831         * Converts the specified unscaled decimal value into a float value and returns it. The arithmetic's
832         * {@link #getRoundingMode() rounding mode} is applied if rounding is necessary.
833         * 
834         * @param uDecimal
835         *            the unscaled decimal value to convert into a float value
836         * @return the {@code uDecimal} value converted into a float value, possibly rounded or truncated
837         * @throws ArithmeticException
838         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
839         */
840        float toFloat(long uDecimal);
841
842        /**
843         * Converts the specified unscaled decimal value into a double value and returns it. The arithmetic's
844         * {@link #getRoundingMode() rounding mode} is applied if rounding is necessary.
845         * 
846         * @param uDecimal
847         *            the unscaled decimal value to convert into a double value
848         * @return the {@code uDecimal} value converted into a double value, possibly rounded or truncated
849         * @throws ArithmeticException
850         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
851         */
852        double toDouble(long uDecimal);
853
854        /**
855         * Converts the specified unscaled decimal value into a {@link BigDecimal} value using this arithmetic's
856         * {@link #getScale() scale} for the result value.
857         * <p>
858         * Note: this operation is <b>not</b> strictly garbage free since the result value is usually allocated; however no
859         * temporary objects other than the result are allocated during the conversion.
860         * 
861         * @param uDecimal
862         *            the unscaled decimal value to convert into a {@code BigDecimal} value
863         * @return the {@code uDecimal} value converted into a {@code BigDecimal} value
864         */
865        BigDecimal toBigDecimal(long uDecimal);
866
867        /**
868         * Converts the specified unscaled decimal value into a {@link BigDecimal} value using the specified {@code scale}
869         * for the result value. The arithmetic's {@link #getRoundingMode() rounding mode} is applied if rounding is
870         * necessary.
871         * <p>
872         * Note: this operation is <b>not</b> garbage free since the result value is usually allocated and also temporary
873         * objects may be allocated during the conversion. Note however that temporary objects are only allocated if the
874         * unscaled value of the result exceeds the range of a long value.
875         * 
876         * @param uDecimal
877         *            the unscaled decimal value to convert into a {@code BigDecimal} value
878         * @param scale
879         *            the scale to use for the resulting {@code BigDecimal} value
880         * @return the {@code uDecimal} value converted into a {@code BigDecimal} value, possibly rounded or truncated
881         * @throws ArithmeticException
882         *             if {@link #getRoundingMode() rounding mode} is UNNECESSARY and rounding is necessary
883         */
884        BigDecimal toBigDecimal(long uDecimal, int scale);
885
886        /**
887         * Converts the specified unscaled decimal value into a {@link String} and returns it. If the {@link #getScale()
888         * scale} is zero, the conversion is identical to {@link Long#toString(long)}. For all other scales a value with
889         * exactly {@code scale} fraction digits is returned even if some trailing fraction digits are zero.
890         * <p>
891         * Note: this operation is <b>not</b> strictly garbage free since the result value is allocated; however no
892         * temporary objects other than the result are allocated during the conversion (internally a {@link ThreadLocal}
893         * {@link StringBuilder} object is used to construct the string value, which may become garbage if the thread
894         * becomes garbage).
895         * 
896         * @param uDecimal
897         *            the unscaled decimal value to convert into a {@code String}
898         * @return the {@code uDecimal} value as into a {@code String}
899         */
900        String toString(long uDecimal);
901
902        /**
903         * Converts the specified unscaled decimal value into a {@link String} and appends the string to the
904         * {@code appendable}.
905         * <p>
906         * If the {@link #getScale() scale} is zero, the conversion into a string is identical to
907         * {@link Long#toString(long)}. For all other scales a string value with exactly {@code scale} fraction digits is
908         * created even if some trailing fraction digits are zero.
909         * <p>
910         * Note: this operation is <b>not</b> strictly garbage free since internally, a {@link ThreadLocal} string builder
911         * is used to construct the string. The {@code ThreadLocal} value may become garbage if the thread becomes garbage.
912         * 
913         * @param uDecimal
914         *            the unscaled decimal value to convert into a {@code String}
915         * @param appendable
916         *            the appendable to which the string representation of the unscaled decimal value is to be appended
917         * @throws IOException
918         *             If an I/O error occurs when appending to {@code appendable}
919         */
920        void toString(long uDecimal, Appendable appendable) throws IOException;
921}