glsl: improve the accuracy of the asin() builtin function.
authorPaul Berry <stereotype441@gmail.com>
Wed, 27 Jul 2011 21:34:12 +0000 (14:34 -0700)
committerPaul Berry <stereotype441@gmail.com>
Mon, 1 Aug 2011 21:37:38 +0000 (14:37 -0700)
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.

Fixes piglit tests {vs,fs}-asin-float and {vs,fs}-atan-*

src/glsl/builtins/ir/asin

index e230ad614ee50e87be35ad4bedd62861cfae3c2d..45d9e672958e9247b7a56b8ac7d6f7fd339d529d 100644 (file)
@@ -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
      ((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
      ((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
      ((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))
+                    ))))))))))))
 ))