]> www.ginac.de Git - cln.git/blobdiff - src/float/transcendental/cl_LF_ratseries_qb.cc
Fix linking problems on some platforms caused by inline/non-inline versions
[cln.git] / src / float / transcendental / cl_LF_ratseries_qb.cc
index c006f09ac16febbf7921cc936e969550d7d1fadf..10c79f9dab292224459f54c1eab1b7e8a4072950 100644 (file)
@@ -1,4 +1,4 @@
-// eval_rational_series().
+// eval_rational_series<bool>().
 
 // General includes.
 #include "cl_sysdep.h"
@@ -82,7 +82,8 @@ static void eval_qb_series_aux (uintC N1, uintC N2,
        }
 }
 
-const cl_LF eval_rational_series (uintC N, const cl_qb_series& args, uintC len)
+template<>
+const cl_LF eval_rational_series<false> (uintC N, const cl_qb_series& args, uintC len)
 {
        if (N==0)
                return cl_I_to_LF(0,len);
@@ -90,6 +91,83 @@ const cl_LF eval_rational_series (uintC N, const cl_qb_series& args, uintC len)
        eval_qb_series_aux(0,N,args,&Q,&B,&T);
        return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len);
 }
+
+static void eval_qb_series_aux (uintC N1, uintC N2,
+                                cl_qb_series_stream& args,
+                                cl_I* Q, cl_I* B, cl_I* T)
+{
+       switch (N2 - N1) {
+       case 0:
+               throw runtime_exception(); break;
+       case 1: {
+               var cl_qb_series_term v0 = args.next(); // [N1]
+               *Q = v0.q;
+               *B = v0.b;
+               *T = 1;
+               break;
+               }
+       case 2: {
+               var cl_qb_series_term v0 = args.next(); // [N1]
+               var cl_qb_series_term v1 = args.next(); // [N1+1]
+               *Q = v0.q * v1.q;
+               *B = v0.b * v1.b;
+               *T = v1.b * v1.q + v0.b;
+               break;
+               }
+       case 3: {
+               var cl_qb_series_term v0 = args.next(); // [N1]
+               var cl_qb_series_term v1 = args.next(); // [N1+1]
+               var cl_qb_series_term v2 = args.next(); // [N1+2]
+               var cl_I q12 = v1.q * v2.q;
+               *Q = v0.q * q12;
+               var cl_I b12 = v1.b * v2.b;
+               *B = v0.b * b12;
+               *T = b12 * q12 + v0.b * (v2.b * v2.q + v1.b);
+               break;
+               }
+       case 4: {
+               var cl_qb_series_term v0 = args.next(); // [N1]
+               var cl_qb_series_term v1 = args.next(); // [N1+1]
+               var cl_qb_series_term v2 = args.next(); // [N1+2]
+               var cl_qb_series_term v3 = args.next(); // [N1+3]
+               var cl_I q23 = v2.q * v3.q;
+               var cl_I q123 = v1.q * q23;
+               *Q = v0.q * q123;
+               var cl_I b01 = v0.b * v1.b;
+               var cl_I b23 = v2.b * v3.b;
+               *B = b01 * b23;
+               *T = b23 * (v1.b * q123 + v0.b * q23)
+                  + b01 * (v3.b * v3.q + v2.b);
+               break;
+               }
+       default: {
+               var uintC Nm = (N1+N2)/2; // midpoint
+               // Compute left part.
+               var cl_I LQ, LB, LT;
+               eval_qb_series_aux(N1,Nm,args,&LQ,&LB,&LT);
+               // Compute right part.
+               var cl_I RQ, RB, RT;
+               eval_qb_series_aux(Nm,N2,args,&RQ,&RB,&RT);
+               // Put together partial results.
+               *Q = LQ*RQ;
+               *B = LB*RB;
+               // S = LS + 1/LQ * RS, so T = RB*RQ*LT + LB*RT.
+               *T = RB*RQ*LT + LB*RT;
+               break;
+               }
+       }
+}
+
+template<>
+const cl_LF eval_rational_series<false> (uintC N, cl_qb_series_stream& args, uintC len)
+{
+       if (N==0)
+               return cl_I_to_LF(0,len);
+       var cl_I Q, B, T;
+       eval_qb_series_aux(0,N,args,&Q,&B,&T);
+       return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len);
+}
+
 // Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))):
 // O(log(N)^2*M(N)).