[Top][All Lists]
[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