%mathpiper,def="CatalanConstNum"

//Jonathan Leto

/////////////////////////////////////////////////
/// Catalan's constant, various algorithms for comparison. (SW)
/////////////////////////////////////////////////

/* Brent-Fee's method based on Ramanujan's identity and Brent's trick.
 * Geometric convergence as 2^(-n). */
CatalanConstNum1() :=
[
  Local(prec,Aterm,Bterm,nterms,result,n);
  prec:=BuiltinPrecisionGet();
	BuiltinPrecisionSet(10);
	// estimate the number of terms from above
	nterms := 1+Floor(N((prec*Ln(10)+Ln(prec*Ln(10)/Ln(2)))/Ln(2)));
  BuiltinPrecisionSet(prec+5);
	Aterm:=N(1/2);
  result:= Aterm;
  Bterm:=Aterm;
  For(n:=1, n<=nterms, n++ )
	[
/*
    Bterm := MultiplyNum(Bterm, n/(2*n+1));
    Aterm:= DivideN(MultiplyNum(Aterm,n)+Bterm, 2*n+1);
/* this is faster: */
    Bterm:=DivideN(MultiplyN(Bterm,n), 2*n+1); // Bterm = (k!)^2*2^(k-1)/(2*k+1)!
    Aterm:=DivideN(MultiplyN(Aterm,n)+Bterm, 2*n+1); // Aterm = Bterm * Sum(k,0,n,1/(2*k+1))
/**/
    result := result + Aterm;
  ];
  BuiltinPrecisionSet(prec);
  RoundTo(result,prec);
];

/* Bailey 1997's method.
 * Geometric convergence as 4^(-n). */

CatalanConstNum() :=
[
	Local(prec, n, result);
	prec:=BuiltinPrecisionGet();

	// number of terms
	n := 1+Quotient(prec*1068+642,643); // prec*Ln(10)/Ln(4)
	BuiltinPrecisionSet(prec+2);	// 2 guard digits

	result := N(1/(2*n+1));
	While(n>0)
	[
/*
		result := MultiplyNum(result, n/(4*n+2))+N(1/(2*n-1));
/* this is faster: */
		result := DivideN(MultiplyN(result, n), 4*n+2)+DivideN(1,2*n-1);
/**/
		n := n-1;
	];
	result := MultiplyNum(result, 3/8) + N(Pi/8*Ln(2+Sqrt(3)));
	BuiltinPrecisionSet(prec);
	RoundTo(result,prec);
];

/* Broadhurst's series.
 * Geometric convergence as 16^(-n). */

CatalanConstNum2() :=
[
	Local(prec, n, result1, result2);
	prec:=BuiltinPrecisionGet();

	// first series
	// number of terms
	n := 1+Quotient(prec*534+642,643); // prec*Ln(10)/Ln(16)
	BuiltinPrecisionSet(prec+2);	// 2 guard digits

	result1 := 0;
	While(n>=0)
	[
		result1 := DivideN(result1, 16)+N(
			+1/(8*n+1)^2 -1/(8*n+2)^2 +1/2/(8*n+3)^2 -1/4/(8*n+5)^2 +1/4/(8*n+6)^2 -1/8/(8*n+7)^2
		);
		n := n-1;
	];

	// second series
	// number of terms
	n := 1+Quotient(prec*178+642,643); // prec*Ln(10)/Ln(4096)
	BuiltinPrecisionSet(prec+2);	// 2 guard digits

	result2 := 0;
	While(n>=0)
	[
		result2 := DivideN(result2, 4096)+N(
			+1/(8*n+1)^2 +1/2/(8*n+2)^2 +1/8/(8*n+3)^2 -1/64/(8*n+5)^2 -1/128/(8*n+6)^2 -1/512/(8*n+7)^2
		);
		n := n-1;
	];
	result1 := MultiplyNum(result1, 3/2) - MultiplyNum(result2, 1/4);
	BuiltinPrecisionSet(prec);
	RoundTo(result1,prec);
];

%/mathpiper