summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/gallivm
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-10-06 17:44:05 +0100
committerJosé Fonseca <jfonseca@vmware.com>2010-10-06 18:46:59 +0100
commit012d57737b1b4e4263aa3414abe433195ff8a713 (patch)
treeb138b67fe88cb4bd436c06904d6310ef78872001 /src/gallium/auxiliary/gallivm
parent4648846bd6c376877f024ccf300ceac5b0b3dcd6 (diff)
gallivm: Fast implementation of iround(log2(x))
Not tested yet, but should be correct.
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c35
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.h4
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 ff94f498ac..15b7441018 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 3ed4fec233..f36197479f 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,