added qse_randxs32() and qse_randxs64().
changed awk's rand() to use these. fixed a bug of registering rand() with a wrong number of arguments in StdAwk.
This commit is contained in:
parent
53c98cce93
commit
a35c10fbfc
@ -26,6 +26,7 @@
|
||||
#include <qse/cmn/sio.h>
|
||||
#include <qse/cmn/nwio.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/alg.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include "awk.h"
|
||||
|
||||
@ -139,7 +140,7 @@ int StdAwk::open ()
|
||||
if (addFunction (QSE_T("rand"), 0, 0, (FunctionHandler)&StdAwk::rand, 0) <= -1 ||
|
||||
addFunction (QSE_T("srand"), 0, 1, (FunctionHandler)&StdAwk::srand, 0) <= -1 ||
|
||||
addFunction (QSE_T("system"), 1, 1, (FunctionHandler)&StdAwk::system, 0) <= -1 ||
|
||||
addFunction (QSE_T("time"), 1, 1, (FunctionHandler)&StdAwk::time, 0) <= -1 ||
|
||||
addFunction (QSE_T("time"), 0, 0, (FunctionHandler)&StdAwk::time, 0) <= -1 ||
|
||||
addFunction (QSE_T("setioattr"), 3, 3, (FunctionHandler)&StdAwk::setioattr, QSE_AWK_RIO) <= -1 ||
|
||||
addFunction (QSE_T("getioattr"), 2, 2, (FunctionHandler)&StdAwk::getioattr, QSE_AWK_RIO) <= -1)
|
||||
{
|
||||
@ -149,10 +150,13 @@ int StdAwk::open ()
|
||||
|
||||
qse_ntime_t now;
|
||||
|
||||
this->seed = (qse_gettime(&now) <= -1)? 0u: (unsigned int)now;
|
||||
this->seed += (qse_uintptr_t)&now;
|
||||
this->seed = (qse_gettime(&now) <= -1)? 0u: (long_t)now;
|
||||
/* i don't care if the seed becomes negative or overflows.
|
||||
* i just convert the signed value to the unsigned one. */
|
||||
this->prand = (qse_ulong_t)(this->seed * this->seed * this->seed);
|
||||
/* make sure that the actual seeding is not 0 */
|
||||
if (this->prand == 0) this->prand++;
|
||||
|
||||
::srand (this->seed);
|
||||
this->cmgrtab_inited = false;
|
||||
return 0;
|
||||
}
|
||||
@ -401,29 +405,44 @@ int StdAwk::make_additional_globals (Run* run)
|
||||
int StdAwk::rand (Run& run, Value& ret, const Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
return ret.setFlt ((flt_t)(::rand() % RAND_MAX) / RAND_MAX);
|
||||
#if (QSE_SIZEOF_ULONG_T == 2)
|
||||
# define RANDV_MAX 0x7FFFl
|
||||
#elif (QSE_SIZEOF_ULONG_T == 4)
|
||||
# define RANDV_MAX 0x7FFFFFFFl
|
||||
#elif (QSE_SIZEOF_ULONG_T == 8)
|
||||
# define RANDV_MAX 0x7FFFFFFFFFFFFFFl
|
||||
#else
|
||||
# error Unsupported
|
||||
#endif
|
||||
|
||||
this->prand = qse_randxsulong (this->prand);
|
||||
long_t randv = this->prand % RANDV_MAX;
|
||||
return ret.setFlt ((flt_t)randv / RANDV_MAX);
|
||||
}
|
||||
|
||||
int StdAwk::srand (Run& run, Value& ret, const Value* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
unsigned int prevSeed = this->seed;
|
||||
long_t prevSeed = (long_t)this->seed;
|
||||
|
||||
qse_ntime_t now;
|
||||
|
||||
if (nargs <= 0)
|
||||
{
|
||||
qse_ntime_t now;
|
||||
|
||||
this->seed = (qse_gettime (&now) <= -1)?
|
||||
(this->seed >> 1): (unsigned int)now;
|
||||
this->seed += (qse_uintptr_t)&now;
|
||||
(this->seed * this->seed): (long_t)now;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->seed = (unsigned int)args[0].toInt();
|
||||
this->seed = args[0].toInt();
|
||||
}
|
||||
|
||||
/* i don't care if the seed becomes negative or overflows.
|
||||
* i just convert the signed value to the unsigned one. */
|
||||
this->prand = (qse_ulong_t)(this->seed * this->seed * this->seed);
|
||||
/* make sure that the actual seeding is not 0 */
|
||||
if (this->prand == 0) this->prand++;
|
||||
|
||||
::srand (this->seed);
|
||||
return ret.setInt ((long_t)prevSeed);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/env.h>
|
||||
#include <qse/cmn/alg.h>
|
||||
#include <qse/cmn/stdio.h> /* TODO: remove dependency on qse_vsprintf */
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
@ -112,7 +113,8 @@ typedef struct xtn_t
|
||||
|
||||
typedef struct rxtn_t
|
||||
{
|
||||
unsigned int seed;
|
||||
qse_long_t seed;
|
||||
qse_ulong_t prand; /* last random value returned */
|
||||
|
||||
struct
|
||||
{
|
||||
@ -1921,9 +1923,12 @@ qse_awk_rtx_t* qse_awk_rtx_openstd (
|
||||
|
||||
qse_awk_rtx_pushrcb (rtx, &rcb);
|
||||
|
||||
rxtn->seed = (qse_gettime (&now) <= -1)? 0u: (unsigned int)now;
|
||||
rxtn->seed += (qse_uintptr_t)&now;
|
||||
srand (rxtn->seed);
|
||||
rxtn->seed = (qse_gettime (&now) <= -1)? 0u: (qse_long_t)now;
|
||||
/* i don't care if the seed becomes negative or overflows.
|
||||
* i just convert the signed value to the unsigned one. */
|
||||
rxtn->prand = (qse_ulong_t)(rxtn->seed * rxtn->seed * rxtn->seed);
|
||||
/* make sure that the actual seeding is not 0 */
|
||||
if (rxtn->prand == 0) rxtn->prand++;
|
||||
|
||||
rxtn->c.in.files = icf;
|
||||
rxtn->c.in.index = 0;
|
||||
@ -1972,16 +1977,26 @@ void* qse_awk_rtx_getxtnstd (qse_awk_rtx_t* rtx)
|
||||
|
||||
static int fnc_rand (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
{
|
||||
qse_awk_val_t* r;
|
||||
#if (QSE_SIZEOF_ULONG_T == 2)
|
||||
# define RANDV_MAX 0x7FFFl
|
||||
#elif (QSE_SIZEOF_ULONG_T == 4)
|
||||
# define RANDV_MAX 0x7FFFFFFFl
|
||||
#elif (QSE_SIZEOF_ULONG_T == 8)
|
||||
# define RANDV_MAX 0x7FFFFFFFFFFFFFFl
|
||||
#else
|
||||
# error Unsupported
|
||||
#endif
|
||||
|
||||
/*
|
||||
qse_awk_val_t* r;
|
||||
qse_long_t randv;
|
||||
rxtn_t* rxtn;
|
||||
|
||||
rxtn = (rxtn_t*) QSE_XTN (rtx);
|
||||
r = qse_awk_rtx_makefltval (
|
||||
rtx, (qse_flt_t)(rand_r(rxtn->seed) % RAND_MAX) / RAND_MAX );
|
||||
*/
|
||||
r = qse_awk_rtx_makefltval (
|
||||
rtx, (qse_flt_t)(rand() % RAND_MAX) / RAND_MAX);
|
||||
|
||||
rxtn->prand = qse_randxsulong (rxtn->prand);
|
||||
randv = rxtn->prand % RANDV_MAX;
|
||||
|
||||
r = qse_awk_rtx_makefltval (rtx, (qse_flt_t)randv / RANDV_MAX);
|
||||
if (r == QSE_NULL) return -1;
|
||||
|
||||
qse_awk_rtx_setretval (rtx, r);
|
||||
@ -1995,7 +2010,8 @@ static int fnc_srand (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
qse_long_t lv;
|
||||
qse_awk_val_t* r;
|
||||
int n;
|
||||
unsigned int prev;
|
||||
qse_long_t prev;
|
||||
qse_ntime_t now;
|
||||
rxtn_t* rxtn;
|
||||
|
||||
rxtn = (rxtn_t*) QSE_XTN (rtx);
|
||||
@ -2006,10 +2022,8 @@ static int fnc_srand (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
|
||||
if (nargs <= 0)
|
||||
{
|
||||
qse_ntime_t now;
|
||||
rxtn->seed = (qse_gettime (&now) <= -1)?
|
||||
(rxtn->seed >> 1): (unsigned int)now;
|
||||
rxtn->seed += (qse_uintptr_t)&now;
|
||||
(rxtn->seed * rxtn->seed): (qse_long_t)now;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2018,8 +2032,11 @@ static int fnc_srand (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
if (n <= -1) return -1;
|
||||
rxtn->seed = lv;
|
||||
}
|
||||
|
||||
srand (rxtn->seed);
|
||||
/* i don't care if the seed becomes negative or overflows.
|
||||
* i just convert the signed value to the unsigned one. */
|
||||
rxtn->prand = (qse_ulong_t)(rxtn->seed * rxtn->seed * rxtn->seed);
|
||||
/* make sure that the actual seeding is not 0 */
|
||||
if (rxtn->prand == 0) rxtn->prand++;
|
||||
|
||||
r = qse_awk_rtx_makeintval (rtx, prev);
|
||||
if (r == QSE_NULL) return -1;
|
||||
|
@ -844,16 +844,19 @@ static int val_int_to_str (
|
||||
qse_awk_rtx_valtostr_out_t* out)
|
||||
{
|
||||
qse_char_t* tmp;
|
||||
qse_long_t t;
|
||||
qse_ulong_t t;
|
||||
qse_size_t rlen = 0;
|
||||
int type = out->type & ~QSE_AWK_RTX_VALTOSTR_PRINT;
|
||||
|
||||
t = v->val;
|
||||
if (t == 0) rlen++;
|
||||
if (v->val == 0) rlen++;
|
||||
else
|
||||
{
|
||||
/* non-zero values */
|
||||
if (t < 0) { t = -t; rlen++; }
|
||||
if (v->val < 0)
|
||||
{
|
||||
t = v->val * -1; rlen++;
|
||||
}
|
||||
else t = v->val;
|
||||
while (t > 0) { rlen++; t /= 10; }
|
||||
}
|
||||
|
||||
@ -939,11 +942,10 @@ static int val_int_to_str (
|
||||
}
|
||||
}
|
||||
|
||||
t = v->val;
|
||||
if (t == 0) tmp[0] = QSE_T('0');
|
||||
if (v->val == 0) tmp[0] = QSE_T('0');
|
||||
else
|
||||
{
|
||||
if (t < 0) t = -t;
|
||||
t = (v->val < 0)? (v->val * -1): v->val;
|
||||
|
||||
/* fill in the buffer with digits */
|
||||
while (t > 0)
|
||||
|
@ -41,3 +41,43 @@ qse_uint32_t qse_rand31 (qse_uint32_t seed)
|
||||
|
||||
return lo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Xorshift RNGs by George Marsaglia, The Florida State University
|
||||
* http://www.jstatsoft.org/v08/i14/paper
|
||||
*/
|
||||
|
||||
|
||||
#if (QSE_SIZEOF_UINT32_T > 0)
|
||||
qse_uint32_t qse_randxs32 (qse_uint32_t seed)
|
||||
{
|
||||
qse_uint32_t x;
|
||||
|
||||
QSE_ASSERT (seed != 0);
|
||||
|
||||
x = seed;
|
||||
|
||||
x ^= (x << 13);
|
||||
x ^= (x >> 17);
|
||||
x ^= (x << 5);
|
||||
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (QSE_SIZEOF_UINT64_T > 0)
|
||||
qse_uint64_t qse_randxs64 (qse_uint64_t seed)
|
||||
{
|
||||
qse_uint64_t x;
|
||||
|
||||
QSE_ASSERT (seed != 0);
|
||||
|
||||
x = seed;
|
||||
|
||||
x ^= (x << 21);
|
||||
x ^= (x >> 35);
|
||||
x ^= (x << 4);
|
||||
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user