]> www.ginac.de Git - ginac.git/blobdiff - ginac/inifcns_trans.cpp
Really fixed the atan2(-Pi, 0) bug.
[ginac.git] / ginac / inifcns_trans.cpp
index 3f9c380b6dd51fe60708a275175f1831a63c1787..c8a0a8214ca7f276da625096c36899cdd1be9d78 100644 (file)
@@ -4,7 +4,7 @@
  *  functions. */
 
 /*
- *  GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2010 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -21,9 +21,6 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <vector>
-#include <stdexcept>
-
 #include "inifcns.h"
 #include "ex.h"
 #include "constant.h"
@@ -35,6 +32,9 @@
 #include "pseries.h"
 #include "utils.h"
 
+#include <stdexcept>
+#include <vector>
+
 namespace GiNaC {
 
 //////////
@@ -246,11 +246,15 @@ static ex log_series(const ex &arg,
 
 static ex log_real_part(const ex & x)
 {
+       if (x.info(info_flags::nonnegative))
+               return log(x).hold();
        return log(abs(x));
 }
 
 static ex log_imag_part(const ex & x)
 {
+       if (x.info(info_flags::nonnegative))
+               return 0;
        return atan2(GiNaC::imag_part(x), GiNaC::real_part(x));
 }
 
@@ -816,67 +820,68 @@ static ex atan2_evalf(const ex &y, const ex &x)
 
 static ex atan2_eval(const ex & y, const ex & x)
 {
-       if (y.info(info_flags::numeric) && x.info(info_flags::numeric)) {
+       if (y.is_zero()) {
 
-               if (y.is_zero()) {
+               // atan2(0, 0) -> 0
+               if (x.is_zero())
+                       return _ex0;
 
-                       // atan(0, 0) -> 0
-                       if (x.is_zero())
-                               return _ex0;
+               // atan2(0, x), x real and positive -> 0
+               if (x.info(info_flags::positive))
+                       return _ex0;
 
-                       // atan(0, x), x real and positive -> 0
-                       if (x.info(info_flags::positive))
-                               return _ex0;
+               // atan2(0, x), x real and negative -> Pi
+               if (x.info(info_flags::negative))
+                       return Pi;
+       }
 
-                       // atan(0, x), x real and negative -> -Pi
-                       if (x.info(info_flags::negative))
-                               return _ex_1*Pi;
-               }
+       if (x.is_zero()) {
 
-               if (x.is_zero()) {
+               // atan2(y, 0), y real and positive -> Pi/2
+               if (y.info(info_flags::positive))
+                       return _ex1_2*Pi;
 
-                       // atan(y, 0), y real and positive -> Pi/2
-                       if (y.info(info_flags::positive))
-                               return _ex1_2*Pi;
+               // atan2(y, 0), y real and negative -> -Pi/2
+               if (y.info(info_flags::negative))
+                       return _ex_1_2*Pi;
+       }
 
-                       // atan(y, 0), y real and negative -> -Pi/2
-                       if (y.info(info_flags::negative))
-                               return _ex_1_2*Pi;
-               }
+       if (y.is_equal(x)) {
 
-               if (y.is_equal(x)) {
+               // atan2(y, y), y real and positive -> Pi/4
+               if (y.info(info_flags::positive))
+                       return _ex1_4*Pi;
 
-                       // atan(y, y), y real and positive -> Pi/4
-                       if (y.info(info_flags::positive))
-                               return _ex1_4*Pi;
+               // atan2(y, y), y real and negative -> -3/4*Pi
+               if (y.info(info_flags::negative))
+                       return numeric(-3, 4)*Pi;
+       }
 
-                       // atan(y, y), y real and negative -> -3/4*Pi
-                       if (y.info(info_flags::negative))
-                               return numeric(-3, 4)*Pi;
-               }
+       if (y.is_equal(-x)) {
 
-               if (y.is_equal(-x)) {
+               // atan2(y, -y), y real and positive -> 3*Pi/4
+               if (y.info(info_flags::positive))
+                       return numeric(3, 4)*Pi;
 
-                       // atan(y, -y), y real and positive -> 3*Pi/4
-                       if (y.info(info_flags::positive))
-                               return numeric(3, 4)*Pi;
+               // atan2(y, -y), y real and negative -> -Pi/4
+               if (y.info(info_flags::negative))
+                       return _ex_1_4*Pi;
+       }
 
-                       // atan(y, -y), y real and negative -> -Pi/4
-                       if (y.info(info_flags::negative))
-                               return _ex_1_4*Pi;
-               }
+       // atan2(float, float) -> float
+       if (is_a<numeric>(y) && !y.info(info_flags::crational) &&
+           is_a<numeric>(x) && !x.info(info_flags::crational))
+               return atan(ex_to<numeric>(y), ex_to<numeric>(x));
 
-               // atan(float, float) -> float
-               if (!y.info(info_flags::crational) && !x.info(info_flags::crational))
-                       return atan(ex_to<numeric>(y), ex_to<numeric>(x));
+       // atan2(real, real) -> atan(y/x) +/- Pi
+       if (y.info(info_flags::real) && x.info(info_flags::real)) {
+               if (x.info(info_flags::positive))
+                       return atan(y/x);
 
-               // atan(real, real) -> atan(y/x) +/- Pi
-               if (y.info(info_flags::real) && x.info(info_flags::real)) {
-                       if (x.info(info_flags::positive))
-                               return atan(y/x);
-                       else if(y.info(info_flags::positive))
+               if (x.info(info_flags::negative)) {
+                       if (y.info(info_flags::positive))
                                return atan(y/x)+Pi;
-                       else
+                       if (y.info(info_flags::negative))
                                return atan(y/x)-Pi;
                }
        }
@@ -889,10 +894,10 @@ static ex atan2_deriv(const ex & y, const ex & x, unsigned deriv_param)
        GINAC_ASSERT(deriv_param<2);
        
        if (deriv_param==0) {
-               // d/dy atan(y,x)
+               // d/dy atan2(y,x)
                return x*power(power(x,_ex2)+power(y,_ex2),_ex_1);
        }
-       // d/dx atan(y,x)
+       // d/dx atan2(y,x)
        return -y*power(power(x,_ex2)+power(y,_ex2),_ex_1);
 }