/*
* 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 );
}