Search code examples
c64-bit32-bitmultiplicationfixed-point

Multiplication of 32 bits numbers in C


Why the below code produces this error?

error: left shift count >= width of type [-Werror]

The code:

int32_t a,b;
int64_t apo;
a = 2673;
b = 19;
apo = BIG_MULL(a,b);
printf("\n %ld \n", apo );

The macros found here:

#define WORD_MASK ((1<<16) - 1)
#define LOW_WORD(x)  (x & WORD_MASK)
#define HIGH_WORD(x) ((x & (WORD_MASK<<16)) >> 16)
#define BIG_MULL(a, b) \
((LOW_WORD(a)  * LOW_WORD(b))  <<  0) + \
((LOW_WORD(a)  * HIGH_WORD(b)) << 16) + \
((HIGH_WORD(a) * LOW_WORD(b))  << 16) + \
((HIGH_WORD(a) * HIGH_WORD(b)) << 32)

I am trying to multiply to signed values of 32 bit. The target machine has no support of 64 bit math.


Solution

  • assume you are trying to multiple two 32-bit int to a 64-bit result manually, in your macro,

    ((HIGH_WORD(a) * HIGH_WORD(b)) << 32
    

    shifts beyond the length of a int, so you have that error.

    if you want to make it work, first change BIG_MULL to a function, and:

    1. cast to long long and perform multiplication. long long is oftenly long enough in system with 32-bit int.
    2. continue simulating with a proper struct.

    second one is a little bit subtle, but is doable. first you need to operate on unsigned int and have

    struct {
        unsigned int low, high;
    } bigmul_result;
    

    and perform what you have done in the macro but turn

    ((LOW_WORD(a)  * HIGH_WORD(b)) << 16) + \
    ((HIGH_WORD(a) * LOW_WORD(b))  << 16)
    

    to

    (((LOW_WORD(a)  * HIGH_WORD(b)) + (HIGH_WORD(a) * LOW_WORD(b))) << 16)
    

    so that it's easy to remember to check the sum to see if 17th bit is set. if so, add 1 to high.