2017-10-20

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

L'Ecuyer LCG3 Pseudo-Random Number Generation

Algorithm creator(s)

Pierre L'Ecuyer


PB author(s)

Information Management Systems, Inc.


Description

An excellent composite pseudo-RNG with an extremely long period ( >8*10^12 )


Note

Source: Pierre L'Ecuyer: Communications of the ACM, 31, 6, June 88


Source

http://www.infoms.com/bsp/list7-10.zip


See also


Source Code

Download source code file lecuyer.bas (Right-click -> "Save as ...")

DECLARE SUB SeedStore(Operation$, seed1%, seed2%, seed3%)

' RanSeed
' Seed the L'Ecuyer LCG3 Pseudo Random Number Generator

' Input: Seed1%  Seed value generator 1. Value: 1..32362 (inclusive)
'        Seed2%  Seed value generator 2. Value: 1..31726 (inclusive)
'        Seed3%  Seed value generator 3. Value: 1..31656 (inclusive)

SUB RanSeed(Seed1%, Seed2%, Seed3%) Public

  '*** Force lowerlimits to prevent lockup
  IF Seed1% < 1 THEN Seed1%=1
  IF Seed2% < 1 THEN Seed2%=1
  IF Seed3% < 1 THEN Seed3%=1

  '*** Force upperlimits to prevent wrong max. seeds
  IF Seed1%>32362 THEN Seed1%=32362
  IF Seed2%>31726 THEN Seed2%=31726
  IF Seed3%>31656 THEN Seed3%=31656

  '*** Store seeds
  SeedStore "S", Seed1%, Seed2%, Seed3%

END SUB 'RanSeed

' RanGetSeed
' Read the seedvalues. Read-Only

SUB RanGetSeed(Seed1%, Seed2%, Seed3%) Public

  SeedStore "R", Seed1%, Seed2%, Seed3%

END SUB 'RanGetSeed

' Rand
' Composite Pseudo Random Number Generator
' Source: Pierre L'Ecuyer, Communications of the ACM, 31, 6, June 88
' An excellent Pseudo RNG with an extremely long period ( >8*10^12).

' Before using this routine, initialize by calling RanSeed

' Returns: single precision uniformly distributed random number
' from range  0.0 ... 1.0

FUNCTION Rand!() Public

  LOCAL seed1%, seed2%, seed3%, itemp%, icombined%

  ' *** Read current seeds
  SeedStore "R", seed1%, seed2%, seed3%

  '*** First algorithm
  itemp% = seed1% \ 206
  seed1% = 157 * (seed1% - itemp%*206) - itemp%*21
  IF seed1% < 0 THEN seed1% = seed1% + 32363

  '*** Second algorithm
  itemp% = seed2% \ 217
  seed2% = 146 * (seed2% - itemp%*217) -itemp%*45
  IF seed2% < 0 THEN seed2% = seed2% + 31727

  '*** Third algorithm
  itemp%= seed3% \ 222
  seed3%= 142 * (seed3% - itemp%*222) - itemp%*133
  IF seed3% <0 THEN seed3% = seed3% + 31657

  '*** Combine the random number generators
  icombined% = seed1% - seed2%
  IF icombined% > 706 THEN icombined% = icombined% - 32362
  icombined% = icombined% + seed3%
  IF icombined% < 1 THEN icombined% = icombined% + 32362

  '*** Scale to single precision value (0.0 , 1.0]
  Rand! = icombined% * 3.0899E-5

  '*** Update internal seeds
  SeedStore "S", seed1%, seed2%, seed3%

END FUNCTION 'Rand

' SeedStore
' Store and Retrieve seeds
'   Input: Operation$ "R"=Retrieve seedvalues, "S"=Store seedvalues
'   Input/output: Seed1%, Seed2%, Seed3%

SUB SeedStore(Operation$, seed1%, seed2%, seed3%) Private
  STATIC static_seed1%, static_seed2%, static_seed3%, static_init?

  SELECT CASE UCASE$(Operation$)
    CASE "S"              'Store seed values
      static_init?  = 1      'Set initialization flag
      static_seed1% = seed1%
      static_seed2% = seed2%
      static_seed3% = seed3%
    CASE "R"              'Retrieve seed values
      IF static_init? = 1 THEN   'Initialized; use seeds
        seed1% = static_seed1%
        seed2% = static_seed2%
        seed3% = static_seed3%
      ELSE                   ' Not initialized. Force random seeds
        RANDOMIZE TIMER
        static_seed1% = 1 + INT( RND * 32362 )
        static_seed2% = 1 + INT( RND * 31726 )
        static_seed3% = 1 + INT( RND * 31656 )
        static_init?  = 1       ' Consider now as initialized

        seed1% = static_seed1%
        seed2% = static_seed2%
        seed3% = static_seed3%
      END IF
  END SELECT

END SUB 'SeedStore
 
DECLARE SUB RanPermutation(Arr%(), NrElements%)

'FUNCTION PBMAIN  ' uncomment for use with PB/CC

DIM Arr%(1:10)
CLS

' *** Initialize array of 10 elements
FOR i%=1 TO 10
  Arr%(i%)=i%
NEXT i

' *** Initialize the L'Ecuyer LCG3 random number generator
Seed1%=12345
Seed2%=12345
Seed3%=12345
RanSeed Seed1%, Seed2%, Seed3%

' *** Use the L'Ecuyer RNG to produce a random permutation
RanPermutation Arr%(), 10

' *** Print the random permutation
PRINT "Random permutation: ";
FOR i%=1 TO 10
  PRINT Arr%(i%) " ";
NEXT i%

' *** Print the current internal seeds
RanGetseed seed1%, seed2%, seed3%
PRINT
PRINT "Current seeds: "seed1%, seed2%, seed3%

END 'FUNCTION  ' uncomment for use with PB/CC


SUB RanPermutation(Arr%(), NrElements%) PUBLIC
  LOCAL i%, swapelement%

  FOR i% = 1 TO NrElements%-1
    swapelement% = INT(Rand! * (NrElements%-i%+1))
    SWAP Arr%(i%), Arr%(i%+swapelement%)
  NEXT i

END SUB 'RanPermutation

Mirror provided by Knuth Konrad