diff --git a/src/main/java/pythagoras/f/FloatMath.java b/src/main/java/pythagoras/f/FloatMath.java new file mode 100644 index 0000000..1d0ec93 --- /dev/null +++ b/src/main/java/pythagoras/f/FloatMath.java @@ -0,0 +1,381 @@ +// +// Pythagoras - a collection of geometry classes +// http://github.com/samskivert/pythagoras + +package pythagoras.f; + +/** + * Utility methods and constants for single-precision floating point math. + */ +public class FloatMath +{ + /** The ratio of a circle's circumference to its diameter. */ + public static final float PI = (float)Math.PI; + + /** The circle constant, tau (τ) http://tauday.com/ */ + public static final float TWO_PI = (float)(Math.PI * 2); + + /** Pi times one half. */ + public static final float HALF_PI = PI * 0.5f; + + /** The base value of the natural logarithm. */ + public static final float E = (float)Math.E; + + /** A small number. */ + public static final float EPSILON = 0.000001f; + + /** + * Computes and returns the sine of the given angle. + * + * @see Math#sin + */ + public static float sin (float a) + { + return (float)Math.sin(a); + } + + /** + * Computes and returns the cosine of the given angle. + * + * @see Math#cos + */ + public static float cos (float a) + { + return (float)Math.cos(a); + } + + /** + * Computes and returns the tangent of the given angle. + * + * @see Math#tan + */ + public static float tan (float a) + { + return (float)Math.tan(a); + } + + /** + * Computes and returns the arc sine of the given value. + * + * @see Math#asin + */ + public static float asin (float a) + { + return (float)Math.asin(a); + } + + /** + * Computes and returns the arc cosine of the given value. + * + * @see Math#acos + */ + public static float acos (float a) + { + return (float)Math.acos(a); + } + + /** + * Computes and returns the arc tangent of the given value. + * + * @see Math#atan + */ + public static float atan (float a) + { + return (float)Math.atan(a); + } + + /** + * Computes and returns the arc tangent of the given values. + * + * @see Math#atan2 + */ + public static float atan2 (float y, float x) + { + return (float)Math.atan2(y, x); + } + + /** + * Converts from radians to degrees. + * + * @see Math#toDegrees + */ + public static float toDegrees (float a) + { + return a * (180f / PI); + } + + /** + * Converts from degrees to radians. + * + * @see Math#toRadians + */ + public static float toRadians (float a) + { + return a * (PI / 180f); + } + + /** + * Returns the square root of the supplied value. + * + * @see Math#sqrt + */ + public static float sqrt (float v) + { + return (float)Math.sqrt(v); + } + + /** + * Returns the cube root of the supplied value. + * + * @see Math#cbrt + */ + public static float cbrt (float v) + { + return (float)Math.cbrt(v); + } + + /** + * Computes and returns sqrt(x*x + y*y). + * + * @see Math#hypot + */ + public static float hypot (float x, float y) + { + return (float)Math.hypot(x, y); + } + + /** + * Returns e to the power of the supplied value. + * + * @see Math#exp + */ + public static float exp (float v) + { + return (float)Math.exp(v); + } + + /** + * Returns the natural logarithm of the supplied value. + * + * @see Math#log + */ + public static float log (float v) + { + return (float)Math.log(v); + } + + /** + * Returns the base 10 logarithm of the supplied value. + * + * @see Math#log10 + */ + public static float log10 (float v) + { + return (float)Math.log10(v); + } + + /** + * Returns v to the power of e. + * + * @see Math#pow + */ + public static float pow (float v, float e) + { + return (float)Math.pow(v, e); + } + + /** + * Returns the floor of v. + * + * @see Math#floor + */ + public static float floor (float v) + { + return (float)Math.floor(v); + } + + /** + * A cheaper version of {@link Math#round} that doesn't handle the special cases. + */ + public static int round (float v) + { + return (v < 0f) ? (int)(v - 0.5f) : (int)(v + 0.5f); + } + + /** + * Returns the floor of v as an integer without calling the relatively expensive + * {@link Math#floor}. + */ + public static int ifloor (float v) + { + int iv = (int)v; + return (v < 0f) ? ((iv == v || iv == Integer.MIN_VALUE) ? iv : (iv - 1)) : iv; + } + + /** + * Returns the ceiling of v. + * + * @see Math#ceil + */ + public static float ceil (float v) + { + return (float)Math.ceil(v); + } + + /** + * Returns the ceiling of v as an integer without calling the relatively expensive + * {@link Math#ceil}. + */ + public static int iceil (float v) + { + int iv = (int)v; + return (v > 0f) ? ((iv == v || iv == Integer.MAX_VALUE) ? iv : (iv + 1)) : iv; + } + + /** + * Returns the remainder when f1 is divided by f2. + * + * @see Math#IEEEremainder + */ + public static float IEEEremainder (float f1, float f2) + { + return (float)Math.IEEEremainder(f1, f2); + } + + /** + * Clamps a value to the range [lower, upper]. + */ + public static float clamp (float v, float lower, float upper) + { + return Math.min(Math.max(v, lower), upper); + } + + /** + * Rounds a value to the nearest multiple of a target. + */ + public static float roundNearest (float v, float target) + { + target = Math.abs(target); + if (v >= 0) { + return target * floor((v + 0.5f * target) / target); + } else { + return target * ceil((v - 0.5f * target) / target); + } + } + + /** + * Checks whether the value supplied is in [lower, upper]. + */ + public static boolean isWithin (float v, float lower, float upper) + { + return v >= lower && v <= upper; + } + + /** + * Returns a random value according to the normal distribution with the provided mean and + * standard deviation. + * + * @param normal a normally distributed random value. + * @param mean the desired mean. + * @param stddev the desired standard deviation. + */ + public static float normal (float normal, float mean, float stddev) + { + return stddev*normal() + mean; + } + + /** + * Returns a random value according to the exponential distribution with the provided mean. + * + * @param random a uniformly distributed random value. + * @param mean the desired mean. + */ + public static float exponential (float random, float mean) + { + return -log(1f - random) * mean; + } + + /** + * Linearly interpolates between two angles, taking the shortest path around the circle. + * This assumes that both angles are in [-pi, +pi]. + */ + public static float lerpa (float a1, float a2, float t) + { + float ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2); + float d = Math.abs(a2 - a1), md = Math.abs(ma1 - ma2); + return (d < md) ? lerp(a1, a2, t) : mirrorAngle(lerp(ma1, ma2, t)); + } + + /** + * Linearly interpolates between v1 and v2 by the parameter t. + */ + public static float lerp (float v1, float v2, float t) + { + return v1 + t*(v2 - v1); + } + + /** + * Determines whether two values are "close enough" to equal. + */ + public static boolean epsilonEquals (float v1, float v2) + { + return Math.abs(v1 - v2) < EPSILON; + } + + /** + * Returns the (shortest) distance between two angles, assuming that both angles are in + * [-pi, +pi]. + */ + public static float getAngularDistance (float a1, float a2) + { + float ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2); + return Math.min(Math.abs(a1 - a2), Math.abs(ma1 - ma2)); + } + + /** + * Returns the (shortest) difference between two angles, assuming that both angles are in + * [-pi, +pi]. + */ + public static float getAngularDifference (float a1, float a2) + { + float ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2); + float diff = a1 - a2, mdiff = ma2 - ma1; + return (Math.abs(diff) < Math.abs(mdiff)) ? diff : mdiff; + } + + /** + * Returns an angle in the range [-pi, pi]. + */ + public static float normalizeAngle (float a) + { + while (a < -PI) { + a += TWO_PI; + } + while (a > PI) { + a -= TWO_PI; + } + return a; + } + + /** + * Returns an angle in the range [0, 2pi]. + */ + public static float normalizeAnglePositive (float a) + { + while (a < 0f) { + a += TWO_PI; + } + while (a > TWO_PI) { + a -= TWO_PI; + } + return a; + } + + /** + * Returns the mirror angle of the specified angle (assumed to be in [-pi, +pi]). + */ + public static float mirrorAngle (float a) + { + return (a > 0f ? PI : -PI) - a; + } +}