[Mesa-dev] [PATCH 2/2] gallivm: fix edge cases in exp2

Zack Rusin zackr at vmware.com
Tue Jul 16 10:10:10 PDT 2013


exp2(0) needs to be exactly 1, if exp2(src) overflows then it has
to be equal to infinity and exp2(nan) has to be equal to a nan.
The patches fixes all three cases.

Signed-off-by: Zack Rusin <zackr at vmware.com>
---
 src/gallium/auxiliary/gallivm/lp_bld_arit.c |   16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 7beb117..467cbc6 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -3004,7 +3004,7 @@ lp_build_polynomial(struct lp_build_context *bld,
  */
 const double lp_build_exp2_polynomial[] = {
 #if EXP_POLY_DEGREE == 5
-   0.999999925063526176901,
+   1.000000000000000000000,
    0.693153073200168932794,
    0.240153617044375388211,
    0.0558263180532956664775,
@@ -3046,6 +3046,8 @@ lp_build_exp2_approx(struct lp_build_context *bld,
    LLVMValueRef expipart = NULL;
    LLVMValueRef expfpart = NULL;
    LLVMValueRef res = NULL;
+   LLVMValueRef infmask = bld->zero;
+   LLVMValueRef nanmask = bld->zero;
 
    assert(lp_check_value(bld->type, x));
 
@@ -3059,6 +3061,10 @@ lp_build_exp2_approx(struct lp_build_context *bld,
 
       assert(type.floating && type.width == 32);
 
+      /* We need ot handle both inf and nan inputs */
+      infmask = lp_build_cmp(bld, PIPE_FUNC_GREATER, x,
+                             lp_build_const_vec(bld->gallivm, type,  129.0));
+      nanmask = LLVMBuildFCmp(bld->gallivm->builder, LLVMRealOEQ, x, x, "");
       x = lp_build_min(bld, x, lp_build_const_vec(bld->gallivm, type,  129.0));
       x = lp_build_max(bld, x, lp_build_const_vec(bld->gallivm, type, -126.99999));
 
@@ -3081,6 +3087,14 @@ lp_build_exp2_approx(struct lp_build_context *bld,
                                      Elements(lp_build_exp2_polynomial));
 
       res = LLVMBuildFMul(builder, expipart, expfpart, "");
+      /* If the input would overflow make sure return is correctly an inf */
+      res = lp_build_select(bld, infmask,
+                            lp_build_const_vec(bld->gallivm, type,  INFINITY),
+                            res);
+      /* If the input was a nan make sure the return is also a nan */
+      res = LLVMBuildSelect(bld->gallivm->builder, nanmask, res,
+                            lp_build_const_vec(bld->gallivm, type,  NAN),
+                            "");
    }
 
    if(p_exp2_int_part)
-- 
1.7.10.4


More information about the mesa-dev mailing list