Skip to content

Commit

Permalink
Improve MathUtils.asin(), acos() (#6332)
Browse files Browse the repository at this point in the history
The average and largest error are significantly better for this version (2-3 orders of magnitude), and it can be slightly faster.
  • Loading branch information
tommyettinger committed Dec 27, 2020
1 parent 4f57d2f commit 7933720
Showing 1 changed file with 32 additions and 8 deletions.
40 changes: 32 additions & 8 deletions gdx/src/com/badlogic/gdx/math/MathUtils.java
Expand Up @@ -108,16 +108,40 @@ static public float atan2 (float y, float x) {
return y < 0f ? atan - PI : atan;
}

/** Returns acos in radians, less accurate than Math.acos but may be faster. */
static public float acos (float a) {
return 1.5707963267948966f - (a * (1f + (a *= a) * (-0.141514171442891431f + a * -0.719110791477959357f)))
/ (1f + a * (-0.439110389941411144f + a * -0.471306172023844527f));
/** Returns acos in radians; less accurate than Math.acos but may be faster. Average error of 0.00002845 radians
* (0.0016300649 degrees), largest error of 0.000067548 radians (0.0038702153 degrees). This implementation does not
* return NaN if given an out-of-range input (Math.acos does return NaN), unless the input is NaN.
* @param a acos is defined only when a is between -1f and 1f, inclusive
* @return between {@code 0} and {@code PI} when a is in the defined range */
static public float acos(float a) {
float a2 = a * a; // a squared
float a3 = a * a2; // a cubed
if (a >= 0f) {
return (float) Math.sqrt(1f - a) *
(1.5707288f - 0.2121144f * a + 0.0742610f * a2 - 0.0187293f * a3);
}
else {
return 3.14159265358979323846f - (float) Math.sqrt(1f + a) *
(1.5707288f + 0.2121144f * a + 0.0742610f * a2 + 0.0187293f * a3);
}
}

/** Returns asin in radians, less accurate than Math.asin but may be faster. */
static public float asin (float a) {
return (a * (1f + (a *= a) * (-0.141514171442891431f + a * -0.719110791477959357f)))
/ (1f + a * (-0.439110389941411144f + a * -0.471306172023844527f));
/** Returns asin in radians; less accurate than Math.asin but may be faster. Average error of 0.000028447 radians
* (0.0016298931 degrees), largest error of 0.000067592 radians (0.0038727364 degrees). This implementation does not
* return NaN if given an out-of-range input (Math.asin does return NaN), unless the input is NaN.
* @param a asin is defined only when a is between -1f and 1f, inclusive
* @return between {@code -HALF_PI} and {@code HALF_PI} when a is in the defined range */
static public float asin(float a) {
float a2 = a * a; // a squared
float a3 = a * a2; // a cubed
if (a >= 0f) {
return 1.5707963267948966f - (float) Math.sqrt(1f - a) *
(1.5707288f - 0.2121144f * a + 0.0742610f * a2 - 0.0187293f * a3);
}
else {
return -1.5707963267948966f + (float) Math.sqrt(1f + a) *
(1.5707288f + 0.2121144f * a + 0.0742610f * a2 + 0.0187293f * a3);
}
}

// ---
Expand Down

0 comments on commit 7933720

Please sign in to comment.