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.Decimal10f;
039import org.decimal4j.immutable.Decimal11f;
040import org.decimal4j.immutable.Decimal12f;
041import org.decimal4j.immutable.Decimal13f;
042import org.decimal4j.immutable.Decimal14f;
043import org.decimal4j.immutable.Decimal15f;
044import org.decimal4j.immutable.Decimal16f;
045import org.decimal4j.immutable.Decimal17f;
046import org.decimal4j.immutable.Decimal18f;
047import org.decimal4j.mutable.MutableDecimal0f;
048import org.decimal4j.mutable.MutableDecimal1f;
049import org.decimal4j.mutable.MutableDecimal2f;
050import org.decimal4j.mutable.MutableDecimal3f;
051import org.decimal4j.mutable.MutableDecimal4f;
052import org.decimal4j.mutable.MutableDecimal5f;
053import org.decimal4j.mutable.MutableDecimal6f;
054import org.decimal4j.mutable.MutableDecimal7f;
055import org.decimal4j.mutable.MutableDecimal8f;
056import org.decimal4j.scale.Scale10f;
057
058/**
059 * A {@code Multipliable10f} encapsulates a Decimal of scale 10 and facilitates
060 * exact typed multiplication. The multipliable object acts as first factor in the multiplication
061 * and provides a set of overloaded methods for different scales. Each one of those methods 
062 * delivers a different result scale which represents the appropriate scale for the product of
063 * an exact multiplication.
064 * <p>
065 * A {@code Multipliable10f} object is returned by {@link Decimal10f#multiplyExact()},
066 * hence an exact typed multiplication can be written as:
067 * <pre>
068 * Decimal10f value = ... //some value
069 * Decimal12f product = value.multiplyExact().by(Decimal2f.FIVE);
070 * </pre>
071 */
072public final class Multipliable10f {
073        
074        private final Decimal<Scale10f> value;
075        
076        /**
077         * Constructor with Decimal value to be encapsulated.
078         * @param value the decimal value to be wrapped as a multipliable object
079         */
080        public Multipliable10f(Decimal<Scale10f> value) {
081                this.value = Objects.requireNonNull(value, "value cannot be null");
082        }
083        
084        /**
085         * Returns the value underlying this Multipliable10f.
086         * @return the Decimal value wrapped by this multipliable object
087         */
088        public Decimal<Scale10f> getValue() {
089                return value;
090        }
091
092        /**
093         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
094         * result is exact and has scale 10 which is the sum of the scales 
095         * of the Decimal that this multipliable object represents and the scale of
096         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
097         * product is out of the possible range for a {@code Decimal10f}.
098         * <p>
099         * Note that the result is <i>always</i> a new instance.
100         * 
101         * @param factor
102         *            the factor to multiply with the Decimal that this multipliable represents
103         * @return <code>(this * factor)</code>
104         * @throws ArithmeticException
105         *             if an overflow occurs and product is out of the possible
106         *             range for a {@code Decimal10f}
107         */
108        public Decimal10f by(Decimal0f factor) {
109                return Decimal10f.valueOf(this.value.multiplyExact(factor));
110        }
111        /**
112         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
113         * result is exact and has scale 10 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 Decimal10f}.
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 Decimal10f}
126         */
127        public Decimal10f by(MutableDecimal0f factor) {
128                return Decimal10f.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 11 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 Decimal11f}.
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 Decimal11f}
146         */
147        public Decimal11f by(Decimal1f factor) {
148                return Decimal11f.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 11 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 Decimal11f}.
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 Decimal11f}
165         */
166        public Decimal11f by(MutableDecimal1f factor) {
167                return Decimal11f.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 12 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 Decimal12f}.
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 Decimal12f}
185         */
186        public Decimal12f by(Decimal2f factor) {
187                return Decimal12f.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 12 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 Decimal12f}.
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 Decimal12f}
204         */
205        public Decimal12f by(MutableDecimal2f factor) {
206                return Decimal12f.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 13 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 Decimal13f}.
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 Decimal13f}
224         */
225        public Decimal13f by(Decimal3f factor) {
226                return Decimal13f.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 13 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 Decimal13f}.
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 Decimal13f}
243         */
244        public Decimal13f by(MutableDecimal3f factor) {
245                return Decimal13f.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 14 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 Decimal14f}.
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 Decimal14f}
263         */
264        public Decimal14f by(Decimal4f factor) {
265                return Decimal14f.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 14 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 Decimal14f}.
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 Decimal14f}
282         */
283        public Decimal14f by(MutableDecimal4f factor) {
284                return Decimal14f.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 15 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 Decimal15f}.
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 Decimal15f}
302         */
303        public Decimal15f by(Decimal5f factor) {
304                return Decimal15f.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 15 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 Decimal15f}.
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 Decimal15f}
321         */
322        public Decimal15f by(MutableDecimal5f factor) {
323                return Decimal15f.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 16 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 Decimal16f}.
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 Decimal16f}
341         */
342        public Decimal16f by(Decimal6f factor) {
343                return Decimal16f.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 16 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 Decimal16f}.
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 Decimal16f}
360         */
361        public Decimal16f by(MutableDecimal6f factor) {
362                return Decimal16f.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 17 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 Decimal17f}.
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 Decimal17f}
380         */
381        public Decimal17f by(Decimal7f factor) {
382                return Decimal17f.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 17 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 Decimal17f}.
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 Decimal17f}
399         */
400        public Decimal17f by(MutableDecimal7f factor) {
401                return Decimal17f.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 18 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 Decimal18f}.
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 Decimal18f}
419         */
420        public Decimal18f by(Decimal8f factor) {
421                return Decimal18f.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 18 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 Decimal18f}.
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 Decimal18f}
438         */
439        public Decimal18f by(MutableDecimal8f factor) {
440                return Decimal18f.valueOf(this.value.multiplyExact(factor));
441        }
442
443        
444        /**
445         * Returns a hash code for this <code>Multipliable10f</code> which happens to be the
446         * hash code of the underlying {@code Decimal10f} value.
447         * 
448         * @return a hash code value for this object
449         * @see Decimal#hashCode()
450         */
451        @Override
452        public int hashCode() {
453                return value.hashCode();
454        }
455
456        /**
457         * Compares this Multipliable10f to the specified object. The result is {@code true}
458         * if and only if the argument is a {@code Multipliable10f} with an equal underlying 
459         * {@link #getValue() value}.
460         * 
461         * @param obj
462         *            the object to compare with
463         * @return {@code true} if the argument is a {@code Multipliable10f} and if its value
464         *         is equal to this multipliables's value; {@code false} otherwise
465         * @see #getValue()
466         * @see Decimal#equals(Object)
467         */
468        @Override
469        public boolean equals(Object obj) {
470                if (this == obj) return true;
471                if (obj == null) return false;
472                if (getClass() != obj.getClass()) return false;
473                return value.equals(((Multipliable10f)obj).value);
474        }
475
476        /**
477         * Returns a string representation of this {@code Multipliable10f} which is
478         * simply the string representation of the underlying Decimal {@link #getValue() value}.
479         * 
480         * @return a {@code String} Decimal representation of this {@code Multipliable10f}'s
481         *         value with all the fraction digits (including trailing zeros)
482         * @see #getValue()
483         * @see Decimal#toString()
484         */
485        @Override
486        public String toString() {
487                return value.toString();
488        }
489}