Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: rigorously predictable random numbers



Hi folks:

This was an interesting pointer.  I am puzzled about some of the zsh-isms here and the logic, so

some questions:

     while (( $#bytes < 4 )); do
       sysread -s$((4-$#bytes)) 'bytes[$#bytes+1]' </dev/urandom || return
     done

It looks like we want 4 individual byes (the sysread promises anywhere from 1 to size of buffer specified, max 8192 (in zshmodules(1)) but may return after only reading 1B.    So why not only say `-s1` instead of the more involved `-s$((4-$#bytes))`?

     local b1=$bytes[1] b2=$bytes[2] b3=$bytes[3] b4=$bytes[4]
     return '#b1 << 24 | #b2 << 16 | #b3 << 8 | #b4'
Now these two lines have me very confused.   Why copy to a scalar parameters and what does referring to them as '#b1', #b2', ... mean.   I have not seen these before and cant figure out where in the zsh documentation this is explained.


Thanks


Kannan


On 5/2/24 21:58, Roman Perepelitsa wrote:
On Fri, May 3, 2024 at 5:48 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
How does one obtain a genuinely random number then?
There are several ways. I use this:
https://gist.github.com/romkatv/a6cede40714ec77d4da73605c5ddb36a

   # Returns a random 32-bit number.
   # If /dev/urandom is cryptographically secure, so is srand32.
   #
   # If zsh is compiled with 64-bit number support, the result
   # is non-negative. Otherwise it may be negative and the value
   # is governed by the rules of unsigned-to-signed conversion in C.
   #
   # Examples:
   #
   #   % print -r -- $(( srand32() ))
   #   263510467
   #
   #   % local -i x='srand32()'
   #   % typeset -p x
   #   typeset -i x=858148951
   #
   # Performance: ~30us per call.
   #
   #   % time ( repeat 1000000 srand32 )
   #   user=19.95s system=6.95s cpu=99% total=26.934
   #
   #   % uname -srm
   #   Linux 5.4.0-58-generic x86_64
   #
   #   % grep 'model name' /proc/cpuinfo | head -1
   #   model name      : AMD Ryzen 7 3700X 8-Core Processor
   function srand32() {
     emulate -L zsh -o no_multi_byte
     local bytes
     while (( $#bytes < 4 )); do
       sysread -s$((4-$#bytes)) 'bytes[$#bytes+1]' </dev/urandom || return
     done
     local b1=$bytes[1] b2=$bytes[2] b3=$bytes[3] b4=$bytes[4]
     return '#b1 << 24 | #b2 << 16 | #b3 << 8 | #b4'
   }
   functions -M srand32 0 0

Roman





Messages sorted by: Reverse Date, Date, Thread, Author