home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / unity / d56 / FNDUTL.ZIP / Utils / cRandom.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  8.7 KB  |  268 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cRandom;
  3.  
  4. {                                                                              }
  5. { Revision history:                                                            }
  6. {   1999/11/07  v0.01  Added RandomSeed.                                       }
  7. {   1999/12/01  v0.02  Added RandomUniform.                                    }
  8. {   2000/01/23  v1.03  Added RandomPseudoWord.                                 }
  9. {   2000/07/13  v1.04  Fixed bug in RandomUniform reported by Andrew Driazgov  }
  10. {                      <andrey@asp.tstu.ru>                                    }
  11. {   2000/08/22  v1.05  Added RandomHex.                                        }
  12. {   2000/09/20  v1.06  Added more random states to RandomSeed.                 }
  13. {   2002/06/01  v3.07  Created cRandom unit from cSysUtils and cMaths.         }
  14. {                                                                              }
  15.  
  16. interface
  17.  
  18.  
  19.  
  20. {                                                                              }
  21. { RandomSeed                                                                   }
  22. {   Returns a random seed value, based on the Windows counter, the CPU counter }
  23. {   and the current date/time and other 'random' states.                       }
  24. {                                                                              }
  25. Function  RandomSeed : LongWord;
  26.  
  27. type
  28.   TGUID128 = Array [0..3] of LongWord;
  29.  
  30. Function  GenerateGUID32 : LongWord;
  31. Function  GenerateGUID64 : Int64;
  32. Function  GenerateGUID128 : TGUID128;
  33.  
  34.  
  35.  
  36. {                                                                              }
  37. { Uniform random number generator                                              }
  38. {   Returns a random number from a uniform density distribution (ie all number }
  39. {   have an equal probability of being 'chosen')                               }
  40. {   RandomFloat returns an random floating point value between 0 and 1.        }
  41. {   RandomPseudoWord returns a random word-like string.                        }
  42. {                                                                              }
  43. Function  RandomUniform : LongWord; overload;
  44. Function  RandomUniform (const N : Integer) : Integer; overload;
  45. Function  RandomBoolean : Boolean;
  46. Function  RandomInt64 : Int64;
  47. Function  RandomHex (const Digits : Integer = 8) : String;
  48. Function  RandomFloat : Extended;
  49. Function  RandomPseudoWord (const Length : Integer) : String;
  50.  
  51.  
  52.  
  53. implementation
  54.  
  55. uses
  56.   // Delphi
  57.   Windows,
  58.   SysUtils;
  59.  
  60.  
  61.  
  62. {                                                                              }
  63. { RandomSeed                                                                   }
  64. {                                                                              }
  65. Function RandomSeed : LongWord;
  66. var I            : Int64;
  67.     Ye, Mo, Da   : Word;
  68.     H, Mi, S, S1 : Word;
  69.   Begin
  70.     Result := $A5F04182;
  71.  
  72.     // Date
  73.     DecodeDate (Date, Ye, Mo, Da);
  74.     Result := Result xor Ye xor (Mo shl 16) xor (Da shl 24);
  75.  
  76.     // Time
  77.     DecodeTime (Time, H, Mi, S, S1);
  78.     Result := Result xor H xor (Mi shl 8) xor (S1 shl 16) xor (S shl 24);
  79.  
  80.     {$IFDEF OS_WIN32}
  81.     // Ticks since start-up
  82.     Result := Result xor GetTickCount;
  83.  
  84.     // CPU Frequency
  85.     if QueryPerformanceFrequency (I) then
  86.       Result := Result xor LongWord (I) xor LongWord (I shr 32);
  87.  
  88.     // CPU Counter
  89.     if QueryPerformanceCounter (I) then
  90.       Result := Result xor LongWord (I) xor LongWord (I shr 32);
  91.  
  92.     // Process
  93.     Result := Result xor GetCurrentProcess xor GetCurrentThread;
  94.     {$ENDIF}
  95.   End;
  96.  
  97. var
  98.   GUIDInit : Boolean = False;
  99.   GUIDBase : TGUID128 = (0, 0, 0, 0);
  100.  
  101. Procedure InitGUID;
  102. var I : Integer;
  103.   Begin
  104.     GUIDBase [0] := RandomSeed;
  105.     For I := 1 to 3 do
  106.       GUIDBase [I] := RandomUniform;
  107.     GUIDInit := True;
  108.   End;
  109.  
  110. Function GenerateGUID32 : LongWord;
  111.   Begin
  112.     if not GUIDInit then
  113.       InitGUID;
  114.     Result := GUIDBase [3];
  115.     GUIDBase [3] := LongWord (GUIDBase [3] + 1);
  116.   End;
  117.  
  118. Function GenerateGUID64 : Int64;
  119.   Begin
  120.     if not GUIDInit then
  121.       InitGUID;
  122.     Int64Rec (Result).Hi := GUIDBase [2];
  123.     Int64Rec (Result).Lo := GUIDBase [3];
  124.     GUIDBase [3] := LongWord (GUIDBase [3] + 1);
  125.   End;
  126.  
  127. Function GenerateGUID128 : TGUID128;
  128.   Begin
  129.     if not GUIDInit then
  130.       InitGUID;
  131.     Result := GUIDBase;
  132.     GUIDBase [3] := LongWord (GUIDBase [3] + 1);
  133.     if GUIDBase [3] = 0 then
  134.       GUIDBase [2] := LongWord (GUIDBase [2] + 1);
  135.     GUIDBase [1] := RandomUniform;
  136.   End;
  137.  
  138.  
  139.  
  140. { Random number generator from ACM Transactions on Modeling and Computer       }
  141. { Simulation 8(1) 3-30, 1990.  Supposedly it has a period of -1 + 2^19937.     }
  142. { The original was in C; this translation returns the same values as the       }
  143. { original.  It is called the Mersenne Twister.                                }
  144. { The following code was written by Toby Ewing <ewing@iastate.edu>, slightly   }
  145. { modified by Frank Heckenbach <frank@pascal.gnu.de>, again slightly modified  }
  146. { by David Butler <david@e.co.za> for use in Delphi. Bug fixes with reference  }
  147. { to the original code http://www.math.keio.ac.jp/~matumoto/emt.html, by       }
  148. { Andrew Driazgov <andrey@asp.tstu.ru>.                                        }
  149. { It was inspired by C code, released under the GNU Library General Public     }
  150. { License, written by Makoto Matsumoto <matumoto@math.keio.ac.jp> and          }
  151. { Takuji Nishimura, considering the suggestions by Topher Cooper and           }
  152. { Marc Rieffel in July-Aug 97.                                                 }
  153. const
  154.   N = 624; // Period parameters
  155.   M = 397;
  156.  
  157. var
  158.   mti : Integer;
  159.   mt  : Array [0..N - 1] of LongWord; // the array for the state vector
  160.   RandomUniformInitialized : Boolean = False;
  161.  
  162. { Set initial seeds to mt [N] using the generator Line 25 of Table 1 in        }
  163. { [KNUTH 1981, The Art of Computer Programming Vol. 2 (2nd Ed.), pp 102].      }
  164. Procedure RandomUniformInit (const Seed : LongWord);
  165. var I : Integer;
  166.   Begin
  167.     mt [0] := Seed;
  168.     For I := 1 to N - 1 do
  169.       mt [I] := LongWord (Int64 (69069) * mt [I - 1]);
  170.     mti := N;
  171.     RandomUniformInitialized := True
  172.   End;
  173.  
  174. Function RandomUniform : LongWord;
  175. const
  176.   Matrix_A = $9908B0DF; // constant vector a
  177.   T_Mask_B = $9D2C5680; // Tempering parameters
  178.   T_Mask_C = $EFC60000;
  179.   Up_Mask  = $80000000; // most significant w-r bits
  180.   Low_Mask = $7FFFFFFF; // least significant r bits
  181.   mag01    : Array [0..1] of LongWord = (0, Matrix_A);
  182.  
  183. var
  184.   y  : LongWord;
  185.   kk : Integer;
  186.  
  187.   Begin
  188.     if not RandomUniformInitialized then
  189.       RandomUniformInit (RandomSeed);
  190.     if mti >= N then { generate N words at one time }
  191.       begin
  192.         For kk := 0 to N - M - 1 do
  193.           begin
  194.             y := (mt [kk] and Up_Mask) or (mt [kk + 1] and Low_Mask);
  195.             mt [kk] := mt [kk + M] xor (y shr 1) xor mag01 [y and 1]
  196.           end;
  197.         For kk := N - M to N - 2 do
  198.           begin
  199.             y := (mt [kk] and Up_Mask) or (mt [kk + 1] and Low_Mask);
  200.             mt [kk] := mt [kk + M - N] xor (y shr 1) xor mag01 [y and 1]
  201.           end;
  202.         y := (mt [N - 1] and Up_Mask) or (mt [0] and Low_Mask);
  203.         mt [N - 1] := mt [M - 1] xor (y shr 1) xor mag01 [y and 1];
  204.         mti := 0
  205.       end;
  206.     y := mt [mti];
  207.     Inc (mti);
  208.     y := y xor (y shr 11);
  209.     y := y xor ((y shl 7) and T_Mask_B);
  210.     y := y xor ((y shl 15) and T_Mask_C);
  211.     y := y xor (y shr 18);
  212.     Result := y;
  213.   End;
  214.  
  215. Function RandomUniform (const N : Integer) : Integer;
  216.   Begin
  217.     if N = 0 then
  218.       Result := 0 else
  219.       Result := Integer (Int64 (RandomUniform) mod N);
  220.   End;
  221.  
  222. Function RandomBoolean : Boolean;
  223.   Begin
  224.     Result := RandomUniform and 1 = 1;
  225.   End;
  226.  
  227. Function RandomFloat : Extended;
  228.   Begin
  229.     Result := RandomUniform / High (LongWord);
  230.   End;
  231.  
  232. Function RandomInt64 : Int64;
  233.   Begin
  234.     Int64Rec (Result).Lo := RandomUniform;
  235.     Int64Rec (Result).Hi := RandomUniform;
  236.   End;
  237.  
  238. Function RandomHex (const Digits : Integer) : String;
  239. var I : Integer;
  240.   Begin
  241.     Result := '';
  242.     Repeat
  243.       I := Digits - Length (Result);
  244.       if I > 0 then
  245.         Result := Result + IntToHex (RandomUniform, 8);
  246.     Until I <= 0;
  247.     SetLength (Result, Digits);
  248.   End;
  249.  
  250. Function RandomPseudoWord (const Length : Integer) : String;
  251. const Vowels = 'AEIOUY';
  252.       Consonants = 'BCDFGHJKLMNPQRSTVWXZ';
  253. var I : Integer;
  254.   Begin
  255.     Assert (Length >= 0, 'RandomPseudoWord: Invalid Length parameter');
  256.     SetLength (Result, Length);
  257.     For I := 1 to Length do
  258.       Case RandomUniform (2) of
  259.         0 : Result [I] := Vowels [RandomUniform (6) + 1];
  260.         1 : Result [I] := Consonants [RandomUniform (20) + 1];
  261.       end;
  262.   End;
  263.  
  264.  
  265.  
  266. end.
  267.  
  268.