Random number generator (device): Difference between revisions
Content deleted Content added
Childishbeat (talk | contribs) m A GlovePIE section has been added. |
|||
Line 658: | Line 658: | ||
2366495746 |
2366495746 |
||
692037942</pre> |
692037942</pre> |
||
=={{header|Phix}}== |
|||
{{todo|Phix|Test once 0.8.0 is released.}} |
|||
My machine does not support the rdrand instruction.<br> |
|||
Tested as best I can by commenting out the jnc instructions and replacing rdrand with rdtsc.<br> |
|||
I have uploaded replacement pttree.e and pilasm.e (use at your own risk) for |
|||
anyone wanting to test prior to 0.8.0 being shipped. |
|||
If your chip does not support rdrand, you get {1,0}, else {0,-2147483648..2147483647}.<br> |
|||
For completeness, I have shown how to convert the signed result to an unsigned one. |
|||
<lang Phix>integer res -- 1=failure, 0=success |
|||
atom rint = 0 -- random 32-bit int |
|||
#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") |
|||
if fn=-1 then |
|||
puts(1,"cannot open /dev/urandom\n") |
|||
else |
|||
sequence s = {} |
|||
for i=1 to 4 do |
|||
s &= getc(fn) |
|||
end for |
|||
close(fn) |
|||
?bytes_to_int(s,signed:=false) |
|||
end if</lang> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |