# New Ticket Created by  [EMAIL PROTECTED] 
# Please include the string:  [perl #37117]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=37117 >


This is a bug report for perl from [EMAIL PROTECTED],
generated with the help of perlbug 1.35 running under perl v5.8.7.

This bug is still present in 5.9.2.

-----------------------------------------------------------------
[I just found out about perlbug. I hope this finally is the
preferred method of reporting bugs. This one's really easy to
fix (just apply the three line patch), but can be a real hassle
if it isn't fixed. I have tried contacting the former module
author (before Math::Complex went into the core), but the mail
address of Mr. Lewart is no longer valid.]

The syntax of using the atan2 routine is, generally:
atan2(y, x) = atan(y/x).

You will know that
atan(0) = 0. (Since tan(0) = 0 = sin(0) / cos(0).)

perl -MMath::Complex -e "print atan2(0,1)"
prints '0' alright. (Which is, in fact atan(0/1).)

perl -MMath::Complex -e "print atan2(1,0)"
prints pi/2 alright. (Which is, in fact atan(1/0)
and lim(x-->inf) atan(x) is pi/2.)

Now, in the complex plane, we get:
perl -MMath::Complex -e "print atan2(0,i)"
i/0: Division by zero.
Died at c:/perl/perl58/lib/Math/Complex.pm line 1284.

This is not correct. Obviously, 0/i is the same as 0/1
which is 0. Thus atan2(0,i) == atan2(0,1) == atan(0) == 0

At fault is the following code:
sub atan2 {
      my ($z1, $z2, $inverted) = [at]_;
      my ($re1, $im1, $re2, $im2);
      if ($inverted) {
          ($re1, $im1) = ref $z2 ? [at]{$z2->cartesian} : ($z2, 0);
          ($re2, $im2) = [at]{$z1->cartesian};
      } else {
          ($re1, $im1) = [at]{$z1->cartesian};
          ($re2, $im2) = ref $z2 ? [at]{$z2->cartesian} : ($z2, 0);
      }
      if ($im2 == 0) {
          return CORE::atan2($re1, $re2) if $im1 == 0;
          return ($im1<=>0) * pip2 if $re2 == 0;
      }
      my $w = atan($z1/$z2); # !!! line 1284
      my ($u, $v) = ref $w ? [at]{$w->cartesian} : ($w, 0);
      $u += pi   if $re2 < 0;
      $u -= pit2 if $u > pi;
      return cplx($u, $v);
}

In the last test case above, $inverted is set. Therefore, if
$im2 = 0, the switched real and imaginary parts are used. But
if that's not the case, the code at line 1284 is executed with
the *unswitched* complex numbers $z1 and $z2.
I suppose the author omitted something like
($z1, $z2) = ($z2, $z1) if $inverted;
before line 1284. (The patch uses slightly different code.)

I attached a patch which adds another if($inverted){}else{}
block. It's a patch against the Math::Complex in 5.8.7, but I
have verified that the version in the bleadperl is the same.

I assume you want to add a test for any bugfix, but since I
know nothing about perl's internal testing (and Complex.t in
5.9.2 is as ugly as it gets), I'll just include the simplest bit
of code that tests the patch, provided Math::Complex was loaded:

($eps defined in Complex.t)

my $res;
eval {$res = atan2(0,i);};
print( ($@ or not abs($res) < $eps ) ?  'not ok' : 'ok' );

diff -u follows:

-----
--- Complex.pm  2005-04-01 11:43:02.000000000 +0200
+++ C:/perl/perl58/lib/Math/Complex.pm  2005-08-04 16:45:13.890625000 +0200
@@ -1281,7 +1281,13 @@
            return CORE::atan2($re1, $re2) if $im1 == 0;
            return ($im1<=>0) * pip2 if $re2 == 0;
        }
-       my $w = atan($z1/$z2);
+       my $w;
+        if ($inverted) {
+            $w = atan($z2/$z1);
+        }
+        else {
+            $w = atan($z1/$z2);
+        }
        my ($u, $v) = ref $w ? @{$w->cartesian} : ($w, 0);
        $u += pi   if $re2 < 0;
        $u -= pit2 if $u > pi;
-----

Steffen Mueller
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=medium
---
Site configuration information for perl v5.8.7:

Configured by builder at Mon Jun  6 13:36:05 2005.

Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
  Platform:
    osname=MSWin32, osvers=5.0, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cl', ccflags ='-nologo -Gf -W3 -MD -Zi -DNDEBUG -O1 -DWIN32
-D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DBUILT_BY_ACTIVESTATE
-DNO_HASH_SEED -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT
-DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX',
    optimize='-MD -Zi -DNDEBUG -O1',
    cppflags='-DWIN32'
    ccversion='12.00.8804', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf 
-libpath:"c:\perl\perl58\lib\CORE"  -machine:x86'
    libpth=\lib
    libs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib 
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib
odbc32.lib odbccp32.lib msvcrt.lib
    perllibs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib
 comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib
odbc32.lib odbccp32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=yes, libperl=perl58.lib
    gnulibc_version='undef'
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug
-opt:ref,icf  -libpath:"c:\perl\perl58\lib\CORE"  -machine:x86'

Locally applied patches:
    ACTIVEPERL_LOCAL_PATCHES_ENTRY
    #  if !defined(PERL_DARWIN)
    Iin_load_module moved for compatibility with build 806
    #  endif
    #  if defined(__hpux)
    Avoid signal flag SA_RESTART for older versions of HP-UX
    #  endif
    PerlEx hacks for CGI::Carp
    Less verbose ExtUtils::Install and Pod::Find
    instmodsh upgraded from ExtUtils-MakeMaker-6.25
    24699 ICMP_UNREACHABLE handling in Net::Ping
    21540 Fix backward-compatibility issues in if.pm

---
@INC for perl v5.8.7:
    c:/perl/perl58/lib
    c:/perl/perl58/site/lib
    .

---
Environment for perl v5.8.7:
    HOME (unset)
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    
PATH=D:\texmf\miktex\bin;c:\perl\perl58\bin;C:\cygwin\bin;C:\Tcl\bin;p:\util;p:\util\gnuplot\bin;p:\util\perltidy\bin;C:\WINNT\system32;C:\WINNT;C:\WINNT\system32\nls;C:\WINNT\system32\nls\ENGLISH;C:\Programme\Network
Associates\PGPNT;C:\Programme\Novell\ZENworks\;C:\Programme\Gemeinsame
Dateien\GTK\2.0\bin;p:\sdbdata;p:\sdbdata\sdbdata_win;c:\cygwin\usr\X11R6\bin
    PERL_BADLANG (unset)
    SHELL (unset)

Reply via email to