using pre-processor to count bits in integer types...

C

Chris M. Thomasson

How "reliable" is the following code:
____________________________________________________________
#include <stdio.h>
#include <limits.h>


#define COUNT_BITS_X_CALC(mp_value, mp_level) \
(! ((mp_value) >> (CHAR_BIT * (mp_level)))) \
? (CHAR_BIT * (mp_level))


#define COUNT_BITS_X(mp_value) ( \
(COUNT_BITS_X_CALC(mp_value, 1) \
: (COUNT_BITS_X_CALC(mp_value, 2) \
: (COUNT_BITS_X_CALC(mp_value, 4) \
: (COUNT_BITS_X_CALC(mp_value, 5) \
: (COUNT_BITS_X_CALC(mp_value, 6) \
: (COUNT_BITS_X_CALC(mp_value, 7) \
: (COUNT_BITS_X_CALC(mp_value, 8) \
: (COUNT_BITS_X_CALC(mp_value, 9) \
: (COUNT_BITS_X_CALC(mp_value, 10) \
: 0))))))))) \
)


#define COUNT_BITS(mp_value) COUNT_BITS_X(mp_value)


#if (COUNT_BITS(USHRT_MAX) == 16)
typedef short int int16_type;
typedef unsigned short int uint16_type;
#else
# error Platform does not provide an exact 16-bit integer! ;^(...
#endif


int main(void) {
printf(
"char is %lu bits\n"
"short is %lu bits\n"
"int is %lu bits\n"
"long is %lu bits\n"
"int16_type is %lu bits\n",
(unsigned long int)COUNT_BITS(UCHAR_MAX),
(unsigned long int)COUNT_BITS(USHRT_MAX),
(unsigned long int)COUNT_BITS(UINT_MAX),
(unsigned long int)COUNT_BITS(ULONG_MAX),
(unsigned long int)(CHAR_BIT * sizeof(int16_type))
);

return 0;
}
____________________________________________________________




I am tinkering around with different ways to use the pre-processor to
determine exact number of bits in integral types. Is there a much better way
to do this? What am I missing here?




Thanks.
 
S

Spiros Bousbouras

How "reliable" is the following code:
____________________________________________________________
#include <stdio.h>
#include <limits.h>

#define COUNT_BITS_X_CALC(mp_value, mp_level) \
(! ((mp_value) >> (CHAR_BIT * (mp_level)))) \
? (CHAR_BIT * (mp_level))

#define COUNT_BITS_X(mp_value) ( \
(COUNT_BITS_X_CALC(mp_value, 1) \
: (COUNT_BITS_X_CALC(mp_value, 2) \
: (COUNT_BITS_X_CALC(mp_value, 4) \
: (COUNT_BITS_X_CALC(mp_value, 5) \
: (COUNT_BITS_X_CALC(mp_value, 6) \
: (COUNT_BITS_X_CALC(mp_value, 7) \
: (COUNT_BITS_X_CALC(mp_value, 8) \
: (COUNT_BITS_X_CALC(mp_value, 9) \
: (COUNT_BITS_X_CALC(mp_value, 10) \
: 0))))))))) \
)

#define COUNT_BITS(mp_value) COUNT_BITS_X(mp_value)

#if (COUNT_BITS(USHRT_MAX) == 16)
typedef short int int16_type;
typedef unsigned short int uint16_type;
#else
# error Platform does not provide an exact 16-bit integer! ;^(...
#endif

int main(void) {
printf(
"char is %lu bits\n"
"short is %lu bits\n"
"int is %lu bits\n"
"long is %lu bits\n"
"int16_type is %lu bits\n",
(unsigned long int)COUNT_BITS(UCHAR_MAX),
(unsigned long int)COUNT_BITS(USHRT_MAX),
(unsigned long int)COUNT_BITS(UINT_MAX),
(unsigned long int)COUNT_BITS(ULONG_MAX),
(unsigned long int)(CHAR_BIT * sizeof(int16_type))
);

return 0;}

____________________________________________________________

I am tinkering around with different ways to use the pre-processor to
determine exact number of bits in integral types. Is there a much better way
to do this? What am I missing here?

You are missing number 3 from your list of possibilities! The
same thing could be written much more clearly by checking
whether the value you are testing is equal to 2^n - 1 for
successive values of n. You would need to write a larger list
but it would look clearer. For example

#define COUNT_BITS(n) ( \
(n) == 255 ? 8 : \
(n) == 511 ? 9 : \
(n) == 1023 ? 10 : \
.....
)

A bit more complicated but still (IMO) clearer is

#define COUNT_BITS(n) ( \
(n) == ( (1 << CHAR_BIT) -1) ? CHAR_BIT : \
(n) == ( (1 << 2*CHAR_BIT) -1) ? 2*CHAR_BIT : \
(n) == ( (1 << 3*CHAR_BIT) -1) ? 3*CHAR_BIT : \
.....
)

(Neither one tested)

I have a vague recollection that a while ago someone posted a
macro which did what you wanted (or something close) and could
handle ridiculously large numbers of bits. Sadly I haven't
stored the link and some Google search didn't find the thread
I was looking for. I would love to see that again.

But it would be even simpler if you didn't use the preprocessor
but did it during runtime in the beginning of your programme. Is
there any practical reason you want to use the preprocessor ?
 
C

Chris M. Thomasson

Eric Sosman said:
Chris said:
How "reliable" is the following code:
[... see up-thread ...]

"Reliable" in the face of what threats or eventualities?
It doesn't work in the presence of padding bits, it might not
work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
floating-point types ... I'm not sure what realm of possibilities
you're concerned about.

I would only ever pass the following values to the `COUNT_BITS' macro:


UCHAR_MAX
USHRT_MAX
UINT_MAX
ULONG_MAX


I am assuming that the number of bits it takes to hold any of those values
will be a multiple of `CHAR_BIT'.



[...]
I am tinkering around with different ways to use the pre-processor to
determine exact number of bits in integral types. Is there a much better
way to do this? What am I missing here?

The total number of bits in a type is `sizeof(type) * CHAR_BIT'.
Excluding possible padding bits seems difficult. I guess you could
change your procedure to increase the shift distances by one bit at
at time instead of CHAR_BIT, and test for equality to one instead of
zero (to guard against a too-wide shift), but you've still got to
figure out how many tests to make: C99's integers go up to at least
64 bits, and possibly beyond.

I could shift by one. Humm, well I also could add support for a couple of
hundred bits. This macro would be contained in a dedicated header file, so
its not that bad.



The "much better way" -- well, can you formulate your questions
in terms of ranges rather than in terms of logarithms? That is, how
badly do you need actual bit counts?

This macro would only get invoked when the end user build system for my
library determines that its being compiled on an "unknown" platform.
Something like:




/* try to determine operating system */
/* [...] */


/* try to determine architecture */
/* [...] */


/* try to determine compiler */
#if defined (COMPILER_VENDOR_1)
# include "compiler/vendor/1/core.h"
#elif defined (COMPILER_VENDOR_2)
# include "compiler/vendor/2/core.h"
#elif
# include "compiler/vendor/unknown/core.h"
#endif




The `compiler/vendor/.../core.h' files are required to define some types
that have exact number of bits. If I know the compiler, I will use specific
extensions to get the job done. However, if the compiler is unknown, well, I
need to at least "attempt" to render the correctly sized types. I need this
to all be performed at compile time.
 
S

Spiros Bousbouras

This macro would only get invoked when the end user build system for my
library determines that its being compiled on an "unknown" platform.
Something like:

/* try to determine operating system */
/* [...] */

/* try to determine architecture */
/* [...] */

/* try to determine compiler */
#if defined (COMPILER_VENDOR_1)
# include "compiler/vendor/1/core.h"
#elif defined (COMPILER_VENDOR_2)
# include "compiler/vendor/2/core.h"
#elif
# include "compiler/vendor/unknown/core.h"
#endif

The `compiler/vendor/.../core.h' files are required to define some types
that have exact number of bits. If I know the compiler, I will use specific
extensions to get the job done. However, if the compiler is unknown, well, I
need to at least "attempt" to render the correctly sized types. I need this
to all be performed at compile time.

You could run a programme which tests these things,
writes a configuration file with preprocessor directives
and then the compilation of your library begins. So
basically a much simpler version of what autoconf does.
 
P

Peter Nilsson

Spiros Bousbouras said:
...
A bit more complicated but still (IMO) clearer is

#define COUNT_BITS(n) (                           \
(n) == ( (1 << CHAR_BIT) -1) ? CHAR_BIT :         \
(n) == ( (1 << 2*CHAR_BIT) -1) ? 2*CHAR_BIT  :    \
(n) == ( (1 << 3*CHAR_BIT) -1) ? 3*CHAR_BIT :     \

There are a few problems with this:
n may be a signed type
n may be a padded type
n may be wider than the left shifted 1 (int)
[Even 1<<CHAR_BIT can potentially invoke UB.]

I have a vague recollection that a while ago someone
posted a macro which did what you wanted (or something
close) and could handle ridiculously large numbers of
bits.

Hallvard B Furuseth once posted the following (which
I've edited slightly due to line wrap issues)...

/* Number of bits in inttype_MAX, or in any (1<<b)-1
where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
/0x3fffffffL %0x3fffffffL *30 + \
(m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
12/((m)%31+3))
 
S

Spiros Bousbouras

Hallvard B Furuseth once posted the following (which
I've edited slightly due to line wrap issues)...

/* Number of bits in inttype_MAX, or in any (1<<b)-1
where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
/0x3fffffffL %0x3fffffffL *30 + \
(m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
12/((m)%31+3))

Thank you. This had been bugging me for a while.
 
C

Chris M. Thomasson

Eric Sosman said:
Chris said:
How "reliable" is the following code:
[... see up-thread ...]

"Reliable" in the face of what threats or eventualities?
It doesn't work in the presence of padding bits, it might not
work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
floating-point types ... I'm not sure what realm of possibilities
you're concerned about.
[...]
I am tinkering around with different ways to use the pre-processor to
determine exact number of bits in integral types. Is there a much better
way to do this? What am I missing here?

The total number of bits in a type is `sizeof(type) * CHAR_BIT'.
Excluding possible padding bits seems difficult. I guess you could
change your procedure to increase the shift distances by one bit at
at time instead of CHAR_BIT, and test for equality to one instead of
zero (to guard against a too-wide shift), but you've still got to
figure out how many tests to make: C99's integers go up to at least
64 bits, and possibly beyond.

