Hi,

the apl.info is slightly incorrect: *⎕RAVL* uses *initstate() *and friends and not*initstate_r()* and friends. I sometimes write documentation before the implementation and then forget to update it.

The man pages for both *initstate()* and *initstate_r()* say that they are only available on some platforms and I so far required platforms with *libc* to be on the safe side. I am one of very few *⎕RVAL* users (I use t in automated test cases for GNU APL) and I simply wanted to make sure that it does not cause compile
errors for users that do not use it anyway.

I will prepare an update that removes the *libc* requirement within the next days or so. In the meantime
you can safely replace: *#if HAVE_LIBC* with: *#if* 1 in *⎕RVALcc*.

Best Regards,
Jürgen


On 12/2/25 23:29, Paul Rockwell wrote:
Mike,

No. I hacked the Quad_RVAL.cc so that the code that would have compiled on Linux (where configure would set HAVE_LIBC by finding initstate_r() ) would be compiled - which it does. And seems to run in cursory testing.

My point is that the code does not behave as advertised and may be limiting platforms from running  ⎕RVAL that could. The code is using the “standard” versions (initstate, setstate, and random) of those functions instead of the _r versions.

Hence my question to Jürgen.

- Paul

Sent from my iPad

On Dec 2, 2025, at 4:49 PM, M.Hall <[email protected]> wrote:


This was from me complaining to Jurgen in January 2025 that macos didn't have quad-rval because it doesn't have glibc and initstate_r  -- even though it *does* have 'initstate'.  The changes were around svn 1820.

So your macos finds initstate_r and friends?

On Tue, Dec 2, 2025 at 3:32 PM Paul Rockwell <[email protected]> wrote:

    In src/Quad_RVAL.cc <http://quad_rval.cc/> 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;
    }
    
//----------------------------------------------------------------------------

    I have tested a build of GNU APL SVN 1922 and "reversed" the test
    for the HAVE_LIBC in Quadf_RVAL.cc <http://quadf_rval.cc/> so
    that the code would try to be compiled under macOS. Everything
    related to ⎕RVAL seems to work in my limited testing (it at least
    didn't crash the interpreter).

    Is the use of random() instead of random_r(), etc. in the code an
    oversight. Or is the documentation incorrect?

    - Paul Rockwell




--
Mike Hall


Reply via email to