Using the scalable approach, beyond the occupying of memory, the slowing down of the extraction takes place. However, assuming to have a space of N numbers, if it is represented by a one-dimensional array, to carry out the extraction of a number of such space I will have to perform, on average, an amount of (N / 2) iterations; but if this space is a square matrix, for example, for each number that I extract, I will have, on average, an amount of (Sqrt (N) / 2 + Sqrt (N) / 2) iterations; it is the row search and the column search: less iterations. With a 3-dimensional matrix the number of iterations is even smaller: ( N ^ (1/3) / 2 + N ^ (1/3) / 2 + N ^ (1/3) / 2), and so on, increasing the number of dimensions of the structure associated with the number space, the number of overall iterations is always smaller.
Obviously for each dimension above the first one, I have to take into account the number of available elements of the immediately smaller dimension of the vector space.
For example, I report this unit, written in assembler (protected mode) under Delphi. To extract 2 ^ 27 numbers, the GetRndGRNum () function, on an old ACER TravelMate 4220 laptop, takes 37 seconds:
unit x;
interface
Const GRMinCellValue=-1 ShL 31;
GRMaxDeltaNum=(1 ShL 27)-1;
Type {2} TGRData0=Record
{1} GRNumArrAmount0,
{1} GRNumArr0:Byte;
End;
{16} TGRArr1=Array [0..7] Of TGRData0;
{17} TGRData1=Record
{1} GRNumArrAmount1:Byte;
{16} GRNumArr1:TGRArr1;
End;
{136} TGRArr2=Array [0..7] Of TGRData1;
{137} TGRData2=Record
{1} GRNumArrAmount2:Byte;
{136} GRNumArr2:TGRArr2;
End;
{1096} TGRArr3=Array [0..7] Of TGRData2;
{1097} TGRData3=Record
{1} GRNumArrAmount3:Byte;
{1096} GRNumArr3:TGRArr3;
End;
{8776} TGRArr4=Array [0..7] Of TGRData3;
{8777} TGRData4=Record
{1} GRNumArrAmount4:Byte;
{8776} GRNumArr4:TGRArr4;
End;
{70216} TGRArr5=Array [0..7] Of TGRData4;
{70217} TGRData5=Record
{1} GRNumArrAmount5:Byte;
{70216} GRNumArr5:TGRArr5;
End;
{561736} TGRArr6=Array [0..7] Of TGRData5;
{561737} TGRData6=Record
{1} GRNumArrAmount6:Byte;
{561736} GRNumArr6:TGRArr6;
End;
{4493896} TGRArr7=Array [0..7] Of TGRData6;
{4493897} TGRData7=Record
{1} GRNumArrAmount7:Byte;
{4493896} GRNumArr7:TGRArr7;
End;
{35951176} TGRArr8=Array [0..7] Of TGRData7;
{35951185} TGRData8=Record
{1} GRNumArrAmount8:Byte;
{4} GRNumMin8,
{4} GRNumMax8:Integer;
{35951176} GRNumArr8:TGRArr8;
End;
TGRData8Ptr=^TGRData8;
TRndXSeed=Array[0..3] Of Cardinal;
Var RndXSeed:TRndXSeed=(123456789, (* X: Seed *)
362436000, (* Y: Must be <>0 *)
521288629, (* Z: Must be <>0 *)
7654321); (* C: Must be <>0 *)
Function GetPtr (PValue:Integer):Pointer;
{Trasforma il valore PValue IN un PUNTATORE POINTER.
NOTE: È scritta IN ASSEMBLER.
Non chiama alcuna Sub-ROUTINE.
Testata con successo}
Function GetPtrValue (P:Pointer):Integer;
{Converte il PUNTATORE P IN un valore.
NOTE: È scritta IN ASSEMBLER.
Non chiama alcuna Sub-ROUTINE.
Testata con successo}
Procedure MyFillChar (M:Pointer;S,V:Cardinal);
{ Analoga alla System.FillChar(), ma più veloce.
NOTE: è scritta interam. IN ASSEMBLER.
Non effettua alcun salto (CALL, Jmp o salto condizionato),
ed è molto veloce.
Per impostare a 0 la VAR. A
(di tipo BYTE, WORD, SMALLINT o INTEGER):
MyFillChar(@A,SIZEOF(A),0);
Per impostare a 0 la VAR. A
(di tipo T=RECORD):
MyFillChar(@A,SIZEOF(A),0) }
Procedure ReSetGRConfig (GRConfig:TGRData8Ptr;
Min,Max:Integer);
(* (Re)inizializza l' estrazione di numeri casuali,
compresi tra Min e Max, con GetRndGRNum(GRConfig).
I valori ammessi per Min e Max
vanno da -2147483647 a +2147483647,
ma il numero massimo di numeri
che si possono estrarre è 134217728.
Se Min e Max costituiscono un range troppo ampio,
sarà ristretto il suddetto range e
sarà alzato il valore minimo.
è possibile specificare Min>Max *)
Function GetRndGRNum (GRConfig:TGRData8Ptr):Integer;
(* Estrae un numero casuale nel range Min-Max sempre
diverso da quelli estratti precedentemente.
Ritorna GRMinCellValue (-2147483648)
se non ci sono altri numeri da estrarre.
Inizializzare l' estrazione con ReSetGRConfig(GRConfig,Min,Max) *)
implementation
Uses Math;
Function GetPtr(PValue:Integer):Pointer; Assembler;
Asm
Mov EAX,PValue
End;
Function GetPtrValue(P:Pointer):Integer; Assembler;
Asm
Mov EAX,P
End;
Procedure MyFillChar(M:Pointer;S,V:Cardinal); Assembler;
Asm
Push EDI
Mov EDI,M (* EAX *)
Mov EAX,V (* ECX *)
Mov ECX,S (* EDX *)
ClD
Mov AH,AL
Mov DX,AX
ShL EAX,16
Mov AX,DX
Mov EDX,ECX
ShR ECX,2
Rep StoSD
SetB CL
Rep StoSW
Test DL,1
SetNE CL
Rep StoSB
Pop EDI
End;
Procedure ReSetGRConfig(GRConfig:TGRData8Ptr;
Min,Max:Integer);
Var I0,I1,I2,I3,I4,I5,I6,I7,I8:Byte;
Diff,Amount,Filled:Integer;
Begin
Inc(Min,Integer(Min=GRMinCellValue));
Diff:=Max-Min+Integer(Max=GRMinCellValue);
Dec(Diff,Integer(Abs(Diff)>GRMaxDeltaNum)*
(Diff-Sign(Diff)*GRMaxDeltaNum));
Filled:=0;
If Assigned(GRConfig) Then
With GRConfig^ Do
Begin
GRNumMin8:=Max-Diff*Integer(Diff>=0);
Diff:=Abs(Diff);
GRNumMax8:=GRNumMin8+Diff;
Amount:=Diff+1;
I8:=0;
Inc(Filled,9);
While (I8<8) And (Amount<>0) Do
With GRNumArr8[I8] Do
Begin
I7:=0;
Inc(Filled);
While (I7<8) And (Amount<>0) Do
With GRNumArr7[I7] Do
Begin
I6:=0;
Inc(Filled);
While (I6<8) And (Amount<>0) Do
With GRNumArr6[I6] Do
Begin
I5:=0;
Inc(Filled);
While (I5<8) And (Amount<>0) Do
With GRNumArr5[I5] Do
Begin
I4:=0;
Inc(Filled);
While (I4<8) And (Amount<>0) Do
With GRNumArr4[I4] Do
Begin
I3:=0;
Inc(Filled);
While (I3<8) And (Amount<>0) Do
With GRNumArr3[I3] Do
Begin
I2:=0;
Inc(Filled);
While (I2<8) And (Amount<>0) Do
With GRNumArr2[I2] Do
Begin
I1:=0;
Inc(Filled);
While (I1<8) And (Amount<>0) Do
With GRNumArr1[I1] Do
Begin
I0:=Integer((8+Amount-Abs(8-Amount)) ShR 1);
GRNumArrAmount0:=I0;
GRNumArr0:=0;
Dec(Amount,I0);
Inc(Filled,2);
Inc(I1);
End;
GRNumArrAmount1:=I1;
Inc(I2);
End;
GRNumArrAmount2:=I2;
Inc(I3);
End;
GRNumArrAmount3:=I3;
Inc(I4);
End;
GRNumArrAmount4:=I4;
Inc(I5);
End;
GRNumArrAmount5:=I5;
Inc(I6);
End;
GRNumArrAmount6:=I6;
Inc(I7);
End;
GRNumArrAmount7:=I7;
Inc(I8);
End;
GRNumArrAmount8:=I8;
(* 108'000'000= $66ff300
I6=7, I5=7, I4=16, I3=16, I2=3, I1=16, I0=16 = $7700300 *)
MyFillChar(GetPtr(GetPtrValue(GRConfig)+Filled),
SizeOf(GRConfig^)-Filled,0);
End;
End;
Function GetRndGRNum(GRConfig:TGRData8Ptr):Integer; Assembler;
Var Am7P,
Am6P,
Am5P,
Am4P,
Am3P,
Am2P,
Am1P,
GRData8Ptr:Integer;
RndN0,
RndN1,
RndN2,
RndN3,
RndN4,
RndN5,
RndN6,
RndN7,
RndN8,
RC7,
RC6,
RC5,
RC4,
RC3,
RC2,
RC1,
RC0:Byte;
Asm
Push EDI { Salva il registro EDI sullo STACK }
(* ---------------------------------------- *)
Mov EDI,GRConfig { Carica GRConfig (EAX) nel reg. EDI }
Mov EAX,GRMinCellValue { Carica il reg. di output con GRMinCellValue }
Or EDI,EDI { Se GRConfig=Nil ... }
JE @@00 { ... Ha finito, esce }
Cmp Byte Ptr [EDI],0 { Se GRConfig^.GRNumArrAmount6=0 ... }
JE @@00 { ... Ha finito, esce }
Mov GRData8Ptr,EDI { Salva GRConfig su GRData8Ptr }
(* ======================================== *)
LEA EDI,RndXSeed { Carica in EDI l' offs. di MyStrUt.MyRndXSeed }
(* ---------------------------------------- *)
(* - Generaz. di un num. casuale a 32 Bit - *)
(* ---------------------------------------- *)
Mov EAX,[EDI]
Mov EDX,69069
Mul EDX
Add EAX,12345
Mov [EDI],EAX // RndXSeed[0]:=69069*RndXSeed[0]+12345;
Mov EAX,[EDI+4]
ShL EAX,13
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 13);
Mov EAX,[EDI+4]
ShR EAX,17
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShR 17);
Mov EAX,[EDI+4]
ShL EAX,5
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 5);
Mov EAX,[EDI+8]
Mov EDX,698769069
Mul EDX
Add EAX,[EDI+12]
AdC EDX,0 // EDX:EAX:=698769069*RndXSeed[2]+RndXSeed[3];
Mov [EDI+12],EDX // RndXSeed[3]:=T ShR 32;
Cmp EAX,[EDI+8]
Mov EAX,0
SetE AL
Or EDX,EDX
SetE DL
And AL,DL // EAX:=Cardinal(RndXSeed[2]=T)
Add EAX,[EDI]
Add EAX,[EDI+4] // RndX:=RndXSeed[0]+RndXSeed[1]+Cardinal(RndXSeed[2]=T);
(* ---------------------------------------- *)
(* - Fine generazione numero casuale ------ *)
(* ---------------------------------------- *)
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN0,DL { ... in RndN0 }
ShR EAX,7
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN1,DL { ... in RndN1 }
ShR EAX,7
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN2,DL { ... in RndN2 }
ShR EAX,7
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN3,DL { ... in RndN3 }
ShR EAX,7
Mov RndN4,AL
(* ---------------------------------------- *)
(* - Generaz. di un num. casuale a 32 Bit - *)
(* ---------------------------------------- *)
Mov EAX,[EDI]
Mov EDX,69069
Mul EDX
Add EAX,12345
Mov [EDI],EAX
Mov EAX,[EDI+4]
ShL EAX,13
XOr [EDI+4],EAX
Mov EAX,[EDI+4]
ShR EAX,17
XOr [EDI+4],EAX
Mov EAX,[EDI+4]
ShL EAX,5
XOr [EDI+4],EAX
Mov EAX,[EDI+8]
Mov EDX,698769069
Mul EDX
Add EAX,[EDI+12]
AdC EDX,0
Mov [EDI+12],EDX
Cmp EAX,[EDI+8]
Mov EAX,0
SetE AL
Or EDX,EDX
SetE DL
And AL,DL
Add EAX,[EDI]
Add EAX,[EDI+4]
(* ---------------------------------------- *)
(* - Fine generazione numero casuale ------ *)
(* ---------------------------------------- *)
Mov DL,AL
And DL,7
ShL DL,4
Or RndN4,DL
ShR EAX,3
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN5,DL { ... in RndN5 }
ShR EAX,7
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN6,DL { ... in RndN6 }
ShR EAX,7
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN7,DL { ... in RndN7 }
ShR EAX,7
And AL,127
Mov RndN8,AL
Mov EDI,GRData8Ptr { Carica GRConfig in EDI }
(* ======================================== *)
(* = Ricerca del record TGRData7 ========= *)
(* ======================================== *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr8[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData8.GRNumArr8-TYPE(TGRData7) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr8-SizeOf(TGRData7) }
(* ---------------------------------------- *)
@@L8:Add EDI,TYPE(TGRData7) { EDI += SizeOf(TGRData7) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr8[CL].GRNumArrAmount7<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L8 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am7P,EDI { Salva OFFS(GRNumArr8[CL].GRNumArrAmount7) ...}
{ ... (EDI) in Am7P }
Mov RC7,CL { Salva RC (CL) in RC7 }
(* ======================================== *)
(* = Ricerca del record TGRData6 ========= *)
(* ======================================== *)
Mov AL,RndN7
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr7[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData7.GRNumArr7-TYPE(TGRData6) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr7-SizeOf(TGRData6) }
(* ---------------------------------------- *)
@@L7:Add EDI,TYPE(TGRData6) { EDI += SizeOf(TGRData6) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr7[CL].GRNumArrAmount6<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L7 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am6P,EDI { Salva OFFS(GRNumArr7[CL].GRNumArrAmount6) ...}
{ ... (EDI) in Am6P }
Mov RC6,CL { Salva RC (CL) in RC6 }
(* ======================================== *)
(* = Ricerca del record TGRData5 ========= *)
(* ======================================== *)
Mov AL,RndN6
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr6[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData6.GRNumArr6-TYPE(TGRData5) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr6-SizeOf(TGRData5) }
(* ---------------------------------------- *)
@@L6:Add EDI,TYPE(TGRData5) { EDI += SizeOf(TGRData5) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr6[CL].GRNumArrAmount5<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L6 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am5P,EDI { Salva OFFS(GRNumArr6[CL].GRNumArrAmount5) ...}
{ ... (EDI) in Am5P }
Mov RC5,CL { Salva RC (CL) in RC5 }
(* ======================================== *)
(* = Ricerca del record TGRData4 ========= *)
(* ======================================== *)
Mov AL,RndN5
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr5[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData5.GRNumArr5-TYPE(TGRData4) { EDI <- OFFSET ... }
{ ... TGRData5.GRNumArr5-SizeOf(TGRData4) }
(* ---------------------------------------- *)
@@L5:Add EDI,TYPE(TGRData4) { EDI += SizeOf(TGRData4) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr5[CL].GRNumArrAmount4<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L5 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am4P,EDI { Salva OFFS(GRNumArr5[CL].GRNumArrAmount4) ...}
{ ... (EDI) in Am4P }
Mov RC4,CL { Salva RC (CL) in RC4 }
(* ======================================== *)
(* = Ricerca del record TGRData3 ========= *)
(* ======================================== *)
Mov AL,RndN4
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr4[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData4.GRNumArr4-TYPE(TGRData3) { EDI <- OFFSET ... }
{ ... TGRData4.GRNumArr4-SizeOf(TGRData3) }
(* ---------------------------------------- *)
@@L4:Add EDI,TYPE(TGRData3) { EDI += SizeOf(TGRData3) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr4[CL].GRNumArrAmount3<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L4 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am3P,EDI { Salva OFFS(GRNumArr4[CL].GRNumArrAmount3) ...}
{ ... (EDI) in Am3P }
Mov RC3,CL { Salva RC (CL) in RC3 }
(* ======================================== *)
(* = Ricerca del record TGRData2 ========= *)
(* ======================================== *)
Mov AL,RndN3
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr3[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData3.GRNumArr3-TYPE(TGRData2) { EDI <- OFFSET ... }
{ ... TGRData3.GRNumArr3-SizeOf(TGRData2) }
(* ---------------------------------------- *)
@@L3:Add EDI,TYPE(TGRData2) { EDI += SizeOf(TGRData2) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr3[CL].GRNumArrAmount2<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L3 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am2P,EDI { Salva OFFS(GRNumArr3[CL].GRNumArrAmount2) ...}
{ ... (EDI) in Am2P }
Mov RC2,CL { Salva RC (CL) in RC2 }
(* ======================================== *)
(* = Ricerca del record TGRData1 ========= *)
(* ======================================== *)
Mov AL,RndN2
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr2[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData2.GRNumArr2-TYPE(TGRData1) { EDI <- OFFSET ... }
{ ... TGRData2.GRNumArr2-SizeOf(TGRData1) }
(* ---------------------------------------- *)
@@L2:Add EDI,TYPE(TGRData1) { EDI += SizeOf(TGRData1) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr2[CL].GRNumArrAmount1<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L2 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am1P,EDI { Salva OFFS(GRNumArr2[CL].GRNumArrAmount1) ...}
{ ... (EDI) in Am1P }
Mov RC1,CL { Salva RC (CL) in RC1 }
(* ======================================== *)
(* = Ricerca del record TGRData0 ========= *)
(* ======================================== *)
Mov AL,RndN1
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr1[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData1.GRNumArr1-TYPE(TGRData0) { EDI <- OFFSET ... }
{ ... TGRData1.GRNumArr1-SizeOf(TGRData0) }
(* ---------------------------------------- *)
@@L1:Add EDI,TYPE(TGRData0) { EDI += SizeOf(TGRData0) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr1[CL].GRNumArrAmount0<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L1 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov RC0,CL { Salva RC (CL) in RC0 }
(* ======================================== *)
(* = Ricerca del Bit selezionato ========= *)
(* ======================================== *)
Mov AL,RndN0
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{ DX: GRNumArr0.
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Mov DL,[EDI+OFFSET TGRData0.GRNumArr0] { DL <- TGRData0.GRNumArr0 }
(* ---------------------------------------- *)
@@L0:Inc CL { RC += 1 }
ShR DL,1 { GRNumArr0>>1 }
CmC { Se FCarry=0 ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L0 { Se VC<>0, ripete il ciclo }
(* ======================================== *)
Mov DL,1 { ... }
ShL DL,CL { ... DL <- 1<<RC }
Or [EDI+OFFSET TGRData0.GRNumArr0],DL { Marca il num. come già estratto}
(* ---------------------------------------- *)
Mov EDX,GRData8Ptr { Carica GRConfig in EDX }
Dec Byte Ptr [EDI] { TGRData0.GRNumArrAmount0 -= 1 }
JNE @@01 { Se TGRData0.GRNumArrAmount0<>0, salta }
Mov EDI,Am1P { Carica OFFS(TGRData1.GRNumArrAmount1) in EDI }
Dec Byte Ptr [EDI] { TGRData1.GRNumArrAmount1 -= 1 }
JNE @@01 { Se TGRData1.GRNumArrAmount1<>0, salta }
Mov EDI,Am2P { Carica OFFS(TGRData2.GRNumArrAmount2) in EDI }
Dec Byte Ptr [EDI] { TGRData2.GRNumArrAmount2 -= 1 }
JNE @@01 { Se TGRData2.GRNumArrAmount2<>0, salta }
Mov EDI,Am3P { Carica OFFS(TGRData3.GRNumArrAmount3) in EDI }
Dec Byte Ptr [EDI] { TGRData3.GRNumArrAmount3 -= 1 }
JNE @@01 { Se TGRData3.GRNumArrAmount3<>0, salta }
Mov EDI,Am4P { Carica OFFS(TGRData4.GRNumArrAmount4) in EDI }
Dec Byte Ptr [EDI] { TGRData4.GRNumArrAmount4 -= 1 }
JNE @@01 { Se TGRData4.GRNumArrAmount4<>0, salta }
Mov EDI,Am5P { Carica OFFS(TGRData5.GRNumArrAmount5) in EDI }
Dec Byte Ptr [EDI] { TGRData5.GRNumArrAmount5 -= 1 }
JNE @@01 { Se TGRData5.GRNumArrAmount5<>0, salta }
Mov EDI,Am6P { Carica OFFS(TGRData6.GRNumArrAmount6) in EDI }
Dec Byte Ptr [EDI] { TGRData6.GRNumArrAmount6 -= 1 }
JNE @@01 { Se TGRData6.GRNumArrAmount6<>0, salta }
Mov EDI,Am7P { Carica OFFS(TGRData7.GRNumArrAmount7) in EDI }
Dec Byte Ptr [EDI] { TGRData7.GRNumArrAmount7 -= 1 }
JNE @@01 { Se TGRData7.GRNumArrAmount7<>0, salta }
Dec Byte Ptr [EDX] { GRConfig^.GRNumArrAmount8 -= 1 }
(* ---------------------------------------- *)
@@01:MovZX EAX,RC7 { EAX <- pos. ("Real Count.") r. TGRData7 trov.}
ShL Al,3 { EAX <<= 3 }
Or AL,RC6 { EAX |= pos. ("Real Count.") r. TGRData6 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC5 { EAX |= pos. ("Real Count.") r. TGRData5 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC4 { EAX |= pos. ("Real Count.") r. TGRData4 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC3 { EAX |= pos. ("Real Count.") r. TGRData3 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC2 { EAX |= pos. ("Real Count.") r. TGRData2 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC1 { EAX |= pos. ("Real Count.") r. TGRData1 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC0 { EAX |= pos. ("Real Count.") r. TGRData0 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,CL { EAX |= pos. Bit selezionato }
(* ---------------------------------------- *)
Add EAX,[EDX+OFFSET TGRData8.GRNumMin8] { Somma GRConfig^.GRNumMin8 ... }
{ ... al numero cas. gen. }
(* ======================================== *)
@@00:Pop EDI { Ripristina il registro EDI dallo STACK }
End;
end.