From 39c37311eef0c4f2d42edfcfeba3809b917bf086 Mon Sep 17 00:00:00 2001 From: Norayr Chilingarian Date: Wed, 22 Jan 2014 00:43:16 +0400 Subject: [PATCH] ported ulmConclusions, ulmRandomGenerators Former-commit-id: d5a6f185c61f9ec64c0c5e680a60f5f448c73763 --- makefile | 2 + makefile.gnuc.armv6j | 2 + makefile.gnuc.armv6j_hardfp | 2 + makefile.gnuc.armv7a_hardfp | 2 + makefile.gnuc.powerpc | 2 + makefile.gnuc.x86 | 2 + makefile.gnuc.x86_64 | 2 + src/lib/ulm/ulmConclusions.Mod | 169 +++++++++++ src/lib/ulm/ulmRandomGenerators.Mod | 419 ++++++++++++++++++++++++++++ 9 files changed, 602 insertions(+) create mode 100644 src/lib/ulm/ulmConclusions.Mod create mode 100644 src/lib/ulm/ulmRandomGenerators.Mod diff --git a/makefile b/makefile index cb2d9c25..4e3dc160 100644 --- a/makefile +++ b/makefile @@ -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 diff --git a/makefile.gnuc.armv6j b/makefile.gnuc.armv6j index 1126d884..d156db9c 100644 --- a/makefile.gnuc.armv6j +++ b/makefile.gnuc.armv6j @@ -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 diff --git a/makefile.gnuc.armv6j_hardfp b/makefile.gnuc.armv6j_hardfp index 81c452a6..85b10e3b 100644 --- a/makefile.gnuc.armv6j_hardfp +++ b/makefile.gnuc.armv6j_hardfp @@ -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 diff --git a/makefile.gnuc.armv7a_hardfp b/makefile.gnuc.armv7a_hardfp index 5ca4b414..c6fede7a 100644 --- a/makefile.gnuc.armv7a_hardfp +++ b/makefile.gnuc.armv7a_hardfp @@ -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 diff --git a/makefile.gnuc.powerpc b/makefile.gnuc.powerpc index a35ddb72..573b9f5e 100644 --- a/makefile.gnuc.powerpc +++ b/makefile.gnuc.powerpc @@ -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 diff --git a/makefile.gnuc.x86 b/makefile.gnuc.x86 index 9930ce3c..637152b2 100644 --- a/makefile.gnuc.x86 +++ b/makefile.gnuc.x86 @@ -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 diff --git a/makefile.gnuc.x86_64 b/makefile.gnuc.x86_64 index df0ba347..64a6b4e7 100644 --- a/makefile.gnuc.x86_64 +++ b/makefile.gnuc.x86_64 @@ -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 diff --git a/src/lib/ulm/ulmConclusions.Mod b/src/lib/ulm/ulmConclusions.Mod new file mode 100644 index 00000000..2d0a6ade --- /dev/null +++ b/src/lib/ulm/ulmConclusions.Mod @@ -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. diff --git a/src/lib/ulm/ulmRandomGenerators.Mod b/src/lib/ulm/ulmRandomGenerators.Mod new file mode 100644 index 00000000..cb63a9a5 --- /dev/null +++ b/src/lib/ulm/ulmRandomGenerators.Mod @@ -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.