From 4c4c29212e90fd172728c6727e4d1c7ea8310215 Mon Sep 17 00:00:00 2001 From: "C.Ponapalt" Date: Tue, 20 Aug 2019 20:16:57 +0900 Subject: [PATCH] =?UTF-8?q?Tc551-1=20SRAND=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aya5.rc | 8 ++--- ayavm.cpp | 26 ++++++++++++++-- ayavm.h | 9 ++++++ manifest.cpp | 2 +- mt19937ar.cpp | 83 ++++++++++++++++++++++++++------------------------- mt19937ar.h | 23 +++++++++----- sysfunc.cpp | 68 ++++++++++++++++++++++++++++++++++++++--- sysfunc.h | 1 + 8 files changed, 158 insertions(+), 62 deletions(-) diff --git a/aya5.rc b/aya5.rc index 3c059f37..ff58dfe4 100644 --- a/aya5.rc +++ b/aya5.rc @@ -7,9 +7,7 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include -#define IDC_STATIC -1 -//#include "afxres.h" +#include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -30,7 +28,7 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT // VS_VERSION_INFO VERSIONINFO - FILEVERSION 5,50,4,0 + FILEVERSION 5,51,1,0 PRODUCTVERSION 5,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG @@ -49,7 +47,7 @@ BEGIN VALUE "Comments", "YAYA\0" VALUE "CompanyName", "YAYA Development Team\0" VALUE "FileDescription", "yaya\0" - VALUE "FileVersion", "5, 50, 4, 0\0" + VALUE "FileVersion", "5, 51, 1, 0\0" VALUE "InternalName", "Yet Another AYA5\0" VALUE "LegalCopyright", " \0" VALUE "LegalTrademarks", " \0" diff --git a/ayavm.cpp b/ayavm.cpp index d49a2f9c..df80530f 100644 --- a/ayavm.cpp +++ b/ayavm.cpp @@ -64,7 +64,8 @@ void CAyaVM::Load(void) dwSeed = ::GetTickCount(); #endif - init_genrand(dwSeed); + init_genrand(rs_internal,dwSeed); + init_genrand(rs_sysfunc,dwSeed); } /*----------------------------------------------- @@ -79,12 +80,31 @@ void CAyaVM::Unload(void) -----------------------------------------------*/ unsigned int CAyaVM::genrand(void) { - return genrand_int32(); + return genrand_int32(rs_internal); } int CAyaVM::genrand_int(int n) { - return genrand_int32() % n; + return genrand_int32(rs_internal) % n; +} +unsigned int CAyaVM::genrand_sysfunc(void) +{ + return genrand_int32(rs_sysfunc); +} + +int CAyaVM::genrand_sysfunc_int(int n) +{ + return genrand_int32(rs_sysfunc) % n; +} + +void CAyaVM::genrand_sysfunc_srand(int n) +{ + init_genrand(rs_sysfunc,n); +} + +void CAyaVM::genrand_sysfunc_srand_array(const unsigned long a[],const int n) +{ + init_by_array(rs_sysfunc,a,n); } // ちょっとひどいハックですが…… diff --git a/ayavm.h b/ayavm.h index b10a5e4f..9ad88e59 100644 --- a/ayavm.h +++ b/ayavm.h @@ -47,6 +47,9 @@ class CAyaVM CLog m_logger; + MersenneTwister rs_sysfunc; + MersenneTwister rs_internal; + public: void Load(void); void Unload(void); @@ -54,6 +57,12 @@ class CAyaVM unsigned int genrand(void); int genrand_int(int n); + unsigned int genrand_sysfunc(void); + int genrand_sysfunc_int(int n); + + void genrand_sysfunc_srand(int n); + void genrand_sysfunc_srand_array(const unsigned long a[],const int n); + // 主制御 CBasis& basis(); diff --git a/manifest.cpp b/manifest.cpp index 85cd08d1..e8fa44cb 100644 --- a/manifest.cpp +++ b/manifest.cpp @@ -8,7 +8,7 @@ #include "manifest.h" const yaya::char_t *aya_name = L"YAYA"; -const yaya::char_t *aya_version = L"Tc550-4"; +const yaya::char_t *aya_version = L"Tc551-1"; const yaya::char_t *aya_author = L"umeici/The Maintenance Shop"; diff --git a/mt19937ar.cpp b/mt19937ar.cpp index 2247ca56..e2ea62d7 100644 --- a/mt19937ar.cpp +++ b/mt19937ar.cpp @@ -44,6 +44,7 @@ */ #include +#include "mt19937ar.h" /* Period parameters */ #define N 624 @@ -54,68 +55,68 @@ #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) -static unsigned long state[N]; /* the array for the state vector */ +/*static unsigned long state[N]; //the array for the state vector static int left = 1; static int initf = 0; -static unsigned long *next; +static unsigned long *next; */ /* initializes state[N] with a seed */ -void init_genrand(unsigned long s) +void init_genrand(MersenneTwister &rs,unsigned long s) { int j; - state[0]= s & 0xffffffffUL; + rs.state[0]= s & 0xffffffffUL; for (j=1; j> 30)) + j); + rs.state[j] = (1812433253UL * (rs.state[j-1] ^ (rs.state[j-1] >> 30)) + j); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array state[]. */ + /* only MSBs of the array rs.state[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ - state[j] &= 0xffffffffUL; /* for >32 bit machines */ + rs.state[j] &= 0xffffffffUL; /* for >32 bit machines */ } - left = 1; initf = 1; + rs.left = 1; /*rs.initf = 1;*/ } /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length) +void init_by_array(MersenneTwister &rs,const unsigned long init_key[], const int key_length) { int i, j, k; - init_genrand(19650218UL); + init_genrand(rs,19650218UL); i=1; j=0; k = (N>key_length ? N : key_length); for (; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL)) + rs.state[i] = (rs.state[i] ^ ((rs.state[i-1] ^ (rs.state[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + rs.state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; j++; - if (i>=N) { state[0] = state[N-1]; i=1; } + if (i>=N) { rs.state[0] = rs.state[N-1]; i=1; } if (j>=key_length) j=0; } for (k=N-1; k; k--) { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL)) + rs.state[i] = (rs.state[i] ^ ((rs.state[i-1] ^ (rs.state[i-1] >> 30)) * 1566083941UL)) - i; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + rs.state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; - if (i>=N) { state[0] = state[N-1]; i=1; } + if (i>=N) { rs.state[0] = rs.state[N-1]; i=1; } } - state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ - left = 1; initf = 1; + rs.state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ + rs.left = 1; /*rs.initf = 1;*/ } -static void next_state(void) +static void next_state(MersenneTwister &rs) { - unsigned long *p=state; + unsigned long *p=rs.state; int j; /* if init_genrand() has not been called, */ /* a default initial seed is used */ - if (initf==0) init_genrand(5489UL); + //if (rs.initf==0) init_genrand(rs,5489UL); - left = N; - next = state; + rs.left = N; + rs.next = rs.state; for (j=N-M+1; --j; p++) *p = p[M] ^ TWIST(p[0], p[1]); @@ -123,16 +124,16 @@ static void next_state(void) for (j=M; --j; p++) *p = p[M-N] ^ TWIST(p[0], p[1]); - *p = p[M-N] ^ TWIST(p[0], state[0]); + *p = p[M-N] ^ TWIST(p[0], rs.state[0]); } /* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void) +unsigned long genrand_int32(MersenneTwister &rs) { unsigned long y; - if (--left == 0) next_state(); - y = *next++; + if (--rs.left == 0) next_state(rs); + y = *rs.next++; /* Tempering */ y ^= (y >> 11); @@ -144,12 +145,12 @@ unsigned long genrand_int32(void) } /* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void) +long genrand_int31(MersenneTwister &rs) { unsigned long y; - if (--left == 0) next_state(); - y = *next++; + if (--rs.left == 0) next_state(rs); + y = *rs.next++; /* Tempering */ y ^= (y >> 11); @@ -161,12 +162,12 @@ long genrand_int31(void) } /* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) +double genrand_real1(MersenneTwister &rs) { unsigned long y; - if (--left == 0) next_state(); - y = *next++; + if (--rs.left == 0) next_state(rs); + y = *rs.next++; /* Tempering */ y ^= (y >> 11); @@ -179,12 +180,12 @@ double genrand_real1(void) } /* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) +double genrand_real2(MersenneTwister &rs) { unsigned long y; - if (--left == 0) next_state(); - y = *next++; + if (--rs.left == 0) next_state(rs); + y = *rs.next++; /* Tempering */ y ^= (y >> 11); @@ -197,12 +198,12 @@ double genrand_real2(void) } /* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) +double genrand_real3(MersenneTwister &rs) { unsigned long y; - if (--left == 0) next_state(); - y = *next++; + if (--rs.left == 0) next_state(rs); + y = *rs.next++; /* Tempering */ y ^= (y >> 11); @@ -215,9 +216,9 @@ double genrand_real3(void) } /* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) +double genrand_res53(MersenneTwister &rs) { - unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; + unsigned long a=genrand_int32(rs)>>5, b=genrand_int32(rs)>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } /* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/mt19937ar.h b/mt19937ar.h index 8478c3a1..458a728a 100644 --- a/mt19937ar.h +++ b/mt19937ar.h @@ -46,32 +46,39 @@ #ifndef MTRANDH #define MTRANDH +typedef struct tagMersenneTwister { + unsigned long state[624]; /* the array for the state vector */ + int left; +// int initf; + unsigned long *next; +} MersenneTwister; + /* initializes mt[N] with a seed */ -void init_genrand(unsigned long s); +void init_genrand(MersenneTwister &rs,unsigned long s); /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length); +void init_by_array(MersenneTwister &rs,const unsigned long init_key[],const int key_length); /* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void); +unsigned long genrand_int32(MersenneTwister &rs); /* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void); +long genrand_int31(MersenneTwister &rs); /* These real versions are due to Isaku Wada, 2002/01/09 added */ /* generates a random number on [0,1]-real-interval */ -double genrand_real1(void); +double genrand_real1(MersenneTwister &rs); /* generates a random number on [0,1)-real-interval */ -double genrand_real2(void); +double genrand_real2(MersenneTwister &rs); /* generates a random number on (0,1)-real-interval */ -double genrand_real3(void); +double genrand_real3(MersenneTwister &rs); /* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void); +double genrand_res53(MersenneTwister &rs); #endif diff --git a/sysfunc.cpp b/sysfunc.cpp index b2f8d9e6..f0750bfb 100644 --- a/sysfunc.cpp +++ b/sysfunc.cpp @@ -91,7 +91,7 @@ extern "C" { #endif #endif -#define SYSFUNC_NUM 134 //システム関数の全数 +#define SYSFUNC_NUM 135 //システム関数の全数 #define SYSFUNC_HIS 61 //EmBeD_HiStOrY の位置(0start) static const wchar_t sysfunc[SYSFUNC_NUM][32] = { @@ -281,7 +281,9 @@ static const wchar_t sysfunc[SYSFUNC_NUM][32] = { // 配列(5) L"ASORT", // 文字列操作(9) - L"TRANSLATE" + L"TRANSLATE", + // 数値(4) + L"SRAND", }; //このグローバル変数はマルチインスタンスでも共通 @@ -677,6 +679,8 @@ CValue CSystemFunction::Execute(int index, const CValue &arg, const std::vector< return ASORT(arg, d, l); case 133: return TRANSLATE(arg, d, l); + case 134: + return SRAND(arg, d, l); default: vm.logger().Error(E_E, 49, d, l); return CValue(F_TAG_NOP, 0/*dmy*/); @@ -1404,7 +1408,7 @@ CValue CSystemFunction::CHARSETLIBEX(const CValue &arg, yaya::string_t &d, int & CValue CSystemFunction::RAND(const CValue &arg, yaya::string_t &d, int &l) { if (!arg.array_size()) - return vm.genrand_int(100); + return vm.genrand_sysfunc_int(100); if (!arg.array()[0].IsNum()) { vm.logger().Error(E_W, 9, L"RAND", d, l); @@ -1419,9 +1423,65 @@ CValue CSystemFunction::RAND(const CValue &arg, yaya::string_t &d, int &l) return CValue(0); } - return vm.genrand_int(num); + return vm.genrand_sysfunc_int(num); } + +/* ----------------------------------------------------------------------- + * 関数名 : CSystemFunction::SRAND + * + * RANDのseed。パラメータは文字列も可。 + * ----------------------------------------------------------------------- + */ +CValue CSystemFunction::SRAND(const CValue &arg, yaya::string_t &d, int &l) +{ + if (!arg.array_size()) { + vm.logger().Error(E_W, 19, L"SRAND", d, l); + SetError(19); + return CValue(0); + } + + if (arg.array()[0].IsInt()) { + int num = arg.array()[0].GetValueInt(); + vm.genrand_sysfunc_srand(num); + } + else if (arg.array()[0].IsDouble()) { + union { + double d; + unsigned long i[2]; + } num; + + num.d = arg.array()[0].GetValueDouble(); + + vm.genrand_sysfunc_srand_array(num.i,2); + } + else if (arg.array()[0].IsString()) { + std::vector num; + + yaya::string_t str = arg.array()[0].GetValueString(); + + int nlen = str.length(); + int n = nlen / 2; + + for ( int i = 0 ; i < n ; ++i ) { + num.push_back( static_cast(str[i]) | (static_cast(str[i+1]) << 16) ); + } + if ( (n*2) != nlen ) { //奇数 + num.push_back( static_cast(str[nlen-1]) ); + } + + vm.genrand_sysfunc_srand_array(&(num[0]),num.size()); + } + else { + vm.logger().Error(E_W, 9, L"SRAND", d, l); + SetError(9); + return CValue(0); + } + + return CValue(1); +} + + /* ----------------------------------------------------------------------- * 関数名 : CSystemFunction::FLOOR * ----------------------------------------------------------------------- diff --git a/sysfunc.h b/sysfunc.h index cc9795a0..daa900ab 100644 --- a/sysfunc.h +++ b/sysfunc.h @@ -89,6 +89,7 @@ class CSystemFunction CValue REQUESTLIB(const CValue &arg, yaya::string_t &d, int &l); CValue CHARSETLIB(const CValue &arg, yaya::string_t &d, int &l); CValue RAND(const CValue &arg, yaya::string_t &d, int &l); + CValue SRAND(const CValue &arg, yaya::string_t &d, int &l); CValue FLOOR(const CValue &arg, yaya::string_t &d, int &l); CValue CEIL(const CValue &arg, yaya::string_t &d, int &l); CValue ROUND(const CValue &arg, yaya::string_t &d, int &l);