]> www.ginac.de Git - cln.git/blob - src/float/transcendental/cl_LF_exp_aux.cc
Cater to the fact that g++ 4.3 will use a different naming for
[cln.git] / src / float / transcendental / cl_LF_exp_aux.cc
1 // cl_exp_aux().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_F_tran.h"
8
9
10 // Implementation.
11
12 #include "cln/lfloat.h"
13 #include "cl_LF_tran.h"
14 #include "cl_LF.h"
15 #include "cln/integer.h"
16 #include "cl_alloca.h"
17 #include "cln/exception.h"
18
19 #undef floor
20 #include <cmath>
21 #define floor cln_floor
22
23 namespace cln {
24
25 const cl_LF cl_exp_aux (const cl_I& p, uintE lq, uintC len)
26 {
27  {      Mutable(cl_I,p);
28         var uintE lp = integer_length(p); // now |p| < 2^lp.
29         if (!(lp <= lq)) throw runtime_exception();
30         lp = lq - lp; // now |p/2^lq| < 2^-lp.
31         // Minimize lq (saves computation time).
32         {
33                 var uintC lp2 = ord2(p);
34                 if (lp2 > 0) {
35                         p = p >> lp2;
36                         lq = lq - lp2;
37                 }
38         }
39         // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n)))
40         // with appropriate N, and
41         //   a(n) = 1, b(n) = 1, p(n) = p for n>0, q(n) = n*2^lq for n>0.
42         var uintC actuallen = len+1; // 1 Schutz-Digit
43         // How many terms to we need for M bits of precision? N terms suffice,
44         // provided that
45         //   1/(2^(N*lp)*N!) < 2^-M
46         // <==   N*(log(N)-1)+N*lp*log(2) > M*log(2)
47         // First approximation:
48         //   N0 = M will suffice, so put N<=N0.
49         // Second approximation:
50         //   N1 = floor(M*log(2)/(log(N0)-1+lp*log(2))), slightly too small,
51         //   so put N>=N1.
52         // Third approximation:
53         //   N2 = ceiling(M*log(2)/(log(N1)-1+lp*log(2))), slightly too large.
54         //   N = N2+2, two more terms for safety.
55         var uintC N0 = intDsize*actuallen;
56         var uintC N1 = (uintC)(0.693147*intDsize*actuallen/(::log((double)N0)-1.0+0.693148*lp));
57         var uintC N2 = (uintC)(0.693148*intDsize*actuallen/(::log((double)N1)-1.0+0.693147*lp))+1;
58         var uintC N = N2+2;
59         CL_ALLOCA_STACK;
60         var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I));
61         var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I));
62         var uintC* qsv = (uintC*) cl_alloca(N*sizeof(uintC));
63         var uintC n;
64         init1(cl_I, pv[0]) (1);
65         init1(cl_I, qv[0]) (1);
66         for (n = 1; n < N; n++) {
67                 init1(cl_I, pv[n]) (p);
68                 init1(cl_I, qv[n]) ((cl_I)n << lq);
69         }
70         var cl_pq_series series;
71         series.pv = pv; series.qv = qv; series.qsv = qsv;
72         var cl_LF fsum = eval_rational_series(N,series,actuallen);
73         for (n = 0; n < N; n++) {
74                 pv[n].~cl_I();
75                 qv[n].~cl_I();
76         }
77         return shorten(fsum,len); // verkürzen und fertig
78 }}
79 // Bit complexity (N = len, and if p has length O(log N) and ql = O(log N)):
80 // O(log(N)*M(N)).
81
82 }  // namespace cln