[commit: random] master: Extended the float fix to Doubles. Fixed a bug introduced by the last checkin. next is not a sufficient substitute for randomBounded in the Int instance. It doesn't have sufficient genRange. (6280211)

Ian Lynagh igloo at earth.li
Sun Jun 26 15:55:55 CEST 2011


Repository : ssh://darcs.haskell.org//srv/darcs/packages/random

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/628021146f6890d41175cc2eafc3da120da11948

>---------------------------------------------------------------

commit 628021146f6890d41175cc2eafc3da120da11948
Author: Ryan Newton <rrnewton at gmail.com>
Date:   Sun Jun 26 02:18:52 2011 -0400

    Extended the float fix to Doubles.  Fixed a bug introduced by the last checkin.  next is not a sufficient substitute for randomBounded in the Int instance.  It doesn't have sufficient genRange.

>---------------------------------------------------------------

 Benchmark/SimpleRNGBench.hs |    2 ++
 System/Random.hs            |   37 +++++++++++++++++++++++--------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/Benchmark/SimpleRNGBench.hs b/Benchmark/SimpleRNGBench.hs
index 71f55f4..2d1bd72 100644
--- a/Benchmark/SimpleRNGBench.hs
+++ b/Benchmark/SimpleRNGBench.hs
@@ -189,6 +189,8 @@ approxBounds initrng nxt iters = (mn_, mx_, sum_ / fromIntegral iters)
 floatBounds :: IO (Float, Float, Float)
 floatBounds = do g<-getStdGen; return$ approxBounds g random 100000 :: IO (Float,Float,Float)
 
+doubleBounds :: IO (Double, Double, Double)
+doubleBounds = do g<-getStdGen; return$ approxBounds g random 100000 :: IO (Double,Double,Double)
 
 ----------------------------------------------------------------------------------------------------
 -- Main Script
diff --git a/System/Random.hs b/System/Random.hs
index 1364b98..b36cb28 100644
--- a/System/Random.hs
+++ b/System/Random.hs
@@ -33,6 +33,8 @@
 --
 -----------------------------------------------------------------------------
 
+#include "MachDeps.h"
+
 module System.Random
 	(
 
@@ -285,7 +287,7 @@ instance Random Integer where
   randomR ival g = randomIvalInteger ival g
   random g	 = randomR (toInteger (minBound::Int), toInteger (maxBound::Int)) g
 
-instance Random Int        where randomR = randomIvalIntegral; random = next
+instance Random Int        where randomR = randomIvalIntegral; random = randomBounded
 instance Random Int8       where randomR = randomIvalIntegral; random = randomBounded
 instance Random Int16      where randomR = randomIvalIntegral; random = randomBounded
 instance Random Int32      where randomR = randomIvalIntegral; random = randomBounded
@@ -343,38 +345,45 @@ instance Random Bool where
 
 instance Random Double where
   randomR ival g = randomIvalDouble ival id g
-  random g       = randomR (0::Double,1) g
+  random rng     = 
+    case random rng of 
+      (x,rng') -> 
+          -- We use 53 bits of randomness corresponding to the 53 bit significand:
+          ((fromIntegral (mask53 .&. (x::Int64)) :: Double)  
+	   /  fromIntegral twoto53, rng')
+   where 
+    twoto53 = (2::Int64) ^ (53::Int64)
+    mask53 = twoto53 - 1
   
 instance Random Float where
   randomR = randomIvalFrac
   random rng = 
-    case next rng of 
+    -- TODO: Faster to just use 'next' IF it generates enough bits of randomness.   
+    case random rng of 
       (x,rng') -> 
-         let 
-            -- We use 24 bits of randomness corresponding to the 24 bit significand:
-            rand = fromIntegral (mask24 .&. x) 
-		   :: Float
-	 in 
-         (rand / fromIntegral twoto24, rng')
+          -- We use 24 bits of randomness corresponding to the 24 bit significand:
+          ((fromIntegral (mask24 .&. (x::Int32)) :: Float) 
+	   /  fromIntegral twoto24, rng')
 	 -- Note, encodeFloat is another option, but I'm not seeing slightly
 	 --  worse performance with the following [2011.06.25]:
 --         (encodeFloat rand (-24), rng')
    where
-     mask24 :: Int 
      mask24 = twoto24 - 1
-     -- RRN: Note, in my tests [2011.06.25] this worked as well as using Data.Bit:
-     twoto24 = (2::Int) ^ (24::Int)
+     twoto24 = (2::Int32) ^ (24::Int32)
 
 
 instance Random CFloat where
   randomR = randomIvalFrac
   random rng = case random rng of 
-	         (x,rng') -> (realToFrac (x::Float), rng')
+  	         (x,rng') -> (realToFrac (x::Float), rng')
 
 instance Random CDouble where
   randomR = randomIvalFrac
+  -- Presently, this is showing better performance than the Double instance:
+  -- (And yet, if the Double instance uses randomFracthen its performance is much worse!)
   random  = randomFrac
-
+  -- random rng = case random rng of 
+  -- 	         (x,rng') -> (realToFrac (x::Double), rng')
 
 mkStdRNG :: Integer -> IO StdGen
 mkStdRNG o = do





More information about the Cvs-libraries mailing list