/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package eglx.lang;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.eclipse.edt.javart.AnyBoxedObject;
import org.eclipse.edt.javart.Constants;
import org.eclipse.edt.javart.resources.ExecutableBase;
public class MathLib extends ExecutableBase {
private static final long serialVersionUID = Constants.SERIAL_VERSION_UID;
/**
* A constant used by log10. The value is StrictMath.log(10).
*/
private static final double LOG_OF_10 = 2.302585092994046;
/**
* A mask that can extract the exponent bits from the bits of a double.
*/
private static final long DOUBLE_EXPONENT_MASK = 0x7ff0000000000000L;
/**
* The number of bits in the mantissa of a double.
*/
private static final int DOUBLE_MANTISSA_LENGTH = 52;
/**
* A bit pattern which can be anded to a double to set its exponent to zero.
*/
private static final long DOUBLE_NO_EXPONENT_MASK = 0x800fffffffffffffL;
/**
* The largest biased exponent a double may have if it's not infinite or NaN.
*/
private static final int DOUBLE_MAX_EXPONENT = 0x7fe;
/**
* The amount that the exponent of a double is biased.
*/
private static final int DOUBLE_EXPONENT_BIAS = 1022;
/**
* A mask that can extract the sign bit from the bits of a double.
*/
private static final long DOUBLE_SIGN_MASK = 0x8000000000000000L;
/**
* A bit pattern which when considered as a double will have a mantissa of zero with a biased zero exponent.
*/
private static final long DOUBLE_ZERO_EXPONENT = ((long) DOUBLE_EXPONENT_BIAS << DOUBLE_MANTISSA_LENGTH);
/**
* A mask that can extract the mantissa bits from the bits of a double.
*/
private static final long DOUBLE_MANTISSA_MASK = 0x000fffffffffffffL;
/**
* The constructor.
*/
public MathLib() throws AnyException {
}
/**
* Computes the absolute value of <code>numericField</code>.
*/
public static short abs(short numericField) {
if (numericField < 0)
return (short)-numericField;
return numericField;
}
public static int abs(int numericField) {
if (numericField < 0)
return -numericField;
return numericField;
}
public static long abs(long numericField) {
if (numericField < 0)
return -numericField;
return numericField;
}
public static double abs(double numericField) {
return StrictMath.abs(numericField);
}
public static float abs(float numericField) {
return StrictMath.abs(numericField);
}
public static BigDecimal abs(BigDecimal numericField) {
return numericField.abs();
}
/**
* Computes the arc cos of <code>numericField</code>.
*/
public static double acos(double numericField) {
if (numericField < -1 || numericField > 1)
return Double.NaN;
return StrictMath.acos(numericField);
}
/**
* Computes the arc sin of <code>numericField</code>.
*/
public static double asin(double numericField) {
if (numericField < -1 || numericField > 1)
return Double.NaN;
return StrictMath.asin(numericField);
}
/**
* Computes the arc tan of <code>numericField</code>.
*/
public static double atan(double numericField) {
return StrictMath.atan(numericField);
}
/**
* Computes the arc tan of <code>numericField1 / numericField2</code> in the range -PI to PI.
*/
public static double atan2(double numericField1, double numericField2) {
return StrictMath.atan2(numericField1, numericField2);
}
/**
* Computes the ceiling of <code>numericField</code>. Ceiling is the smallest (closest to negative infinity)
* floating-point value that is not less than the argument and is equal to a mathematical integer.
*/
public static double ceiling(double numericField) {
return StrictMath.ceil(numericField);
}
/**
* Computes the ceiling of <code>numericField</code>. Ceiling is the smallest (closest to negative infinity)
* floating-point value that is not less than the argument and is equal to a mathematical integer.
*/
public static BigDecimal ceiling(BigDecimal numericField) {
return numericField.setScale(0, BigDecimal.ROUND_CEILING);
}
/**
* Computes the cos of <code>numericField</code>.
*/
public static double cos(double numericField) {
return StrictMath.cos(numericField);
}
/**
* Computes the hyperbolic cosine of <code>numericField</code>.
*/
public static double cosh(double numericField) {
return StrictMath.cosh(numericField);
}
/**
* Computes the exp of <code>numericField</code>. e to the power(<code>numericField</code>)
*/
public static double exp(double numericField) {
return StrictMath.exp(numericField);
}
/**
* Computes the floor of <code>numericField</code>: the largest (closest to positive infinity) floating-point value that
* is not greater than the argument and is equal to a mathematical integer.
*/
public static double floor(double numericField) {
return StrictMath.floor(numericField);
}
/**
* Computes the floor of <code>numericField</code>: the largest (closest to positive infinity) floating-point value that
* is not greater than the argument and is equal to a mathematical integer.
*/
public static BigDecimal floor(BigDecimal numericField) {
return numericField.setScale(0, BigDecimal.ROUND_FLOOR);
}
/**
* Breaks <code>numericField</code> into its mantissa, which is stored in <code>result</code>, and its exponent, which is
* stored in <code>exponent</code>.
*/
public static double frexp(double numericField, AnyBoxedObject<Integer> exponent) {
// Get the number to be split.
double value = numericField;
// Extract the exponent.
long bits = Double.doubleToLongBits(numericField);
int exp = (int) ((bits & DOUBLE_EXPONENT_MASK) >> DOUBLE_MANTISSA_LENGTH);
// See if it's a "normal" number.
if (0 < exp && exp <= DOUBLE_MAX_EXPONENT) {
// Unbias the exponent.
exp -= DOUBLE_EXPONENT_BIAS;
// Store the exponent.
exponent.ezeCopy(exp);
// Give the mantissa a zero exponent.
long mantissa = bits & (DOUBLE_SIGN_MASK | DOUBLE_MANTISSA_MASK);
mantissa |= DOUBLE_ZERO_EXPONENT;
// Turn the mantissa into a double.
value = Double.longBitsToDouble(mantissa);
} else {
// value is either NaN, positive or negative zero, positive
// or negative Infinity, or a denormalized number. All of
// these cases are handled the same.
exponent.ezeCopy(0);
}
return value;
}
/**
* Multiplies <code>numericField</code> by 2<sup><code>power</code></sup> and stores the answer in <code>result</code>.
*/
public static double ldexp(double numericField, int pow) {
// Convert the value of numericField to its bit pattern, get the current
// exponent, and remove it from the bit string.
double value = numericField;
long bits = Double.doubleToLongBits(value);
long exp = (bits & DOUBLE_EXPONENT_MASK) >> DOUBLE_MANTISSA_LENGTH;
bits &= DOUBLE_NO_EXPONENT_MASK;
// Increase the exponent by adding pow, and quit if the new exponent
// is too big or too small.
exp += pow;
if (exp < 0 || exp > DOUBLE_MAX_EXPONENT)
return Double.NaN;
// Construct the new double and assign it to result.
bits |= (exp << DOUBLE_MANTISSA_LENGTH);
return Double.longBitsToDouble(bits);
}
/**
* Computes the log of <code>numericField</code>. the natural logarithm (base e) of <code>numericField</code>
*/
public static double log(double numericField) {
if (numericField <= 0)
return Double.NaN;
return StrictMath.log(numericField);
}
/**
* Computes the log of <code>numericField</code>. the logarithm (base 10) of <code>numericField</code>
*/
public static double log10(double numericField) {
if (numericField <= 0)
return Double.NaN;
// Compute the log and return the result. Since Java has no
// log10 method, we use the formula log_b(x) = nl(x) / nl(b).
return StrictMath.log(numericField) / LOG_OF_10;
}
/**
* Computes the maximum of the fields
*/
public static short max(short numericField1, short numericField2) {
if (numericField1 < numericField2)
return numericField2;
return numericField1;
}
public static int max(int numericField1, int numericField2) {
if (numericField1 < numericField2)
return numericField2;
return numericField1;
}
public static long max(long numericField1, long numericField2) {
if (numericField1 < numericField2)
return numericField2;
return numericField1;
}
public static double max(double numericField1, double numericField2) {
return StrictMath.max(numericField1, numericField2);
}
public static float max(float numericField1, float numericField2) {
return StrictMath.max(numericField1, numericField2);
}
public static BigDecimal max(BigDecimal numericField1, BigDecimal numericField2) {
return numericField1.max(numericField2);
}
/**
* Computes the minimum of the fields
*/
public static short min(short numericField1, short numericField2) {
if (numericField1 < numericField2)
return numericField1;
return numericField2;
}
public static int min(int numericField1, int numericField2) {
if (numericField1 < numericField2)
return numericField1;
return numericField2;
}
public static long min(long numericField1, long numericField2) {
if (numericField1 < numericField2)
return numericField1;
return numericField2;
}
public static double min(double numericField1, double numericField2) {
return StrictMath.min(numericField1, numericField2);
}
public static float min(float numericField1, float numericField2) {
return StrictMath.min(numericField1, numericField2);
}
public static BigDecimal min(BigDecimal numericField1, BigDecimal numericField2) {
return numericField1.min(numericField2);
}
/**
* Stores the integral part of <code>op1</code> in <code>op2</code> and the fractional part in <code>result</code>
*/
public static double modf(double numericField1, AnyBoxedObject<Double> numericField2) {
// Get the number and split it.
BigDecimal bd = new BigDecimal(numericField1);
BigInteger intPart = bd.toBigInteger();
// Store the integral part in numericField2.
numericField2.ezeCopy(intPart.doubleValue());
BigDecimal fractPart = new BigDecimal(intPart).subtract(bd).negate();
return fractPart.doubleValue();
}
/**
* Computes <code>op1</code> to the power of <code>op2</code>.
*/
public static double pow(double op1, double op2) {
// Check the args. If op1 is 0, op2 must be > 0. If op1 is
// negative, op2 must be a whole number.
if (op1 == 0 && op2 <= 0)
return Double.POSITIVE_INFINITY;
else if (op1 < 0 && op2 > StrictMath.floor(op2))
return Double.NaN;
return StrictMath.pow(op1, op2);
}
/**
* Generates a random number between 0 (inclusive) and 1 (exclusive).
*/
public static double random() {
return Math.random();
}
/**
* Rounds a number or expression to a nearest value (for example, to the nearest thousands) and returns the result.
*/
public static float round(float value, int exp) {
return round( BigDecimal.valueOf( value ), exp ).floatValue();
}
public static double round(double value, int exp) {
return round( BigDecimal.valueOf( value ), exp ).doubleValue();
}
public static BigDecimal round(BigDecimal value, int exp) {
// Round it.
BigDecimal rounder;
if (exp > 0) {
rounder = BigDecimal.valueOf(5);
rounder = rounder.movePointRight(exp - 1);
} else
rounder = BigDecimal.valueOf(5, -exp + 1);
if (value.signum() >= 0)
// Round positive numbers up.
value = value.add(rounder);
else
// Round negative numbers down.
value = value.subtract(rounder);
// Zero out the digits past the ones we rounded.
if (exp > 0) {
value = value.movePointLeft(exp);
value = new BigDecimal(value.toBigInteger());
value = value.movePointRight(exp);
} else {
value = value.movePointRight(-exp);
value = new BigDecimal(value.toBigInteger());
value = value.movePointLeft(-exp);
}
return value;
}
/**
* Computes the sine of <code>numericField</code>.
*/
public static double sin(double numericField) {
return StrictMath.sin(numericField);
}
/**
* Computes the hyperbolic sine of <code>numericField</code>.
*/
public static double sinh(double numericField) {
return StrictMath.sinh(numericField);
}
/**
* Computes the squareroot of <code>numericField</code>.
*/
public static double sqrt(double numericField) {
if (numericField < 0)
return Double.NaN;
return StrictMath.sqrt(numericField);
}
/**
* Computes the tangent of <code>numericField</code>.
*/
public static double tan(double numericField) {
return StrictMath.tan(numericField);
}
/**
* Computes the hyperbolic tangent of <code>numericField</code>.
*/
public static double tanh(double numericField) {
return StrictMath.tanh(numericField);
}
}