srand64(3S)

srand64, drand64, drand64_advance, drand64_get, drand64_getv, drand64_maxthreads, drand64_set, drand64_setv, drand64_thread - Thread- safe parallel 64-bit random number generator

As shipped in IRIX 6.5.30. Added in IRIX 6.5.15.

NAME
     srand64, drand64, drand64_advance, drand64_get, drand64_getv,
     drand64_maxthreads, drand64_set, drand64_setv, drand64_thread - Thread-
     safe parallel 64-bit random number generator

SYNOPSIS
     Fortran synopsis:

          REAL FUNCTION SRAND64 (harvest)
          REAL harvest

          DOUBLE PRECISION FUNCTION DRAND64 (harvest)
          DOUBLE PRECISION harvest

          SUBROUTINE DRAND64_ADVANCE (count)
          INTEGER*8 count

          SUBROUTINE DRAND64_GET (seed, count, thread)
          INTEGER*8 seed, count
          INTEGER thread

          SUBROUTINE DRAND64_GETV (state, count)
          INTEGER*8 state(*), count(*)

          INTEGER FUNCTION DRAND64_MAXTHREADS ()

          SUBROUTINE DRAND64_SET (seed)
          INTEGER*8 seed

          SUBROUTINE DRAND64_SETV (state, count)
          INTEGER*8 state(*), count(*)

          INTEGER FUNCTION DRAND64_THREAD (thread)
          INTEGER thread

     C/C++ synopsis:

          #include <scsl.h>

          float srand64 (float *harvest);

          double drand64 (double *harvest);

          void drand64_advance (long long count);

          void drand64_get (long long *seed, long long *count, int thread);

          void drand64_getv (long long state[], long long count[]);

          int drand64_maxthreads (void);

          void drand64_set (long long seed);

          void drand64_setv (long long state[], long long count[]);

          int drand64_thread (int thread);

IMPLEMENTATION
     These routines are part of the SCSL Scientific Library and can be loaded
     using either the -lscs or the -lscs_mp option.  The -lscs_mp option
     directs the linker to use the multi-processor version of the library.

     When linking to SCSL with -lscs or -lscs_mp, the default integer size is
     4 bytes (32 bits). Another version of SCSL is available in which integers
     are 8 bytes (64 bits). This version allows the user access to larger
     memory sizes and helps when porting legacy Cray codes.  It can be loaded
     by using the -lscs_i8 option or the -lscs_i8_mp option.  A program may
     use only one of the two versions; 4-byte integer and 8-byte integer
     library calls cannot be mixed.

     The C and C++ prototypes shown above are appropriate for the 4-byte
     integer version of SCSL. When using the 8-byte integer version, the
     variables of type int become long long and the <scsl_i8.h> header file
     should be included.

DESCRIPTION
     These routines comprise a 64-bit thread-safe parallel random number
     generator that is based on the linear congruent sequence

          Y(n+1) = (a X(n) + c) mod 2^64.

     The parameters a and c are chosen from Knuth, The Art of Computer
     Programming , Vol. 2, 3rd edition, pp. 106-108:

          a = 6364136223846793005
          c = 1

     Y(n+1) is then converted to a floating point value in the range [0,1).

     The thread safety is ensured by separating the RNG state for each thread.
     Thus, each thread generates an independent random sequence starting from
     predefined values.  Up to drand64_maxthreads() parallel streams of random
     numbers can be supported simultaneously.

     srand64
          This function returns a single precision random number in the range
          [0,1); the same value is returned in the argument, if provided.

     drand64
          This function returns a double precision random number in the range
          [0,1); the same value is returned in the argument, if provided.

     drand64_advance
          This routine advances the internal state table entries for the
          calling thread as if srand64() or drand64() had been called count
          times.

     drand64_get
          This routine obtains the starting point of srand64() and drand64(),
          as well as the invocation count for the thread specified in the
          third argument.

     drand64_getv
          This routine provides the internal state of srand64() and drand64().
          The arguments are arrays of seeds and invocation counts that can be
          given as arguments to drand64_setv().  The array arguments must have
          at least drand64_maxthreads() elements.

     drand64_maxthreads
          This function returns the maximum number of random number streams
          that can be generated in parallel.  The internal state tables used
          in drand64_getv() and drand64_setv() have drand64_maxthreads()
          entries.

     drand64_set
          This routine sets the starting point of srand64() and drand64().  By
          default the generator is initialized to -1.

     drand64_setv
          This routine sets the internal state of srand64() and drand64().
          The arguments are arrays of seeds and invocation counts, as returned
          by drand64_getv, for example.  The array arguments must have
          drand64_maxthreads() elements.

     drand64_thread
          After a call this routine, the next invocations of srand64() and
          drand64() will have the same effect as if called from the base
          thread number specified in the argument to drand64_thread().

          This function returns the base thread number that had previously
          been generating the random sequence.

