From b46aad6df449445a9fc4aa7b32bd40005438e3f7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 14:18:05 +0200 Subject: Adding upstream version 2.9.5. Signed-off-by: Daniel Baumann --- tests/unit/test-1-among.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/unit/test-1-among.c (limited to 'tests/unit/test-1-among.c') diff --git a/tests/unit/test-1-among.c b/tests/unit/test-1-among.c new file mode 100644 index 0000000..bd19192 --- /dev/null +++ b/tests/unit/test-1-among.c @@ -0,0 +1,105 @@ +#include +#include +#include + +static inline unsigned long statistical_prng() +{ + static unsigned long statistical_prng_state = 2463534242U; + unsigned long x = statistical_prng_state; + + if (sizeof(long) <= 4) { + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + } else { + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + } + return statistical_prng_state = x; +} + +/* returns the position of one bit set in , starting at position , and + * searching in other halves if not found. This is intended to be used to + * report the position of one bit set among several based on a counter or a + * random generator while preserving a relatively good distribution so that + * values made of holes in the middle do not see one of the bits around the + * hole being returned much more often than the other one. It can be seen as a + * disturbed ffsl() where the initial search starts at bit . The look up + * is performed in O(logN) time for N bit words, yielding a bit among 64 in + * about 16 cycles. Passing value 0 for makes no sense and -1 is returned + * in this case. + */ +int one_among(unsigned long v, int bit) +{ + /* note, these masks may be produced by ~0UL/((1UL< 4) ? 5 : 4; scale >= 0; scale--) { + halfword >>= (1UL << scale); + scope |= (1UL << scale); + mirror = bit ^ (1UL << scale); + if (v & ((1UL << bit) | (1UL << mirror))) + return (v & (1UL << bit)) ? bit : mirror; + + if (!((v >> (bit & scope)) & halves[scale] & halfword)) + bit = mirror; + } + return bit; +} + +int main(int argc, char **argv) +{ + unsigned long mask; + int bit; + + if (argc < 2) { + unsigned long long tests = 0; + int ret; + + while (1) { + mask = statistical_prng(); // note: cannot be zero + bit = statistical_prng() % (sizeof(long) * 8); + ret = one_among(mask, bit); + if (ret < 0 || !((mask >> ret) & 1)) + printf("###ERR### mask=%#lx bit=%d ret=%d\n", mask, bit, ret); + if (!(tests & 0xffffff)) + printf("count=%Ld mask=%lx bit=%d ret=%d\n", tests, mask, bit, ret); + tests++; + } + } + + mask = atol(argv[1]); + + if (argc < 3) { + for (bit = 0; bit < 8*sizeof(long); bit++) + printf("v %#x bit %d best %d\n", mask, bit, one_among(mask, bit)); + } else { + bit = atoi(argv[2]); + printf("v %#x bit %d best %d\n", mask, bit, one_among(mask, bit)); + } + return 0; +} -- cgit v1.2.3