Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- log2 behavior tester
- copyright 2021 Damian Yerrick
- insert GNU All-Permissive License here
- build and run:
- gcc -Wall -Wextra -Og -fsanitize=undefined log2test.c -lm -o log2test && log2test | less
- Notice how the inaccuracy creeps in at 25 bits for cast to float
- or 49 bits for cast to double.
- */
- #include <stdio.h>
- #include <inttypes.h> // same as stdint.h plus
- #include <math.h>
- /**
- * calculates floor(log[2](i)), or -1 if i < 1
- * but can a compiler recognize it and convert it to clz?
- */
- signed log2ul (uint_fast32_t x) {
- signed result = 0;
- if (x < 3) return x - 1; // 0->-1, 1->0, 2->1
- while (x > 1 << 16) { result += 16; x >>= 16; }
- while (x > 1 << 4) { result += 4; x >>= 4; }
- while (x > 1 ) { result += 1; x >>= 1; }
- return result;
- }
- /**
- * calculates floor(log[2](i)), or -1 if i < 1
- * but can a compiler recognize it and convert it to clz?
- */
- signed log2ull (unsigned long long x) {
- signed result = 0;
- if (x < 3) return x - 1; // 0->-1, 1->0, 2->1
- while (x > 1 << 16) { result += 16; x >>= 16; }
- while (x > 1 << 4) { result += 4; x >>= 4; }
- while (x > 1 ) { result += 1; x >>= 1; }
- return result;
- }
- void u32_trial(unsigned shiftamt) {
- uint32_t arg = (uint32_t)1 << (shiftamt - 1); // e.g. 8->128
- arg = (arg - 1) * 2; // e.g. 8->254
- printf("trial for log2(1 << %u) using uint32_t\n",
- shiftamt);
- for (unsigned b = 5; b > 0 && arg > 0; --b, ++arg) {
- signed loop_result = log2ul(arg);
- double float_result = log2((float)arg);
- signed floor_float = floor(float_result);
- double double_result = log2((double)arg);
- signed floor_double = floor(double_result);
- printf("log2(%10"PRIu32") = %2d int, %7.4f=>%2d float, %7.4f=>%2d double\n",
- arg, loop_result, float_result, floor_float,
- double_result, floor_double);
- }
- }
- void u64_trial(unsigned shiftamt) {
- uint64_t arg = (uint64_t)1 << (shiftamt - 1); // e.g. 8->128
- arg = (arg - 1) * 2; // e.g. 8->254
- printf("trial for log2(1 << %u) using uint64_t\n",
- shiftamt);
- for (unsigned b = 5; b > 0 && arg > 0; --b, ++arg) {
- signed loop_result = log2ul(arg);
- double float_result = log2((float)arg);
- signed floor_float = floor(float_result);
- double double_result = log2((double)arg);
- signed floor_double = floor(double_result);
- printf("log2(%10"PRIu64") = %2d int, %7.4f=>%2d float, %7.4f=>%2d double\n",
- arg, loop_result, float_result, floor_float,
- double_result, floor_double);
- }
- }
- int main(void) {
- for (unsigned i = 4; i <= 32; ++i) u32_trial(i);
- for (unsigned i = 4; i <= 64; ++i) u64_trial(i);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement