001/*
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2024 decimal4j (tools4j), Marco Terzer
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in all
014 * copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022 * SOFTWARE.
023 */
024package org.decimal4j.exact;
025
026import java.util.Objects;
027
028import org.decimal4j.api.Decimal;
029import org.decimal4j.immutable.Decimal0f;
030import org.decimal4j.immutable.Decimal1f;
031import org.decimal4j.immutable.Decimal2f;
032import org.decimal4j.immutable.Decimal3f;
033import org.decimal4j.immutable.Decimal4f;
034import org.decimal4j.immutable.Decimal5f;
035import org.decimal4j.immutable.Decimal6f;
036import org.decimal4j.immutable.Decimal7f;
037import org.decimal4j.immutable.Decimal8f;
038import org.decimal4j.immutable.Decimal9f;
039import org.decimal4j.immutable.Decimal10f;
040import org.decimal4j.immutable.Decimal11f;
041import org.decimal4j.immutable.Decimal12f;
042import org.decimal4j.immutable.Decimal13f;
043import org.decimal4j.immutable.Decimal14f;
044import org.decimal4j.immutable.Decimal15f;
045import org.decimal4j.immutable.Decimal16f;
046import org.decimal4j.immutable.Decimal17f;
047import org.decimal4j.immutable.Decimal18f;
048import org.decimal4j.mutable.MutableDecimal0f;
049import org.decimal4j.mutable.MutableDecimal1f;
050import org.decimal4j.mutable.MutableDecimal2f;
051import org.decimal4j.mutable.MutableDecimal3f;
052import org.decimal4j.mutable.MutableDecimal4f;
053import org.decimal4j.mutable.MutableDecimal5f;
054import org.decimal4j.mutable.MutableDecimal6f;
055import org.decimal4j.mutable.MutableDecimal7f;
056import org.decimal4j.mutable.MutableDecimal8f;
057import org.decimal4j.scale.Scale9f;
058
059/**
060 * A {@code Multipliable9f} encapsulates a Decimal of scale 9 and facilitates
061 * exact typed multiplication. The multipliable object acts as first factor in the multiplication
062 * and provides a set of overloaded methods for different scales. Each one of those methods 
063 * delivers a different result scale which represents the appropriate scale for the product of
064 * an exact multiplication.
065 * <p>
066 * A {@code Multipliable9f} object is returned by {@link Decimal9f#multiplyExact()},
067 * hence an exact typed multiplication can be written as:
068 * <pre>
069 * Decimal9f value = ... //some value
070 * Decimal11f product = value.multiplyExact().by(Decimal2f.FIVE);
071 * </pre>
072 */
073public final class Multipliable9f {
074        
075        private final Decimal<Scale9f> value;
076        
077        /**
078         * Constructor with Decimal value to be encapsulated.
079         * @param value the decimal value to be wrapped as a multipliable object
080         */
081        public Multipliable9f(Decimal<Scale9f> value) {
082                this.value = Objects.requireNonNull(value, "value cannot be null");
083        }
084        
085        /**
086         * Returns the value underlying this Multipliable9f.
087         * @return the Decimal value wrapped by this multipliable object
088         */
089        public Decimal<Scale9f> getValue() {
090                return value;
091        }
092
093        /**
094         * Returns a {@code Decimal} whose value is <code>(this<sup>2</sup>)</code>. The
095         * result is exact and has scale 18 which is twice the scale of
096         * the Decimal that this multipliable object represents. An
097         * {@link ArithmeticException} is thrown if the product is out of the
098         * possible range for a {@code Decimal18f}.
099         * <p>
100         * Note that the result is <i>always</i> a new instance.
101         * 
102         * @return <code>(this * this)</code>
103         * @throws ArithmeticException
104         *             if an overflow occurs and product is out of the possible
105         *             range for a {@code Decimal18f}
106         */
107        public Decimal18f square() {
108                return by(this.value);
109        }
110
111        /**
112         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
113         * result is exact and has scale 18 which is the sum of the scales 
114         * of the Decimal that this multipliable object represents and the scale of
115         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
116         * product is out of the possible range for a {@code Decimal18f}.
117         * <p>
118         * Note that the result is <i>always</i> a new instance.
119         * 
120         * @param factor
121         *            the factor to multiply with the Decimal that this multipliable represents
122         * @return <code>(this * factor)</code>
123         * @throws ArithmeticException
124         *             if an overflow occurs and product is out of the possible
125         *             range for a {@code Decimal18f}
126         */
127        public Decimal18f by(Decimal<Scale9f> factor) {
128                return Decimal18f.valueOf(this.value.multiplyExact(factor));
129        }
130
131        /**
132         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
133         * result is exact and has scale 9 which is the sum of the scales 
134         * of the Decimal that this multipliable object represents and the scale of
135         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
136         * product is out of the possible range for a {@code Decimal9f}.
137         * <p>
138         * Note that the result is <i>always</i> a new instance.
139         * 
140         * @param factor
141         *            the factor to multiply with the Decimal that this multipliable represents
142         * @return <code>(this * factor)</code>
143         * @throws ArithmeticException
144         *             if an overflow occurs and product is out of the possible
145         *             range for a {@code Decimal9f}
146         */
147        public Decimal9f by(Decimal0f factor) {
148                return Decimal9f.valueOf(this.value.multiplyExact(factor));
149        }
150        /**
151         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
152         * result is exact and has scale 9 which is the sum of the scales 
153         * of the Decimal that this multipliable object represents and the scale of
154         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
155         * product is out of the possible range for a {@code Decimal9f}.
156         * <p>
157         * Note that the result is <i>always</i> a new instance.
158         * 
159         * @param factor
160         *            the factor to multiply with the Decimal that this multipliable represents
161         * @return <code>(this * factor)</code>
162         * @throws ArithmeticException
163         *             if an overflow occurs and product is out of the possible
164         *             range for a {@code Decimal9f}
165         */
166        public Decimal9f by(MutableDecimal0f factor) {
167                return Decimal9f.valueOf(this.value.multiplyExact(factor));
168        }
169
170        /**
171         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
172         * result is exact and has scale 10 which is the sum of the scales 
173         * of the Decimal that this multipliable object represents and the scale of
174         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
175         * product is out of the possible range for a {@code Decimal10f}.
176         * <p>
177         * Note that the result is <i>always</i> a new instance.
178         * 
179         * @param factor
180         *            the factor to multiply with the Decimal that this multipliable represents
181         * @return <code>(this * factor)</code>
182         * @throws ArithmeticException
183         *             if an overflow occurs and product is out of the possible
184         *             range for a {@code Decimal10f}
185         */
186        public Decimal10f by(Decimal1f factor) {
187                return Decimal10f.valueOf(this.value.multiplyExact(factor));
188        }
189        /**
190         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
191         * result is exact and has scale 10 which is the sum of the scales 
192         * of the Decimal that this multipliable object represents and the scale of
193         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
194         * product is out of the possible range for a {@code Decimal10f}.
195         * <p>
196         * Note that the result is <i>always</i> a new instance.
197         * 
198         * @param factor
199         *            the factor to multiply with the Decimal that this multipliable represents
200         * @return <code>(this * factor)</code>
201         * @throws ArithmeticException
202         *             if an overflow occurs and product is out of the possible
203         *             range for a {@code Decimal10f}
204         */
205        public Decimal10f by(MutableDecimal1f factor) {
206                return Decimal10f.valueOf(this.value.multiplyExact(factor));
207        }
208
209        /**
210         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
211         * result is exact and has scale 11 which is the sum of the scales 
212         * of the Decimal that this multipliable object represents and the scale of
213         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
214         * product is out of the possible range for a {@code Decimal11f}.
215         * <p>
216         * Note that the result is <i>always</i> a new instance.
217         * 
218         * @param factor
219         *            the factor to multiply with the Decimal that this multipliable represents
220         * @return <code>(this * factor)</code>
221         * @throws ArithmeticException
222         *             if an overflow occurs and product is out of the possible
223         *             range for a {@code Decimal11f}
224         */
225        public Decimal11f by(Decimal2f factor) {
226                return Decimal11f.valueOf(this.value.multiplyExact(factor));
227        }
228        /**
229         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
230         * result is exact and has scale 11 which is the sum of the scales 
231         * of the Decimal that this multipliable object represents and the scale of
232         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
233         * product is out of the possible range for a {@code Decimal11f}.
234         * <p>
235         * Note that the result is <i>always</i> a new instance.
236         * 
237         * @param factor
238         *            the factor to multiply with the Decimal that this multipliable represents
239         * @return <code>(this * factor)</code>
240         * @throws ArithmeticException
241         *             if an overflow occurs and product is out of the possible
242         *             range for a {@code Decimal11f}
243         */
244        public Decimal11f by(MutableDecimal2f factor) {
245                return Decimal11f.valueOf(this.value.multiplyExact(factor));
246        }
247
248        /**
249         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
250         * result is exact and has scale 12 which is the sum of the scales 
251         * of the Decimal that this multipliable object represents and the scale of
252         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
253         * product is out of the possible range for a {@code Decimal12f}.
254         * <p>
255         * Note that the result is <i>always</i> a new instance.
256         * 
257         * @param factor
258         *            the factor to multiply with the Decimal that this multipliable represents
259         * @return <code>(this * factor)</code>
260         * @throws ArithmeticException
261         *             if an overflow occurs and product is out of the possible
262         *             range for a {@code Decimal12f}
263         */
264        public Decimal12f by(Decimal3f factor) {
265                return Decimal12f.valueOf(this.value.multiplyExact(factor));
266        }
267        /**
268         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
269         * result is exact and has scale 12 which is the sum of the scales 
270         * of the Decimal that this multipliable object represents and the scale of
271         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
272         * product is out of the possible range for a {@code Decimal12f}.
273         * <p>
274         * Note that the result is <i>always</i> a new instance.
275         * 
276         * @param factor
277         *            the factor to multiply with the Decimal that this multipliable represents
278         * @return <code>(this * factor)</code>
279         * @throws ArithmeticException
280         *             if an overflow occurs and product is out of the possible
281         *             range for a {@code Decimal12f}
282         */
283        public Decimal12f by(MutableDecimal3f factor) {
284                return Decimal12f.valueOf(this.value.multiplyExact(factor));
285        }
286
287        /**
288         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
289         * result is exact and has scale 13 which is the sum of the scales 
290         * of the Decimal that this multipliable object represents and the scale of
291         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
292         * product is out of the possible range for a {@code Decimal13f}.
293         * <p>
294         * Note that the result is <i>always</i> a new instance.
295         * 
296         * @param factor
297         *            the factor to multiply with the Decimal that this multipliable represents
298         * @return <code>(this * factor)</code>
299         * @throws ArithmeticException
300         *             if an overflow occurs and product is out of the possible
301         *             range for a {@code Decimal13f}
302         */
303        public Decimal13f by(Decimal4f factor) {
304                return Decimal13f.valueOf(this.value.multiplyExact(factor));
305        }
306        /**
307         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
308         * result is exact and has scale 13 which is the sum of the scales 
309         * of the Decimal that this multipliable object represents and the scale of
310         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
311         * product is out of the possible range for a {@code Decimal13f}.
312         * <p>
313         * Note that the result is <i>always</i> a new instance.
314         * 
315         * @param factor
316         *            the factor to multiply with the Decimal that this multipliable represents
317         * @return <code>(this * factor)</code>
318         * @throws ArithmeticException
319         *             if an overflow occurs and product is out of the possible
320         *             range for a {@code Decimal13f}
321         */
322        public Decimal13f by(MutableDecimal4f factor) {
323                return Decimal13f.valueOf(this.value.multiplyExact(factor));
324        }
325
326        /**
327         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
328         * result is exact and has scale 14 which is the sum of the scales 
329         * of the Decimal that this multipliable object represents and the scale of
330         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
331         * product is out of the possible range for a {@code Decimal14f}.
332         * <p>
333         * Note that the result is <i>always</i> a new instance.
334         * 
335         * @param factor
336         *            the factor to multiply with the Decimal that this multipliable represents
337         * @return <code>(this * factor)</code>
338         * @throws ArithmeticException
339         *             if an overflow occurs and product is out of the possible
340         *             range for a {@code Decimal14f}
341         */
342        public Decimal14f by(Decimal5f factor) {
343                return Decimal14f.valueOf(this.value.multiplyExact(factor));
344        }
345        /**
346         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
347         * result is exact and has scale 14 which is the sum of the scales 
348         * of the Decimal that this multipliable object represents and the scale of
349         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
350         * product is out of the possible range for a {@code Decimal14f}.
351         * <p>
352         * Note that the result is <i>always</i> a new instance.
353         * 
354         * @param factor
355         *            the factor to multiply with the Decimal that this multipliable represents
356         * @return <code>(this * factor)</code>
357         * @throws ArithmeticException
358         *             if an overflow occurs and product is out of the possible
359         *             range for a {@code Decimal14f}
360         */
361        public Decimal14f by(MutableDecimal5f factor) {
362                return Decimal14f.valueOf(this.value.multiplyExact(factor));
363        }
364
365        /**
366         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
367         * result is exact and has scale 15 which is the sum of the scales 
368         * of the Decimal that this multipliable object represents and the scale of
369         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
370         * product is out of the possible range for a {@code Decimal15f}.
371         * <p>
372         * Note that the result is <i>always</i> a new instance.
373         * 
374         * @param factor
375         *            the factor to multiply with the Decimal that this multipliable represents
376         * @return <code>(this * factor)</code>
377         * @throws ArithmeticException
378         *             if an overflow occurs and product is out of the possible
379         *             range for a {@code Decimal15f}
380         */
381        public Decimal15f by(Decimal6f factor) {
382                return Decimal15f.valueOf(this.value.multiplyExact(factor));
383        }
384        /**
385         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
386         * result is exact and has scale 15 which is the sum of the scales 
387         * of the Decimal that this multipliable object represents and the scale of
388         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
389         * product is out of the possible range for a {@code Decimal15f}.
390         * <p>
391         * Note that the result is <i>always</i> a new instance.
392         * 
393         * @param factor
394         *            the factor to multiply with the Decimal that this multipliable represents
395         * @return <code>(this * factor)</code>
396         * @throws ArithmeticException
397         *             if an overflow occurs and product is out of the possible
398         *             range for a {@code Decimal15f}
399         */
400        public Decimal15f by(MutableDecimal6f factor) {
401                return Decimal15f.valueOf(this.value.multiplyExact(factor));
402        }
403
404        /**
405         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
406         * result is exact and has scale 16 which is the sum of the scales 
407         * of the Decimal that this multipliable object represents and the scale of
408         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
409         * product is out of the possible range for a {@code Decimal16f}.
410         * <p>
411         * Note that the result is <i>always</i> a new instance.
412         * 
413         * @param factor
414         *            the factor to multiply with the Decimal that this multipliable represents
415         * @return <code>(this * factor)</code>
416         * @throws ArithmeticException
417         *             if an overflow occurs and product is out of the possible
418         *             range for a {@code Decimal16f}
419         */
420        public Decimal16f by(Decimal7f factor) {
421                return Decimal16f.valueOf(this.value.multiplyExact(factor));
422        }
423        /**
424         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
425         * result is exact and has scale 16 which is the sum of the scales 
426         * of the Decimal that this multipliable object represents and the scale of
427         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
428         * product is out of the possible range for a {@code Decimal16f}.
429         * <p>
430         * Note that the result is <i>always</i> a new instance.
431         * 
432         * @param factor
433         *            the factor to multiply with the Decimal that this multipliable represents
434         * @return <code>(this * factor)</code>
435         * @throws ArithmeticException
436         *             if an overflow occurs and product is out of the possible
437         *             range for a {@code Decimal16f}
438         */
439        public Decimal16f by(MutableDecimal7f factor) {
440                return Decimal16f.valueOf(this.value.multiplyExact(factor));
441        }
442
443        /**
444         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
445         * result is exact and has scale 17 which is the sum of the scales 
446         * of the Decimal that this multipliable object represents and the scale of
447         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
448         * product is out of the possible range for a {@code Decimal17f}.
449         * <p>
450         * Note that the result is <i>always</i> a new instance.
451         * 
452         * @param factor
453         *            the factor to multiply with the Decimal that this multipliable represents
454         * @return <code>(this * factor)</code>
455         * @throws ArithmeticException
456         *             if an overflow occurs and product is out of the possible
457         *             range for a {@code Decimal17f}
458         */
459        public Decimal17f by(Decimal8f factor) {
460                return Decimal17f.valueOf(this.value.multiplyExact(factor));
461        }
462        /**
463         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
464         * result is exact and has scale 17 which is the sum of the scales 
465         * of the Decimal that this multipliable object represents and the scale of
466         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
467         * product is out of the possible range for a {@code Decimal17f}.
468         * <p>
469         * Note that the result is <i>always</i> a new instance.
470         * 
471         * @param factor
472         *            the factor to multiply with the Decimal that this multipliable represents
473         * @return <code>(this * factor)</code>
474         * @throws ArithmeticException
475         *             if an overflow occurs and product is out of the possible
476         *             range for a {@code Decimal17f}
477         */
478        public Decimal17f by(MutableDecimal8f factor) {
479                return Decimal17f.valueOf(this.value.multiplyExact(factor));
480        }
481
482        
483        /**
484         * Returns a hash code for this <code>Multipliable9f</code> which happens to be the
485         * hash code of the underlying {@code Decimal9f} value.
486         * 
487         * @return a hash code value for this object
488         * @see Decimal#hashCode()
489         */
490        @Override
491        public int hashCode() {
492                return value.hashCode();
493        }
494
495        /**
496         * Compares this Multipliable9f to the specified object. The result is {@code true}
497         * if and only if the argument is a {@code Multipliable9f} with an equal underlying 
498         * {@link #getValue() value}.
499         * 
500         * @param obj
501         *            the object to compare with
502         * @return {@code true} if the argument is a {@code Multipliable9f} and if its value
503         *         is equal to this multipliables's value; {@code false} otherwise
504         * @see #getValue()
505         * @see Decimal#equals(Object)
506         */
507        @Override
508        public boolean equals(Object obj) {
509                if (this == obj) return true;
510                if (obj == null) return false;
511                if (getClass() != obj.getClass()) return false;
512                return value.equals(((Multipliable9f)obj).value);
513        }
514
515        /**
516         * Returns a string representation of this {@code Multipliable9f} which is
517         * simply the string representation of the underlying Decimal {@link #getValue() value}.
518         * 
519         * @return a {@code String} Decimal representation of this {@code Multipliable9f}'s
520         *         value with all the fraction digits (including trailing zeros)
521         * @see #getValue()
522         * @see Decimal#toString()
523         */
524        @Override
525        public String toString() {
526                return value.toString();
527        }
528}