    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 &pi;.
    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    }