7

In fixed point math I use a lot of 16bit signals and perform multiplication with 32bit intermediate results. For example:

int16_t a = 16384; //-1.0q14  or 1.0*2^14
int16_t b = -24576; // -1.4q14  or 1.4*2^14
int16_t c; // result will be q14

c = (int16_t)(((int32_t)a * (int32_t)b)>>14);

Lets say a is a q14 number then c with have the same scaling as b.

This is fine and works for unsigned as well as signed arithmetic.

The question is: What happens if I were to mix types? For example if I know the multiplier "a" is always going to range from 0.0 to 1.0, it is tempting to make it an unsigned int q15 to get the extra bit of precision (and change the shift count to 15). However, I never understood what happens if you try to multiply signed and unsigned numbers in C and have avoided it. In ASM I don't recall there being a multiply instruction that would work with mixed types on any architecture, so even if C does the right thing I'm not sure it would generate efficient code.

Should I continue my practice of not mixing signed an unsigned types in fixed point code? Or can this work nicely?

phkahler
  • 5,687
  • 1
  • 23
  • 31
  • 2
    This post will answer you're question about what happens when multiplying signed and unsigned integers. http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe. Short answer is, as long as they are the same rank (size), a signed is implicitly typecast to unsigned. – Benjamin Leinweber Jun 06 '13 at 16:05
  • Post an answer instead of a comment so I can accept it ;-) – phkahler Jun 10 '13 at 19:52
  • For some reason at the time I thought I was only answering part of your question, so I left it as a comment. Now that I look again, I'm not sure why I thought that. Thanks! – Benjamin Leinweber Jun 11 '13 at 00:19

2 Answers2

10

This post Talks about what happens when multiplying signed and unsigned integers. Short answer is, as long as they are the same rank (size), a signed is implicitly typecast to unsigned.

As long as you understand the typecasting rules (of whatever language you are programming in), or use explicit typecasting, and you also understand the implications of typecasting from signed to unsigned (a negative number will produce what may appear as gibberish when typecasted to a signed value), then there should be no issue mixing signed and unsigned types.

Community
  • 1
  • 1
Benjamin Leinweber
  • 2,774
  • 1
  • 24
  • 41
  • In my case mixing types will result in wrong results according to the rules. And that's what I was afraid of. – phkahler Jun 11 '13 at 22:16
  • 1
    Can you edit your post above with the exact values that you are imputing into a and b which come up with results that go against the rules? – Benjamin Leinweber Jun 11 '13 at 23:00
0

I had a similar problem. It caused an access violation crash in x64 version. The code iterates through a buffer of image scan lines. Getting the next scan line pointer goes as:

unsigned char* pImg = ...
int stride = -3324;
unsigned int iRow = 1; // 2, 3, 4, ...
unsigned char* pNextLine = pImg + stride * iRow

Negative stride means iterating from bottom towards top scan line. The product stride * iRow i.e. signed * unsigned is typecasted to unsigned __int64 with value 4294963972 which pushes the pNextLine out of program's memory.

The same happens with the x32 program version, but there is no crash. Maybe because the x32 pNextLine pointer just wraps around (but stays within the program's memory).

Naum
  • 105
  • 1
  • 7