Pitkä koodinpätkä

pässi

En löydä tästä (lienee liian helppoa) miten tän
generaattorin saa tekemään pidemmällä periodilla
kuin 2^128 randomia. Jos joku nyt viittis tän
tsekata mihin teen muutoksia, muuta ei tarvitse
selitellä: Koodi ja mitä muutetaan?

{Copyright: Hagen Reddmann mailto:[email protected]
Author: Hagen Reddmann
Remarks: freeware, but this Copyright must be included
known Problems: none
Version: 3.0
Delphi 2-4, designed and testet under D3 and D4
Description: Linear Feedback Shift Register (LFSR)
Random Number Generator with variable Period
from 2^32 -1 to 2^2032 -1, Standard is 2^128 -1
with .Seed('', -1) absolutly random
The Period have theoretical no effect on the Speed.

Speed: ca. 40 Mb/sec of a PII MMX 266 MHz 64Mb RAM

* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Speed: all times for PII MMX 266Mhz 64Mb
theoretical have the Period (Size of LFSR) no effect on the Speed,
but a greater Period will run faster. (Cache, little Branches on Pentium, etc.)
except the Period 2^128-1, this use a specially optimized method.

> 14.5 Mb/sec
> 40.5 Mb/sec with 128bit LFSR
Version 3.0

TRandom is now a descend from TProtect, see Unit DECUtil.pas

}
unit RNG;

interface

{$I VER.INC}

uses SysUtils, Classes, DECUtil;

type
ERandom = class(Exception);

TRandom = class(TProtection) // Basicly RNG, equal to Borland's Random()
private
FRegister: Integer;
FPassword: String;
protected
FCount: Integer; // not as private Fields, easier access for descends
FSize: Integer;
FBasicSeed: Integer;
procedure SetSize(Value: Integer); virtual;
function GetState: String; virtual;
procedure SetState(Value: String); virtual;
// override TProtect Methods
procedure CodeInit(Action: TPAction); override;
procedure CodeDone(Action: TPAction); override;
procedure CodeBuf(var Buffer; const BufferSize: Integer; Action: TPAction); override;
public
constructor Create(const APassword: String; ASize: Integer; ARandomize: Boolean; AProtection: TProtection); virtual;
destructor Destroy; override;
// set the Seed register
// Size = 0 -> Seed to initial Value
// Size < 0 -> Seed to randomness Value, equal to Randomize
// Size > 0 -> Seed is set to Buffer
procedure Seed(const ABuffer; ASize: Integer); virtual;
// fill out ABuffer ASize Bytes randomly
procedure Buffer(var ABuffer; ASize: Integer); virtual;
// gives Random Integer in ARange
function Int(ARange: Integer): Integer; virtual;
// Stream loading/saving
procedure SaveToStream(Stream: TStream); virtual;
procedure LoadFromStream(Stream: TStream); virtual;
// File loading/saving
procedure SaveToFile(const FileName: String);
procedure LoadFromFile(const FileName: String);
// Count of Bytes that Int() or Buffer() has generated
property Count: Integer read FCount write FCount;
// the Size in Bits
property Size: Integer read FSize write SetSize;
// basicly Seed Value for use in .Seed(), Standard is DefaultSeed
property BasicSeed: Integer read FBasicSeed write FBasicSeed;
// the internal State as MIMIE Base64 String
property State: String read GetState write SetState;
end;

TRandom_LFSR = class(TRandom) // Linear Feedback Shift Register
private
FPtr: Integer; // Current Position in FRegister
FLast: Integer; // Highest Position in FRegister
FTable: array[0..255] of Word; // Lookup Table for FRegister
FRegister: array[0..255] of Byte; // Linear Feedback Shift Register
FFunc: procedure(Self: Pointer; var Buffer; Size: Integer);
protected
procedure SetSize(Value: Integer); override;
function GetState: String; override;
procedure SetState(Value: String); override;
public
procedure Seed(const ABuffer; ASize: Integer); override;
procedure Buffer(var ABuffer; ASize: Integer); override;
end;

