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 }