zsh-users
 help / color / mirror / code / Atom feed
* rigorously predictable random numbers
@ 2024-05-03  1:23 Ray Andrews
  2024-05-03  3:09 ` Lawrence Velázquez
  0 siblings, 1 reply; 22+ messages in thread
From: Ray Andrews @ 2024-05-03  1:23 UTC (permalink / raw)
  To: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 830 bytes --]

#!/usr/bin/zsh

echo $RANDOM
var=$( echo $RANDOM )
echo $var

... I run that and get:



3 /aWorking/Zsh/Source/Wk 1 % . test1
23008
3809

3 /aWorking/Zsh/Source/Wk 1 % . test1
3809
768

3 /aWorking/Zsh/Source/Wk 1 % . test1
768
11071

3 /aWorking/Zsh/Source/Wk 1 % . test1
11071
26432

3 /aWorking/Zsh/Source/Wk 1 % . test1
26432
19059

3 /aWorking/Zsh/Source/Wk 1 % . test1
19059
14427

... the result of the first $RANDOM is always exactly the result of the 
second $RANDOM in the previous call to the script.  This might not be as 
unexpected in a function where at least it's the same shell, but a 
script, seems to me, should always have a virginal notion of $RANDOM, 
no?  Yet it remembers the previous result from another shell.  I have 
the vaguest fragment of memory that we discussed this on the list once 
before.


[-- Attachment #2: Type: text/html, Size: 1411 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  1:23 rigorously predictable random numbers Ray Andrews
@ 2024-05-03  3:09 ` Lawrence Velázquez
  2024-05-03  3:48   ` Ray Andrews
  0 siblings, 1 reply; 22+ messages in thread
From: Lawrence Velázquez @ 2024-05-03  3:09 UTC (permalink / raw)
  To: zsh-users

On Thu, May 2, 2024, at 9:23 PM, Ray Andrews wrote:
> ... the result of the first $RANDOM is always exactly the result of the 
> second $RANDOM in the previous call to the script.

As zshparam(1) says:

	The values of RANDOM form an intentionally-repeatable
	pseudo-random sequence; subshells that reference RANDOM
	will result in identical pseudo-random values unless the
	value of RANDOM is referenced or seeded in the parent shell
	in between subshell invocations.

Referencing RANDOM advances the sequence, but doing so in $(...)
-- or any other subshell -- causes that progress to be discarded
upon returning to the parent shell, and the next reference to
RANDOM will "rewind" to the first value seen in that subshell.

	% typeset -p RANDOM
	typeset -i10 RANDOM=9493
	% (repeat 3; do typeset -p RANDOM; done)
	typeset -i10 RANDOM=5570
	typeset -i10 RANDOM=30244
	typeset -i10 RANDOM=21515
	% typeset -p RANDOM
	typeset -i10 RANDOM=5570


> This might not be 
> as unexpected in a function where at least it's the same shell, but a 
> script, seems to me, should always have a virginal notion of $RANDOM, 
> no?  Yet it remembers the previous result from another shell.

There are no other shells, other than the $(...) subshells.  You
are using the "." command, which sources the given script in the
current shell.


> I have 
> the vaguest fragment of memory that we discussed this on the list once 
> before.

https://www.zsh.org/mla/workers/2015/msg00549.html
https://www.zsh.org/mla/workers/2017/msg00586.html
https://www.zsh.org/mla/users/2017/msg00618.html
https://www.zsh.org/mla/workers/2019/msg00887.html
https://www.zsh.org/mla/workers/2023/msg00012.html
https://www.zsh.org/mla/workers/2023/msg00208.html
https://www.zsh.org/mla/users/2023/msg00475.html


-- 
vq


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  3:09 ` Lawrence Velázquez
@ 2024-05-03  3:48   ` Ray Andrews
  2024-05-03  4:58     ` Roman Perepelitsa
                       ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Ray Andrews @ 2024-05-03  3:48 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1421 bytes --]



On 2024-05-02 20:09, Lawrence Velázquez wrote:
> 	The values of RANDOM form an intentionally-repeatable
> 	pseudo-random sequence; subshells that reference RANDOM
> 	will result in identical pseudo-random values unless the
> 	value of RANDOM is referenced or seeded in the parent shell
> 	in between subshell invocations.
Ok then at least this is intentional.  How does one obtain a genuinely 
random number then?  TBH, for my particular needs right now the standard 
behavior is perfect, but as a matter of principle I'd like to know how 
to get 'real' random numbers.  There will be a way.