The "much better way" -- well, can you formulate your questions
in terms of ranges rather than in terms of logarithms? That is, how
badly do you need actual bit counts?

Let post code with a shift by one:
______________________________________________________________________
#include <limits.h>
#include <stdio.h>


#define CHECK_BIT_X(n, b) (((n) >> (b)) == 1) ? (b) + 1


#define COUNT_BITS_CALC_X(n, b) ( \
(CHECK_BIT_X(n, (b) + 0) : (CHECK_BIT_X(n, (b) + 1) \
: (CHECK_BIT_X(n, (b) + 2) : (CHECK_BIT_X(n, (b) + 3) \
: (CHECK_BIT_X(n, (b) + 4) : (CHECK_BIT_X(n, (b) + 5) \
: (CHECK_BIT_X(n, (b) + 6) : (CHECK_BIT_X(n, (b) + 7) \
: (CHECK_BIT_X(n, (b) + 8) : (CHECK_BIT_X(n, (b) + 9) \
: (CHECK_BIT_X(n, (b) + 10) : (CHECK_BIT_X(n, (b) + 11) \
: (CHECK_BIT_X(n, (b) + 12) : (CHECK_BIT_X(n, (b) + 13) \
: (CHECK_BIT_X(n, (b) + 14) : (CHECK_BIT_X(n, (b) + 15) \
: (CHECK_BIT_X(n, (b) + 16) : (CHECK_BIT_X(n, (b) + 17) \
: (CHECK_BIT_X(n, (b) + 18) : (CHECK_BIT_X(n, (b) + 19) \
: (CHECK_BIT_X(n, (b) + 20) : (CHECK_BIT_X(n, (b) + 21) \
: (CHECK_BIT_X(n, (b) + 22) : (CHECK_BIT_X(n, (b) + 23) \
: (CHECK_BIT_X(n, (b) + 24) : (CHECK_BIT_X(n, (b) + 24) \
: (CHECK_BIT_X(n, (b) + 26) : (CHECK_BIT_X(n, (b) + 26) \
: (CHECK_BIT_X(n, (b) + 28) : (CHECK_BIT_X(n, (b) + 28) \
: (CHECK_BIT_X(n, (b) + 30) : (CHECK_BIT_X(n, (b) + 31) \
: (CHECK_BIT_X(n, (b) + 32) : (CHECK_BIT_X(n, (b) + 33) \
: (CHECK_BIT_X(n, (b) + 34) : (CHECK_BIT_X(n, (b) + 35) \
: (CHECK_BIT_X(n, (b) + 36) : (CHECK_BIT_X(n, (b) + 37) \
: (CHECK_BIT_X(n, (b) + 38) : (CHECK_BIT_X(n, (b) + 39) \
: (0))))))))))))))))))))))))))))))))))))))))) \
)


#define COUNT_BITS_X(n, b) \
COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


#define COUNT_BITS(n) ( \
(COUNT_BITS_X(n, 0) : (COUNT_BITS_X(n, 40) \
: (COUNT_BITS_X(n, 80) : (COUNT_BITS_X(n, 120) \
: (COUNT_BITS_X(n, 160) : (COUNT_BITS_X(n, 200) \
: (COUNT_BITS_X(n, 240) : (COUNT_BITS_X(n, 280) \
: (COUNT_BITS_X(n, 320) : (COUNT_BITS_X(n, 360) \
: (COUNT_BITS_X(n, 400) : (COUNT_BITS_X(n, 440) \
: (COUNT_BITS_X(n, 480) : (COUNT_BITS_X(n, 520) \
: (COUNT_BITS_X(n, 540) : (COUNT_BITS_X(n, 560) \
: (COUNT_BITS_X(n, 600) : (COUNT_BITS_X(n, 640) \
: (COUNT_BITS_X(n, 680) : (COUNT_BITS_X(n, 720) \
: (COUNT_BITS_X(n, 760) : (COUNT_BITS_X(n, 800) \
: (COUNT_BITS_X(n, 840) : (COUNT_BITS_X(n, 880) \
: (COUNT_BITS_X(n, 920) : (COUNT_BITS_X(n, 960) \
: (COUNT_BITS_X(n, 1000) : (COUNT_BITS_X(n, 1040) \
: (COUNT_BITS_X(n, 1080) : (COUNT_BITS_X(n, 1120) \
: (COUNT_BITS_X(n, 1160) : (COUNT_BITS_X(n, 1200) \
: (COUNT_BITS_X(n, 1240) : (COUNT_BITS_X(n, 1260) \
: (COUNT_BITS_X(n, 1300) : (COUNT_BITS_X(n, 1340) \
: (COUNT_BITS_X(n, 1380) : (COUNT_BITS_X(n, 1420) \
: (COUNT_BITS_X(n, 1460) : (COUNT_BITS_X(n, 1500) \
: (COUNT_BITS_X(n, 1540) : (COUNT_BITS_X(n, 1580) \
: (0))))))))))))))))))))))))))))))))))))))))))) \
)




