28#ifndef CLICK_LIBDIVIDE_H
29#define CLICK_LIBDIVIDE_H
30#include <click/glue.hh>
35#define __has_builtin(x) 0
38#if defined(__SIZEOF_INT128__)
42#if defined(__x86_64__) || defined(_WIN64) || defined(_M_X64)
43#define LIBDIVIDE_IS_X86_64 1
47#define LIBDIVIDE_IS_i386 1
50#if __GNUC__ || __clang__
51#define LIBDIVIDE_GCC_STYLE_ASM 1
54#define LIBDIVIDE_ASSERT(x) assert(x)
86 LIBDIVIDE_32_SHIFT_MASK = 0x1F,
87 LIBDIVIDE_64_SHIFT_MASK = 0x3F,
88 LIBDIVIDE_ADD_MARKER = 0x40,
89 LIBDIVIDE_U32_SHIFT_PATH = 0x80,
90 LIBDIVIDE_U64_SHIFT_PATH = 0x80,
91 LIBDIVIDE_S32_SHIFT_PATH = 0x20,
92 LIBDIVIDE_NEGATIVE_DIVISOR = 0x80
95struct libdivide_u32_t {
100struct libdivide_u32_branchfree_t {
106#define LIBDIVIDE_API static inline
109LIBDIVIDE_API
struct libdivide_u32_t libdivide_u32_gen(uint32_t y);
111LIBDIVIDE_API
struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t y);
113LIBDIVIDE_API uint32_t libdivide_u32_do(uint32_t numer,
const struct libdivide_u32_t *denom);
115LIBDIVIDE_API uint32_t libdivide_u32_branchfree_do(uint32_t numer,
const struct libdivide_u32_branchfree_t *denom);
117LIBDIVIDE_API uint32_t libdivide_u32_recover(
const struct libdivide_u32_t *denom);
119LIBDIVIDE_API uint32_t libdivide_u32_branchfree_recover(
const struct libdivide_u32_branchfree_t *denom);
121LIBDIVIDE_API
int libdivide_u32_get_algorithm(
const struct libdivide_u32_t *denom);
122LIBDIVIDE_API uint32_t libdivide_u32_do_alg0(uint32_t numer,
const struct libdivide_u32_t *denom);
123LIBDIVIDE_API uint32_t libdivide_u32_do_alg1(uint32_t numer,
const struct libdivide_u32_t *denom);
124LIBDIVIDE_API uint32_t libdivide_u32_do_alg2(uint32_t numer,
const struct libdivide_u32_t *denom);
129static inline uint32_t libdivide__mullhi_u32(uint32_t x, uint32_t y) {
130 uint64_t xl = x, yl = y;
131 uint64_t rl = xl * yl;
132 return (uint32_t)(rl >> 32);
135static inline int32_t libdivide__count_leading_zeros32(uint32_t val) {
136#if __GNUC__ || __has_builtin(__builtin_clz)
138 return __builtin_clz(val);
141 uint32_t hi = 1U << 31;
151static inline int32_t libdivide__count_leading_zeros64(uint64_t val) {
152#if __GNUC__ || __has_builtin(__builtin_clzll)
154 return __builtin_clzll(val);
156 uint32_t hi = val >> 32;
157 uint32_t lo = val & 0xFFFFFFFF;
158 if (hi != 0)
return libdivide__count_leading_zeros32(hi);
159 return 32 + libdivide__count_leading_zeros32(lo);
166#if (LIBDIVIDE_IS_i386 || LIBDIVIDE_IS_X86_64) && LIBDIVIDE_GCC_STYLE_ASM
167static uint32_t libdivide_64_div_32_to_32(uint32_t u1, uint32_t u0, uint32_t v, uint32_t *r) {
170 :
"=a"(result),
"=d"(*r)
171 : [v]
"r"(v),
"a"(u0),
"d"(u1)
176static uint32_t libdivide_64_div_32_to_32(uint32_t u1, uint32_t u0, uint32_t v, uint32_t *r) {
177 uint64_t n = (((uint64_t)u1) << 32) | u0;
179 *r = (uint32_t)(n - result * (uint64_t)v);
186static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) {
188 LIBDIVIDE_ASSERT(!branchfree || d != 1);
190 struct libdivide_u32_t result;
191 const uint32_t floor_log_2_d = 31 - libdivide__count_leading_zeros32(d);
192 if ((d & (d - 1)) == 0) {
196 result.more = floor_log_2_d | LIBDIVIDE_U32_SHIFT_PATH;
202 result.more = (floor_log_2_d-1) | LIBDIVIDE_ADD_MARKER;
206 uint32_t rem, proposed_m;
207 proposed_m = libdivide_64_div_32_to_32(1U << floor_log_2_d, 0, d, &rem);
209 LIBDIVIDE_ASSERT(rem > 0 && rem < d);
210 const uint32_t e = d - rem;
213 if (!branchfree && (e < (1U << floor_log_2_d))) {
215 more = floor_log_2_d;
222 proposed_m += proposed_m;
223 const uint32_t twice_rem = rem + rem;
224 if (twice_rem >= d || twice_rem < rem) proposed_m += 1;
225 more = floor_log_2_d | LIBDIVIDE_ADD_MARKER;
227 result.magic = 1 + proposed_m;
238struct libdivide_u32_t libdivide_u32_gen(uint32_t d) {
239 return libdivide_internal_u32_gen(d, 0);
242struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d) {
243 struct libdivide_u32_t tmp = libdivide_internal_u32_gen(d, 1);
244 struct libdivide_u32_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_32_SHIFT_MASK)};
248uint32_t libdivide_u32_do(uint32_t numer,
const struct libdivide_u32_t *denom) {
249 uint8_t more = denom->more;
250 if (more & LIBDIVIDE_U32_SHIFT_PATH) {
251 return numer >> (more & LIBDIVIDE_32_SHIFT_MASK);
254 uint32_t q = libdivide__mullhi_u32(denom->magic, numer);
255 if (more & LIBDIVIDE_ADD_MARKER) {
256 uint32_t t = ((numer - q) >> 1) + q;
257 return t >> (more & LIBDIVIDE_32_SHIFT_MASK);
265uint32_t libdivide_u32_recover(
const struct libdivide_u32_t *denom) {
266 uint8_t more = denom->more;
267 uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK;
268 if (more & LIBDIVIDE_U32_SHIFT_PATH) {
270 }
else if (! (more & LIBDIVIDE_ADD_MARKER)) {
276 uint32_t hi_dividend = 1U << shift;
277 uint32_t rem_ignored;
278 return 1 + libdivide_64_div_32_to_32(hi_dividend, 0, denom->magic, &rem_ignored);
286 uint64_t half_n = 1ULL << (32 + shift);
287 uint64_t d = (1ULL << 32) | denom->magic;
290 uint32_t half_q = (uint32_t)
int_divide(half_n, d);
291 uint64_t rem = half_n - half_q * d;
296 uint32_t full_q = half_q + half_q + ((rem<<1) >= d);
300 return full_q + (denom->magic != 0);
304uint32_t libdivide_u32_branchfree_recover(
const struct libdivide_u32_branchfree_t *denom) {
305 struct libdivide_u32_t denom_u32 = {denom->magic, (uint8_t)(denom->more | LIBDIVIDE_ADD_MARKER)};
306 return libdivide_u32_recover(&denom_u32);
309int libdivide_u32_get_algorithm(
const struct libdivide_u32_t *denom) {
310 uint8_t more = denom->more;
311 if (more & LIBDIVIDE_U32_SHIFT_PATH)
return 0;
312 else if (! (more & LIBDIVIDE_ADD_MARKER))
return 1;
316uint32_t libdivide_u32_do_alg0(uint32_t numer,
const struct libdivide_u32_t *denom) {
317 return numer >> (denom->more & LIBDIVIDE_32_SHIFT_MASK);
320uint32_t libdivide_u32_do_alg1(uint32_t numer,
const struct libdivide_u32_t *denom) {
321 uint32_t q = libdivide__mullhi_u32(denom->magic, numer);
322 return q >> denom->more;
325uint32_t libdivide_u32_do_alg2(uint32_t numer,
const struct libdivide_u32_t *denom) {
327 uint32_t q = libdivide__mullhi_u32(denom->magic, numer);
328 uint32_t t = ((numer - q) >> 1) + q;
331 return t >> (denom->more & LIBDIVIDE_32_SHIFT_MASK);
334uint32_t libdivide_u32_branchfree_do(uint32_t numer,
const struct libdivide_u32_branchfree_t *denom) {
336 uint32_t q = libdivide__mullhi_u32(denom->magic, numer);
337 uint32_t t = ((numer - q) >> 1) + q;
338 return t >> denom->more;
Functions for manipulating integers.
uint32_t int_divide(uint32_t a, uint32_t b)
Return a / b.
Definition integers.hh:354