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:08:54 +0000 (23:08 +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 3f161d218c068e2a4d016fce5d5cfcb2d32f789e..c8a0a8214ca7f276da625096c36899cdd1be9d78 100644 (file)
@@ -822,65 +822,68 @@ static ex atan2_eval(const ex & y, const ex & x)
 {
        if (y.is_zero()) {
 
 {
        if (y.is_zero()) {
 
-               // atan(0, 0) -> 0
+               // atan2(0, 0) -> 0
                if (x.is_zero())
                        return _ex0;
 
                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;
 
                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()) {
 
                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;
 
                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)) {
 
                        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;
 
                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)) {
 
                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;
 
                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;
        }
 
                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));
 
        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);
        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();
        }
 
        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) {
        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);
        }
                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);
 }
 
        return -y*power(power(x,_ex2)+power(y,_ex2),_ex_1);
 }