#if (COUNT_BITS(UCHAR_MAX) == 8)
typedef signed char int8_type;
typedef unsigned char uint8_type;
#else
# error Platform does not provide an exact 8-bit integer!
#endif


#if (COUNT_BITS(USHRT_MAX) == 16)
typedef signed short int int16_type;
typedef unsigned char uint16_type;
#else
# error Platform does not provide an exact 16-bit integer!
#endif




int main(void) {
printf("%lu\n", COUNT_BITS(18446744073709551615));
return 0;
}
______________________________________________________________________




This should go up to 1559 bit integers. Anyway, what do you think?
 
C

Chris M. Thomasson

There are a few problems with this:
n may be a signed type
n may be a padded type
n may be wider than the left shifted 1 (int)
[Even 1<<CHAR_BIT can potentially invoke UB.]
Hallvard B Furuseth once posted the following (which
I've edited slightly due to line wrap issues)...
/* Number of bits in inttype_MAX, or in any (1<<b)-1
where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
/0x3fffffffL %0x3fffffffL *30 + \
(m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
12/((m)%31+3))

That does not seem to work at all; here is an example:
______________________________________________________________________
#include <limits.h>
#include <stdio.h>


#define CHECK_BIT_X(n, b) (((n) >> (b)) == 1) ? (b) + 1


#define COUNT_BITS_CALC_X(n, b) ( \
(CHECK_BIT_X(n, (b) + 0) : (CHECK_BIT_X(n, (b) + 1) \
: (CHECK_BIT_X(n, (b) + 2) : (CHECK_BIT_X(n, (b) + 3) \
: (CHECK_BIT_X(n, (b) + 4) : (CHECK_BIT_X(n, (b) + 5) \
: (CHECK_BIT_X(n, (b) + 6) : (CHECK_BIT_X(n, (b) + 7) \
: (CHECK_BIT_X(n, (b) + 8) : (CHECK_BIT_X(n, (b) + 9) \
: (CHECK_BIT_X(n, (b) + 10) : (CHECK_BIT_X(n, (b) + 11) \
: (CHECK_BIT_X(n, (b) + 12) : (CHECK_BIT_X(n, (b) + 13) \
: (CHECK_BIT_X(n, (b) + 14) : (CHECK_BIT_X(n, (b) + 15) \
: (CHECK_BIT_X(n, (b) + 16) : (CHECK_BIT_X(n, (b) + 17) \
: (CHECK_BIT_X(n, (b) + 18) : (CHECK_BIT_X(n, (b) + 19) \
: (CHECK_BIT_X(n, (b) + 20) : (CHECK_BIT_X(n, (b) + 21) \
: (CHECK_BIT_X(n, (b) + 22) : (CHECK_BIT_X(n, (b) + 23) \
: (CHECK_BIT_X(n, (b) + 24) : (CHECK_BIT_X(n, (b) + 24) \
: (CHECK_BIT_X(n, (b) + 26) : (CHECK_BIT_X(n, (b) + 26) \
: (CHECK_BIT_X(n, (b) + 28) : (CHECK_BIT_X(n, (b) + 28) \
: (CHECK_BIT_X(n, (b) + 30) : (CHECK_BIT_X(n, (b) + 31) \
: (CHECK_BIT_X(n, (b) + 32) : (CHECK_BIT_X(n, (b) + 33) \
: (CHECK_BIT_X(n, (b) + 34) : (CHECK_BIT_X(n, (b) + 35) \
: (CHECK_BIT_X(n, (b) + 36) : (CHECK_BIT_X(n, (b) + 37) \
: (CHECK_BIT_X(n, (b) + 38) : (CHECK_BIT_X(n, (b) + 39) \
: (0))))))))))))))))))))))))))))))))))))))))) \
)


#define COUNT_BITS_X(n, b) \
COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


#define COUNT_BITS(n) ( \
(COUNT_BITS_X(n, 0) : (COUNT_BITS_X(n, 40) \
: (COUNT_BITS_X(n, 80) : (COUNT_BITS_X(n, 120) \
: (COUNT_BITS_X(n, 160) : (COUNT_BITS_X(n, 200) \
: (COUNT_BITS_X(n, 240) : (COUNT_BITS_X(n, 280) \
: (COUNT_BITS_X(n, 320) : (COUNT_BITS_X(n, 360) \
: (COUNT_BITS_X(n, 400) : (COUNT_BITS_X(n, 440) \
: (COUNT_BITS_X(n, 480) : (COUNT_BITS_X(n, 520) \
: (COUNT_BITS_X(n, 540) : (COUNT_BITS_X(n, 560) \
: (COUNT_BITS_X(n, 600) : (COUNT_BITS_X(n, 640) \
: (COUNT_BITS_X(n, 680) : (COUNT_BITS_X(n, 720) \
: (COUNT_BITS_X(n, 760) : (COUNT_BITS_X(n, 800) \
: (COUNT_BITS_X(n, 840) : (COUNT_BITS_X(n, 880) \
: (COUNT_BITS_X(n, 920) : (COUNT_BITS_X(n, 960) \
: (COUNT_BITS_X(n, 1000) : (COUNT_BITS_X(n, 1040) \
: (COUNT_BITS_X(n, 1080) : (COUNT_BITS_X(n, 1120) \
: (COUNT_BITS_X(n, 1160) : (COUNT_BITS_X(n, 1200) \
: (COUNT_BITS_X(n, 1240) : (COUNT_BITS_X(n, 1260) \
: (COUNT_BITS_X(n, 1300) : (COUNT_BITS_X(n, 1340) \
: (COUNT_BITS_X(n, 1380) : (COUNT_BITS_X(n, 1420) \
: (COUNT_BITS_X(n, 1460) : (COUNT_BITS_X(n, 1500) \
: (COUNT_BITS_X(n, 1540) : (COUNT_BITS_X(n, 1580) \
: (0))))))))))))))))))))))))))))))))))))))))))) \
)




#if (COUNT_BITS(UCHAR_MAX) == 8)
typedef signed char int8_type;
typedef unsigned char uint8_type;
#else
# error Platform does not provide an exact 8-bit integer!
#endif


#if (COUNT_BITS(USHRT_MAX) == 16)
typedef signed short int int16_type;
typedef unsigned char uint16_type;
#else
# error Platform does not provide an exact 16-bit integer!
#endif


#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
/0x3fffffffL %0x3fffffffL *30 + \
(m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
12/((m)%31+3))


#if (IMAX_BITS(UINT_MAX) == 32)
typedef signed char int32_type;
typedef unsigned char uint32_type;
#else
# error Platform does not provide an exact 32-bit integer!
#endif




int main(void) {
printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551615));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551615));


printf("IMAX_BITS - %lu\n", IMAX_BITS(184467440737095516));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(184467440737095516));


printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551));


return 0;
}
______________________________________________________________________






Here is the output I get on a 32-bit P4:


IMAX_BITS - 64
COUNT_BITS - 64

IMAX_BITS - 858993464
COUNT_BITS - 58

IMAX_BITS - 39
COUNT_BITS - 55




What am I doing wrong?
 
B

Ben Bacarisse

Hallvard B Furuseth once posted the following (which
I've edited slightly due to line wrap issues)...

/* Number of bits in inttype_MAX, or in any (1<<b)-1
where 0 <= b < 3E+10 */

Unless I am miss-reading the notation, that should probably be "where
0 <= (1<<b) < 3E+10".
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) \
/0x3fffffffL %0x3fffffffL *30 + \
(m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4 - \
12/((m)%31+3))

