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    
018    package org.apache.commons.math3.util;
019    
020    import java.util.Arrays;
021    
022    import org.apache.commons.math3.exception.MathArithmeticException;
023    import org.apache.commons.math3.exception.NotFiniteNumberException;
024    import org.apache.commons.math3.exception.NullArgumentException;
025    import org.apache.commons.math3.exception.util.Localizable;
026    import org.apache.commons.math3.exception.util.LocalizedFormats;
027    
028    /**
029     * Miscellaneous utility functions.
030     *
031     * @see ArithmeticUtils
032     * @see Precision
033     * @see MathArrays
034     *
035     * @version $Id: MathUtils.java 1416643 2012-12-03 19:37:14Z tn $
036     */
037    public final class MathUtils {
038        /**
039         * 2 π.
040         * @since 2.1
041         */
042        public static final double TWO_PI = 2 * FastMath.PI;
043    
044        /**
045         * Class contains only static methods.
046         */
047        private MathUtils() {}
048    
049    
050        /**
051         * Returns an integer hash code representing the given double value.
052         *
053         * @param value the value to be hashed
054         * @return the hash code
055         */
056        public static int hash(double value) {
057            return new Double(value).hashCode();
058        }
059    
060        /**
061         * Returns an integer hash code representing the given double array.
062         *
063         * @param value the value to be hashed (may be null)
064         * @return the hash code
065         * @since 1.2
066         */
067        public static int hash(double[] value) {
068            return Arrays.hashCode(value);
069        }
070    
071        /**
072         * Normalize an angle in a 2&pi wide interval around a center value.
073         * <p>This method has three main uses:</p>
074         * <ul>
075         *   <li>normalize an angle between 0 and 2&pi;:<br/>
076         *       {@code a = MathUtils.normalizeAngle(a, FastMath.PI);}</li>
077         *   <li>normalize an angle between -&pi; and +&pi;<br/>
078         *       {@code a = MathUtils.normalizeAngle(a, 0.0);}</li>
079         *   <li>compute the angle between two defining angular positions:<br>
080         *       {@code angle = MathUtils.normalizeAngle(end, start) - start;}</li>
081         * </ul>
082         * <p>Note that due to numerical accuracy and since &pi; cannot be represented
083         * exactly, the result interval is <em>closed</em>, it cannot be half-closed
084         * as would be more satisfactory in a purely mathematical view.</p>
085         * @param a angle to normalize
086         * @param center center of the desired 2&pi; interval for the result
087         * @return a-2k&pi; with integer k and center-&pi; &lt;= a-2k&pi; &lt;= center+&pi;
088         * @since 1.2
089         */
090         public static double normalizeAngle(double a, double center) {
091             return a - TWO_PI * FastMath.floor((a + FastMath.PI - center) / TWO_PI);
092         }
093    
094        /**
095         * <p>Reduce {@code |a - offset|} to the primary interval
096         * {@code [0, |period|)}.</p>
097         *
098         * <p>Specifically, the value returned is <br/>
099         * {@code a - |period| * floor((a - offset) / |period|) - offset}.</p>
100         *
101         * <p>If any of the parameters are {@code NaN} or infinite, the result is
102         * {@code NaN}.</p>
103         *
104         * @param a Value to reduce.
105         * @param period Period.
106         * @param offset Value that will be mapped to {@code 0}.
107         * @return the value, within the interval {@code [0 |period|)},
108         * that corresponds to {@code a}.
109         */
110        public static double reduce(double a,
111                                    double period,
112                                    double offset) {
113            final double p = FastMath.abs(period);
114            return a - p * FastMath.floor((a - offset) / p) - offset;
115        }
116    
117        /**
118         * Returns the first argument with the sign of the second argument.
119         *
120         * @param magnitude Magnitude of the returned value.
121         * @param sign Sign of the returned value.
122         * @return a value with magnitude equal to {@code magnitude} and with the
123         * same sign as the {@code sign} argument.
124         * @throws MathArithmeticException if {@code magnitude == Byte.MIN_VALUE}
125         * and {@code sign >= 0}.
126         */
127        public static byte copySign(byte magnitude, byte sign)
128            throws MathArithmeticException {
129            if ((magnitude >= 0 && sign >= 0) ||
130                (magnitude < 0 && sign < 0)) { // Sign is OK.
131                return magnitude;
132            } else if (sign >= 0 &&
133                       magnitude == Byte.MIN_VALUE) {
134                throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
135            } else {
136                return (byte) -magnitude; // Flip sign.
137            }
138        }
139    
140        /**
141         * Returns the first argument with the sign of the second argument.
142         *
143         * @param magnitude Magnitude of the returned value.
144         * @param sign Sign of the returned value.
145         * @return a value with magnitude equal to {@code magnitude} and with the
146         * same sign as the {@code sign} argument.
147         * @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE}
148         * and {@code sign >= 0}.
149         */
150        public static short copySign(short magnitude, short sign)
151                throws MathArithmeticException {
152            if ((magnitude >= 0 && sign >= 0) ||
153                (magnitude < 0 && sign < 0)) { // Sign is OK.
154                return magnitude;
155            } else if (sign >= 0 &&
156                       magnitude == Short.MIN_VALUE) {
157                throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
158            } else {
159                return (short) -magnitude; // Flip sign.
160            }
161        }
162    
163        /**
164         * Returns the first argument with the sign of the second argument.
165         *
166         * @param magnitude Magnitude of the returned value.
167         * @param sign Sign of the returned value.
168         * @return a value with magnitude equal to {@code magnitude} and with the
169         * same sign as the {@code sign} argument.
170         * @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE}
171         * and {@code sign >= 0}.
172         */
173        public static int copySign(int magnitude, int sign)
174                throws MathArithmeticException {
175            if ((magnitude >= 0 && sign >= 0) ||
176                (magnitude < 0 && sign < 0)) { // Sign is OK.
177                return magnitude;
178            } else if (sign >= 0 &&
179                       magnitude == Integer.MIN_VALUE) {
180                throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
181            } else {
182                return -magnitude; // Flip sign.
183            }
184        }
185    
186        /**
187         * Returns the first argument with the sign of the second argument.
188         *
189         * @param magnitude Magnitude of the returned value.
190         * @param sign Sign of the returned value.
191         * @return a value with magnitude equal to {@code magnitude} and with the
192         * same sign as the {@code sign} argument.
193         * @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE}
194         * and {@code sign >= 0}.
195         */
196        public static long copySign(long magnitude, long sign)
197            throws MathArithmeticException {
198            if ((magnitude >= 0 && sign >= 0) ||
199                (magnitude < 0 && sign < 0)) { // Sign is OK.
200                return magnitude;
201            } else if (sign >= 0 &&
202                       magnitude == Long.MIN_VALUE) {
203                throw new MathArithmeticException(LocalizedFormats.OVERFLOW);
204            } else {
205                return -magnitude; // Flip sign.
206            }
207        }
208        /**
209         * Check that the argument is a real number.
210         *
211         * @param x Argument.
212         * @throws NotFiniteNumberException if {@code x} is not a
213         * finite real number.
214         */
215        public static void checkFinite(final double x)
216            throws NotFiniteNumberException {
217            if (Double.isInfinite(x) || Double.isNaN(x)) {
218                throw new NotFiniteNumberException(x);
219            }
220        }
221    
222        /**
223         * Check that all the elements are real numbers.
224         *
225         * @param val Arguments.
226         * @throws NotFiniteNumberException if any values of the array is not a
227         * finite real number.
228         */
229        public static void checkFinite(final double[] val)
230            throws NotFiniteNumberException {
231            for (int i = 0; i < val.length; i++) {
232                final double x = val[i];
233                if (Double.isInfinite(x) || Double.isNaN(x)) {
234                    throw new NotFiniteNumberException(LocalizedFormats.ARRAY_ELEMENT, x, i);
235                }
236            }
237        }
238    
239        /**
240         * Checks that an object is not null.
241         *
242         * @param o Object to be checked.
243         * @param pattern Message pattern.
244         * @param args Arguments to replace the placeholders in {@code pattern}.
245         * @throws NullArgumentException if {@code o} is {@code null}.
246         */
247        public static void checkNotNull(Object o,
248                                        Localizable pattern,
249                                        Object ... args)
250            throws NullArgumentException {
251            if (o == null) {
252                throw new NullArgumentException(pattern, args);
253            }
254        }
255    
256        /**
257         * Checks that an object is not null.
258         *
259         * @param o Object to be checked.
260         * @throws NullArgumentException if {@code o} is {@code null}.
261         */
262        public static void checkNotNull(Object o)
263            throws NullArgumentException {
264            if (o == null) {
265                throw new NullArgumentException();
266            }
267        }
268    }