001/**
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2016 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.MutableDecimal9f;
057import org.decimal4j.mutable.MutableDecimal10f;
058import org.decimal4j.scale.Scale8f;
059
060/**
061 * A {@code Multipliable8f} encapsulates a Decimal of scale 8 and facilitates
062 * exact typed multiplication. The multipliable object acts as first factor in the multiplication
063 * and provides a set of overloaded methods for different scales. Each one of those methods 
064 * delivers a different result scale which represents the appropriate scale for the product of
065 * an exact multiplication.
066 * <p>
067 * A {@code Multipliable8f} object is returned by {@link Decimal8f#multiplyExact()},
068 * hence an exact typed multiplication can be written as:
069 * <pre>
070 * Decimal8f value = ... //some value
071 * Decimal10f product = value.multiplyExact().by(Decimal2f.FIVE);
072 * </pre>
073 */
074public final class Multipliable8f {
075        
076        private final Decimal<Scale8f> value;
077        
078        /**
079         * Constructor with Decimal value to be encapsulated.
080         * @param value the decimal value to be wrapped as a multipliable object
081         */
082        public Multipliable8f(Decimal<Scale8f> value) {
083                this.value = Objects.requireNonNull(value, "value cannot be null");
084        }
085        
086        /**
087         * Returns the value underlying this Multipliable8f.
088         * @return the Decimal value wrapped by this multipliable object
089         */
090        public Decimal<Scale8f> getValue() {
091                return value;
092        }
093
094        /**
095         * Returns a {@code Decimal} whose value is <tt>(this<sup>2</sup>)</tt>. The
096         * result is exact and has scale 16 which is twice the scale of
097         * the Decimal that this multipliable object represents. An
098         * {@link ArithmeticException} is thrown if the product is out of the
099         * possible range for a {@code Decimal16f}.
100         * <p>
101         * Note that the result is <i>always</i> a new instance.
102         * 
103         * @return <tt>(this * this)</tt>
104         * @throws ArithmeticException
105         *             if an overflow occurs and product is out of the possible
106         *             range for a {@code Decimal16f}
107         */
108        public Decimal16f square() {
109                return by(this.value);
110        }
111
112        /**
113         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
114         * result is exact and has scale 16 which is the sum of the scales 
115         * of the Decimal that this multipliable object represents and the scale of
116         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
117         * product is out of the possible range for a {@code Decimal16f}.
118         * <p>
119         * Note that the result is <i>always</i> a new instance.
120         * 
121         * @param factor
122         *            the factor to multiply with the Decimal that this multipliable represents
123         * @return <tt>(this * factor)</tt>
124         * @throws ArithmeticException
125         *             if an overflow occurs and product is out of the possible
126         *             range for a {@code Decimal16f}
127         */
128        public Decimal16f by(Decimal<Scale8f> factor) {
129                return Decimal16f.valueOf(this.value.multiplyExact(factor));
130        }
131
132        /**
133         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
134         * result is exact and has scale 8 which is the sum of the scales 
135         * of the Decimal that this multipliable object represents and the scale of
136         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
137         * product is out of the possible range for a {@code Decimal8f}.
138         * <p>
139         * Note that the result is <i>always</i> a new instance.
140         * 
141         * @param factor
142         *            the factor to multiply with the Decimal that this multipliable represents
143         * @return <tt>(this * factor)</tt>
144         * @throws ArithmeticException
145         *             if an overflow occurs and product is out of the possible
146         *             range for a {@code Decimal8f}
147         */
148        public Decimal8f by(Decimal0f factor) {
149                return Decimal8f.valueOf(this.value.multiplyExact(factor));
150        }
151        /**
152         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
153         * result is exact and has scale 8 which is the sum of the scales 
154         * of the Decimal that this multipliable object represents and the scale of
155         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
156         * product is out of the possible range for a {@code Decimal8f}.
157         * <p>
158         * Note that the result is <i>always</i> a new instance.
159         * 
160         * @param factor
161         *            the factor to multiply with the Decimal that this multipliable represents
162         * @return <tt>(this * factor)</tt>
163         * @throws ArithmeticException
164         *             if an overflow occurs and product is out of the possible
165         *             range for a {@code Decimal8f}
166         */
167        public Decimal8f by(MutableDecimal0f factor) {
168                return Decimal8f.valueOf(this.value.multiplyExact(factor));
169        }
170
171        /**
172         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
173         * result is exact and has scale 9 which is the sum of the scales 
174         * of the Decimal that this multipliable object represents and the scale of
175         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
176         * product is out of the possible range for a {@code Decimal9f}.
177         * <p>
178         * Note that the result is <i>always</i> a new instance.
179         * 
180         * @param factor
181         *            the factor to multiply with the Decimal that this multipliable represents
182         * @return <tt>(this * factor)</tt>
183         * @throws ArithmeticException
184         *             if an overflow occurs and product is out of the possible
185         *             range for a {@code Decimal9f}
186         */
187        public Decimal9f by(Decimal1f factor) {
188                return Decimal9f.valueOf(this.value.multiplyExact(factor));
189        }
190        /**
191         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
192         * result is exact and has scale 9 which is the sum of the scales 
193         * of the Decimal that this multipliable object represents and the scale of
194         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
195         * product is out of the possible range for a {@code Decimal9f}.
196         * <p>
197         * Note that the result is <i>always</i> a new instance.
198         * 
199         * @param factor
200         *            the factor to multiply with the Decimal that this multipliable represents
201         * @return <tt>(this * factor)</tt>
202         * @throws ArithmeticException
203         *             if an overflow occurs and product is out of the possible
204         *             range for a {@code Decimal9f}
205         */
206        public Decimal9f by(MutableDecimal1f factor) {
207                return Decimal9f.valueOf(this.value.multiplyExact(factor));
208        }
209
210        /**
211         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
212         * result is exact and has scale 10 which is the sum of the scales 
213         * of the Decimal that this multipliable object represents and the scale of
214         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
215         * product is out of the possible range for a {@code Decimal10f}.
216         * <p>
217         * Note that the result is <i>always</i> a new instance.
218         * 
219         * @param factor
220         *            the factor to multiply with the Decimal that this multipliable represents
221         * @return <tt>(this * factor)</tt>
222         * @throws ArithmeticException
223         *             if an overflow occurs and product is out of the possible
224         *             range for a {@code Decimal10f}
225         */
226        public Decimal10f by(Decimal2f factor) {
227                return Decimal10f.valueOf(this.value.multiplyExact(factor));
228        }
229        /**
230         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
231         * result is exact and has scale 10 which is the sum of the scales 
232         * of the Decimal that this multipliable object represents and the scale of
233         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
234         * product is out of the possible range for a {@code Decimal10f}.
235         * <p>
236         * Note that the result is <i>always</i> a new instance.
237         * 
238         * @param factor
239         *            the factor to multiply with the Decimal that this multipliable represents
240         * @return <tt>(this * factor)</tt>
241         * @throws ArithmeticException
242         *             if an overflow occurs and product is out of the possible
243         *             range for a {@code Decimal10f}
244         */
245        public Decimal10f by(MutableDecimal2f factor) {
246                return Decimal10f.valueOf(this.value.multiplyExact(factor));
247        }
248
249        /**
250         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
251         * result is exact and has scale 11 which is the sum of the scales 
252         * of the Decimal that this multipliable object represents and the scale of
253         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
254         * product is out of the possible range for a {@code Decimal11f}.
255         * <p>
256         * Note that the result is <i>always</i> a new instance.
257         * 
258         * @param factor
259         *            the factor to multiply with the Decimal that this multipliable represents
260         * @return <tt>(this * factor)</tt>
261         * @throws ArithmeticException
262         *             if an overflow occurs and product is out of the possible
263         *             range for a {@code Decimal11f}
264         */
265        public Decimal11f by(Decimal3f factor) {
266                return Decimal11f.valueOf(this.value.multiplyExact(factor));
267        }
268        /**
269         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
270         * result is exact and has scale 11 which is the sum of the scales 
271         * of the Decimal that this multipliable object represents and the scale of
272         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
273         * product is out of the possible range for a {@code Decimal11f}.
274         * <p>
275         * Note that the result is <i>always</i> a new instance.
276         * 
277         * @param factor
278         *            the factor to multiply with the Decimal that this multipliable represents
279         * @return <tt>(this * factor)</tt>
280         * @throws ArithmeticException
281         *             if an overflow occurs and product is out of the possible
282         *             range for a {@code Decimal11f}
283         */
284        public Decimal11f by(MutableDecimal3f factor) {
285                return Decimal11f.valueOf(this.value.multiplyExact(factor));
286        }
287
288        /**
289         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
290         * result is exact and has scale 12 which is the sum of the scales 
291         * of the Decimal that this multipliable object represents and the scale of
292         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
293         * product is out of the possible range for a {@code Decimal12f}.
294         * <p>
295         * Note that the result is <i>always</i> a new instance.
296         * 
297         * @param factor
298         *            the factor to multiply with the Decimal that this multipliable represents
299         * @return <tt>(this * factor)</tt>
300         * @throws ArithmeticException
301         *             if an overflow occurs and product is out of the possible
302         *             range for a {@code Decimal12f}
303         */
304        public Decimal12f by(Decimal4f factor) {
305                return Decimal12f.valueOf(this.value.multiplyExact(factor));
306        }
307        /**
308         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
309         * result is exact and has scale 12 which is the sum of the scales 
310         * of the Decimal that this multipliable object represents and the scale of
311         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
312         * product is out of the possible range for a {@code Decimal12f}.
313         * <p>
314         * Note that the result is <i>always</i> a new instance.
315         * 
316         * @param factor
317         *            the factor to multiply with the Decimal that this multipliable represents
318         * @return <tt>(this * factor)</tt>
319         * @throws ArithmeticException
320         *             if an overflow occurs and product is out of the possible
321         *             range for a {@code Decimal12f}
322         */
323        public Decimal12f by(MutableDecimal4f factor) {
324                return Decimal12f.valueOf(this.value.multiplyExact(factor));
325        }
326
327        /**
328         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
329         * result is exact and has scale 13 which is the sum of the scales 
330         * of the Decimal that this multipliable object represents and the scale of
331         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
332         * product is out of the possible range for a {@code Decimal13f}.
333         * <p>
334         * Note that the result is <i>always</i> a new instance.
335         * 
336         * @param factor
337         *            the factor to multiply with the Decimal that this multipliable represents
338         * @return <tt>(this * factor)</tt>
339         * @throws ArithmeticException
340         *             if an overflow occurs and product is out of the possible
341         *             range for a {@code Decimal13f}
342         */
343        public Decimal13f by(Decimal5f factor) {
344                return Decimal13f.valueOf(this.value.multiplyExact(factor));
345        }
346        /**
347         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
348         * result is exact and has scale 13 which is the sum of the scales 
349         * of the Decimal that this multipliable object represents and the scale of
350         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
351         * product is out of the possible range for a {@code Decimal13f}.
352         * <p>
353         * Note that the result is <i>always</i> a new instance.
354         * 
355         * @param factor
356         *            the factor to multiply with the Decimal that this multipliable represents
357         * @return <tt>(this * factor)</tt>
358         * @throws ArithmeticException
359         *             if an overflow occurs and product is out of the possible
360         *             range for a {@code Decimal13f}
361         */
362        public Decimal13f by(MutableDecimal5f factor) {
363                return Decimal13f.valueOf(this.value.multiplyExact(factor));
364        }
365
366        /**
367         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
368         * result is exact and has scale 14 which is the sum of the scales 
369         * of the Decimal that this multipliable object represents and the scale of
370         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
371         * product is out of the possible range for a {@code Decimal14f}.
372         * <p>
373         * Note that the result is <i>always</i> a new instance.
374         * 
375         * @param factor
376         *            the factor to multiply with the Decimal that this multipliable represents
377         * @return <tt>(this * factor)</tt>
378         * @throws ArithmeticException
379         *             if an overflow occurs and product is out of the possible
380         *             range for a {@code Decimal14f}
381         */
382        public Decimal14f by(Decimal6f factor) {
383                return Decimal14f.valueOf(this.value.multiplyExact(factor));
384        }
385        /**
386         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
387         * result is exact and has scale 14 which is the sum of the scales 
388         * of the Decimal that this multipliable object represents and the scale of
389         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
390         * product is out of the possible range for a {@code Decimal14f}.
391         * <p>
392         * Note that the result is <i>always</i> a new instance.
393         * 
394         * @param factor
395         *            the factor to multiply with the Decimal that this multipliable represents
396         * @return <tt>(this * factor)</tt>
397         * @throws ArithmeticException
398         *             if an overflow occurs and product is out of the possible
399         *             range for a {@code Decimal14f}
400         */
401        public Decimal14f by(MutableDecimal6f factor) {
402                return Decimal14f.valueOf(this.value.multiplyExact(factor));
403        }
404
405        /**
406         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
407         * result is exact and has scale 15 which is the sum of the scales 
408         * of the Decimal that this multipliable object represents and the scale of
409         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
410         * product is out of the possible range for a {@code Decimal15f}.
411         * <p>
412         * Note that the result is <i>always</i> a new instance.
413         * 
414         * @param factor
415         *            the factor to multiply with the Decimal that this multipliable represents
416         * @return <tt>(this * factor)</tt>
417         * @throws ArithmeticException
418         *             if an overflow occurs and product is out of the possible
419         *             range for a {@code Decimal15f}
420         */
421        public Decimal15f by(Decimal7f factor) {
422                return Decimal15f.valueOf(this.value.multiplyExact(factor));
423        }
424        /**
425         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
426         * result is exact and has scale 15 which is the sum of the scales 
427         * of the Decimal that this multipliable object represents and the scale of
428         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
429         * product is out of the possible range for a {@code Decimal15f}.
430         * <p>
431         * Note that the result is <i>always</i> a new instance.
432         * 
433         * @param factor
434         *            the factor to multiply with the Decimal that this multipliable represents
435         * @return <tt>(this * factor)</tt>
436         * @throws ArithmeticException
437         *             if an overflow occurs and product is out of the possible
438         *             range for a {@code Decimal15f}
439         */
440        public Decimal15f by(MutableDecimal7f factor) {
441                return Decimal15f.valueOf(this.value.multiplyExact(factor));
442        }
443
444        /**
445         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
446         * result is exact and has scale 17 which is the sum of the scales 
447         * of the Decimal that this multipliable object represents and the scale of
448         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
449         * product is out of the possible range for a {@code Decimal17f}.
450         * <p>
451         * Note that the result is <i>always</i> a new instance.
452         * 
453         * @param factor
454         *            the factor to multiply with the Decimal that this multipliable represents
455         * @return <tt>(this * factor)</tt>
456         * @throws ArithmeticException
457         *             if an overflow occurs and product is out of the possible
458         *             range for a {@code Decimal17f}
459         */
460        public Decimal17f by(Decimal9f factor) {
461                return Decimal17f.valueOf(this.value.multiplyExact(factor));
462        }
463        /**
464         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
465         * result is exact and has scale 17 which is the sum of the scales 
466         * of the Decimal that this multipliable object represents and the scale of
467         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
468         * product is out of the possible range for a {@code Decimal17f}.
469         * <p>
470         * Note that the result is <i>always</i> a new instance.
471         * 
472         * @param factor
473         *            the factor to multiply with the Decimal that this multipliable represents
474         * @return <tt>(this * factor)</tt>
475         * @throws ArithmeticException
476         *             if an overflow occurs and product is out of the possible
477         *             range for a {@code Decimal17f}
478         */
479        public Decimal17f by(MutableDecimal9f factor) {
480                return Decimal17f.valueOf(this.value.multiplyExact(factor));
481        }
482
483        /**
484         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
485         * result is exact and has scale 18 which is the sum of the scales 
486         * of the Decimal that this multipliable object represents and the scale of
487         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
488         * product is out of the possible range for a {@code Decimal18f}.
489         * <p>
490         * Note that the result is <i>always</i> a new instance.
491         * 
492         * @param factor
493         *            the factor to multiply with the Decimal that this multipliable represents
494         * @return <tt>(this * factor)</tt>
495         * @throws ArithmeticException
496         *             if an overflow occurs and product is out of the possible
497         *             range for a {@code Decimal18f}
498         */
499        public Decimal18f by(Decimal10f factor) {
500                return Decimal18f.valueOf(this.value.multiplyExact(factor));
501        }
502        /**
503         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
504         * result is exact and has scale 18 which is the sum of the scales 
505         * of the Decimal that this multipliable object represents and the scale of
506         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
507         * product is out of the possible range for a {@code Decimal18f}.
508         * <p>
509         * Note that the result is <i>always</i> a new instance.
510         * 
511         * @param factor
512         *            the factor to multiply with the Decimal that this multipliable represents
513         * @return <tt>(this * factor)</tt>
514         * @throws ArithmeticException
515         *             if an overflow occurs and product is out of the possible
516         *             range for a {@code Decimal18f}
517         */
518        public Decimal18f by(MutableDecimal10f factor) {
519                return Decimal18f.valueOf(this.value.multiplyExact(factor));
520        }
521
522        
523        /**
524         * Returns a hash code for this <tt>Multipliable8f</tt> which happens to be the 
525         * hash code of the underlying {@code Decimal8f} value.
526         * 
527         * @return a hash code value for this object
528         * @see Decimal#hashCode()
529         */
530        @Override
531        public int hashCode() {
532                return value.hashCode();
533        }
534
535        /**
536         * Compares this Multipliable8f to the specified object. The result is {@code true}
537         * if and only if the argument is a {@code Multipliable8f} with an equal underlying 
538         * {@link #getValue() value}.
539         * 
540         * @param obj
541         *            the object to compare with
542         * @return {@code true} if the argument is a {@code Multipliable8f} and if its value
543         *         is equal to this multipliables's value; {@code false} otherwise
544         * @see #getValue()
545         * @see Decimal#equals(Object)
546         */
547        @Override
548        public boolean equals(Object obj) {
549                if (this == obj) return true;
550                if (obj == null) return false;
551                if (getClass() != obj.getClass()) return false;
552                return value.equals(((Multipliable8f)obj).value);
553        }
554
555        /**
556         * Returns a string representation of this {@code Multipliable8f} which is
557         * simply the string representation of the underlying Decimal {@link #getValue() value}.
558         * 
559         * @return a {@code String} Decimal representation of this {@code Multipliable8f}'s
560         *         value with all the fraction digits (including trailing zeros)
561         * @see #getValue()
562         * @see Decimal#toString()
563         */
564        @Override
565        public String toString() {
566                return value.toString();
567        }
568}