Was there an explanation? :)
 
B

Ben Bacarisse

Chris M. Thomasson said:
"Peter Nilsson" <[email protected]> wrote in message


That does not seem to work at all; here is an example:
int main(void) {
printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551615));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551615));

printf("IMAX_BITS - %lu\n", IMAX_BITS(184467440737095516));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(184467440737095516));

printf("IMAX_BITS - %lu\n", IMAX_BITS(18446744073709551));
printf("COUNT_BITS - %lu\n\n", COUNT_BITS(18446744073709551));

return 0;
}
______________________________________________________________________

Here is the output I get on a 32-bit P4:

IMAX_BITS - 64
COUNT_BITS - 64

IMAX_BITS - 858993464
COUNT_BITS - 58

IMAX_BITS - 39
COUNT_BITS - 55

What am I doing wrong?

IMAX_BITS expects a number of the form (1 << n) - 1. I.e. one less
than a (non-negative) integer power of 2. Only the first example fits
that pattern.
 
C

Chris M. Thomasson

Here is the code with a slight tweak:
___________________________________________________________________
#include <limits.h>
#include <stdio.h>


#define CHECK_BIT_X(n, b) (((n) >> (b)) == 1UL) ? (b) + 1UL


#define COUNT_BITS_CALC_X(n, b) ( \
(CHECK_BIT_X(n, (b) + 0UL) : (CHECK_BIT_X(n, (b) + 1UL) \
: (CHECK_BIT_X(n, (b) + 2UL) : (CHECK_BIT_X(n, (b) + 3UL) \
: (CHECK_BIT_X(n, (b) + 4UL) : (CHECK_BIT_X(n, (b) + 5UL) \
: (CHECK_BIT_X(n, (b) + 6UL) : (CHECK_BIT_X(n, (b) + 7UL) \
: (CHECK_BIT_X(n, (b) + 8UL) : (CHECK_BIT_X(n, (b) + 9UL) \
: (CHECK_BIT_X(n, (b) + 10UL) : (CHECK_BIT_X(n, (b) + 11UL) \
: (CHECK_BIT_X(n, (b) + 12UL) : (CHECK_BIT_X(n, (b) + 13UL) \
: (CHECK_BIT_X(n, (b) + 14UL) : (CHECK_BIT_X(n, (b) + 15UL) \
: (CHECK_BIT_X(n, (b) + 16UL) : (CHECK_BIT_X(n, (b) + 17UL) \
: (CHECK_BIT_X(n, (b) + 18UL) : (CHECK_BIT_X(n, (b) + 19UL) \
: (CHECK_BIT_X(n, (b) + 20UL) : (CHECK_BIT_X(n, (b) + 21UL) \
: (CHECK_BIT_X(n, (b) + 22UL) : (CHECK_BIT_X(n, (b) + 23UL) \
: (CHECK_BIT_X(n, (b) + 24UL) : (CHECK_BIT_X(n, (b) + 24UL) \
: (CHECK_BIT_X(n, (b) + 26UL) : (CHECK_BIT_X(n, (b) + 26UL) \
: (CHECK_BIT_X(n, (b) + 28UL) : (CHECK_BIT_X(n, (b) + 28UL) \
: (CHECK_BIT_X(n, (b) + 30UL) : (CHECK_BIT_X(n, (b) + 31UL) \
: (CHECK_BIT_X(n, (b) + 32UL) : (CHECK_BIT_X(n, (b) + 33UL) \
: (CHECK_BIT_X(n, (b) + 34UL) : (CHECK_BIT_X(n, (b) + 35UL) \
: (CHECK_BIT_X(n, (b) + 36UL) : (CHECK_BIT_X(n, (b) + 37UL) \
: (CHECK_BIT_X(n, (b) + 38UL) : (CHECK_BIT_X(n, (b) + 39UL) \
: (0))))))))))))))))))))))))))))))))))))))))) \
)


