Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mruby
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
mruby
Commits
f99e9963
Commit
f99e9963
authored
Jul 22, 2019
by
Yukihiro "Matz" Matsumoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch random generator from Mersenne Twister to Xorshit128.
Now `rand` can be used with `MRB_WITHOUT_FLOAT`; ref #4576
parent
277be410
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
108 additions
and
422 deletions
+108
-422
mrbgems/mruby-random/src/mt19937ar.c
mrbgems/mruby-random/src/mt19937ar.c
+0
-224
mrbgems/mruby-random/src/mt19937ar.h
mrbgems/mruby-random/src/mt19937ar.h
+0
-80
mrbgems/mruby-random/src/random.c
mrbgems/mruby-random/src/random.c
+108
-118
No files found.
mrbgems/mruby-random/src/mt19937ar.c
deleted
100644 → 0
View file @
277be410
/*
** mt19937ar.c - MT Random functions
**
** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura,
** All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
**
** Any feedback is very welcome.
** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
**
** This version is modified by mruby developers. If you see any problem,
** contact us first at https://github.com/mruby/mruby/issues
*/
#include <mruby.h>
#include "mt19937ar.h"
/* Period parameters */
/* #define N 624 */
#define M 397
#define MATRIX_A 0x9908b0dfUL
/* constant vector a */
#define UPPER_MASK 0x80000000UL
/* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL
/* least significant r bits */
#if 0 /* dead_code */
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
#endif /* dead_code */
void
mrb_random_init_genrand
(
mt_state
*
t
,
unsigned
long
s
)
{
t
->
mt
[
0
]
=
s
&
0xffffffffUL
;
for
(
t
->
mti
=
1
;
t
->
mti
<
N
;
t
->
mti
++
)
{
t
->
mt
[
t
->
mti
]
=
(
1812433253UL
*
(
t
->
mt
[
t
->
mti
-
1
]
^
(
t
->
mt
[
t
->
mti
-
1
]
>>
30
))
+
t
->
mti
);
t
->
mt
[
t
->
mti
]
&=
0xffffffffUL
;
}
}
unsigned
long
mrb_random_genrand_int32
(
mt_state
*
t
)
{
unsigned
long
y
;
static
const
unsigned
long
mag01
[
2
]
=
{
0x0UL
,
MATRIX_A
};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if
(
t
->
mti
>=
N
)
{
/* generate N words at one time */
int
kk
;
if
(
t
->
mti
==
N
+
1
)
/* if init_genrand() has not been called, */
mrb_random_init_genrand
(
t
,
5489UL
);
/* a default initial seed is used */
for
(
kk
=
0
;
kk
<
N
-
M
;
kk
++
)
{
y
=
(
t
->
mt
[
kk
]
&
UPPER_MASK
)
|
(
t
->
mt
[
kk
+
1
]
&
LOWER_MASK
);
t
->
mt
[
kk
]
=
t
->
mt
[
kk
+
M
]
^
(
y
>>
1
)
^
mag01
[
y
&
0x1UL
];
}
for
(;
kk
<
N
-
1
;
kk
++
)
{
y
=
(
t
->
mt
[
kk
]
&
UPPER_MASK
)
|
(
t
->
mt
[
kk
+
1
]
&
LOWER_MASK
);
t
->
mt
[
kk
]
=
t
->
mt
[
kk
+
(
M
-
N
)]
^
(
y
>>
1
)
^
mag01
[
y
&
0x1UL
];
}
y
=
(
t
->
mt
[
N
-
1
]
&
UPPER_MASK
)
|
(
t
->
mt
[
0
]
&
LOWER_MASK
);
t
->
mt
[
N
-
1
]
=
t
->
mt
[
M
-
1
]
^
(
y
>>
1
)
^
mag01
[
y
&
0x1UL
];
t
->
mti
=
0
;
}
y
=
t
->
mt
[
t
->
mti
++
];
/* Tempering */
y
^=
(
y
>>
11
);
y
^=
(
y
<<
7
)
&
0x9d2c5680UL
;
y
^=
(
y
<<
15
)
&
0xefc60000UL
;
y
^=
(
y
>>
18
);
t
->
gen
.
int_
=
y
;
return
y
;
}
double
mrb_random_genrand_real1
(
mt_state
*
t
)
{
mrb_random_genrand_int32
(
t
);
t
->
gen
.
double_
=
t
->
gen
.
int_
*
(
1
.
0
/
4294967295
.
0
);
return
t
->
gen
.
double_
;
/* divided by 2^32-1 */
}
#if 0 /* dead_code */
/* initializes mt[N] with a seed */
void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
/* 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)
{
int i, j, k;
init_genrand(19650218UL);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void)
{
unsigned long y;
static const unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void)
{
return (long)(genrand_int32()>>1);
}
/* generates a random number on [0,1]-real-interval */
double genrand_real1(void)
{
return genrand_int32()*(1.0/4294967295.0);
/* divided by 2^32-1 */
}
/* generates a random number on [0,1)-real-interval */
double genrand_real2(void)
{
return genrand_int32()*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on (0,1)-real-interval */
double genrand_real3(void)
{
return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
{
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */
#endif /* dead_code */
mrbgems/mruby-random/src/mt19937ar.h
deleted
100644 → 0
View file @
277be410
/*
** mt19937ar.h - MT Random functions
**
** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura,
** All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
**
** Any feedback is very welcome.
** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
**
** This version is modified by mruby developers. If you see any problem,
** contact us first at https://github.com/mruby/mruby/issues
*/
#define N 624
typedef
struct
{
unsigned
long
mt
[
N
];
int
mti
;
union
{
unsigned
long
int_
;
double
double_
;
}
gen
;
mrb_int
seed
;
mrb_bool
has_seed
:
1
;
}
mt_state
;
void
mrb_random_init_genrand
(
mt_state
*
,
unsigned
long
);
unsigned
long
mrb_random_genrand_int32
(
mt_state
*
);
double
mrb_random_genrand_real1
(
mt_state
*
t
);
/* initializes mt[N] with a seed */
void
init_genrand
(
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
);
/* generates a random number on [0,0xffffffff]-interval */
unsigned
long
genrand_int32
(
void
);
/* generates a random number on [0,0x7fffffff]-interval */
long
genrand_int31
(
void
);
/* 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
);
/* generates a random number on [0,1)-real-interval */
double
genrand_real2
(
void
);
/* generates a random number on (0,1)-real-interval */
double
genrand_real3
(
void
);
/* generates a random number on [0,1) with 53-bit resolution*/
double
genrand_res53
(
void
);
mrbgems/mruby-random/src/random.c
View file @
f99e9963
...
...
@@ -4,71 +4,86 @@
** See Copyright Notice in mruby.h
*/
#ifdef MRB_WITHOUT_FLOAT
# error Conflict 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb'
#endif
#include <mruby.h>
#include <mruby/variable.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/array.h>
#include "mt19937ar.h"
#include <time.h>
static
char
const
MT_STATE_KEY
[]
=
"$mrb_i_mt
_state"
;
static
char
const
RAND_STATE_KEY
[]
=
"$mrb_i_rand
_state"
;
static
const
struct
mrb_data_type
mt
_state_type
=
{
MT
_STATE_KEY
,
mrb_free
,
static
const
struct
mrb_data_type
rand
_state_type
=
{
RAND
_STATE_KEY
,
mrb_free
,
};
static
mrb_value
mrb_random_rand
(
mrb_state
*
mrb
,
mrb_value
self
);
static
mrb_value
mrb_random_srand
(
mrb_state
*
mrb
,
mrb_value
self
);
typedef
struct
rand_state
{
uint32_t
seed
[
4
];
}
rand_state
;
static
void
mt_srand
(
mt_state
*
t
,
unsigned
long
seed
)
rand_init
(
rand_state
*
t
)
{
mrb_random_init_genrand
(
t
,
seed
);
t
->
seed
[
0
]
=
123456789
;
t
->
seed
[
1
]
=
362436069
;
t
->
seed
[
2
]
=
521288629
;
t
->
seed
[
3
]
=
88675123
;
}
static
u
nsigned
long
mt_rand
(
mt_state
*
t
)
static
u
int32_t
rand_seed
(
rand_state
*
t
,
uint32_t
seed
)
{
return
mrb_random_genrand_int32
(
t
);
uint32_t
old_seed
=
t
->
seed
[
3
];
rand_init
(
t
);
t
->
seed
[
3
]
=
seed
;
return
old_seed
;
}
static
double
mt_rand_real
(
mt_state
*
t
)
static
uint32_t
rand_uint32
(
rand_state
*
state
)
{
return
mrb_random_genrand_real1
(
t
);
uint32_t
*
seed
=
state
->
seed
;
uint32_t
x
=
seed
[
0
];
uint32_t
y
=
seed
[
1
];
uint32_t
z
=
seed
[
2
];
uint32_t
w
=
seed
[
3
];
uint32_t
t
;
t
=
x
^
(
x
<<
11
);
x
=
y
;
y
=
z
;
z
=
w
;
w
=
(
w
^
(
w
>>
19
))
^
(
t
^
(
t
>>
8
));
seed
[
0
]
=
x
;
seed
[
1
]
=
y
;
seed
[
2
]
=
z
;
seed
[
3
]
=
w
;
return
w
;
}
static
mrb_value
mrb_random_mt_srand
(
mrb_state
*
mrb
,
mt_state
*
t
,
mrb_value
seed
)
#ifndef MRB_WITHOUT_FLOAT
static
double
rand_real
(
rand_state
*
t
)
{
if
(
mrb_nil_p
(
seed
))
{
seed
=
mrb_fixnum_value
((
mrb_int
)(
time
(
NULL
)
+
mt_rand
(
t
)));
if
(
mrb_fixnum
(
seed
)
<
0
)
{
seed
=
mrb_fixnum_value
(
0
-
mrb_fixnum
(
seed
));
}
}
mt_srand
(
t
,
(
unsigned
)
mrb_fixnum
(
seed
));
return
seed
;
uint32_t
x
=
rand_uint32
(
t
);
return
x
*
(
1
.
0
/
4294967295
.
0
);
}
#endif
static
mrb_value
mrb_random_mt_rand
(
mrb_state
*
mrb
,
mt
_state
*
t
,
mrb_value
max
)
random_rand
(
mrb_state
*
mrb
,
rand
_state
*
t
,
mrb_value
max
)
{
mrb_value
value
;
if
(
mrb_fixnum
(
max
)
==
0
)
{
value
=
mrb_float_value
(
mrb
,
mt_rand_real
(
t
));
#ifndef MRB_WITHOUT_FLOAT
value
=
mrb_float_value
(
mrb
,
rand_real
(
t
));
#else
mrb_raise
(
mrb
,
E_ARGUMENT_ERROR
,
"Float not supported"
);
#endif
}
else
{
value
=
mrb_fixnum_value
(
mt_rand
(
t
)
%
mrb_fixnum
(
max
));
value
=
mrb_fixnum_value
(
rand_uint32
(
t
)
%
mrb_fixnum
(
max
));
}
return
value
;
...
...
@@ -95,105 +110,70 @@ get_opt(mrb_state* mrb)
}
static
mrb_value
get_random
(
mrb_state
*
mrb
)
{
random_default
(
mrb_state
*
mrb
)
{
return
mrb_const_get
(
mrb
,
mrb_obj_value
(
mrb_class_get
(
mrb
,
"Random"
)),
mrb_intern_lit
(
mrb
,
"DEFAULT"
));
}
static
mt_state
*
get_random_state
(
mrb_state
*
mrb
)
{
mrb_value
random_val
=
get_random
(
mrb
);
return
DATA_GET_PTR
(
mrb
,
random_val
,
&
mt_state_type
,
mt_state
);
}
static
mrb_value
mrb_random_g_rand
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
random
=
get_random
(
mrb
);
return
mrb_random_rand
(
mrb
,
random
);
}
static
mrb_value
mrb_random_g_srand
(
mrb_state
*
mrb
,
mrb_value
self
)
static
rand_state
*
random_state
(
mrb_state
*
mrb
)
{
mrb_value
random
=
get_random
(
mrb
);
return
mrb_random_srand
(
mrb
,
random
);
mrb_value
random
_val
=
random_default
(
mrb
);
return
DATA_GET_PTR
(
mrb
,
random_val
,
&
rand_state_type
,
rand_state
);
}
static
mrb_value
mrb_rando
m_init
(
mrb_state
*
mrb
,
mrb_value
self
)
random_
m_init
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
seed
;
mt
_state
*
t
;
rand
_state
*
t
;
seed
=
get_opt
(
mrb
);
/* avoid memory leaks */
t
=
(
mt_state
*
)
DATA_PTR
(
self
);
if
(
t
)
{
mrb_free
(
mrb
,
t
);
t
=
(
rand_state
*
)
DATA_PTR
(
self
);
if
(
t
==
NULL
)
{
t
=
(
rand_state
*
)
mrb_malloc
(
mrb
,
sizeof
(
rand_state
));
mrb_data_init
(
self
,
t
,
&
rand_state_type
);
}
mrb_data_init
(
self
,
NULL
,
&
mt_state_type
);
t
=
(
mt_state
*
)
mrb_malloc
(
mrb
,
sizeof
(
mt_state
));
t
->
mti
=
N
+
1
;
seed
=
mrb_random_mt_srand
(
mrb
,
t
,
seed
);
if
(
mrb_nil_p
(
seed
))
{
t
->
has_seed
=
FALSE
;
rand_init
(
t
)
;
}
else
{
mrb_assert
(
mrb_fixnum_p
(
seed
));
t
->
has_seed
=
TRUE
;
t
->
seed
=
mrb_fixnum
(
seed
);
rand_seed
(
t
,
(
uint32_t
)
mrb_fixnum
(
seed
));
}
mrb_data_init
(
self
,
t
,
&
mt_state_type
);
return
self
;
}
static
void
mrb_random_rand_seed
(
mrb_state
*
mrb
,
mt_state
*
t
)
{
if
(
!
t
->
has_seed
)
{
mrb_random_mt_srand
(
mrb
,
t
,
mrb_nil_value
());
}
}
static
mrb_value
mrb_rando
m_rand
(
mrb_state
*
mrb
,
mrb_value
self
)
random_
m_rand
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
max
;
mt_state
*
t
=
DATA_GET_PTR
(
mrb
,
self
,
&
mt_state_type
,
mt
_state
);
rand_state
*
t
=
DATA_GET_PTR
(
mrb
,
self
,
&
rand_state_type
,
rand
_state
);
max
=
get_opt
(
mrb
);
mrb_random_rand_seed
(
mrb
,
t
);
return
mrb_random_mt_rand
(
mrb
,
t
,
max
);
return
random_rand
(
mrb
,
t
,
max
);
}
static
mrb_value
mrb_rando
m_srand
(
mrb_state
*
mrb
,
mrb_value
self
)
random_
m_srand
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
seed
;
mrb_value
old_seed
;
mt_state
*
t
=
DATA_GET_PTR
(
mrb
,
self
,
&
mt_state_type
,
mt_state
);
seed
=
get_opt
(
mrb
);
seed
=
mrb_random_mt_srand
(
mrb
,
t
,
seed
);
old_seed
=
t
->
has_seed
?
mrb_fixnum_value
(
t
->
seed
)
:
mrb_nil_value
();
if
(
mrb_nil_p
(
seed
))
{
t
->
has_seed
=
FALSE
;
uint32_t
seed
;
uint32_t
old_seed
;
mrb_value
sv
;
rand_state
*
t
=
DATA_GET_PTR
(
mrb
,
self
,
&
rand_state_type
,
rand_state
);
sv
=
get_opt
(
mrb
);
if
(
mrb_nil_p
(
sv
))
{
seed
=
(
uint32_t
)
time
(
NULL
)
+
rand_uint32
(
t
);
}
else
{
mrb_assert
(
mrb_fixnum_p
(
seed
));
t
->
has_seed
=
TRUE
;
t
->
seed
=
mrb_fixnum
(
seed
);
seed
=
(
uint32_t
)
mrb_fixnum
(
sv
);
}
old_seed
=
rand_seed
(
t
,
seed
);
return
old_seed
;
return
mrb_fixnum_value
((
mrb_int
)
old_seed
)
;
}
/*
...
...
@@ -207,25 +187,23 @@ static mrb_value
mrb_ary_shuffle_bang
(
mrb_state
*
mrb
,
mrb_value
ary
)
{
mrb_int
i
;
mt_state
*
random
=
NULL
;
mrb_value
max
;
rand_state
*
random
=
NULL
;
if
(
RARRAY_LEN
(
ary
)
>
1
)
{
mrb_get_args
(
mrb
,
"|d"
,
&
random
,
&
mt
_state_type
);
mrb_get_args
(
mrb
,
"|d"
,
&
random
,
&
rand
_state_type
);
if
(
random
==
NULL
)
{
random
=
get_
random_state
(
mrb
);
random
=
random_state
(
mrb
);
}
mrb_random_rand_seed
(
mrb
,
random
);
mrb_ary_modify
(
mrb
,
mrb_ary_ptr
(
ary
));
max
=
mrb_fixnum_value
(
RARRAY_LEN
(
ary
));
for
(
i
=
RARRAY_LEN
(
ary
)
-
1
;
i
>
0
;
i
--
)
{
mrb_int
j
;
mrb_value
*
ptr
=
RARRAY_PTR
(
ary
);
mrb_value
tmp
;
j
=
mrb_fixnum
(
mrb_random_mt_rand
(
mrb
,
random
,
mrb_fixnum_value
(
RARRAY_LEN
(
ary
))));
j
=
mrb_fixnum
(
random_rand
(
mrb
,
random
,
max
));
tmp
=
ptr
[
i
];
ptr
[
i
]
=
ptr
[
j
];
...
...
@@ -272,15 +250,13 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
{
mrb_int
n
=
0
;
mrb_bool
given
;
mt
_state
*
random
=
NULL
;
rand
_state
*
random
=
NULL
;
mrb_int
len
;
mrb_get_args
(
mrb
,
"|i?d"
,
&
n
,
&
given
,
&
random
,
&
mt
_state_type
);
mrb_get_args
(
mrb
,
"|i?d"
,
&
n
,
&
given
,
&
random
,
&
rand
_state_type
);
if
(
random
==
NULL
)
{
random
=
get_
random_state
(
mrb
);
random
=
random_state
(
mrb
);
}
mrb_random_rand_seed
(
mrb
,
random
);
mt_rand
(
random
);
len
=
RARRAY_LEN
(
ary
);
if
(
!
given
)
{
/* pick one element */
switch
(
len
)
{
...
...
@@ -289,7 +265,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
case
1
:
return
RARRAY_PTR
(
ary
)[
0
];
default:
return
RARRAY_PTR
(
ary
)[
mt_rand
(
random
)
%
len
];
return
RARRAY_PTR
(
ary
)[
rand_uint32
(
random
)
%
len
];
}
}
else
{
...
...
@@ -304,7 +280,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
for
(;;)
{
retry:
r
=
mt_rand
(
random
)
%
len
;
r
=
(
mrb_int
)
rand_uint32
(
random
)
%
len
;
for
(
j
=
0
;
j
<
i
;
j
++
)
{
if
(
mrb_fixnum
(
RARRAY_PTR
(
result
)[
j
])
==
r
)
{
...
...
@@ -322,23 +298,37 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
}
}
static
mrb_value
random_f_rand
(
mrb_state
*
mrb
,
mrb_value
self
)
{
rand_state
*
t
=
random_state
(
mrb
);
return
random_rand
(
mrb
,
t
,
get_opt
(
mrb
));
}
static
mrb_value
random_f_srand
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
random
=
random_default
(
mrb
);
return
random_m_srand
(
mrb
,
random
);
}
void
mrb_mruby_random_gem_init
(
mrb_state
*
mrb
)
{
struct
RClass
*
random
;
struct
RClass
*
array
=
mrb
->
array_class
;
mrb_define_method
(
mrb
,
mrb
->
kernel_module
,
"rand"
,
mrb_random_g
_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
mrb
->
kernel_module
,
"srand"
,
mrb_random_g
_srand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
mrb
->
kernel_module
,
"rand"
,
random_f
_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
mrb
->
kernel_module
,
"srand"
,
random_f
_srand
,
MRB_ARGS_OPT
(
1
));
random
=
mrb_define_class
(
mrb
,
"Random"
,
mrb
->
object_class
);
MRB_SET_INSTANCE_TT
(
random
,
MRB_TT_DATA
);
mrb_define_class_method
(
mrb
,
random
,
"rand"
,
mrb_random_g
_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_class_method
(
mrb
,
random
,
"srand"
,
mrb_random_g
_srand
,
MRB_ARGS_OPT
(
1
));
mrb_define_class_method
(
mrb
,
random
,
"rand"
,
random_f
_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_class_method
(
mrb
,
random
,
"srand"
,
random_f
_srand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"initialize"
,
mrb_rando
m_init
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"rand"
,
mrb_rando
m_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"srand"
,
mrb_rando
m_srand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"initialize"
,
random_
m_init
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"rand"
,
random_
m_rand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
random
,
"srand"
,
random_
m_srand
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
array
,
"shuffle"
,
mrb_ary_shuffle
,
MRB_ARGS_OPT
(
1
));
mrb_define_method
(
mrb
,
array
,
"shuffle!"
,
mrb_ary_shuffle_bang
,
MRB_ARGS_OPT
(
1
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment