Post Reply 
ArcTan(x,y)?
04-06-2017, 03:30 PM
Post: #21
RE: ArcTan(x,y)?
(04-05-2017 10:41 PM)KeithB Wrote:  So if the limit of atan2(x,x) as x approaches 0 is 45, maybe that is what atan2() should return?

Clearly, discontinuities near 0 cannot be avoided - I have even seen it suggested online that one could scale values and use integer arithmetic to work around. I am beginning to wonder whether returning an error might be useful. But many Atan2 implementations do return 0, so changing to return 45 instead would introduce compatibility issues.

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
04-06-2017, 03:53 PM (This post was last modified: 04-06-2017 04:01 PM by Han.)
Post: #22
RE: ArcTan(x,y)?
(04-06-2017 03:30 PM)StephenG1CMZ Wrote:  
(04-05-2017 10:41 PM)KeithB Wrote:  So if the limit of atan2(x,x) as x approaches 0 is 45, maybe that is what atan2() should return?

Clearly, discontinuities near 0 cannot be avoided - I have even seen it suggested online that one could scale values and use integer arithmetic to work around. I am beginning to wonder whether returning an error might be useful. But many Atan2 implementations do return 0, so changing to return 45 instead would introduce compatibility issues.

Care should be taken when evaluating limits of 2-variable functions. See second-to-last post in:

http://www.hpmuseum.org/forum/thread-7346.html

atan(x/x) is 45, but atan(0/x) is 0 and atan(y/0) is 90*sign(y) (EDIT: I erroneously wrote "infinite" earlier). The limit does not exist so mathematically atan(0/0) is undefined.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
04-09-2017, 09:50 AM
Post: #23
RE: ArcTan(x,y)?
(04-06-2017 03:30 PM)StephenG1CMZ Wrote:  
(04-05-2017 10:41 PM)KeithB Wrote:  So if the limit of atan2(x,x) as x approaches 0 is 45, maybe that is what atan2() should return?

Clearly, discontinuities near 0 cannot be avoided - I have even seen it suggested online that one could scale values and use integer arithmetic to work around. I am beginning to wonder whether returning an error might be useful. But many Atan2 implementations do return 0, so changing to return 45 instead would introduce compatibility issues.

The PRIME function polar_coordinates, also works in a similar way:

polar_coordinates(1,1) returns: [1.41421356237 45]

polar_coordinates(0.001,0.001) returns: [1.41421356237ᴇ−3 45]

polar_coordinates(0,0) returns: [0 0]
Find all posts by this user
Quote this message in a reply
04-09-2017, 03:47 PM (This post was last modified: 04-09-2017 05:26 PM by StephenG1CMZ.)
Post: #24
RE: ArcTan(x,y)?
(04-09-2017 09:50 AM)JMB Wrote:  
(04-06-2017 03:30 PM)StephenG1CMZ Wrote:  Clearly, discontinuities near 0 cannot be avoided - I have even seen it suggested online that one could scale values and use integer arithmetic to work around. I am beginning to wonder whether returning an error might be useful. But many Atan2 implementations do return 0, so changing to return 45 instead would introduce compatibility issues.

The PRIME function polar_coordinates, also works in a similar way:

polar_coordinates(1,1) returns: [1.41421356237 45]

polar_coordinates(0.001,0.001) returns: [1.41421356237ᴇ−3 45]

polar_coordinates(0,0) returns: [0 0]

Interesting.

Arctan returns an angle.

It was only after Debugging why polar_coordinates sometimes doesnt return at all that I realised polar_coordinates returns a pair of values instead (I know, the plural "coordinates" should have been a clue) - which explains why something goes wrong if you assign it to a global rather than local variable...

Code:


 LOCAL XY:=0.0001;
 LOCAL II;
 LOCAL KK:=3;

 PC(XX,YY)
 BEGIN
  PRINT("PC");
  FOR II FROM 1 TO KK DO
   PRINT(II);
   XY:=polar_coordinates(1+2*);
   A:=polar_coordinates(1+2*);//STALLS
   PRINT(II);

  END;
  RETURN 1;
 END;

 EXPORT TNBUG() 
 BEGIN
  PRINT();
  PRINT(TEVAL(N:=PC(XY,XY)));
  PRINT("STALLS"); 
 END;

