001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.math3.util;
019
020import java.util.Arrays;
021
022import org.apache.commons.math3.RealFieldElement;
023import org.apache.commons.math3.exception.MathArithmeticException;
024import org.apache.commons.math3.exception.NotFiniteNumberException;
025import org.apache.commons.math3.exception.NullArgumentException;
026import org.apache.commons.math3.exception.util.Localizable;
027import org.apache.commons.math3.exception.util.LocalizedFormats;
028
029/**
030 * Miscellaneous utility functions.
031 *
032 * @see ArithmeticUtils
033 * @see Precision
034 * @see MathArrays
035 *
036 */
037public final class MathUtils {
038    /**
039     * \(2\pi\)
040     * @since 2.1
041     */
042    public static final double TWO_PI = 2 * FastMath.PI;
043
044    /**
045     * \(\pi^2\)
046     * @since 3.4
047     */
048    public static final double PI_SQUARED = FastMath.PI * FastMath.PI;
049
050
051    /**
052     * Class contains only static methods.
053     */
054    private MathUtils() {}
055
056
057    /**
058     * Returns an integer hash code representing the given double value.
059     *
060     * @param value the value to be hashed
061     * @return the hash code
062     */
063    public static int hash(double value) {
064        return new Double(value).hashCode();
065    }
066
067    /**
068     * Returns {@code true} if the values are equal according to semantics of
069     * {@link Double#equals(Object)}.
070     *
071     * @param x Value
072     * @param y Value
073     * @return {@code new Double(x).equals(new Double(y))}
074     */
075    public static boolean equals(double x, double y) {
076        return new Double(x).equals(new Double(y));
077    }
078
079    /**
080     * Returns an integer hash code representing the given double array.
081     *
082     * @param value the value to be hashed (may be null)
083     * @return the hash code
084     * @since 1.2
085     */
086    public static int hash(double[] value) {
087        return Arrays.hashCode(value);
088    }
089
090    /**
091     * Normalize an angle in a 2π wide interval around a center value.
092     * <p>This method has three main uses:</p>
093     * <ul>
094     *   <li>normalize an angle between 0 and 2&pi;:<br/>
095     *       {@code a = MathUtils.normalizeAngle(a, FastMath.PI);}</li>
096     *   <li>normalize an angle between -&pi; and +&pi;<br/>
097     *       {@code a = MathUtils.normalizeAngle(a, 0.0);}</li>
098     *   <li>compute the angle between two defining angular positions:<br>
099     *       {@code angle = MathUtils.normalizeAngle(end, start) - start;}</li>
100     * </ul>
101     * <p>Note that due to numerical accuracy and since &pi; cannot be represented
102     * exactly, the result interval is <em>closed</em>, it cannot be half-closed
103     * as would be more satisfactory in a purely mathematical view.</p>
104     * @param a angle to normalize
105     * @param center center of the desired 2&pi; interval for the result
106     * @return a-2k&pi; with integer k and center-&pi; &lt;= a-2k&pi; &lt;= center+&pi;
107     * @since 1.2
108     */
109     public static double normalizeAngle(double a, double center) {
110         return a - TWO_PI * FastMath.floor((a + FastMath.PI - center) / TWO_PI);
111     }
112
113     /** Find the maximum of two field elements.
114      * @param <T> the type of the field elements
115      * @param e1 first element
116      * @param e2 second element
117      * @return max(a1, e2)
118      * @since 3.6
119      */
120     public static <T extends RealFieldElement<T>> T max(final T e1, final T e2) {
121         return e1.subtract(e2).getReal() >= 0 ? e1 : e2;
122     }
123
124     /** Find the minimum of two field elements.
125      * @param <T> the type of the field elements
126      * @param e1 first element
127      * @param e2 second element
128      * @return min(a1, e2)
129      * @since 3.6
130      */
131     public static <T extends RealFieldElement<T>> T min(final T e1, final T e2) {
132         return e1.subtract(e2).getReal() >= 0 ? e2 : e1;
133     }
134
135    /**
136     * <p>Reduce {@code |a - offset|} to the primary interval
137     * {@code [0, |period|)}.</p>
138     *
139     * <p>Specifically, the value returned is <br/>
140     * {@code a - |period| * floor((a - offset) / |period|) - offset}.</p>
141     *
142     * <p>If any of the parameters are {@code NaN} or infinite, the result is
143     * {@code NaN}.</p>
144     *
145     * @param a Value to reduce.
146     * @param period Period.
147     * @param offset Value that will be mapped to {@code 0}.
148     * @return the value, within the interval {@code [0 |period|)},
149     * that corresponds to {@code a}.
150     */
151    public static double reduce(double a,
152                                double period,
153                                double offset) {
154        final double p = FastMath.abs(period);
155        return a - p * FastMath.floor((a - offset) / p) - offset;
156    }
157
158    /**
159     * Returns the first argument with the sign of the second argument.
160     *
161     * @param magnitude Magnitude of the returned value.
162     * @param sign Sign of the returned value.
163     * @return a value with magnitude equal to {@code magnitude} and with the
164     * same sign as the {@code sign} argument.
165     * @throws MathArithmeticException if {@code magnitude == Byte.MIN_VALUE}
166     * and {@code sign >= 0}.
167     */
168    public static byte copySign(byte magnitude, byte sign)
169        throws MathArithmeticException {
170        if ((magnitude >= 0 && sign >= 0) ||
171            (magnitude < 0 && sign < 0)) { // Sign is OK.
172            return magnitude;
173        } else if (sign >= 0 &&
174                   magnitude == Byte.MIN_VALUE) {
175            throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
176        } else {
177            return (byte) -magnitude; // Flip sign.
178        }
179    }
180
181    /**
182     * Returns the first argument with the sign of the second argument.
183     *
184     * @param magnitude Magnitude of the returned value.
185     * @param sign Sign of the returned value.
186     * @return a value with magnitude equal to {@code magnitude} and with the
187     * same sign as the {@code sign} argument.
188     * @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE}
189     * and {@code sign >= 0}.
190     */
191    public static short copySign(short magnitude, short sign)
192            throws MathArithmeticException {
193        if ((magnitude >= 0 && sign >= 0) ||
194            (magnitude < 0 && sign < 0)) { // Sign is OK.
195            return magnitude;
196        } else if (sign >= 0 &&
197                   magnitude == Short.MIN_VALUE) {
198            throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
199        } else {
200            return (short) -magnitude; // Flip sign.
201        }
202    }
203
204    /**
205     * Returns the first argument with the sign of the second argument.
206     *
207     * @param magnitude Magnitude of the returned value.
208     * @param sign Sign of the returned value.
209     * @return a value with magnitude equal to {@code magnitude} and with the
210     * same sign as the {@code sign} argument.
211     * @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE}
212     * and {@code sign >= 0}.
213     */
214    public static int copySign(int magnitude, int sign)
215            throws MathArithmeticException {
216        if ((magnitude >= 0 && sign >= 0) ||
217            (magnitude < 0 && sign < 0)) { // Sign is OK.
218            return magnitude;
219        } else if (sign >= 0 &&
220                   magnitude == Integer.MIN_VALUE) {
221            throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
222        } else {
223            return -magnitude; // Flip sign.
224        }
225    }
226
227    /**
228     * Returns the first argument with the sign of the second argument.
229     *
230     * @param magnitude Magnitude of the returned value.
231     * @param sign Sign of the returned value.
232     * @return a value with magnitude equal to {@code magnitude} and with the
233     * same sign as the {@code sign} argument.
234     * @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE}
235     * and {@code sign >= 0}.
236     */
237    public static long copySign(long magnitude, long sign)
238        throws MathArithmeticException {
239        if ((magnitude >= 0 && sign >= 0) ||
240            (magnitude < 0 && sign < 0)) { // Sign is OK.
241            return magnitude;
242        } else if (sign >= 0 &&
243                   magnitude == Long.MIN_VALUE) {
244            throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
245        } else {
246            return -magnitude; // Flip sign.
247        }
248    }
249    /**
250     * Check that the argument is a real number.
251     *
252     * @param x Argument.
253     * @throws NotFiniteNumberException if {@code x} is not a
254     * finite real number.
255     */
256    public static void checkFinite(final double x)
257        throws NotFiniteNumberException {
258        if (Double.isInfinite(x) || Double.isNaN(x)) {
259            throw new NotFiniteNumberException(x);
260        }
261    }
262
263    /**
264     * Check that all the elements are real numbers.
265     *
266     * @param val Arguments.
267     * @throws NotFiniteNumberException if any values of the array is not a
268     * finite real number.
269     */
270    public static void checkFinite(final double[] val)
271        throws NotFiniteNumberException {
272        for (int i = 0; i < val.length; i++) {
273            final double x = val[i];
274            if (Double.isInfinite(x) || Double.isNaN(x)) {
275                throw new NotFiniteNumberException(LocalizedFormats.ARRAY_ELEMENT, x, i);
276            }
277        }
278    }
279
280    /**
281     * Checks that an object is not null.
282     *
283     * @param o Object to be checked.
284     * @param pattern Message pattern.
285     * @param args Arguments to replace the placeholders in {@code pattern}.
286     * @throws NullArgumentException if {@code o} is {@code null}.
287     */
288    public static void checkNotNull(Object o,
289                                    Localizable pattern,
290                                    Object ... args)
291        throws NullArgumentException {
292        if (o == null) {
293            throw new NullArgumentException(pattern, args);
294        }
295    }
296
297    /**
298     * Checks that an object is not null.
299     *
300     * @param o Object to be checked.
301     * @throws NullArgumentException if {@code o} is {@code null}.
302     */
303    public static void checkNotNull(Object o)
304        throws NullArgumentException {
305        if (o == null) {
306            throw new NullArgumentException();
307        }
308    }
309}