Thanks, it will hold me over for the moment.
It's BROKE! see below for details, and a working (and simplified) version.
I think I'll start practising writing macros like that, it could come in
handy, and above it all it might be fun!
It IS fun, but it is generally NOT a Good Idea. Though I have done a
few not _quite_ so repulsive things in production code, such things
should be done with the appropriate sense of fear and trembling.
[OFF-TOPIC from here on]
I'm actually writing a C++ template, and such a macro would allow me to
write:
template<class T>
class UnsignedNumericTypeInfo {
public:
static T const max_power_of_ten = maxPowerOf( (T)-1, 10 );
};
If all you want is powers-of-10, there is another option, quite more
repulsive yet beautiful in the way of Rodin's "Belle Heauimiere".
------------------------------------
#include <stdio.h>
#include <limits.h>
/* This macro calculates the highest power of 10 less than X */
/* X _must be_ > 0 and have no leading 0 */
static int powersOfTen[] =
{ 1
, 10
, 100
, 1000
, 10000
, 100000
, 1000000
, 10000000
, 100000000
,1000000000
};
/* Returns the power of 10 with the same number of digits as X */
#define maxPowerOfTen(X) (powersOfTen[sizeof(#X)-2])
#define show(X) \
printf("Inputs: %10d\nOutputs: %10d\n\n", X, maxPowerOfTen(X))
int
main(int argc, char *argv[])
{
show(0);
show(9);
show(98722);
show(9270720);
show(237509275);
show(INT_MAX);
return 0;
}
------------------------------------
Inputs: 0
Outputs: 1
Inputs: 9
Outputs: 1
Inputs: 98722
Outputs: 10000
Inputs: 9270720
Outputs: 1000000
Inputs: 237509275
Outputs: 100000000
Inputs: 2147483647
Outputs: 1000000000
------------------------------------
My original macro had a horrible bug, and was much more complicated
than necessary. If max_value was greater than INT_MAX/divisor, the
highest power of divisor greater than max_value could not be
calculated. Copious warnings were produced, which (being groggy) I
fixed by reducing the table size for larger values, which didn't
solve the problem but avoided the errors for the test cases.
Here's the New and Improved version implemented for divisors >=9.
To extend that to divisors >= 2, the number of lines in each section
must be expanded to log_base_mindivisor(max maxvalue), eg,
log2(LONG_MAX), 63 on a well-mannered compiler.
I _could_ calculate the power expressions as long and drop the second
half of the macro, but that just postpones the problem. If the range
of max_value exceeds int_max, the power expressions (Y*Y..) should be
cast to (_calculated as_, take care where the cast is) an integer
type that can hold the maximum desired max_value.
------------------------------------
#include <stdio.h>
#include <limits.h>
/* This macro calculates the highest power of Y less than X */
/* It oes not handle Y=0 or Y=1 or Y>X */
#define maxPowerOf(X,Y) ( \
/* If X is less than INT_MAX/Y, find the highest power of Y < X */ \
X < INT_MAX/Y? \
( \
X < Y ? 1: \
X < Y*Y ? Y:\
X < Y*Y*Y ? Y*Y:\
X < Y*Y*Y*Y ? Y*Y*Y:\
X < Y*Y*Y*Y*Y ? Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y:\
X < Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y ? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y \
) \
: \
/* Y > INT_MAX/X: find the highest power of Y < INT_MAX. */ \
( \
Y > INT_MAX/Y? Y: \
Y*Y > INT_MAX/Y? Y*Y: \
Y*Y*Y > INT_MAX/Y? Y*Y*Y: \
Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y: \
Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y > INT_MAX/Y? Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y: \
Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y*Y \
) \
)
#define show(X,Y) \
printf("Inputs: %10d\n %10d\nOutputs: %10d\n\n", \
X, Y, maxPowerOf(X,Y))
int
main(int argc, char *argv[])
{
show(1000,2);
show(10000,2);
show(65535,2);
show(100000,2);
show(98722, 10);
show(9270720, 10);
show(237509275,10);
show(INT_MAX,10);
show(INT_MAX,INT_MAX);
return 0;
}
------------------------------------
Inputs: 1000
2
Outputs: 512
Inputs: 10000
2
Outputs: 8192
Inputs: 65535
2
Outputs: 32768
Inputs: 100000
2
Outputs: 65536
Inputs: 98722
10
Outputs: 10000
Inputs: 9270720
10
Outputs: 1000000
Inputs: 237509275
10
Outputs: 1000000000
Inputs: 2147483647
10
Outputs: 1000000000
Inputs: 2147483647
2147483647
Outputs: 2147483647
------------------------------------
Now my code will work if compiled on a 36-Bit machine. : )
Only if you extend the macro by log10(2^36)-log10(2^32) lines.
Martin