MPAライブラリ 乱数ルーチン



[ 簡単な説明 ]

m_rand( )は、内部でM系列の疑似一様乱数生成関数を使用しています。
その初期設定の為、m_rand( )を使用する前に、まず m_srand( )を呼び出す必要があります。

関数プロトタイプ 機能説明
MPA m_rand(void) 一様乱数
void m_srand(long seed) 一様乱数初期設定

プログラム・ソース("m_rand.c")           top (トップに戻る)
/*		m_rand.c		random MPA		*/
#include "mpa.h"

unsigned long *_prx, *_prx_end;			/* mrnd()の乱数核ほか変数 */
unsigned long _rx[522];					/*      〃        */

void rnd521(void);
int mrnd(void);

MPA m_rand(void)
{
	MPA r;
	unsigned long t;
	int i;

	for(i = 0; i <= NMPA; i += 2)	r.num[i] = mrnd();
	r.zero = 0;
	r.sign = 1;
	if(r.num[NMPA] != 0)	r.exp = -1;
	else
	{
		i = mrnd();
		r.exp = -2;
		while(i < RADIX_2)
		{
			r.exp--;
			i <<= 1;
		}
	}
	return r;
}

void rnd521(void)
{
	unsigned long *p, *p1, *p2;

	p1 = (_prx = p = p2 = _rx) + 489;
	while(p1 != _prx_end)	*p++ ^= *p1++;
	while(p  != _prx_end)	*p++ ^= *p2++;
}

int mrnd(void)
{
	static int sw = 1, rnd;

	if(sw)
	{
		sw = 0;
		if(++_prx == _prx_end)	rnd521();
		rnd = *_prx & RADIX1;
		return *_prx >> (RADIXBITS + 1);
	}
	sw = 1;
	return rnd;
}

void m_srand(long seed)
{
	int i, j;
	unsigned long *p, *p1, *p2, *p3, s, u;

	_prx_end = &_rx[521];

	s = seed ^ 987612345L;
	u = 0;
	for(i = 0, _prx = _rx; i <= 16; i++)
	{
		for(j = 0; j < 32; j++)
		{
			s = s * 1566083941L + 1;
			u = (u >> 1) | (s & (1L << 31));
		}
		*_prx++ = u;
	}
	_prx--;
	*_prx = (0xffffffff & (*_prx << 23)) ^ (*_rx >> 9) ^ *(_rx + 15);
	p1 = _rx;
	p2 = &_rx[1];
	p3 = _prx++;
	while(_prx != _prx_end)
		*_prx++ = (0xffffffff & (*p1++ << 23)) ^ (*p2++ >> 9) ^ *p3++;
	rnd521();		/* wram up */
	rnd521();
	rnd521();
	_prx = &_rx[520];
}