0

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.

Community
  • 1
  • 1
Franx
  • 87
  • 1
  • 10

1 Answers1

4

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.

Jason Hu
  • 6,239
  • 1
  • 20
  • 41
  • 2
    I gave you a vote, but I still have to comment that if the system has a 64-bit `unsigned long long` then the macros are completely useless, since you can simply do this `ull_t result = (ull_t)a * (ull_t)b` where `ull_t` is a typedef for `unsigned long long`. Those macros were designed for tiny embedded systems that have no builtin support for 64-bit math. – user3386109 Mar 05 '15 at 20:42
  • Yup, that might be the reason :) – user3386109 Mar 05 '15 at 20:45
  • @user3386109 Note: I am working with one of those " tiny embedded systems" and `(1<<16)` is UB for `int` is 16-bit, not to mention problems with `((LOW_WORD(a) * HIGH_WORD(b)) << 16)`. IAC, my code does have 64-bit types. IOWs, there are many problems with the macros. – chux - Reinstate Monica Mar 05 '15 at 21:00
  • @chux I was tempted to add an answer that shows how to do the multiplication correctly on a system that has 32-bit `long ints` and no support for 64-bit types, but it's not clear to me what OP is actually trying to accomplish. This answer addresses the immediate question, "what does that error message mean?" – user3386109 Mar 05 '15 at 21:10
  • @chux Exactly my case. Next time go with your instinct! :) That would be the perf I have no support for 64-bit math. @user3386109 I have no support for 64-bit math. So actually the result that I produce i have to save it in two variables? One 32 bit for the integer part and another for the fractional? So actually the `apo` variable which is `int64_t` has to become two....? Or is that a compiler job, meaning that even if I declare a variable 64-bits the machine is going to save it in two 32-bit registers? Did I mention thank you for your time? :P ... a lot! – Franx Mar 06 '15 at 10:51
  • @HuStmpHrrr First of all thank you. What I did was just casting the last line as you said to `long long` : `((long long)(HIGH_WORD(a) * HIGH_WORD(b)) << 32)`. If you could explain/extend a little your answer why is it important turning the macros to a function? and why is the 17th bit also important if its set? Thanks – Franx Mar 06 '15 at 10:59
  • @Franx macro in C is not complete, in terms of side effect. function is more formalized. if you are aware of efficiency, you can make it inline. in gcc, it's as fast as macro. about the 17th bit thing, it's a consideration of overflow. but it would be totally unnecessary if you choose to cast it to `long long`. – Jason Hu Mar 06 '15 at 14:05
  • @HuStmpHrrr Thanks. About the overflow i know the range of the computed values (the results) and it wont be overflowed. But SHOULD I cast if the processor supports 32-bit x 32-bit multiplies with a 32-bit result, (no support 64-bit results) ?? – Franx Mar 06 '15 at 14:16
  • @Franx you need to check the 33rd bit to know that. but you now cast it to `long long`, how comes it doesn't support 64-bit results. – Jason Hu Mar 06 '15 at 14:23
  • @HuStmpHrrr I cast it for the sake of the result, just to get the right result. I am not compiling with the targets compiler. I am just writing the code so it can be imported later on...(is that wrong?) – Franx Mar 08 '15 at 20:02