ported ulmConclusions, ulmRandomGenerators

This commit is contained in:
Norayr Chilingarian 2014-01-22 00:43:16 +04:00
parent 7b7c968aac
commit d5a6f185c6
9 changed files with 602 additions and 0 deletions

View file

@ -210,6 +210,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -209,6 +209,8 @@ stage6:
$(VOCSTATIC) -sP ulmCipherOps.Mod
$(VOCSTATIC) -sP ulmBlockCiphers.Mod
$(VOCSTATIC) -sP ulmAsymmetricCiphers.Mod
$(VOCSTATIC) -sP ulmConclusions.Mod
$(VOCSTATIC) -sP ulmRandomGenerators.Mod
#pow32 libs
$(VOCSTATIC) -sP powStrings.Mod

View file

@ -0,0 +1,169 @@
(* Ulm's Oberon Library
Copyright (C) 1989-1994 by University of Ulm, SAI, D-89069 Ulm, Germany
----------------------------------------------------------------------------
Ulm's Oberon Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either version
2 of the License, or (at your option) any later version.
Ulm's Oberon Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
----------------------------------------------------------------------------
E-mail contact: oberon@mathematik.uni-ulm.de
----------------------------------------------------------------------------
$Id: Conclusions.om,v 1.2 1994/07/05 12:50:01 borchert Exp $
----------------------------------------------------------------------------
$Log: Conclusions.om,v $
Revision 1.2 1994/07/05 12:50:01 borchert
formatting of error messages depends now on the indentation width
of StreamDisciplines
Revision 1.1 1994/02/23 07:46:17 borchert
Initial revision
----------------------------------------------------------------------------
AFB 11/91
----------------------------------------------------------------------------
*)
MODULE ulmConclusions;
(* convert errors and events into conclusions,
i.e. a final message and reaction
*)
IMPORT Errors := ulmErrors, Events := ulmEvents, Process := ulmProcess, RelatedEvents := ulmRelatedEvents, StreamDisciplines := ulmStreamDisciplines,
Streams := ulmStreams, Strings := ulmStrings, Write := ulmWrite;
VAR
handlerSet*: Errors.HandlerSet;
errors*: INTEGER; (* number of errors *)
fatalcode*: INTEGER; (* exit code on fatal events *)
(* private variables *)
cmdName: Process.Name; (* should be sufficient for a base name *)
cmdNameLen: INTEGER; (* Strings.Len(cmdName) *)
(* private procedures *)
PROCEDURE GeneralHandler(event: Events.Event; kind: Errors.Kind);
VAR
width: INTEGER;
BEGIN
IF event # NIL THEN
Write.IndentS(Streams.stderr);
Write.StringS(Streams.stderr, cmdName);
Write.StringS(Streams.stderr, ": ");
width := SHORT(Strings.Len(cmdName) + 2);
StreamDisciplines.IncrIndentationWidth(Streams.stderr, width);
IF kind # Errors.message THEN
Write.StringS(Streams.stderr, Errors.kindText[kind]);
Write.StringS(Streams.stderr, ": ");
END;
Errors.Write(Streams.stderr, event); Write.LnS(Streams.stderr);
StreamDisciplines.IncrIndentationWidth(Streams.stderr, -width);
END;
CASE kind OF
| Errors.error: INC(errors);
| Errors.fatal: Process.Exit(fatalcode);
| Errors.bug: Process.Abort;
ELSE
(* no further actions *)
END;
END GeneralHandler;
PROCEDURE AbortHandler(event: Events.Event);
BEGIN
GeneralHandler(event, Errors.bug);
END AbortHandler;
PROCEDURE Init;
VAR
messageKind: Errors.Kind;
BEGIN
fatalcode := 1;
errors := 0;
cmdName := Process.name;
cmdNameLen := SHORT(Strings.Len(cmdName));
messageKind := 0;
Errors.CreateHandlerSet(handlerSet);
WHILE messageKind < Errors.nkinds DO
Errors.InstallHandler(handlerSet, messageKind, GeneralHandler);
INC(messageKind);
END;
Events.AbortHandler(AbortHandler);
END Init;
(* public procedures *)
PROCEDURE CatchEvent*(type: Events.EventType; kind: Errors.Kind);
BEGIN
Errors.CatchEvent(handlerSet, kind, type);
END CatchEvent;
PROCEDURE ConcludeS*(s: Streams.Stream;
object: RelatedEvents.Object; kind: Errors.Kind;
text: ARRAY OF CHAR);
VAR
queue: RelatedEvents.Queue;
width: INTEGER;
PROCEDURE ReverseQueue(VAR queue: RelatedEvents.Queue);
VAR
ptr, prev, next: RelatedEvents.Queue;
BEGIN
ptr := queue; prev := NIL;
WHILE ptr # NIL DO
next := ptr.next;
ptr.next := prev;
prev := ptr;
ptr := next;
END;
queue := prev;
END ReverseQueue;
BEGIN
RelatedEvents.GetQueue(object, queue);
Write.IndentS(s);
Write.StringS(s, cmdName); Write.StringS(s, ": ");
IF kind # Errors.message THEN
Write.StringS(s, Errors.kindText[kind]); Write.StringS(s, ": ");
END;
IF text # "" THEN
Write.StringS(s, text); Write.StringS(s, ": ");
END;
IF queue = NIL THEN
Write.StringS(s, "*no error messages found*"); Write.LnS(s);
ELSE
width := cmdNameLen + (* ": " *) 2;
StreamDisciplines.IncrIndentationWidth(s, width);
(* convert FIFO into LIFO *)
ReverseQueue(queue);
LOOP
Errors.Write(s, queue.event); Write.LnS(s);
queue := queue.next;
(**)IF queue = NIL THEN EXIT END;
Write.IndentS(s);
END;
StreamDisciplines.IncrIndentationWidth(s, -width);
END;
GeneralHandler(NIL, kind);
END ConcludeS;
PROCEDURE Conclude*(object: RelatedEvents.Object; kind: Errors.Kind;
text: ARRAY OF CHAR);
BEGIN
ConcludeS(Streams.stderr, object, kind, text);
END Conclude;
BEGIN
Init;
END ulmConclusions.

