mirror of
https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02.git
synced 2024-12-01 11:09:44 +01:00
426 lines
12 KiB
Java
426 lines
12 KiB
Java
|
////////////////////////////////////////
|
||
|
// Programming project code
|
||
|
// UniBw M, 2022, 2023, 2024
|
||
|
// www.unibw.de/inf2
|
||
|
// (c) Mark Minas (mark.minas@unibw.de)
|
||
|
////////////////////////////////////////
|
||
|
|
||
|
package pp.util;
|
||
|
|
||
|
/**
|
||
|
* Provides mathematical functions using float precision.
|
||
|
*/
|
||
|
public class FloatMath {
|
||
|
private FloatMath() { /* don't instantiate */ }
|
||
|
|
||
|
public static final double DBL_EPSILON = 2.220446049250313E-16d;
|
||
|
/**
|
||
|
* A "close to zero" float epsilon value for use
|
||
|
*/
|
||
|
public static final float FLT_EPSILON = 1.1920928955078125E-7f;
|
||
|
/**
|
||
|
* A "close to zero" float epsilon value for use
|
||
|
*/
|
||
|
public static final float ZERO_TOLERANCE = 0.0001f;
|
||
|
/**
|
||
|
* The value 1/3, as a float.
|
||
|
*/
|
||
|
public static final float ONE_THIRD = 1f / 3f;
|
||
|
/**
|
||
|
* The value PI as a float. (180 degrees)
|
||
|
*/
|
||
|
public static final float PI = (float) Math.PI;
|
||
|
/**
|
||
|
* The value 2PI as a float. (360 degrees)
|
||
|
*/
|
||
|
public static final float TWO_PI = 2.0f * PI;
|
||
|
/**
|
||
|
* The value PI/2 as a float. (90 degrees)
|
||
|
*/
|
||
|
public static final float HALF_PI = 0.5f * PI;
|
||
|
/**
|
||
|
* The value PI/4 as a float. (45 degrees)
|
||
|
*/
|
||
|
public static final float QUARTER_PI = 0.25f * PI;
|
||
|
/**
|
||
|
* The value 1/PI as a float.
|
||
|
*/
|
||
|
public static final float INV_PI = 1.0f / PI;
|
||
|
/**
|
||
|
* The value 1/(2PI) as a float.
|
||
|
*/
|
||
|
public static final float INV_TWO_PI = 1.0f / TWO_PI;
|
||
|
/**
|
||
|
* A value to multiply a degree value by, to convert it to radians.
|
||
|
*/
|
||
|
public static final float DEG_TO_RAD = PI / 180.0f;
|
||
|
/**
|
||
|
* A value to multiply a radian value by, to convert it to degrees.
|
||
|
*/
|
||
|
public static final float RAD_TO_DEG = 180.0f / PI;
|
||
|
|
||
|
/**
|
||
|
* Linear interpolation from startValue to endValue by the given percent.
|
||
|
* Basically: ((1 - percent) * startValue) + (percent * endValue)
|
||
|
*
|
||
|
* @param scale scale value to use. if 1, use endValue, if 0, use startValue.
|
||
|
* @param startValue Beginning value. 0% of f
|
||
|
* @param endValue ending value. 100% of f
|
||
|
* @return The interpolated value between startValue and endValue.
|
||
|
*/
|
||
|
public static float interpolateLinear(float scale, float startValue, float endValue) {
|
||
|
if (startValue == endValue) {
|
||
|
return startValue;
|
||
|
}
|
||
|
if (scale <= 0f) {
|
||
|
return startValue;
|
||
|
}
|
||
|
if (scale >= 1f) {
|
||
|
return endValue;
|
||
|
}
|
||
|
return ((1f - scale) * startValue) + (scale * endValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Linear extrapolation from startValue to endValue by the given scale.
|
||
|
* if scale is between 0 and 1 this method returns the same result as interpolateLinear
|
||
|
* if the scale is over 1 the value is linearly extrapolated.
|
||
|
* Note that the end value is the value for a scale of 1.
|
||
|
*
|
||
|
* @param scale the scale for extrapolation
|
||
|
* @param startValue the starting value (scale = 0)
|
||
|
* @param endValue the end value (scale = 1)
|
||
|
* @return an extrapolation for the given parameters
|
||
|
*/
|
||
|
public static float extrapolateLinear(float scale, float startValue, float endValue) {
|
||
|
return ((1f - scale) * startValue) + (scale * endValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the arc cosine of a value.<br>
|
||
|
* Special cases:
|
||
|
* <ul><li>If fValue is smaller than -1, then the result is PI.
|
||
|
* <li>If the argument is greater than 1, then the result is 0.</ul>
|
||
|
*
|
||
|
* @param fValue The value to arc cosine.
|
||
|
* @return The angle, in radians.
|
||
|
* @see Math#acos(double)
|
||
|
*/
|
||
|
public static float acos(float fValue) {
|
||
|
if (-1.0f < fValue) {
|
||
|
if (fValue < 1.0f) {
|
||
|
return (float) Math.acos(fValue);
|
||
|
}
|
||
|
|
||
|
return 0.0f;
|
||
|
}
|
||
|
|
||
|
return PI;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the arc sine of a value.<br>
|
||
|
* Special cases:
|
||
|
* <ul><li>If fValue is smaller than -1, then the result is -HALF_PI.
|
||
|
* <li>If the argument is greater than 1, then the result is HALF_PI.</ul>
|
||
|
*
|
||
|
* @param fValue The value to arc sine.
|
||
|
* @return the angle in radians.
|
||
|
* @see Math#asin(double)
|
||
|
*/
|
||
|
public static float asin(float fValue) {
|
||
|
if (-1.0f < fValue) {
|
||
|
if (fValue < 1.0f) {
|
||
|
return (float) Math.asin(fValue);
|
||
|
}
|
||
|
|
||
|
return HALF_PI;
|
||
|
}
|
||
|
|
||
|
return -HALF_PI;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the arc tangent of an angle given in radians.<br>
|
||
|
*
|
||
|
* @param fValue The angle, in radians.
|
||
|
* @return fValue's atan
|
||
|
* @see Math#atan(double)
|
||
|
*/
|
||
|
public static float atan(float fValue) {
|
||
|
return (float) Math.atan(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A direct call to Math.atan2.
|
||
|
*
|
||
|
* @param fY ordinate
|
||
|
* @param fX abscissa
|
||
|
* @return Math.atan2(fY, fX)
|
||
|
* @see Math#atan2(double, double)
|
||
|
*/
|
||
|
public static float atan2(float fY, float fX) {
|
||
|
return (float) Math.atan2(fY, fX);
|
||
|
}
|
||
|
|
||
|
public static float sinh(float x) {
|
||
|
return (float) Math.sinh(x);
|
||
|
}
|
||
|
|
||
|
public static float cosh(float x) {
|
||
|
return (float) Math.cosh(x);
|
||
|
}
|
||
|
|
||
|
public static float tanh(float x) {
|
||
|
return (float) Math.tanh(x);
|
||
|
}
|
||
|
|
||
|
public static float coth(float x) {
|
||
|
return (float) (1d / Math.tanh(x));
|
||
|
}
|
||
|
|
||
|
public static float arsinh(float x) {
|
||
|
return log(x + sqrt(x * x + 1f));
|
||
|
}
|
||
|
|
||
|
public static float arcosh(float x) {
|
||
|
return log(x + sqrt(x * x - 1f));
|
||
|
}
|
||
|
|
||
|
public static float artanh(float x) {
|
||
|
return 0.5f * log((1f + x) / (1f - x));
|
||
|
}
|
||
|
|
||
|
public static float arcoth(float x) {
|
||
|
return 0.5f * log((x + 1f) / (x - 1f));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Rounds a fValue up. A call to Math.ceil
|
||
|
*
|
||
|
* @param fValue The value.
|
||
|
* @return The fValue rounded up
|
||
|
* @see Math#ceil(double)
|
||
|
*/
|
||
|
public static float ceil(float fValue) {
|
||
|
return (float) Math.ceil(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns cosine of an angle. Direct call to Math
|
||
|
*
|
||
|
* @param v The angle to cosine.
|
||
|
* @return the cosine of the angle.
|
||
|
* @see Math#cos(double)
|
||
|
*/
|
||
|
public static float cos(float v) {
|
||
|
return (float) Math.cos(v);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the sine of an angle. Direct call to Math
|
||
|
*
|
||
|
* @param v The angle to sine.
|
||
|
* @return the sine of the angle.
|
||
|
* @see Math#sin(double)
|
||
|
*/
|
||
|
public static float sin(float v) {
|
||
|
return (float) Math.sin(v);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns E^fValue
|
||
|
*
|
||
|
* @param fValue Value to raise to a power.
|
||
|
* @return The value E^fValue
|
||
|
* @see Math#exp(double)
|
||
|
*/
|
||
|
public static float exp(float fValue) {
|
||
|
return (float) Math.exp(fValue);
|
||
|
}
|
||
|
|
||
|
public static float expm1(float fValue) {
|
||
|
return (float) Math.expm1(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns Absolute value of a float.
|
||
|
*
|
||
|
* @param fValue The value to abs.
|
||
|
* @return The abs of the value.
|
||
|
* @see Math#abs(float)
|
||
|
*/
|
||
|
public static float abs(float fValue) {
|
||
|
if (fValue < 0) {
|
||
|
return -fValue;
|
||
|
}
|
||
|
return fValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a number rounded down.
|
||
|
*
|
||
|
* @param fValue The value to round
|
||
|
* @return The given number rounded down
|
||
|
* @see Math#floor(double)
|
||
|
*/
|
||
|
public static float floor(float fValue) {
|
||
|
return (float) Math.floor(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns 1/sqrt(fValue)
|
||
|
*
|
||
|
* @param fValue The value to process.
|
||
|
* @return 1/sqrt(fValue)
|
||
|
* @see Math#sqrt(double)
|
||
|
*/
|
||
|
public static float invSqrt(float fValue) {
|
||
|
return (float) (1.0f / Math.sqrt(fValue));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Quickly estimate 1/sqrt(fValue).
|
||
|
*
|
||
|
* @param x the input value (≥0)
|
||
|
* @return an approximate value for 1/sqrt(x)
|
||
|
*/
|
||
|
public static float fastInvSqrt(float x) {
|
||
|
float halfX = 0.5f * x;
|
||
|
int i = Float.floatToIntBits(x); // get bits for floating value
|
||
|
i = 0x5f375a86 - (i >> 1); // gives initial guess y0
|
||
|
x = Float.intBitsToFloat(i); // convert bits back to float
|
||
|
x = x * (1.5f - halfX * x * x); // Newton step, repeating increases accuracy
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the log base E of a value.
|
||
|
*
|
||
|
* @param fValue The value to log.
|
||
|
* @return The log of fValue base E
|
||
|
* @see Math#log(double)
|
||
|
*/
|
||
|
public static float log(float fValue) {
|
||
|
return (float) Math.log(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a number raised to an exponent power. fBase^fExponent
|
||
|
*
|
||
|
* @param fBase The base value (IE 2)
|
||
|
* @param fExponent The exponent value (IE 3)
|
||
|
* @return base raised to exponent (IE 8)
|
||
|
* @see Math#pow(double, double)
|
||
|
*/
|
||
|
public static float pow(float fBase, float fExponent) {
|
||
|
return (float) Math.pow(fBase, fExponent);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the value squared. fValue ^ 2
|
||
|
*
|
||
|
* @param fValue The value to square.
|
||
|
* @return The square of the given value.
|
||
|
*/
|
||
|
public static float sqr(float fValue) {
|
||
|
return fValue * fValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the square root of a given value.
|
||
|
*
|
||
|
* @param fValue The value to sqrt.
|
||
|
* @return The square root of the given value.
|
||
|
* @see Math#sqrt(double)
|
||
|
*/
|
||
|
public static float sqrt(float fValue) {
|
||
|
return (float) Math.sqrt(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the tangent of the specified angle.
|
||
|
*
|
||
|
* @param fValue The value to tangent, in radians.
|
||
|
* @return The tangent of fValue.
|
||
|
* @see Math#tan(double)
|
||
|
*/
|
||
|
public static float tan(float fValue) {
|
||
|
return (float) Math.tan(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns 1 if the number is positive, -1 if the number is negative, and 0 otherwise
|
||
|
*
|
||
|
* @param iValue The integer to examine.
|
||
|
* @return The integer's sign.
|
||
|
*/
|
||
|
public static int sign(int iValue) {
|
||
|
return Integer.compare(iValue, 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns 1 if the number is positive, -1 if the number is negative, and 0 otherwise
|
||
|
*
|
||
|
* @param fValue The float to examine.
|
||
|
* @return The float's sign.
|
||
|
*/
|
||
|
public static float sign(float fValue) {
|
||
|
return Math.signum(fValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Take a float input and clamp it between min and max.
|
||
|
*
|
||
|
* @param input the value to be clamped
|
||
|
* @param min the minimum output value
|
||
|
* @param max the maximum output value
|
||
|
* @return clamped input
|
||
|
*/
|
||
|
public static float clamp(float input, float min, float max) {
|
||
|
return Math.max(min, Math.min(input, max));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clamps the given float to be between 0 and 1.
|
||
|
*
|
||
|
* @param input the value to be clamped
|
||
|
* @return input clamped between 0 and 1.
|
||
|
*/
|
||
|
public static float saturate(float input) {
|
||
|
return clamp(input, 0f, 1f);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine if two floats are approximately equal.
|
||
|
* This takes into account the magnitude of the floats, since
|
||
|
* large numbers will have larger differences be close to each other.
|
||
|
* <p>
|
||
|
* Should return true for a=100000, b=100001, but false for a=10000, b=10001.
|
||
|
*
|
||
|
* @param a The first float to compare
|
||
|
* @param b The second float to compare
|
||
|
* @return True if a and b are approximately equal, false otherwise.
|
||
|
*/
|
||
|
public static boolean approximateEquals(float a, float b) {
|
||
|
if (a == b) {
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
return (abs(a - b) / Math.max(abs(a), abs(b))) <= 0.00001f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Normalizes the specified angle to lie in the interval (-pi,pi] and returns the normalized value in radians.
|
||
|
*
|
||
|
* @param angle the specified angle in radians
|
||
|
*/
|
||
|
public static float normalizeAngle(float angle) {
|
||
|
final float res = angle % TWO_PI;
|
||
|
if (res <= -FloatMath.PI) return res + TWO_PI;
|
||
|
else if (res > FloatMath.PI) return res - TWO_PI;
|
||
|
return res;
|
||
|
}
|
||
|
}
|