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