I was trying to time which of the three alternatives was slower, and I'm still waiting for polar_coordinates to finish the race Smile [Android version]

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
04-09-2017, 08:00 PM
Post: #25
RE: ArcTan(x,y)?
(04-09-2017 03:47 PM)StephenG1CMZ Wrote:  I was trying to time which of the three alternatives was slower, and I'm still waiting for polar_coordinates to finish the race Smile [Android version]

The function polar_coordinates returns a vector, so instead of A you have to use one of the global variables M0, M1, ..., M9 as storage.
Find all posts by this user
Quote this message in a reply
04-09-2017, 09:54 PM (This post was last modified: 04-09-2017 09:58 PM by StephenG1CMZ.)
Post: #26
RE: ArcTan(x,y)?
I have put together a little program to illustrate the relative timings of the various methods.
Some of the timings can be improved, but it gives an idea.
The printouts seem to be in duration order, quickest first, although sometimes that can change on the Android (presumably because the phone is taking cycles).

Code:


 LOCAL XY:=0.0001;
 LOCAL II;
 LOCAL KK:=1000;

 
 ATANS(XY)
 BEGIN
  RETURN ATAN(XY/XY);
 END;

 ATANSIMPLECALL(XY)
 BEGIN
  FOR II FROM 1 TO KK DO
   U:=ATANS(XY);
  END;
  RETURN U;
 END;

 ATANYX(YY,XX)
  BEGIN
  IF YY==0 AND XX==0 THEN
   RETURN 0;
  END;
  RETURN ARG(XX+*YY);
  END;
 


 ATANYXCALL(YY,XX)
 BEGIN
  FOR II FROM 1 TO KK DO
   U:=ATANYX(YY,XX);
  END;
  RETURN U;
 END;


arctanxy(x, y)
begin
  local a;
  if x == 0 then
    if y == 0 then
      a := 0;
    else
      a := sign(y) * pi / 2
    end;
  else
    a := atan(y / x);
    if x < 0 then
      if y < 0 then
        a := a - pi;
      else
        a := a + pi;
      end;
    end;
  end;

  return a;

end;
 
 ATANPCALL(XX,YY)
 BEGIN
  FOR II FROM 1 TO KK DO
   U:=arctanxy(XX,YY);
  END;
  RETURN U;
 END;

 ARGZ(XX,YY) 
 BEGIN
  RETURN ARG(XX+*YY);
 END;
 
 ARGZCALL(XX,YY) 
 BEGIN
  FOR II FROM 1 TO KK DO
   U:=ARGZ(XX,YY);
  END;
  RETURN U;
 END;

 PC(XX,YY)
 BEGIN
  RETURN polar_coordinates(XX+YY*);
 END;

 PCCALL(XX,YY)
 BEGIN
  LOCAL TMP;
  FOR II FROM 1 TO KK DO
   TMP:=PC(XX,YY);
  END;
  RETURN TMP[2];
 END;

 EXPORT TN() 
 BEGIN
  LOCAL RR;
  LOCAL SP:="      ";

  PRINT();
  PRINT(KK +" LOOPS");

  //SIMPLE ATAN:QUADRANT IGNORANT
  PRINT("ATAN1: "+TEVAL(RR:=ATANSIMPLECALL(XY))+SP+RR);
  
  //CALL ARG:MAY FAIL IF YOUR COMPILERS ARG DOESNT DO 0
  PRINT("ARG: "+TEVAL(RR:=ARGZCALL(XY,XY))+SP+RR);
 
  //CALL USER ATAN (USING ARG) HANDLING 0
  PRINT("ATAN(ARG):"+TEVAL(RR:=ATANYXCALL(XY,XY))+SP+RR);
  
  //CALL USER ATAN (PORTABLE) HANDLING 0
  //WORKS ON PLATFORMS WITHOUT ARG
  PRINT("ATAN(Portable):"+TEVAL(RR:=ATANPCALL(XY,XY))+SP+RR);

  //CALL coordinates:FAIL IF GLOBAL
  PRINT("polar : "+TEVAL(RR:=PCCALL(XY,XY))+SP+RR); 
  END;

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 2 Guest(s)