[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.