/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.modeshape.common.math; import java.math.BigDecimal; import java.util.Comparator; import java.util.Random; import org.modeshape.common.annotation.Immutable; /** * The set of mathematic operations for a particular class of values. This is useful for generic classes that must work with one * of the {@link Number} subclasses. * * @param <T> the numeric class, usually a subclass of {@link Number} (although this is not required) */ @Immutable public interface MathOperations<T> { /** * Return the class that these operations operate upon. * * @return the class */ public Class<T> getOperandClass(); /** * Add the two operands and return the sum. The {@link #createZeroValue() zero value} is used in place of any operand that is * null. * * @param value1 the first operand * @param value2 the second operand * @return the sum of the two operands. */ public T add( T value1, T value2 ); /** * Subtract the second operand from the first, and return the difference. The {@link #createZeroValue() zero value} is used in * place of any operand that is null. * * @param value1 the first operand * @param value2 the second operand * @return the difference between the two operands. */ public T subtract( T value1, T value2 ); /** * Multiply the two operands and return the product. The {@link #createZeroValue() zero value} is used in place of any operand * that is null. * * @param value1 the first operand * @param value2 the second operand * @return the product of the two operands. */ public T multiply( T value1, T value2 ); /** * Divide the first operand by the second, and return the result. The {@link #createZeroValue() zero value} is used in place * of any operand that is null. * * @param value1 the first operand * @param value2 the second operand * @return the result of the division */ public double divide( T value1, T value2 ); /** * Negate the supplied operand. The {@link #createZeroValue() zero value} is used in place of any operand that is null. * * @param value the value that is to be negated * @return the result of the negation */ public T negate( T value ); /** * Increment the supplied operand by 1. (Note, the exact meaning of "1" is dependent upon the particular * {@link #getOperandClass() operand class}. The {@link #createZeroValue() zero value} is used in place of any operand that is * null. * * @param value the value that is to be incremented * @return the incremented value */ public T increment( T value ); /** * Compare the two operands and return the one that is larger. A null value is considered smaller than non-null values * (including 0). * * @param value1 the first operand * @param value2 the second operand * @return the larger of the two operands */ public T maximum( T value1, T value2 ); /** * Compare the two operands and return the one that is smaller. A null value is considered larger than non-null values * (including 0). * * @param value1 the first operand * @param value2 the second operand * @return the smaller of the two operands */ public T minimum( T value1, T value2 ); /** * Compare the two operands and return an integer that describes whether the first value is larger, smaller or the same as the * second value. The semantics are identical to those of {@link Comparable}. The {@link #createZeroValue() zero value} is used * in place of any operand that is null. * * @param value1 the first operand * @param value2 the second operand * @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 * equal. */ public int compare( T value1, T value2 ); /** * Create a {@link BigDecimal} representation of the supplied value. * * @param value the value that is to be converted to a BigDecimal * @return the BigDecimal representation, or null if <code>value</code> is null */ public BigDecimal asBigDecimal( T value ); /** * Convert the {@link BigDecimal} representation into the natural object representation. This may result in loss of some data * (e.g., converting a decimal to an integer results in the loss of the fractional part of the number). * * @param value the BigDecimal value * @return the natural representation, or null if <code>value</code> is null */ public T fromBigDecimal( BigDecimal value ); /** * Convert the value to a double. This may result in a loss of information depending upon the {@link #getOperandClass() * operand class}. * * @param value the value * @return the representation as a double */ public double doubleValue( T value ); /** * Convert the value to a float. This may result in a loss of information depending upon the {@link #getOperandClass() operand * class}. * * @param value the value * @return the representation as a float */ public float floatValue( T value ); /** * Convert the value to an integer. This may result in a loss of information depending upon the {@link #getOperandClass() * operand class}. * * @param value the value * @return the representation as an integer */ public int intValue( T value ); /** * Convert the value to a short. This may result in a loss of information depending upon the {@link #getOperandClass() operand * class}. * * @param value the value * @return the representation as a short */ public short shortValue( T value ); /** * Convert the value to a long integer. This may result in a loss of information depending upon the {@link #getOperandClass() * operand class}. * * @param value the value * @return the representation as a long */ public long longValue( T value ); /** * Create the object form of the "zero value". This is often used to create an uninitialized object. * * @return the object that represents zero. */ public T createZeroValue(); /** * Convert the integer representation into the natural object representation. * * @param value the integer value * @return the object representation of the integer */ public T create( int value ); /** * Convert the long representation into the natural object representation. * * @param value the long value * @return the object representation of the long integer */ public T create( long value ); /** * Convert the double representation into the natural object representation. * * @param value the double value * @return the object representation of the floating point number */ public T create( double value ); /** * Return the square root of the supplied operand. * * @param value the value whose root is to be found; may not be null or 0 * @return the square root of the value */ public double sqrt( T value ); /** * Return a {@link Comparator Comparator<T>} for this {@link #getOperandClass() operand class}. The implementation is free to * return the same comparator instance from multiple invocations of this method. * * @return a comparator */ public Comparator<T> getComparator(); /** * Get the exponent if the number were written in exponential form. * * @param value the value * @return the scale */ public int getExponentInScientificNotation( T value ); /** * Round up the supplied value to the desired scale. This process works (conceptually) by shifting the decimal point of the * value by <code>decimalShift</code> places, rounding, and then shifting the decimal point of the rounded value by * <code>-decimalShift</code> * <p> * For example, consider the number 10.000354. This can be rounded to 10.0004 by calling this method and supplying the value * and an "exponentToKeep" value of -4. * </p> * * @param value the value to be rounded * @param decimalShift the number of places the decimal point should be shifted before rounding * @return the rounded value */ public T roundUp( T value, int decimalShift ); /** * Round down the supplied value to the desired scale. This process works (conceptually) by shifting the decimal point of the * value by <code>decimalShift</code> places, rounding, and then shifting the decimal point of the rounded value by * <code>-decimalShift</code> * <p> * For example, consider the number 10.000354. This can be rounded to 10.0003 by calling this method and supplying the value * and an "exponentToKeep" value of -4. * </p> * * @param value the value to be rounded * @param decimalShift the number of places the decimal point should be shifted before rounding * @return the rounded value */ public T roundDown( T value, int decimalShift ); public T keepSignificantFigures( T value, int numSigFigs ); /** * Generate a random instance within the specified range. * * @param minimum the minimum value, or null if the {@link #createZeroValue() zero-value} should be used for the minimum * @param maximum the maximum value, or null if the {@link #createZeroValue() zero-value} should be used for the maximum * @param rng the random number generator to use * @return an instance of the {@link #getOperandClass() operand class} placed within the desired range using a random * distribution, or null if this class does not support generating random instances */ public T random( T minimum, T maximum, Random rng ); }