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