Reputation: 8857
I have a constant WIDTH
which is always a power of 2, e.g. #define WIDTH 1024
.
I have an associated #define WIDTH_BINARY_LOG 10
which I must change every time that I modify WIDTH
, to be the binary logarithm of WIDTH
. This is undesirable as sometimes I forget to do so, and things consequently go haywire. Unfortunately pow()
is also not available in macros.
Usage is
*z = zx >> WIDTH_BINARY_LOG
.
My plan to fix this, given that the maximum possible value of WIDTH_BINARY_LOG
is 16
, was the following usage:
*z = zx >> BINARY_LOG(WIDTH)
with the following defines:
#define BINARY_LOG_1 0
#define BINARY_LOG_2 1
#define BINARY_LOG_4 2
#define BINARY_LOG_8 3
#define BINARY_LOG_16 4
#define BINARY_LOG_32 5
#define BINARY_LOG_64 6
#define BINARY_LOG_128 7
#define BINARY_LOG_256 8
#define BINARY_LOG_512 9
#define BINARY_LOG_1024 10
#define BINARY_LOG_2048 11
#define BINARY_LOG_4096 12
#define BINARY_LOG_8192 13
#define BINARY_LOG_16384 14
#define BINARY_LOG_32768 15
#define BINARY_LOG_65536 16
#define BINARY_LOG(n) BINARY_LOG_##n
or
#define BINARY_LOG(n) BINARY_LOG_#n
However, gcc complains bitterly in each case. What am I doing wrong? How would others tackle this problem, assuming the way above is completely unworthy?
Upvotes: 2
Views: 71
Reputation: 899
Since there are already working answers available, I want to point to some different solution:
Using constexpr (C++11) that can be evaluated at compile-time to calculate WIDTH from a given exponent. This looks much nicer than the use of macros IMHO: (see Casey's answer in c++11 fast constexpr integer powers)
#include <cstdint>
constexpr int64_t ipow(int64_t base, int exp, int64_t result = 1) {
return exp < 1 ? result : ipow(base*base, exp/2, (exp % 2) ? result*base : result);
}
int64_t foo(int64_t base, int exp) {
return ipow(base, exp);
}
Upvotes: -2
Reputation: 846
It can be done with macros. I used this answer in my code:
#define WIDTH 2048
#define BINARY_LOG_1 0
#define BINARY_LOG_2 1
#define BINARY_LOG_4 2
#define BINARY_LOG_8 3
#define BINARY_LOG_16 4
#define BINARY_LOG_32 5
#define BINARY_LOG_64 6
#define BINARY_LOG_128 7
#define BINARY_LOG_256 8
#define BINARY_LOG_512 9
#define BINARY_LOG_1024 10
#define BINARY_LOG_2048 11
#define BINARY_LOG_4096 12
#define BINARY_LOG_8192 13
#define BINARY_LOG_16384 14
#define BINARY_LOG_32768 15
#define BINARY_LOG_65536 16
#define PPCAT_NX(A, B) A ## B
#define BINARY_LOG(B) PPCAT_NX(BINARY_LOG_, B)
BINARY_LOG(WIDTH)
Output of gcc -E test.c
(only macro substitution phase):
>gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.c"
# 24 "test.c"
11
Upvotes: 3