]> www.ginac.de Git - ginac.git/blobdiff - ginac/inifcns_nstdsums.cpp
G_numeric: fix numeric evaluation with trailing zeros and y != 1.
[ginac.git] / ginac / inifcns_nstdsums.cpp
index c33a4cf8370d22020e302b0c08e1ade04f6a24f1..62c6c62f2737cf6b87a34db73bc51060103c1ff5 100644 (file)
@@ -1136,6 +1136,7 @@ G_numeric(const std::vector<cln::cl_N>& x, const std::vector<int>& s,
        // check for convergence and necessary accelerations
        bool need_trafo = false;
        bool need_hoelder = false;
+       bool have_trailing_zero = false;
        std::size_t depth = 0;
        for (std::size_t i = 0; i < x.size(); ++i) {
                if (!zerop(x[i])) {
@@ -1149,14 +1150,16 @@ G_numeric(const std::vector<cln::cl_N>& x, const std::vector<int>& s,
                                need_hoelder = true;
                }
        }
-       if (zerop(x[x.size() - 1]))
+       if (zerop(x[x.size() - 1])) {
+               have_trailing_zero = true;
                need_trafo = true;
+       }
 
        if (depth == 1 && x.size() == 2 && !need_trafo)
                return - Li_projection(2, y/x[1], cln::float_format(Digits));
        
        // do acceleration transformation (hoelder convolution [BBB])
-       if (need_hoelder)
+       if (need_hoelder && !have_trailing_zero)
                return G_do_hoelder(x, s, y);
        
        // convergence transformation
@@ -1577,7 +1580,17 @@ static ex Li_eval(const ex& m_, const ex& x_)
                                }
                        }
                        if (is_zeta) {
-                               return zeta(m_,x_);
+                               lst newx;
+                               for (lst::const_iterator itx = x.begin(); itx != x.end(); ++itx) {
+                                       GINAC_ASSERT((*itx == _ex1) || (*itx == _ex_1));
+                                       // XXX: 1 + 0.0*I is considered equal to 1. However
+                                       // the former is a not automatically converted
+                                       // to a real number. Do the conversion explicitly
+                                       // to avoid the "numeric::operator>(): complex inequality"
+                                       // exception (and similar problems).
+                                       newx.append(*itx != _ex_1 ? _ex1 : _ex_1);
+                               }
+                               return zeta(m_, newx);
                        }
                        if (is_H) {
                                ex prefactor;
@@ -2044,7 +2057,9 @@ const cln::cl_N S_num(int n, int p, const cln::cl_N& x)
                prec = cln::float_format(cln::the<cln::cl_F>(cln::imagpart(value)));
 
        // [Kol] (5.3)
-       if ((cln::realpart(value) < -0.5) || (n == 0) || ((cln::abs(value) <= 1) && (cln::abs(value) > 0.95))) {
+       // the condition abs(1-value)>1 avoids an infinite recursion in the region abs(value)<=1 && abs(value)>0.95 && abs(1-value)<=1 && abs(1-value)>0.95
+       // we don't care here about abs(value)<1 && real(value)>0.5, this will be taken care of in S_projection
+       if ((cln::realpart(value) < -0.5) || (n == 0) || ((cln::abs(value) <= 1) && (cln::abs(value) > 0.95) && (cln::abs(1-value) > 1) )) {
 
                cln::cl_N result = cln::expt(cln::cl_I(-1),p) * cln::expt(cln::log(value),n)
                                   * cln::expt(cln::log(1-value),p) / cln::factorial(n) / cln::factorial(p);
@@ -2085,6 +2100,16 @@ const cln::cl_N S_num(int n, int p, const cln::cl_N& x)
 
                return result;
        }
+
+       if ((cln::abs(value) > 0.95) && (cln::abs(value-9.53) < 9.47)) {
+               lst m;
+               m.append(n+1);
+               for (int s=0; s<p-1; s++)
+                       m.append(1);
+
+               ex res = H(m,numeric(value)).evalf();
+               return ex_to<numeric>(res).to_cl_N();
+       }
        else {
                return S_projection(n, p, value, prec);
        }
@@ -2482,7 +2507,12 @@ lst convert_parameter_Li_to_H(const lst& m, const lst& x, ex& pf)
        res.append(*itm);
        itm++;
        while (itx != x.end()) {
-               signum *= (*itx > 0) ? 1 : -1;
+               GINAC_ASSERT((*itx == _ex1) || (*itx == _ex_1));
+               // XXX: 1 + 0.0*I is considered equal to 1. However the former
+               // is not automatically converted to a real number.
+               // Do the conversion explicitly to avoid the
+               // "numeric::operator>(): complex inequality" exception.
+               signum *= (*itx != _ex_1) ? 1 : -1;
                pf *= signum;
                res.append((*itm) * signum);
                itm++;
@@ -3230,7 +3260,7 @@ static ex H_evalf(const ex& x1, const ex& x2)
                // x -> 1/x
                if (cln::abs(x) >= 2.0) {
                        map_trafo_H_1overx trafo;
-                       res *= trafo(H(m, xtemp));
+                       res *= trafo(H(m, xtemp).hold());
                        if (cln::imagpart(x) <= 0) {
                                res = res.subs(H_polesign == -I*Pi);
                        } else {
@@ -3245,7 +3275,7 @@ static ex H_evalf(const ex& x1, const ex& x2)
                if (cln::abs(x-9.53) <= 9.47) {
                        // x -> (1-x)/(1+x)
                        map_trafo_H_1mxt1px trafo;
-                       res *= trafo(H(m, xtemp));
+                       res *= trafo(H(m, xtemp).hold());
                } else {
                        // x -> 1-x
                        if (has_minus_one) {
@@ -3253,7 +3283,7 @@ static ex H_evalf(const ex& x1, const ex& x2)
                                return filter(H(m, numeric(x)).hold()).evalf();
                        }
                        map_trafo_H_1mx trafo;
-                       res *= trafo(H(m, xtemp));
+                       res *= trafo(H(m, xtemp).hold());
                }
 
                return res.subs(xtemp == numeric(x)).evalf();