#define COUNT_BITS_X(n, b) \
COUNT_BITS_CALC_X(n, b) ? COUNT_BITS_CALC_X(n, b)


#define COUNT_BITS(n) ( \
(COUNT_BITS_X(n, 0UL) : (COUNT_BITS_X(n, 40UL) \
: (COUNT_BITS_X(n, 80UL) : (COUNT_BITS_X(n, 120UL) \
: (COUNT_BITS_X(n, 160UL) : (COUNT_BITS_X(n, 200UL) \
: (COUNT_BITS_X(n, 240UL) : (COUNT_BITS_X(n, 280UL) \
: (COUNT_BITS_X(n, 320UL) : (COUNT_BITS_X(n, 360UL) \
: (COUNT_BITS_X(n, 400UL) : (COUNT_BITS_X(n, 440UL) \
: (COUNT_BITS_X(n, 480UL) : (COUNT_BITS_X(n, 520UL) \
: (COUNT_BITS_X(n, 540UL) : (COUNT_BITS_X(n, 560UL) \
: (COUNT_BITS_X(n, 600UL) : (COUNT_BITS_X(n, 640UL) \
: (COUNT_BITS_X(n, 680UL) : (COUNT_BITS_X(n, 720UL) \
: (COUNT_BITS_X(n, 760UL) : (COUNT_BITS_X(n, 800UL) \
: (COUNT_BITS_X(n, 840UL) : (COUNT_BITS_X(n, 880UL) \
: (COUNT_BITS_X(n, 920UL) : (COUNT_BITS_X(n, 960UL) \
: (COUNT_BITS_X(n, 1000UL) : (COUNT_BITS_X(n, 1040UL) \
: (COUNT_BITS_X(n, 1080UL) : (COUNT_BITS_X(n, 1120UL) \
: (COUNT_BITS_X(n, 1160UL) : (COUNT_BITS_X(n, 1200UL) \
: (COUNT_BITS_X(n, 1240UL) : (COUNT_BITS_X(n, 1260UL) \
: (COUNT_BITS_X(n, 1300UL) : (COUNT_BITS_X(n, 1340UL) \
: (COUNT_BITS_X(n, 1380UL) : (COUNT_BITS_X(n, 1420UL) \
: (COUNT_BITS_X(n, 1460UL) : (COUNT_BITS_X(n, 1500UL) \
: (COUNT_BITS_X(n, 1540UL) : (COUNT_BITS_X(n, 1580UL) \
: (0))))))))))))))))))))))))))))))))))))))))))) \
)




#if (COUNT_BITS(UCHAR_MAX) == 8UL)
typedef signed char int8_type;
typedef unsigned char uint8_type;
#else
# error Platform does not provide an exact 8-bit integer!
#endif