View file

@ -0,0 +1,419 @@
(* Ulm's Oberon Library
Copyright (C) 1989-1994 by University of Ulm, SAI, D-89069 Ulm, Germany
----------------------------------------------------------------------------
Ulm's Oberon Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either version
2 of the License, or (at your option) any later version.
Ulm's Oberon Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
----------------------------------------------------------------------------
E-mail contact: oberon@mathematik.uni-ulm.de
----------------------------------------------------------------------------
$Id: RandomGener.om,v 1.9 2004/03/09 21:44:12 borchert Exp $
----------------------------------------------------------------------------
$Log: RandomGener.om,v $
Revision 1.9 2004/03/09 21:44:12 borchert
unpredictable added to the standard set of PRNGs
Revision 1.8 2004/03/06 07:22:09 borchert
Init asserts that the sequence has been registered at Services
Revision 1.7 1998/02/14 22:04:09 martin
Missing calls of Services.Init and Services.CreateType added.
Revision 1.6 1997/10/11 21:22:03 martin
assertion in ValS added, obsolete variable removed
Revision 1.5 1997/10/10 16:26:49 martin
RestartSequence added, range conversions improved,
default implementation replaced.
Revision 1.4 1997/04/01 16:33:41 borchert
major revision of Random:
- module renamed to RandomGenerators
- abstraction instead of simple implementation (work by Frank Fischer)
Revision 1.3 1994/09/01 18:15:41 borchert
bug fix: avoid arithmetic overflow in ValS
Revision 1.2 1994/08/30 09:48:00 borchert
sequences added
Revision 1.1 1994/02/23 07:25:30 borchert
Initial revision
----------------------------------------------------------------------------
original implementation by AFB 2/90
conversion to abstraction by Frank B.J. Fischer 3/97
----------------------------------------------------------------------------
*)
MODULE ulmRandomGenerators;
(* Anyone who considers arithmetical
methods of producing random digits
is, of course, in a state of sin.
- John von Neumann (1951)
*)
IMPORT
Clocks := ulmClocks, Disciplines := ulmDisciplines, Objects := ulmObjects, Operations := ulmOperations, Process := ulmProcess, Services := ulmServices, Times := ulmTimes,
Types := ulmTypes, S := SYSTEM;
TYPE
Sequence* = POINTER TO SequenceRec;
Int32ValSProc* = PROCEDURE (sequence: Sequence): Types.Int32;
LongRealValSProc* = PROCEDURE (sequence: Sequence): LONGREAL;
RewindSequenceProc* = PROCEDURE (sequence: Sequence);
RestartSequenceProc* = PROCEDURE (sequence, seed: Sequence);
SetValSProc* = PROCEDURE (sequence: Sequence; value: Operations.Operand);
CONST
int32ValS* = 0; longRealValS* = 1; rewindSequence* = 2; restartSequence* = 3;
TYPE
CapabilitySet* = SET; (* of [int32ValS..restartSequence] *)
Interface* = POINTER TO InterfaceRec;
InterfaceRec* =
RECORD
(Objects.ObjectRec)
int32ValS* : Int32ValSProc; (* at least one of ... *)
longRealValS* : LongRealValSProc; (* ... these required *)
rewindSequence* : RewindSequenceProc; (* optional *)
restartSequence*: RestartSequenceProc; (* optional *)
END;
SequenceRec* =
RECORD
(Services.ObjectRec)
(* private components *)
if : Interface;
caps: CapabilitySet;
END;
VAR
std* : Sequence; (* default sequence *)
seed*: Sequence; (* sequence of seed values *)
unpredictable*: Sequence;
(* reasonably fast sequence of unpredictable values;
is initially NIL
*)
(* ----- private definitions ----- *)
CONST
modulus1 = 2147483647; (* a Mersenne prime *)
factor1 = 48271; (* passes spectral test *)
quotient1 = modulus1 DIV factor1; (* 44488 *)
remainder1 = modulus1 MOD factor1; (* 3399; must be < quotient1 *)
modulus2 = 2147483399; (* a non-Mersenne prime *)
factor2 = 40692; (* also passes spectral test *)
quotient2 = modulus2 DIV factor2; (* 52774 *)
remainder2 = modulus2 MOD factor2; (* 3791; must be < quotient2 *)
TYPE
DefaultSequence = POINTER TO DefaultSequenceRec;
DefaultSequenceRec =
RECORD
(SequenceRec)
seed1, seed2: LONGINT;
value1, value2: LONGINT;
END;
ServiceDiscipline = POINTER TO ServiceDisciplineRec;
ServiceDisciplineRec =
RECORD
(Disciplines.DisciplineRec)
setValS: SetValSProc;
END;
VAR
service : Services.Service;
serviceDiscID: Disciplines.Identifier;
sequenceType,
defaultSequenceType: Services.Type;
(* ----- bug workaround ----- *)
PROCEDURE Entier(value: LONGREAL): LONGINT;
VAR
result: LONGINT;
BEGIN
result := ENTIER(value);
IF result > value THEN
DEC(result);
END;
RETURN result
END Entier;
(* ----- exported procedures ----- *)
PROCEDURE Init*(sequence: Sequence; if: Interface; caps: CapabilitySet);
(* initialize sequence *)
VAR
type: Services.Type;
BEGIN
ASSERT((if.int32ValS # NIL) OR (if.longRealValS # NIL));
ASSERT(~(int32ValS IN caps) OR (if.int32ValS # NIL));
ASSERT(~(longRealValS IN caps) OR (if.longRealValS # NIL));
ASSERT(~(rewindSequence IN caps) OR (if.rewindSequence # NIL));
Services.GetType(sequence, type); ASSERT(type # NIL);
sequence.if := if;
sequence.caps := caps;
END Init;
PROCEDURE Capabilities*(sequence: Sequence): CapabilitySet;
(* tell which procedures are implemented *)
BEGIN
RETURN sequence.caps
END Capabilities;
PROCEDURE RewindSequence*(sequence: Sequence);
(* re-examine sequence *)
BEGIN
ASSERT(rewindSequence IN sequence.caps);
sequence.if.rewindSequence(sequence);
END RewindSequence;
PROCEDURE RestartSequence*(sequence, seed: Sequence);
(* restart sequence with new seed values *)
BEGIN
ASSERT(restartSequence IN sequence.caps);
sequence.if.restartSequence(sequence, seed);
END RestartSequence;
PROCEDURE ^ LongRealValS*(sequence: Sequence): LONGREAL;
PROCEDURE Int32ValS*(sequence: Sequence): Types.Int32;
(* get random 32-bit value from sequence *)
VAR
real: LONGREAL;
BEGIN
IF int32ValS IN sequence.caps THEN
RETURN sequence.if.int32ValS(sequence)
ELSE
real := LongRealValS(sequence);
RETURN SHORT(Entier( (1. - real - real) * MIN(Types.Int32) ))
END;
END Int32ValS;
PROCEDURE Int32Val*(): Types.Int32;
(* get random 32-bit value from std sequence *)
BEGIN
RETURN Int32ValS(std);
END Int32Val;
PROCEDURE LongRealValS*(sequence: Sequence): LONGREAL;
(* get a uniformly distributed longreal value in [0..1) *)
BEGIN
IF longRealValS IN sequence.caps THEN
RETURN sequence.if.longRealValS(sequence)
ELSE
RETURN 0.5 +
Int32ValS(sequence) / (0. - MIN(Types.Int32) - MIN(Types.Int32))
END;
END LongRealValS;
PROCEDURE LongRealVal*(): LONGREAL;
(* get a uniformly distributed longreal value in [0..1) *)
BEGIN
RETURN LongRealValS(std)
END LongRealVal;
PROCEDURE RealValS*(sequence: Sequence): REAL;
(* get a uniformly distributed real value in [0..1) *)
BEGIN
RETURN SHORT(LongRealValS(sequence))
END RealValS;
PROCEDURE RealVal*(): REAL;
(* get a uniformly distributed real value in [0..1) *)
BEGIN
RETURN SHORT(LongRealValS(std))
END RealVal;
PROCEDURE ValS*(sequence: Sequence; low, high: LONGINT): LONGINT;
(* get a uniformly distributed integer in [low..high] *)
BEGIN
ASSERT(low <= high);
RETURN Entier( low + LongRealValS(sequence) * (1. + high - low) )
END ValS;
PROCEDURE Val*(low, high: LONGINT): LONGINT;
(* get a uniformly distributed integer in [low..high] *)
BEGIN
RETURN ValS(std, low, high)
END Val;
PROCEDURE FlipS*(sequence: Sequence): BOOLEAN;
(* return TRUE or FALSE *)
BEGIN
IF int32ValS IN sequence.caps THEN
RETURN sequence.if.int32ValS(sequence) >= 0
ELSE
RETURN sequence.if.longRealValS(sequence) >= 0.5
END;
END FlipS;
PROCEDURE Flip*(): BOOLEAN;
(* return TRUE or FALSE *)
BEGIN
RETURN FlipS(std)
END Flip;
PROCEDURE Support*(type: Services.Type; setValS: SetValSProc);
(* support service for type *)
VAR
serviceDisc: ServiceDiscipline;
BEGIN
NEW(serviceDisc);
serviceDisc.id := serviceDiscID;
serviceDisc.setValS := setValS;
Disciplines.Add(type, serviceDisc);
Services.Define(type, service, NIL);
END Support;
PROCEDURE SetValS*(sequence: Sequence; value: Operations.Operand);
(* store random value from sequence into already initialized value *)
VAR
baseType : Services.Type;
serviceDisc: ServiceDiscipline;
ok : BOOLEAN;
BEGIN
Services.GetSupportedBaseType(value, service, baseType);
ok := Disciplines.Seek(baseType, serviceDiscID, S.VAL(Disciplines.Discipline, serviceDisc));
ASSERT(ok);
serviceDisc.setValS(sequence, value);
END SetValS;
PROCEDURE SetVal*(value: Operations.Operand);
(* store random value from std sequence into already initialized value *)
BEGIN
SetValS(std, value);
END SetVal;
(* ----- DefaultSequence ----- *)
PROCEDURE CongruentialStep(VAR value1, value2: LONGINT);
BEGIN
value1 :=
factor1 * (value1 MOD quotient1) - remainder1 * (value1 DIV quotient1);
IF value1 < 0 THEN
INC(value1, modulus1);
END;
value2 :=
factor2 * (value2 MOD quotient2) - remainder2 * (value2 DIV quotient2);
IF value2 < 0 THEN
INC(value2, modulus2);
END;
END CongruentialStep;
PROCEDURE DefaultSequenceValue(sequence: Sequence): LONGREAL;
VAR
value: LONGINT;
BEGIN
WITH sequence: DefaultSequence DO
CongruentialStep(sequence.value1, sequence.value2);
value := sequence.value1 - sequence.value2;
IF value <= 0 THEN
INC(value, modulus1);
END;
RETURN (value - 1.) / (modulus1 - 1.)
END;
END DefaultSequenceValue;
PROCEDURE DefaultSequenceRewind(sequence: Sequence);
BEGIN
WITH sequence: DefaultSequence DO
sequence.value1 := sequence.seed1;
sequence.value2 := sequence.seed2;
END;
END DefaultSequenceRewind;
PROCEDURE DefaultSequenceRestart(sequence, seed: Sequence);
BEGIN
WITH sequence: DefaultSequence DO
sequence.seed1 := ValS(seed, 1, modulus1-1);
sequence.seed2 := ValS(seed, 1, modulus2-1);
sequence.value1 := sequence.seed1;
sequence.value2 := sequence.seed2;
END;
END DefaultSequenceRestart;
PROCEDURE CreateDefaultSequences;
VAR
mySeed, myStd: DefaultSequence;
if: Interface;
daytime: Times.Time;
timeval: Times.TimeValueRec;
count: LONGINT;
PROCEDURE Hash(str: ARRAY OF CHAR): LONGINT;
VAR
index,
val: LONGINT;
BEGIN
val := 27567352;
index := 0;
WHILE str[index] # 0X DO
val := (val MOD 16777216) * 128 +
(val DIV 16777216 + ORD(str[index])) MOD 128;
INC(index);
END; (*WHILE*)
RETURN val
END Hash;
BEGIN
(* define interface for all default sequences *)
NEW(if);
if.longRealValS := DefaultSequenceValue;
if.rewindSequence := DefaultSequenceRewind;
if.restartSequence := DefaultSequenceRestart;
(* fake initial randomness using some portably accessible sources *)
NEW(mySeed);
Services.Init(mySeed, defaultSequenceType);
Init(mySeed, if, {longRealValS});
Clocks.GetTime(Clocks.system, daytime);
Times.GetValue(daytime, timeval);
(* extract those 31 bits from daytime that are most likely to vary *)
mySeed.value1 := timeval.usec * 2048 + timeval.second MOD 65536 + 1;
(* generate 31 more bits from the process name *)
mySeed.value2 := Hash(Process.name) MOD (modulus2 - 1) + 1;
(* scramble these values *)
count := 0;
WHILE count < 4 DO
CongruentialStep(mySeed.value1, mySeed.value2);
INC(count);
END;
(* mix them together *)
DefaultSequenceRestart(mySeed, mySeed);
seed := mySeed;
(* now use our seed to initialize std sequence *)
NEW(myStd);
Services.Init(myStd, defaultSequenceType);
Init(myStd, if, {longRealValS, rewindSequence, restartSequence});
DefaultSequenceRestart(myStd, mySeed);
std := myStd;
unpredictable := NIL;
END CreateDefaultSequences;
BEGIN
serviceDiscID := Disciplines.Unique();
Services.Create(service, "RandomGenerators");
Services.CreateType(sequenceType, "RandomGenerators.Sequence", "");
Services.CreateType(defaultSequenceType, "RandomGenerators.DefaultSequence",
"RandomGenerators.Sequence");
CreateDefaultSequences;
END ulmRandomGenerators.