atan (double) accuracy is about the same as atanf (float)

Asked by Donald Haselwood

On a STM32F407, using atan (double) and launchpad with hard floating pt, the accuracy is about the same as atanf (float), and of course much slower. Using CodeSourcery and soft fp the accuracy for atan is the same as when I compare to the results on the PC with gnu C.
For example--
 atan(0.15)
0.148889947609497253639 atanl (long double) on PC
0.14888994760950 STM32 CodeSourcery & soft fp
0.14888994433051 STM32 launchpad & hard fp
                      ^^^^^^
atanf(.15)
0.14888995 STM32 launchpad & hard fp

This suggests something is limiting the precision for trig routines when doubles are being used. What is behind the low accuracy for the atan (double)? Are the double trig routines for hard fp using floats?

Question information

Language:
English Edit question
Status:
Answered
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Terry Guo (terry.guo) said :
#1

Could you please list the version information of tools you are using? I want to reproduce your results before I start to look into it. Thanks.

Revision history for this message
Terry Guo (terry.guo) said :
#2

Hello,

I ran below codes on my STM32F407 board with OpenOCD as gdb server:

  double x = 0.15;
  printf ("atan(0.15):%.20f\n", atan (x));
  printf ("atanf(0.15f):%.20f\n", atan (0.15f));

Here are the outputs I collected:
atan(0.15):0.14888994760949725293
atanf(0.15f):0.14888995343880234712

They look good compared to what you said. Is there anything wrong I am doing?

Revision history for this message
Donald Haselwood (dhaselwood) said :
#3

Terry,

Thanks for the reply.

I'm not sure what you are running. Is the code you are running
stand-alone on the STM32F407 board, or running via the gdb/OpenOCD? Or
putting it another way, is gdb handling the printf. I was wondering if
the result might be really the atan from the PC side.

I looked at the .list file for atan and I see a number of 'v'
instructions which indicates that atan is using the hw fp registers,
which I think are only 32 bits. For example, a few snips--

08005c68 <atan>:
 8005c68: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
 8005c6c: ec55 4b10 vmov r4, r5, d0

See if your .list for atan has 'vmov' (as well as others, e.g. 'vldr').

Don

On Mon, 2014-08-25 at 07:12 +0000, Terry Guo wrote:
> Your question #253552 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/253552
>
> Terry Guo requested more information:
> Hello,
>
> I ran below codes on my STM32F407 board with OpenOCD as gdb server:
>
> double x = 0.15;
> printf ("atan(0.15):%.20f\n", atan (x));
> printf ("atanf(0.15f):%.20f\n", atan (0.15f));
>
> Here are the outputs I collected:
> atan(0.15):0.14888994760949725293
> atanf(0.15f):0.14888995343880234712
>
> They look good compared to what you said. Is there anything wrong I am
> doing?
>

Revision history for this message
Donald Haselwood (dhaselwood) said :
#4

Terry,

Some additional info--

Using the code you used, the following was run on my STM32F407 board
(output on uart6)--

...
volatile double x = 0.15;
xprintf (6,"\natan(0.15):%.20f\n\r", atan (x));
xprintf (6,"atanf(0.15f):%.20f\n\r\n", atan (0.15f));
...

Which puts out the following--

atan(0.15):0.14888995343880234712
atanf(0.15f):0.14888995343880234712

Which indicates that atan is putting out the same as atanf.

Using my routine which separates the atan from the printf--
Source code C statement--
  ...
  rr = atan(xx);
  ...

.list file
  ...
  rr = atan(xx);
 8005af4: ec45 4b10 vmov d0, r4, r5
 8005af8: f000 f93e bl 8005d78 <atan>
 8005afc: ec57 6b10 vmov r6, r7, d0
  ...

I place a breakpoint and examine the registers following execution at
address 0x8005afc--

r6 0x60cd2906
r7 0x3fc30ed3

So the double returned from atan is--
0x3fc30ed360cd2906

