<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
Mark,</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
This is very helpful - thank you.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
I have now: dropped the grounded implementation; renamed the unique implementation to "mt"; added an array.copy() to ensure that the old state array is not updated; included a derived shared random type, including runif() and set_seed() predicates; and revised
the test.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof">
Kindly, Mark.<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Mark Brown <mark@mercurylang.org><br>
<b>Sent:</b> 20 February 2023 14:32<br>
<b>To:</b> Mark Clements <mark.clements@ki.se><br>
<b>Cc:</b> users <users@lists.mercurylang.org><br>
<b>Subject:</b> Re: [m-users.] Announcement: mercury-mt Mercury only Mersenne Twister random numbers</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">[You don't often get email from mark@mercurylang.org. Learn why this is important at
<a href="https://aka.ms/LearnAboutSenderIdentification">https://aka.ms/LearnAboutSenderIdentification</a> ]<br>
<br>
Hi Mark,<br>
<br>
As Volker said, thanks for sharing your work. In regards to your question,<br>
<br>
> Question for Mercury users: is it better to do this as a ground generator or as a unique generator?<br>
<br>
Short answer: it's generally best for a library to supply as many<br>
instances as it can correctly implement. For this application it<br>
would be better to implement it as a unique generator, and use<br>
adapters to make other instances as needed.<br>
<br>
Long answer: the choice for the user is similar to the choice of<br>
whether or not to use destructive update in other circumstances. If<br>
there is a significant amount of state that is frequently updated,<br>
then destructive update is probably worthwhile even though the user<br>
will need to manage uniqueness as a result. Since MT requires about<br>
2.5k of state and is likely to be used when lots of calls are made,<br>
the unique generator will be the one that most users would want.<br>
<br>
If a shared generator is required by the user and they don't mind<br>
copying the state for every number generated, this can be done with<br>
one of the adapters down near the bottom of the random.m interface<br>
rather than re-implementing the algorithm. For example, you can import<br>
mt_unique and define a type:<br>
<br>
:- type random == shared_random(params, ustate).<br>
<br>
Then create a generator as follows:<br>
<br>
seed(12345u32, P, R),<br>
S0 = make_shared_random(P, R)<br>
<br>
See the attached file test_mt_1.m.<br>
<br>
It's also possible to attach a generator to the I/O state using<br>
make_io_urandom, so that the generator can be used more conveniently<br>
without copying, and without the generator itself needing to be<br>
unique.<br>
<br>
The "ugly truth" answer: the shared implementation you've given still<br>
uses arrays underneath, and these are destructively updated and aren't<br>
supposed to be shared. As a consequence this typeclass instance<br>
doesn't behave correctly if the generator is not actually used in a<br>
unique way. For example, if the runif test was called twice in<br>
sequence, passing the final state from the first call as the initial<br>
state of the second, we'd expect to observe different numbers. If it<br>
was run a third time, using the *first* state, it should reproduce the<br>
first numbers again, but the attached file test_mt_2.m shows that it<br>
doesn't.<br>
<br>
The underlying problem is that if arrays are put in data structures,<br>
and you refer to an array that has been elsewhere updated, you can get<br>
the new value when logically it should return the old value. The<br>
correct way to handle this, aside from not referring to old arrays in<br>
the first place, is to copy arrays when required. That's what the<br>
shared adapter does via urandom_dup Ideally, the compiler would<br>
check that this is done correctly, but unfortunately the current<br>
implementation doesn't always do that - see the caveat at the start of<br>
array.m.<br>
<br>
I've included in the above test some code to demonstrate the problem<br>
just with arrays on their own.<br>
<br>
Shortest answer: I'll add some docs to the random.m module to clarify<br>
for instance implementors. :-)<br>
<br>
Hope this helps!<br>
<br>
Mark<br>
<br>
On Sun, Feb 12, 2023 at 12:38 AM Mark Clements <mark.clements@ki.se> wrote:<br>
><br>
> I have written a Mercury-only implementation of the Mersenne Twister random number generator. This is a very common and reasonably good pseudo random number generator. For details:<br>
><br>
> <a href="https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fmclements%2Fmercury-mt&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=V4x8%2FyBaB5Eh11m73B2k4x9RhVEqTJVGyaAoT6Tc2DM%3D&reserved=0">
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fmclements%2Fmercury-mt&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=V4x8%2FyBaB5Eh11m73B2k4x9RhVEqTJVGyaAoT6Tc2DM%3D&reserved=0</a><br>
><br>
> Sincerely, Mark.<br>
><br>
><br>
> När du skickar e-post till Karolinska Institutet (KI) innebär detta att KI kommer att behandla dina personuppgifter. Här finns information om hur KI behandlar personuppgifter<<a href="https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fki.se%2Fmedarbetare%2Fintegritetsskyddspolicy&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=B7iJrTi5U7KcEbmXLh%2ByzeNZUQo9nq67xEsspy48Qu0%3D&reserved=0">https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fki.se%2Fmedarbetare%2Fintegritetsskyddspolicy&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=B7iJrTi5U7KcEbmXLh%2ByzeNZUQo9nq67xEsspy48Qu0%3D&reserved=0</a>>.<br>
><br>
><br>
> Sending email to Karolinska Institutet (KI) will result in KI processing your personal data. You can read more about KI’s processing of personal data here<<a href="https://ki.se/en/staff/data-protection-policy">https://ki.se/en/staff/data-protection-policy</a>>.<br>
> _______________________________________________<br>
> users mailing list<br>
> users@lists.mercurylang.org<br>
> <a href="https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.mercurylang.org%2Flistinfo%2Fusers&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=Ztb33y1WBBmyQA%2B3aasFSbbzuHOMATU0a10NxMYN0Xw%3D&reserved=0">
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.mercurylang.org%2Flistinfo%2Fusers&data=05%7C01%7Cmark.clements%40ki.se%7Cb48b433f28744e59a55d08db1346e47e%7Cbff7eef1cf4b4f32be3da1dda043c05d%7C0%7C0%7C638124967789194891%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000%7C%7C%7C&sdata=Ztb33y1WBBmyQA%2B3aasFSbbzuHOMATU0a10NxMYN0Xw%3D&reserved=0</a><br>
</div>
</span></font></div>
</body>
</html>