/*
* __ .__ .__ ._____.
* _/ |_ _______ __|__| ____ | | |__\_ |__ ______
* \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
* | | ( <_> > <| \ \___| |_| || \_\ \\___ \
* |__| \____/__/\_ \__|\___ >____/__||___ /____ >
* \/ \/ \/ \/
*
* Copyright (c) 2006-2011 Karsten Schmidt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* http://creativecommons.org/licenses/LGPL/2.1/
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
package toxi.math;
import java.util.Random;
/**
* Miscellaneous math utilities.
*/
public final class MathUtils {
/**
*
*/
public static final float THIRD = 1f / 3;
/**
* Square root of 2
*/
public static final float SQRT2 = (float) Math.sqrt(2);
/**
* Square root of 3
*/
public static final float SQRT3 = (float) Math.sqrt(3);
/**
* Log(2)
*/
public static final float LOG2 = (float) Math.log(2);
/**
* PI
*/
public static final float PI = 3.14159265358979323846f;
/**
* The reciprocal of PI: (1/PI)
*/
public static final float INV_PI = 1f / PI;
/**
* PI/2
*/
public static final float HALF_PI = PI / 2;
/**
* PI/3
*/
public static final float THIRD_PI = PI / 3;
/**
* PI/4
*/
public static final float QUARTER_PI = PI / 4;
/**
* PI*2
*/
public static final float TWO_PI = PI * 2;
/**
* PI*1.5
*/
public static final float THREE_HALVES_PI = TWO_PI - HALF_PI;
/**
* PI*PI
*/
public static final float PI_SQUARED = PI * PI;
/**
* Epsilon value
*/
public static final float EPS = 1.1920928955078125E-7f;
/**
* Degrees to radians conversion factor
*/
public static final float DEG2RAD = PI / 180;
/**
* Radians to degrees conversion factor
*/
public static final float RAD2DEG = 180 / PI;
private static final float SHIFT23 = 1 << 23;
private static final float INV_SHIFT23 = 1.0f / SHIFT23;
private final static double SIN_A = -4d / (PI * PI);
private final static double SIN_B = 4d / PI;
private final static double SIN_P = 9d / 40;
/**
* Default random number generator used by random methods of this class
* which don't use a passed in {@link Random} instance.
*/
public static Random RND = new Random();
/**
* @param x
* @return absolute value of x
*/
public static final double abs(double x) {
return x < 0 ? -x : x;
}
/**
* @param x
* @return absolute value of x
*/
public static final float abs(float x) {
return x < 0 ? -x : x;
}
/**
* @param x
* @return absolute value of x
*/
public static final int abs(int x) {
int y = x >> 31;
return (x ^ y) - y;
}
/**
* Rounds up the value to the nearest higher power^2 value.
*
* @param x
* @return power^2 value
*/
public static final int ceilPowerOf2(int x) {
int pow2 = 1;
while (pow2 < x) {
pow2 <<= 1;
}
return pow2;
}
/**
*
* @param a
* @param min
* @param max
* @return
*/
public static final double clip(double a, double min, double max) {
return a < min ? min : (a > max ? max : a);
}
/**
*
* @param a
* @param min
* @param max
* @return
*/
public static final float clip(float a, float min, float max) {
return a < min ? min : (a > max ? max : a);
}
/**
*
* @param a
* @param min
* @param max
* @return
*/
public static final int clip(int a, int min, int max) {
return a < min ? min : (a > max ? max : a);
}
/**
*
* @param a
* @return
*/
public static double clipNormalized(double a) {
if (a < 0) {
return 0;
} else if (a > 1) {
return 1;
}
return a;
}
/**
* Clips the value to the 0.0 .. 1.0 interval.
*
* @param a
* @return clipped value
* @since 0012
*/
public static final float clipNormalized(float a) {
if (a < 0) {
return 0;
} else if (a > 1) {
return 1;
}
return a;
}
/**
*
* @param theta
* @return
*/
public static final double cos(final double theta) {
return sin(theta + HALF_PI);
}
/**
* Returns fast cosine approximation of a value. Note: code from wiki posting on
* java.net by jeffpk
*
* @param theta
* angle in radians.
* @return cosine of theta.
*/
public static final float cos(final float theta) {
return sin(theta + HALF_PI);
}
/**
*
* @param radians
* @return
*/
public static final double degrees(double radians) {
return radians * RAD2DEG;
}
/**
*
* @param radians
* @return
*/
public static final float degrees(float radians) {
return radians * RAD2DEG;
}
/**
*
* @param a
* @param b
* @return
*/
public static double dualSign(double a, double b) {
double x = (a >= 0 ? a : -a);
return (b >= 0 ? x : -x);
}
/**
* Fast cosine approximation.
*
* @param x
* angle in -PI/2 .. +PI/2 interval
* @return cosine
*/
public static final double fastCos(final double x) {
return fastSin(x + ((x > HALF_PI) ? -THREE_HALVES_PI : HALF_PI));
}
/**
* @param x
* @return
* @deprecated
*/
@Deprecated
public static final float fastInverseSqrt(float x) {
float half = 0.5F * x;
int i = Float.floatToIntBits(x);
i = 0x5f375a86 - (i >> 1);
x = Float.intBitsToFloat(i);
return x * (1.5F - half * x * x);
}
/**
* Computes a fast approximation to Math.pow(a, b)
. Adapted
* from http://www.dctsystems.co.uk/Software/power.html.
*
* @param a
* a positive number
* @param b
* a number
* @return a^b
*
*/
public static final float fastPow(float a, float b) {
float x = Float.floatToRawIntBits(a);
x *= INV_SHIFT23;
x -= 127;
float y = x - (x >= 0 ? (int) x : (int) x - 1);
b *= x + (y - y * y) * 0.346607f;
y = b - (b >= 0 ? (int) b : (int) b - 1);
y = (y - y * y) * 0.33971f;
return Float.intBitsToFloat((int) ((b + 127 - y) * SHIFT23));
}
/**
* Fast sine approximation.
*
* @param x
* angle in -PI/2 .. +PI/2 interval
* @return sine
*/
public static final double fastSin(double x) {
// float B = 4/pi;
// float C = -4/(pi*pi);
// float y = B * x + C * x * abs(x);
// y = P * (y * abs(y) - y) + y;
x = SIN_B * x + SIN_A * x * abs(x);
return SIN_P * (x * abs(x) - x) + x;
}
/**
*
* @return
*/
public static final boolean flipCoin() {
return RND.nextBoolean();
}
/**
*
* @param rnd
* @return
*/
public static final boolean flipCoin(Random rnd) {
return rnd.nextBoolean();
}
/**
*
* @param x
* @return
*/
public static final long floor(double x) {
long y = (long) x;
if (x < 0 && x != y) {
y--;
}
return y;
}
/**
* This method is a *lot* faster than using (int)Math.floor(x).
*
* @param x
* value to be floored
* @return floored value as integer
* @since 0012
*/
public static final int floor(float x) {
int y = (int) x;
if (x < 0 && x != y) {
y--;
}
return y;
}
/**
* Rounds down the value to the nearest lower power^2 value.
*
* @param x
* @return power^2 value
*/
public static final int floorPowerOf2(int x) {
return (int) Math.pow(2, (int) (Math.log(x) / LOG2));
}
/**
* Computes the Greatest Common Devisor of integers p and q.
*
* @param p
* @param q
* @return gcd
*/
public static final int gcd(int p, int q) {
if (q == 0) {
return p;
}
return gcd(q, p % q);
}
/**
* Creates a single normalized impulse signal with its peak at t=1/k. The
* attack and decay period is configurable via the k parameter. Code from:
* http://www.iquilezles.org/www/articles/functions/functions.htm
*
* @param k
* smoothness
* @param t
* time position (should be >= 0)
* @return impulse value (as double)
*/
public static double impulse(double k, double t) {
double h = k * t;
return h * Math.exp(1.0 - h);
}
/**
* Creates a single normalized impulse signal with its peak at t=1/k. The
* attack and decay period is configurable via the k parameter. Code from:
* http://www.iquilezles.org/www/articles/functions/functions.htm
*
* @param k
* smoothness
* @param t
* time position (should be >= 0)
* @return impulse value (as float)
*/
public static float impulse(float k, float t) {
float h = k * t;
return (float) (h * Math.exp(1.0f - h));
}
/**
*
* @param p
* @param q
* @return
*/
public static final int lcm(int p, int q) {
return abs(p * q) / gcd(p, q);
}
/**
*
* @param a
* @param b
* @param t
* @return
*/
public static double lerp(double a, double b, double t) {
return a + (b - a) * t;
}
/**
*
* @param a
* @param b
* @param t
* @return
*/
public static float lerp(float a, float b, float t) {
return a + (b - a) * t;
}
/**
*
* @param x
* @param minIn
* @param maxIn
* @param minOut
* @param maxOut
* @return
*/
public static double mapInterval(double x, double minIn, double maxIn,
double minOut, double maxOut) {
return minOut + (maxOut - minOut) * (x - minIn) / (maxIn - minIn);
}
/**
*
* @param x
* @param minIn
* @param maxIn
* @param minOut
* @param maxOut
* @return
*/
public static float mapInterval(float x, float minIn, float maxIn,
float minOut, float maxOut) {
return minOut + (maxOut - minOut) * (x - minIn) / (maxIn - minIn);
}
/**
*
* @param a
* @param b
* @return
*/
public static final double max(double a, double b) {
return a > b ? a : b;
}
/**
*
* @param a
* @param b
* @param c
* @return
*/
public static final double max(double a, double b, double c) {
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
}
/**
*
* @param values
* @return
*/
public static final double max(double[] values) {
return max(values[0], values[1], values[2]);
}
/**
*
* @param a
* @param b
* @return
*/
public static final float max(float a, float b) {
return a > b ? a : b;
}
/**
* Returns the maximum value of three floats.
*
* @param a
* @param b
* @param c
* @return max val
*/
public static final float max(float a, float b, float c) {
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
}
/**
*
* @param values
* @return
*/
public static final float max(float[] values) {
return max(values[0], values[1], values[2]);
}
/**
*
* @param a
* @param b
* @return
*/
public static final int max(int a, int b) {
return a > b ? a : b;
}
/**
* Returns the maximum value of three ints.
*
* @param a
* @param b
* @param c
* @return max val
*/
public static final int max(int a, int b, int c) {
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
}
/**
*
* @param values
* @return
*/
public static final int max(int[] values) {
return max(values[0], values[1], values[2]);
}
/**
*
* @param a
* @param b
* @return
*/
public static final double min(double a, double b) {
return a < b ? a : b;
}
/**
*
* @param a
* @param b
* @param c
* @return
*/
public static final double min(double a, double b, double c) {
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
}
/**
*
* @param a
* @param b
* @return
*/
public static final float min(float a, float b) {
return a < b ? a : b;
}
/**
* Returns the minimum value of three floats.
*
* @param a
* @param b
* @param c
* @return min val
*/
public static final float min(float a, float b, float c) {
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
}
/**
*
* @param a
* @param b
* @return
*/
public static final int min(int a, int b) {
return a < b ? a : b;
}
/**
* Returns the minimum value of three ints.
*
* @param a
* @param b
* @param c
* @return min val
*/
public static final int min(int a, int b, int c) {
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
}
/**
* Returns a random number in the interval -1 .. +1.
*
* @return random float
*/
public static final float normalizedRandom() {
return RND.nextFloat() * 2 - 1;
}
/**
* Returns a random number in the interval -1 .. +1 using the {@link Random}
* instance provided.
*
* @param rnd
* @return random float
*/
public static final float normalizedRandom(Random rnd) {
return rnd.nextFloat() * 2 - 1;
}
/**
*
* @param degrees
* @return
*/
public static double radians(double degrees) {
return degrees * DEG2RAD;
}
/**
*
* @param degrees
* @return
*/
public static final float radians(float degrees) {
return degrees * DEG2RAD;
}
/**
*
* @param max
* @return
*/
public static final float random(float max) {
return RND.nextFloat() * max;
}
/**
*
* @param min
* @param max
* @return
*/
public static final float random(float min, float max) {
return RND.nextFloat() * (max - min) + min;
}
/**
*
* @param max
* @return
*/
public static final int random(int max) {
return (int) (RND.nextFloat() * max);
}
/**
*
* @param min
* @param max
* @return
*/
public static final int random(int min, int max) {
return (int) (RND.nextFloat() * (max - min)) + min;
}
/**
*
* @param rnd
* @param max
* @return
*/
public static final double random(Random rnd, double max) {
return rnd.nextDouble() * max;
}
/**
*
* @param rnd
* @param min
* @param max
* @return
*/
public static final double random(Random rnd, double min, double max) {
return rnd.nextDouble() * (max - min) + min;
}
/**
*
* @param rnd
* @param max
* @return
*/
public static final float random(Random rnd, float max) {
return rnd.nextFloat() * max;
}
/**
*
* @param rnd
* @param min
* @param max
* @return
*/
public static final float random(Random rnd, float min, float max) {
return rnd.nextFloat() * (max - min) + min;
}
/**
*
* @param rnd
* @param max
* @return
*/
public static final int random(Random rnd, int max) {
return (int) (rnd.nextDouble() * max);
}
/**
*
* @param rnd
* @param min
* @param max
* @return
*/
public static final int random(Random rnd, int min, int max) {
return (int) (rnd.nextDouble() * (max - min)) + min;
}
/**
*
* @param chance
* @return
*/
public static final boolean randomChance(double chance) {
return RND.nextDouble() < chance;
}
/**
*
* @param chance
* @return
*/
public static final boolean randomChance(float chance) {
return RND.nextFloat() < chance;
}
/**
*
* @param rnd
* @param chance
* @return
*/
public static final boolean randomChance(Random rnd, double chance) {
return rnd.nextDouble() < chance;
}
/**
*
* @param rnd
* @param chance
* @return
*/
public static final boolean randomChance(Random rnd, float chance) {
return rnd.nextFloat() < chance;
}
/**
*
* @param theta
* @return
*/
public static final double reduceAngle(double theta) {
theta %= TWO_PI;
if (abs(theta) > PI) {
theta = theta - TWO_PI;
}
if (abs(theta) > HALF_PI) {
theta = PI - theta;
}
return theta;
}
/**
* Reduces the given angle into the -PI/4 ... PI/4 interval for faster
* computation of sin/cos. This method is used by {@link #sin(float)} &
* {@link #cos(float)}.
*
* @param theta
* angle in radians
* @return reduced angle
* @see #sin(float)
* @see #cos(float)
*/
public static final float reduceAngle(float theta) {
theta %= TWO_PI;
if (abs(theta) > PI) {
theta = theta - TWO_PI;
}
if (abs(theta) > HALF_PI) {
theta = PI - theta;
}
return theta;
}
/**
* Rounds a double precision value to the given precision.
*
* @param val
* @param prec
* @return rounded value
*/
public static final double roundTo(double val, double prec) {
return floor(val / prec + 0.5) * prec;
}
/**
* Rounds a single precision value to the given precision.
*
* @param val
* @param prec
* @return rounded value
*/
public static final float roundTo(float val, float prec) {
return floor(val / prec + 0.5f) * prec;
}
/**
* Rounds an integer value to the given precision.
*
* @param val
* @param prec
* @return rounded value
*/
public static final int roundTo(int val, int prec) {
return floor((float) val / prec + 0.5f) * prec;
}
/**
* Sets the default Random number generator for this class. This generator
* is being reused by all future calls to random() method versions which
* don't explicitly ask for a {@link Random} instance to be used.
*
* @param rnd
*/
public static void setDefaultRandomGenerator(Random rnd) {
RND = rnd;
}
/**
*
* @param x
* @return
*/
public static int sign(double x) {
return x < 0 ? -1 : (x > 0 ? 1 : 0);
}
/**
*
* @param x
* @return
*/
public static int sign(float x) {
return x < 0 ? -1 : (x > 0 ? 1 : 0);
}
/**
*
* @param x
* @return
*/
public static int sign(int x) {
return x < 0 ? -1 : (x > 0 ? 1 : 0);
}
/**
*
* @param theta
* @return
*/
public static final double sin(double theta) {
theta = reduceAngle(theta);
if (abs(theta) <= QUARTER_PI) {
return (float) fastSin(theta);
}
return (float) fastCos(HALF_PI - theta);
}
/**
* Returns a fast sine approximation of a value. Note: code from wiki posting on
* java.net by jeffpk
*
* @param theta
* angle in radians.
* @return sine of theta.
*/
public static final float sin(float theta) {
theta = reduceAngle(theta);
if (abs(theta) <= QUARTER_PI) {
return (float) fastSin(theta);
}
return (float) fastCos(HALF_PI - theta);
}
/**
* @param x
* @return
* @deprecated
*/
@Deprecated
public static final float sqrt(float x) {
x = fastInverseSqrt(x);
if (x > 0) {
return 1.0f / x;
} else {
return 0;
}
}
}