{ Follow the used polynomial's for TRandom_LFSR
size in bytes of register, XORCode, Polynomial, Period

4, $F5, x^32 x^7 x^5 x^3 x^2 x 1, 2^32 -1
5, $9C, x^40 x^5 x^4 x^3 1, 2^40 -1
6, $ED, x^48 x^7 x^5 x^4 x^2 x 1, 2^48 -1
7, $A9, x^56 x^7 x^4 x^2 1, 2^56 -1
8, $D8, x^64 x^4 x^3 x 1, 2^64 -1
9, $FA, x^72 x^6 x^4 x^3 x^2 x 1, 2^72 -1
10, $F5, x^80 x^7 x^5 x^3 x^2 x 1, 2^80 -1
12, $BB, x^96 x^7 x^6 x^4 x^3 x^2 1, 2^96 -1
15, $E7, x^120 x^7 x^6 x^5 x^2 x 1, 2^120 -1
16, $E1, x^128 x^7 x^2 x 1, 2^128 -1
18, $A9, x^144 x^7 x^4 x^2 1, 2^144 -1
19, $B2, x^152 x^6 x^3 x^2 1, 2^152 -1
20, $B4, x^160 x^5 x^3 x^2 1, 2^160 -1
22, $BD, x^176 x^7 x^5 x^4 x^3 x^2 1, 2^176 -1
25, $B4, x^200 x^5 x^3 x^2 1, 2^200 -1
27, $D1, x^216 x^7 x^3 x 1, 2^216 -1
38, $FC, x^304 x^5 x^4 x^3 x^2 x 1, 2^304 -1
40, $D8, x^320 x^4 x^3 x 1, 2^320 -1
42, $C9, x^336 x^7 x^4 x 1, 2^336 -1
44, $BD, x^352 x^7 x^5 x^4 x^3 x^2 1, 2^352 -1
50, $B4, x^400 x^5 x^3 x^2 1, 2^400 -1
51, $FA, x^408 x^6 x^4 x^3 x^2 x 1, 2^408 -1
55, $D8, x^440 x^4 x^3 x 1, 2^440 -1
60, $BB, x^480 x^7 x^6 x^4 x^3 x^2 1, 2^480 -1
61, $D8, x^488 x^4 x^3 x 1, 2^488 -1
63, $FA, x^504 x^6 x^4 x^3 x^2 x 1, 2^504 -1
67, $95, x^536 x^7 x^5 x^3 1, 2^536 -1
84, $F6, x^672 x^6 x^5 x^3 x^2 x 1, 2^672 -1
89, $9C, x^712 x^5 x^4 x^3 1, 2^712 -1
91, $B8, x^728 x^4 x^3 x^2 1, 2^728 -1
103, $FC, x^824 x^5 x^4 x^3 x^2 x 1, 2^824 -1
141, $D1, x^1128 x^7 x^3 x 1, 2^1128 -1
154, $F3, x^1232 x^7 x^6 x^3 x^2 x 1, 2^1232 -1
254, $A3, x^2032 x^7 x^6 x^2 1, 2^2032 -1

follow various Periods
--------------------------------------------------------------------------------
2^32-1 = 4294967295
2^64-1 = 18446744073709551615
2^128-1 = 340282366920938463463374607431768211455
2^2032-1 = it's one Number
49311837877366649323600580884811328064642490645928167773636391338386009428204
17921935608125537553934278674005267623599165972833122328326583112816221076703
35702985799671951234310153163915857728680359766210694390385082889078409114931
66867209378778336289339669574030006474132653643098550122997363890264786354861
31947843882498538312526670313197249581325688984118966381501107686008635362008
71492771279798342546336760614070411100118371556871830774626226863061725361438
46476937385117828689155818331492509954024778049592066494651864619855274961300
9880449926596639031121858756000207590413184793166384097191709192063287295
--------------------------------------------------------------------------------
}

// Your actual Random Class, per default TRandom_LFSR.Create(128, False)
function RND: TRandom;

// internal used for the random initialization of the Seed Initial Value
// change this to produce Application dependent Randomness
const
DefaultSeed: Integer = 693258280;

implementation

uses DECConst;

const
FRND: TRandom = nil;

// avaible Periods for the LFSR
LFSRPeriod: array[0..33, 0..1] of Word =
(( 32, $F5), ( 40, $9C), ( 48, $ED), ( 56, $A9),
( 64, $D8), ( 72, $FA), ( 80, $F5), ( 96, $BB),
( 120, $E7), ( 128, $E1), ( 144, $A9), ( 152, $B2),
( 160, $B4), ( 176, $BD), ( 200, $B4), ( 216, $D1),
( 304, $FC), ( 320, $D8), ( 336, $C9), ( 352, $BD),
( 400, $B4), ( 408, $FA), ( 440, $D8), ( 480, $BB),
( 488, $D8), ( 504, $FA), ( 536, $95), ( 672, $F6),
( 712, $9C), ( 728, $B8), ( 824, $FC), ( 1128, $D1),
( 1232, $F3), ( 2032, $A3));

function RND: TRandom;
begin
if FRND = nil then
begin
FRND := TRandom_LFSR.Create('', 0, False, nil);
FRND.AddRef;
end;
Result := FRND;
end;

procedure TRandom.SetSize(Value: Integer);
begin
FSize := 32; // allways 32
end;

function TRandom.GetState: String;
var
CRC: Word;
M: TMemoryStream;
begin
M := TMemoryStream.Create;
try
// write a Randomized Word to begin,
// any Encryption produce allways other outputs
RndXORBuffer(RndTimeSeed, CRC, SizeOf(CRC));
M.Write(CRC, SizeOf(CRC));
M.Write(FSize, SizeOf(FSize));
M.Write(FBasicSeed, SizeOf(FBasicSeed));
M.Write(FCount, SizeOf(FCount));
M.Write(FRegister, SizeOf(FRegister));
CRC := not CRC16($FFFF, M.Memory, M.Size);
M.Write(CRC, SizeOf(CRC));
CRC := $0100; // Version 1 without Protection
if Protection nil then
begin
CRC := CRC or 1; // with Protection
M.Position := 0;
Protection.CodeStream(M, M, M.Size, paEncode);
M.Position := M.Size;
end;
M.Write(CRC, SizeOf(CRC));
Result := StrToFormat(M.Memory, M.Size, fmtMIME64);
finally
M.Free;
end;
end;

procedure TRandom.SetState(Value: String);
var
CRC: Word;
I: Integer;
M: TMemoryStream;
begin
M := TMemoryStream.Create;
try
Value := FormatToStr(PChar(Value), Length(Value), fmtMIME64);
M.Write(PChar(Value)^, Length(Value));
M.Position := M.Size - SizeOf(CRC);
M.Read(CRC, SizeOf(CRC));
if CRC and $FF00 $0100 then // it's Version $0100 ?
raise ERandom.Create(sInvalidRandomStream);
if CRC and 1 0 then
if Protection nil then
begin
M.Position := 0;
Protection.CodeStream(M, M, M.Size - SizeOf(CRC), paDecode);
end else raise ERandom.Create(sRandomDataProtected);
M.Position := M.Size - SizeOf(CRC) * 2;
M.Read(CRC, SizeOf(CRC));
if CRC not CRC16($FFFF, M.Memory, M.Size - SizeOf(CRC) * 2) then
raise ERandom.Create(sInvalidRandomStream);
M.Position := SizeOf(CRC); // skip Dummy Random Word
M.Read(I, SizeOf(FSize));
SetSize(I);
M.Read(FCount, SizeOf(FCount));
M.Read(FBasicSeed, SizeOf(FBasicSeed));
M.Read(FRegister, SizeOf(FRegister));
finally
M.Free;
end;
end;

constructor TRandom.Create(const APassword: String; ASize: Integer; ARandomize: Boolean; AProtection: TProtection);
begin
inherited Create(AProtection);
FBasicSeed := DefaultSeed;
FSize := -1;
FPassword := APassword;
SetSize(ASize);
if ASize > 0 then
if not ARandomize then Seed(PChar(FPassword)^, Length(FPassword))
else Seed('', -1);
end;

destructor TRandom.Destroy;
begin
Seed('', 0);
if Self = FRND then FRND := nil;
inherited Destroy;
end;

procedure TRandom.Seed(const ABuffer; ASize: Integer);
var
I: Integer;
R: PByteArray;
begin
if (ASize > 0) and (@ABuffer nil) then
begin
FRegister := FBasicSeed;
FillChar(FRegister, SizeOf(FRegister), 0);
R := @FRegister;
for I := 0 to ASize -1 do
R[I and 3] := R[I and 3] TByteArray(ABuffer)[I];
end else
if ASize < 0 then FRegister := RndTimeSeed (FCount 1)
else FRegister := FBasicSeed;
if Protection nil then
Protection.CodeBuffer(FRegister, SizeOf(FRegister), paScramble);
end;

function TRandom.Int(ARange: Integer): Integer;
begin
Buffer(Result, SizeOf(Result));
if (ARange = 0) or (Result = 0) then Exit;
if (ARange >= 0) and (Result < 0) then Result := -Result else
if ARange < 0 then ARange := -ARange;
Result := Result mod (ARange 1);
Inc(FCount, SizeOf(Result));
end;

procedure TRandom.Buffer(var ABuffer; ASize: Integer);
begin
if ASize 0 then Delete(C, 1, I);
S := InsertCR(State, 64);
C := C IntToHex(Length(S), 4) #13#10 S;
Stream.Write(PChar(C)^, Length(C));
end;

procedure TRandom.LoadFromStream(Stream: TStream);
var
C,S: String;
I: Integer;
begin
// write the Name from ClassName (i.E. TRandom_LFSR -> "LFSR"),
// the Size as a 4 Char HEX String and State.
// i.E. LFSR0FCB State
C := ClassName;
if C[1] = 'T' then Delete(C, 1, 1);
I := Pos('_', C);
if I > 0 then Delete(C, 1, I);
SetLength(S, Length(C));
Stream.Read(PChar(S)^, Length(C));
if S C then Abort;
SetLength(S, 6);
Stream.Read(PChar(S)^, 6);
SetLength(S, 4);
I := StrToInt('$' S);
SetLength(S, I);
Stream.Read(PChar(S)^, I);
State := DeleteCR(S);
end;

procedure TRandom.SaveToFile(const FileName: String);
var
S: TStream;
begin
S := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(S);
finally
S.Free;
end;
end;

procedure TRandom.LoadFromFile(const FileName: String);
var
S: TStream;
begin
S := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
LoadFromStream(S);
finally
S.Free;
end;
end;

procedure TRandom.CodeInit(Action: TPAction);
begin
if Action = paWipe then Seed('', -1)
else Seed(PChar(FPassword)^, Length(FPassword));
inherited CodeInit(Action);
end;

procedure TRandom.CodeDone(Action: TPAction);
begin
inherited CodeDone(Action);
if Action = paWipe then Seed('', -1)
else Seed(PChar(FPassword)^, Length(FPassword));
end;

procedure TRandom.CodeBuf(var Buffer; const BufferSize: Integer; Action: TPAction);
const
maxBufSize = 1024 * 4;
var
Buf: Pointer;
BPtr: PByte;
BSize,CSize: Integer;
begin
if Action paDecode then inherited CodeBuf(Buffer, BufferSize, Action);
if Action in Actions then
begin
BPtr := @Buffer;
if BPtr = nil then Exit;
BSize := maxBufSize;
if BSize > BufferSize then BSize := BufferSize;
Buf := AllocMem(BSize);
CSize := BufferSize;
try
if Action = paCalc then
begin
while CSize > 0 do
begin
BSize := CSize;
if BSize > maxBufSize then BSize := maxBufSize;
Self.Buffer(Buf^, BSize);
XORBuffers(Buf, BPtr, BSize, Buf);
Inc(BPtr, BSize);
Dec(CSize, BSize);
end
end else
begin
while CSize > 0 do
begin
BSize := CSize;
if BSize > maxBufSize then BSize := maxBufSize;
Self.Buffer(Buf^, BSize);
XORBuffers(Buf, BPtr, BSize, BPtr);
Inc(BPtr, BSize);
Dec(CSize, BSize);
end;
end;
finally
ReallocMem(Buf, 0);
end;
end;
if Action = paDecode then
inherited CodeBuf(Buffer, BufferSize, Action);
end;

// internal for TRandom_LFSR
procedure LFSRBuf(Self: Pointer; var Buffer; Size: Integer); assembler;
asm
AND EDX,EDX // Buffer = nil ?
JZ @@9
AND ECX,ECX // BufferSize

4

506

    Vastaukset

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • ihmeellistä

      Tuo koodi on aika käsittämätöntä sotkua. En viitsi edes ruveta tulkitsemaan sitä, sen verran hankalalta vaikuttaa.

      • pässi

        onhan se sekavan näköistä, mutta täysin toimivaa
        koodia. Sekavaa sikäli, että aihekin on sekava
        eli "suhteellisen varmojen" pseudosatunnaislukujen
        generoiminen.

        Ohjelmointiteknisesti koodi on kuulemma hyvää mutta "nolladokumentointua".


    • delphi coder

      Korvaa...


      if Value = LFSRPeriod[I, 0] then
      begin
      DoSet(I);
      Exit;
      end;
      DoSet(9); // Tässä 9 tilalle 33 niin saat 2^2032 randomia...
      end;
      end;

      • pässi

        Olihan se sinne aika selkeästi kirjoitettu, kun
        viitsi itse katsoa 10 kertaa, hätäily on pahasta.

        Mutta kiitän vaivannäöstä, vaikka kokeilemalla
        homma myös selvisi itsellekin!

        PS. Koodin varmuutta käytännössä lienee mahdoton
        todistaa muuta kuin matemaattisesti, mutta onhan
        tuo runsaasti käytössä.


    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Poliisitehtävä alkuviikosta Maisan kotona

      Iltasanomat: Helsingin poliisilaitos vahvistaa, että Vantaalla on ollut poliisitehtävä kyseisenä ajankohtana. Poliisin
      Kotimaiset julkkisjuorut
      88
      2079
    2. Tämä on sinulle vaikka kaikki lukee

      Vaikka kuinka olet viisas ja kaikin puolin velho, niin et tiedä tilanteestani. Senkin takia menetät mielenkiinnon. Eikä
      Tunteet
      11
      1692
    3. T-mies tässä

      Kerro nainen huolesi niin pohditaan yhdessä. 😎
      Ikävä
      102
      1162
    4. Lulu selvityttää Elokapinan lakkautusta

      Persukannattajien mielistely otti Lulu Ranteella aika tavalla runtua, kun hän aikoo selvityttää mahdollisuuksia Elokapin
      Maailman menoa
      350
      1136
    5. Ensitreffit Matti joutuu "ulkoruokintaan" - Väärinymmärrysten suossa Taina-vaimon kanssa: "Oli..."

      No nyt on kyllä väärinymmärrystä kerrakseen… Mitä luulet, pysyykö Taina ja Matti yhdessä vai onko tulevaisuudessa ero ed
      Ensitreffit alttarilla
      3
      1123
    6. Harmi, kun sillä nousi

      kaikki huomio päähän. Vaikutti aluksi niin mukavalta ja vaatimattomalta 😔
      Ikävä
      53
      851
    7. Täytyy sanoa

      Että olit kyllä mielenkiintoisin ja omaperäisin nainen mitä olen koskaan tavannut. Aivan kuin joku olisi tiputtanut sinu
      Ikävä
      21
      839
    8. Miten saisin

      Hurmattua sinut uudelleen,? Pissin omiin muroihini ensinmäisellä kerralla koska olin tyhmä ja liiaksi kiinni menneess
      Ikävä
      31
      787
    9. Persu Meri Valkama kadehtii Sanna Marinin menestystä

      Taas yksi persu tuli nolaamaan itsensä kadehtiessaan menestynyttä Suomen kansan supertähteä Sanna Marinia. https://demo
      Maailman menoa
      237
      737
    10. Raamatun tärkein lause

      Ja Mooses tuli alas vuorilta missä jumala oli, Mooseksen mukaan, ilmoittanut hänelle, että hän ja koko juutalainen väki,
      Hindulaisuus
      367
      719
    Aihe