home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
LANGUAGS
/
PASCAL
/
TAUSGEN3.PQS
/
TAUSGEN3.PAS
Wrap
Pascal/Delphi Source File
|
2000-06-30
|
12KB
|
392 lines
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.
}