[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