Archived

This topic is now archived and is closed to further replies.

fixedpoint multiply?

This topic is 6998 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Ok, here's the general algorthm in C++. Please note: this is the general case so please optimize it for your personal needs before you use it.

// I am assuming something like this
typedef long FixedPoint;
// assuming long is 32 bits
#define FP_INTEGER_PRECISION 16
#define FP_DECIMAL_PRECISION 16

FixedPoint operator*(FixedPoint op1,FixedPoint op2)
{
FixedPoint op2int = op2 > FP_DECIMAL_PRECISION;
FixedPoint op2dec = op2 & FP_DECIMAL_MASK;
FixedPoint product = 0;
product = op1 * op2dec;
product = product > FP_DECIMAL_PRECISION;
product += op1 * op2high;
return product;
}

I haven't had time to test this code...so please respond here or email me if it has any errors. Also, please note that the potential for overflow is enormous. It is no different than multiplying 2 integers, but it is easy to forget that the highest 32 bit fixed point number (if 16x16 format is assumed) is the same as a 16 bit number, so 300*254 doesn't fit.

[This message has been edited by Xai (edited October 17, 1999).]

Share on other sites
ASM is the only way to reliably multiply and divide fixed point numbers, because you can span 2 registers to make sure no accuracy is lost. You would have to twist my arm to get me to do fixed point multiply/divide using C/C++ code. Note that I'm not some fixed point lunatic (I've used it twice) and I would use floats 99% of the time. Only fixed point when you have to convert to integer often (like screen coordinates)

Share on other sites
First of all, I think the problem is that "SHRD"...in ASM, the instruction is "SHR"(shift right). So that's probably what is wrong, however...I have my own function here that you can try:

fixed FixedMul(fixed num1, fixed num2)
{
fixed result;
bool sign=0;
asm
{
//num1 = ebx = eax
//num2 = ecx = edx
FixedMul_top:
mov ebx, num1
mov ecx, num2
xor eax, eax
xor edx, edx
//Check for negative numbers...
cmp ebx, 0
jg FixedMul_next1
mov sign, 1
neg ebx
FixedMul_next1:
cmp ecx, 0
jg FixedMul_next2
xor sign, 1
neg ecx
FixedMul_next2:
//num1.high * num2.high
mov eax, ebx
mov edx, ecx
shr eax, 16
shr edx, 16
mul edx
shl eax, 16
mov result, eax
//num1.high * num2.low
mov eax, ebx
mov dx, cx
shr eax, 16
mul edx
//num2.high * num1.low
xor eax, eax
mov edx, ecx
mov ax, bx
shr edx, 16
mul edx
//num1.low * num2.low
xor eax, eax
xor edx, edx
mov ax, bx
mov dx, cx
mul edx
shr eax, 16
//If sign variable is true, negate result
cmp sign, 0
jz FixedMul_bottom
neg result
FixedMul_bottom:
}
return (result);
}

It takes 2 32-bit fixed numbers, and returns a 32-bit fixed product. The precision is 16 bits, that is, shift right 16 times to get the integer value(but I'm sure you knew that). Optimize it further if you can/want to...let me know how it works for you or if you have questions.

asmlock@aol.com

Share on other sites
asmlock - first of all, your fixed multiply is shitty complicated. Also, SHRD instruction is right and should be used.

Nazghul - this routine was written for Watcom C, so it has this strainght syntax not compatible with VC. You can use this procedure anyway:

fixed FixedMul(fixed f1, fixed f2) {
fixed result;
asm {
mov eax, f1
mov edx, f2
imul edx
shrd eax,edx,16
mov result,eax
}
return result;
}

There is fixed point math unit on my homepage (written for pascal, but all procedures in asm). You can look there for more fixed point functions (like division, rounding, square roots etc...)

------------------
FlyFire/CodeX
http://codexorg.webjump.com

Share on other sites
You're right, SHRD is what to use...I didn't even check into it. I feel like an idiot now because I didn't even consider looking it up(I haven't needed to use anything beyond 32-bit multiplys...so I forgot about double-precision).
Anyway, what my function did was F.O.I.L. the top and bottom 16 bits of both numbers to avoid overflow, sorry about the complicated nature of it.

Share on other sites
Hello everybody!

I need to multiply two fixedpoint variables.
The following snippet is from a friend. But it does'nt work in MS-Visual C++ 5:

Fixedpoint FixedMul(long num1, long num2);
#pragma aux FixedMul = \
"imul edx" \
"shrd eax, edx, 16" \
parm caller [eax] [edx] \
value [eax] \
modify [eax edx];

Can anybody help me by converting the above snippet into plain C/C++/Pascal/Delphi.
Or just ASM without the "shrd"-command.
The Debugger stops on that line with "unknown command"...

Thanks!
Nazghul

1. 1
2. 2
Rutin
15
3. 3
4. 4
5. 5

• 13
• 26
• 10
• 11
• 9
• Forum Statistics

• Total Topics
633733
• Total Posts
3013585
×