c     =======================================================================
c     PROGRAM: The n-block test.
c     -----------------------------------------------------------------------
c     for    testing of pseudorandom numbers; based on renormalizing
c            a sequence of random numbers. A one-dimensional random
c            walk is also closely related to the idea.
c     by     I. Vattulainen, vattulai@convex.csc.fi
c     alg    random walks, a chi-square test
c     ref    Phys. Rev. Lett. 73, 2513 (1994).
c     title  n_blocktest.f
c     size
c     prec   single/double
c     lang   Fortran77
c     -----------------------------------------------------------------------
c     The author of this software is I. Vattulainen.  Copyright (c) 1993.
c     Permission to use, copy, modify, and distribute this software for
c     any purpose without fee is hereby granted, provided that this entire
c     notice is included in all copies of any software which is or includes
c     a copy or modification of this software and in all copies of the
c     supporting documentation for such software.
c     THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
c     WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKE ANY
c     REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
c     OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
c     -----------------------------------------------------------------------
c     In the n-block test, we calculate averages of sequences of pseudorandom
c     numbers. Each average determines the value of a block variable (one or
c     zero). When repeated several times, the test then performs a statistical
c     analysis to either fail or pass the generator. For those who are
c     interested, the original reference of this test is I. Vattulainen et
c     al., Phys. Rev. Lett. 73, 2513 (1994).
c     -----------------------------------------------------------------------
c     The test is very simple. First, generate N pseudorandom numbers, and
c     then calculate their sum. If the sum is larger than N/2, increase the
c     counter 1 by one. Otherwise, increase the counter 0. Finally, perform
c     a chi-square test to the block variables (counters 0 and 1) and write
c     the results.
c     -----------------------------------------------------------------------
c     Main parameters in the test are as follows:
c        N          The size of the block.
c        ISCANS     Number of samples (blocks). This parameter must be
c                   an even number.
c     ------------------------------------------------------
c     Required modification to this code:
c                   initialization and implementation of the pseudorandom
c                   number generator (PRNG), which will be tested. For
c                   initialization, there is a reserved space in the code
c                   below. The PRNG may be appended to the end of the file,
c                   or may be called separately during compiling. In this
c                   version, the default generator is GGL.
c
c     Output files: fort.20    All the necessary results.
c     =======================================================================

      IMPLICIT NONE
      INTEGER N, ISCANS
      PARAMETER( N = 100 )
      PARAMETER( ISCANS = 100000 )

      INTEGER
     +     I, J, K, ICNT, IHALF, IONE(2)
      DOUBLE PRECISION
     +     DR_REF
      REAL*8
     +     DSEED, DISEED
      REAL
     +     RAN(N), RSUM, CHISUM, GGL

      DR_REF = DFLOAT(N)/2
      IONE(1) = 0
      IONE(2) = 0
      IHALF = ISCANS/2

c     ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
c     First of all, initialize the pseudorandom number generator.
c     In the case of GGL, only one number is needed:

      DSEED   = 12345.D0
c     ```````````````````````````````````````````````````````````
      DISEED = DSEED

c     Begin the sampling loop:

      DO 199 ICNT=1,ISCANS

         RSUM = 0.

c     (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
c     Generate a sequence of N U(0,1] distributed random numbers.
c     If U[0,1), U[0,1], or U(0,1) distributed random numbers are
c     used, the bias (systematic error) is most likely negligible.

         DO 110 I=1,N
            RAN(I) = GGL(DSEED)
 110     CONTINUE

c     )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

c     Calculate the block average and update the counter:
         DO 101 I=1,N
            RSUM = RSUM + RAN(I)
 101     CONTINUE
         IF(RSUM.GT.DR_REF) THEN
            IONE(1) = IONE(1) + 1
         ENDIF

 199  CONTINUE

c     Perform a chi-square test to the counter(s):

      IONE(2) = ISCANS - IONE(1)
      CHISUM = 0.
      DO 210 I=1,2
         CHISUM = CHISUM +
     +        ((FLOAT(IONE(I)) - FLOAT(IHALF))**2)/IHALF
 210  CONTINUE

      WRITE(20,*) ' ==============================================='
      WRITE(20,*) ' Parameters in the n-block test:'
      WRITE(20,*) '      Initial seed:                 ', NINT(DISEED)
      WRITE(20,*) '      Block size (N):               ', N
      WRITE(20,*) '      Number of samples (ISCANS):   ', ISCANS
      WRITE(20,*)
      WRITE(20,*) ' Results:'
      WRITE(20,*) '      Probabilities of blocks 0 and 1:'
      WRITE(20,*) '               Block 0: ', DFLOAT(IONE(2))/ISCANS
      WRITE(20,*) '               Block 1: ', DFLOAT(IONE(1))/ISCANS
      WRITE(20,*) '      Chi-square value: ', CHISUM
      WRITE(20,*)
      WRITE(20,*) ' To compare with, with one degree of freedom'
      WRITE(20,*) ' some percentage points of chi-square values'
      WRITE(20,*) ' are as follows:'
      WRITE(20,*) '       1% limit:   0.00016'
      WRITE(20,*) '       5% limit:   0.00393'
      WRITE(20,*) '      95% limit:   3.841'
      WRITE(20,*) '      99% limit:   6.635'
      WRITE(20,*) ' ==============================================='

      STOP
      END

C     ************************************************************
C     ============================================================
C     A pseudorandom number generator GGL
C     ------------------------------------------------------------

      REAL FUNCTION GGL (DS)

      DOUBLE PRECISION
c     +     D1,
     +     DS, D2
c      DATA D1/2147483648.D0/
      DATA D2/2147483647.D0/
      DS  = DMOD(16807.D0*DS,D2)
c     Generate U(0,1] distributed random numbers:
      GGL = DS/D2

      RETURN
      END

C     ============================================================