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