最速の素数判定アルゴリズム  

このエントリーをはてなブックマークに追加
175デフォルトの名無しさん
function LucasTest(n:int64):boolean;
var dt,odt:array of Word;
var cy:int64;
var i,hDt,hPg:integer;
var mask:LongWord;

 procedure mul2; //2乗する処理
 var w1,w2:array of Word;
 var wk:LongWord;
 var i,j:integer;
 begin
 SetLength(w1,1+hDt );//メモリを確保して
  SetLength(w2,1+1+hDt );
   cy:=0;
  for i:=0 to  hDt do  begin
   for j:=0 to i do cy:=cy+dt[j]*dt[i-j];
    w1[i]:=cy;//下位桁だけを代入
    cy:=cy shr 16;
  end;
  for i:=1 to  hDt do  begin
   for j:=i to hDt do cy:=cy+dt[j]*dt[hDt+i-j];
    w2[i-1]:=cy;//
    cy:=cy shr 16;
  end;
  w2[hDt ]:=cy; cy:=cy shr 16;
  w2[hDt+1]:=cy; cy:=0;
   wk:=(w2[0] shl (16- hPg)) and $ffff;
   cy:=cy+ wk +w1[0];
   dt[0]:=cy;//下位桁だけを代入
   cy:=cy shr 16;
  for i:=1 to  hDt do begin //上位を下位に加算する
   wk:=(((w2[i] shl 16)+w2[i-1])shr hPg) and $ffff;
   cy:=cy+ wk +w1[i];
   dt[i]:=cy;//下位桁だけを代入
   cy:=cy shr 16;
  end;
   wk:=((w2[hDt+1] shl 16)+w2[hDt])shr hPg ;
  cy:=wk+(( (cy shl 16) +dt[hDt]) shr hPg);
  while cy >0 do begin
   dt[hDt]:=dt[hDt] and mask;
   for i:=0 to  hDt do begin //さらに溢れた上位を加算する
        cy:=cy+dt[i];
     dt[i]:=cy;//下位桁だけを代入
     cy:=cy shr 16;
   end;
  cy:=( (cy shl 16)+ dt[hDt] ) shr hPg;
  end;
 end;

----- つづく ----
176デフォルトの名無しさん:2001/06/30(土) 18:17
var fsame,fzero:boolean;
var Rep:int64;
begin
hDt:=((n-1) div 16);//最大桁位置
hPg:= ((n-1) mod 16)+1 ;//ビット位置
mask:=(1 shl hPg)-1;
SetLength(dt,1+hDt );//メモリを確保して
for i:=0 to High(dt) do dt[i]:=0; dt[0]:=4; //初期値を4に
rep:=n;
while rep>0 do begin
 odt:=copy(dt,0,hdt+1);
 mul2; //2乗する
 fsame:=     dt[0]=odt[0];
 fzero:=true;
 for i:=1 to High(dt) do begin
   fsame:=fsame and (dt[i]=odt[i]);//全て同じかチェック
   fzero:=fzero and (dt[i]=0); //全て同じかチェック
   if (not fsame) and (not fzero) then break;
 end;
 if fsame then begin Result:=false;exit;end;//もはや見込みなし
 cy:=-2;
 if fzero then
 begin
   if dt[0] =2 then begin Result:=True;exit;end;//オメデトウ
   if dt[0] <2 then begin //2以下なら負数になるから
   for i:=1 to High(dt) do dt[i]:=$ffff;//全部が1は0と同じ
    dt[hDt]:=mask;
    dt[0]:=$ffff+dt[0]-2;cy:=0; //で引算する
   end;
  end;
  for i:=0 to  hDt do begin //2を引く処理
    cy:=cy+dt[i];
    dt[i]:=cy;//下位桁だけを代入
    cy:=(cy-dt[i]) div $10000;
    if cy=0 then break;
   end;
 Dec(rep);
 end;
Result:=false;
end;