> There are no other shells, other than the $(...) subshells.  You
> are using the "." command, which sources the given script in the
> current shell.
Yes, pardon.  I get it mixed up with $( ) and with piping.
> https://www.zsh.org/mla/workers/2015/msg00549.html
> https://www.zsh.org/mla/workers/2017/msg00586.html
> https://www.zsh.org/mla/users/2017/msg00618.html
> https://www.zsh.org/mla/workers/2019/msg00887.html
> https://www.zsh.org/mla/workers/2023/msg00012.html
> https://www.zsh.org/mla/workers/2023/msg00208.html
> https://www.zsh.org/mla/users/2023/msg00475.html
>
How do you do that?  It would save a lot of repetition if I could 
research the archives myself.    Such a resource, but inaccessible -- 
tho you seem to know how.  It bothers me to ask a question that I know 
has been asked before.





[-- Attachment #2: Type: text/html, Size: 3125 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  3:48   ` Ray Andrews
@ 2024-05-03  4:58     ` Roman Perepelitsa
  2024-05-03 13:14       ` Ray Andrews
  2024-05-20 17:41       ` Kannan Varadhan
  2024-05-03  5:40     ` Lawrence Velázquez
  2024-05-03 13:36     ` Clinton Bunch
  2 siblings, 2 replies; 22+ messages in thread
From: Roman Perepelitsa @ 2024-05-03  4:58 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

On Fri, May 3, 2024 at 5:48 AM Ray Andrews <rayandrews@eastlink.ca> 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


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  3:48   ` Ray Andrews
  2024-05-03  4:58     ` Roman Perepelitsa
@ 2024-05-03  5:40     ` Lawrence Velázquez
  2024-05-03 12:51       ` Ray Andrews
  2024-05-03 13:36     ` Clinton Bunch
  2 siblings, 1 reply; 22+ messages in thread
From: Lawrence Velázquez @ 2024-05-03  5:40 UTC (permalink / raw)
  To: zsh-users

On Thu, May 2, 2024, at 11:48 PM, Ray Andrews wrote:
> On 2024-05-02 20:09, Lawrence Velázquez wrote:
>> https://www.zsh.org/mla/workers/2015/msg00549.html
>> https://www.zsh.org/mla/workers/2017/msg00586.html
>> https://www.zsh.org/mla/users/2017/msg00618.html
>> https://www.zsh.org/mla/workers/2019/msg00887.html
>> https://www.zsh.org/mla/workers/2023/msg00012.html
>> https://www.zsh.org/mla/workers/2023/msg00208.html
>> https://www.zsh.org/mla/users/2023/msg00475.html
>> 
> How do you do that?  It would save a lot of repetition if I could 
> research the archives myself.    Such a resource, but inaccessible -- 
> tho you seem to know how.

I just search a folder in my email account.  I've saved almost every
message from the lists since I joined on [checks] December 9, 2013.

-- 
vq


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  5:40     ` Lawrence Velázquez
@ 2024-05-03 12:51       ` Ray Andrews
  0 siblings, 0 replies; 22+ messages in thread
From: Ray Andrews @ 2024-05-03 12:51 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]



On 2024-05-02 22:40, Lawrence Velázquez wrote:
> I just search a folder in my email account.  I've saved almost every
> message from the lists since I joined on [checks] December 9, 2013.
>
Just a while back seems to me there was some thoughts as to making the 
archives searchable.  IMHO that would be most useful.  I know there's 
many times I'd like to dredge up stuff that's been covered previously.  
I remember it was covered but not the details.

[-- Attachment #2: Type: text/html, Size: 910 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  4:58     ` Roman Perepelitsa
@ 2024-05-03 13:14       ` Ray Andrews
  2024-05-20 17:41       ` Kannan Varadhan
  1 sibling, 0 replies; 22+ messages in thread
From: Ray Andrews @ 2024-05-03 13:14 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 270 bytes --]



On 2024-05-02 21:58, Roman Perepelitsa wrote:
> # Examples:
>    #
>    #   % print -r -- $(( srand32() ))
>    #   263510467
>

1 /aWorking/Zsh/Source/Wk 2 % print -r -- $(( srand32() ))
srand32:4: command not found: sysread
4


... how the devil?  It's a builtin.


