[scilab-Users] Atan function

Michaël Baudin michael.baudin at scilab.org
Wed May 18 10:52:09 CEST 2011


Hi,

I do not see any bug in Scilab in this thread except, perhaps, in Matlab.

At first, we can inspect the plot of the atan(y,x) function:

scf();
N=20;
y=linspace(-4,4,N);
x=linspace(-4,4,N);
Z=(feval(y,x,myatan))';
surf (y ,x ,Z);
h = gcf ();
cmap = graycolormap (10);
h. color_map = cmap ;
xtitle("atan(y,x)","y","x");

There is a discontinuity on the line y=0 for x<0.

The following session:

-->atan(0,+0)
  ans  =
     0.
-->atan(0,-0)
  ans  =
     3.1415927

is caused by the signed zeros of the IEEE floating point arithmetic. The 
values returned by atan are consistent with the mathematical limit of 
the atan(0,x) function.

The signed zero exists because there are two ways of representing zero 
in a floating point format:

  * (-1)^0 * 0 * 2^-1022
  * (-1)^1 * 0 * 2^-1022

In both case, the significant is zero and the exponent is set to the 
minimum. But in the first case, the sign bit is set to 0, while in the 
second it is set to 1. This topic is covered in "Floating point numbers 
in Scilab", section 3.8 "Signed zeros":

http://forge.scilab.org/index.php/p/docscifloat/downloads/

These signed zeros can be consistently used to make branch cuts of 
inverse trigonometric function consistent, as emphasized by Kahan in 
"Branch cuts for complex elementary functions, or much ado about 
nothing's sign bit".

Exactly the same session can be reproduced in Octave, although Scilab 
atan(y,x) is called atan2(y,x) in Octave:

octave-3.2.4.exe:5> atan2([+0 -0 +0 -0],[+0 +0 -0 -0])
ans =

    0.00000  -0.00000   3.14159  -3.14159

This is the same result as in Scilab:

-->atan([+0 -0 +0 -0],[+0 +0 -0 -0])
  ans  =
     0.    0.    3.1415927  - 3.1415927

These values are consistent with the values given in the ISO C99 
standard (see the section F.9.1.4 "The atan2 functions"). These values 
are also consistent with the wikipedia page:

http://en.wikipedia.org/wiki/Atan2

See the "Variations" section and the note on the FPATAN function.

On the other hand, it seems to me that Matlab has a chosen to set zero 
on output whenever one of the inputs x or y is zero:

 >> atan2([+0 -0 +0 -0],[+0 +0 -0 -0])
ans =
      0     0     0     0

My point of view is that this is a bug, but it seems that this is on 
purpose:

http://www.mathworks.com/support/solutions/en/data/1-1CBTV/index.html?product=ML

Most functions consistently take into account for signed zeros in 
Scilab. The fact that

-->-0==+0
  ans  =
   T

is not really surprising: it is consistent with the mathematical 
definition of the zero.

The "sign" function in Scilab does not allow to distinguish these two zeros:

-->sign(+0)
  ans  =
     0.
-->sign(-0)
  ans  =
     0.

This is consistent with the mathematical definition of the "sign" 
function, which is zero when x is zero.

The missing function in Scilab is "signbit", which returns the sign bit 
of the given number. A implementation is available in the floating point 
module :

http://forge.scilab.org/index.php/p/floatingpoint/source/tree/HEAD/macros/flps_signbit.sci

This implementation is based on the fact that the most simple way to 
know the sign bit of a real number is to invert it, as shown in the 
following session:

-->ieee(2)
-->1/-0
  ans  =
   - Inf
-->1/+0
  ans  =
     Inf

Using this function is simple with ATOMS:

-->atomsInstall("floatingpoint");
-->atomsLoad("floatingpoint");
-->b = flps_signbit ( +0 )
  b  =
   F
-->b = flps_signbit ( -0 )
  b  =
   T

There are a couple of functions also missing in this category, 
including: copysign, hypot, isfinite, pow2.

Best regards,

Michaël Baudin

PS
Here are a couple of plots.

// 2D plots
scf();
subplot(2,2,1);
z2=atan(y,-4*ones(y));
plot(y,z2)
xtitle("atan(y,-4)","y");
//
subplot(2,2,2);
z2=atan(y,-2*ones(y));
plot(y,z2)
xtitle("atan(y,-2)","y");
//
subplot(2,2,3);
z2=atan(y,+2*ones(y));
plot(y,z2)
xtitle("atan(y,2)","y");
//
subplot(2,2,4);
z2=atan(y,+4*ones(y));
plot(y,z2)
xtitle("atan(y,4)","y");



Le 11/05/2011 15:49, Samuel GOUGEON a écrit :
>  ----- Message d'origine -----
> De : Serge Steer
> Date : 10/05/2011 22:57:
>> Le 10/05/2011 21:18, Samuel GOUGEON a écrit :
>>>  Look at that:
>>>
>>> -->atan(0, 0)
>>>  ans  =
>>>     0.00000000D+00
>>>
>>> -->atan(0, -0)
>>>  ans  =
>>>     3.14159265D+00
>>>
>>> --> -0 == 0
>>>  ans  =
>>>   T
>>>
>>> :-(( Funny, isn't it ?!
>> This later result is really quite  funny, but the atan result is just 
>> due to the branch cut definition for that function
> The "special" branching cut is used only when atan() is used with a 
> single argument.
> It is not the case here. The help page states: The range of atan(y,x) 
> is (-pi, pi].
> while : atan(-0,-0)== -%pi  => %T
>
> By the way, how is it possible to explain that the sign of -0 looks to 
> be recorded
> in floating point mode?? This "feature" makes Scilab somewhat 
> unconsistent:
> -->floor(-0)
>  ans  =
>     0.
> // -1 would instead be expected!
> -->sign(-0)
>  ans  =
>     0.
> -->sign(-number_properties("tiniest"))
>  ans  =
>   - 1.
> This is why atan(y,x) should return always the same result if x and y 
> are reals and null.
> -->help minus // does not document this special feature, no more than
> -->help sign
>
> Finally, to answer to Laurent:
>
> How can I guess that variable x is -0 and not 0?
>
> is_0minus = (x==0 & atan(0,x)==%pi);
>
> but we should hope that this puzzling feature will be fixed.
>
> Samuel
>


-- 
Michaël Baudin
Ingénieur de développement
michael.baudin at scilab.org
-------------------------
Consortium Scilab - Digiteo
Domaine de Voluceau - Rocquencourt
B.P. 105 - 78153 Le Chesnay Cedex
Tel. : 01 39 63 56 87 - Fax : 01 39 63 55 94





More information about the users mailing list