# RANDLIB を移植するときの注意

RANDLIB に含まれる RNGU0 はシステムが供給する乱数発生ルーチンを使用す
る. システム供給ルーチンがない場合には, RNGU1 等と同等のルーチンを用意
してもよい. 以下に, SunFORTRAN 1.4, Lahey Fortran および C 言語 (Sun 
およびそれ以外のシステム用の2つ)で記述した例を示す. また, メインフレー
ム系の計算機で, integer overflow を無視するような計算機では32ビットを
使った乗算合同法のルーチンを用意するのがよい.

なお C 言語の例の中の識別子は次のような意味を持つ. 

  RAND_MAX : 関数 rand によって返される疑似乱数の最大値

これはふつう, stdlib.h の中で定義されている. 

さらに Sun 用のものについては:

  FLOATFUNCTIONTYPE, RETURNFLOAT : Fortran と C の実数型関数によるイン
    ターフェイスはマシンによって異なる. FLOATFUNCTIONTYPE は C の関数
    定義の型, RETURNFLOAT は C から Fortran へ値を持って帰る時のオペレー
    ションをあらわす. 

これらは, math.h の中で定義されている. 

C 言語用のソースは rngu0.c.sun と rngu0.c.others が用意されており,
make の際, トップディレクトリにある Mkinclude の中の RANDLIB を sun あ
るいは others のどちらかを指定することによって選択する. 

*-----------------------------------------------------------------------
*     RANDOM NUMBER GENERATOR (Sun Fortran)
*-----------------------------------------------------------------------

      FUNCTION RNGU0(ISEED)
      LOGICAL  LFIRST
      SAVE
      DATA     LFIRST / .TRUE. /

      IF(ISEED.NE.0) THEN
        ISEED = ABS(ISEED) + 1
        RNGU0 = RAND(ISEED)       ! 乱数発生
        ISEED  = 0
        LFIRST = .FALSE.
      ELSE
        IF(LFIRST) CALL MSGDMP('E', 'RNGU0',
     #                         'ISEED MUST BE > 0 FOR 1ST CALL.')
        RNGU0=RAND(0)             ! 乱数発生
      ENDIF

      RETURN
      END
*-----------------------------------------------------------------------
*     RANDOM NUMBER GENERATOR (Lahey Fortran)
*-----------------------------------------------------------------------

      FUNCTION RNGU0(ISEED)
      LOGICAL  LFIRST
      SAVE
      DATA     LFIRST / .TRUE. /

      IF(ISEED.NE.0) THEN
        X = REAL(ABS(ISEED))/10000.
        RNGU0 = RANDS(X)
        ISEED  = 0
        LFIRST = .FALSE.
      ELSE
        IF(LFIRST) CALL MSGDMP('E', 'RNGU0',
     #                         'ISEED MUST BE > 0 FOR 1ST CALL.')
        RNGU0=RND()
      ENDIF

      RETURN
      END

/*
 *    rngu0 (written in C for sun)
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define TRUE   1             /* numeric value for true  */
#define FALSE  0             /* numeric value for false */

#define RAND_MAX 0x7FFFFFFF

static int lfirst = TRUE;

FLOATFUNCTIONTYPE rngu0_(iseed)
    int *iseed;
{
    if (*iseed != 0){
	*iseed = abs(*iseed) + 1;
	srand(*iseed);
	*iseed = 0;
	lfirst = FALSE;
	RETURNFLOAT((float)rand()/(float)RAND_MAX);
    }
    else {
	if (lfirst){
	    fprintf (stderr, "*** Error in rngu0 : ");
	    fprintf (stderr, "Iseed must be > 0 for 1st call.\n");
	    exit(1);
	}
	RETURNFLOAT((float)rand()/(float)RAND_MAX);
    }
}

/*
 *    rngu0 (written in C for others)
 */

#include <stdio.h>
#include <stdlib.h>

#define TRUE   1             /* numeric value for true  */
#define FALSE  0             /* numeric value for false */

static int lfirst = TRUE;

float rngu0_(iseed)
    int *iseed;
{
    if (*iseed != 0){
	*iseed = abs(*iseed) + 1;
	srand(*iseed);
	*iseed = 0;
	lfirst = FALSE;
	return((float)rand()/(float)RAND_MAX);
    }
    else {
	if (lfirst){
	    fprintf (stderr, "*** Error in rngu0 : ");
	    fprintf (stderr, "Iseed must be > 0 for 1st call.\n");
	    exit(1);
	}
	return((float)rand()/(float)RAND_MAX);
    }
}
