Switch to unified view

a b/RandomLib.mod.m2pp
1
IMPLEMENTATION MODULE RandomLib;
2
3
  (*========================================================================*)
4
  (* HINWEIS : Bitte nur die Datei RandomLib.mod.m2pp editieren             *)
5
  (*========================================================================*)
6
  (* Es sind 2 Versionen enthalten die mit                                  *)
7
  (*                                                                        *)
8
  (*   m2pp -D __{Parameter}__ < RandomLib.mod.m2pp > RandomLib.mod         *)
9
  (*                                                                        *)
10
  (* mit Parameter = {XDS|GM2} erzeugt werden koennen.                      *)
11
  (*                                                                        *)
12
  (*   XDS    : Der Export von Objekten aus lokalen Modulen wird mit        *)
13
  (*            "IMPORT" angezeigt - das scheint nicht ganz "regelkonform"  *)
14
  (*   GM2    : Normales "EXPORT" wird genutzt (ELSE-Fall).                 *)
15
  (*                                                                        *)
16
  (* ansonsten gibt es keine Aenderungen am Quellcode                       *)
17
  (*------------------------------------------------------------------------*)
18
  (* Dieses Modul stellt verschiedene uniforme Pseudozufallszahlen-         *)
19
  (* generatoren zur Verfuegung.                                            *)
20
  (* This module providing several uniform pseudorandom number generators.  *)
21
  (*------------------------------------------------------------------------*)
22
  (* Letzte Aenderung:                                                      *)
23
  (*                                                                        *)
24
  (* 03.06.93, MRi: Erstellen der ersten Version von RanMar / RanMarInit    *)