EXAMPLES
     Below are several usage examples for RAND64 routines.

     Example 1:  Initialize the internal RNG state table with a single seed
     value and generate a random number for each thread.

     Fortran 77:

                EXTERNAL SRAND64
                REAL SRAND64
                INTEGER*8 SEED
                REAL S1, DUMMY
                SEED = 1
                CALL DRAND64_SET(SEED)
          C Each thread gets a different random number
          C$OMP PARALLEL PRIVATE(S1, DUMMY)
                S1 = SRAND64(DUMMY)
          C$OMP END PARALLEL


     C/C++:

          #include <scsl.h>
          float s1, dummy;
          long long seed = 1LL;
          drand64_set(seed);
          /* Each thread gets a different random number */
          #pragma omp parallel private(s1, dummy)
          {
            s1 = srand64(&dummy);
          }


     Example 2:  After saving the RNG state table, generate 11 random numbers
     for each thread.  Then restore the state table and use drand64_advance()
     to "skip" 10 random numbers.  The next random number generated for each
     thread should be identical to the 11th value from the original stream.

     Fortran 90:

          INTEGER(KIND=8), DIMENSION(:), ALLOCATABLE :: STATE, COUNT
          EXTERNAL DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM, DRAND64
          INTEGER :: I, TABLE_SIZE, DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM
          REAL(KIND=8) :: D1, DUMMY, DRAND64
          TABLE_SIZE = DRAND64_MAXTHREADS()
          ALLOCATE(STATE(TABLE_SIZE))
          ALLOCATE(COUNT(TABLE_SIZE))
          CALL DRAND64_GETV(STATE, COUNT)
          !$OMP PARALLEL PRIVATE(I, D1, DUMMY)
          DO I = 1, 11
            D1 = DRAND64(DUMMY)
          END DO
          PRINT *, OMP_GET_THREAD_NUM(), D1
          !$OMP END PARALLEL
          CALL DRAND64_SETV(STATE, COUNT)
          !$OMP PARALLEL PRIVATE(D1, DUMMY)
          DRAND64_ADVANCE(10_8)
          D1 = DRAND64(DUMMY)
          PRINT *, OMP_GET_THREAD_NUM(), D1
          !$OMP END PARALLEL


     C/C++:

          #include <scsl.h>
          #include <omp.h>
          #include <stdlib.h>
          #include <stdio.h>
          long long *state, *count;
          int i, table_size;
          double d1, dummy;
          table_size = drand64_maxthreads();
          state = (long long *) malloc(table_size * sizeof(long long));
          count = (long long *) malloc(table_size * sizeof(long long));
          drand64_getv(state, count);
          #pragma omp parallel private(i, d1, dummy)
          {
            for (i = 0; i < 11; i++)
              d1 = drand64(&dummy);
            printf("%d, %g0, omp_get_thread_num(), d1);
          }
          drand64_setv(state, count);
          #pragma omp parallel private(d1, dummy)
          {
            drand64_advance(10LL);
            d1 = drand64(&dummy);
            printf("%d, %g0, omp_get_thread_num(), d1);
          }


     Example 3:  Using only a single thread, generate 10 independent streams
     of random numbers.

     Fortran 77:

                EXTERNAL DRAND64_THREAD, SRAND64
                INTEGER DRAND64_THREAD
                REAL SRAND64
                INTEGER I, J, OLDID
                REAL STREAM(1000,10), DUMMY
                DO J = 1, 10
                  OLDID = DRAND64_THREAD(J-1)
                  DO I = 1, 1000
                    STREAM(I, J) = SRAND64(DUMMY)
                  END DO
                END DO
          C RESTORE ORIGINAL BASE THREAD
                OLDID = DRAND64_THREAD(0)


     C/C++:

          #include <scsl.h>
          int i, j, oldid;
          float stream[10][1000], dummy;
          for (i = 0; i < 10; i++) {
            oldid = drand64_thread(i);
            for (j = 0; j < 1000; j++)
              stream[i][j] = srand64(&dummy);
          }
          /* restore original base thread */
          oldid = drand64_thread(0);


CAUTIONS
     Care is required when using drand64_thread() in parallel regions.  If
     multiple parallel threads possess the same RAND64 base thread number as
     assigned with a call to drand64_thread(), then thread safety will be
     compromised, with different threads no longer producing independent
     random sequences.  The statistical randomness of the resulting individual
     sequences will also likely be degraded.

SEE ALSO
     INTRO_SCSL(3S), DRAND48(3C)