Random number generator (device): Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring the hard way
m (added related task)
m (→‎{{header|Phix}}: added syntax colouring the hard way)
Line 1,030:
For completeness, I have shown how to convert the signed result to an unsigned one.
 
<!--<lang Phix>integer res -- 1=failure, 0=success>
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #000080;font-style:italic;">-- 1=failure, 0=success</span>
atom rint = 0 -- random 32-bit int
<span style="color: #004080;">atom</span> <span style="color: #000000;">rint</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- random 32-bit int</span>
#ilASM{
mov eax,1
cpuid
bt ecx,30
mov edi,1 -- exit code: failure
jnc :exit
-- rdrand sets CF=0 if no random number
-- was available. Intel documentation
-- recommends 10 retries in a tight loop
mov ecx,11
::loop1
sub ecx, 1
jz :exit -- exit code is set already
rdrand eax
-- (the above generates exception #C000001D if not supported)
-- rdtsc
jnc :loop1
lea edi,[rint]
call :%pStoreMint
xor edi,edi
::exit
mov [res],edi
xor ebx,ebx -- important!
}
<span style="color: #0000FF;">?{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rint</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (success)
--
-- To convert a signed 32-bit int to an unsigned one:
--
-- method 1
-- atom urint1 = rint
-- if urint1&lt;0 then urint1+=#100000000 end if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">urint1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rint</span><span style="color: #0000FF;">+</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rint</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">#100000000</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- method 2</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">pMem</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">poke4</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rint</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">urint2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek4u</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- method 3</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">urint3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rint</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span><span style="color: #000000;">signed</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?{</span><span style="color: #000000;">urint1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">urint2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">urint3</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</lang>-->
 
#ilASM{
mov eax,1
cpuid
bt ecx,30
mov edi,1 -- exit code: failure
jnc :exit
 
-- rdrand sets CF=0 if no random number
-- was available. Intel documentation
-- recommends 10 retries in a tight loop
mov ecx,11
::loop1
sub ecx, 1
jz :exit -- exit code is set already
rdrand eax
-- (the above generates exception #C000001D if not supported)
-- rdtsc
jnc :loop1
 
lea edi,[rint]
call :%pStoreMint
xor edi,edi
 
::exit
mov [res],edi
xor ebx,ebx -- important!
}
 
?{res,rint}
 
if res=0 then -- (success)
 
--
-- To convert a signed 32-bit int to an unsigned one:
--
-- method 1
-- atom urint1 = rint
-- if urint1<0 then urint1+=#100000000 end if
atom urint1 = rint+iff(rint<0?#100000000:0)
 
-- method 2
atom pMem = allocate(4)
poke4(pMem,rint)
atom urint2 = peek4u(pMem)
free(pMem)
 
-- method 3
atom urint3 = bytes_to_int(int_to_bytes(rint,4),signed:=false)
 
?{urint1,urint2,urint3}
 
end if</lang>
A linux-only solution:
<!--<lang Phix>integer fn = open("/dev/urandom","rb")-->
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"/dev/urandom"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rb"</span><span style="color: #0000FF;">)</span>
if fn=-1 then
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
puts(1,"cannot open /dev/urandom\n")
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cannot open /dev/urandom\n"</span><span style="color: #0000FF;">)</span>
else
<span style="color: #008080;">else</span>
sequence s = {}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
for i=1 to 4 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
s &= getc(fn)
<span style="color: #000000;">s</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">getc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
close(fn)
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
?bytes_to_int(s,signed:=false)
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">signed</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
end if</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</lang>-->
 
=={{header|PicoLisp}}==
7,813

edits