{Bit boolean - because it stores 8 bools per bytye, it will} {handle up to 16 gigabyte in a 32 bit programming environment} type TBitBoolArray = class(TObject) private FSize: int64; ByteArray: array of Byte; function GetValue(Index: int64): boolean; procedure WriteValue(Index: int64; const Value: boolean); function GetSize: int64; procedure SetSize(const Value: int64); protected public property Value[Index: int64]: boolean read GetValue write WriteValue; default; constructor Create; property Count: int64 read GetSize write SetSize; procedure Clear(Value: boolean); end; { TBitBoolArray } const BitArray: array [0..7] of byte = ($01, $02, $04, $08, $10, $20, $40, $80); function TBitBoolArray.GetValue(Index: int64): boolean; begin {Note: (Index and 7) is faster than (Index mod 8)} Result:=(ByteArray[Index shr 3] and BitArray[Index and 7])<>0; end; procedure TBitBoolArray.WriteValue(Index: int64; const Value: boolean); var Inx: int64; begin Inx:=Index shr 3; {Note: (Index and 7) is faster than (Index mod 8)} if Value then ByteArray[Inx]:=ByteArray[Inx] or BitArray[Index and 7] else ByteArray[Inx]:=ByteArray[Inx] and not BitArray[Index and 7] end; constructor TBitBoolArray.Create; begin SetLength(ByteArray,0); end; function TBitBoolArray.GetSize: int64; begin Result:=FSize; end; procedure TBitBoolArray.SetSize(const Value: int64); var Len: int64; begin FSize:=Value; {Storing 8 items per byte} Len:=Value div 8; {We need one more to fill partial bits} if (Value mod 8)<>0 then Inc(Len); SetLength(ByteArray,Len); end; procedure TBitBoolArray.Clear(Value: boolean); var Fill: byte; begin if Value then Fill:=$FF else Fill:=0; FillChar(ByteArray[0],Length(ByteArray),Fill); end; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ {Sieve object the generates and holds prime values} {Enable this flag if you need primes past 2 billion. The flag signals the code to use bit-booleans arrays which can contain up to 8 x 4 gigabytes = 32 gig booleans.} {$define BITBOOL} type TPrimeSieve = class(TObject) private {$ifdef BITBOOL} PrimeArray: TBitBoolArray; {$else} PrimeArray: array of boolean; {$endif} FArraySize: int64; function GetPrime(Index: int64): boolean; procedure Clear; protected procedure DoSieve; property ArraySize: int64 read FArraySize; public BitBoolean: boolean; constructor Create; destructor Destroy; override; procedure Intialize(Size: int64); property Prime[Index: int64]: boolean read GetPrime; default; function NextPrime(Start: int64): int64; end; procedure TPrimeSieve.Clear; begin {$ifdef BITBOOL} PrimeArray.Clear(True); {$else} FillChar(PrimeArray[0],Length(PrimeArray),True); {$endif} end; constructor TPrimeSieve.Create; begin {$ifdef BITBOOL} PrimeArray:=TBitBoolArray.Create; BitBoolean:=True; {$else} BitBoolean:=False; {$endif} end; destructor TPrimeSieve.Destroy; begin {$ifdef BITBOOL} PrimeArray.Free; {$endif} inherited; end; procedure TPrimeSieve.DoSieve; {Load flags with true/false to flag that number is prime} {Note: does not store even values, because except for 2, all primes are even} {Starts storing flags at Index=3, so reading/writing routines compensate} {Uses for-loops for boolean arrays and while-loops for bitbooleans arrays} {$ifdef BITBOOL} var Offset, I, K: int64; {$else} var Offset, I, K: cardinal; {$endif} begin Clear; {$ifdef BITBOOL} I:=0; while I0) or (((p3 - p2) mod 18)<>0) then exit; Pd1:=EncodeNumber(P1); Pd2:=EncodeNumber(P2); if Pd1<>Pd2 then exit; Pd3:=EncodeNumber(P3); Result:=Pd2=Pd3; end; function TOrm3Iterator.GetNext(Limit: int64; var Info: TTripleInfo): boolean; {Iterate to next Ormiston Pair - automatically stop at prime>Limit} {Returns false if it hits limit - true if it found Next Ormiston Pair} begin Result:=False; while true do begin {Get next set of primes} FInfo.Prime1:=FInfo.Prime2; FInfo.Prime2:=FInfo.Prime3; FInfo.Prime3:=PS.NextPrime(FInfo.Prime3); {Abort if 3rd prime is ove limit} if FInfo.Prime3>=Limit then break; {Test if it is an Ormiston triple} if IsOrmistonTriple(FInfo.Prime1,FInfo.Prime2,FInfo.Prime3) then begin {Return info on triple} Inc(FInfo.Count); Info:=FInfo; Result:=True; break; end; end; end; procedure ShowOrmistonTriple(Memo: TMemo); var I: integer; var S: string; var OI: TOrm3Iterator; var Info: TTripleInfo; const Limit = 10000000000; const DisMod = Limit div 10000000; const Bill = Limit div 1000000000; var NS: string; procedure DisplayTitle; begin NS:=IntToStr(Bill)+'-Billion'; Memo.Lines.Add('====== Find Ormiston Triples ======'); Memo.Lines.Add('First 25 plus number to '+NS); S:='Bit-Boolean Array: '; if OI.PS.BitBoolean then S:=S+'Yes' else S:=S+'No'; Memo.Lines.Add(S); end; begin {Create iterator} OI:=TOrm3Iterator.Create; try DisplayTitle; Memo.Lines.Add('Sieving Primes'); OI.SetSize(Limit); Memo.Lines.Add('Finding first 25 Triples'); {Iterate throug 1st 25 tuples} for I:=1 to 25 do begin OI.GetNext(High(Int64),Info); Memo.Lines.Add(Format('%3d - (%6D %6D %6D) ',[I,Info.Prime1,Info.Prime2,Info.Prime3])); end; Memo.Lines.Add('Count='+IntToStr(Info.Count)); Memo.Lines.Add('Counting triples to '+NS); {Iterate to limit number of triples} while OI.GetNext(Limit,Info) do if (Info.Count mod DisMod)=0 then Memo.Lines.Add('Count='+IntToStr(Info.Count)); Memo.Lines.Add(NS+'='+IntToStr(Info.Count)); finally OI.Free; end; end;