Professional Documents
Culture Documents
Math Lib
Math Lib
interface
type
intset = set of byte;
TPoint64=record
x,y:int64;
end;
type
TPrimes = class(TObject)
protected
function BSPrime(const n: int64; var index: integer): boolean;
public
Prime: array of int64; {Array of primes - 0th entry is not used}
nbrprimes, nbrfactors, nbrcanonicalfactors, nbrdivisors: integer;
Factors: array of int64; {array of factors - 0th entry is not used}
CanonicalFactors: array of TPoint64;
Divisors: array of int64;
function GetNextPrime(n: int64): int64;
function GetPrevPrime(n: int64): int64;
function IsPrime(n: int64): boolean;
procedure GetFactors(const n: int64); {get all prime factors}
function MaxPrimeInTable: int64;
function GetNthPrime(const n: integer): int64;
procedure GetCanonicalFactors(const n: int64); {get ccanonical prime factors}
procedure GetDivisors(const n: int64); {get all divisors}
function Getnbrdivisors(n: int64): integer;
var
Primes: TPrimes;
maxprimes: integer = 50000; {initial size of primes array}
maxfactors: integer = 200; {initial size of factors array}
maxval: int64 = 1000000000000;
{10^12 - 10^6 is max prime to be tested from tables}
{primes up to the sqrt of maxval will be tabled}
continuants: array of int64;
maxcontinuant: integer;
implementation
uses Math;
var
nbrdiv: int64;
var
i: integer;
{m:integer;}
g: integer;
begin
{ result:=0; }
(*
m:=minintvalue(a);
g:=gcd2(m,a[0]);
For i := 1 to length(a)-1 do g:=min(gcd2(m,a[i]),g);
*)
g := a[0];
if length(a) >= 2 then
begin
g := gcd2(g, a[1]);
if length(a) > 2 then
for i := 2 to length(a) - 1 do
g := gcd2(g, a[i]);
end;
Result := g;
end;
{************** GetNextPandigital}
function GetNextPandigital(size: integer; var Digits: array of integer): boolean;
{Generates 9 or 10 digit permutations of digits in decreasing sequence,
Input parameter "size" is the number of digits to generate (2 to 10).
Output placed in open array "digits", so index value of k refers
to (k+1)th entry.
Result is true until all values have been returned.
Initialize "digits" array with 9,8,7,6,5,4,3,2,1,0 (10 digit pandigitals) or
9,8,7,6,5,4,3,2,1 (9 digit "almost" pandigitals) before first call.
}
procedure swap(i: integer; j: integer);
{swap digits[i] and digits[j]}
var
temp: integer;
begin
temp := Digits[i];
Digits[i] := Digits[j];
Digits[j] := temp;
end;
var
k, j, r, s: integer;
begin
k := size - 2; {start at next-to-last}
{find the last decreasing-order pair}
while (k >= 0) and (Digits[k] > Digits[k + 1]) do
Dec(k);
if k < 0 then
Result := False {if none in decreasing order, we're done}
else
begin
j := size - 1; {find the rightmost digit less than digits[k]}
while Digits[k] > Digits[j] do
j := j - 1;
swap(j, k); {and swap them}
r := size - 1;
s := k + 1; {from there to the end, swap end digits toward the center}
while r > s do
begin
swap(r, s);
r := r - 1;
s := s + 1;
end;
Result := True; {magic!}
end;
end;
{************** GetPrevPandigital}
function GetPrevPandigital(size: integer; var Digits: array of integer): boolean;
{Generates 9 or 10 digit permutations of digits in decreasing sequence,
Input parameter "size" is the number of digits to generate (2 to 10).
Output placed in open array "digits", so index value of k refers
to (k+1)th entry.
Result is true until all values have been returned.
Initialize "digits" array with 9,8,7,6,5,4,3,2,1,0 (10 digit pandigitals) or
9,8,7,6,5,4,3,2,1 (9 digit "almost" pandigitals) before first call.
}
procedure swap(i: integer; j: integer);
{swap digits[i] and digits[j]}
var
temp: integer;
begin
temp := Digits[i];
Digits[i] := Digits[j];
Digits[j] := temp;
end;
var
k, j, r, s: integer;
begin
k := size - 2; {start at next-to-last}
{find the last decreasing-order pair}
while (k >= 0) and (Digits[k] < Digits[k + 1]) do
Dec(k);
if k < 0 then
Result := False {if none in decreasing order, we're done}
else
begin
j := size - 1; {find the rightmost digit less than digits[k]}
while Digits[k] < Digits[j] do
j := j - 1;
swap(j, k); {and swap them}
r := size - 1;
s := k + 1; {from there to the end, swap end digits toward the center}
while r > s do
begin
swap(r, s);
r := r - 1;
s := s + 1;
end;
Result := True; {magic!}
end;
end;
{************ RotateStrLeft **********}
procedure rotatestrleft(var s: string);
var
ch: char;
len: integer;
begin
len := length(s);
if len > 1 then
begin
ch := s[1];
move(s[2],s[1],len-1);
s[len] := ch;
end;
end;
var
i, j, key, temp, rightmost: integer;
begin
{1. Find Key, the leftmost byte of rightmost in-sequence pair
If none found, we are done}
}
rightmost := high(a);
i := rightmost - 1; {Start at right end -1}
while (i >= 0) and (a[i] >= a[i + 1]) do
Dec(i); {Find in-sequence pair}
if i >= 0 then {Found it, so there is another permutation}
begin
Result := True;
key := a[i];
(*
function IsPolygonal(T:int64):intset;
{from http://mathworld.wolfram.com/PolygonalNumber.html}
var
test:byte;
n:int64;
s2,s:int64;
begin
result:=[];
test:=3;
while test<=8 do
begin
s2:=8*(test-2)*T+(test-4)*(test-4);
s:=trunc(sqrt(0.0+s2));
if s*s=s2 then
begin {s2 is a perfect square do the number is Test-ogonal};
result:=result+[test];
end;
inc(test);
end;
end;
*)
function getpolygonal(p, r: int64): int64;
begin
case p of
3: Result := (r * (r + 1) div 2);
4: Result := (r * r);
5: Result := (r * (3 * r - 1) div 2);
6: Result := (r * (2 * r - 1));
7: Result := (r * (5 * r - 3) div 2);
8: Result := (r * (3 * r - 2));
else
Result := 0;
end;
end;
function IsPolygonal(T: int64; var rank: array of integer): boolean;
{from http://mathworld.wolfram.com/PolygonalNumber.html}
var
test: byte;
r: int64;
s2, s: int64;
begin
Result := False;
test := 3;
while test <= 8 do
begin
s2 := 8 * (test - 2) * T + (test - 4) * (test - 4);
s := trunc(sqrt(0.0 + s2));
if s * s = s2 then {it could be a polygonal}
begin
{s2 is a perfect square do the number could be Test-ogonal};
r := (s + test - 4) div (2 * (test - 2));
if getpolygonal(test, r) <> T then
r := 0;
Result := True;
end
else
r := 0;
rank[test] := r;
Inc(test);
end;
end;
(*
Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ...
Square P4,n=n2 1, 4, 9, 16, 25, ...
Pentagonal P5,n=n(3n1)/2 1, 5, 12, 22, 35, ...
Hexagonal P6,n=n(2n1) 1, 6, 15, 28, 45, ...
Heptagonal P7,n=n(5n3)/2 1, 7, 18, 34, 55, ...
Octagonal P8,n=n(3n2)
*)
(*
procedure generateTriangle(n:integer);
var i:integer;
oldlength:integer;
begin
oldlength:=length(triangle);
setlength(triangle,n);
for i:= oldlength+1 to n do triangle[i-1]:=i*(i+1) div 2;
end;
procedure generatePentagon(n:integer);
var
i:integer;
oldlength:integer;
begin
oldlength:=length(pentagon);
setlength(Pentagon,n);
for i:= oldlength+1 to n do pentagon[i-1]:=i*(3*i-1) div 2;
end;
procedure generateHexagon(n:integer);
var i:integer;
oldlength:integer;
begin
oldlength:=length(hexagon);
setlength(hexagon,n);
for i:= oldlength+1 to n do hexagon[i-1]:=i*(2*i-1);
end;
w := n * n + a * n + b;
if (w >= 0) and isprime(w) then
Inc(Result)
else
quit := True;
until quit;
end;
end;
const
maxdigits = 1000;
var
Base: int64 = 10000000000;
type
tbigint = array[0..maxdigits div 10] of int64;
end;
break;
end;
end;
var
n: integer;
begin
n := length(a);
if n <= maxcontinuant then
Result := continuants[n]
else
begin
if length(A) = 0 then
Result := 1
else if length(A) = 1 then
Result := a[0]
else
Result := A[high(A)] * continuant(slice(A, length(A) - 1)) +
continuant(slice(A, length(A) - 2));
Inc(maxcontinuant);
continuants[maxcontinuant] := Result;
end;
end;
var
A2: array of int64; {reversed version of A so we can use slice function}
i: integer;
x: int64;
begin
SetLength(A2, length(A) - 1);
{reverse the array for passing to continuant}
if length(a2) > 0 then
begin
for i := 1 to high(A) do
A2[high(A) - i] := A[i];
x := a[0];
denominator := continuant(A2);
SetLength(A2, length(A2) - 1);
numerator := x * denominator + continuant(A2);
end
else
begin
numerator := a[0];
denominator := 1;
end;
end;
var
i, j: integer;
temp: int64;
begin
SetLength(divisors, getnbrdivisors(n) + 1);
nbrdiv := 0;
temp := 1;
getit(0, temp);
if nbrdivisors <> nbrdiv then
ShowMessage('Divisors calc error');
{let's sort the divisors}
for i := 1 to nbrdivisors - 1 do
for j := i + 1 to nbrdivisors do
if divisors[i] > divisors[j] then
begin
temp := divisors[i];
divisors[i] := divisors[j];
divisors[j] := temp;
end;
end;
{********************Primes.Create ***********************}
constructor TPrimes.Create;
{Calculate primes less than maxval using Sieve of Eratosthenes}
var
workprimes: array of integer;
i, j: integer;
nbr, stopval: integer;
begin
inherited;
SetLength(workprimes, maxprimes + 1);
SetLength(Prime, maxprimes + 1);
{showmessage('Max prime is '+inttostr(high(x)));}
SetLength(factors, maxfactors + 1);
{initialize array starting with 2,3,4,5, etc.}
for i := 1 to maxprimes do
workprimes[i] := i + 1;
initialization
Primes := TPrimes.Create;
finalization
Primes.Destroy;
end.