avr-gcc floating point problems

In response to another thread, I am still getting these problems with WinAVR 2010. I think the linker is hitting some AVR limits. There are similar reports on the web as well.

-------------------------------------------------------------------------------------------------

unsigned char u; float f;

u = (unsigned char) f;

--------------------------------------------------------------------------------------------------- c:/wavr10/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/ avr35\libc.a(fp_powsodd.o): In function `__fp_powsodd': (.text.avr-libc.fplib+0x10): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/wavr10/bin/../lib/gcc/avr/4.3.3/avr35\libgcc.a(_mul_sf.o) c:/wavr10/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/ avr35\libc.a(fp_powsodd.o): In function `__fp_powsodd': (.text.avr-libc.fplib+0x20): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/wavr10/bin/../lib/gcc/avr/4.3.3/avr35\libgcc.a(_mul_sf.o)

Reply to
linnix
Loading thread data ...

-------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------

"relocation truncated to fit" sure sounds ominous.

Altavista-ing that phrase pops up with a discussion on an Intel board of

32-bit vs. 64-bit immediate addressing, and the comment "If you're seeing this and you're not hand-coding, you probably want to check out the -mmodel argument to gcc."

So it appears that it's not really doing anything serious other than completely screwing up your addressing.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

Le Thu, 18 Mar 2010 10:47:44 -0700, linnix a écrit :

In what kind of situation you need to cast a float to that unsigned char ??? If you want to extract the integer part of the float, let me tell you that this way is a bit silly.

Question yourself before asking to C.

Habib

Reply to
Habib Bouaziz-Viallet

f is result of k1 * sine x + k2 * cosine y.

How would you extract the integer part without casting? I thought that's the job of the compiler.

Reply to
linnix

-------------------------------------------------------------------------------------------------

Approach it a little at a time: Try casting to a (signed) int first. If that works, then unsigned (assuming your value truly is "non negative"). Finally, shrink it to a char.

Sometimes compilers get upset if you do things that it doesn't expect.

You might also experiment with real doubles to see if there are any subtle differences.

---------------------------------------------------------------------------------------------------

Reply to
D Yuniskis

Well, technically, there are a lot of ways you *could* do it -- but most are not as efficient as a simple cast. Remember that a cast *discards* the fractional part (i.e., doesn't round). Also, the cast will misbehave if the argument doesn't fit in the data type.

Reply to
D Yuniskis

--------------------------

Noop, this does not work either:

int i; unsigned char u;

i =3D (int) f; u =3D (unsigned char) i;

---------------------------------------------------

All these ops works on x86 gcc. I guess AVR is not ready for floating points. Any one got FP apps working for AVR? For me, I am ready to ARM, as soon as my LPC (ARM Cortex M0) kit arrival.

----------------------------

Reply to
linnix

Le Thu, 18 Mar 2010 12:39:32 -0700, linnix a écrit :

Sure that's the compiler job, so please cast a float to an integer (signed int). Remember char are not meant to be used for math.

Keep It Simple.

Habib

Reply to
Habib Bouaziz-Viallet

The cast isn't necessary but it may give a hint to the compiler that what you've written is what you've intended. In a simple assignment, the operator itself causes the type of the right operand to be converted to the type of the left and the resulting value to then be stored in the object indicated by the left operand. Absent the cast, you're likely to get an "Are you sure you meant to do this?" type of warning.

When a real (e.g., not a NAN or otherwise) floating point type is converted to an integer type, the fractional part is simply discarded (no rounding, truncate towards zero). You will hit undefined behavior, though, if the resulting integral value can't be represented in the intended integer type.

So, "u = f;" is perfectly legal, no cast required, but f would have to be in the open interval (-1, UCHAR_MAX + 1) to avoid undefined behavior.

An explicit cast doesn't hurt and also lets the maintenance programmer know that yes, this is what I meant to do.

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

But the real world (as least in my case) is unsigned char (8 bits).

Now, the strange thing is:

i =3D (int) f; works or u =3D (unsigned char) i; works

but not together i =3D (int) f; u =3D (unsigned char) i;

Unless my apps is very unique (USB CDC A2D), I have to conclude that AVR is not ready for it.

Reply to
linnix

I do heavy floating point computations with AVR (IAR workbench compiler), and it works nicely. BTW, the math on the AVR at 20MHz is somewhat 3 times faster then the same math on 40MHz PIC18.

My experience is not all compilers provide for every possible cast between the standard types; I have seen bugs in float int conversions also. But you can always do a function for explicit conversion.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

g

n.

Then I guess it's a avr-gcc porting problem. I'll check if arm-gcc works or not.

Reply to
linnix

-------------------------------------------------------------------------------------------------

Try ICC's AVR compiler. There's a free trial that decays to a code-size limited version after 45 days. Imagecraft produces compilers for quite a few microcontrollers but their AVR offering is far and away their most popular.

I tried your test above and it compiles cleanly. Don't have an AVR dev board or breadboard set up right now but I'll give it a run this evening. I expect it to work as per spec, though.

formatting link

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

Le Thu, 18 Mar 2010 13:29:24 -0700, linnix a écrit :

...

oh no you cannot conclude that AVR or avr-gcc or AVR and avr-gcc are not ready for doing math, no you cannot !

Habib

Reply to
Habib Bouaziz-Viallet

It sounds like it's at least partially an optimizer bug.

Try lowering the optimization level (and hope that whoever wrote it was paying attention).

Or make a function

int cast_float_to_int_boy_gcc_is_stupid(float f) { return (int) f; }

in extreme cases you may need to put it in a separate file to _really_ confound an over-eager optimizer.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

If you insert some printfs (or just single-step a debugger), what does it produce for i and u (assuming, say, f was... 123.456 to begin with?)?

Just the compiler. :-)

Reply to
Joel Koltner

Now it works if I remove some other functions. I guess I am hitting some kinds of compiler limits.

Yes, I got correct result of 123.

Yes, it is taking too much time for me. I'll try other options.

Reply to
linnix

That is a bit too harsh. This may be an optimisation problem or a problem in the libraries. Check the assembler to see what is going on. Try to compile with -O0 to turn off all optimisation first and try again.

--
Failure does not prove something is impossible, failure simply
indicates you are not using the right tools...
nico@nctdevpuntnl (punt=.)
--------------------------------------------------------------
Reply to
Nico Coesel

Are you sure you're not just flat out running out of room?

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

On a sunny day (Thu, 18 Mar 2010 13:16:33 -0700 (PDT)) it happened linnix wrote in :

Are you doing fft? (sin cos). I just tried integer fft in C, made 2 versions, one with an 8 bit sine lookup table, and one with a 16 bit table. Fiddled it so all values fit in a 16 bit integer... can do integer math. Now I can port it to PIC.... in asm. The difference is noticable when compared to floating point, but on a 64 bit high display the 'noise' reduces to very little. I mean you need to divide a lot... to fit the maximum... So it all depends, I think my integer fft is good, worth some money too.

Reply to
Jan Panteltje

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.