#if (COUNT_BITS(USHRT_MAX) == 16UL)
typedef signed short int int16_type;
typedef unsigned short int uint16_type;
#else
# error Platform does not provide an exact 16-bit integer!
#endif


#if (COUNT_BITS(UINT_MAX) == 32UL)
typedef signed int int32_type;
typedef unsigned int uint32_type;
#else
# error Platform does not provide an exact 32-bit integer!
#endif


#if (COUNT_BITS(18446744073709551615) == 64UL)
# if ! defined (_MSC_VER)
typedef signed long long int int64_type;
typedef unsigned long long int uint64_type;
# else
typedef signed __int64 int64_type;
typedef unsigned __int64 uint64_type;
# endif
#else
# error Platform does not provide an exact 64-bit integer!
#endif




int main(void) {
printf("COUNT_BITS 8 - %lu\n\n",
(unsigned long int)(sizeof(int8_type) * CHAR_BIT));

printf("COUNT_BITS 16 - %lu\n\n",
(unsigned long int)(sizeof(int16_type) * CHAR_BIT));

printf("COUNT_BITS 32 - %lu\n\n",
(unsigned long int)(sizeof(int32_type) * CHAR_BIT));

printf("COUNT_BITS 64 - %lu\n\n",
(unsigned long int)(COUNT_BITS(18446744073709551615)));

printf("COUNT_BITS 63 - %lu\n\n",
(unsigned long int)(COUNT_BITS(9223372036854775807)));

return 0;
}
___________________________________________________________________





Your compiler needs to support 64-bit integers in order to properly count
the last two large numbers.



This should go up to 1559 bit integers. Anyway, what do you think?

Humm...
 
C

Chris M. Thomasson

There was a bug in the `COUNT_BITS_CALC_X' macro. The number sequence had a
bad value. Here is correction:




#define COUNT_BITS_CALC_X(n, b) ( \
(CHECK_BIT_X(n, (b) + 0UL) : (CHECK_BIT_X(n, (b) + 1UL) \
: (CHECK_BIT_X(n, (b) + 2UL) : (CHECK_BIT_X(n, (b) + 3UL) \
: (CHECK_BIT_X(n, (b) + 4UL) : (CHECK_BIT_X(n, (b) + 5UL) \
: (CHECK_BIT_X(n, (b) + 6UL) : (CHECK_BIT_X(n, (b) + 7UL) \
: (CHECK_BIT_X(n, (b) + 8UL) : (CHECK_BIT_X(n, (b) + 9UL) \
: (CHECK_BIT_X(n, (b) + 10UL) : (CHECK_BIT_X(n, (b) + 11UL) \
: (CHECK_BIT_X(n, (b) + 12UL) : (CHECK_BIT_X(n, (b) + 13UL) \
: (CHECK_BIT_X(n, (b) + 14UL) : (CHECK_BIT_X(n, (b) + 15UL) \
: (CHECK_BIT_X(n, (b) + 16UL) : (CHECK_BIT_X(n, (b) + 17UL) \
: (CHECK_BIT_X(n, (b) + 18UL) : (CHECK_BIT_X(n, (b) + 19UL) \
: (CHECK_BIT_X(n, (b) + 20UL) : (CHECK_BIT_X(n, (b) + 21UL) \
: (CHECK_BIT_X(n, (b) + 22UL) : (CHECK_BIT_X(n, (b) + 23UL) \
: (CHECK_BIT_X(n, (b) + 24UL) : (CHECK_BIT_X(n, (b) + 25UL) \
: (CHECK_BIT_X(n, (b) + 26UL) : (CHECK_BIT_X(n, (b) + 27UL) \
: (CHECK_BIT_X(n, (b) + 28UL) : (CHECK_BIT_X(n, (b) + 29UL) \
: (CHECK_BIT_X(n, (b) + 30UL) : (CHECK_BIT_X(n, (b) + 31UL) \
: (CHECK_BIT_X(n, (b) + 32UL) : (CHECK_BIT_X(n, (b) + 33UL) \
: (CHECK_BIT_X(n, (b) + 34UL) : (CHECK_BIT_X(n, (b) + 35UL) \
: (CHECK_BIT_X(n, (b) + 36UL) : (CHECK_BIT_X(n, (b) + 37UL) \
: (CHECK_BIT_X(n, (b) + 38UL) : (CHECK_BIT_X(n, (b) + 39UL) \
: (0))))))))))))))))))))))))))))))))))))))))) \
)




Sorry about that non-sense!


;^(...
 
B

Bartc

Chris M. Thomasson said:
How "reliable" is the following code:
____________________________________________________________
....
____________________________________________________________

Your code gave some warnings about improper shifts.
I am tinkering around with different ways to use the pre-processor to
determine exact number of bits in integral types. Is there a much better
way to do this? What am I missing here?

Perhaps I'm missing the point but I would just use code like the following
for each platform:

#define CHAR_BITS 8
#define SHORT_BITS 16
#define INT_BITS 32
#define LONG_BITS 32
#define INT16_BITS 16

For example "bitsizes.h". Perhaps created by a utility that you run one once
on each platform, which then works out the figures during (it's) runtime.
 
E

Eric Sosman

Chris said:
Eric Sosman said:
Chris said:
How "reliable" is the following code:
[... see up-thread ...]

"Reliable" in the face of what threats or eventualities?
It doesn't work in the presence of padding bits, it might not
work for UINTMAX_MAX or INTMAX_MAX, it definitely won't work for
floating-point types ... I'm not sure what realm of possibilities
you're concerned about.

I would only ever pass the following values to the `COUNT_BITS' macro:


UCHAR_MAX
USHRT_MAX
UINT_MAX
ULONG_MAX


I am assuming that the number of bits it takes to hold any of those
values will be a multiple of `CHAR_BIT'.

Okay, so you're also assuming that the number of padding
bits is also a multiple of CHAR_BIT. That is, you're assuming
that if there's any padding it's in byte-sized chunks.

Note that shifting by `sizeof(unsigned long)*CHAR_BIT' may
be undefined for C99 and *is* undefined for C90.
[...]
The "much better way" -- well, can you formulate your questions
in terms of ranges rather than in terms of logarithms? That is, how
badly do you need actual bit counts?
[...]
The `compiler/vendor/.../core.h' files are required to define some types
that have exact number of bits. If I know the compiler, I will use
specific extensions to get the job done. However, if the compiler is
unknown, well, I need to at least "attempt" to render the correctly
sized types. I need this to all be performed at compile time.

The task of choosing an N-bit type for known N is much
easier than that of finding the number of bits in a type T.
For C90:

#include <limits.h>
#if UCHAR_MAX == 0xFFFFF
typedef unsigned char u20;
#elif USHRT_MAX == 0xFFFFF
typedef unsigned short u20;
#elif UINT_MAX == 0xFFFFF
typedef unsigned int u20;
#elif ULONG_MAX == 0xFFFFF
/* necessarily false; just here to show the pattern */
typedef unsigned long u20;
#else
#error "No 20-bit type!"
#endif

For C99 the repertoire of integer types is open-ended
and you can't enumerate and test them this way. However, C99
has a helpful header of its own:

#include <stdint.h>
#ifdef UINT20_MAX
typedef uint20_t u20;
#else
#error "No 20-bit type!"
#endif
 
K

Kaz Kylheku

...
____________________________________________________________

Your code gave some warnings about improper shifts.


Perhaps I'm missing the point but I would just use code like the following
for each platform:

#define CHAR_BITS 8

What's wrong with CHAR_BIT from <limits.h>?

I get it, you're new.
#define SHORT_BITS 16
#define INT_BITS 32
#define LONG_BITS 32
#define INT16_BITS 16

Would INT16_BITS be anything other than 16? Are you including paddding bits
that don't contribute to the representation of value?
For example "bitsizes.h". Perhaps created by a utility that you run one once
on each platform, which then works out the figures during (it's) runtime.

How do you run this utility if you're cross-compiling?
 
B

Bartc

Kaz Kylheku said:
What's wrong with CHAR_BIT from <limits.h>?

I snipped too much code. The OP seemed to be trying to calculate these,
which seem to include bits in char and int16:

Chris M. Thomasson said:
(unsigned long int)COUNT_BITS(UCHAR_MAX),
(unsigned long int)COUNT_BITS(USHRT_MAX),
(unsigned long int)COUNT_BITS(UINT_MAX),
(unsigned long int)COUNT_BITS(ULONG_MAX),
(unsigned long int)(CHAR_BIT * sizeof(int16_type))
I get it, you're new.

In a way..
Would INT16_BITS be anything other than 16? Are you including paddding
bits
that don't contribute to the representation of value?

I don't know about padding bits. If they need to be included then those
defines (or the bit of code I suggested) need tweaking.
How do you run this utility if you're cross-compiling?

With difficulty. Or just do it manually if it's impossible. Even the
lowliest microprocessor must have some LED (or some I/O pin) it can flash N
times to indicate how many bits in a C word.
 
S

Spiros Bousbouras

Unless I am miss-reading the notation, that should probably be "where
0 <= (1<<b) < 3E+10".

Perhaps you are misreading the notation or perhaps you think
it's too good to be true but the macro really can handle numbers
of the form (1<<b) - 1 where 0 <= b < 30 * ( (1<<30) - 1)
Quite ingenious.
Was there an explanation? :)

http://tinyurl.com/bfeddm
 
B

Ben Bacarisse

Spiros Bousbouras said:
Perhaps you are misreading the notation

No, it seems I was not misreading it, but my suggested correction is
way off.
or perhaps you think
it's too good to be true but the macro really can handle numbers
of the form (1<<b) - 1 where 0 <= b < 30 * ( (1<<30) - 1)

Not "too good to be true" just an unlikely bound on a bit-counting
algorithm! I was, none the less, mistaken.

Thanks for finding that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top