Really fixed the atan2(-Pi, 0) bug.
authorRichard Kreckel <kreckel@ginac.de>
Thu, 25 Mar 2010 22:08:54 +0000 (23:08 +0100)
committerRichard Kreckel <kreckel@ginac.de>
Thu, 25 Mar 2010 22:16:35 +0000 (23:16 +0100)
The problem was that atan2_eval assumed that if y is real and not
positive, it must be negative. But this neglects the fact that in
symbolic compution it may just not be possible to determine the
sign. Now, the expression is returned as it is. Ugly, but correct.

ginac/inifcns_trans.cpp

index 3f161d2..c8a0a82 100644 (file)
@@ -822,65 +822,68 @@ static ex atan2_eval(const ex & y, const ex & x)
 {
        if (y.is_zero()) {
 
-               // atan(0, 0) -> 0
+               // atan2(0, 0) -> 0
                if (x.is_zero())
                        return _ex0;
 
-               // atan(0, x), x real and positive -> 0
+               // atan2(0, x), x real and positive -> 0
                if (x.info(info_flags::positive))
                        return _ex0;
 
-               // atan(0, x), x real and negative -> Pi
+               // atan2(0, x), x real and negative -> Pi
                if (x.info(info_flags::negative))
                        return Pi;
        }
 
        if (x.is_zero()) {
 
-               // atan(y, 0), y real and positive -> Pi/2
+               // 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 negative -> -Pi/2
-               if (y.info(info_flags::real) && !y.is_zero())
+               // atan2(y, 0), y real and negative -> -Pi/2
+               if (y.info(info_flags::negative))
                        return _ex_1_2*Pi;
        }
 
        if (y.is_equal(x)) {
 
-               // atan(y, y), y real and positive -> Pi/4
+               // 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 negative -> -3/4*Pi
+               // atan2(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)) {
 
-               // atan(y, -y), y real and positive -> 3*Pi/4
+               // 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 negative -> -Pi/4
+               // atan2(y, -y), y real and negative -> -Pi/4
                if (y.info(info_flags::negative))
                        return _ex_1_4*Pi;
        }
 
-       // atan(float, float) -> float
+       // 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(real, real) -> atan(y/x) +/- Pi
+       // 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);
-               else if (y.info(info_flags::positive))
-                       return atan(y/x)+Pi;
-               else
-                       return atan(y/x)-Pi;
+
+               if (x.info(info_flags::negative)) {
+                       if (y.info(info_flags::positive))
+                               return atan(y/x)+Pi;
+                       if (y.info(info_flags::negative))
+                               return atan(y/x)-Pi;
+               }
        }
 
        return atan2(y, x).hold();
@@ -891,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);
 }