Re: [m-users.] Random Number Generator
Volker Wysk <[email protected]>
| Newsgroups | gmane.comp.lang.mercury.general |
|---|---|
| Message-ID | <[email protected]> |
Am Montag, dem 31.07.2023 um 22:33 +1000 schrieb Julien Fischer: > On Mon, 31 Jul 2023, Volker Wysk wrote: > > > Am Montag, dem 31.07.2023 um 09:46 +1000 schrieb Mark Brown: > > > > In C terms, this is akin to having access to a global resource (e,g,, > > > /dev/urandom), but having your code pass around the file handle with > > > which the process accesses it. You could avoid passing around the > > > handle by using a global static variable if you wanted. > > > > > > Similarly, in Mercury you could use a module-local mutable variable to > > > store the system_rng handle, once initialized. > > > > I'm using system_rng for creating a random seed only. It's the "M" variable > > of type io_urandom(P, S), the result of make_io_urandom, which I don't want > > to carry around. > > > > I've looked for info on mutable variables and found the modules thread.mvar, > > store and mutvar (which is undocumented). It's confusing. It uses impurity > > and I can't see how to make and initialize a handle to a mutable variable > > local to a module, such that nothing needs to be carried around. It looks to > > me like some use of promise_pure is needed - but would that be safe? > > Mark is referring to module-local mutable variables as described in > section 10.6 of the reference manual. Have a look at what the > attach_to_io_state attribute does. I've got it working, using a mutable variable. Now there's no more dummy variable that needs to be carried around. Thanks! I've attached it, for people who like to learn by example (hint! ;-) ). > > > > > Actually, that M argument is of type params and this is a dummy type (from > > > > the source code of random.sfc64): > > > > > > > > :- type params > > > > ---> params. > > > > > > > > It's the same for random.sfc32, but not for random.sfc16. And the module > > > > random.sfc64 defines this: > > > > > > > > :- pred generate_uint64(uint64::out, ustate::di, ustate::uo) is det. > > > > > > > > That's looks like what I need, but there isn't such a member of the urandom > > > > type class, which I need to use when I want it to be attached to the IO > > > > state. > > > > > > Since you're digging into the implementation, you could look at the > > > source code of make_io_urandom to see what's going on. It wraps the > > > ustate, which is destructively updatable because it is unique (it's an > > > array), in a mutvar, which is destructively updatable because it is > > > attached to the I/O state. > > > > > > By "destructively updatable" I mean that there is some way for the > > > compiler to verify that such an update is safe. The two interfaces > > > provide two such options, though the actual update that is happening > > > is the same either way. > > > > Sorry, but this makes me even more confused. I think, I'll bite the bullet > > and pass around that dummy variable. > > The dummy variable is necessary because otherwise you couldn't create > instances of the urandom type class. Also, for some random number > generators, it is not a dummy variable (e.g. on some systems the > system_rng handle contains the file descriptor used to open /dev/urandom > etc.) I was wondering why the dummy (or non-dummy) value isn't included in the random state. Zoltan's answer makes that clear. Cheers, Volker _______________________________________________ users mailing list [email protected] https://lists.mercurylang.org/listinfo/users
random128.m
(text/x-matlab, 2.7 KB)
%====================================================================================================
% The 128 bit random number generator for directory identities
%====================================================================================================
:- module random128.
:- interface.
:- import_module io.
% Make a 128 bit random number and return it as a hexadecimal string of length 32. On the first call, this will
% initialize the used random number generator with a seed received from the system random number generator (for
% Linux, this reads from /dev/urandom).
:- pred random128(string::out, io::di, io::uo) is det.
% :- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module random, random.sfc64, random.system_rng, string, list, maybe, int, int64, require.
random128(Random, !IO) :-
get_maybedummy(MaybeDummy, !IO),
(
% Already seeded the random generator
MaybeDummy = yes(Dummy)
;
% Seed the random generator
MaybeDummy = no,
open_system_rng(MaybeHandle, !IO),
(
MaybeHandle = maybe.ok(Handle),
random.system_rng.generate_uint64(Handle, Seed1, !IO),
random.system_rng.generate_uint64(Handle, Seed2, !IO),
random.system_rng.generate_uint64(Handle, Seed3, !IO),
random.sfc64.seed(Seed1, Seed2, Seed3, P, RandState),
make_io_urandom(P, RandState, Dummy, !IO),
set_maybedummy(yes(Dummy), !IO)
;
MaybeHandle = maybe.error(Msg),
unexpected($pred, "Error opening system random number generator:\n" ++ Msg)
)
),
random.generate_uint64(Dummy, Rand1, !IO),
random.generate_uint64(Dummy, Rand2, !IO),
Random = fill_hex_16(string.uint64_to_hex_string(Rand1)) ++
fill_hex_16(string.uint64_to_hex_string(Rand2)).
% Mutable variable for storing the dummy value which is needed for the random.generate_uint64 predicate. So we
% don't need to carry this value around. See section "10.6 Module-local mutable variables" in the Language
% Reference Manual.
:- mutable(
maybedummy,
maybe(random.io_urandom(random.sfc64.params, random.sfc64.ustate)),
no,
ground,
[attach_to_io_state, untrailed]
).
% Fill the string with leading zeros, such that it has 16 digits.
:- func fill_hex_16(string) = string.
fill_hex_16(HexStr) =
string.join_list(
"",
map((func(_) = "0"), 1 .. (16-length(HexStr)))
++ [HexStr]).
% main(!IO) :-
% foldl(
% (pred(_::in, !.IO1::di, !:IO1::uo) is det :-
% random128(Rand, !IO1),
% io.format("Rand = %s\n", [s(Rand)], !IO1)
% ),
% 1 .. 10,
% !IO).
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE6QXGh82Ov3+2nrxp+K4ydFOsHoUFAmTIu0sACgkQ+K4ydFOs HoVcnQ/+O53Lxv+/9hrrOb0/5bAsnAXj+8XioaFLJdpLKYPGoKGnL7ZuybOJjuzS OgNvJRm1sN7/x4c0BfozNmDjstjNj6iUx+qQoAr/SDHyWbQeo+Gp+6nMHOp6YH7D 5owxJRw/wcda2Nt9G7VfbBz5m4M32MGXVx9Xao0JlBMTL+DeMoxgQhempu3cYWO0 kigf+sWUOQFwc5nKxKRO6mQB2sE0WfsSO72od/txB4Bg6c8gjt3Gu+zUo7SAWL0v CdLAZD8scDvNZsQe3S+A0WM8U/JhR2bliTKO7VgppV36bkN51ehNh+0694baEKSG fW10iBfjbUsHidrP4mW1MpLl/YRmWu/LXVt5csrdWLtXJ09gD2K0lk5O+gbYxiM6 4NhrhU1VXaEdCeE+Sk+M22v0XkvNrAsgNatVl6/cGUpMG4AenCVDb64c2QrtDlQL x+3NBJ+Z7vNt7oz4cXYZ2ex2hTjEwJVjmMXJmePwu3nWSGcQHBzEqorpjJTwax3S MHm0LypZr4mq/aQ8xYgyLCqQmG/wErIHPXEETa2viexP+M/NwhBXI1ORjutQwC1c BB7jWKxHfYw6ToIKB2SEvvnEOHkS8GcTIslJ7cj5qooH3J80OuOwTYu8xAipMdtb bvxLhmfGVcxkAv92dX6CSvtbmGn0fC0EZ8RNrsc+8gKD8JDRYWE= =+bLI -----END PGP SIGNATURE-----