[commit: packages/random] new_api: Intermediate checkin. Fixed one bug with the order of type conversion/shifting. Right now trying to fix randomIvalBits behavior on (signed) Ints. (7f44303)

git at git.haskell.org git at git.haskell.org
Thu Mar 19 15:43:55 UTC 2015


Repository : ssh://git@git.haskell.org/random

On branch  : new_api
Link       : http://git.haskell.org/packages/random.git/commitdiff/7f44303fc009b282f940b986ab93feaaaba31489

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

commit 7f44303fc009b282f940b986ab93feaaaba31489
Author: Ryan Newton <rrnewton at gmail.com>
Date:   Mon Jun 27 13:05:25 2011 -0400

    Intermediate checkin.  Fixed one bug with the order of type conversion/shifting.  Right now trying to fix randomIvalBits behavior on (signed) Ints.


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

7f44303fc009b282f940b986ab93feaaaba31489
 DEVLOG.md        |  1 +
 System/Random.hs | 33 ++++++++++++++++++++++++---------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/DEVLOG.md b/DEVLOG.md
index db1d12f..b482f1f 100644
--- a/DEVLOG.md
+++ b/DEVLOG.md
@@ -201,3 +201,4 @@ randomIvalBits uses a very inefficient bitScanReverse which can be
 improved.  And in spite of that it didn't slow down TOO much.  Also,
 randomIvalBits can fix the problems in tickets #5278 and #5280 having
 to do with uniformity and assumptions about the generators.
+
diff --git a/System/Random.hs b/System/Random.hs
index eac2e1e..7a162ef 100644
--- a/System/Random.hs
+++ b/System/Random.hs
@@ -89,7 +89,14 @@ import Data.Char	( isSpace, chr, ord )
 import System.IO.Unsafe ( unsafePerformIO )
 import Data.IORef
 import Numeric		( readDec )
+
+
+#define DEBUGRAND
+#ifdef DEBUGRAND
+import Numeric		( showIntAtBase )
+import Data.Char     ( intToDigit )
 import Debug.Trace
+#endif
 
 -- The standard nhc98 implementation of Time.ClockTime does not match
 -- the extended one expected in this module, so we lash-up a quick
@@ -425,9 +432,13 @@ randomBits desired gen =
 		 if bits <= c
 		 then loop g' (acc `shiftL` bits .|. fromIntegral x) (c - bits)
 		 -- Otherwise we must make sure not to generate too many bits:
-	         else let shft = min bits c in
-		      (acc `shiftL` shft .|. (fromIntegral x `shiftR` fromIntegral (bits - shft)),
-		       g')
+	         else 
+		      let shifted = fromIntegral (x `shiftR` (bits - c)) in
+#ifdef DEBUGRAND
+		      trace ("    Got random "++ showIntAtBase 16 intToDigit x "" ++
+		      	     ", shifted "++ show (bits-c)++": " ++ show shifted) $
+#endif
+		      (acc `shiftL` c .|. shifted, g')
 	in loop gen 0 desired
     Nothing -> error "TODO: IMPLEMENT ME"    
  where 
@@ -450,7 +461,10 @@ randomIvalBits :: (RandomGen g, Integral a, Bits a) => (a, a) -> g -> (a, g)
 randomIvalBits (l,h) rng 
   | l > h     = randomIvalBits (h,l) rng
   | otherwise = 
-      -- trace ("Got pow2: "++ show pow2 ++ " range " ++ show range ++ " cutoff "++ show cutoff) $ 
+#ifdef DEBUGRAND
+      trace ("  Got pow2: "++show pow2++" bounding "++show bounding++" maxbits "++show maxbits++
+	     " range " ++ show range ++ " cutoff "++ show cutoff) $ 
+#endif
       (l + fin_x, fin_rng)
  where 
     (fin_x,fin_rng) = 
@@ -462,14 +476,15 @@ randomIvalBits (l,h) rng
 
     -- range is the number of distinct values we wish to generate:
     -- If we are dealing with a signed type, range may be negative!
---    range  = h - l + 1
-    range  = h - l 
+    range  = h - l + 1
     maxbits = bitSize l
 
     -- With randomBits we can only generate power-of-two ranges.  We
     -- need to find the smallest power-of-two that is bigger than range.
     pow2 = findBoundingPow2 range
-    bounding = 1 `shiftL` pow2
+    -- Bounding is the largest number we will generate with pow2 random bits:
+    -- bounding = (1 `shiftL` pow2) - 1 -- This could overflow!
+    bounding = complement 0 `shiftR` (maxbits - pow2)
     cutoff = --if pow2 == maxbits 
 	     --then error "UNFINISHED"
 	     --else 
@@ -479,8 +494,8 @@ randomIvalBits (l,h) rng
     -- results, but usually it should be much much less.
     rollAndTrash g = 
       case randomBits pow2 g of 
-        (x,g') | x > cutoff -> rollAndTrash g'
-        pair                -> pair
+        (x,g') | x >= cutoff -> rollAndTrash g'
+        pair                 -> pair
 
 -- Find the smallest power of two greater than or equal to the given number.
 -- findBoundingPow2 :: (Bits a, Ord a) => a -> Int



More information about the ghc-commits mailing list