001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.common.math;
017
018import java.math.BigDecimal;
019import java.util.Comparator;
020import java.util.Random;
021import org.modeshape.common.annotation.Immutable;
022
023/**
024 * The set of mathematic operations for a particular class of values. This is useful for generic classes that must work with one
025 * of the {@link Number} subclasses.
026 * 
027 * @param <T> the numeric class, usually a subclass of {@link Number} (although this is not required)
028 */
029@Immutable
030public interface MathOperations<T> {
031
032    /**
033     * Return the class that these operations operate upon.
034     * 
035     * @return the class
036     */
037    public Class<T> getOperandClass();
038
039    /**
040     * Add the two operands and return the sum. The {@link #createZeroValue() zero value} is used in place of any operand that is
041     * null.
042     * 
043     * @param value1 the first operand
044     * @param value2 the second operand
045     * @return the sum of the two operands.
046     */
047    public T add( T value1,
048                  T value2 );
049
050    /**
051     * Subtract the second operand from the first, and return the difference. The {@link #createZeroValue() zero value} is used in
052     * place of any operand that is null.
053     * 
054     * @param value1 the first operand
055     * @param value2 the second operand
056     * @return the difference between the two operands.
057     */
058    public T subtract( T value1,
059                       T value2 );
060
061    /**
062     * Multiply the two operands and return the product. The {@link #createZeroValue() zero value} is used in place of any operand
063     * that is null.
064     * 
065     * @param value1 the first operand
066     * @param value2 the second operand
067     * @return the product of the two operands.
068     */
069    public T multiply( T value1,
070                       T value2 );
071
072    /**
073     * Divide the first operand by the second, and return the result. The {@link #createZeroValue() zero value} is used in place
074     * of any operand that is null.
075     * 
076     * @param value1 the first operand
077     * @param value2 the second operand
078     * @return the result of the division
079     */
080    public double divide( T value1,
081                          T value2 );
082
083    /**
084     * Negate the supplied operand. The {@link #createZeroValue() zero value} is used in place of any operand that is null.
085     * 
086     * @param value the value that is to be negated
087     * @return the result of the negation
088     */
089    public T negate( T value );
090
091    /**
092     * Increment the supplied operand by 1. (Note, the exact meaning of "1" is dependent upon the particular
093     * {@link #getOperandClass() operand class}. The {@link #createZeroValue() zero value} is used in place of any operand that is
094     * null.
095     * 
096     * @param value the value that is to be incremented
097     * @return the incremented value
098     */
099    public T increment( T value );
100
101    /**
102     * Compare the two operands and return the one that is larger. A null value is considered smaller than non-null values
103     * (including 0).
104     * 
105     * @param value1 the first operand
106     * @param value2 the second operand
107     * @return the larger of the two operands
108     */
109    public T maximum( T value1,
110                      T value2 );
111
112    /**
113     * Compare the two operands and return the one that is smaller. A null value is considered larger than non-null values
114     * (including 0).
115     * 
116     * @param value1 the first operand
117     * @param value2 the second operand
118     * @return the smaller of the two operands
119     */
120    public T minimum( T value1,
121                      T value2 );
122
123    /**
124     * Compare the two operands and return an integer that describes whether the first value is larger, smaller or the same as the
125     * second value. The semantics are identical to those of {@link Comparable}. The {@link #createZeroValue() zero value} is used
126     * in place of any operand that is null.
127     * 
128     * @param value1 the first operand
129     * @param value2 the second operand
130     * @return -1 if the first value is smaller than the second, 1 if the first value is larger than the second, or 0 if they are
131     *         equal.
132     */
133    public int compare( T value1,
134                        T value2 );
135
136    /**
137     * Create a {@link BigDecimal} representation of the supplied value.
138     * 
139     * @param value the value that is to be converted to a BigDecimal
140     * @return the BigDecimal representation, or null if <code>value</code> is null
141     */
142    public BigDecimal asBigDecimal( T value );
143
144    /**
145     * Convert the {@link BigDecimal} representation into the natural object representation. This may result in loss of some data
146     * (e.g., converting a decimal to an integer results in the loss of the fractional part of the number).
147     * 
148     * @param value the BigDecimal value
149     * @return the natural representation, or null if <code>value</code> is null
150     */
151    public T fromBigDecimal( BigDecimal value );
152
153    /**
154     * Convert the value to a double. This may result in a loss of information depending upon the {@link #getOperandClass()
155     * operand class}.
156     * 
157     * @param value the value
158     * @return the representation as a double
159     */
160    public double doubleValue( T value );
161
162    /**
163     * Convert the value to a float. This may result in a loss of information depending upon the {@link #getOperandClass() operand
164     * class}.
165     * 
166     * @param value the value
167     * @return the representation as a float
168     */
169    public float floatValue( T value );
170
171    /**
172     * Convert the value to an integer. This may result in a loss of information depending upon the {@link #getOperandClass()
173     * operand class}.
174     * 
175     * @param value the value
176     * @return the representation as an integer
177     */
178    public int intValue( T value );
179
180    /**
181     * Convert the value to a short. This may result in a loss of information depending upon the {@link #getOperandClass() operand
182     * class}.
183     * 
184     * @param value the value
185     * @return the representation as a short
186     */
187    public short shortValue( T value );
188
189    /**
190     * Convert the value to a long integer. This may result in a loss of information depending upon the {@link #getOperandClass()
191     * operand class}.
192     * 
193     * @param value the value
194     * @return the representation as a long
195     */
196    public long longValue( T value );
197
198    /**
199     * Create the object form of the "zero value". This is often used to create an uninitialized object.
200     * 
201     * @return the object that represents zero.
202     */
203    public T createZeroValue();
204
205    /**
206     * Convert the integer representation into the natural object representation.
207     * 
208     * @param value the integer value
209     * @return the object representation of the integer
210     */
211    public T create( int value );
212
213    /**
214     * Convert the long representation into the natural object representation.
215     * 
216     * @param value the long value
217     * @return the object representation of the long integer
218     */
219    public T create( long value );
220
221    /**
222     * Convert the double representation into the natural object representation.
223     * 
224     * @param value the double value
225     * @return the object representation of the floating point number
226     */
227    public T create( double value );
228
229    /**
230     * Return the square root of the supplied operand.
231     * 
232     * @param value the value whose root is to be found; may not be null or 0
233     * @return the square root of the value
234     */
235    public double sqrt( T value );
236
237    /**
238     * Return a {@link Comparator Comparator<T>} for this {@link #getOperandClass() operand class}. The implementation is free to
239     * return the same comparator instance from multiple invocations of this method.
240     * 
241     * @return a comparator
242     */
243    public Comparator<T> getComparator();
244
245    /**
246     * Get the exponent if the number were written in exponential form.
247     * 
248     * @param value the value
249     * @return the scale
250     */
251    public int getExponentInScientificNotation( T value );
252
253    /**
254     * Round up the supplied value to the desired scale. This process works (conceptually) by shifting the decimal point of the
255     * value by <code>decimalShift</code> places, rounding, and then shifting the decimal point of the rounded value by
256     * <code>-decimalShift</code>
257     * <p>
258     * For example, consider the number 10.000354. This can be rounded to 10.0004 by calling this method and supplying the value
259     * and an "exponentToKeep" value of -4.
260     * </p>
261     * 
262     * @param value the value to be rounded
263     * @param decimalShift the number of places the decimal point should be shifted before rounding
264     * @return the rounded value
265     */
266    public T roundUp( T value,
267                      int decimalShift );
268
269    /**
270     * Round down the supplied value to the desired scale. This process works (conceptually) by shifting the decimal point of the
271     * value by <code>decimalShift</code> places, rounding, and then shifting the decimal point of the rounded value by
272     * <code>-decimalShift</code>
273     * <p>
274     * For example, consider the number 10.000354. This can be rounded to 10.0003 by calling this method and supplying the value
275     * and an "exponentToKeep" value of -4.
276     * </p>
277     * 
278     * @param value the value to be rounded
279     * @param decimalShift the number of places the decimal point should be shifted before rounding
280     * @return the rounded value
281     */
282    public T roundDown( T value,
283                        int decimalShift );
284
285    public T keepSignificantFigures( T value,
286                                     int numSigFigs );
287
288    /**
289     * Generate a random instance within the specified range.
290     * 
291     * @param minimum the minimum value, or null if the {@link #createZeroValue() zero-value} should be used for the minimum
292     * @param maximum the maximum value, or null if the {@link #createZeroValue() zero-value} should be used for the maximum
293     * @param rng the random number generator to use
294     * @return an instance of the {@link #getOperandClass() operand class} placed within the desired range using a random
295     *         distribution, or null if this class does not support generating random instances
296     */
297    public T random( T minimum,
298                     T maximum,
299                     Random rng );
300}