summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-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 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,