LAPACK 3.3.0

dlaran.f

Go to the documentation of this file.
00001       DOUBLE PRECISION FUNCTION DLARAN( ISEED )
00002 *
00003 *  -- LAPACK auxiliary routine (version 3.1) --
00004 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00005 *     November 2006
00006 *
00007 *     .. Array Arguments ..
00008       INTEGER            ISEED( 4 )
00009 *     ..
00010 *
00011 *  Purpose
00012 *  =======
00013 *
00014 *  DLARAN returns a random real number from a uniform (0,1)
00015 *  distribution.
00016 *
00017 *  Arguments
00018 *  =========
00019 *
00020 *  ISEED   (input/output) INTEGER array, dimension (4)
00021 *          On entry, the seed of the random number generator; the array
00022 *          elements must be between 0 and 4095, and ISEED(4) must be
00023 *          odd.
00024 *          On exit, the seed is updated.
00025 *
00026 *  Further Details
00027 *  ===============
00028 *
00029 *  This routine uses a multiplicative congruential method with modulus
00030 *  2**48 and multiplier 33952834046453 (see G.S.Fishman,
00031 *  'Multiplicative congruential random number generators with modulus
00032 *  2**b: an exhaustive analysis for b = 32 and a partial analysis for
00033 *  b = 48', Math. Comp. 189, pp 331-344, 1990).
00034 *
00035 *  48-bit integers are stored in 4 integer array elements with 12 bits
00036 *  per element. Hence the routine is portable across machines with
00037 *  integers of 32 bits or more.
00038 *
00039 *  =====================================================================
00040 *
00041 *     .. Parameters ..
00042       INTEGER            M1, M2, M3, M4
00043       PARAMETER          ( M1 = 494, M2 = 322, M3 = 2508, M4 = 2549 )
00044       DOUBLE PRECISION   ONE
00045       PARAMETER          ( ONE = 1.0D+0 )
00046       INTEGER            IPW2
00047       DOUBLE PRECISION   R
00048       PARAMETER          ( IPW2 = 4096, R = ONE / IPW2 )
00049 *     ..
00050 *     .. Local Scalars ..
00051       INTEGER            IT1, IT2, IT3, IT4
00052       DOUBLE PRECISION   RNDOUT
00053 *     ..
00054 *     .. Intrinsic Functions ..
00055       INTRINSIC          DBLE, MOD
00056 *     ..
00057 *     .. Executable Statements ..
00058   10  CONTINUE
00059 *
00060 *     multiply the seed by the multiplier modulo 2**48
00061 *
00062       IT4 = ISEED( 4 )*M4
00063       IT3 = IT4 / IPW2
00064       IT4 = IT4 - IPW2*IT3
00065       IT3 = IT3 + ISEED( 3 )*M4 + ISEED( 4 )*M3
00066       IT2 = IT3 / IPW2
00067       IT3 = IT3 - IPW2*IT2
00068       IT2 = IT2 + ISEED( 2 )*M4 + ISEED( 3 )*M3 + ISEED( 4 )*M2
00069       IT1 = IT2 / IPW2
00070       IT2 = IT2 - IPW2*IT1
00071       IT1 = IT1 + ISEED( 1 )*M4 + ISEED( 2 )*M3 + ISEED( 3 )*M2 +
00072      $      ISEED( 4 )*M1
00073       IT1 = MOD( IT1, IPW2 )
00074 *
00075 *     return updated seed
00076 *
00077       ISEED( 1 ) = IT1
00078       ISEED( 2 ) = IT2
00079       ISEED( 3 ) = IT3
00080       ISEED( 4 ) = IT4
00081 *
00082 *     convert 48-bit integer to a real number in the interval (0,1)
00083 *
00084       RNDOUT = R*( DBLE( IT1 )+R*( DBLE( IT2 )+R*( DBLE( IT3 )+R*
00085      $         ( DBLE( IT4 ) ) ) ) )
00086 *
00087       IF (RNDOUT.EQ.1.0D+0) THEN
00088 *        If a real number has n bits of precision, and the first
00089 *        n bits of the 48-bit integer above happen to be all 1 (which
00090 *        will occur about once every 2**n calls), then DLARAN will
00091 *        be rounded to exactly 1.0. 
00092 *        Since DLARAN is not supposed to return exactly 0.0 or 1.0
00093 *        (and some callers of DLARAN, such as CLARND, depend on that),
00094 *        the statistically correct thing to do in this situation is
00095 *        simply to iterate again.
00096 *        N.B. the case DLARAN = 0.0 should not be possible.
00097 *
00098          GOTO 10
00099       END IF
00100 *
00101       DLARAN = RNDOUT
00102       RETURN
00103 *
00104 *     End of DLARAN
00105 *
00106       END
 All Files Functions