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π:<br/>
076 * {@code a = MathUtils.normalizeAngle(a, FastMath.PI);}</li>
077 * <li>normalize an angle between -π and +π<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 π 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π interval for the result
087 * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π
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 }