From 64eb0738d4e35e9ceb4bf99b028bdd5e12c59c34 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 5 Oct 2018 20:28:40 -0500 Subject: [PATCH] util: Add fast division helpers Reviewed-by: Jason Ekstrand --- src/util/fast_idiv_by_const.h | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/util/fast_idiv_by_const.h b/src/util/fast_idiv_by_const.h index ac10cf79ba8..1ba9f9a20b8 100644 --- a/src/util/fast_idiv_by_const.h +++ b/src/util/fast_idiv_by_const.h @@ -130,6 +130,50 @@ struct util_fast_udiv_info { struct util_fast_udiv_info util_compute_fast_udiv_info(uint_t D, unsigned num_bits); +/* Below are possible options for dividing by a uniform in a shader where + * the divisor is constant but not known at compile time. + */ + +/* Full version. */ +static inline uint32_t +util_fast_udiv32(uint32_t n, struct util_fast_udiv_info info) +{ + n = n >> info.pre_shift; + /* For non-power-of-two divisors, use a 32-bit ADD that clamps to UINT_MAX. */ + n = (((uint64_t)n + info.increment) * info.multiplier) >> 32; + n = n >> info.post_shift; + return n; +} + +/* A little more efficient version if n != UINT_MAX, i.e. no unsigned + * wraparound in the computation. + */ +static inline uint32_t +util_fast_udiv32_nuw(uint32_t n, struct util_fast_udiv_info info) +{ + assert(n != UINT32_MAX); + n = n >> info.pre_shift; + n = n + info.increment; + n = ((uint64_t)n * info.multiplier) >> 32; + n = n >> info.post_shift; + return n; +} + +/* Even faster version but both operands must be 31-bit unsigned integers + * and the divisor must be greater than 1. + * + * info must be computed with num_bits == 31. + */ +static inline uint32_t +util_fast_udiv32_u31_d_not_one(uint32_t n, struct util_fast_udiv_info info) +{ + assert(info.pre_shift == 0); + assert(info.increment == 0); + n = ((uint64_t)n * info.multiplier) >> 32; + n = n >> info.post_shift; + return n; +} + #ifdef __cplusplus } /* extern C */ #endif -- 2.30.2