# [Mesa-dev] [PATCH] glsl: improve the accuracy of the asin() builtin function.

Paul Berry stereotype441 at gmail.com
Wed Jul 27 15:15:16 PDT 2011

```The previous formula for asin(x) was algebraically equivalent to:

sign(x)*(pi/2 - sqrt(1-|x|)*(A + B|x| + C|x|^2))

where A, B, and C were arbitrary constants determined by a curve fit.

This formula had a worst case absolute error of 0.00448, an unbounded
worst case relative error, and a discontinuity near x=0.

Changed the formula to:

sign(x)*(pi/2 - sqrt(1-|x|)*(pi/2 + (pi/4-1)|x| + A|x|^2 + B|x|^3))

where A and B are arbitrary constants determined by a curve fit.  This
has a worst case absolute error of 0.00039, a worst case relative
error of 0.000405, and no discontinuities.

I don't expect a significant performance degradation, since the extra
multiply-accumulate should be fast compared to the sqrt() computation.
---
src/glsl/builtins/ir/asin |   68 ++++++++++++++++++++++++++------------------
1 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/src/glsl/builtins/ir/asin b/src/glsl/builtins/ir/asin
--- a/src/glsl/builtins/ir/asin
+++ b/src/glsl/builtins/ir/asin
@@ -5,23 +5,26 @@
((return (expression float *
(expression float sign (var_ref x))
(expression float -
-		(expression float *
-		 (constant float (3.1415926))
-		 (constant float (0.5)))
+		(constant float (1.5707964))
(expression float *
(expression float sqrt
(expression float -
(constant float (1.0))
(expression float abs (var_ref x))))
(expression float +
-		  (constant float (1.5707288))
+		  (constant float (1.5707964))
(expression float *
(expression float abs (var_ref x))
(expression float +
-		    (constant float (-0.2121144))
+		    (constant float (-0.21460183))
(expression float *
-		     (constant float (0.0742610))
-		     (expression float abs (var_ref x))))))))))))
+		     (expression float abs (var_ref x))
+                     (expression float +
+                      (constant float (0.086566724))
+                      (expression float *
+                       (expression float abs (var_ref x))
+                       (constant float (-0.03102955))
+		     ))))))))))))

(signature vec2
(parameters
@@ -29,23 +32,26 @@
((return (expression vec2 *
(expression vec2 sign (var_ref x))
(expression vec2 -
-		(expression float *
-		 (constant float (3.1415926))
-		 (constant float (0.5)))
+		(constant float (1.5707964))
(expression vec2 *
(expression vec2 sqrt
(expression vec2 -
(constant float (1.0))
(expression vec2 abs (var_ref x))))
(expression vec2 +
-		  (constant float (1.5707288))
+		  (constant float (1.5707964))
(expression vec2 *
(expression vec2 abs (var_ref x))
(expression vec2 +
-		    (constant float (-0.2121144))
+		    (constant float (-0.21460183))
(expression vec2 *
-		     (constant float (0.0742610))
-		     (expression vec2 abs (var_ref x))))))))))))
+		     (expression vec2 abs (var_ref x))
+                     (expression vec2 +
+                      (constant float (0.086566724))
+                      (expression vec2 *
+                       (expression vec2 abs (var_ref x))
+                       (constant float (-0.03102955))
+		     ))))))))))))

(signature vec3
(parameters
@@ -53,23 +59,26 @@
((return (expression vec3 *
(expression vec3 sign (var_ref x))
(expression vec3 -
-		(expression float *
-		 (constant float (3.1415926))
-		 (constant float (0.5)))
+		(constant float (1.5707964))
(expression vec3 *
(expression vec3 sqrt
(expression vec3 -
(constant float (1.0))
(expression vec3 abs (var_ref x))))
(expression vec3 +
-		  (constant float (1.5707288))
+		  (constant float (1.5707964))
(expression vec3 *
(expression vec3 abs (var_ref x))
(expression vec3 +
-		    (constant float (-0.2121144))
+		    (constant float (-0.21460183))
(expression vec3 *
-		     (constant float (0.0742610))
-		     (expression vec3 abs (var_ref x))))))))))))
+		     (expression vec3 abs (var_ref x))
+                     (expression vec3 +
+                      (constant float (0.086566724))
+                      (expression vec3 *
+                       (expression vec3 abs (var_ref x))
+                       (constant float (-0.03102955))
+		     ))))))))))))

(signature vec4
(parameters
@@ -77,21 +86,24 @@
((return (expression vec4 *
(expression vec4 sign (var_ref x))
(expression vec4 -
-		(expression float *
-		 (constant float (3.1415926))
-		 (constant float (0.5)))
+		(constant float (1.5707964))
(expression vec4 *
(expression vec4 sqrt
(expression vec4 -
(constant float (1.0))
(expression vec4 abs (var_ref x))))
(expression vec4 +
-		  (constant float (1.5707288))
+		  (constant float (1.5707964))
(expression vec4 *
(expression vec4 abs (var_ref x))
(expression vec4 +
-		    (constant float (-0.2121144))
+		    (constant float (-0.21460183))
(expression vec4 *
-		     (constant float (0.0742610))
-		     (expression vec4 abs (var_ref x))))))))))))
+		     (expression vec4 abs (var_ref x))
+                     (expression vec4 +
+                      (constant float (0.086566724))
+                      (expression vec4 *
+                       (expression vec4 abs (var_ref x))
+                       (constant float (-0.03102955))
+		     ))))))))))))
))
--
1.7.6

```