POV-Ray : Newsgroups : povray.general : I have a problem with atan2() Server Time16 Apr 2024 10:41:49 EDT (-0400)
 I have a problem with atan2() (Message 1 to 10 of 10)
 From: kurtz le pirate Subject: I have a problem with atan2() Date: 17 Oct 2021 06:40:29 Message: <616bfd9d\$1@news.povray.org>
Hello,

I have a problem with  atan2(a,b) when b = zero.

The documentation on the page
<http://www.povray.org/documentation/view/3.7.1/228/> says :

Arc-tangent of (A/B). Returns the angle, measured in radians, whose
tangent is (A/B). **Returns appropriate value even if B is zero**

In my case, i get : Parse Error: Domain error in atan2!

So it's up to me to test if b=zero and return the appropriate value ?

--
Kurtz le pirate
Compagnie de la Banquise
 From: Le Forgeron Subject: Re: I have a problem with atan2() Date: 17 Oct 2021 08:01:30 Message: <616c109a\$1@news.povray.org>
Le 17/10/2021 à 12:40, kurtz le pirate a écrit :
>
> Hello,
>
> I have a problem with  atan2(a,b) when b = zero.
>
> The documentation on the page
> <http://www.povray.org/documentation/view/3.7.1/228/> says :
>
> Arc-tangent of (A/B). Returns the angle, measured in radians, whose
> tangent is (A/B). **Returns appropriate value even if B is zero**
>
> In my case, i get : Parse Error: Domain error in atan2!
>
> So it's up to me to test if b=zero and return the appropriate value ?
>
>
>
Looking at the code (parser_expression.cpp), it is a direct call to
atan2 function.
Povray parsed A, B, so from atan2 man page, A=y, B=x, *BUT* the code is
just defensive:

<pre>
if (FTRUE(Val) || FTRUE(Val2))
Val = atan2(Val,Val2);
else
Error("Domain error in atan2!");
break;
</pre>

0 & 0 : Domain error. Which is correct as well as atan2 implementation
returning +pi/-0/-pi/+0 according to y,x being +/-0 at the same time.
 From: kurtz le pirate Subject: Re: I have a problem with atan2() Date: 17 Oct 2021 11:48:21 Message: <616c45c5\$1@news.povray.org>
On 17/10/2021 14:01, Le_Forgeron wrote:

> ...
> Povray parsed A, B, so from atan2 man page, A=y, B=x, *BUT* the code is
> just defensive:
> ...
>

Clear and precise answer. I was misled by the description of the
function in the documentation.

--
Kurtz le pirate
Compagnie de la Banquise
 From: Alain Martel Subject: Re: I have a problem with atan2() Date: 17 Oct 2021 11:56:58 Message: <616c47ca\$1@news.povray.org>
Le 2021-10-17 à 06:40, kurtz le pirate a écrit :
>
> Hello,
>
> I have a problem with  atan2(a,b) when b = zero.
>
> The documentation on the page
> <http://www.povray.org/documentation/view/3.7.1/228/> says :
>
> Arc-tangent of (A/B). Returns the angle, measured in radians, whose
> tangent is (A/B). **Returns appropriate value even if B is zero**
>
> In my case, i get : Parse Error: Domain error in atan2!
>
> So it's up to me to test if b=zero and return the appropriate value ?
>
>
>

A/B is undefined when B = 0.
So, «Parse Error: Domain error in atan2» is the appropriate value when B
is zero.
The appropriate value when B is zero would be plus AND minus infinity.
 From: Kenneth Subject: Re: I have a problem with atan2() Date: 17 Oct 2021 14:15:00 Message:
kurtz le pirate <kur### [at] gmailcom> wrote:
>
> Clear and precise answer. I was misled by the description of the
> function in the documentation.
>

