diff options
author | José Fonseca <[email protected]> | 2010-10-06 17:44:05 +0100 |
---|---|---|
committer | José Fonseca <[email protected]> | 2010-10-06 18:46:59 +0100 |
commit | 012d57737b1b4e4263aa3414abe433195ff8a713 (patch) | |
tree | b138b67fe88cb4bd436c06904d6310ef78872001 /src/gallium/auxiliary | |
parent | 4648846bd6c376877f024ccf300ceac5b0b3dcd6 (diff) |
gallivm: Fast implementation of iround(log2(x))
Not tested yet, but should be correct.
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_arit.c | 35 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_arit.h | 4 |
2 files changed, 39 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index ff94f498acf..15b74410188 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -2330,3 +2330,38 @@ lp_build_fast_log2(struct lp_build_context *bld, /* floor(log2(x)) + frac(x) */ return LLVMBuildFAdd(bld->builder, ipart, fpart, ""); } + + +/** + * Fast implementation of iround(log2(x)). + * + * Not an approximation -- it should give accurate results all the time. + */ +LLVMValueRef +lp_build_ilog2(struct lp_build_context *bld, + LLVMValueRef x) +{ + const struct lp_type type = bld->type; + LLVMTypeRef int_vec_type = bld->int_vec_type; + + unsigned mantissa = lp_mantissa(type); + LLVMValueRef sqrt2 = lp_build_const_vec(type, 1.4142135623730951); + + LLVMValueRef ipart; + + assert(lp_check_value(bld->type, x)); + + assert(type.floating); + + /* x * 2^(0.5) i.e., add 0.5 to the log2(x) */ + x = LLVMBuildFMul(bld->builder, x, sqrt2, ""); + + x = LLVMBuildBitCast(bld->builder, x, int_vec_type, ""); + + /* ipart = floor(log2(x) + 0.5) */ + ipart = LLVMBuildLShr(bld->builder, x, lp_build_const_int_vec(type, mantissa), ""); + ipart = LLVMBuildAnd(bld->builder, ipart, lp_build_const_int_vec(type, 255), ""); + ipart = LLVMBuildSub(bld->builder, ipart, lp_build_const_int_vec(type, 127), ""); + + return ipart; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h index 3ed4fec2333..f36197479f0 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h @@ -216,6 +216,10 @@ LLVMValueRef lp_build_fast_log2(struct lp_build_context *bld, LLVMValueRef a); +LLVMValueRef +lp_build_ilog2(struct lp_build_context *bld, + LLVMValueRef x); + void lp_build_exp2_approx(struct lp_build_context *bld, |