https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68397

            Bug ID: 68397
           Summary: std::tr1::expint fails in __expint_En_cont_frac for
                    some long double arguments due to low __max_iter value
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: trivial
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: uquendo at gmail dot com
  Target Milestone: ---

Created attachment 36746
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36746&action=edit
patch increasing __max_iter in __expint_En_cont_frac @
libstdc++-v3/include/tr1/exp_integral.tcc

Continued fractions for the exponential integral E_n(x) fail to converge in
std::tr1::expintl ( std::tr1::expint(long double) ) for some long double
arguments in the interval [1.0;1.4] due to low std::numeric_limits<long
double>::epsilon().

Raising in [gcc.git]/libstdc++-v3/include/tr1/exp_integral.tcc __max_iter value
in  __expint_En_series(unsigned int __n, _Tp __x) function from 100 to 1000
resolves the issue, patch is attached.

minimal test for reproducing this bug follows:

__________________________________________________

#include <iostream>
#include <stdexcept>
#include <tr1/cmath>

int main(int argc, char* argv[]){
  std::cout.precision(10);
  for(long double x=-1.600001L; x<-0.9L; x+=0.05L){
    try{
      std::cout << "std::tr1::expint(" << x << ")= " << std::tr1::expint(x) <<
std::endl;
    } catch (std::exception& e){
      std::cerr << "std::tr1::expint(" << x << ") failed with error: " <<
e.what() << std::endl;
    }
  }
  return 0;
}

__________________________________________________

compiling with g++ -O0 test.cpp and running, i've got:
std::tr1::expint(-1.600001)= -0.08630820751
std::tr1::expint(-1.550001)= -0.09288197123
std::tr1::expint(-1.500001)= -0.1000194337
std::tr1::expint(-1.45) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.4) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.35) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.3) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.25) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.2) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.15) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.1) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1.05) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-1) failed with error: Continued fraction failed in
__expint_En_cont_frac.
std::tr1::expint(-0.950001)= -0.2387371166
std::tr1::expint(-0.900001)= -0.2601834876


after changing argument to double or raising __max_iter as mentioned above,
i've been able to obtain expected results:
std::tr1::expint(-1.600001)= -0.08630820751
std::tr1::expint(-1.550001)= -0.09288197123
std::tr1::expint(-1.500001)= -0.1000194337
std::tr1::expint(-1.450001)= -0.1077772781
std::tr1::expint(-1.400001)= -0.1162191364
std::tr1::expint(-1.350001)= -0.1254166524
std::tr1::expint(-1.300001)= -0.1354507482
std::tr1::expint(-1.250001)= -0.1464131433
std::tr1::expint(-1.200001)= -0.1584081859
std::tr1::expint(-1.150001)= -0.1715550783
std::tr1::expint(-1.100001)= -0.1859906019
std::tr1::expint(-1.050001)= -0.2018724799
std::tr1::expint(-1.000001)= -0.2193835665
std::tr1::expint(-0.950001)= -0.2387371166
std::tr1::expint(-0.900001)= -0.2601834876

Reply via email to