mkStdGen32: Avoid infinite recursion when applied to minBound
authorJohan Kiviniemi <devel@johan.kiviniemi.name>
Fri, 21 Jan 2011 07:02:58 +0000 (07:02 +0000)
committerJohan Kiviniemi <devel@johan.kiviniemi.name>
Fri, 21 Jan 2011 07:02:58 +0000 (07:02 +0000)
"mkStdGen32 s" would call itself with "negate s" if "s" is negative. Alas,
(minBound :: Int32) == negate minBound. "mkStdGen32 minBound" would thus
recurse infinitely.

Compute "sMaybeNegative .&. maxBound" instead. That clears the most significant
bit in signed types.

System/Random.hs

index f5b1360..9a30b4a 100644 (file)
@@ -68,6 +68,7 @@ module System.Random
 
 import Prelude
 
 
 import Prelude
 
+import Data.Bits
 import Data.Int
 import Data.Word
 import Foreign.C.Types
 import Data.Int
 import Data.Word
 import Foreign.C.Types
@@ -218,10 +219,9 @@ mkStdGen :: Int -> StdGen -- why not Integer ?
 mkStdGen s = mkStdGen32 $ fromIntegral s
 
 mkStdGen32 :: Int32 -> StdGen
 mkStdGen s = mkStdGen32 $ fromIntegral s
 
 mkStdGen32 :: Int32 -> StdGen
-mkStdGen32 s
- | s < 0     = mkStdGen32 (-s)
- | otherwise = StdGen (s1+1) (s2+1)
+mkStdGen32 sMaybeNegative = StdGen (s1+1) (s2+1)
       where
       where
+       s       = sMaybeNegative .&. maxBound
        (q, s1) = s `divMod` 2147483562
        s2      = q `mod` 2147483398
 
        (q, s1) = s `divMod` 2147483562
        s2      = q `mod` 2147483398