avr-gcc-list
[Top][All Lists]

## Re: [avr-gcc-list] Problem with asin() and acos()

 From: jlf Subject: Re: [avr-gcc-list] Problem with asin() and acos() Date: Wed, 9 Oct 2002 22:50:20 +0200

```Hi all,
thanks for the help so far.
I'll try to sum up some of the comments from the avrFreaks-gcc
forum and from the avr-gcc and avr-libc mailing lists:

1) asin() does return incorrect values close to pi/2.
2) Since acos() equals pi/2-asin(), this one is also flawed.
3) A feasible workaround is to make your own functions using:
asin(y) = atan2(sqrt(1-y*y, y).

Mmmm, as far as I can see, asin(y) = atan(y/sqrt(1-y*y)
is just as good, because sqrt() is always positive so
atan2() always returns an angle in the -pi/2...pi/2 range.
So in this case we win nothing using atan2() instead of atan().

Anyway, my suggestion is this:

/* atan2(0,1) and atan2(0,-1) never returns on the ATMega163,
(no check for zero division?) therefore some ugly
checks are needed...
Using "if (y==1.0)..." is not enough...
returned value is in the range [-pi/2...pi/2]
*/
double my_asin(double y) {
if (fabs(y-1)<0.0000001)
return M_PI/2;   /* y=1 => x=atan(1/0)=pi/2 */
if (fabs(y+1)<0.0000001)
return -M_PI/2;  /* y=-1 => x=atan(-1/0)=-pi/2 */
return(atan2(sqrt(1-y*y), y)); /* -1<y<1 => -pi/2<x<pi/2 */
}

/* returned value is in the range [0...pi]
*/
double my_acos(double y) {
return(M_PI/2 - my_asin(y)); /* -1<=y<=1 => 0<=x<=pi */
}

-----------------------------------------
This is a list of some results, compared with
results from a calculator
Errors from 4-5th digit, but good enough for my purpose.

y      my_asin(y)  calculator
0.60000000  0.64342572  0.64350111
0.70000000  0.77533760  0.77539750
0.80000000  0.92736312  0.92729522
0.90000000  1.11975840  1.11976952
0.99000000  1.42921120  1.42925685
0.99900000  1.52615504  1.52607124
0.99990000  1.55671648  1.55665407
0.99999000  1.56638240  1.56632419
1.00000000  1.57079632  1.57079633 (= pi/2)

- jesper

On 1 Oct 2002 at 22:39, address@hidden wrote:

> Greetings,
> the acos() and asin() calls cause me some trouble,
> they return incorrect numbers as shown for acos in
> the listing below. tan(x), sin(x) and cos(x) are ok.
>
> In a posting on the avr-gcc mailing list july 27th
> exactly the same problem.
> What strokes me in Jamie's desciption is that he gets
> the same (wrong) result as I did:
> y=1.00000000 => acos(y)=0.08713222
> (I would expect something close to 0...).
>
> So, does anybody know if acos/asin really are flawed? Is there
> any possible work-around? Or have I missed something?
>
> If there are any (verified) code examples out there which uses
> acon or asin, please post an example or an URL.
>
> I use the ATMega163 and the latest windows-distro from avrFreaks: -
> avr-gcc 3.2 - avr-libc-20020612 - binutils-20020614
>
>
>
> - jesper
>
>
avr-gcc-list at http://avr1.org

```