I would be mislead by that too. The docs imply that *a value* will be returned
(not a domain error message)-- but "The appropriate value when B is zero would
be plus AND minus infinity", as Alain has mentioned. Which naturally triggers a
domain-error. Seems to me that the error message should be worded more
appropriately, at least. Or the docs should include this bit of info, for users
who may not know the math details of what happens when B=0.
 From: Cousin Ricky Subject: Re: I have a problem with atan2() Date: 17 Oct 2021 17:46:33 Message: <616c99b9@news.povray.org>
On 2021-10-17 6:40 AM (-4), kurtz le pirate wrote:
>
> I have a problem with  atan2(a,b) when b = zero.
>
> The documentation on the page
> <http://www.povray.org/documentation/view/3.7.1/228/> says :
>
> Arc-tangent of (A/B). Returns the angle, measured in radians, whose
> tangent is (A/B). **Returns appropriate value even if B is zero**
>
> In my case, i get : Parse Error: Domain error in atan2!

Is your value for A also zero?

> So it's up to me to test if b=zero and return the appropriate value ?

It seems that some people are confused about atan2().

Of course, the inverse tangent of A/0 is undefined, because A/0 is
undefined.  But a simple limits exercise, as well as the very definition
of the tangent of an angle, show that these undefined tangents
correspond to the angles pi/2 and -pi/2, and it is therefore useful to
pretend that they are valid.

The purpose of atan2() is to handle these special cases, by converting a
naive atan()'s argument into an ordered pair, thus allowing the would-be
inverse tangent of A/0 to be computed without having to divide by 0.  A
simple scene file shows that the *only* time atan2() fails with a domain
error is when *both* A and B are zero.  Of course, (0, 0) is an
indeterminate case, for which returning a value would be nonsensical.

----------[BEGIN CODE]----------
#version 3.7;
global_settings { assumed_gamma 1 }
#declare Args = array [9]
{ <0, 1>, <1, 1>, <1, 0>, <1, -1>, <0, -1>,
<-1, -1>, <-1, 0>, <-1, 1>, <0, 0>,
}
#for (I, 0, 8)
#debug concat ("atan2 (", vstr (2, Args[I], ", ", 0, 0), ") = ")
#debug concat (str (atan2 (Args[I].x, Args[I].y), 0, 6), "\n")
#end
-----------[END CODE]-----------

This scene runs fine with the 3rd and 7th arguments; it does not halt
with a parse error until it gets to the last argument.

Perhaps "unless both A and B are zero" could be added to the documentation.
 From: kurtz le pirate Subject: Re: I have a problem with atan2() Date: 18 Oct 2021 11:42:41 Message: <616d95f1\$1@news.povray.org>
On 17/10/2021 23:46, Cousin Ricky wrote:

> ...
> Of course, the inverse tangent of A/0 is undefined, because A/0 is
> undefined.  But a simple limits exercise, as well as the very definition
> of the tangent of an angle, show that these undefined tangents
> correspond to the angles pi/2 and -pi/2, and it is therefore useful to
> pretend that they are valid.
>
> The purpose of atan2() is to handle these special cases, by converting a
> naive atan()'s argument into an ordered pair, thus allowing the would-be
> inverse tangent of A/0 to be computed without having to divide by 0.  A
> simple scene file shows that the *only* time atan2() fails with a domain
> error is when *both* A and B are zero.  Of course, (0, 0) is an
> indeterminate case, for which returning a value would be nonsensical.
> ...

Cousin Ricky is right about everything!

And therefore, my problem is when A AND B are equal to zero.

