[MLton] cvs commit: rewrite of MLton.Random.alphaNumString
Matthew Fluet
fluet@cs.cornell.edu
Sun, 28 Dec 2003 18:32:07 -0500 (EST)
> + val refresh =
> + Int.quot (Word.wordSize,
> + 1 + IntInf.log2 (IntInf.fromInt (String.size chars)))
The only thing I disliked about this is the fact that it is overly
conservative on powers of 2; i.e., the refresh rate on 64 chars is
computed as 4 rather than 5. I'd really want IntInf.log2 to return the
ceil rather than the floor.
> + val r: word ref = ref (rand ())
> + val count: int ref = ref 0
> + val numChars = Word.fromInt (String.size chars)
> in
> + fun alphaNumChar (): char =
> + let
> + val n = !count
> + val _ = if 0 = n then r := rand () else ()
> + val w = !r
> + val c = String.sub (chars, Word.toInt (Word.mod (w, numChars)))
> + val _ = r := Word.div (w, numChars)
> + val n = n + 1
> + val _ = count := (if n = refresh then 0 else n)
> + in
> + c
> + end
Looks correct, but a little redundant. How about:
> + val r: word ref = ref (rand ())
> + val count: int ref = ref refresh
> + val numChars = Word.fromInt (String.size chars)
> in
> + fun alphaNumChar (): char =
> + let
> + val n = !count
> + val _ = if n = refresh
> + then (r := rand ()
> + ; count := 1)
> + else (count := n + 1)
> + val w = !r
> + val c = String.sub (chars, Word.toInt (Word.mod (w, numChars)))
> + val _ = r := Word.div (w, numChars)
> + in
> + c
> + end
We only do one comparison per character.