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.

Coding > signed long long integers?

#41595 - nicouiuc - Sat Apr 30, 2005 1:48 am

Hi together,

I am still fighting with a control algorithm I set up on the GBA. I used fixed point math to set up an equation; however, that did not really work. So i put my filter into matlab, and the reason why its not working is HUGE integer numbers. I need a precision of about 30 bits, else the filter screws up.

Now I was wondering if I can use signed long long integers on the GBA. TONC says I could use them; however, I did not really find much more about it on the internet.

I tried it, and some problems occured:
1) I have to declare them as "volatile", else my display crahes, or it sometimes shows up in funny colours. I dont really know what volatile means to variables. Are they else moved into an area that the display uses maybe?
2) When I display the variables, it shows an "normal" integer which is overflowing. However, when I display the final result of the computation (which is right shifted again), it might make sense, im not sure though.

So my question is if I can use signed long long int at all, and if so, if theres anything i have to be beware of.

Thanks,
~Nico

#41599 - sgeos - Sat Apr 30, 2005 3:49 am

nicouiuc wrote:
I need a precision of about 30 bits, else the filter screws up.

A regular signed long int has 32 bits precision. 1 bit sign, 31 bits integer.

nicouiuc wrote:
1) I have to declare them as "volatile", else my display crahes, or it sometimes shows up in funny colours. I dont really know what volatile means to variables. Are they else moved into an area that the display uses maybe?

What are you trying to do? Volatile is a way of telling the compiler "don't optimize this variable, something outside outside this code needs all values exactly as provided."

nicouiuc wrote:
2) When I display the variables, it shows an "normal" integer which is overflowing. However, when I display the final result of the computation (which is right shifted again), it might make sense, im not sure though.

Have you tried a signed long int?

nicouiuc wrote:
So my question is if I can use signed long long int at all, and if so, if theres anything i have to be beware of.

It was an extension of gcc last time I checked. As such it may not be portable in theory. The GBA does not have native support for 64-bit ints, so operations on a long long will be done in software (slow). If you need 64-bit ints and you don't care about speed, long long is fine. If you need speed (probably not), use assembler.

-Brendan

#41601 - nicouiuc - Sat Apr 30, 2005 4:47 am

Ok,

I do care about speed, as long as it doesnt take more than maybe 400microseconds.

Quote:

What are you trying to do? Volatile is a way of telling the compiler "don't optimize this variable, something outside outside this code needs all values exactly as provided."


I want to use them as regular changing variables, I just set them up as volatile because else my programm crashed several times or the text display was screwed up or coloured.

Quote:

Have you tried a signed long int?


yeah I set up a signed long long int, and it is displaying an overflow shortly after it reaches 2 billion, e.g. it seems to be an overflowing signed int, not signed long long int.

Quote:

It was an extension of gcc last time I checked. As such it may not be portable in theory.


Ok, Im not very familiar with this, sorry :-) That means that I'd "just" have to update the gcc Im using in the DevKit?

And, btw, I was thinking this afternoon of "taking the calculations apart", e.g. use integers for the fractional part and different ones for the non-fractional.... but I first have to sit down and think about if and how that works.

#41612 - poslundc - Sat Apr 30, 2005 8:04 am

nicouiuc wrote:
So my question is if I can use signed long long int at all, and if so, if theres anything i have to be beware of.


Long longs (they are signed by default) are somewhat wonky and are intended primarily for maintaining precision when multiplying two regular 32-bit integers, which is required frequently enough that the ARM processor has native support for it (and not other 64-bit operations).

The biggest caveat to be aware of is that while in other expressions, simpler data types will get promoted to more complicated ones (eg. if you add an integer and a float, it treats them both as floats), long longs will constantly get demoted to regular ints unless you thoroughly make sure all terms of an expression are either long long or cast to that type. It can become quite a hassle.