[-- Attachment #2: Type: text/html, Size: 768 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  3:48   ` Ray Andrews
  2024-05-03  4:58     ` Roman Perepelitsa
  2024-05-03  5:40     ` Lawrence Velázquez
@ 2024-05-03 13:36     ` Clinton Bunch
  2024-05-03 13:58       ` Ray Andrews
  2 siblings, 1 reply; 22+ messages in thread
From: Clinton Bunch @ 2024-05-03 13:36 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1229 bytes --]

On 5/2/2024 22:48, Ray Andrews wrote:
>
>
> On 2024-05-02 20:09, Lawrence Velázquez wrote:
>> 	The values of RANDOM form an intentionally-repeatable
>> 	pseudo-random sequence; subshells that reference RANDOM
>> 	will result in identical pseudo-random values unless the
>> 	value of RANDOM is referenced or seeded in the parent shell
>> 	in between subshell invocations.
> Ok then at least this is intentional.  How does one obtain a genuinely 
> random number then?  TBH, for my particular needs right now the 
> standard behavior is perfect, but as a matter of principle I'd like to 
> know how to get 'real' random numbers.  There will be a way.
'real' random numbers are not possible on a computer, but 'good enough' 
random numbers are available in /dev/random character device file.  I 
have also written the zsh/random module that uses system calls to access 
the same kernel 'random' pool, but it has yet to be accepted for 
addition to the next release.  It provides the SRANDOM parameter (32-bit 
unsigned) similar to modern bash, a zrand_float() math function for 
numbers between 0 and 1, and zrand_int(upper,lower,inclusive) to return 
an integer between two values (32-bit integer max)