Lot of datas to deal with, the debugging will be long...
(i'm working on the visualization of complex functions with domain coloring)

--
Kurtz le pirate
Compagnie de la Banquise
 From: Alain Martel Subject: Re: I have a problem with atan2() Date: 18 Oct 2021 12:25:17 Message: <616d9fed\$1@news.povray.org>
Le 2021-10-18 à 11:42, kurtz le pirate a écrit :
> On 17/10/2021 23:46, Cousin Ricky wrote:
>
>> ... Of course, the inverse tangent of A/0 is undefined, because A/0 is
>> undefined.  But a simple limits exercise, as well as the very definition
>> of the tangent of an angle, show that these undefined tangents
>> correspond to the angles pi/2 and -pi/2, and it is therefore useful to
>> pretend that they are valid.
>>
>> The purpose of atan2() is to handle these special cases, by converting a
>> naive atan()'s argument into an ordered pair, thus allowing the would-be
>> inverse tangent of A/0 to be computed without having to divide by 0.  A
>> simple scene file shows that the *only* time atan2() fails with a domain
>> error is when *both* A and B are zero.  Of course, (0, 0) is an
>> indeterminate case, for which returning a value would be nonsensical.
>> ...
>
> Cousin Ricky is right about everything!
>
> And therefore, my problem is when A AND B are equal to zero.
>
> Lot of datas to deal with, the debugging will be long...
> (i'm working on the visualization of complex functions with domain
> coloring)
>
>
>
Add a test to see if both A and B are zero, and replace that with some
small value for B. It could be something like the following just before
the call to atan2 :

#if (A=0 ! B=0) #declare B= 0.001; #end
... atan2(A,B) ...
 From: Bald Eagle Subject: Re: I have a problem with atan2() Date: 18 Oct 2021 15:25:00 Message:
Alain Martel <kua### [at] videotronca> wrote:

> > And therefore, my problem is when A AND B are equal to zero.
> >
> > Lot of datas to deal with, the debugging will be long...
> > (i'm working on the visualization of complex functions with domain
> > coloring)
> >
> >
> >
> Add a test to see if both A and B are zero, and replace that with some
> small value for B. It could be something like the following just before
> the call to atan2 :
>
> #if (A=0 ! B=0) #declare B= 0.001; #end
> ... atan2(A,B) ...

This problem seems to come up a fair number of times

http://news.povray.org/web.5d4222c54ed4290e4eec112d0%40news.povray.org

And I've had the same sorts of problems and even segmentation faults and core
dumps triggered by similar issues with acos and asin.

Off the top of my head, the way I see it, is that if you're taking atan2 (A/B),
and both A and B are zero, then let's assume arguendo that A is held constant at
zero throughout the evaluation of all B's.  0/N is always zero, so the above
suggested solution and past similar solutions seem to be a good way to address
the issue.

I typically use the usual 1x10^-6 value used for coincident surface stuff and
whatnot in POV-Ray, but maybe Bill P or someone else could suggest a better
value, or that atan2 values could be graphed for a range of B values to get a
better idea of where the point of diminishing returns / insignificant
differences in results lies.

Perhaps it might be a good idea to have a few wrapper macros to perform these
calculations with effective and reliable protective measures proceding the
evaluation of atan2, asin, and acos.
 From: Kenneth Subject: Re: I have a problem with atan2() Date: 19 Oct 2021 06:50:00 Message:
the impression that there is no truly *standard* way of implementing the
function.

"The realization of the function differs from one computer language to another."

Hmm, that doesn't sound good.

"The C function atan2, and most other computer implementations, are designed
to...always define atan2(0, 0). On implementations without signed zero, or when
given positive zero arguments, it is normally defined as 0. It will always
return a value...rather than raising an error or returning a NaN (Not a
Number)."

However...
"For systems implementing signed zero, infinities, or Not a Number (for example,
IEEE floating point)...these *may* return NaN or raise an exception when given a
NaN argument."

Then it gets more complex-- with such stuff as real vs. imaginary-and/or-complex
numbers, "undefined" vs. "indeterminate" values, "signed 0" vs. "unsigned 0",
the two arguments sometimes being reversed, etc.

Various programs and computer languages handle the atan2(0,0) problem in
different ways-- and with different outcomes(!)

Much of this stuff is way over my head, as I am a NaM
(Not-a-Mathematician :-P ),
but the overall situation is surprising to me. And some of the explanations
border on the realm of mathematical 'philosophy'.