Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1076 → Rev 1077

/Delphi/akPi/Source/CalcUnit.pas
0,0 → 1,172
// akPi v2.2
// Copyright (c) 1997-98 Anatoli Klassen
 
unit CalcUnit;
 
interface
 
uses
Classes, Graphics, ExtCtrls, ComCtrls, LongIntegerUnit, Dialogs;
 
type
TCalc = class(TThread)
private
FRes : PChar;
FStatusBar : TStatusBar;
FNDigit : longint;
protected
procedure ShowProgress(R : real);
procedure Execute; override;
public
constructor Create(SB : TStatusBar; NDigit : longint; var Res : PChar);
end;
 
implementation
 
uses SysUtils;
 
procedure TCalc.ShowProgress(R : real);
begin
if R > 100 then R := 100;
FStatusBar.SimpleText := Format('%5.1f%s', [R, '% Done']);
end;
 
procedure TCalc.Execute;
const
NewLine = #13#10' ';
 
var
Pi, X1, X2, X3 : PLongInteger;
i, j, n, m, k1, k2 : longint;
All : real;
OldDecSeparator : char;
 
begin
OldDecSeparator := DecimalSeparator;
DecimalSeparator := '.';
 
NumDWord := Round((FNDigit + 40) / 2.3) div 4;
All := FNDigit * 1.47;
k1 := 0; k2 := 0;
 
GetMem(Pi, NumDWord * 4);
GetMem(X1, NumDWord * 4);
GetMem(X2, NumDWord * 4);
GetMem(X3, NumDWord * 4);
 
LetLong(X1^, 0);
LetLong(X2^, 1);
j := 0;
for i := 1 to FNDigit do begin
ShowProgress(i / All * 100);
if i = 1 then DivLongLim(X2^, 5, j)
else DivLongLim(X2^, 5*5, j);
 
MovLongLim(X2^, X3^, j);
DivLongLim(X3^, 2 * i - 1, j);
while (NumDWord - j div 4 - 1 > 0)
and (X2^[NumDWord - j div 4 - 1] = 0) do Inc(j, 4);
if NumDWord - j div 4 - 1 <= 0 then Break;
 
if i mod 2 = 1 then AddLongLim(X1^, X3^, j)
else SubLongLim(X1^, X3^, j);
 
if Terminated then begin
FreeMem(Pi, NumDWord * 4);
FreeMem(X1, NumDWord * 4);
FreeMem(X2, NumDWord * 4);
FreeMem(X3, NumDWord * 4);
Exit;
end;
k1 := i;
end;
MovLong(X1^, Pi^);
MulLong(Pi^, 16);
 
LetLong(X1^, 0);
LetLong(X2^, 1);
j := 0;
for i := 1 to FNDigit do begin
ShowProgress((i + k1) / All * 100);
if i = 1 then DivLongLim(X2^, 239, j)
else DivLongLim(X2^, 239*239, j);
 
MovLongLim(X2^, X3^, j);
DivLongLim(X3^, 2 * i - 1, j);
while (NumDWord - j div 4 - 1 > 0)
and (X2^[NumDWord - j div 4 - 1] = 0) do Inc(j, 4);
if NumDWord - j div 4 - 1 <= 0 then Break;
 
if i mod 2 = 1 then AddLongLim(X1^, X3^, j)
else SubLongLim(X1^, X3^, j);
 
if Terminated then begin
FreeMem(Pi, NumDWord * 4);
FreeMem(X1, NumDWord * 4);
FreeMem(X2, NumDWord * 4);
FreeMem(X3, NumDWord * 4);
Exit;
end;
k2 := i;
end;
MulLong(X1^, 4);
SubLong(Pi^, X1^);
 
i := NumDWord;
while (i > 0) and (Pi^[i] = 0) do Dec(i);
 
StrPCopy(FRes, IntToStr(Pi^[i]) + '.');
 
n := 0;
m := 2;
for j := FNDigit + i downto 1 do begin
ShowProgress((n/2 + k1 + k2) / All * 100);
if j <= 0 then Break;
 
Pi^[i] := 0;
MulLongLenLim(Pi^, 10, n div 3);
Inc(n, 1);
 
FRes[m] := Chr(Pi^[i] + Ord('0'));
Inc(m);
 
if n mod 50 = 0 then begin
Move(NewLine, FRes[m], 5);
Inc(m, 5);
end
else
if n mod 10 = 0 then begin
FRes[m] := ' ';
Inc(m);
end;
 
if (n + 2) > FNDigit then Break;
 
if Terminated then begin
FreeMem(Pi, NumDWord * 4);
FreeMem(X1, NumDWord * 4);
FreeMem(X2, NumDWord * 4);
FreeMem(X3, NumDWord * 4);
Exit;
end;
end;
FRes[m] := #0;
 
FreeMem(Pi, NumDWord * 4);
FreeMem(X1, NumDWord * 4);
FreeMem(X2, NumDWord * 4);
FreeMem(X3, NumDWord * 4);
 
DecimalSeparator := OldDecSeparator;
end;
 
constructor TCalc.Create;
begin
FStatusBar := SB;
FNDigit := NDigit + 1;
FRes := Res;
FreeOnTerminate := True;
inherited Create(False);
end;
 
end.