[-- Attachment #2: Type: text/html, Size: 1980 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03 13:36     ` Clinton Bunch
@ 2024-05-03 13:58       ` Ray Andrews
  2024-05-03 23:42         ` Lawrence Velázquez
  0 siblings, 1 reply; 22+ messages in thread
From: Ray Andrews @ 2024-05-03 13:58 UTC (permalink / raw)
  To: zsh-users



On 2024-05-03 06:36, Clinton Bunch wrote:
> 'real' random numbers are not possible on a computer, 
Understood, thus the air-quotes.

> but 'good enough' random numbers are available in /dev/random 
> character device file.  I have also written the zsh/random module that 
> uses system calls to access the same kernel 'random' pool, but it has 
> yet to be accepted for addition to the next release. It provides the 
> SRANDOM parameter (32-bit unsigned) similar to modern bash, a 
> zrand_float() math function for numbers between 0 and 1, and 
> zrand_int(upper,lower,inclusive) to return an integer between two 
> values (32-bit integer max)
Sounds luxuriously complete.  I noted in those links that Lawrence 
posted that every one of them considered the existing behavior to be 
'obviously' wrong.  And it is 'obviously' wrong intuitively whatever 
it's merits may be.  A predictable random number isn't.  Besides, if 
bash can offer a 'real' random number then that's established practice 
so we should too.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03 13:58       ` Ray Andrews
@ 2024-05-03 23:42         ` Lawrence Velázquez
  2024-05-04  0:28           ` Bart Schaefer
  2024-05-04  1:19           ` Ray Andrews
  0 siblings, 2 replies; 22+ messages in thread
From: Lawrence Velázquez @ 2024-05-03 23:42 UTC (permalink / raw)
  To: zsh-users

On Fri, May 3, 2024, at 9:58 AM, Ray Andrews wrote:
> I noted in those links that Lawrence 
> posted that every one of them considered the existing behavior to be 
> 'obviously' wrong.  And it is 'obviously' wrong intuitively whatever 
> it's merits may be.  A predictable random number isn't.

This is just a consequence of the name "RANDOM", which unfortunately
implies a property that the parameter doesn't quite have.  There is
nothing "'obviously' wrong" with repeatable pseudorandom sequences.

Also, seven discussions over ten years doesn't exactly scream
"everyone is super confused by this".

> Besides, if 
> bash can offer a 'real' random number then that's established practice 
> so we should too.

Copying bash's "established practice" is not a reason to do anything.
Bash has plenty of misfeatures and poor design decisions that should
not be imitated.  If we choose to ship Clinton's module, it will
be because it is useful, not because of any perceived need to catch
up to another shell.

-- 
vq


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03 23:42         ` Lawrence Velázquez
@ 2024-05-04  0:28           ` Bart Schaefer
  2024-05-04  1:32             ` Ray Andrews
  2024-05-05  6:17             ` Lawrence Velázquez
  2024-05-04  1:19           ` Ray Andrews
  1 sibling, 2 replies; 22+ messages in thread
From: Bart Schaefer @ 2024-05-04  0:28 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 348 bytes --]

On Fri, May 3, 2024 at 4:43 PM Lawrence Velázquez <larryv@zsh.org> wrote:
>
> Also, seven discussions over ten years doesn't exactly scream
> "everyone is super confused by this".

No, but it might be enough to qualify for the "F" in "AQ".

> https://www.zsh.org/mla/users/2023/msg00475.html

That one isn't really the same Q, though.

[-- Attachment #2: random-faq.txt --]
[-- Type: text/plain, Size: 1811 bytes --]

diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index 4e11637ea..2c83fe7fa 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -137,6 +137,7 @@ Chapter 3:  How to get various things to work
 3.28. How do I edit the input buffer in $EDITOR?
 3.29. Why does `which' output for missing commands go to stdout?
 3.30. Why doesn't the expansion mytt(*.{tex,aux,pdf}) do what I expect?
+3.31. Why does mytt($RANDOM) return the same number more than once?
 
 Chapter 4:  The mysteries of completion
 4.1. What is completion?
@@ -2219,6 +2220,37 @@ sect(Why doesn't the expansion mytt(*.{tex,aux,pdf}) do what I expect?)
   This is harder for the user to remember but easier for the shell to
   parse!
 
+sect(Why does mytt($RANDOM) return the same number more than once?)
+
+  As tt(zshparam(1)) says:
+  verb(
+      The values of RANDOM form an intentionally-repeatable
+      pseudo-random sequence; subshells that reference RANDOM
+      will result in identical pseudo-random values unless the
+      value of RANDOM is referenced or seeded in the parent shell
+      in between subshell invocations.
+  )
+
+  You can use a function, including an anonymous function, to always
+  evaluate mytt($RANDOM) in the parent shell.  This example illustrates
+  the difference:
+  verb(
+    for i in {1..10}; do
+      echo subshell: $(echo $RANDOM) $RANDOM
+      () { echo parent: $(echo $1) $2 } $RANDOM $RANDOM;
+    done
+  )
+
+  Remember that for a pipe like mytt(A | B), zsh runs A in a subshell
+  and B in the current shell.  This means that, for example:
+  verb(
+    for i in {1..10}; do
+      echo $RANDOM | tee
+    done
+  )
+  also repeats the same value, because mytt($RANDOM) is evaluated in
+  the subshell and the parent sequence is left unchanged.
+
 chapter(The mysteries of completion)
 
 sect(What is completion?)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03 23:42         ` Lawrence Velázquez
  2024-05-04  0:28           ` Bart Schaefer
@ 2024-05-04  1:19           ` Ray Andrews
  1 sibling, 0 replies; 22+ messages in thread
From: Ray Andrews @ 2024-05-04  1:19 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1371 bytes --]



On 2024-05-03 16:42, Lawrence Velázquez wrote:
> This is just a consequence of the name "RANDOM", which unfortunately
> implies a property that the parameter doesn't quite have.  There is
> nothing "'obviously' wrong" with repeatable pseudorandom sequences.
Indeed.  As I said, the current behavior suits my current need 
perfectly.  Still I'd say that a 'real' random number should be 
available.  One can't have too many resources.
> Also, seven discussions over ten years doesn't exactly scream
> "everyone is super confused by this".
Not exactly a crisis, still I think I'm not alone in being surprised by 
the current behavior.
> Copying bash's "established practice" is not a reason to do anything.
But I have noticed a strong deference to tradition and consensus, so it 
at least does not hurt that bash has 'real' random numbers.
> Bash has plenty of misfeatures and poor design decisions that should
> not be imitated.  If we choose to ship Clinton's module, it will
> be because it is useful, not because of any perceived need to catch
> up to another shell.
I'd not put it that way.  Of course it would have to be a genuine 
improvement. 'Catching up' is not a mentality I think any of us have.  
It seems to be near universally agreed that zsh is by far the more 
advanced shell. Still a precedent exists.  It is to be noted casually, 
that's all.



[-- Attachment #2: Type: text/html, Size: 2577 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-04  0:28           ` Bart Schaefer
@ 2024-05-04  1:32             ` Ray Andrews
  2024-05-05  6:17             ` Lawrence Velázquez
  1 sibling, 0 replies; 22+ messages in thread
From: Ray Andrews @ 2024-05-04  1:32 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 532 bytes --]



On 2024-05-03 17:28, Bart Schaefer wrote:
> No, but it might be enough to qualify for the "F" in "AQ".
>
+3.31. Why does mytt($RANDOM) return the same number more than once?
  
What I like is that even acknowledging that the question is out there goes half way to answering it.  The question first awakens you to the fact that zsh is aware that what 'you' think 'RANDOM' means might not be what the shell delivers.  That's half the battle right there.  De-confused, one then seeks a method of producing 'real' random numbers.
   

[-- Attachment #2: Type: text/html, Size: 1018 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-04  0:28           ` Bart Schaefer
  2024-05-04  1:32             ` Ray Andrews
@ 2024-05-05  6:17             ` Lawrence Velázquez
  2024-05-05 15:35               ` Bart Schaefer
  1 sibling, 1 reply; 22+ messages in thread
From: Lawrence Velázquez @ 2024-05-05  6:17 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

On Fri, May 3, 2024, at 8:28 PM, Bart Schaefer wrote:
> On Fri, May 3, 2024 at 4:43 PM Lawrence Velázquez <larryv@zsh.org> wrote:
>> https://www.zsh.org/mla/users/2023/msg00475.html
>
> That one isn't really the same Q, though.

Hm, I guess I didn't read it closely enough.  Is the difference
that that one is really about the consequences of pipeline stages
forking earlier than they used to?

-- 
vq


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-05  6:17             ` Lawrence Velázquez
@ 2024-05-05 15:35               ` Bart Schaefer
  0 siblings, 0 replies; 22+ messages in thread
From: Bart Schaefer @ 2024-05-05 15:35 UTC (permalink / raw)
  To: Zsh Users

On Sat, May 4, 2024 at 11:18 PM Lawrence Velázquez <larryv@zsh.org> wrote:
>
> On Fri, May 3, 2024, at 8:28 PM, Bart Schaefer wrote:
> > On Fri, May 3, 2024 at 4:43 PM Lawrence Velázquez <larryv@zsh.org> wrote:
> >> https://www.zsh.org/mla/users/2023/msg00475.html
> >
> > That one isn't really the same Q, though.
>
> Hm, I guess I didn't read it closely enough.  Is the difference
> that that one is really about the consequences of pipeline stages
> forking earlier than they used to?

It's about parameters that used to be expanded after forking, instead
being expanded before forking.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-03  4:58     ` Roman Perepelitsa
  2024-05-03 13:14       ` Ray Andrews
@ 2024-05-20 17:41       ` Kannan Varadhan
  2024-05-20 18:01         ` Roman Perepelitsa
  1 sibling, 1 reply; 22+ messages in thread
From: Kannan Varadhan @ 2024-05-20 17:41 UTC (permalink / raw)
  To: Roman Perepelitsa, Ray Andrews; +Cc: zsh-users

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@eastlink.ca> 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
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 17:41       ` Kannan Varadhan
@ 2024-05-20 18:01         ` Roman Perepelitsa
  2024-05-20 19:14           ` Kannan Varadhan
  0 siblings, 1 reply; 22+ messages in thread
From: Roman Perepelitsa @ 2024-05-20 18:01 UTC (permalink / raw)
  To: Kannan Varadhan; +Cc: Ray Andrews, zsh-users

On Mon, May 20, 2024 at 7:41 PM Kannan Varadhan <kvaradhan3@gmail.com> wrote:
>
> 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))`?

Reading 1 byte at a time is slower than reading 4 bytes at once.

> >      local b1=$bytes[1] b2=$bytes[2] b3=$bytes[3] b4=$bytes[4]
> >      return '#b1 << 24 | #b2 << 16 | #b3 << 8 | #b4'
>
> Why copy to a scalar parameters

My goal was to implement the contract described in the comments. This
is how I managed to do it. Your asking "why" appears to imply that you
have another implementation in mind that is more natural to you. If
so, can you post it?

> what does referring to them as '#b1', #b2', ... mean.

These are the numeric values of the bytes held in b1..b4.

    % x='A'
    % print -r -- $(( #x ))
    65

Roman.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 18:01         ` Roman Perepelitsa
@ 2024-05-20 19:14           ` Kannan Varadhan
  2024-05-20 19:40             ` Roman Perepelitsa
                               ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Kannan Varadhan @ 2024-05-20 19:14 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Ray Andrews, zsh-users

