(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.
(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.
(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]
(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
[Android version]
(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 [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.
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;