xorshift を使用したランダムな std::vecotr を作る

xorshift のコードはコピペした.以前のエントリにも同内容があるはず.主題は main.cpp の getArray 関数.dst をアドレス受け取りにする事で,やっと完成した.sizeof(unsigned int) がマシンによって異なるところを,気にせず使用できるようにしたかったけれど,分からなかった.妥協した.

2011年1月10日18時36分追記

main.cpp を書き換えた.

コード

main.cpp
#include <iostream>
#include <iomanip>
#include <sstream>
#include <process.h>
#include <ctime>

#include "xorshift.h"

// base: http://stackoverflow.com/questions/673240/how-do-i-print-an-unsigned-char-as-hex-in-c-using-ostream/673389#673389
// plus: http://www.velocityreviews.com/forums/t289100-print-a-byte-number-with-cout.html
struct HexCharStruct
{
  unsigned char c;
  HexCharStruct(unsigned char _c) : c(_c) { }
};

inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
  return (o << std::hex << std::setw(2) << std::setfill('0') << (int)hs.c);
}

inline HexCharStruct hex(unsigned char _c)
{
  return HexCharStruct(_c);
}

void print(std::vector<unsigned char> data)
{
	int Size = data.size();
	for( int i = 0; i < Size; i++ )
	{
		std::cout << hex(data[i]);
	}
	std::cout << std::endl;

}

// sizeof(unsigned int) が 4 でないシステムでは,要改造
int getArray ( std::vector<unsigned char>&dst, const int Size )
{
	// データ入力先を整形する
	dst.clear();
	dst.reserve(Size);

	// 乱数発生器を時刻とプロセスIDの積で初期化する
	xorshift xos( (int)time(NULL)* _getpid() );

	// 生成したランダムデータの代入先.代入後は dst へコピーする
	unsigned int random;
	// unsigned int のサイズ
	const int LoopBase = sizeof( unsigned int );
	// size と loopBase の商と剰余
	const int LoopCount = Size / LoopBase;
	const int Surplus = Size % LoopBase;
	// LoopBase が 4 だから 0xFF を代入
	const unsigned int Mask = 0xFF;

	// 剰余サイズを書き込み
	random = xos.fxor128();
	for ( int i = 0; i < Surplus; i++ )
	{
		dst.push_back( unsigned char (random & Mask ) );
		random = random >> LoopBase;
	}
	// 商サイズ*LoopBaseを書き込み
	for ( int j = 0; j < LoopCount; j++ )
	{
		random = xos.fxor128();
		for ( int i = 0; i < LoopBase; i++ )
		{
			dst.push_back( unsigned char(random & Mask ) );
			random = random >> 2;
		}
	}

	return 0;
}

// sizeof(unsigned int) が 4 でないシステムでは,要改造
int getArray ( std::vector<unsigned char>&dst, const int Size , xorshift &xos)
{
	// データ入力先を整形する
	dst.clear();
	dst.reserve(Size);

	// 生成したランダムデータの代入先.代入後は dst へコピーする
	unsigned int random;
	// unsigned int のサイズ
	const int LoopBase = sizeof( unsigned int );
	// size と loopBase の商と剰余
	const int LoopCount = Size / LoopBase;
	const int Surplus = Size % LoopBase;
	// LoopBase が 4 だから 0xFF を代入
	const unsigned int Mask = 0xFF;

	// 剰余サイズを書き込み
	random = xos.fxor128();
	for ( int i = 0; i < Surplus; i++ )
	{
		dst.push_back( unsigned char (random & Mask ) );
		random = random >> LoopBase;
	}
	// 商サイズ*LoopBaseを書き込み
	for ( int j = 0; j < LoopCount; j++ )
	{
		random = xos.fxor128();
		for ( int i = 0; i < LoopBase; i++ )
		{
			dst.push_back( unsigned char(random & Mask ) );
			random = random >> 2;
		}
	}

	return 0;
}

int main(int argc, char **arv)
{
	xorshift xos( (int)time(NULL)* _getpid() );
	std::vector<unsigned char>data;
	for ( int i = 16 ; i; i-- )
	{
		getArray(data, 32, xos);
		print(data);
	}
	return 0;
}
xorshift.cpp
#include "xorshift.h"
xorshift.h
#include <vector>

// http://www001.upp.so-net.ne.jp/isaku/rand.html
// http://ogawa-sankinkoutai.seesaa.net/article/108848981.html

class xorshift{

	unsigned int gSeed128[4];

public:

	xorshift( void );

	// s には time( NULL ) または time( NULL ) * getpid()
	inline xorshift( unsigned int s );

	unsigned int xor128( void );
	unsigned int fxor128( void );
};

__inline xorshift::xorshift( void )
{
	gSeed128[0] = 123456789U;
	gSeed128[1] = 362436069U;
	gSeed128[2] = 521288629U;
	gSeed128[3] =  88675123U;
}

// s には time( NULL ) または time( NULL ) * _getpid()
// time(): time.h
// _getpid(): process.h
__inline xorshift::xorshift( unsigned int s )
{
	for( int i = 1; i <= 4; i++ )
	{
		gSeed128[ i - 1 ] = s = 1812433253U * ( s ^ ( s >> 30 ) ) + i;
	}
}

__inline unsigned int xorshift::xor128(void) {
    unsigned int t=gSeed128[0]^(gSeed128[0]<<11);
    gSeed128[0]=gSeed128[1];
	gSeed128[1]=gSeed128[2];
	gSeed128[2]=gSeed128[3];
	return gSeed128[3]^=(gSeed128[3]>>19)^t^(t>>8);
}


__inline unsigned int xorshift::fxor128( void )
{
	// http://www001.upp.so-net.ne.jp/isaku/rand.html
	/* 機械語命令とCのステートメントを1対1にした Xorshift。*/
	/* 一見無駄に見えるが、こちらのほうが速いことが多い。*/
	unsigned int t=gSeed128[0],r=t;
	t<<=11;
	t^=r;
	r=t;
	r>>=8;
	t^=r;
	r=gSeed128[1];
	gSeed128[0]=r;
	r=gSeed128[2];
	gSeed128[1]=r;
	r=gSeed128[3];
	gSeed128[2]=r;
	t^=r;
	r>>=19;
	r^=t;
	gSeed128[3]=r;
	return r;
}