[-- Attachment #1: Type: text/plain, Size: 1539 bytes --]


On 5/20/24 11:01, Roman Perepelitsa wrote:
> On Mon, May 20, 2024 at 7:41 PM Kannan Varadhan<kvaradhan3@gmail.com>  wrote:
>> 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))`?
> Reading 1 byte at a time is slower than reading 4 bytes at once.

ok but the loop seems to read 4, then 3, 2, and 1B in each iteration, or 
did I miss something?

>>>       local b1=$bytes[1] b2=$bytes[2] b3=$bytes[3] b4=$bytes[4]
>>>       return '#b1 << 24 | #b2 << 16 | #b3 << 8 | #b4'
>> Why copy to a scalar parameters
> My goal was to implement the contract described in the comments. This
> is how I managed to do it. Your asking "why" appears to imply that you
> have another implementation in mind that is more natural to you. If
> so, can you post it?

i dont have an alternate implementation.  I was trying to use 
'#bytes[1]' directly and that did not work.

>> what does referring to them as '#b1', #b2', ... mean.
> These are the numeric values of the bytes held in b1..b4.
>
>      % x='A'
>      % print -r -- $(( #x ))
>      65


Interesting,


Kannan

[-- Attachment #2: Type: text/html, Size: 3174 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 19:14           ` Kannan Varadhan
@ 2024-05-20 19:40             ` Roman Perepelitsa
  2024-05-20 22:56             ` Bart Schaefer
  2024-05-24 22:49             ` Bart Schaefer
  2 siblings, 0 replies; 22+ messages in thread
From: Roman Perepelitsa @ 2024-05-20 19:40 UTC (permalink / raw)
  To: Kannan Varadhan; +Cc: Ray Andrews, zsh-users

On Mon, May 20, 2024 at 9:14 PM Kannan Varadhan <kvaradhan3@gmail.com> wrote:
>
> ok but the loop seems to read 4, then 3, 2, and 1B in each
> iteration, or did I miss something?

You can add something like 'print reading' in that loop to see how
many times sysread is invoked.

> i dont have an alternate implementation.  I was trying to use '#bytes[1]' directly and that did not work.

That's "why" then.

Roman.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 19:14           ` Kannan Varadhan
  2024-05-20 19:40             ` Roman Perepelitsa
@ 2024-05-20 22:56             ` Bart Schaefer
  2024-05-21 15:43               ` Mark J. Reed
  2024-05-24 22:49             ` Bart Schaefer
  2 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2024-05-20 22:56 UTC (permalink / raw)
  To: Kannan Varadhan; +Cc: zsh-users

