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.Decimal14f;
035import org.decimal4j.immutable.Decimal15f;
036import org.decimal4j.immutable.Decimal16f;
037import org.decimal4j.immutable.Decimal17f;
038import org.decimal4j.immutable.Decimal18f;
039import org.decimal4j.mutable.MutableDecimal0f;
040import org.decimal4j.mutable.MutableDecimal1f;
041import org.decimal4j.mutable.MutableDecimal2f;
042import org.decimal4j.mutable.MutableDecimal3f;
043import org.decimal4j.mutable.MutableDecimal4f;
044import org.decimal4j.scale.Scale14f;
045
046/**
047 * A {@code Multipliable14f} encapsulates a Decimal of scale 14 and facilitates
048 * exact typed multiplication. The multipliable object acts as first factor in the multiplication
049 * and provides a set of overloaded methods for different scales. Each one of those methods 
050 * delivers a different result scale which represents the appropriate scale for the product of
051 * an exact multiplication.
052 * <p>
053 * A {@code Multipliable14f} object is returned by {@link Decimal14f#multiplyExact()},
054 * hence an exact typed multiplication can be written as:
055 * <pre>
056 * Decimal14f value = ... //some value
057 * Decimal16f product = value.multiplyExact().by(Decimal2f.FIVE);
058 * </pre>
059 */
060public final class Multipliable14f {
061        
062        private final Decimal<Scale14f> value;
063        
064        /**
065         * Constructor with Decimal value to be encapsulated.
066         * @param value the decimal value to be wrapped as a multipliable object
067         */
068        public Multipliable14f(Decimal<Scale14f> value) {
069                this.value = Objects.requireNonNull(value, "value cannot be null");
070        }
071        
072        /**
073         * Returns the value underlying this Multipliable14f.
074         * @return the Decimal value wrapped by this multipliable object
075         */
076        public Decimal<Scale14f> getValue() {
077                return value;
078        }
079
080        /**
081         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
082         * result is exact and has scale 14 which is the sum of the scales 
083         * of the Decimal that this multipliable object represents and the scale of
084         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
085         * product is out of the possible range for a {@code Decimal14f}.
086         * <p>
087         * Note that the result is <i>always</i> a new instance.
088         * 
089         * @param factor
090         *            the factor to multiply with the Decimal that this multipliable represents
091         * @return <tt>(this * factor)</tt>
092         * @throws ArithmeticException
093         *             if an overflow occurs and product is out of the possible
094         *             range for a {@code Decimal14f}
095         */
096        public Decimal14f by(Decimal0f factor) {
097                return Decimal14f.valueOf(this.value.multiplyExact(factor));
098        }
099        /**
100         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
101         * result is exact and has scale 14 which is the sum of the scales 
102         * of the Decimal that this multipliable object represents and the scale of
103         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
104         * product is out of the possible range for a {@code Decimal14f}.
105         * <p>
106         * Note that the result is <i>always</i> a new instance.
107         * 
108         * @param factor
109         *            the factor to multiply with the Decimal that this multipliable represents
110         * @return <tt>(this * factor)</tt>
111         * @throws ArithmeticException
112         *             if an overflow occurs and product is out of the possible
113         *             range for a {@code Decimal14f}
114         */
115        public Decimal14f by(MutableDecimal0f factor) {
116                return Decimal14f.valueOf(this.value.multiplyExact(factor));
117        }
118
119        /**
120         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
121         * result is exact and has scale 15 which is the sum of the scales 
122         * of the Decimal that this multipliable object represents and the scale of
123         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
124         * product is out of the possible range for a {@code Decimal15f}.
125         * <p>
126         * Note that the result is <i>always</i> a new instance.
127         * 
128         * @param factor
129         *            the factor to multiply with the Decimal that this multipliable represents
130         * @return <tt>(this * factor)</tt>
131         * @throws ArithmeticException
132         *             if an overflow occurs and product is out of the possible
133         *             range for a {@code Decimal15f}
134         */
135        public Decimal15f by(Decimal1f factor) {
136                return Decimal15f.valueOf(this.value.multiplyExact(factor));
137        }
138        /**
139         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
140         * result is exact and has scale 15 which is the sum of the scales 
141         * of the Decimal that this multipliable object represents and the scale of
142         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
143         * product is out of the possible range for a {@code Decimal15f}.
144         * <p>
145         * Note that the result is <i>always</i> a new instance.
146         * 
147         * @param factor
148         *            the factor to multiply with the Decimal that this multipliable represents
149         * @return <tt>(this * factor)</tt>
150         * @throws ArithmeticException
151         *             if an overflow occurs and product is out of the possible
152         *             range for a {@code Decimal15f}
153         */
154        public Decimal15f by(MutableDecimal1f factor) {
155                return Decimal15f.valueOf(this.value.multiplyExact(factor));
156        }
157
158        /**
159         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
160         * result is exact and has scale 16 which is the sum of the scales 
161         * of the Decimal that this multipliable object represents and the scale of
162         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
163         * product is out of the possible range for a {@code Decimal16f}.
164         * <p>
165         * Note that the result is <i>always</i> a new instance.
166         * 
167         * @param factor
168         *            the factor to multiply with the Decimal that this multipliable represents
169         * @return <tt>(this * factor)</tt>
170         * @throws ArithmeticException
171         *             if an overflow occurs and product is out of the possible
172         *             range for a {@code Decimal16f}
173         */
174        public Decimal16f by(Decimal2f factor) {
175                return Decimal16f.valueOf(this.value.multiplyExact(factor));
176        }
177        /**
178         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
179         * result is exact and has scale 16 which is the sum of the scales 
180         * of the Decimal that this multipliable object represents and the scale of
181         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
182         * product is out of the possible range for a {@code Decimal16f}.
183         * <p>
184         * Note that the result is <i>always</i> a new instance.
185         * 
186         * @param factor
187         *            the factor to multiply with the Decimal that this multipliable represents
188         * @return <tt>(this * factor)</tt>
189         * @throws ArithmeticException
190         *             if an overflow occurs and product is out of the possible
191         *             range for a {@code Decimal16f}
192         */
193        public Decimal16f by(MutableDecimal2f factor) {
194                return Decimal16f.valueOf(this.value.multiplyExact(factor));
195        }
196
197        /**
198         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
199         * result is exact and has scale 17 which is the sum of the scales 
200         * of the Decimal that this multipliable object represents and the scale of
201         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
202         * product is out of the possible range for a {@code Decimal17f}.
203         * <p>
204         * Note that the result is <i>always</i> a new instance.
205         * 
206         * @param factor
207         *            the factor to multiply with the Decimal that this multipliable represents
208         * @return <tt>(this * factor)</tt>
209         * @throws ArithmeticException
210         *             if an overflow occurs and product is out of the possible
211         *             range for a {@code Decimal17f}
212         */
213        public Decimal17f by(Decimal3f factor) {
214                return Decimal17f.valueOf(this.value.multiplyExact(factor));
215        }
216        /**
217         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
218         * result is exact and has scale 17 which is the sum of the scales 
219         * of the Decimal that this multipliable object represents and the scale of
220         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
221         * product is out of the possible range for a {@code Decimal17f}.
222         * <p>
223         * Note that the result is <i>always</i> a new instance.
224         * 
225         * @param factor
226         *            the factor to multiply with the Decimal that this multipliable represents
227         * @return <tt>(this * factor)</tt>
228         * @throws ArithmeticException
229         *             if an overflow occurs and product is out of the possible
230         *             range for a {@code Decimal17f}
231         */
232        public Decimal17f by(MutableDecimal3f factor) {
233                return Decimal17f.valueOf(this.value.multiplyExact(factor));
234        }
235
236        /**
237         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
238         * result is exact and has scale 18 which is the sum of the scales 
239         * of the Decimal that this multipliable object represents and the scale of
240         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
241         * product is out of the possible range for a {@code Decimal18f}.
242         * <p>
243         * Note that the result is <i>always</i> a new instance.
244         * 
245         * @param factor
246         *            the factor to multiply with the Decimal that this multipliable represents
247         * @return <tt>(this * factor)</tt>
248         * @throws ArithmeticException
249         *             if an overflow occurs and product is out of the possible
250         *             range for a {@code Decimal18f}
251         */
252        public Decimal18f by(Decimal4f factor) {
253                return Decimal18f.valueOf(this.value.multiplyExact(factor));
254        }
255        /**
256         * Returns a {@code Decimal} whose value is {@code (this * factor)}. The
257         * result is exact and has scale 18 which is the sum of the scales 
258         * of the Decimal that this multipliable object represents and the scale of
259         * the {@code factor} argument. An {@link ArithmeticException} is thrown if the 
260         * product is out of the possible range for a {@code Decimal18f}.
261         * <p>
262         * Note that the result is <i>always</i> a new instance.
263         * 
264         * @param factor
265         *            the factor to multiply with the Decimal that this multipliable represents
266         * @return <tt>(this * factor)</tt>
267         * @throws ArithmeticException
268         *             if an overflow occurs and product is out of the possible
269         *             range for a {@code Decimal18f}
270         */
271        public Decimal18f by(MutableDecimal4f factor) {
272                return Decimal18f.valueOf(this.value.multiplyExact(factor));
273        }
274
275        
276        /**
277         * Returns a hash code for this <tt>Multipliable14f</tt> which happens to be the 
278         * hash code of the underlying {@code Decimal14f} value.
279         * 
280         * @return a hash code value for this object
281         * @see Decimal#hashCode()
282         */
283        @Override
284        public int hashCode() {
285                return value.hashCode();
286        }
287
288        /**
289         * Compares this Multipliable14f to the specified object. The result is {@code true}
290         * if and only if the argument is a {@code Multipliable14f} with an equal underlying 
291         * {@link #getValue() value}.
292         * 
293         * @param obj
294         *            the object to compare with
295         * @return {@code true} if the argument is a {@code Multipliable14f} and if its value
296         *         is equal to this multipliables's value; {@code false} otherwise
297         * @see #getValue()
298         * @see Decimal#equals(Object)
299         */
300        @Override
301        public boolean equals(Object obj) {
302                if (this == obj) return true;
303                if (obj == null) return false;
304                if (getClass() != obj.getClass()) return false;
305                return value.equals(((Multipliable14f)obj).value);
306        }
307
308        /**
309         * Returns a string representation of this {@code Multipliable14f} which is
310         * simply the string representation of the underlying Decimal {@link #getValue() value}.
311         * 
312         * @return a {@code String} Decimal representation of this {@code Multipliable14f}'s
313         *         value with all the fraction digits (including trailing zeros)
314         * @see #getValue()
315         * @see Decimal#toString()
316         */
317        @Override
318        public String toString() {
319                return value.toString();
320        }
321}