GP32 Fixed Point Math


Charge

Member
Joined
May 26, 2003
Messages
206
Age
45
Location
Croydon, England
Hi,

last night I tried writing a few fixed point math routines to get started in GP32 development. I used 8 bits for the fixed part, 16 for the number, and 8 bits of padding so that when I need to multiply I dont loose most of the number.

The structs I use are as follows :

typedef struct FIXED_TAG
{
unsigned int decimal : 8;
int number : 16;
int buffer : 8;
} FIXED;

typedef struct FIXED_UNION_TAG
{
union
{
FIXED fSplit;
int nWhole;
};
} FIXED_UNION;

and any fixed point numbers are therefore of type FIXED_UNION.
eg:

FIXED_UNION first_fp_num;
FIXED_UNION second_fp_num;
FIXED_UNION result_fp;

If I multiply 2 fixed point numbers together I do it by :

result_fp.nWhole = ((first_fp_num.nWhole * second_fp_num.nWhole) >> 8);


Ththis works fine, except when I used negative numbers with a decimal part. Does anyone have the solution?

Cheers.
 
Well, in my math library i only use the type, int.
and 16:16 fixed point numbers, since the ARM have some nifty instructions to multiply 2 32bit numbers and produce a 64bit result. (which means you won't loose any precision)

Anyway, you mean that you have 8 binals?
I think the problem you are getting is that the padding is the upper 8 bits, and therefore when you write the number to FIXED.Number you are not setting bit 24-31 of FIXED_INION.nWhole.
And i guess that could screw up negative numbers pretty badly.

---
mithris
 
thanks,

changed my structure to :

typedef struct FIXED_TAG
{
unsigned int decimal : 8;
int number : 24;
} FIXED;

and it improved.

However it wasn't right. Then i realised that I was printing the numbers incorrectly :blink: cos I had done this at about 3.00am last night when I came in from a Saturday night session. Now it works.

BUT you say there is a way to keep 16.16 presision on the ARM!? and docs or info you can point me to please?

Cheers,
 
no docs, but.
look at the instruction "smull"
here's an example:

void fpm_fpmul(int val1, int val2, int *pRet)
{
asm volatile ("
smull r3, r4, %0, %1
mov r3, r3, lsr#16
mov r4, r4, asl#16
orr r5, r3, r4
str r5, [%2]
"
:
: "r" (val1), "r" (val2), "r" (pRet)
:"r3", "r4", "r5");

}

---
mithris
 
Back
Top