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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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 
> Jamie Morken (address@hidden) describes 
> 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]