{$mode objfpc}
{$MODESWITCH NESTEDCOMMENTS+}
{$warn 6058 off}
{$warn 5025 off}
program speed_test;
uses sysutils
, strutils
, strings
, math
, Multi_Int
;
const prec = 50; // digits of precision
var
c3_over_24, temp : Multi_Int_XV;
big_int_size,
start_time,
end_time :int32;
delta :double;
t, pi :Multi_Int_XV;
n:UInt32;
procedure bs(a : uint32; b : uint32; var pab : Multi_Int_XV; var qab : Multi_Int_XV; var tab_ : Multi_Int_XV);
(*
computes the terms for binary splitting the chudnovsky infinite series
a(a) = +/- (13591409 + 545140134*a)
p(a) = (6*a-5)*(2*a-1)*(6*a-1)
b(a) = 1
q(a) = a*a*a*c3_over_24
returns p(a,b), q(a,b) and t(a,b) *)
var
m, t : uint32;
pam, qam, tam, pmb, qmb, tmb : Multi_Int_XV;
begin
if (b - a) = 1 then
begin
// directly compute p(a,a+1), q(a,a+1) and t(a,a+1)
if a = 0 then
begin
pab := 1;
qab := 1;
end
else
begin
t:=6*a;
pab := t-1;
pab := pab*(a+a-1);
pab := pab*(t-5);
temp := a;
qab := temp*temp;
qab := qab*temp;
qab := qab*c3_over_24;
end;
tab_ := 545140134;
tab_ := tab_*a;
tab_ := tab_+13591409;
tab_ := tab_*pab; // a(a) * p(a)
if odd(a) then tab_ := tab_*(-1); // = -tab
end
else
begin
// recursively compute p(a,b), q(a,b) and t(a,b)
// m is the midpoint of a and b
m := (a + b) div 2;
// recursively calculate p(a,m), q(a,m) and t(a,m)
bs(a, m, pam, qam, tam);
// recursively calculate p(m,b), q(m,b) and t(m,b)
bs(m, b, pmb, qmb, tmb);
// now combine
pab := pam*pmb;
qab := qam*qmb;
temp := qmb*tam;
tab_ := pam*tmb;
tab_ := tab_+temp;
end;
end;
procedure pi_chudnovsky(var pi : Multi_Int_XV; digits : uint32);
(*
compute int(pi * 10**digits)
this is done using chudnovsky's series with binary splitting
*)
var
one_squared, p, q, sqrtc, t : Multi_Int_XV;
n : uint32;
digits_per_term : double;
// how many terms to compute
begin
//digits_per_term := c3_over_24;
digits_per_term := 14.18164746272548; //Ln(digits_per_term/6/2/6)*0.4342944819032518;
n := round(digits/digits_per_term + 1);
// calclate p(0,n) and q(0,n)
bs(0, n, p, q, t);
one_squared := 10;
one_squared := one_squared**(2*digits);
sqrtc := one_squared*10005;
sqrtc := SqRoot(sqrtc);
pi := sqrtc*426880;
pi := pi*q;
pi := pi div t;
End;
begin
big_int_size:= 3 *ceil( prec / (32*0.3010299956639812));
Multi_Int_Set_XV_Limit(big_int_size); // don't know whether it's needed or not
Multi_Int_Initialisation(big_int_size);
start_time:= GetTickCount64;
c3_over_24 := 640320;
temp := c3_over_24*c3_over_24;
c3_over_24 := temp*c3_over_24;
c3_over_24 := c3_over_24 div 24;
pi_chudnovsky(pi, prec);
end_time:= GetTickCount64;
writeln;
writeln('Trunc(Pi * 10**' + IntToStr(prec) + ')');
writeln(pi.ToStr);
delta:= (end_time - start_time) / 1000;
writeln('time elapsed is ', delta:1:6, ' seconds');
end.