POV-Ray : Newsgroups : povray.off-topic : More random humous : Re: More random humous Server Time
7 Sep 2024 03:22:02 EDT (-0400)
  Re: More random humous  
From: Invisible
Date: 7 Oct 2008 08:43:29
Message: <48eb5971$1@news.povray.org>
>> You write a function that takes a PRNG state and returns a random number 
>> and a new PRNG state.
> 
>   Where do you store this state, given that you can't assign it to anything?

It's not so hard.

   get_random :: Seed -> (Int, Seed)

   foo :: Seed -> (Int, Seed)
   foo s0 =
     let
       (x1,s1) = get_random s0
       (x2,s2) = get_random s1
       (x3,s3) = get_random s2
     in ((x1 + x2 + x3) `div` 3, s3)

   bar :: Seed -> ([Int], Seed)
   bar s0 =
     let
       (y1,s1) = foo s0
       (y2,s2) = foo s1
       (y3,s3) = foo s2
     in ([y1, y2, y3], s3)

Here "foo" grabs three random numbers and returns their arithmetic mean. 
(And also returns the final PRNG seed, in case anybody else wants it.) 
Basically you create a new variable for each version of the seed value.

(Similarly, "bar" calls "foo" three times to generate three (more 
uniformly distributed) random numbers and returns them in a list - along 
with the new seed.)

>   But then the calling code would have to keep that seed somewhere. This
> can be a real burden if the same RNG stream would need to be used in
> different parts of the code.

Yes. This does quickly become tedious if you need random numbers all 
over the place. In principle each function that uses it must take an 
initial seed value, and return a new seed value as part of its result. 
And the callers must remember to use the correct version of the state 
each time.

(E.g., imagine if I make a typo and foo actually returns s0 instead of 
s3. Now the "random" number generator appears to always return the same 
result!)

But basically, it works.

You can improve it by using a state monad. This basically means that the 
seed is invisibly passed from place to place automatically (and you 
can't accidentally use the wrong seed by mistake).

Alternatively, you can go down the mutable state road. On the face of 
it, this would still require you to pass around a reference to the 
mutable state, because Haskell doesn't have mutable global variables. So 
some hacking is required there.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.