[MLton] cvs commit: rewrite of MLton.Random.alphaNumString
Stephen Weeks
sweeks@mlton.org
Sun, 28 Dec 2003 15:15:01 -0800
sweeks 03/12/28 15:15:01
Modified: basis-library/mlton random.sig random.sml
lib/mlton-stubs random.sml
Log:
MAIL rewrite of MLton.Random.alphaNumString
Used Matthew's (excellent) suggestion to compute the refresh period.
Also added alphaNumChar, which will save even a few more random bits.
Please check for errors :-).
Revision Changes Path
1.4 +3 -0 mlton/basis-library/mlton/random.sig
Index: random.sig
===================================================================
RCS file: /cvsroot/mlton/mlton/basis-library/mlton/random.sig,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- random.sig 10 Apr 2003 02:03:01 -0000 1.3
+++ random.sig 28 Dec 2003 23:15:00 -0000 1.4
@@ -3,6 +3,9 @@
signature MLTON_RANDOM =
sig
+ (* Return a random alphanumeric character. *)
+ val alphaNumChar: unit -> char
+
(* Return a string of random alphanumeric characters of specified
* length.
*)
1.8 +21 -16 mlton/basis-library/mlton/random.sml
Index: random.sml
===================================================================
RCS file: /cvsroot/mlton/mlton/basis-library/mlton/random.sml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- random.sml 28 Dec 2003 22:43:48 -0000 1.7
+++ random.sml 28 Dec 2003 23:15:00 -0000 1.8
@@ -61,22 +61,27 @@
local
val chars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- val n = Word.fromInt (String.size chars)
- val r: word ref = ref 0w0
+ val refresh =
+ Int.quot (Word.wordSize,
+ 1 + IntInf.log2 (IntInf.fromInt (String.size chars)))
+ val r: word ref = ref (rand ())
+ val count: int ref = ref 0
+ val numChars = Word.fromInt (String.size chars)
in
- fun alphaNumString (length: int) =
- String.tabulate
- (length, fn i =>
- let
- val _ =
- if 0 = Int.rem (i, 6) (* n^6 = 62^6 = 965,660,736 *)
- then r := rand ()
- else ()
- val w = !r
- val c = String.sub (chars, Word.toInt (Word.mod (w, n)))
- val _ = r := Word.div (w, n)
- in
- c
- end)
+ 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
end
+
+ fun alphaNumString (length: int): string =
+ String.tabulate (length, fn _ => alphaNumChar ())
end
1.4 +32 -26 mlton/lib/mlton-stubs/random.sml
Index: random.sml
===================================================================
RCS file: /cvsroot/mlton/mlton/lib/mlton-stubs/random.sml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- random.sml 28 Dec 2003 22:45:36 -0000 1.3
+++ random.sml 28 Dec 2003 23:15:01 -0000 1.4
@@ -15,33 +15,39 @@
end
fun srand (w: word): unit = seed := w
-
- structure String =
- struct
- open String
+ end
+
+ structure String =
+ struct
+ open String
- val tabulate = CharVector.tabulate
- end
- local
- val chars =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- val n = Word.fromInt (String.size chars)
- val r: word ref = ref 0w0
- in
- fun alphaNumString (length: int) =
- String.tabulate
- (length, fn i =>
- let
- val _ =
- if 0 = Int.rem (i, 6) (* n^6 = 62^6 = 965,660,736 *)
- then r := rand ()
- else ()
- val w = !r
- val c = String.sub (chars, Word.toInt (Word.mod (w, n)))
- val _ = r := Word.div (w, n)
- in
- c
- end)
+ val tabulate = CharVector.tabulate
end
+
+ local
+ val chars =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ val refresh =
+ Int.quot (Word.wordSize,
+ 1 + IntInf.log2 (IntInf.fromInt (String.size chars)))
+ 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
end
+
+ fun alphaNumString (length: int): string =
+ String.tabulate (length, fn _ => alphaNumChar ())
end