1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.math3.util; 19 20 import org.apache.commons.math3.RealFieldElement; 21 import org.apache.commons.math3.exception.MathArithmeticException; 22 import org.apache.commons.math3.exception.NotFiniteNumberException; 23 import org.apache.commons.math3.exception.NullArgumentException; 24 import org.apache.commons.math3.exception.util.Localizable; 25 import org.apache.commons.math3.exception.util.LocalizedFormats; 26 27 import java.util.Arrays; 28 29 /** 30 * Miscellaneous utility functions. 31 * 32 * @see ArithmeticUtils 33 * @see Precision 34 * @see MathArrays 35 */ 36 public final class MathUtils { 37 /** 38 * \(2\pi\) 39 * 40 * @since 2.1 41 */ 42 public static final double TWO_PI = 2 * FastMath.PI; 43 44 /** 45 * \(\pi^2\) 46 * 47 * @since 3.4 48 */ 49 public static final double PI_SQUARED = FastMath.PI * FastMath.PI; 50 51 /** Class contains only static methods. */ MathUtils()52 private MathUtils() {} 53 54 /** 55 * Returns an integer hash code representing the given double value. 56 * 57 * @param value the value to be hashed 58 * @return the hash code 59 */ hash(double value)60 public static int hash(double value) { 61 return new Double(value).hashCode(); 62 } 63 64 /** 65 * Returns {@code true} if the values are equal according to semantics of {@link 66 * Double#equals(Object)}. 67 * 68 * @param x Value 69 * @param y Value 70 * @return {@code new Double(x).equals(new Double(y))} 71 */ equals(double x, double y)72 public static boolean equals(double x, double y) { 73 return new Double(x).equals(new Double(y)); 74 } 75 76 /** 77 * Returns an integer hash code representing the given double array. 78 * 79 * @param value the value to be hashed (may be null) 80 * @return the hash code 81 * @since 1.2 82 */ hash(double[] value)83 public static int hash(double[] value) { 84 return Arrays.hashCode(value); 85 } 86 87 /** 88 * Normalize an angle in a 2π wide interval around a center value. 89 * 90 * <p>This method has three main uses: 91 * 92 * <ul> 93 * <li>normalize an angle between 0 and 2π:<br> 94 * {@code a = MathUtils.normalizeAngle(a, FastMath.PI);} 95 * <li>normalize an angle between -π and +π<br> 96 * {@code a = MathUtils.normalizeAngle(a, 0.0);} 97 * <li>compute the angle between two defining angular positions:<br> 98 * {@code angle = MathUtils.normalizeAngle(end, start) - start;} 99 * </ul> 100 * 101 * <p>Note that due to numerical accuracy and since π cannot be represented exactly, the 102 * result interval is <em>closed</em>, it cannot be half-closed as would be more satisfactory in 103 * a purely mathematical view. 104 * 105 * @param a angle to normalize 106 * @param center center of the desired 2π interval for the result 107 * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π 108 * @since 1.2 109 */ normalizeAngle(double a, double center)110 public static double normalizeAngle(double a, double center) { 111 return a - TWO_PI * FastMath.floor((a + FastMath.PI - center) / TWO_PI); 112 } 113 114 /** 115 * Find the maximum of two field elements. 116 * 117 * @param <T> the type of the field elements 118 * @param e1 first element 119 * @param e2 second element 120 * @return max(a1, e2) 121 * @since 3.6 122 */ max(final T e1, final T e2)123 public static <T extends RealFieldElement<T>> T max(final T e1, final T e2) { 124 return e1.subtract(e2).getReal() >= 0 ? e1 : e2; 125 } 126 127 /** 128 * Find the minimum of two field elements. 129 * 130 * @param <T> the type of the field elements 131 * @param e1 first element 132 * @param e2 second element 133 * @return min(a1, e2) 134 * @since 3.6 135 */ min(final T e1, final T e2)136 public static <T extends RealFieldElement<T>> T min(final T e1, final T e2) { 137 return e1.subtract(e2).getReal() >= 0 ? e2 : e1; 138 } 139 140 /** 141 * Reduce {@code |a - offset|} to the primary interval {@code [0, |period|)}. 142 * 143 * <p>Specifically, the value returned is <br> 144 * {@code a - |period| * floor((a - offset) / |period|) - offset}. 145 * 146 * <p>If any of the parameters are {@code NaN} or infinite, the result is {@code NaN}. 147 * 148 * @param a Value to reduce. 149 * @param period Period. 150 * @param offset Value that will be mapped to {@code 0}. 151 * @return the value, within the interval {@code [0 |period|)}, that corresponds to {@code a}. 152 */ reduce(double a, double period, double offset)153 public static double reduce(double a, double period, 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 same sign as the 164 * {@code sign} argument. 165 * @throws MathArithmeticException if {@code magnitude == Byte.MIN_VALUE} and {@code sign >= 0}. 166 */ copySign(byte magnitude, byte sign)167 public static byte copySign(byte magnitude, byte sign) throws MathArithmeticException { 168 if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. 169 return magnitude; 170 } else if (sign >= 0 && magnitude == Byte.MIN_VALUE) { 171 throw new MathArithmeticException(LocalizedFormats.OVERFLOW); 172 } else { 173 return (byte) -magnitude; // Flip sign. 174 } 175 } 176 177 /** 178 * Returns the first argument with the sign of the second argument. 179 * 180 * @param magnitude Magnitude of the returned value. 181 * @param sign Sign of the returned value. 182 * @return a value with magnitude equal to {@code magnitude} and with the same sign as the 183 * {@code sign} argument. 184 * @throws MathArithmeticException if {@code magnitude == Short.MIN_VALUE} and {@code sign >= 185 * 0}. 186 */ copySign(short magnitude, short sign)187 public static short copySign(short magnitude, short sign) throws MathArithmeticException { 188 if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. 189 return magnitude; 190 } else if (sign >= 0 && magnitude == Short.MIN_VALUE) { 191 throw new MathArithmeticException(LocalizedFormats.OVERFLOW); 192 } else { 193 return (short) -magnitude; // Flip sign. 194 } 195 } 196 197 /** 198 * Returns the first argument with the sign of the second argument. 199 * 200 * @param magnitude Magnitude of the returned value. 201 * @param sign Sign of the returned value. 202 * @return a value with magnitude equal to {@code magnitude} and with the same sign as the 203 * {@code sign} argument. 204 * @throws MathArithmeticException if {@code magnitude == Integer.MIN_VALUE} and {@code sign >= 205 * 0}. 206 */ copySign(int magnitude, int sign)207 public static int copySign(int magnitude, int sign) throws MathArithmeticException { 208 if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. 209 return magnitude; 210 } else if (sign >= 0 && magnitude == Integer.MIN_VALUE) { 211 throw new MathArithmeticException(LocalizedFormats.OVERFLOW); 212 } else { 213 return -magnitude; // Flip sign. 214 } 215 } 216 217 /** 218 * Returns the first argument with the sign of the second argument. 219 * 220 * @param magnitude Magnitude of the returned value. 221 * @param sign Sign of the returned value. 222 * @return a value with magnitude equal to {@code magnitude} and with the same sign as the 223 * {@code sign} argument. 224 * @throws MathArithmeticException if {@code magnitude == Long.MIN_VALUE} and {@code sign >= 0}. 225 */ copySign(long magnitude, long sign)226 public static long copySign(long magnitude, long sign) throws MathArithmeticException { 227 if ((magnitude >= 0 && sign >= 0) || (magnitude < 0 && sign < 0)) { // Sign is OK. 228 return magnitude; 229 } else if (sign >= 0 && magnitude == Long.MIN_VALUE) { 230 throw new MathArithmeticException(LocalizedFormats.OVERFLOW); 231 } else { 232 return -magnitude; // Flip sign. 233 } 234 } 235 236 /** 237 * Check that the argument is a real number. 238 * 239 * @param x Argument. 240 * @throws NotFiniteNumberException if {@code x} is not a finite real number. 241 */ checkFinite(final double x)242 public static void checkFinite(final double x) throws NotFiniteNumberException { 243 if (Double.isInfinite(x) || Double.isNaN(x)) { 244 throw new NotFiniteNumberException(x); 245 } 246 } 247 248 /** 249 * Check that all the elements are real numbers. 250 * 251 * @param val Arguments. 252 * @throws NotFiniteNumberException if any values of the array is not a finite real number. 253 */ checkFinite(final double[] val)254 public static void checkFinite(final double[] val) throws NotFiniteNumberException { 255 for (int i = 0; i < val.length; i++) { 256 final double x = val[i]; 257 if (Double.isInfinite(x) || Double.isNaN(x)) { 258 throw new NotFiniteNumberException(LocalizedFormats.ARRAY_ELEMENT, x, i); 259 } 260 } 261 } 262 263 /** 264 * Checks that an object is not null. 265 * 266 * @param o Object to be checked. 267 * @param pattern Message pattern. 268 * @param args Arguments to replace the placeholders in {@code pattern}. 269 * @throws NullArgumentException if {@code o} is {@code null}. 270 */ checkNotNull(Object o, Localizable pattern, Object... args)271 public static void checkNotNull(Object o, Localizable pattern, Object... args) 272 throws NullArgumentException { 273 if (o == null) { 274 throw new NullArgumentException(pattern, args); 275 } 276 } 277 278 /** 279 * Checks that an object is not null. 280 * 281 * @param o Object to be checked. 282 * @throws NullArgumentException if {@code o} is {@code null}. 283 */ checkNotNull(Object o)284 public static void checkNotNull(Object o) throws NullArgumentException { 285 if (o == null) { 286 throw new NullArgumentException(); 287 } 288 } 289 } 290