gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > FIXED multiplication

#23311 - ProblemBaby - Fri Jul 09, 2004 7:17 pm

If I multiply two FIXED values i Get a value
but when I multiply the same thing but negative I dont get this relation
x == -y
it differs, why and how can I fix that I dont want to make if-tests in my FixedMul-function.

now my function looks like this:
((a * b) >> 8)

Its very important for me to fix this...

#23315 - jma - Fri Jul 09, 2004 8:13 pm

You are using an unsigned shift instead of a signed one, mose likely.

Jeff
_________________
massung@gmail.com
http://www.retrobyte.org

#23317 - ProblemBaby - Fri Jul 09, 2004 8:25 pm

um how?

#23320 - poslundc - Fri Jul 09, 2004 8:53 pm

If your variables are declared as unsigned (eg. u16 or u32) then it will perform a logical (unsigned) shift instead of an arithmetic (signed) shift. Use s16 or s32 instead.

Dan.

#23321 - ProblemBaby - Fri Jul 09, 2004 9:24 pm

What but the other told me not to do it...
this is my code

typedef signed int FIXED;

FIXED v1, v2;

v1 = 4238829;
v2 = 2348823;

s1 = (v1*v2)>>8;
s2 = (v1*-v2)>>8;

if (s1 == -s2) // this is not true.. s2 = -s1 - 1
{

}

#23322 - jma - Fri Jul 09, 2004 9:44 pm

Uh... I hate to break it to you, but those numbers are huge. The largest fixed point number (assuming 24.8 fp math) you can get is 16777215. And 4238829 * 2348823 = 9956259048267 which is well outside the 32-bit range (so your shift croaks).

Jeff
_________________
massung@gmail.com
http://www.retrobyte.org

#23325 - ProblemBaby - Fri Jul 09, 2004 10:18 pm

Remember that
4238829 and 2348823 are fixed.

it would be
16557,92578125
and
9175,08984375
with 24.8

#23326 - jma - Fri Jul 09, 2004 10:45 pm

Quite right, but you still get the same problem:
16557 * 9175 = 151910475 > 0xFFFFFF (24-bit)

Hell, maybe I am just thinking too fast (been a long day at work), but just try plugging in smaller numbers and see if it works.

Jeff
_________________
massung@gmail.com
http://www.retrobyte.org

#23328 - poslundc - Fri Jul 09, 2004 11:51 pm

ProblemBaby wrote:
Remember that
4238829 and 2348823 are fixed.

it would be
16557,92578125
and
9175,08984375
with 24.8


Okay, here's the thing. You've got an s32, and you want to split it up into 24 bits of integer and 8 bits of fraction.

You do that with your first number (16,557.whatever) and it is stored internally as a 32-bit value: 4238829.

Your second number (9175.whatever) is stored internally as 2348823.

You perform the multiplication and get 9956259048267 internally. It requires 44 bits to represent that number (45 signed), which is more than the 32 you've got in your s32 variable.

You've got some options. You can downshift your variables beforehand if you don't mind losing precision on your result. Alternatively, you can use the long long datatype to do 64-bit multiplication. It isn't cheap on the processor, though, so you don't want to be doing it unless your application really requires that kind of precision with numbers that large.

Dan.

#23340 - ProblemBaby - Sat Jul 10, 2004 2:58 am

Well yeah they are too big
but that isnt the point the point is why:

for example

a = (56 * 56) << 8;
b = (56 * -56) << 8;

a == -b // this should be true but it isnt

#23342 - poslundc - Sat Jul 10, 2004 4:21 am

You're right, that code should work if both variables are signed and 32 bits.

So there is probably something in the context you are using it in that is making it not work. Can you post the actual code, including where the variables are defined and how you are performing the test and checking the result?

Dan.