vtn: Make tanh implementation even stupider
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 27 Jan 2016 23:31:53 +0000 (15:31 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 27 Jan 2016 23:34:50 +0000 (15:34 -0800)
The dEQP "precision" test tries to verify that the reference functions

   float sinh(float a) { return ((exp(a) - exp(-a)) / 2); }
   float cosh(float a) { return ((exp(a) + exp(-a)) / 2); }
   float tanh(float a) { return (sinh(a) / cosh(a)); }

produce the same values as the built-ins.  We simplified away the
multiplication by 0.5 in the numerator and denominator, and apparently
this causes them not to match for exactly 1 out of 13,632 values.

So, put it back in, fixing the test, but making our code generation
(and precision?) worse.

src/glsl/nir/spirv/vtn_glsl450.c

index 8d73016..219a9c7 100644 (file)
@@ -545,12 +545,14 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
       return;
 
    case GLSLstd450Tanh:
-      /* (e^x - e^(-x)) / (e^x + e^(-x)) */
+      /* (0.5 * (e^x - e^(-x))) / (0.5 * (e^x + e^(-x))) */
       val->ssa->def =
-         nir_fdiv(nb, nir_fsub(nb, build_exp(nb, src[0]),
-                                   build_exp(nb, nir_fneg(nb, src[0]))),
-                      nir_fadd(nb, build_exp(nb, src[0]),
-                                   build_exp(nb, nir_fneg(nb, src[0]))));
+         nir_fdiv(nb, nir_fmul(nb, nir_imm_float(nb, 0.5f),
+                                   nir_fsub(nb, build_exp(nb, src[0]),
+                                                build_exp(nb, nir_fneg(nb, src[0])))),
+                      nir_fmul(nb, nir_imm_float(nb, 0.5f),
+                                   nir_fadd(nb, build_exp(nb, src[0]),
+                                                build_exp(nb, nir_fneg(nb, src[0])))));
       return;
 
    case GLSLstd450Asinh: