home *** CD-ROM | disk | FTP | other *** search
- program Tausgen ;
-
- {
- Demonstration of Tausworthe Pseudorandom Number Generator
- 30 April 1985
- David P Kirschbaum, Toad Hall
- 7573 Jennings Lane, Fayetteville NC 28303
- on ARPANet: ABN.ISCAMS@USC-ISID
- See extracts from Professor Thesen's paper (the source of this code) at
- the end of this program.
-
- Expect an initial delay during the initialization of the byte table and
- offset pointers when the program actually runs. During actual implementation
- in a program, the table would be initialized only once (until you wanted to
- reseed again, anyway).
-
- If using my simple screen display version below, you have flow control.
- Enter any key to pause, and enter RETURN to continue. (Your system may
- stop on its own occasionally if your system XOFFs high-speed printing to the
- console. Just enter RETURN to continue.)
-
- Enter Q or q to end.
- }
-
- {Relax string parameter checking}
-
- {V$-}
-
- Type
- Line = string[79] ;
- Menu = string[25] ;
-
-
- const
- pminusl = 97 ; {p = 98; q = 27}
- maxbit = 255 ;
- maxs = 26 ;
- Selection : array[1..4] of Menu =
- ('1 Random Number Display ' ,
- '2 Speed Run (no display)' ,
- '3 Distribution Display ' ,
- '4 Quit ') ;
- var
- Ch : Char ;
- Sentence : Line ;
- BlankLine : Line ;
- Halted : Boolean ;
- Quit : Boolean ;
- Error : Boolean ;
- f,s : Integer ;
- x,y : Integer ;
- count : Integer ;
- prandom : Integer ;
- choice : Integer ;
- ByteTable : array[0..pminusl]of byte ;
- RCounter : array[0..maxbit] of Integer ;
-
- procedure CenterPrint(Sentence : Line) ;
- var
- Centered : Line ;
-
- begin
- Centered := BlankLine ;
- y := (80 - Length(Sentence)) div 2 ;
- Insert(Sentence,Centered,y) ;
- Writeln(Centered) ;
- end ;
-
-
- procedure PlotXY(var number : integer; value : integer) ;
-
- begin
- x := (number mod 12) * 4 + 12 ;
- y := (number div 12) + 2 ;
- GoToXY(x,y) ;
- Write(value:4) ;
- end ; {PlotXY}
-
-
- procedure CheckUser ;
-
- begin
- if KeyPressed then
- begin
- GoToXY(1,24) ;
- Read(Ch) ;
- Quit := Ch in ['Q', 'q'] ;
- end ; {KeyPressed}
- end ; {CheckUser}
-
- procedure ContPrompt ;
-
- begin
- Writeln ;
- GoToXY(1,22) ;
- CenterPrint('Hit any key to continue: ' ) ;
- Writeln ;
- GoToXY(54,22) ;
- Repeat until KeyPressed = True ;
- end ;
-
- procedure TauInit(var f,s : integer) ;
- var
- BitIndex : integer ;
- WorkTable : array[0..pminusl]of byte ;
-
- begin
- for count := 0 to pminusl do
- begin
- ByteTable[count] := maxbit ;
- WorkTable[count] := 0 ;
- end ; {count loop}
- f := pminusl ;
- s := maxs ;
- Quit := False ;
- for BitIndex := 1 to 16 do
- begin
- CheckUser ;
- If NOT Quit then
- begin
- for count := 1 to 9800 do
- begin
- if f < pminusl then
- f := f + 1
- else
- f := 0 ;
- if s < pminusl then
- s := s + 1
- else
- s := 0 ;
- ByteTable[f] := ByteTable[f] xor ByteTable[s] ;
- end; {count loop}
- if BitIndex > 8 then
- begin
- ClrScr ;
- Writeln ;
- Writeln('Loop ',BitIndex) ;
- for count := 0 to pminusl do
- begin
- if odd(ByteTable[count]) then
- WorkTable[count] := (WorkTable[count] div 2) + 128
- else
- WorkTable[count] := WorkTable[count] div 2 ;
- ByteTable[count] := ByteTable[count] div 2 ;
- PlotXY(count,WorkTable[count]) ;
- end; {count loop}
- end ; {BitIndex > 8}
- end ; {not Quit}
- end ; {BitIndex loop}
- ClrScr ;
- CenterPrint('Final Byte Table.') ;
- for count := 0 to pminusl do
- begin
- ByteTable[count] := WorkTable[count] ;
- PlotXY(count,ByteTable[count]) ;
- end; {count loop}
- f := pminusl ;
- s := maxs ;
- end ; {TauInit}
-
-
- function RByte : byte ;
- begin
- if f < pminusl then
- f := f + 1
- else
- f := 0 ;
- if s < pminusl then
- s := s + 1
- else
- s := 0 ;
- RByte := ByteTable[f] ;
- ByteTable[f] := ByteTable[f] xor ByteTable[s] ;
- end ; {RByte}
-
-
- {main program [Toad Hall]}
- begin
- FillChar(BlankLine,79,chr(32)) ;
- ClrScr ;
- CenterPrint('A Toad Hall Demonstration.') ;
- CenterPrint('of a Tausworthe Pseudorandom Number Generator.') ;
- CenterPrint('as described by Thesen et al.') ;
- Writeln ;
- CenterPrint('Beginning table initialization.') ;
- TauInit(f,s) ;
- ContPrompt ;
- ClrScr ;
- Writeln ;
- CenterPrint('Initialization complete.') ;
- Writeln ;
- for x := 1 to 4 do
- CenterPrint(Selection[x]) ;
- Writeln ;
- Quit := False ;
- Error := True ;
- repeat
- GoToXY(30,10) ;
- Write('Enter Selection (1-4): ') ;
- Readln(choice) ;
- if choice in [1..4] then
- Error := False ;
- if choice = 4 then
- Quit := True ;
- until Error = False ;
-
- If NOT Quit then
- begin
- ClrScr ;
- CenterPrint('Beginning random number generation.') ;
- for prandom := 0 to maxbit do
- RCounter[prandom] := 0 ;
-
- { This is a screen display so you (human) can see the numbers. Comment
- this out, and use the next segment if you want clock timing. Add in your
- own file-related stuff if you want to collect lots of numbers for some sort
- of statistical analysis. Easy... but YOU can do it!
- }
-
- if choice = 1 then
- repeat
- for y := 5 to 23 do
- begin
- If NOT Quit then
- begin
- for x := 1 to 16 do
- begin
- GoToXY(x * 4,y) ;
- Write(RByte:4) ;
- end; {x}
- CheckUser ;
- end ; {NOT Quit}
- end; {y}
- until Quit = True ; {choice 1}
-
- {And if you want to do some timing loops - this sucker is FAST!
- Kludge in any system clock you have at the beginning and end of this
- next routine, bring it on line instead of the display one above, and
- do some timing. On my Z80B CP/M system (Morrow Decision I), wristwatch
- timing looked like 8 or 9 seconds for the 32000 loop. Prof. Thesen
- reported 8 seconds on an IBM-PC.}
-
- if choice = 2 then
- begin
- CenterPrint('30 000 random numbers.') ;
- Writeln ;
- CenterPrint('The big hand is pointing to .') ;
- for count := 1 to 32000 do
- prandom := RByte ;
- CenterPrint('The big hand is pointing to .') ;
- for x := 1 to 20 do
- Write(' ') ;
- Write('Completed with count = ',count) ;
- Writeln(', and last number = ',prandom) ;
- end ; {choice 2}
-
- {
- And if you want a down-and-dirty analysis of random number distribution,
- try this one ...
- }
-
- if choice = 3 then
- repeat
- CheckUser ;
- prandom := RByte ;
- if RCounter[prandom] < maxbit then
- RCounter[prandom] := RCounter[prandom] + 1
- else RCounter[prandom] := 0 ;
- PlotXY(prandom,RCounter[prandom]) ;
- until Quit = True ; {choice 3}
-
- end ; {not Quit}
-
- GoToXY(1,23) ;
- Writeln ;
- Writeln ;
- CenterPrint('Terminating.') ;
- end.
-
- {
- Algorithms extracted from
- "Some Efficient Random Number Generators for Microcomputers"
- by Arne Thesen, Shanshan Sun and Tzyh-Jong Wang
- Industrial Engineering Department
- University of Wisconsin-Madison
-
- (Released to the Public Domain by Professor Thesen, 23 April 1985
- (message on file at Toad Hall))
-
- This is a Tausworthe Generator. Extracts from Prof. Thesen's paper, the
- implementing demonstration code, and some comments...
-
- by David Kirschbaum, Toad Hall (ABN.ISCAMS@USC-ISID
- "A Tausworthe generator
-
- "Tausworthe [5] has suggested a different approach to the generation of
- pseudo-random integers. This procedure, which operates directly on bits
- to form a stream of random bits, has been shown to produce random number
- sequences that (1) have improved statistical properties over LC [linear
- congruential] generators, and (2) have an arbitrarily long period independent
- of the word size of the computer used.
-
- "Tausworthe generators are not in widespread use. This could be because they
- are difficult to implement efficiently in a higher level language, or because
- their improved statistical properties are of marginal utility on larger
- computers. On microcomputers, the situation is quite different. Here the
- improvement in period length and in statistical properties is quite
- substantial, and well written Tausworthe generators are not necessarily
- more time consuming than other classes of generators.
-
- "Algorithm
-
- The basic procedure of a Tausworthe type generator is illustrated in
- Figure 1:
-
- B[i-p] B[i-r] B[i]
- B = . . x . . . . x . . . . x . . . . .
- | | |
- +-->xor<--+ |
- | |
- +--------------+
-
- "Figure 1: Relationship between bits in a Tausworthe
- generated bit stream.
-
- "Here B is defined as a sequence of bits, and the relationship between
- individual bits in the sequence is defined in Algorithm 2:
-
- B[i] = B[i-r] XOR B[i-p]
-
- where: i = any integer
- r , p = fixed integers with 0<r<p.
- XOR = the exclusive OR operator
- yielding 0 if the terms are
- equal and 1 if they are not.
-
- "Algorithm 2: Tausworthe generator
-
- "When r and p are properly selected (as primitive trimodals [8]), the maximum
- period of the stream (B) is 2**p - 1.
-
- "Implementation
-
- "In Program 3 we present a FORTRAN implementation of the Tausworthe based on
- an idea first proposed by Lewis and Payne [3]. To avoid the need to access
- individual bits, the algorithm maintains 15 independent and parallel streams
- of bits, and the exclusive OR operation is performed on all bits at once.
- Since each of the independent bit streams have a period of 2**p - 1, the
- resulting stream of integers will also have a period of 2**p - 1."
-
- [Algorithm omitted - Toad Hall]
-
- "BIBLIOGRAPHY [segment - Toad Hall]
- ...
- 5. Tausworthe, R.C., Random Numbers Generated by
- Linear Recurrence, Modulo Two, Math. Comp. 19
- (1965) 201-209.
-
- 6. Thesen, Arne, An Efficient Generator of Uniformly
- Distributed Random Deviates Between Zero and One.
- Technical Report. Mathematics Research Center,
- University of Wisconsin-Madison, 1983. To appear
- in Simulation.
-
- 7. Thesen, Arne and Tzyh-Jong Wang, Some Efficient
- Random Number Generators for Micro Computers. MRC
- Technical Summary Report #2562. Mathematics Research
- Center, University of Wisconsin-Madison, 1983.
-
- 8. Zierler, Niel and John Brillhart, On Primitive
- Trinomials (Mod 2), Information and Control,
- Vol. 13 pp 541-554, 1968."
-
- Toad Hall Notes
-
- In the Pascal code from Prof. Thesen et al, a random byte (expressed as a
- integer 0-255) is generated from eight parallel streams of random bits. It
- uses the xor operator built in to TurboPascal.
-
- The initial seed values pminusl and s were (I believe) chosen because of
- their long period. Not fully understanding all this yet, I expect there are
- other suitable seeds (perhaps more of the primitive trimodals referred to in
- the basic paper), or perhaps ANY value between 0 and 97 for pminusl, and any
- lesser value for s? (Sorry, guys, if my thinking is kind of dumb - I'm no
- mathemetician - just a cut-and-try hacker.)
-
- Prof. Thesen states the Tausworthe algorithm is not constrained by the word
- size of the computer. This leads me to believe we might be able to implement
- more than the 8 random bit streams he used in this example, but I expect it
- will impact severely on the code speed.
- }