On Mon, May 20, 2024 at 12:14 PM Kannan Varadhan <kvaradhan3@gmail.com> wrote:
>
>> On 5/20/24 11:01, Roman Perepelitsa wrote:
>
>>> what does referring to them as '#b1', #b2', ... mean.
>
>> These are the numeric values of the bytes held in b1..b4.
>>
>>     % x='A'
>>     % print -r -- $(( #x ))
>>     65
>
> Interesting

This is documented in the "Arithmetic Evaluation" section of the
manual, about 3/4 of the way through:

An expression of the form '##X' where X is any character sequence such
as 'a', '^A', or '\M-\C-x' gives the value of this character and an
expression of the form '#NAME' gives the value of the first character of
the contents of the parameter NAME.  Character values are according to
the character set used in the current locale; for multibyte character
handling the option MULTIBYTE must be set.  Note that this form is
different from '$#NAME', a standard parameter substitution which gives
the length of the parameter NAME.  '#\' is accepted instead of '##', but
its use is deprecated.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 22:56             ` Bart Schaefer
@ 2024-05-21 15:43               ` Mark J. Reed
  0 siblings, 0 replies; 22+ messages in thread
From: Mark J. Reed @ 2024-05-21 15:43 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Kannan Varadhan, zsh-users

[-- Attachment #1: Type: text/plain, Size: 1091 bytes --]

On Mon, May 20, 2024 at 6:57 PM Bart Schaefer <schaefer@brasslantern.com>
wrote:

> This is documented in the "Arithmetic Evaluation" section of the
> manual, about 3/4 of the way through:
>
> An expression of the form '##X' where X is any character sequence such
> as 'a', '^A', or '\M-\C-x' gives the value of this character and an
> expression of the form '#NAME' gives the value of the first character of
> the contents of the parameter NAME.  Character values are according to
> the character set used in the current locale; for multibyte character
> handling the option MULTIBYTE must be set.  Note that this form is
> different from '$#NAME', a standard parameter substitution which gives
> the length of the parameter NAME.  '#\' is accepted instead of '##', but
> its use is deprecated.
>

Note that the *## *form does work fine in conjunction with parameter
expansion:

$ msg=hello
$ for (( i=1; i <= $#msg; ++i )); do echo $(( ##$msg[i] )); done
104
101
108
108
111

But that's not particularly efficient.

-- 
Mark J. Reed <markjreed@gmail.com>

[-- Attachment #2: Type: text/html, Size: 1989 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: rigorously predictable random numbers
  2024-05-20 19:14           ` Kannan Varadhan
  2024-05-20 19:40             ` Roman Perepelitsa
  2024-05-20 22:56             ` Bart Schaefer
@ 2024-05-24 22:49             ` Bart Schaefer
  2 siblings, 0 replies; 22+ messages in thread
From: Bart Schaefer @ 2024-05-24 22:49 UTC (permalink / raw)
  To: Kannan Varadhan; +Cc: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1557 bytes --]

On Mon, May 20, 2024 at 12:14 PM Kannan Varadhan <kvaradhan3@gmail.com>
wrote:

> On 5/20/24 11:01, Roman Perepelitsa wrote:
>
> On Mon, May 20, 2024 at 7:41 PM Kannan Varadhan <kvaradhan3@gmail.com> <kvaradhan3@gmail.com> wrote:
>
>      while (( $#bytes < 4 )); do
>        sysread -s$((4-$#bytes)) 'bytes[$#bytes+1]' </dev/urandom || return
>      done
>
> Reading 1 byte at a time is slower than reading 4 bytes at once.
>
> ok but the loop seems to read 4, then 3, 2, and 1B in each iteration, or
> did I miss something?
>

To clarify this, it has to do with the way sysread assigns to the parameter
'bytes[$#bytes+1]'.

On the first iteration, $#bytes == 0, so this is 'bytes[1]'.  Assignment to
a subscripted parameter reference replaces the element at the subscript
position (or positions, if a range is given, which is not allowed for
associative arrays) with the assigned value.  Thus all bytes returned from
/dev/urandom in the first read are inserted in place of position 1 in the
string bytes.  There's nothing at position 1 yet in this case, so that
becomes the entire value of $bytes.  If fewer than 4 bytes were returned --
say, 2 -- then at the next iteration we sysread into bytes[3], which is
past the end of the existing 2-byte value, so has the effect of appending
the next series of bytes and lengthening the string.

Upshot:  The loop attempts to read the exact number of (remaining) bytes
necessary to fill a four-byte string, and repeatedly appends if and only if
it doesn't yet have all four.

[-- Attachment #2: Type: text/html, Size: 2328 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-05-24 22:51 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-03  1:23 rigorously predictable random numbers Ray Andrews
2024-05-03  3:09 ` Lawrence Velázquez
2024-05-03  3:48   ` Ray Andrews
2024-05-03  4:58     ` Roman Perepelitsa
2024-05-03 13:14       ` Ray Andrews
2024-05-20 17:41       ` Kannan Varadhan
2024-05-20 18:01         ` Roman Perepelitsa
2024-05-20 19:14           ` Kannan Varadhan
2024-05-20 19:40             ` Roman Perepelitsa
2024-05-20 22:56             ` Bart Schaefer
2024-05-21 15:43               ` Mark J. Reed
2024-05-24 22:49             ` Bart Schaefer
2024-05-03  5:40     ` Lawrence Velázquez
2024-05-03 12:51       ` Ray Andrews
2024-05-03 13:36     ` Clinton Bunch
2024-05-03 13:58       ` Ray Andrews
2024-05-03 23:42         ` Lawrence Velázquez
2024-05-04  0:28           ` Bart Schaefer
2024-05-04  1:32             ` Ray Andrews
2024-05-05  6:17             ` Lawrence Velázquez
2024-05-05 15:35               ` Bart Schaefer
2024-05-04  1:19           ` Ray Andrews

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).