Random
Wed, 18 Jun 1997 12:59:48 +0200
I wrote a random unit that uses the same algorithm as BP does.
It produces exact the same random numbers as the Random function of
BP 7.0 (I heard, older BP versions used a different algorithm, though).
Just a couple of notes/questions:
- Is the DOS interrupt in Randomize call OK for DJGPP and EMX?
I'm not really sure if it's good, but it seems to work.
Any improvements welcome!
- The code is not meant as a "default" random procedure for gpc,
but only for BP compatibility.
- Of course, RandReal should have the same name as Random,
when function overloading exists.
- When range checking exists, NextRand must be compiled without it.
(That's why I put "{$W-,R-,W+}" in :-)
- The type declarations should be replaced by machine-independent
ones (or be predefined by the compiler in the future).
- Random produces exact the same random number sequence as BP's
integer random. RandReal gives the same values an BP's Random
for FPU types (e.g. Double). BP's Random for BP's own Real type
differs from that by 0.5 (doesn't really matter, just if someone
wants to compare the random values).
While writing it, I discovered some type casting bugs in gpc
concerning signed/unsigned integers:
program x;
var a:integer value -$80000000;
begin
Writeln(ShortWord((LongWord(a)*4) DIV $100000000)); {65534, should be 2}
Writeln(Word((LongWord(a)*4) DIV $100000000)); {-2, should be 2}
end.
Another thing is the implicit real->integer(!) conversion, e.g.
"Writeln(Integer(2.2))" works (and gives 2).
Is this required by the standard? Otherwise I don't think it should
work. At least, it shouldn't with "--borland-pascal".
Apropos of BP compatibility: I think many BP users wouldn't like to have
to put something like "{$ifdef __gpc__}uses system;{$endif}" in their
programs. Is there a way to do this easier? If not, could one be created
(perhaps a compiler switch that uses a given unit in all compiled files
automatically; though I don't think it should be set by default even
with "--borland-pascal", since System is a "contrib". But people could
then set an alias to
"gpc --automake --executable-file-name --borland-pascal --uses="system"
or so...)?
---
UNIT Rand;
INTERFACE
TYPE
Cardinal=Word;
Card16=ShortWord;
Card32=Word;
Card64=LongWord;
Int32=Integer;
VAR RandSeed:Int32 VALUE 0;
FUNCTION Random(Range:Card16):Card16;
FUNCTION RandReal:Real;
PROCEDURE Randomize;
IMPLEMENTATION
{$W-,R-,W+}
PROCEDURE NextRand;
BEGIN
RandSeed:=$8088405*RandSeed+1
END;
FUNCTION Random(Range:Card16):Card16;
BEGIN
NextRand;
Random:=(Card32(RandSeed)*Card64(Range)) DIV $100000000
END;
FUNCTION RandReal:Real;
BEGIN
NextRand;
RandReal:=RandSeed/4294967296.0+0.5
END;
{$IFDEF __DJGPP__}{$DEFINE DOS}{$ENDIF}
{$IFDEF __EMX__}{$DEFINE DOS}{$ENDIF}
{$IFDEF DOS}
PROCEDURE Randomize;
VAR RandSeedLoHi:PACKED RECORD Lo,Hi:Card16 END ABSOLUTE RandSeed;
BEGIN
ASM("movb $44,%%ah
int $0x21"
:"=c"(RandSeedLoHi.Lo),
"=d"(RandSeedLoHi.Hi)
::"eax","ebx","ecx","edx","esi","edi")
END;
{$ELSE}
FUNCTION Rand:Integer; C;
PROCEDURE SRand(Seed:Cardinal); C;
FUNCTION GetPID:Integer; C;
PROCEDURE Randomize;
BEGIN
SRand(GetPID);
RandSeed:=Rand
END;
{$ENDIF}
END.
--
Frank Heckenbach, Erlangen, Germany
heckenb@mi.uni-erlangen.de
Turbo Pascal: http://www.mi.uni-erlangen.de/~heckenb/programs.htm
Internet links: http://www.mi.uni-erlangen.de/~heckenb/links.htm
Frank Heckenbach (heckenb@mi.uni-erlangen.de)
HTML conversion by Lluís de Yzaguirre i Maura
Institut de Lingüística Aplicada -
Universitat "Pompeu Fabra"
e-mail: de_yza@upf.es