and the GNU APL info doc, it's stated that the ⎕RVAL operator requires glibc. This is stated to be required due to the use of the glibc functions random_r(), which would also imply the use of initstate_r() and setstate_r() to initialize and set the state.
However, looking at the source, there is no use of these glibc functions. The code uses random(), initstate(), and setstate() -- which are available on platforms that use libraries other than glibc (for example macOS).
//----------------------------------------------------------------------------
Quad_RVAL::Quad_RVAL()
: QuadFunction(TOK_Quad_RVAL)
{
enum { count = sizeof(subfunction_infos) / sizeof(*subfunction_infos) };
init_function_group(subfunction_infos, count, "⎕RVAL");
N = 8;
desired_maxdepth = 4;
memset(state, 0, sizeof(state));
initstate(1, state, N); // <<< uses initstate() instead of initstate_r()
while (desired_shape.get_rank() < MAX_RANK)
desired_shape.add_shape_item(1);
desired_ranks.push_back(0);
desired_types.push_back(0); // no chars
desired_types.push_back(1); // ints
desired_types.push_back(0); // no real
desired_types.push_back(0); // no complex
desired_types.push_back(0); // no nested
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
Value_P
Quad_RVAL::generator_state(const Value & B)
{
// expect an empty, 8, 16, 32, 64, 128, or 256 byte integer vector
//
if (B.get_rank() != 1) RANK_ERROR;
const ShapeItem new_N = B.element_count();
if (new_N != 0 && new_N != 8 && new_N != 32 &&
new_N != 64 && new_N != 128 && new_N != 256)
{
MORE_ERROR() << "bad new_N (aka. ⍴B) in generator_state()";
LENGTH_ERROR;
}
// always return the previous state
//
Value_P Z(N, LOC);
loop(n, N) Z->next_ravel_Int(state[n] & 0xFF);
Z->check_value(LOC);
if (new_N) // set generator state
{
// make sure that all values are bytes
//
loop(b, N)
{
const APL_Integer byte = B.get_cravel(b).get_int_value();
if ((byte < -256) || (byte > 255))
{
MORE_ERROR() << "Bad right argument B in 0 ⎕RVAL B,"
"expecting bytes (integers -256...255)";
DOMAIN_ERROR;
}
}
N = new_N;
loop(b, N)
{
state[b] = B.get_cravel(b).get_int_value();
}
setstate(state); // uses setstate() instead of setstate_r()
}
return Z;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
uint64_t
Quad_RVAL::rand17()
{
const int32_t rnd = random(); // uses random() instead of random_r()
// the lower bits are less random, so we xor the upper 16 bits into
// the lower 16 bits and return them.
return (rnd ^ (rnd >> 16)) & 0x1FFFF;
}
//----------------------------------------------------------------------------
Is the use of random() instead of random_r(), etc. in the code an oversight. Or is the documentation incorrect?