There are some good sources on-line to implement fast summation using binary splitting techniques. For example, Ch. 20, Jörg Arndt Book, (2004), Cheng et al. (2007) and papers from Haible and Papanikolaou (1997) and distributed with the CLN library source code. From this last article, the following notes apply to the evaluation of this kind of linearly convergent series (Type 1)
S = SUM(n=0,+oo,a(n)/b(n)*PROD(k=0,n,p(k)/q(k)))
where a(n), b(n), p(n), q(n) are integers with O(log N) bits. The most often used
case is that a(n), b(n), p(n), q(n) are polynomials in n with integer coefficients. Sum S is computed considering the following sequence of partial series with given two index bounds [n1, n2]
S(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n)*PROD(k=n1,n,p(k)/q(k))
S(n1,n2) are not computed directly. Instead, the product of integers
P = p(n1) ... p(n2-1)
Q = q(n1) ... q(n2−1)
B = b(n1) ... b(n2-1)
T = B Q S
are computed recursively by binary splitting until n2 - n1 < 5 when these are computed directly. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr belonging to the interval nm =< n < n2 and set these products and sums
P = Pl Pr
Q = Ql Qr,
B = Bl Br
T = Br Qr Tl + Bl Pl Tr
Finally, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and a final floating-point division
S = T/(B Q)
is performed.
The bit complexity of computing S with N bits of precision is O((log N)^2 M(N)) where M(N) is the bit complexity of the multiplication of two N-bit numbers.
A slightly modified but more complex series (Type 2) that is found in the last reference above can be also summed by binary splitting. It has an additional inner sum of rationals where c(n) and d(n) are integers with O(log N) bits
U = SUM(n=0,+oo,a(n)/b(n) * PROD(k=0,n,p(k)/q(k)) * SUM(m=0,n,c(m)/d(m)))
We consider these partial sums
U(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * SUM(m=n1,n,c(m)/d(m)))
The algorithm is a variation of the above as follows.
P = p(n1) ... p(n2-1)
Q = q(n1) ... q(n2−1)
B = b(n1) ... b(n2-1)
T = B Q S
D = d(n1) ... d(n2-1)
C = D (c(n1)/d(n1) + ... + c(n2-1)/d(n2-1))
V = D B Q U
If n2 - n1 =< 4 these values are computed directly. If n2 - n1 > 4 they are computed by binary splitting. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl, Dl, Cl, Vl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr, Dr, Cr, Vr belonging to the interval nm =< n < n2 and set these products and sums
P = Pl Pr
Q = Ql Qr
B = Bl Br
T = Br Qr Tl + Bl Pl Tr
D = Dl Dr
C = Cl Dr + Cr Dl
V = Dr Br Qr Vl + Dr Cl Bl Pl Tr + Dl Bl Pl Vr
At last, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and final floating point divisions are performed
S = T / (B Q)
V = U / (D B Q)
I have programmed both algorithms in Pari-GP and applied them to compute some mathematical constants using Chudnovsky's formula for Pi, this formula for Catalan Constant and more. (I have got more than 1000000 decimal digits in some cases under this platform). This code has been used to compute some difficult series as well.
I want to go one step ahead to accelerate some series by mixing binary splitting algorithm and levin-type sequence transformations. To do this I need to find the binary splitting relationships for a slight extension of these series.
W = SUM(n=0,+oo,a(n)/b(n) * PROD(k=0,n,p(k)/q(k)) * SUM(m=0,n,c(m)/d(m) * PROD(i=0,m,f(i)/g(i))))
It has has an additional product of rationals inside the inner sum where f(n) and g(n) are integers with O(log N) bits. These series are not hypergeometric but they are nested hypergeometric type sums. I think this algorithm might be derived from these partial series
W(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * SUM(m=n1,n,c(m)/d(m) * PROD(i=n1,m,f(i)/g(i))))
I would very much appreciate if someone can derive the product and sum steps to bin-split this type of series.
I will leave the PARI-GP code for computing fast linearly convergent series of type 1 and 2 as explained. Use ?sumbinsplit for help. There are some Testing examples for Type 2 series as well. You can un-comment one of them and use
precision(-log10(abs(sumbinsplit(~F)[1]/s-1)),ceil(log10(Digits())));
to check it.
\\ ANSI COLOR CODES
{
DGreen = Dg = "\e[0;32m";
Brown = Br = "\e[0;33m";
DCyan = Dc = "\e[0;36m";
Purple = Pr = "\e[0;35m";
Gray = Gy = "\e[0;37m";
Red = Rd = "\e[0;91m";
Green = Gr = "\e[0;92m";
Yellow = Yw = "\e[0;93m";
Blue = Bl = "\e[0;94m";
Magenta = Mg = "\e[0;95m";
Cyan = Cy = "\e[0;96m";
Reset = "\e[0m";
White = Wh = "\e[0;97m";
Black = Bk = "\e[0;30m";
}
eps()={ my(e=1.); while(e+1. != 1., e>>=1); e; }
addhelp(eps,Str(Yw,"\n SMALLEST REAL NUMBER\n",Wh,"\n eps() ",Gr,"returns the minimum positive real number for current precision"));
log10(x) = if(x==0,log(eps()),log(x))/log(10);
Digits(n) = if(type(n) == "t_INT" && n > 0,default(realprecision,n); precision(1.), precision(1.));
addhelp(Digits,Str(Yw,"\n DIGITS\n",Wh,"\n Digits(n)",Gr," Sets global precision to",Wh," n",Gr," decimal digits.",Wh," Digits()",Gr," returns current global precision."));
addhelp(BinSplit2,Str(Yw,"\n SERIES BINARY SPLITTING (TYPE 2)\n\n",Wh,"BinSplit(~F,n1,n2)",Gr," for ",Wh,"F = [a(n),b(n),p(n),q(n),c(n),d(n)]",Gr," a vector of ",Br,"t_CLOSUREs",Gr," whose\n components are typically polynomials, computes by binary splitting method sums of type\n\n",Wh,"S2 = sum(n=n1,n2-1,a(n)/b(n)*prod(k=n1,n,p(k)/q(k))*sum(m=n1,n,c(m)/d(m)))\n\n",Gr,"Output: ",Wh," [P,Q,B,T,D,C,V]",Gr," integer valued algorithm computing parameters"));
addhelp(BinSplit1,Str(Yw,"\n SERIES BINARY SPLITTING (TYPE 1)\n\n",Wh,"BinSplit(~F,n1,n2)",Gr," for ",Wh,"F = [a(n),b(n),p(n),q(n)]",Gr," a vector of ",Br,"t_CLOSUREs",Gr," whose components\n are typically polynomials, computes by binary splitting method sums of type\n\n",Wh,"S1 = sum(n=n1,n2-1,a(n)/b(n)*prod(k=n1,n,p(k)/q(k)))\n\n",Gr,"Output: ",Wh,"[P,Q,B,T]",Gr," integer valued algorithm computing parameters"));
BinSplit2(~F, n1, n2) =
{
my( P = 1, Q = 1, B = 1, T = 0, D = 1, C = 0, V = 0,
LP, LQ, LB, LT, LD, LC, LV, RP, RQ, RB, RT, RD, RC, RV,
nm, tmp1 = 1, tmp2, tmp3 );
\\
\\ F = [a(n),b(n),p(n),q(n),c(n),d(n)]
\\
if( n2 - n1 < 5,
\\
\\ then
\\
for ( j = n1, n2-1,
LP = F[3](j);
LQ = F[4](j);
LB = F[2](j);
LD = F[6](j);
LC = F[5](j);
\\
tmp2 = LB * LQ;
tmp3 = LP * F[1](j) * tmp1;
T = T * tmp2 + tmp3;
C = C * LD + D * LC;
V = V * tmp2 * LD + C * tmp3;
P *= LP;
Q *= LQ;
B *= LB;
D *= LD;
tmp1 *= LP * LB;
),
\\
\\ else
\\
nm = (n1 + n2) >> 1;
\\
[RP,RQ,RB,RT,RD,RC,RV] = BinSplit2(~F, nm, n2);
[LP,LQ,LB,LT,LD,LC,LV] = BinSplit2(~F, n1, nm);
\\
tmp1 = RB * RQ;
tmp2 = LB * LP;
tmp3 = LC * RD;
\\
P = LP * RP;
Q = RQ * LQ;
B = LB * RB;
T = LT * tmp1 + RT * tmp2;
D = LD * RD;
C = RC * LD + tmp3;
V = RD * LV * tmp1 + ( RT * tmp3 + LD * RV ) * tmp2;
\\
\\ end if
);
return([P,Q,B,T,D,C,V]);
}
BinSplit1(~F, n1, n2) =
{
my( P = 1, Q = 1, B = 1, T = 0,
LP, LQ, LB, LT, RP, RQ, RB, RT,
tmp1 = 1, nm );
\\
\\ F = [a(n),b(n),p(n),q(n)]
\\
if( n2 - n1 < 5,
\\
\\ then
\\
for ( j = n1, n2-1,
LP = F[3](j);
LQ = F[4](j);
LB = F[2](j);
\\
T = T * LB * LQ + LP * F[1](j) * tmp1;
P *= LP;
Q *= LQ;
B *= LB;
\\
tmp1 *= LP * LB;
),
\\
\\ else
\\
nm = (n1 + n2) >> 1;
\\
[RP,RQ,RB,RT] = BinSplit1(~F, nm, n2);
[LP,LQ,LB,LT] = BinSplit1(~F, n1, nm);
\\
P = LP * RP;
Q = RQ * LQ;
B = LB * RB;
T = LT * RB * RQ + RT * LB * LP;
\\
\\ end if
);
return([P,Q,B,T]);
}
sumbinsplit(~F, n1 = 1, dgs = getlocalprec()) =
{
my( n = #F, P, Q, B, T, D, C, V, [a,b] = F[3..4] );
my( n2 = 1 + ceil(dgs*log(10)/log(abs(pollead(Pol(b(x),x))/pollead(Pol(a(x),x))))) );
\\
if ( n > 4, [P, Q, B, T, D, C, V] = BinSplit2(~F,n1,n2); return(1.*([V/D,T]/B/Q)),\
[P, Q, B, T] = BinSplit1(~F,n1,n2); return(1.*(T/B/Q)));
}
addhelp(sumbinsplit,Str(Yw,"\n LINEARLY CONVERGENT SERIES BINARY SPLITTING SUMMATION\n\n",Wh,"sumbinsplit( ~F, {n1 = 1}, {dgs = getlocalprec()} )\n\n",Gr,"for either ",Wh,"F = [a(n),b(n),p(n),q(n)] ",Gr,"or",Wh," F = [a(n),b(n),p(n),q(n),c(n),d(n)]",Gr," vectors of ",Br,"t_CLOSUREs",Gr," whose\n components are typically polynomials. It computes sums of type 1 or type 2 by binary splitting method\n\n (See BinSplit1, BinSplit2 help)\n\n",Wh,"n1",Gr," starting index (default 1),",Wh," dgs",Gr," result's floating precision\n\n",Yw,"OUTPUT:",Gr," either",Wh," S1",Gr," series value (Type 1) or ",Wh," [S2, S1]",Gr," series values [Type 2, Type1]"));
/* TESTINGS */
/*
Digits(100000);
a = n->1;
b = n->n;
p = n->n*(n<<1-1);
q = n->3*(3*n-1)*(3*n-2);
c = n->1;
d = n->n*(n<<1-1)<<1;
s = log(2)*(3*log(2)+Pi/2)/10-Pi^2/60;
F = [a,b,p,q,c,d];
*/
/*
Digits(100000);
s = -Pi*Catalan/2+33/32*zeta(3)+log(2)*Pi^2/24;
F = [n->1,n->n^2,n->n*(n<<1-1),n->3*(3*n-1)*(3*n-2),n->1,n->n*(n<<1-1)<<1];
\\ precision(-log10(abs(sumbinsplit(~F)[1]/s-1)),ceil(log10(Digits())));
*/
/*
Digits(10000);
a = n->1;
b = n->n<<1+1;
p = n->n<<1-1;
q = n->n<<3;
c = n->1;
d = n->(n<<1-1)^2;
s = Pi^3/648;
F = [a,b,p,q,c,d];
*/
/*
Digits(10000);
a = n->-1;
b = n->n^3;
p = n->-n;
q = n->(n<<1-1)<<1;
c = n->20*n-9;
d = n->n*(n<<1-1)<<1;
s = 2*Pi^4/75;
F = [a,b,p,q,c,d];
*/
/*
Digits(10000);
a = n->2;
b = n->n^2;
p = n->n;
q = n->(n<<1-1);
c = n->1;
d = n->n<<1-1;
s = 7*zeta(3)-2*Pi*Catalan;
F = [a,b,p,q,c,d];
*/
/*
Digits(10000);
a = n->1;
b = n->n^4;
p = n->n;
q = n->(n<<1-1)<<1;
c = n->36*n-17;
d = n->n*(n<<1-1)<<1;
s = 14*zeta(5)/9+5/18*Pi^2*zeta(3);
F = [a,b,p,q,c,d];
*/
/*
Digits(10000);
a = n->1;
b = n->n^2;
p = n->n;
q = n->(n<<1-1)<<1;
c = n->12*n-5;
d = n->n*(n<<1-1)<<1;
s = 5*zeta(3)/3;
F = [a,b,p,q,c,d];
*/
Making a close analysis of the nested hypergeometric series W and partial sums W(n1,n2) I have found the binary splitting relationships,
Write the inner hypergeometric sum in W(n1,n2) as
Z(n1,n2) = SUM(m=n1,n2-1,c(m)/d(m) * PROD(i=n1,m,f(i)/g(i)))
we have
W(n1,n2) = = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * Z(n1,n+1))
The algorithm is a deeper variation of the previous one. We have now 8 polynomial functions a(n), b(n), p(n), q(n), c(n), d(n), f(n), g(n). Set these products and sums to be computed by binary splitting
P = p(n1) ... p(n2-1)
Q = q(n1) ... q(n2−1)
B = b(n1) ... b(n2-1)
T = B Q S
D = d(n1) ... d(n2-1)
F = f(n1) ... f(n2-1)
G = g(n1) ... g(n2-1)
C = D G Z
V = D B Q G W
If n2 - n1 =< 4 these values are computed directly. If n2 - n1 > 4 they are computed recursively by binary splitting. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl, Dl, Cl, Vl, Fl, Gl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr, Dr, Cr, Vr, Fr, Gr belonging to the interval nm =< n < n2 and set these products and sums
P = Pl Pr
Q = Ql Qr
B = Bl Br
T = Br Qr Tl + Bl Pl Tr
D = Dl Dr
F = Fl Fr
G = Gl Gr
C = Cl Dr Gr + Cr Dl Fl
V = Dr Br Qr Gr Vl + Dr Cl Bl Pl Gr Tr + Dl Bl Pl Fl Vr
Using auxiliary variables and factorizing, these 27 big integer products can be reduced to just 19. Finally, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and final floating point divisions are performed. Algorithm provides all 3 sums
S = T / (B Q)
Z = C / (D G)
W = V / (B Q D G)
I will code and test this algorithm to complement this answer. Many convergence acceleration methods (CAM) applied to some slowly convergent series have the structure of series W (for example, some classical CAMs like Salzer's, Gustavson's, sumalt() from Pari GP -Cohen, Rodriguez, Zagier-, Weniger's transformations and several Levin-type CAMs). I believe that the merge of BinSplit and Levin-type sequence transformations should provide a strong boost to this topic. We will see.