rng: make-random-state conformity and #$ macro fix

`make-random-state' now accepts the conforming types of the
arguments (ie not a fixnum nor simple-vector).

Additionally we sanitize the vector provided to the #$ to be of the
correct arity and type (#313 byte64 or #625 byte32 depending on the
architecture).
This commit is contained in:
Daniel Kochmański 2016-05-06 12:55:25 +02:00
parent 6c31313c07
commit 40ef71aa60
3 changed files with 57 additions and 29 deletions

View file

@ -28,13 +28,29 @@
parameter given to configure script).
* Pending changes since 16.1.2
** API changes
- make-random-state: fix problem with simple-vectors
The correct initialization types for =make-random-state= are:
=(OR RANDOM-STATE (MEMBER T NIL))=
Initializing a random state with an appropriate array (element type and
arity) or with a fixnum is now possible only with the #$ reader macro.
** Enhancements
- Removed 15000 lines of obsolete code
Files not included in the buildsystem but lingering in the codebase or
options failing to build. All info is added in the new documentation in
section "Removed interfaces".
- Indented C/C++ code to follow emacs's gnu C style
This is a first step towards coding standards in the
documentation. Additionally all in the src/c/ directory are listed in the
appropraite documentation section (new-doc).
- Refactored =list_current_directory in unixfsys.d=
Function was obfuscated with ifdefs with non-even pairs of =#\{= and =#\}=.
** Issues fixed
- MOP: fix problemes when redefining non-standard and anonymous classes
Bugs identified and fixed by Pascal Costanza.
@ -43,6 +59,11 @@ Bugs identified and fixed by Pascal Costanza.
This fixes the regression, which crashed ECL at start when pathname
exceeded 128 characters limit.
- make-random-state: fix problem with simple-vectors
Until now #$ reader macro accepted simple vectors as an argument, what lead
to bugs if vector didn't match specific requirements like the element type
or the arity. Now we sanitize this.
* 16.1.2 changes since 16.0.0
** API changes

View file

@ -47,14 +47,13 @@
#define LOWER_MASK 0x7FFFFFFFULL /* least significant 31 bits */
#define ulong uint64_t
static cl_object
cl_object
init_genrand(ulong seed)
{
cl_object array = ecl_alloc_simple_vector((MT_N + 1), ecl_aet_b64);
ulong *mt = array->vector.self.b64;
int j;
mt[0] = seed;
for (j=1; j<MT_N; j++)
for (int j=1; j<MT_N; j++)
mt[j] = (6364136223846793005ULL * (mt[j-1] ^ (mt[j-1] >> 62)) + j);
mt[MT_N] = MT_N+1;
@ -129,14 +128,13 @@ generate_limb(cl_object state)
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
#define ulong uint32_t
static cl_object
cl_object
init_genrand(ulong seed)
{
cl_object array = ecl_alloc_simple_vector((MT_N + 1), ecl_aet_b32);
ulong *mt = array->vector.self.b32;
int j;
mt[0] = seed;
for (j=1; j < MT_N; j++)
for (int j=1; j < MT_N; j++)
mt[j] = (1812433253UL * (mt[j-1] ^ (mt[j-1] >> 30)) + j);
mt[MT_N] = MT_N+1;
@ -289,30 +287,15 @@ ecl_make_random_state(cl_object rs)
if (Null(rs))
rs = ecl_symbol_value(@'*random-state*');
switch (ecl_t_of(rs)) {
case t_random:
if (ecl_t_of(rs) == t_random) {
z->random.value = cl_copy_seq(rs->random.value);
break;
case t_vector:
z->random.value = cl_copy_seq(rs);
break;
case t_fixnum:
/* XXX: If we'll decide to use 64-bit algorithm for
appropriate platforms then this will be replaced
with ecl_to_ulong_long from number.d, which takes
widest available type (32 or 64 bit)
automatically. */
z->random.value = init_genrand(ecl_fixnum(rs));
break;
default: {
const char *type
= "(OR RANDOM-STATE (SIMPLE-VECTOR *) (INTEGER 0 *))";
FEwrong_type_only_arg(@[make-random-state], rs,
ecl_read_from_cstring(type));
}
return z;
}
return(z);
const char *type
= "(OR RANDOM-STATE FIXNUM (MEMBER T NIL))";
FEwrong_type_only_arg(@[make-random-state], rs,
ecl_read_from_cstring(type));
}
@(defun random (x &optional (rs ecl_symbol_value(@'*random-state*')))

View file

@ -1383,7 +1383,31 @@ sharp_dollar_reader(cl_object in, cl_object c, cl_object d)
if (d != ECL_NIL && !read_suppress)
extra_argument('$', in, d);
c = ecl_read_object(in);
rs = ecl_make_random_state(c);
switch (ecl_t_of(c)) {
case t_vector:
#if ECL_FIXNUM_BITS > 32
if (c->vector.dim == 313 && c->vector.elttype == ecl_aet_b64) {
rs = ecl_alloc_object(t_random);
rs->random.value = cl_copy_seq(c);
break;
}
#else /* 32 bit version */
if (c->vector.dim == 625 && c->vector.elttype == ecl_aet_b32) {
rs = ecl_alloc_object(t_random);
rs->random.value = cl_copy_seq(c);
break;
}
#endif
case t_fixnum:
rs = ecl_alloc_object(t_random);
rs->random.value = init_genrand(ecl_fixnum(c));
break;
default:
rs = ecl_make_random_state(c);
break;
}
@(return rs);
}