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

RANDLIB に含まれる RNGU0 はシステムが供給する乱数発生ルーチンを使用す
る. システム供給ルーチンがない場合には, RNGU1 等と同等のルーチンを用意
してもよい. また, メインフレーム系の計算機で, integer overflow を無視
するような計算機では32ビットを使った乗算合同法のルーチンを用意するのが
よい. 

このパッケージでは C 言語で書かれたものを標準としている. 

なお rngu0.c 中の識別子は次のような意味を持つ. 

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

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

以下に, SunFORTRAN 1.4, Lahey Fortran および C 言語 (Sun およびそれ以
外のシステム用の2つ)で記述した例を示す. 

Sun 用のものについては:

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

この便法は, SunFORTRAN 1.4 を用いて Fortran から C の関数を呼び出す時
に生じる問題を回避するために使われており, SunFORTRAN 2 以上を用いてい
る場合には不要となる. 

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

*-----------------------------------------------------------------------
*     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)
 */

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

#ifndef LONG_MAX
#define LONG_MAX 0x7FFFFFFF
#endif

#ifndef RAND_MAX
#define RAND_MAX LONG_MAX
#endif

#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);
    }
}
