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 org.decimal4j.api.DecimalArithmetic;
027import org.decimal4j.scale.Scale18f;
028import org.decimal4j.scale.ScaleMetrics;
029import org.decimal4j.scale.Scales;
030import org.decimal4j.truncate.DecimalRounding;
031import org.decimal4j.truncate.TruncatedPart;
032
033/**
034 * Contains methods for multiplications and divisions with powers of ten.
035 */
036final class Pow10 {
037
038        /**
039         * Calculates the multiple by a power of 10 truncating the result if
040         * necessary for negative {@code n}. Overflows are silently truncated.
041         * 
042         * @param uDecimal
043         *            the value to multiply
044         * @param n
045         *            the power-ten exponent
046         * @return <code>round<sub>DOWN</sub>(uDecimal * 10<sup>n</sup>)</code>
047         */
048        public static final long multiplyByPowerOf10(final long uDecimal, final int n) {
049                if (uDecimal == 0 | n == 0) {
050                        return uDecimal;
051                }
052                if (n > 0) {
053                        int pos = n;
054                        long result = uDecimal;
055                        // NOTE: result will be 0 after at most 1+64/18 rounds
056                        // because 10^64 contains 2^64 which is a shift left by 64
057                        while (pos > 18) {
058                                result = Scale18f.INSTANCE.multiplyByScaleFactor(result);
059                                if (result == 0) {
060                                        return 0;
061                                }
062                                pos -= 18;
063                        }
064                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(pos);
065                        return scaleMetrics.multiplyByScaleFactor(result);
066                } else {
067                        if (n >= -18) {
068                                final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
069                                return scaleMetrics.divideByScaleFactor(uDecimal);
070                        }
071                        // truncated result is 0
072                        return 0;
073                }
074        }
075
076        /**
077         * Calculates the multiple by a power of 10 rounding the result if necessary
078         * for negative {@code n}. Overflows are silently truncated.
079         * 
080         * @param rounding
081         *            the rounding to apply if necessary
082         * @param uDecimal
083         *            the value to multiply
084         * @param n
085         *            the power-ten exponent
086         * @return <code>round(uDecimal * 10<sup>n</sup>)</code>
087         */
088        public static final long multiplyByPowerOf10(final DecimalRounding rounding, final long uDecimal, final int n) {
089                if (uDecimal == 0 | n == 0) {
090                        return uDecimal;
091                }
092                if (n > 0) {
093                        int pos = n;
094                        long result = uDecimal;
095                        // NOTE: result will be 0 after at most 1+64/18 rounds
096                        // because 10^64 contains 2^64 which is a shift left by 64
097                        while (pos > 18) {
098                                result = Scale18f.INSTANCE.multiplyByScaleFactor(result);
099                                if (result == 0) {
100                                        return 0;
101                                }
102                                pos -= 18;
103                        }
104                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(pos);
105                        return scaleMetrics.multiplyByScaleFactor(result);
106                } else {
107                        if (n >= -18) {
108                                final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
109                                final long truncated = scaleMetrics.divideByScaleFactor(uDecimal);
110                                final long rem = uDecimal - scaleMetrics.multiplyByScaleFactor(truncated);
111                                final long inc = Rounding.calculateRoundingIncrement(rounding, truncated, rem,
112                                                scaleMetrics.getScaleFactor());
113                                return truncated + inc;
114                        } else if (n == -19) {
115                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
116                                                Rounding.truncatedPartForScale19(uDecimal));
117                        }
118                        // truncated part is always larger 0 (see first if)
119                        // and less than 0.5 because abs(Long.MIN_VALUE) / 10^20 < 0.5
120                        return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
121                                        TruncatedPart.LESS_THAN_HALF_BUT_NOT_ZERO);
122                }
123        }
124
125        /**
126         * Calculates the multiple by a power of 10 truncating the result if
127         * necessary for negative {@code n}. An exception is thrown if an overflow
128         * occurs.
129         * 
130         * @param arith
131         *            the arithmetic associated with the value
132         * @param uDecimal
133         *            the value to multiply
134         * @param n
135         *            the power-ten exponent
136         * @return <code>round<sub>DOWN</sub>(uDecimal * 10<sup>n</sup>)</code>
137         * @throws ArithmeticException
138         *             if an overflow occurs and the arithmetic's
139         *             {@code OverflowMode} is set to throw an exception
140         */
141        public static final long multiplyByPowerOf10Checked(final DecimalArithmetic arith, final long uDecimal, final int n) {
142                if (uDecimal == 0 | n == 0) {
143                        return uDecimal;
144                }
145
146                if (n > 0) {
147                        if (n > 18) {
148                                throw new ArithmeticException("Overflow: " + arith.toString(uDecimal) + " * 10^" + n);
149                        }
150
151                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
152                        return scaleMetrics.multiplyByScaleFactorExact(uDecimal);
153                } else {
154                        if (n >= -18) {
155                                final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
156                                return scaleMetrics.divideByScaleFactor(uDecimal);
157                        }
158                        return 0;
159                }
160        }
161
162        /**
163         * Calculates the multiple by a power of 10 rounding the result if necessary
164         * for negative {@code n}. An exception is thrown if an overflow occurs.
165         * 
166         * @param arith
167         *            the arithmetic associated with the value
168         * @param rounding
169         *            the rounding to apply if necessary
170         * @param uDecimal
171         *            the value to multiply
172         * @param n
173         *            the power-ten exponent
174         * @return <code>round(uDecimal * 10<sup>n</sup>)</code>
175         * @throws ArithmeticException
176         *             if an overflow occurs and the arithmetic's
177         *             {@code OverflowMode} is set to throw an exception
178         */
179        public static final long multiplyByPowerOf10Checked(final DecimalArithmetic arith, final DecimalRounding rounding, final long uDecimal, final int n) {
180                if (uDecimal == 0 | n == 0) {
181                        return uDecimal;
182                }
183
184                if (rounding == DecimalRounding.DOWN) {
185                        return multiplyByPowerOf10Checked(arith, uDecimal, Math.abs(n));
186                }
187
188                if (n > 0) {
189                        if (n > 18) {
190                                throw new ArithmeticException("Overflow: " + arith.toString(uDecimal) + " * 10^" + n);
191                        }
192
193                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
194                        return scaleMetrics.multiplyByScaleFactorExact(uDecimal);
195                } else {
196                        if (n >= -18) {
197                                final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
198                                final long truncated = scaleMetrics.divideByScaleFactor(uDecimal);
199                                final long rem = uDecimal - scaleMetrics.multiplyByScaleFactor(truncated);
200                                final long inc = Rounding.calculateRoundingIncrement(rounding, truncated, rem,
201                                                scaleMetrics.getScaleFactor());
202                                return truncated + inc;
203                        } else if (n == -19) {
204                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
205                                                Rounding.truncatedPartForScale19(uDecimal));
206                        }
207                        // truncated part is always larger 0 (see first if)
208                        // and less than 0.5 because abs(Long.MIN_VALUE) / 10^20 < 0.5
209                        return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
210                                        TruncatedPart.LESS_THAN_HALF_BUT_NOT_ZERO);
211                }
212        }
213
214        /**
215         * Divides the given value by a power of 10 truncating the result if
216         * necessary. Overflows are silently truncated.
217         * 
218         * @param uDecimal
219         *            the value to divide
220         * @param n
221         *            the power-ten exponent
222         * @return <code>round<sub>DOWN</sub>(uDecimal / 10<sup>n</sup>)</code>
223         */
224        public static final long divideByPowerOf10(final long uDecimal, final int n) {
225                if (uDecimal == 0 | n == 0) {
226                        return uDecimal;
227                }
228
229                if (n > 0) {
230                        if (n > 18) {
231                                return 0; // truncated result is 0
232                        }
233
234                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
235                        return scaleMetrics.divideByScaleFactor(uDecimal);
236                } else {
237                        int pos = n;
238                        long result = uDecimal;
239                        // NOTE: result will be 0 after at most 1+64/18 rounds
240                        // because 10^64 contains 2^64 which is a shift left by 64
241                        while (pos < -18) {
242                                result = Scale18f.INSTANCE.multiplyByScaleFactor(result);
243                                if (result == 0) {
244                                        return 0;
245                                }
246                                pos += 18;
247                        }
248                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-pos);
249                        return scaleMetrics.multiplyByScaleFactor(result);
250                }
251        }
252
253        /**
254         * Divides the given value by a power of 10 rounding the result if
255         * necessary. Overflows are silently truncated.
256         * 
257         * @param rounding
258         *            the rounding to apply if necessary
259         * @param uDecimal
260         *            the value to divide
261         * @param n
262         *            the power-ten exponent
263         * @return <code>round(uDecimal / 10<sup>n</sup>)</code>
264         */
265        public static final long divideByPowerOf10(final DecimalRounding rounding, final long uDecimal, final int n) {
266                if (uDecimal == 0 | n == 0) {
267                        return uDecimal;
268                }
269
270                if (rounding == DecimalRounding.DOWN) {
271                        return divideByPowerOf10(uDecimal, n);
272                }
273
274                if (n > 0) {
275                        if (n > 19) {
276                                // truncated part is always larger 0 (see first if)
277                                // and less than 0.5 because abs(Long.MIN_VALUE) / 10^20 < 0.5
278                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
279                                                TruncatedPart.LESS_THAN_HALF_BUT_NOT_ZERO);
280                        } else if (n == 19) {
281                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
282                                                Rounding.truncatedPartForScale19(uDecimal));
283                        }
284
285                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
286                        final long truncated = scaleMetrics.divideByScaleFactor(uDecimal);
287                        final long rem = uDecimal - scaleMetrics.multiplyByScaleFactor(truncated);
288                        final long inc = Rounding.calculateRoundingIncrement(rounding, truncated, rem,
289                                        scaleMetrics.getScaleFactor());
290                        return truncated + inc;
291                } else {
292                        int pos = n;
293                        long result = uDecimal;
294                        // NOTE: result will be 0 after at most 1+64/18 rounds
295                        // because 10^64 contains 2^64 which is a shift left by 64
296                        while (pos < -18) {
297                                result = Scale18f.INSTANCE.multiplyByScaleFactor(result);
298                                if (result == 0) {
299                                        return 0;
300                                }
301                                pos += 18;
302                        }
303                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-pos);
304                        return scaleMetrics.multiplyByScaleFactor(result);
305                }
306        }
307
308        /**
309         * Divides the given value by a power of 10 truncating the result if
310         * necessary. An exception is thrown if an overflow occurs.
311         * 
312         * @param arith
313         *            the arithmetic associated with the value
314         * @param uDecimal
315         *            the value to divide
316         * @param n
317         *            the power-ten exponent
318         * @return <code>round<sub>DOWN</sub>(uDecimal / 10<sup>n</sup>)</code>
319         * @throws ArithmeticException
320         *             if an overflow occurs and the arithmetic's
321         *             {@code OverflowMode} is set to throw an exception
322         */
323        public static final long divideByPowerOf10Checked(final DecimalArithmetic arith, final long uDecimal, final int n) {
324                if (uDecimal == 0 | n == 0) {
325                        return uDecimal;
326                }
327
328                if (n > 0) {
329                        if (n > 18) {
330                                return 0;
331                        }
332
333                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
334                        return scaleMetrics.divideByScaleFactor(uDecimal);
335                } else {
336                        if (n >= -18) {
337                                final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
338                                return scaleMetrics.multiplyByScaleFactorExact(uDecimal);
339                        }
340                        throw new ArithmeticException("Overflow: " + arith.toString(uDecimal) + " / 10^" + n);
341                }
342        }
343
344        /**
345         * Divides the given value by a power of 10 rounding the result if
346         * necessary. An exception is thrown if an overflow occurs.
347         * 
348         * @param arith
349         *            the arithmetic associated with the value
350         * @param rounding
351         *            the rounding to apply if necessary
352         * @param uDecimal
353         *            the value to divide
354         * @param n
355         *            the power-ten exponent
356         * @return <code>round(uDecimal / 10<sup>n</sup>)</code>
357         * @throws ArithmeticException
358         *             if an overflow occurs and the arithmetic's
359         *             {@code OverflowMode} is set to throw an exception
360         */
361        public static final long divideByPowerOf10Checked(final DecimalArithmetic arith, final DecimalRounding rounding, final long uDecimal, final int n) {
362                if (uDecimal == 0 | n == 0) {
363                        return uDecimal;
364                }
365
366                if (rounding == DecimalRounding.DOWN) {
367                        return divideByPowerOf10Checked(arith, uDecimal, Math.abs(n));
368                }
369
370                if (n > 0) {
371                        if (n > 19) {
372                                // truncated part is always larger 0 (see first if)
373                                // and less than 0.5 because abs(Long.MIN_VALUE) / 10^20 < 0.5
374                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
375                                                TruncatedPart.LESS_THAN_HALF_BUT_NOT_ZERO);
376                        } else if (n == 19) {
377                                return rounding.calculateRoundingIncrement(Long.signum(uDecimal), 0,
378                                                Rounding.truncatedPartForScale19(uDecimal));
379                        }
380
381                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(n);
382                        final long truncated = scaleMetrics.divideByScaleFactor(uDecimal);
383                        final long rem = uDecimal - scaleMetrics.multiplyByScaleFactor(truncated);
384                        final long inc = Rounding.calculateRoundingIncrement(rounding, truncated, rem,
385                                        scaleMetrics.getScaleFactor());
386                        return truncated + inc;
387                } else {
388                        if (n < -18) {
389                                throw new ArithmeticException("Overflow: " + arith.toString(uDecimal) + " / 10^" + n);
390                        }
391
392                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-n);
393                        return scaleMetrics.multiplyByScaleFactorExact(uDecimal);
394                }
395        }
396
397        /**
398         * Divides the specified dividend by a power of ten truncating the result if
399         * necessary. Overflows are silently truncated.
400         * 
401         * @param uDecimalDividend
402         *            the dividend to divide
403         * @param dividendMetrics
404         *            the arithmetics associated with the dividend
405         * @param pow10divisorIsPositive
406         *            true if the divisor is positive
407         * @param pow10divisorMetrics
408         *            the metrics reflecting the power-ten-division
409         * @return <code>round<sub>DOWN</sub>(uDecimalDividend / 10<sup>(scale - scale10)</sup>)</code>
410         *         where scale is the {@code scale} of the dividend and
411         *         {@code scale10} is the exponent of the power-ten divisor (negated
412         *         if {@code pow10divisorIsPositive==false})
413         */
414        static final long divideByPowerOf10(final long uDecimalDividend, final ScaleMetrics dividendMetrics, final boolean pow10divisorIsPositive, final ScaleMetrics pow10divisorMetrics) {
415                final int scaleDiff = dividendMetrics.getScale() - pow10divisorMetrics.getScale();
416                final long quot;
417                if (scaleDiff <= 0) {
418                        // divide
419                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-scaleDiff);
420                        quot = scaleMetrics.divideByScaleFactor(uDecimalDividend);
421
422                } else {
423                        // multiply
424                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(scaleDiff);
425                        quot = scaleMetrics.multiplyByScaleFactor(uDecimalDividend);
426                }
427                return pow10divisorIsPositive ? quot : -quot;
428        }
429
430        /**
431         * Divides the specified dividend by a power of ten rounding the result if
432         * necessary. Overflows are silently truncated.
433         * 
434         * @param rounding
435         *            the rounding to apply if rounding is necessary
436         * @param uDecimalDividend
437         *            the dividend to divide
438         * @param dividendMetrics
439         *            the arithmetics associated with the dividend
440         * @param pow10divisorIsPositive
441         *            true if the divisor is positive
442         * @param pow10divisorMetrics
443         *            the metrics reflecting the power-ten-division
444         * @return <code>round(uDecimalDividend / 10<sup>(scale - scale10)</sup>)</code>
445         *         where scale is the {@code scale} of the dividend and
446         *         {@code scale10} is the exponent of the power-ten divisor (negated
447         *         if {@code pow10divisorIsPositive==false})
448         */
449        static final long divideByPowerOf10(final DecimalRounding rounding, final long uDecimalDividend, final ScaleMetrics dividendMetrics, final boolean pow10divisorIsPositive, final ScaleMetrics pow10divisorMetrics) {
450                final int scaleDiff = dividendMetrics.getScale() - pow10divisorMetrics.getScale();
451                if (scaleDiff <= 0) {
452                        // divide
453                        final ScaleMetrics scaler = Scales.getScaleMetrics(-scaleDiff);
454                        final long truncatedValue = scaler.divideByScaleFactor(uDecimalDividend);
455                        final long truncatedDigits = uDecimalDividend - scaler.multiplyByScaleFactor(truncatedValue);
456                        if (pow10divisorIsPositive) {
457                                return truncatedValue + Rounding.calculateRoundingIncrementForDivision(rounding, truncatedValue,
458                                                truncatedDigits, scaler.getScaleFactor());
459                        }
460                        return -truncatedValue + Rounding.calculateRoundingIncrementForDivision(rounding, -truncatedValue,
461                                        -truncatedDigits, scaler.getScaleFactor());
462                } else {
463                        // multiply
464                        final ScaleMetrics scaler = Scales.getScaleMetrics(scaleDiff);
465                        final long quot = scaler.multiplyByScaleFactor(uDecimalDividend);
466                        return pow10divisorIsPositive ? quot : -quot;
467                }
468        }
469
470        /**
471         * Divides the specified dividend by a power of ten truncating the result if
472         * necessary. An exception is thrown if an overflow occurs.
473         * 
474         * @param arith
475         *            the arithmetic associated with the dividend value
476         * @param uDecimalDividend
477         *            the dividend to divide
478         * @param dividendMetrics
479         *            the arithmetics associated with the dividend
480         * @param pow10divisorIsPositive
481         *            true if the divisor is positive
482         * @param pow10divisorMetrics
483         *            the metrics reflecting the power-ten-division
484         * @return <code>round<sub>DOWN</sub>(uDecimalDividend / 10<sup>(scale - scale10)</sup>)</code>
485         *         where scale is the {@code scale} of the dividend and
486         *         {@code scale10} is the exponent of the power-ten divisor (negated
487         *         if {@code pow10divisorIsPositive==false})
488         * @throws ArithmeticException
489         *             if an overflow occurs and the arithmetic's
490         *             {@code OverflowMode} is set to throw an exception
491         */
492        static final long divideByPowerOf10Checked(final DecimalArithmetic arith, final long uDecimalDividend, final ScaleMetrics dividendMetrics, final boolean pow10divisorIsPositive, final ScaleMetrics pow10divisorMetrics) {
493                final int scaleDiff = dividendMetrics.getScale() - pow10divisorMetrics.getScale();
494                final long quot;
495                if (scaleDiff <= 0) {
496                        // divide
497                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-scaleDiff);
498                        quot = scaleMetrics.divideByScaleFactor(uDecimalDividend);
499                } else {
500                        // multiply
501                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(scaleDiff);
502                        quot = scaleMetrics.multiplyByScaleFactorExact(uDecimalDividend);
503                }
504                return pow10divisorIsPositive ? quot : arith.negate(quot);
505        }
506
507        /**
508         * Divides the specified dividend by a power of ten rounding the result if
509         * necessary. An exception is thrown if an overflow occurs.
510         * 
511         * @param arith
512         *            the arithmetic associated with the dividend value
513         * @param rounding
514         *            the rounding to apply if rounding is necessary
515         * @param uDecimalDividend
516         *            the dividend to divide
517         * @param dividendMetrics
518         *            the arithmetics associated with the dividend
519         * @param pow10divisorIsPositive
520         *            true if the divisor is positive
521         * @param pow10divisorMetrics
522         *            the metrics reflecting the power-ten-division
523         * @return <code>round(uDecimalDividend / 10<sup>(scale - scale10)</sup>)</code>
524         *         where scale is the {@code scale} of the dividend and
525         *         {@code scale10} is the exponent of the power-ten divisor (negated
526         *         if {@code pow10divisorIsPositive==false})
527         * @throws ArithmeticException
528         *             if an overflow occurs and the arithmetic's
529         *             {@code OverflowMode} is set to throw an exception
530         */
531        static final long divideByPowerOf10Checked(final DecimalArithmetic arith, final DecimalRounding rounding, final long uDecimalDividend, final ScaleMetrics dividendMetrics, final boolean pow10divisorIsPositive, final ScaleMetrics pow10divisorMetrics) {
532                final int scaleDiff = dividendMetrics.getScale() - pow10divisorMetrics.getScale();
533                final long quot;
534                if (scaleDiff <= 0) {
535                        // divide
536                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(-scaleDiff);
537                        quot = scaleMetrics.divideByScaleFactor(uDecimalDividend);
538
539                        final long truncatedDigits = uDecimalDividend - scaleMetrics.multiplyByScaleFactor(quot);
540                        if (pow10divisorIsPositive) {
541                                return quot + Rounding.calculateRoundingIncrementForDivision(rounding, quot, truncatedDigits,
542                                                scaleMetrics.getScaleFactor());
543                        }
544                        return -quot + Rounding.calculateRoundingIncrementForDivision(rounding, -quot, -truncatedDigits,
545                                        scaleMetrics.getScaleFactor());
546                } else {
547                        // multiply
548                        final ScaleMetrics scaleMetrics = Scales.getScaleMetrics(scaleDiff);
549                        quot = scaleMetrics.multiplyByScaleFactorExact(uDecimalDividend);
550                }
551                return pow10divisorIsPositive ? quot : arith.negate(quot);
552        }
553
554        // no instances
555        private Pow10() {
556        }
557
558}