Which according the binary to decimal converter--
http://www.binaryconvert.com/result_double.html?hexadecimal=3FC30ED360CD2906
gives the following--
1.48889944330513113168734662395E-1

My program printf gives--
0.14888994433051

Which means the printf is correct, i.e. it is not a conversion problem.

And, of course, the value is incorrect.

Don

Don

On Mon, 2014-08-25 at 07:12 +0000, Terry Guo wrote:
> Your question #253552 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/253552
>
> Terry Guo requested more information:
> Hello,
>
> I ran below codes on my STM32F407 board with OpenOCD as gdb server:
>
> double x = 0.15;
> printf ("atan(0.15):%.20f\n", atan (x));
> printf ("atanf(0.15f):%.20f\n", atan (0.15f));
>
> Here are the outputs I collected:
> atan(0.15):0.14888994760949725293
> atanf(0.15f):0.14888995343880234712
>
> They look good compared to what you said. Is there anything wrong I am
> doing?
>

Revision history for this message
Donald Haselwood (dhaselwood) said :
#5

Terry,

On Mon, 2014-08-25 at 03:51 +0000, Terry Guo wrote:
Your question #253552 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/253552
>
> Status: Open => Needs information
>
> Terry Guo requested more information:
> Could you please list the version information of tools you are using?
I
> want to reproduce your results before I start to look into it. Thanks.
>
>

launchpad version--

deh@dehmain:/opt/launchpad/gcc-arm-none-eabi-4_8-2014q2/bin$
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.4 20140526
(release) [ARM/embedded-4_8-branch revision 211358]
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

flashing--
  stlink-texane: st-flash

Starting to use this more--
  OpenOCD-0.8.0 stlink-v2

Debugging--
  Sometimes: stlink-texane: st-util w telnet localhost 4444
  Sometimes: gdb w st-util

Don

Revision history for this message
Donald Haselwood (dhaselwood) said :
#6

Terry,

I think I have it sorted out.

On Mon, 2014-08-25 at 07:12 +0000, Terry Guo wrote:
> Your question #253552 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/253552
>
> Terry Guo requested more information:
> Hello,
>
> I ran below codes on my STM32F407 board with OpenOCD as gdb server:
>
> double x = 0.15;
> printf ("atan(0.15):%.20f\n", atan (x));
> printf ("atanf(0.15f):%.20f\n", atan (0.15f));
>
> Here are the outputs I collected:
> atan(0.15):0.14888994760949725293
> atanf(0.15f):0.14888995343880234712
>
> They look good compared to what you said. Is there anything wrong I am
> doing?

Yes, you are computing atan twice. The second one should be atanf.
That threw me, too. I was puzzling why both would give exactly the same
answer...

My problem was coming from computing the argument for the double
separately from the float. For decimal arguments that are not exact
representations in binary the arguments were slightly different for the
float and double. If one sets the double argument from the float
argument, then atan produces the expected result, otherwise the
arguments have the potential for being slightly different.

The difference between the same program on the PC and the STM32 may be
due to 64b vs 32b. I haven't checked this out. The key is that the
arguments must be exactly the same, which in retrospect is obvious.

At this point it looks like the STM32 atan is producing the correct
results out to about 14 or 15 decimal digits, which is about all that
can be expected.

All of the above also was true for sin and tan.

Don

Revision history for this message
Terry Guo (terry.guo) said :
#7

I am sorry, Don. You are right about the twice uses of atan. I realized this issue too. Then I changed the code to:

  volatile double x = 0.15;
  volatile float y = 0.15f;
  printf ("atan(0.15):%.20f\n", atan (x));
  printf ("atanf(0.15f):%.20f\n", atanf (y));

Now the results from stm32f407 board are:
atan(0.15):0.14888994760949725293
atanf(0.15f):0.14888995885848999023

For double precision, only 14 or 15 digital numbers in above results in decimal format make sense.

Revision history for this message
Joey Ye (jinyun-ye) said :
#8

Answered

Can you help with this problem?

Provide an answer of your own, or ask Donald Haselwood for more information if necessary.

To post a message you must log in.