If your math application really requires numbers with greater precision than 32 bits, consider other numeric representations as well. Long longs are serviceable, but they really aren't cut out for mathematical manipulation.

And if you need 30 bits of precision... well, regular ints get you 31 bits of precision, so that's a whole extra bit of wiggle room you have before you should even have to consider 64-bit numbers.

Dan.

#41822 - nicouiuc - Mon May 02, 2005 5:05 am

Dan,

thanks for your help. I need about 30 bits of precision, yes, else its not working. The problem is, i need the 30 bits for representing only the fractional part; I have to do some multiplications and that makes my registers blow up/overflow.

What do you mean by

Quote:

If your math application really requires numbers with greater precision than 32 bits, consider other numeric representations as well. Long longs are serviceable, but they really aren't cut out for mathematical manipulation.


floats take too long, i tried it. What did you think of?

Thanks,
~Nico

#41868 - Miked0801 - Mon May 02, 2005 5:31 pm

I've never had much luck with long longs. If I needed more precision than 32-bits, I'd break the number up into 2 longs and do the math myself. That said, 30 bits of precision? And program crashing if not made volatile? The second sounds like an array/memory over-write error. The first makes me think your algorithm may need some tweaking. 30 bits of precision is a ton! If the last few bits cause issue, part of your equation is way overly sensitive and probably could be improved.

#41869 - poslundc - Mon May 02, 2005 5:36 pm

I would recommend analyzing your problem and determining at what points you really need more than 32 bits of precision. Without knowing more about the nature of the problem you are solving, I find it really surprising that you need to retain 32 bits just for the fractional part over the entire course of the problem - that's a level of precision of 1/(2^32) = 1 over more than 4 billion.

That's the idea behind long longs - you switch to them when you need them for temporary calculations, before switching back to more conventional data types. If you want to use them for persistent calculations involving more than the basic four operators, it's buyer beware.

That said, you have a couple of options. You could create a struct/class for storing both an integral and fractional portion, and write functions/methods to temporarily represent them as a long long when needed for the mathematical calculations that require it. (You could use a union to have a single 64-bit variable contain both the long long representation and the integer/fraction representation.)

You could also have a look at BCMath, a library used by the PHP scripting language for arbitrary-precision calculations that represents numbers as strings. I'm certain that there are other similar arbitrary-precision libraries out there as well that you could look at porting over to the GBA.

But again, I really have to stress the preferability of examining your problem and seeing if you can squeeze it into 32 bits.

Dan.

#41875 - DekuTree64 - Mon May 02, 2005 6:06 pm

nicouiuc wrote:
I need about 30 bits of precision, yes, else its not working. The problem is, i need the 30 bits for representing only the fractional part; I have to do some multiplications and that makes my registers blow up/overflow.


If multiplication is the only thing that ever overflows, you can fix it with a small assembly function to use the ARM's 32x32=64 bit multiply. Try putting this in a .s file:
Code:
.text
.global mul30
.align 2
.arm
mul30:
smull r2, r3, r0, r1       @ r2:r3 = r0 * r1
mov   r0, r2, lsr #30      @ Shift the 64 bit result...
orr   r0, r0, r3, lsl #1   @ ...30 bits to the right
bx    lr


And this in a .h/.c/.cpp file:
Code:
#ifdef __cplusplus
extern "C" {
#endif

extern s32 mul30(s32 m1, s32 m2);

#ifdef __cplusplus
}
#endif


Hope that helps.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#41969 - nicouiuc - Tue May 03, 2005 9:20 pm

Hi,

it was indeed only the multiplication that blew up the registers; with the help of DekuTree, I split up my vector multiplication into single 32bitx32bit multiplications, shifted those results and then added them all together. I also changed my sampling timer to a lower rate to be able to get rid off some precision. That did the job finally, and my robot started working with the filter :-)

Thanks to all for the help; However, I occured a new problem/question, but this one should be much easier :-) I posted a new topic...