[MLton-commit] r6005
Vesa Karvonen
vesak at mlton.org
Thu Sep 6 07:20:05 PDT 2007
A couple of new operation (word8 and bits) for random generators. Minor
refactoring.
----------------------------------------------------------------------
U mltonlib/trunk/com/ssh/random/unstable/detail/mk-random-gen.fun
U mltonlib/trunk/com/ssh/random/unstable/public/random-gen.sig
----------------------------------------------------------------------
Modified: mltonlib/trunk/com/ssh/random/unstable/detail/mk-random-gen.fun
===================================================================
--- mltonlib/trunk/com/ssh/random/unstable/detail/mk-random-gen.fun 2007-09-06 14:09:17 UTC (rev 6004)
+++ mltonlib/trunk/com/ssh/random/unstable/detail/mk-random-gen.fun 2007-09-06 14:20:02 UTC (rev 6005)
@@ -6,8 +6,7 @@
functor MkRandomGen (RNG : RNG) :>
RANDOM_GEN where type RNG.t = RNG.t
- where type RNG.Seed.t = RNG.Seed.t =
-struct
+ where type RNG.Seed.t = RNG.Seed.t = struct
(* <-- SML/NJ workarounds *)
open TopLevel
infix 4 <\
@@ -25,7 +24,7 @@
type 'a t = 'a dom -> 'a cod
fun generate n t =
- pass (W.toInt (RNG.value t mod (W.fromInt n)), RNG.next t)
+ pass (W.toInt (RNG.value t mod W.fromInt n), RNG.next t)
fun lift r2a = r2a o Pair.snd
@@ -33,7 +32,8 @@
MkMonad (type 'a monad = 'a t
val return = const
fun (m >>= k) (n, r) =
- k (m (n, RNG.split 0w314 r)) (n, RNG.split 0w159 r))
+ k (m (n, RNG.split 0wx4969599B r))
+ (n, RNG.split 0wx1AB25A6D r))
open Monad
@@ -52,6 +52,11 @@
fun sized i2g (n, r) = i2g n (n, r)
fun resize f g = g o Pair.map (f, id)
fun bool (_, r) = RNG.maxValue div 0w2 < RNG.value r
+ local
+ val n = 0w256 val d = RNG.maxValue div n val m = d * n
+ in
+ fun word8 (_, r) = Word8.fromWord (RNG.value r mod m div d)
+ end
fun Y ? = Tie.pure (fn () => let
val r = ref (raising Fix.Fix)
@@ -64,11 +69,35 @@
fun inRange bInRange (a2b, b2a) =
map b2a o bInRange o Pair.map (Sq.mk a2b)
+ fun list aG n =
+ if n < 0 then raise Domain
+ else fn (s, r) =>
+ List.unfoldl (fn 0w0 => NONE
+ | i => SOME (aG (s, RNG.split i r), i-0w1))
+ (W.fromInt n)
+
+ fun bits n = (* XXX this is O(n*n), O(n) is possible via IntInf.scan *)
+ if n < 0 then raise Domain else let
+ val msk = IntInf.<< (1, Word.fromInt n) - 1
+ in
+ lift (fn r => let
+ fun lp (n, r, i) =
+ if 0 < n
+ then lp (n - 8,
+ RNG.next r,
+ IntInf.<< (i, 0w8) +
+ Word8.toLargeInt (word8 (0, r)))
+ else IntInf.andb (i, msk)
+ in
+ lp (n, r, 0)
+ end)
+ end
+
fun wordInRange (l, h) =
(assert (fn () => l <= h)
; let val n = h - l + 0w1 (* XXX may overflow *)
val d = RNG.maxValue div n (* XXX may result in zero *)
- val m = n * d
+ val m = d * n
in lift (fn r => RNG.value r mod m div d + l)
end)
@@ -78,19 +107,21 @@
(inRange wordInRange (Iso.swap W.isoInt) (0, h - l)))
local
- val w2r = R.fromLargeInt o W.toLargeInt
+ val () = if R.radix <> 2 then fail "Real.radix <> 2" else ()
+ val d = R.fromLargeInt (IntInf.<< (1, W.fromInt R.precision) - 1)
in
fun realInRange (l, h) =
(assert (fn () => l <= h)
- ; let val m = (h - l) / w2r RNG.maxValue
- in fn (_, r) => w2r (RNG.value r) * m + l
+ ; let val m = (h - l) / d
+ in map (fn i => R.fromLargeInt i * m + l) (bits R.precision)
end)
end
- fun elements xs =
- let val xs = V.fromList xs
- in map (xs <\ V.sub) (intInRange (0, V.length xs))
- end
+ fun elements xs = let
+ val xs = V.fromList xs
+ in
+ map (xs <\ V.sub) (intInRange (0, V.length xs))
+ end
fun oneOf gs = elements gs >>= id
@@ -107,22 +138,4 @@
in
intInRange (1, tot) >>= pick 0
end
-
- local
- fun unfold px sx x2y = let
- fun lp ys x =
- if px x then
- rev ys
- else
- lp (x2y x::ys) (sx x)
- in
- lp []
- end
- in
- fun list ga m (n, r) =
- unfold (op = /> 0w0)
- (op - /> 0w1)
- (fn i => ga (n, RNG.split i r))
- (W.fromInt m)
- end
end
Modified: mltonlib/trunk/com/ssh/random/unstable/public/random-gen.sig
===================================================================
--- mltonlib/trunk/com/ssh/random/unstable/public/random-gen.sig 2007-09-06 14:09:17 UTC (rev 6004)
+++ mltonlib/trunk/com/ssh/random/unstable/public/random-gen.sig 2007-09-06 14:20:02 UTC (rev 6005)
@@ -44,6 +44,9 @@
val wordInRange : Word.t Sq.t -> Word.t t
val bool : Bool.t t
+ val word8 : Word8.t t
+ val bits : Int.t -> IntInf.t t
+
val list : 'a t -> Int.t -> 'a List.t t
end
More information about the MLton-commit
mailing list