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.Decimal11f;
038import org.decimal4j.immutable.Decimal12f;
039import org.decimal4j.immutable.Decimal13f;
040import org.decimal4j.immutable.Decimal14f;
041import org.decimal4j.immutable.Decimal15f;
042import org.decimal4j.immutable.Decimal16f;
043import org.decimal4j.immutable.Decimal17f;
044import org.decimal4j.immutable.Decimal18f;
045import org.decimal4j.mutable.MutableDecimal0f;
046import org.decimal4j.mutable.MutableDecimal1f;
047import org.decimal4j.mutable.MutableDecimal2f;
048import org.decimal4j.mutable.MutableDecimal3f;
049import org.decimal4j.mutable.MutableDecimal4f;
050import org.decimal4j.mutable.MutableDecimal5f;
051import org.decimal4j.mutable.MutableDecimal6f;
052import org.decimal4j.mutable.MutableDecimal7f;
053import org.decimal4j.scale.Scale11f;
054
055/**
056 * A {@code Multipliable11f} encapsulates a Decimal of scale 11 and facilitates
057 * exact typed multiplication. The multipliable object acts as first factor in the multiplication
058 * and provides a set of overloaded methods for different scales. Each one of those methods 
059 * delivers a different result scale which represents the appropriate scale for the product of
060 * an exact multiplication.
061 * <p>
062 * A {@code Multipliable11f} object is returned by {@link Decimal11f#multiplyExact()},
063 * hence an exact typed multiplication can be written as:
064 * <pre>
065 * Decimal11f value = ... //some value
066 * Decimal13f product = value.multiplyExact().by(Decimal2f.FIVE);
067 * </pre>
068 */
069public final class Multipliable11f {
070        
071        private final Decimal<Scale11f> value;
072        
073        /**
074         * Constructor with Decimal value to be encapsulated.
075         * @param value the decimal value to be wrapped as a multipliable object
076         */
077        public Multipliable11f(Decimal<Scale11f> value) {
078                this.value = Objects.requireNonNull(value, "value cannot be null");
079        }
080        
081        /**
082         * Returns the value underlying this Multipliable11f.
083         * @return the Decimal value wrapped by this multipliable object
084         */
085        public Decimal<Scale11f> getValue() {
086                return value;
087        }
088
089        /**
090         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
091         * result is exact and has scale 11 which is the sum of the scales 
092         * of the Decimal that this multipliable object represents and the scale of
093         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
094         * product is out of the possible range for a {@code Decimal11f}.
095         * <p>
096         * Note that the result is <i>always</i> a new instance.
097         * 
098         * @param factor
099         *            the factor to multiply with the Decimal that this multipliable represents
100         * @return <code>(this * factor)</code>
101         * @throws ArithmeticException
102         *             if an overflow occurs and product is out of the possible
103         *             range for a {@code Decimal11f}
104         */
105        public Decimal11f by(Decimal0f factor) {
106                return Decimal11f.valueOf(this.value.multiplyExact(factor));
107        }
108        /**
109         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
110         * result is exact and has scale 11 which is the sum of the scales 
111         * of the Decimal that this multipliable object represents and the scale of
112         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
113         * product is out of the possible range for a {@code Decimal11f}.
114         * <p>
115         * Note that the result is <i>always</i> a new instance.
116         * 
117         * @param factor
118         *            the factor to multiply with the Decimal that this multipliable represents
119         * @return <code>(this * factor)</code>
120         * @throws ArithmeticException
121         *             if an overflow occurs and product is out of the possible
122         *             range for a {@code Decimal11f}
123         */
124        public Decimal11f by(MutableDecimal0f factor) {
125                return Decimal11f.valueOf(this.value.multiplyExact(factor));
126        }
127
128        /**
129         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
130         * result is exact and has scale 12 which is the sum of the scales 
131         * of the Decimal that this multipliable object represents and the scale of
132         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
133         * product is out of the possible range for a {@code Decimal12f}.
134         * <p>
135         * Note that the result is <i>always</i> a new instance.
136         * 
137         * @param factor
138         *            the factor to multiply with the Decimal that this multipliable represents
139         * @return <code>(this * factor)</code>
140         * @throws ArithmeticException
141         *             if an overflow occurs and product is out of the possible
142         *             range for a {@code Decimal12f}
143         */
144        public Decimal12f by(Decimal1f factor) {
145                return Decimal12f.valueOf(this.value.multiplyExact(factor));
146        }
147        /**
148         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
149         * result is exact and has scale 12 which is the sum of the scales 
150         * of the Decimal that this multipliable object represents and the scale of
151         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
152         * product is out of the possible range for a {@code Decimal12f}.
153         * <p>
154         * Note that the result is <i>always</i> a new instance.
155         * 
156         * @param factor
157         *            the factor to multiply with the Decimal that this multipliable represents
158         * @return <code>(this * factor)</code>
159         * @throws ArithmeticException
160         *             if an overflow occurs and product is out of the possible
161         *             range for a {@code Decimal12f}
162         */
163        public Decimal12f by(MutableDecimal1f factor) {
164                return Decimal12f.valueOf(this.value.multiplyExact(factor));
165        }
166
167        /**
168         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
169         * result is exact and has scale 13 which is the sum of the scales 
170         * of the Decimal that this multipliable object represents and the scale of
171         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
172         * product is out of the possible range for a {@code Decimal13f}.
173         * <p>
174         * Note that the result is <i>always</i> a new instance.
175         * 
176         * @param factor
177         *            the factor to multiply with the Decimal that this multipliable represents
178         * @return <code>(this * factor)</code>
179         * @throws ArithmeticException
180         *             if an overflow occurs and product is out of the possible
181         *             range for a {@code Decimal13f}
182         */
183        public Decimal13f by(Decimal2f factor) {
184                return Decimal13f.valueOf(this.value.multiplyExact(factor));
185        }
186        /**
187         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
188         * result is exact and has scale 13 which is the sum of the scales 
189         * of the Decimal that this multipliable object represents and the scale of
190         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
191         * product is out of the possible range for a {@code Decimal13f}.
192         * <p>
193         * Note that the result is <i>always</i> a new instance.
194         * 
195         * @param factor
196         *            the factor to multiply with the Decimal that this multipliable represents
197         * @return <code>(this * factor)</code>
198         * @throws ArithmeticException
199         *             if an overflow occurs and product is out of the possible
200         *             range for a {@code Decimal13f}
201         */
202        public Decimal13f by(MutableDecimal2f factor) {
203                return Decimal13f.valueOf(this.value.multiplyExact(factor));
204        }
205
206        /**
207         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
208         * result is exact and has scale 14 which is the sum of the scales 
209         * of the Decimal that this multipliable object represents and the scale of
210         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
211         * product is out of the possible range for a {@code Decimal14f}.
212         * <p>
213         * Note that the result is <i>always</i> a new instance.
214         * 
215         * @param factor
216         *            the factor to multiply with the Decimal that this multipliable represents
217         * @return <code>(this * factor)</code>
218         * @throws ArithmeticException
219         *             if an overflow occurs and product is out of the possible
220         *             range for a {@code Decimal14f}
221         */
222        public Decimal14f by(Decimal3f factor) {
223                return Decimal14f.valueOf(this.value.multiplyExact(factor));
224        }
225        /**
226         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
227         * result is exact and has scale 14 which is the sum of the scales 
228         * of the Decimal that this multipliable object represents and the scale of
229         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
230         * product is out of the possible range for a {@code Decimal14f}.
231         * <p>
232         * Note that the result is <i>always</i> a new instance.
233         * 
234         * @param factor
235         *            the factor to multiply with the Decimal that this multipliable represents
236         * @return <code>(this * factor)</code>
237         * @throws ArithmeticException
238         *             if an overflow occurs and product is out of the possible
239         *             range for a {@code Decimal14f}
240         */
241        public Decimal14f by(MutableDecimal3f factor) {
242                return Decimal14f.valueOf(this.value.multiplyExact(factor));
243        }
244
245        /**
246         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
247         * result is exact and has scale 15 which is the sum of the scales 
248         * of the Decimal that this multipliable object represents and the scale of
249         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
250         * product is out of the possible range for a {@code Decimal15f}.
251         * <p>
252         * Note that the result is <i>always</i> a new instance.
253         * 
254         * @param factor
255         *            the factor to multiply with the Decimal that this multipliable represents
256         * @return <code>(this * factor)</code>
257         * @throws ArithmeticException
258         *             if an overflow occurs and product is out of the possible
259         *             range for a {@code Decimal15f}
260         */
261        public Decimal15f by(Decimal4f factor) {
262                return Decimal15f.valueOf(this.value.multiplyExact(factor));
263        }
264        /**
265         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
266         * result is exact and has scale 15 which is the sum of the scales 
267         * of the Decimal that this multipliable object represents and the scale of
268         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
269         * product is out of the possible range for a {@code Decimal15f}.
270         * <p>
271         * Note that the result is <i>always</i> a new instance.
272         * 
273         * @param factor
274         *            the factor to multiply with the Decimal that this multipliable represents
275         * @return <code>(this * factor)</code>
276         * @throws ArithmeticException
277         *             if an overflow occurs and product is out of the possible
278         *             range for a {@code Decimal15f}
279         */
280        public Decimal15f by(MutableDecimal4f factor) {
281                return Decimal15f.valueOf(this.value.multiplyExact(factor));
282        }
283
284        /**
285         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
286         * result is exact and has scale 16 which is the sum of the scales 
287         * of the Decimal that this multipliable object represents and the scale of
288         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
289         * product is out of the possible range for a {@code Decimal16f}.
290         * <p>
291         * Note that the result is <i>always</i> a new instance.
292         * 
293         * @param factor
294         *            the factor to multiply with the Decimal that this multipliable represents
295         * @return <code>(this * factor)</code>
296         * @throws ArithmeticException
297         *             if an overflow occurs and product is out of the possible
298         *             range for a {@code Decimal16f}
299         */
300        public Decimal16f by(Decimal5f factor) {
301                return Decimal16f.valueOf(this.value.multiplyExact(factor));
302        }
303        /**
304         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
305         * result is exact and has scale 16 which is the sum of the scales 
306         * of the Decimal that this multipliable object represents and the scale of
307         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
308         * product is out of the possible range for a {@code Decimal16f}.
309         * <p>
310         * Note that the result is <i>always</i> a new instance.
311         * 
312         * @param factor
313         *            the factor to multiply with the Decimal that this multipliable represents
314         * @return <code>(this * factor)</code>
315         * @throws ArithmeticException
316         *             if an overflow occurs and product is out of the possible
317         *             range for a {@code Decimal16f}
318         */
319        public Decimal16f by(MutableDecimal5f factor) {
320                return Decimal16f.valueOf(this.value.multiplyExact(factor));
321        }
322
323        /**
324         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
325         * result is exact and has scale 17 which is the sum of the scales 
326         * of the Decimal that this multipliable object represents and the scale of
327         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
328         * product is out of the possible range for a {@code Decimal17f}.
329         * <p>
330         * Note that the result is <i>always</i> a new instance.
331         * 
332         * @param factor
333         *            the factor to multiply with the Decimal that this multipliable represents
334         * @return <code>(this * factor)</code>
335         * @throws ArithmeticException
336         *             if an overflow occurs and product is out of the possible
337         *             range for a {@code Decimal17f}
338         */
339        public Decimal17f by(Decimal6f factor) {
340                return Decimal17f.valueOf(this.value.multiplyExact(factor));
341        }
342        /**
343         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
344         * result is exact and has scale 17 which is the sum of the scales 
345         * of the Decimal that this multipliable object represents and the scale of
346         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
347         * product is out of the possible range for a {@code Decimal17f}.
348         * <p>
349         * Note that the result is <i>always</i> a new instance.
350         * 
351         * @param factor
352         *            the factor to multiply with the Decimal that this multipliable represents
353         * @return <code>(this * factor)</code>
354         * @throws ArithmeticException
355         *             if an overflow occurs and product is out of the possible
356         *             range for a {@code Decimal17f}
357         */
358        public Decimal17f by(MutableDecimal6f factor) {
359                return Decimal17f.valueOf(this.value.multiplyExact(factor));
360        }
361
362        /**
363         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
364         * result is exact and has scale 18 which is the sum of the scales 
365         * of the Decimal that this multipliable object represents and the scale of
366         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
367         * product is out of the possible range for a {@code Decimal18f}.
368         * <p>
369         * Note that the result is <i>always</i> a new instance.
370         * 
371         * @param factor
372         *            the factor to multiply with the Decimal that this multipliable represents
373         * @return <code>(this * factor)</code>
374         * @throws ArithmeticException
375         *             if an overflow occurs and product is out of the possible
376         *             range for a {@code Decimal18f}
377         */
378        public Decimal18f by(Decimal7f factor) {
379                return Decimal18f.valueOf(this.value.multiplyExact(factor));
380        }
381        /**
382         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
383         * result is exact and has scale 18 which is the sum of the scales 
384         * of the Decimal that this multipliable object represents and the scale of
385         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
386         * product is out of the possible range for a {@code Decimal18f}.
387         * <p>
388         * Note that the result is <i>always</i> a new instance.
389         * 
390         * @param factor
391         *            the factor to multiply with the Decimal that this multipliable represents
392         * @return <code>(this * factor)</code>
393         * @throws ArithmeticException
394         *             if an overflow occurs and product is out of the possible
395         *             range for a {@code Decimal18f}
396         */
397        public Decimal18f by(MutableDecimal7f factor) {
398                return Decimal18f.valueOf(this.value.multiplyExact(factor));
399        }
400
401        
402        /**
403         * Returns a hash code for this <code>Multipliable11f</code> which happens to be the
404         * hash code of the underlying {@code Decimal11f} value.
405         * 
406         * @return a hash code value for this object
407         * @see Decimal#hashCode()
408         */
409        @Override
410        public int hashCode() {
411                return value.hashCode();
412        }
413
414        /**
415         * Compares this Multipliable11f to the specified object. The result is {@code true}
416         * if and only if the argument is a {@code Multipliable11f} with an equal underlying 
417         * {@link #getValue() value}.
418         * 
419         * @param obj
420         *            the object to compare with
421         * @return {@code true} if the argument is a {@code Multipliable11f} and if its value
422         *         is equal to this multipliables's value; {@code false} otherwise
423         * @see #getValue()
424         * @see Decimal#equals(Object)
425         */
426        @Override
427        public boolean equals(Object obj) {
428                if (this == obj) return true;
429                if (obj == null) return false;
430                if (getClass() != obj.getClass()) return false;
431                return value.equals(((Multipliable11f)obj).value);
432        }
433
434        /**
435         * Returns a string representation of this {@code Multipliable11f} which is
436         * simply the string representation of the underlying Decimal {@link #getValue() value}.
437         * 
438         * @return a {@code String} Decimal representation of this {@code Multipliable11f}'s
439         *         value with all the fraction digits (including trailing zeros)
440         * @see #getValue()
441         * @see Decimal#toString()
442         */
443        @Override
444        public String toString() {
445                return value.toString();
446        }
447}