25
  (* 13.10.15, MRi: Ersetzen von LFLOAT(LTRUNC( durch LowLong.intpart(      *)
26
  (* 21.01.16, MRi: Einfuehren von InitZufallSysT,                          *)
27
  (*                Verbesserung der Doku im Definitionsmodul               *)
28
  (* 06.09.15, MRi: Uebersetzen von ACM 133 von Algol60 nach Modula-2       *)
29
  (* 02.12.15, MRi: Einfuegen von InitRandom fuer ACM 133                   *)
30
  (* 22.01.16, MRi: Einfuegen von ACM133 in Modul Random                    *)
31
  (* 22.01.16, MRi: Erstellen der ersten Version des CERN Library RanLux    *)
32
  (*                Random number generators - uebersetzt von Fortran 77    *)
33
  (*                nach Modula-2.                                          *)
34
  (* 23.01.16, MRi: Kleinere Anpassungen an RanLux, EA hinzugefuegt         *)
35
  (*                RanLux,RLuxGo gegen F77 Version mit 8*10**6 generierten *)
36
  (*                Zufallszahlen erfolgreich getestet.                     *)
37
  (* 23.01.16, MRi: Integrieren von RanLux in Random, umbenennen des Moduls *)
38
  (*                in RandomLib, testen der Restart-Optionen von RanLux    *)
39
  (* 04.04.16, MRi: Initialisierungsroutinen von Random und Zufall ueber-   *)
40
  (*                arbeitet um sicherzustellen dass nicht mit 0            *)
41
  (*                initialisiert wird.                                     *)
42
  (* 12.04.16, MRi: Initialisierungsroutinen von Random und Zufall ueber-   *)
43
  (*                arbeitet damit nach kuerzerer Zeit eine neue Zufalls-   *)
44
  (*                zahlenreihe abgerufen werden kann.                      *)
45
  (*------------------------------------------------------------------------*)
46
  (* Offene Punkte                                                          *)
47
  (*                                                                        *)
48
  (* - Wieso funktioniert ein Aufruf von RLuxGo mit K1,K2 # 0 nicht bei     *)
49
  (*   luxlev 3 & 4 - dann schlaegt auch der Restart mit RLuxAt/RLuxGo      *)
50
  (*   fehl (merkwuergerweise sind die ersten Werte noch richtig), nicht    *)
51
  (*   aber der mit RLuxUt/RLuxGo&RLuxIn. Wenn K1+K2=0 ist alles gut.       *)
52
  (*   Dir Fortran-Routine verhaelt sich aber auch so ...                   *)
53
  (* - Herausnahme der debug-optionen in RanLux (ersetzen durch             *)
54
  (*   Praeprozessor-direktiven).                                           *)
55
  (*------------------------------------------------------------------------*)
56
  (* Implementation : Michael Riedl                                         *)
57
  (* Licence        : GNU Lesser General Public License (LGPL)              *)
58
  (*------------------------------------------------------------------------*)
59
60
  (* $Id: RandomLib.mod.m2pp,v 1.7 2018/01/16 09:19:51 mriedl Exp mriedl $ *)
61
62
FROM SysClock IMPORT maxSecondParts,DateTime,CanGetClock,GetClock;
63
              IMPORT LowLong;
64
              IMPORT LongMath;
65
              IMPORT Errors;
66
              IMPORT TIO;
67
68
MODULE ACM133;
69
70
IMPORT maxSecondParts,DateTime,CanGetClock,GetClock;
71
72
<* IF (__XDS__) THEN *>
73
IMPORT Random,InitRandom; (* EXPORT *)
74
<* ELSE *>
75
EXPORT Random,InitRandom;
76
<* END *>
77
78
VAR   X : ARRAY [1..2] OF INTEGER;
79
80
PROCEDURE Random(a,b : LONGREAL) : LONGREAL;
81
82
          (* ACM Algorithm 133  *)
83
84
          CONST mult     = 5; 
85
                mscale   = 1048576; 
86
                topscale = 32768;
87
                mrecip   = 3.435973E-10; (* 2.0**(-35) *)
88
                toprecip = 3.051757E-05; (* 2.0**(-15) *)
89
BEGIN
90
      X[1] := mult * X[1];
91
      X[2] := mult * X[2];
92
93
      (* Add overflow from X[2] and remove it from X[2] *)
94
95
      IF (X[2] >= mscale) THEN
96
        X[1] := X[1] + X[2] DIV mscale;
97
        X[2] := X[2] MOD mscale;
98
      END;
99
100
      (* Possibly need to tidy up X[1] *)
101
102
      IF (X[1] >= topscale) THEN
103
        X[1] := X[1] MOD topscale;
104
      END;
105
106
      (* Generate a real value in the required range *)
107
108
      RETURN (VAL(LONGREAL,X[1])*toprecip + VAL(LONGREAL,X[2])*mrecip) *
109
             (b-a) + a;
110
END Random;
111
112
PROCEDURE InitRandom();
113
114
          VAR dt     : DateTime;
115
              T,frac : CARDINAL;
116
              x      : REAL;
117
BEGIN
118
      IF CanGetClock() THEN
119
        GetClock(dt);
120
        frac := dt.fractions + 1;
121
        IF (frac = 1) THEN frac:=maxSecondParts; END;
122
(*
123
        T:=(((dt.hour  + 1)*60 + (dt.minute + 1))*60 +
124
            (dt.second + 1))*maxSecondParts + frac;
125
 *)
126
        T:=((dt.second + 1))*maxSecondParts + frac;
127
        x:=VAL(REAL,T); (* / VAL(REAL,24*360*maxSecondParts); *)
128
        WHILE (x >= 10.0) DO x:=x / 3.14152927; END;
129
        WHILE (x <  10.0) DO x:=x * 10.00; END;
130
        X[1]:=TRUNC(x);
131
        X[2]:=TRUNC(4096.0*(x-VAL(REAL,X[1])));
132
      ELSE
133
        X[1]:=VAL(INTEGER,Random(1.0,111.0)) DIV VAL(INTEGER,Random(1.0,111.0));
134
        X[2]:=VAL(INTEGER,Random(5.0,555.0)) MOD VAL(INTEGER,Random(5.0,555.0));
135
      END;
136
END InitRandom;
137
138
BEGIN
139
      X[1]:=13;
140
      X[2]:=19;
141
END ACM133;
142
143
MODULE RandomMar;
144
145
IMPORT Errors;
146
147
<* IF (__XDS__) THEN *>
148
IMPORT RanMarInit,RanMar; (* EXPORT *)
149
<* ELSE *>
150
EXPORT RanMarInit,RanMar;
151
<* END *>
152
153
VAR       U       : ARRAY [1..97] OF LONGREAL;
154
          c,cd,cm : LONGREAL;
155
          i97,j97 : CARDINAL;
156
157
PROCEDURE RanMarInit(ij,kl : CARDINAL);
158
159
      VAR i,j,k,l,m : CARDINAL;
160
          ii,jj     : CARDINAL;
161
          s,t       : LONGREAL;
162
163
BEGIN
164
      IF (ij > 31328) OR (kl  > 30081) THEN
165
        Errors.ErrOut("(ij IN {0..31328}) oder ");
166
        Errors.FatalError("(kl IN {0..30081}) nicht erfuellt (Random.RanMarInit)");
167
      END;
168
169
      i := ((ij DIV 177) MOD 177) + 2;
170
      j := ( ij          MOD 177) + 2;
171
      k := ((kl DIV 169) MOD 178) + 1;
172
      l := ( kl          MOD 169);
173
174
      FOR ii:= 1 TO 97 DO
175
        s := 0.0;
176
        t := 0.5;
177
        FOR jj:=1 TO 24 DO
178
          m := ((i*j MOD 179)*k) MOD 179;
179
          i := j;
180
          j := k;
181
          k := m;
182
          l := (53*l+1) MOD 169;
183
          IF (((l*m) MOD 64) >= 32) THEN s:=s + t; END;
184
          t := 0.5 * t;
185
        END;
186
        U[ii] := s;
187
      END;
188
189
      c  :=   362436.0 / 16777216.0;
190
      cd :=  7654321.0 / 16777216.0;
191
      cm := 16777213.0 / 16777216.0;
192
193
      i97 := 97;
194
      j97 := 33;
195
END RanMarInit;
196
197
PROCEDURE RanMar() : LONGREAL;
198
199
          VAR  uni : LONGREAL;
200
201
BEGIN
202
      uni := U[i97] - U[j97];
203
      IF ( uni < 0.0 ) THEN uni:=uni + 1.0; END;
204
      U[i97] := uni;
205
      DEC(i97); IF (i97 = 0) THEN i97 := 97; END;
206
      DEC(j97); IF (j97 = 0) THEN j97 := 97; END;
207
      c := c - cd;
208
      IF (c < 0.0) THEN c:=c + cm; END;
209
      uni := uni - c;
210
      IF (uni < 0.0) THEN uni:=uni + 1.0; END;
211
      RETURN uni;
212
END RanMar;
213
214
BEGIN
215
      RanMarInit(1802,9373);
216
END RandomMar;
217
218
MODULE ZUFALL;
219
220
IMPORT LowLong;
221
IMPORT maxSecondParts,DateTime,CanGetClock,GetClock;
222
IMPORT TIO;
223
224
<* IF (__XDS__) THEN *>
225
IMPORT InitZufallSysT,InitZufall,Zufall; (* EXPORT *)
226
<* ELSE *>
227
EXPORT InitZufallSysT,InitZufall,Zufall;
228
<* END *>
229
230
CONST     Order = 13;
231
232
VAR       XV    : ARRAY [1..Order] OF LONGREAL;
233
234
PROCEDURE InitZufall;
235
236
          VAR i : CARDINAL;
237
BEGIN
238
      FOR i:=3 TO Order DO XV[i]:=0.0; END;
239
      XV[1]:=0.14159265E+00;
240
      XV[2]:=0.70710678E+00;
241
END InitZufall;
242
243
PROCEDURE InitZufallSysT;
244
245
          VAR i      : CARDINAL;
246
              dt     : DateTime;
247
              T,frac : CARDINAL;
248
              x      : REAL;
249
BEGIN
250
      IF CanGetClock() THEN
251
        GetClock(dt);
252
        frac := dt.fractions + 1;
253
        IF (frac = 1) THEN frac:=maxSecondParts; END;
254
        T:= (dt.second + 1)*maxSecondParts + frac;
255
        x:=VAL(REAL,T);
256
        WHILE (x >= 10.0) DO x:=x / 3.1415927; END;
257
        WHILE (x <  10.0) DO x:=x*10.0; END;
258
        XV[1]:=VAL(LONGREAL,TRUNC(x));
259
        XV[2]:=VAL(LONGREAL,TRUNC(1000.0*(x-VAL(REAL,XV[1]))));
260
        XV[1]:=0.14159265*XV[1];
261
        XV[2]:=0.70710678*XV[2];
262
        FOR i:=3 TO Order DO XV[i]:=0.0; END;
263
      ELSE
264
        InitZufall;
265
      END;
266
END InitZufallSysT;
267
268
PROCEDURE Zufall() : LONGREAL;
269
270
          VAR  i : CARDINAL;
271
272
BEGIN
273
      FOR i:=1 TO Order-1 DO
274
        XV[i+1]:=(XV[i+1]+XV[i]) - LowLong.intpart(XV[i+1]+XV[i]);
275
      END;
276
      RETURN XV[Order];
277
END Zufall;
278
279
BEGIN
280
      InitZufall();
281
END ZUFALL;
282
283
PROCEDURE IRandom(a,b : CARDINAL) : CARDINAL; (* MR, 12.02.2015 *)
284
285
          VAR min : CARDINAL;
286
BEGIN
287
      IF (b >= a) THEN min:=a; a:=b-a; ELSE min:=b; a:=a-b; END;
288
      RETURN VAL(CARDINAL,(LongMath.round(VAL(LONGREAL,a)*Zufall()))) + min;
289
END IRandom;
290
291
292
MODULE LuxaryRandom;
293
294
IMPORT Errors;
295
IMPORT TIO;
296
IMPORT SeedVektor;
297
298
<* IF (__XDS__) THEN *>
299
IMPORT RLuxGo,RLuxAt,RLuxUt,RLuxIn,RanLux; (* EXPORT *)
300
<* ELSE *>
301
EXPORT RLuxGo,RLuxAt,RLuxUt,RLuxIn,RanLux;
302
<* END *>
303
304
  (*------------------------------------------------------------------------*)
305
  (* All code derived from CERN Program Library SUBROUTINE RANLUX           *)
306
  (* Translated from FORTRAN77 to Modula-2 by Michael Riedl, Jan. 2016      *)
307
  (*------------------------------------------------------------------------*)
308
309
CONST debug  = TRUE;
310
311
CONST MaxLev = 4; 
312
      LXdflt = 3; 
313
      TwoP12 = 4096.0; 
314
      JSdflt = 314159265; 
315
      IGiga  = 1000000000; 
316
      Itwo24 = 16777216; (* 2**24 *)
317
      ICons  = 2147483563;
318
319
VAR   ndskip                 : ARRAY[0..MaxLev] OF INTEGER; (* save *)
320
      seeds                  : ARRAY[1..24] OF LONGREAL;    (* save *)
321
      iseeds                 : ARRAY[1..24] OF INTEGER;     (* save *)
322
      next                   : ARRAY[1..24] OF INTEGER;     (* save *)
323
324
      notyet                 : BOOLEAN;  (* save *)
325
      luxlev                 : INTEGER;  (* save *)
326
      i24,j24,in24           : INTEGER;  (* save *)
327
      kount,mkount           : INTEGER;  (* save *)
328
      nskip                  : INTEGER;  (* save *)
329
      twom24,twom12          : LONGREAL; (* save *)
330
      carry                  : LONGREAL; (* save *)
331
332
      uni                    : LONGREAL;
333
      inseed,jseed           : INTEGER;
334
 
335
PROCEDURE RLuxGo(Lux,InS,K1,K2 : INTEGER);
336
337
          VAR  izip,izip2   : INTEGER;
338
               inner,iouter : INTEGER;
339
               i,k,ilx,isk  : INTEGER;
340
BEGIN
341
      IF (Lux < 0) THEN
342
        luxlev := LXdflt
343
      ELSIF (Lux <= MaxLev) THEN
344
        luxlev := Lux
345
      ELSIF (Lux < 24) OR (Lux > 2000) THEN
346
        luxlev := MaxLev;
347
        Errors.ErrOut('RanLux ILLEGAL Luxury RLuxGo (not in 24 .. 2000) ');
348
      ELSE
349
        luxlev := Lux;
350
        FOR ilx:=0 TO MaxLev DO
351
          IF (Lux = (ndskip[ilx] + 24)) THEN
352
            luxlev := ilx;
353
          END;
354
        END;
355
      END;
356
      IF (luxlev <= MaxLev) THEN
357
        nskip := ndskip[luxlev];
358
        IF debug THEN
359
          TIO.WrStr(' RanLux luxury level set by RLuxGo : ');
360
          TIO.WrInt(luxlev,2); TIO.WrStr(', P = '); TIO.WrInt(nskip+24,1);
361
          TIO.WrLn;
362
        END;
363
      ELSE
364
        nskip := luxlev - 24;
365
        IF debug THEN
366
          TIO.WrStr(' RanLux P-value set by RLuxGo to :');
367
          TIO.WrInt(luxlev,1); TIO.WrLn;
368
        END;
369
      END;
370
      in24 := 0;
371
      IF (InS < 0) THEN
372
        Errors.ErrOut('Illegal initialization by RLuxGo, negative input seed');
373
      END;
374
      IF (InS > 0) THEN
375
        jseed := InS;
376
        IF debug THEN
377
          TIO.WrStr(' RanLux initialized by RLuxGo from seeds ');
378
          TIO.WrInt(jseed,1); TIO.WrChar(",");
379
          TIO.WrInt(K1,1);    TIO.WrChar(","); 
380
          TIO.WrInt(K2,1);    TIO.WrLn;
381
        END;
382
      ELSE
383
        jseed := JSdflt;
384
        IF debug THEN
385
          TIO.WrStr(' RanLux initialized by RLuxGo form default seed');
386
          TIO.WrLn;
387
        END;
388
      END;
389
      inseed := jseed;
390
      notyet:=FALSE;
391
      twom24 := 1.0;
392
      FOR i:=1 TO 24 DO
393
        twom24 := twom24*0.5;
394
        k := jseed DIV 53668;
395
        jseed:=40014*(jseed - k*53668) - k*12211;
396
        IF (jseed < 0) THEN
397
           jseed:=jseed + ICons;
398
        END;
399
        iseeds[i]:= (jseed MOD Itwo24);
400
      END;
401
      twom12 := twom24*4096.0;
402
      FOR i:=1 TO 24 DO;
403
        seeds[i]:=VAL(LONGREAL,iseeds[i])*twom24;
404
        next[i]:=i - 1;
405
      END;
406
      next[1]:=24;
407
      i24 := 24;
408
      j24 := 10;
409
      carry := 0.0;
410
      IF (seeds[24] = 0.0) THEN
411
        carry := twom24;
412
      END;
413
      (* If restarting at a break point, skip K1 + IGiga*K2 *)
414
      (* Note that this is the number of numbers delivered to *)
415
      (* the user PLUS the number skipped (if luxury .GT. 0). *)
416
      kount  := K1;
417
      mkount := K2;
418
      IF (K1+K2 # 0) THEN
419
        FOR iouter:=1 TO K2+1 DO
420
          inner := IGiga;
421
          IF (iouter = (K2+1)) THEN
422
            inner := K1;
423
          END;
424
          FOR isk:=1 TO inner DO
425
            uni:=seeds[j24] - seeds[i24] - carry;
426
            IF (uni < 0.0) THEN
427
              uni:=uni + 1.0;
428
              carry := twom24;
429
            ELSE
430
              carry := 0.0;
431
            END;
432
            seeds[i24]:=uni;
433
            i24 := next[i24];
434
            j24 := next[j24];
435
          END;
436
        END;
437
        (* Get the right value of IN24 by direct calculation *)
438
        in24 := kount MOD (nskip+24);
439
        IF (mkount > 0) THEN
440
          izip := IGiga MOD (nskip+24);
441
          izip2 := mkount*izip + in24;
442
          in24 := izip2 MOD (nskip+24);
443
        END;
444
        (* Now IN24 had better be between zero and 23 inclusive *)
445
        IF (in24 > 23) THEN
446
          Errors.ErrOut('Error in restarting with RLuxGo:');
447
          Errors.WriteString('          The values ');
448
          Errors.WriteInt(InS); Errors.WriteChar(",");
449
          Errors.WriteInt(K1);  Errors.WriteChar(",");
450
          Errors.WriteInt(K2);
451
          Errors.WriteString(' cannot occur at luxury level ');
452
          Errors.WriteInt(luxlev);
453
          Errors.WriteLn; Errors.WriteLn;
454
          in24 := 0;
455
        END;
456
      END; (* IF (K1+K2 # 0) *)
457
END RLuxGo;
458
459
PROCEDURE RLuxAt(VAR Lout,InOut,K1,K2 : INTEGER);
460
461
BEGIN
462
      Lout:=luxlev;
463
      InOut:=inseed;
464
      K1:=kount;
465
      K2:=mkount;
466
END RLuxAt;
467
468
PROCEDURE RLuxUt(VAR ISDext : SeedVektor);
469
470
          VAR i : INTEGER;
471
BEGIN
472
     FOR i:=1 TO 24 DO
473
       ISDext[i] := TRUNC(seeds[i]*TwoP12*TwoP12);
474
     END;
475
     ISDext[25] := i24 + 100*j24 + 10000*in24 + 1000000*luxlev;
476
     IF (carry > 0.0) THEN
477
       ISDext[25] := -ISDext[25];
478
     END;
479
END RLuxUt;
480
481
PROCEDURE RLuxIn(VAR ISDext : SeedVektor);
482
483
          VAR i,isd : INTEGER;
484
BEGIN
485
      notyet:=FALSE;
486
      twom24 := 1.0;
487
      FOR i:=1 TO 24 DO
488
        next[i] := i-1;
489
        twom24 := twom24*0.5;
490
      END;
491
      next[1] := 24;
492
      twom12 := twom24*4096.0;
493
      IF debug THEN
494
        TIO.WrStr(' Full initialization of RanLux with 25 integers:');
495
        TIO.WrLn;
496
        FOR i:=1 TO 25 DO
497
          TIO.WrInt(ISDext[i],1);
498
          IF ((i MOD 5) = 0) THEN TIO.WrLn; ELSE TIO.WrChar(','); END;
499
        END;
500
        TIO.WrLn;
501
      END;
502
      FOR i:=1 TO 24 DO
503
        seeds[i] := VAL(LONGREAL,ISDext[i])*twom24;
504
      END;
505
      carry := 0.0;
506
      IF (ISDext[25] < 0) THEN
507
        carry := twom24;
508
      END;
509
      isd := ABS(ISDext[25]);
510
      i24 := (isd MOD 100);
511
      isd := isd DIV 100;
512
      j24 := (isd MOD 100);
513
      isd := isd DIV 100;
514
      in24 := (isd MOD 100);
515
      isd := isd DIV 100;
516
      luxlev := isd;
517
      IF (luxlev <= MaxLev) THEN
518
        nskip := ndskip[luxlev];
519
        IF debug THEN
520
          TIO.WrStr(' RanLux Luxury level set by RLuxIn to : ');
521
          TIO.WrInt(luxlev,1); TIO.WrLn;
522
        END;
523
      ELSIF (luxlev >= 24) THEN
524
        nskip := luxlev-24;
525
        IF debug THEN
526
          TIO.WrStr(' RanLux P-value set by RLuxIn to : ');
527
          TIO.WrInt(luxlev,1); TIO.WrLn;
528
        END;
529
      ELSE
530
        nskip := ndskip[MaxLev];
531
        IF debug THEN
532
          TIO.WrStr(' RanLux illegal Luxury RLuxIn : ');
533
          TIO.WrInt(luxlev,1); TIO.WrLn;
534
        END;
535
        luxlev := MaxLev;
536
      END;
537
      inseed := -1;
538
END RLuxIn;
539
540
PROCEDURE RanLux(VAR RVec : ARRAY OF LONGREAL;
541
                     LenV : INTEGER);
542
543
          VAR i,k,ivec,isk : INTEGER;
544
BEGIN
545
      (* NOTYET is .TRUE. if no initialization has been performed yet. *)
546
      (* Default Initialization by Multiplicative Congruential         *)
547
      IF (notyet) THEN
548
        notyet := FALSE;
549
        jseed  := JSdflt;
550
        inseed := JSdflt;
551
        IF debug THEN
552
          TIO.WrStr(' RanLux default initialization : ');
553
          TIO.WrInt(jseed,1); TIO.WrLn;
554
        END;
555
        luxlev := LXdflt;
556
        nskip := ndskip[luxlev];
557
        in24 := 0;
558
        kount := 0;
559
        mkount := 0;
560
        IF debug THEN
561
          TIO.WrStr(' RanLux default Luxury level =  ');
562
          TIO.WrInt(luxlev,1);
563
          TIO.WrStr(', p ='); TIO.WrInt(nskip+24,1); TIO.WrLn;
564
        END;
565
        twom24 := 1.0;
566
        FOR i:=1 TO 24 DO
567
          twom24 := twom24*0.5;
568
          k := jseed DIV 53668;
569
          jseed := 40014*(jseed-k*53668) - k*12211;
570
          IF (jseed < 0) THEN
571
            jseed:=jseed + ICons;
572
          END;
573
          iseeds[i] := (jseed MOD Itwo24);
574
        END;
575
        twom12 := twom24*4096.0;
576
        FOR i:=1 TO 24 DO
577
          seeds[i] := VAL(LONGREAL,iseeds[i])*twom24;
578
          next[i] := i-1;
579
        END;
580
        next[1] := 24;
581
        i24 := 24;
582
        j24 := 10;
583
        carry := 0.0;
584
        IF (seeds[24] = 0.0) THEN
585
          carry := twom24;
586
        END;
587
      END; (* IF notyet *)
588
589
      (* The Generator proper: "Subtract-with-borrow", as proposed by       *)
590
      (* Marsaglia and Zaman, Florida State University, March, 1989         *)
591
592
      FOR ivec:=0 TO LenV-1 DO
593
        uni := seeds[j24] - seeds[i24] - carry;
594
        IF (uni < 0.0) THEN
595
          uni:=uni + 1.0;
596
          carry := twom24 
597
        ELSE
598
          carry := 0.0;
599
        END;
600
        seeds[i24] := uni;
601
        i24 := next[i24];
602
        j24 := next[j24];
603
        RVec[ivec] := uni;
604
        (* small numbers (with less than 12 "significant" bits) are "padded". *)
605
        IF (uni < twom12) THEN
606
          RVec[ivec]:=RVec[ivec] + twom24*seeds[j24];
607
          (* and zero is forbidden in case someone takes a logarithm *)
608
          IF (RVec[ivec] = 0.0) THEN
609
            RVec[ivec] := twom24*twom24;
610
          END;
611
        END;
612
        (* Skipping to luxury. As proposed by Martin Luscher. *)
613
        in24:=in24 + 1;
614
        IF (in24 = 24) THEN
615
          in24 := 0;
616
          kount:=kount + nskip;
617
          FOR isk:=1 TO nskip DO
618
            uni := seeds[j24] - seeds[i24] - carry;
619
            IF (uni < 0.0) THEN
620
              uni:=uni + 1.0;
621
              carry := twom24;
622
            ELSE
623
              carry := 0.0;
624
            END;
625
            seeds[i24] := uni;
626
            i24 := next[i24];
627
            j24 := next[j24];
628
          END;
629
        END;
630
      END;
631
      kount:=kount + LenV;
632
      IF (kount >= IGiga) THEN
633
        mkount:=mkount + 1;
634
        kount:=kount - IGiga;
635
      END;
636
END RanLux;
637
638
BEGIN
639
      notyet := TRUE;    (* save *)
640
      luxlev := LXdflt;  (* save xxx *)
641
      in24   := 0;       (* save *)
642
      kount  := 0;       (* save xxx *)
643
      mkount := 0;       (* save xxx *)
644
      inseed := JSdflt;  (* xxx *)
645
 
646
      i24   := 24;       (* save *)
647
      j24   := 10;       (* save *)
648
      carry := 0.0;      (* save *)
649
 
650
      ndskip[0] :=   0;  (* save *)
651
      ndskip[1] :=  24;
652
      ndskip[2] :=  73;
653
      ndskip[3] := 199;
654
      ndskip[4] := 365;
655
END LuxaryRandom;
656
657
END RandomLib.