The formula we were previously using for asinh: asinh x = ln(x + sqrt(x * x + 1))
is numerically unstable: when x is a large negative value, the quantity x + sqrt(x * x + 1) is a small positive value (on the order of 1/(2|x|)). Since the logarithm function is very sensitive in this range, any error in the computation of the square root manifests as a large error in the result. This patch changes the formula to: asinh x = sign(x) * ln(abs(x) + sqrt(x * x + 1)) which is only slightly more expensive to compute, and is numerically stable for all x. Fixes piglit tests spec/glsl-1.30/execution/built-in-functions/[fv]s-asinh-*. --- src/glsl/builtins/ir/asinh | 40 ++++++++++++++++++++++++++++++++++++---- 1 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/glsl/builtins/ir/asinh b/src/glsl/builtins/ir/asinh index 93f73cc..d2dc710 100644 --- a/src/glsl/builtins/ir/asinh +++ b/src/glsl/builtins/ir/asinh @@ -2,20 +2,52 @@ (signature float (parameters (declare (in) float x)) - ((return (expression float log (expression float + (var_ref x) (expression float sqrt (expression float + (expression float * (var_ref x) (var_ref x)) (constant float (1))))))))) + ((return (expression float * + (expression float sign (var_ref x)) + (expression float log + (expression float + + (expression float abs (var_ref x)) + (expression float sqrt + (expression float + + (expression float * (var_ref x) (var_ref x)) + (constant float (1)))))))))) (signature vec2 (parameters (declare (in) vec2 x)) - ((return (expression vec2 log (expression vec2 + (var_ref x) (expression vec2 sqrt (expression vec2 + (expression vec2 * (var_ref x) (var_ref x)) (constant float (1))))))))) + ((return (expression vec2 * + (expression vec2 sign (var_ref x)) + (expression vec2 log + (expression vec2 + + (expression vec2 abs (var_ref x)) + (expression vec2 sqrt + (expression vec2 + + (expression vec2 * (var_ref x) (var_ref x)) + (constant float (1)))))))))) (signature vec3 (parameters (declare (in) vec3 x)) - ((return (expression vec3 log (expression vec3 + (var_ref x) (expression vec3 sqrt (expression vec3 + (expression vec3 * (var_ref x) (var_ref x)) (constant float (1))))))))) + ((return (expression vec3 * + (expression vec3 sign (var_ref x)) + (expression vec3 log + (expression vec3 + + (expression vec3 abs (var_ref x)) + (expression vec3 sqrt + (expression vec3 + + (expression vec3 * (var_ref x) (var_ref x)) + (constant float (1)))))))))) (signature vec4 (parameters (declare (in) vec4 x)) - ((return (expression vec4 log (expression vec4 + (var_ref x) (expression vec4 sqrt (expression vec4 + (expression vec4 * (var_ref x) (var_ref x)) (constant float (1))))))))) + ((return (expression vec4 * + (expression vec4 sign (var_ref x)) + (expression vec4 log + (expression vec4 + + (expression vec4 abs (var_ref x)) + (expression vec4 sqrt + (expression vec4 + + (expression vec4 * (var_ref x) (var_ref x)) + (constant float (1)))))))))) )) -- 1.7.6.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev