/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.commons.math3.util; import org.apache.commons.math3.RealFieldElement; import org.apache.commons.math3.exception.MathArithmeticException; import org.apache.commons.math3.exception.NotFiniteNumberException; import org.apache.commons.math3.exception.NullArgumentException; import org.apache.commons.math3.exception.util.Localizable; import org.apache.commons.math3.exception.util.LocalizedFormats; import java.util.Arrays; /** * Miscellaneous utility functions. * * @see ArithmeticUtils * @see Precision * @see MathArrays */ public final class MathUtils { /** * \(2\pi\) * * @since 2.1 */ public static final double TWO_PI = 2 * FastMath.PI; /** * \(\pi^2\) * * @since 3.4 */ public static final double PI_SQUARED = FastMath.PI * FastMath.PI; /** Class contains only static methods. */ private MathUtils() {} /** * Returns an integer hash code representing the given double value. * * @param value the value to be hashed * @return the hash code */ public static int hash(double value) { return new Double(value).hashCode(); } /** * Returns {@code true} if the values are equal according to semantics of {@link * Double#equals(Object)}. * * @param x Value * @param y Value * @return {@code new Double(x).equals(new Double(y))} */ public static boolean equals(double x, double y) { return new Double(x).equals(new Double(y)); } /** * Returns an integer hash code representing the given double array. * * @param value the value to be hashed (may be null) * @return the hash code * @since 1.2 */ public static int hash(double[] value) { return Arrays.hashCode(value); } /** * Normalize an angle in a 2π wide interval around a center value. * *
This method has three main uses: * *
Note that due to numerical accuracy and since π cannot be represented exactly, the
* result interval is closed, it cannot be half-closed as would be more satisfactory in
* a purely mathematical view.
*
* @param a angle to normalize
* @param center center of the desired 2π interval for the result
* @return a-2kπ with integer k and center-π <= a-2kπ <= center+π
* @since 1.2
*/
public static double normalizeAngle(double a, double center) {
return a - TWO_PI * FastMath.floor((a + FastMath.PI - center) / TWO_PI);
}
/**
* Find the maximum of two field elements.
*
* @param Specifically, the value returned is If any of the parameters are {@code NaN} or infinite, the result is {@code NaN}.
*
* @param a Value to reduce.
* @param period Period.
* @param offset Value that will be mapped to {@code 0}.
* @return the value, within the interval {@code [0 |period|)}, that corresponds to {@code a}.
*/
public static double reduce(double a, double period, double offset) {
final double p = FastMath.abs(period);
return a - p * FastMath.floor((a - offset) / p) - offset;
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the same sign as the
* {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Byte.MIN_VALUE} and {@code sign >= 0}.
*/
public static byte copySign(byte magnitude, byte sign) throws MathArithmeticException {
if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 && magnitude == Byte.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return (byte) -magnitude; // Flip sign.
}
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the same sign as the
* {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE} and {@code sign >=
* 0}.
*/
public static short copySign(short magnitude, short sign) throws MathArithmeticException {
if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 && magnitude == Short.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return (short) -magnitude; // Flip sign.
}
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the same sign as the
* {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE} and {@code sign >=
* 0}.
*/
public static int copySign(int magnitude, int sign) throws MathArithmeticException {
if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 && magnitude == Integer.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return -magnitude; // Flip sign.
}
}
/**
* Returns the first argument with the sign of the second argument.
*
* @param magnitude Magnitude of the returned value.
* @param sign Sign of the returned value.
* @return a value with magnitude equal to {@code magnitude} and with the same sign as the
* {@code sign} argument.
* @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE} and {@code sign >= 0}.
*/
public static long copySign(long magnitude, long sign) throws MathArithmeticException {
if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK.
return magnitude;
} else if (sign >= 0 && magnitude == Long.MIN_VALUE) {
throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
} else {
return -magnitude; // Flip sign.
}
}
/**
* Check that the argument is a real number.
*
* @param x Argument.
* @throws NotFiniteNumberException if {@code x} is not a finite real number.
*/
public static void checkFinite(final double x) throws NotFiniteNumberException {
if (Double.isInfinite(x) || Double.isNaN(x)) {
throw new NotFiniteNumberException(x);
}
}
/**
* Check that all the elements are real numbers.
*
* @param val Arguments.
* @throws NotFiniteNumberException if any values of the array is not a finite real number.
*/
public static void checkFinite(final double[] val) throws NotFiniteNumberException {
for (int i = 0; i < val.length; i++) {
final double x = val[i];
if (Double.isInfinite(x) || Double.isNaN(x)) {
throw new NotFiniteNumberException(LocalizedFormats.ARRAY_ELEMENT, x, i);
}
}
}
/**
* Checks that an object is not null.
*
* @param o Object to be checked.
* @param pattern Message pattern.
* @param args Arguments to replace the placeholders in {@code pattern}.
* @throws NullArgumentException if {@code o} is {@code null}.
*/
public static void checkNotNull(Object o, Localizable pattern, Object... args)
throws NullArgumentException {
if (o == null) {
throw new NullArgumentException(pattern, args);
}
}
/**
* Checks that an object is not null.
*
* @param o Object to be checked.
* @throws NullArgumentException if {@code o} is {@code null}.
*/
public static void checkNotNull(Object o) throws NullArgumentException {
if (o == null) {
throw new NullArgumentException();
}
}
}
* {@code a - |period| * floor((a - offset) / |period|) - offset}.
*
*