xorshift 1 → 2
raw patch · 4 files changed
+187/−112 lines, 4 filesdep +basedep +randomdep +time
Dependencies added: base, random, time
Files
- src/Random/Xorshift.hs +22/−106
- src/Random/Xorshift/Int32.hs +78/−0
- src/Random/Xorshift/Int64.hs +78/−0
- xorshift.cabal +9/−6
src/Random/Xorshift.hs view
@@ -11,144 +11,60 @@ -- | Xorshift random generators. The generators are implemented according to -- the paper <http://www.jstatsoft.org/v08/i14/paper> by George Marsaglia. -- You can use the 'RandomGen' instances to generate random numbers easily.+-- This module only exports the Random generator that matches your word size,+-- if you want to use a specific length, try "Random.Xorshift.Int32" and+-- "Random.Xorshift.Int64" instead. ----------------------------------------------------------------------------- {-# LANGUAGE GeneralizedNewtypeDeriving, CPP #-} --- Use the C-header file to generate a platform depend Xorshift type--- This is handy as I can use the __Xorshift macro as a data-constructor.-#include "MachDeps.h"-#if WORD_SIZE_IN_BITS == 32-#define __Xorshift Xorshift32-#else-#define __Xorshift Xorshift64-#endif- module Random.Xorshift (- Xorshift32 (..),- Xorshift64 (..), Xorshift,- newXorshift32,- newXorshift64, newXorshift,- makeXorshift32,- makeXorshift64, makeXorshift,- getInt64,- getInt32, module System.Random ) where -import Data.Int (Int32,Int64)-import Data.Bits (xor,shiftL,shiftR) import System.Random import Data.Time --- | Xorshift generator with 32 bits.--- This Xorshift generator uses first a left shift, then a right shift and--- again a left shift. It uses the parameters 13, 17 and 5. See the paper for--- more details on how the parameters affect the generation of random numbers.------ The generator has a periode of 2^32-1, please notice that the--- generator has to be initialized with a value different from 0, elseway all--- future values will be zero as well.-newtype Xorshift32 = Xorshift32 Int32- deriving (Eq,Show,Enum,Bounded)---- | Xorshift generator with 64 bits.--- This Xorshift generator uses first a left shift, then a right shift and--- again a left shift. It uses the parameters 13, 7 and 17. See the paper for--- more details on how the parameters affect the generation of random numbers.------ The generator has a periode of 2^64-1, please notice that the--- generator has to be initialized with a value different from 0, elseway all--- future values will be zero as well.-newtype Xorshift64 = Xorshift64 Int64- deriving (Eq,Show,Enum,Bounded)---- | Generates a new Xorshift32 from the current time.-newXorshift32 :: IO Xorshift32-newXorshift32 = getRandomValue >>= return . makeXorshift32---- | Generates a new Xorshift32 from the current time.-newXorshift64 :: IO Xorshift64-newXorshift64 = getRandomValue >>= return . makeXorshift64+-- Use the C-header file to generate a platform depend Xorshift type+-- This is handy as I can use the __Xorshift macro as a data-constructor.+#include "MachDeps.h"+#if WORD_SIZE_IN_BITS == 32+#define __Xorshift Xorshift32+import Random.Xorshift.Int32+import Random.Xorshift.Int64 ()+#else+#define __Xorshift Xorshift64+import Random.Xorshift.Int32 ()+import Random.Xorshift.Int64+#endif -- | Generates a new Xorshift from the current time. This is either a synonym -- for 'newXorshift32' or 'newXorshift64'. newXorshift :: IO Xorshift newXorshift = getRandomValue >>= return . makeXorshift --- | Generate a new 'Xorshift32' generator. This is essentially a wrapper around--- the constructor.-makeXorshift32 :: Integral a => a -> Xorshift32-makeXorshift32 = Xorshift32 . fromIntegral---- | Generate a new 'Xorshift64' generator. This is essentially a wrapper around--- the constructor.-makeXorshift64 :: Integral a => a -> Xorshift64-makeXorshift64 = Xorshift64 . fromIntegral- -- | Generate a new 'Xorshift' generator, regardless of whatever it's bytesize -- is on your platform. makeXorshift :: Integral a => a -> Xorshift makeXorshift = __Xorshift . fromIntegral --- | Get the raw contents of the random generator. This function is preferable--- over direct usage of the constructor itself, as the internal representation--- of the random generator may change in future releases.------ The 'getInt32' function works for 'Xorshift32' and the 'getInt64' function--- works for 'Xorshift64'. If you're using the 'Xorshift' type, use an 'Int'--- type in combination with the 'random' methof of "System.Random".-getInt32 :: Xorshift32 -> Int32-getInt32 (Xorshift32 a) = a--getInt64 :: Xorshift32 -> Int32-getInt64 (Xorshift32 a) = a--instance RandomGen Xorshift32 where- next a = (fromIntegral c, b) where- b@(Xorshift32 c) = step32 a- split = error "Splitting of an Xorshift random generator is not implemented."- genRange a = (fromEnum (minBound `asTypeOf` a),- fromEnum (maxBound `asTypeOf` a))--instance RandomGen Xorshift64 where- next a = (fromIntegral c, b) where- b@(Xorshift64 c) = step64 a- split = error "Splitting of an Xorshift random generator is not implemented."- genRange a = (fromEnum (minBound `asTypeOf` a),- fromEnum (maxBound `asTypeOf` a))---- | The type Xorshift is a wrapper around either 'Xorshift32' or 'Xorshift64',--- depending on the bit size of your system. The idea behind this is, that you--- may want to use this package as an uncomplicated, fast random generator,--- but repeated conversion between different word sizes are an absolute--- performance killer.+-- | The type Xorshift is a wrapper around either Xorshift32 or Xorshift64,+-- depending on the bit size of your system. The idea behind this is, that+-- you may want to use this package as an uncomplicated, fast random+-- generator, but repeated conversion between different word sizes are an+-- absolute performance killer. -- -- Thus, if you don't really care about the period of your random generator or -- how long the result is, use the 'Xorshift' synonym, whenever possible. type Xorshift = __Xorshift --- Iterates the random generator for 32 bits-step32 :: Xorshift32 -> Xorshift32-step32 (Xorshift32 a) = Xorshift32 d where- b = a `xor` (shiftL a 13)- c = b `xor` (shiftR b 17)- d = c `xor` (shiftL c 5)---- Iterates the random generator for 64 bits-step64 :: Xorshift64 -> Xorshift64-step64 (Xorshift64 a) = Xorshift64 d where- b = a `xor` (shiftL a 13)- c = b `xor` (shiftR b 7)- d = c `xor` (shiftL c 17)- -- Generates a random value from current time. We try to archieve a good result -- by summing all information of time. getRandomValue :: IO Integer getRandomValue = do UTCTime (ModifiedJulianDay day) time <- getCurrentTime- let picosecs = truncate $ toRational time * 10^12- dayInPs = day * 86400 * 10^12+ let picosecs = truncate $ toRational time * 10^(12 :: Int)+ dayInPs = day * 86400 * 10^(12 :: Int) return $! picosecs + dayInPs
+ src/Random/Xorshift/Int32.hs view
@@ -0,0 +1,78 @@+-----------------------------------------------------------------------------+--+-- Module : Random.Xorshift.Int32+-- Copyright :+-- License : LGPL 2.0 or higher+--+-- Maintainer :+-- Stability :+-- Portability :+--+-- | This module contains a 32 bit Xorshift random generator. Use this if you+-- need a 32 bit random generator, usually 'Xorshift' itself is a good choice+-- for your platform. This generator has a period of 2^32-1 bits if+-- initialized with a value different from 0. +-----------------------------------------------------------------------------+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Random.Xorshift.Int32 (+ Xorshift32 (..),+ newXorshift32,+ makeXorshift32,+ getInt32+ ) where++import Data.Int (Int32)+import Data.Bits+import System.Random+import Data.Time++-- | Xorshift generator with 32 bits.+-- This Xorshift generator uses first a left shift, then a right shift and+-- again a left shift. It uses the parameters 13, 17 and 5. See the paper for+-- more details on how the parameters affect the generation of random numbers.+--+-- The generator has a periode of 2^32-1, please notice that the+-- generator has to be initialized with a value different from 0, elseway all+-- future values will be zero as well.+--+-- Please notice, that the function 'split' is not implemented and will result+-- in a runtime error.+newtype Xorshift32 = Xorshift32 Int32+ deriving (Eq,Show,Enum,Bounded)++instance RandomGen Xorshift32 where+ next a = (fromIntegral c, b) where+ b@(Xorshift32 c) = step32 a+ split = error "Splitting of an Xorshift random generator is not implemented."+ genRange a = (fromEnum (minBound `asTypeOf` a),+ fromEnum (maxBound `asTypeOf` a))++-- | Generates a new Xorshift32 from the current time.+newXorshift32 :: IO Xorshift32+newXorshift32 = getRandomValue >>= return . makeXorshift32++-- | Generate a new 'Xorshift32' generator. This is essentially a wrapper around+-- the constructor.+makeXorshift32 :: Integral a => a -> Xorshift32+makeXorshift32 = Xorshift32 . fromIntegral++-- | Get the raw contents of the random generator. This function is preferable+-- over direct usage of the constructor itself, as the internal representation+-- of the random generator may change in future releases.+getInt32 :: Xorshift32 -> Int32+getInt32 (Xorshift32 a) = a++-- Generates a random value from current time. We try to archieve a good result+-- by summing all information of time.+getRandomValue :: IO Integer+getRandomValue = do UTCTime (ModifiedJulianDay day) time <- getCurrentTime+ let picosecs = truncate $ toRational time * 10^(12 :: Int)+ dayInPs = day * 86400 * 10^(12 :: Int)+ return $! picosecs + dayInPs++-- Iterates the random generator for 32 bits+step32 :: Xorshift32 -> Xorshift32+step32 (Xorshift32 a) = Xorshift32 d where+ b = a `xor` (shiftL a 13)+ c = b `xor` (shiftR b 17)+ d = c `xor` (shiftL c 5)
+ src/Random/Xorshift/Int64.hs view
@@ -0,0 +1,78 @@+-----------------------------------------------------------------------------+--+-- Module : Random.Xorshift.Int64+-- Copyright :+-- License : LGPL 2.0 or higher+--+-- Maintainer :+-- Stability :+-- Portability :+--+-- | This module contains a 64 bit Xorshift random generator. Use this if you+-- need a 64 bit random generator, usually 'Xorshift' itself is a good choice+-- for your platform. This generator has a period of 2^64-1 bits if+-- initialized with a value different from 0. +-----------------------------------------------------------------------------+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Random.Xorshift.Int64 (+ Xorshift64 (..),+ newXorshift64,+ makeXorshift64,+ getInt64+ ) where++import Data.Int (Int64)+import Data.Bits+import System.Random+import Data.Time++-- | Xorshift generator with 64 bits.+-- This Xorshift generator uses first a left shift, then a right shift and+-- again a left shift. It uses the parameters 13, 7 and 17. See the paper for+-- more details on how the parameters affect the generation of random numbers.+--+-- The generator has a periode of 2^64-1, please notice that the+-- generator has to be initialized with a value different from 0, elseway all+-- future values will be zero as well.+--+-- Please notice, that the function 'split' is not implemented and will result+-- in a runtime error.+newtype Xorshift64 = Xorshift64 Int64+ deriving (Eq,Show,Enum,Bounded)++instance RandomGen Xorshift64 where+ next a = (fromIntegral c, b) where+ b@(Xorshift64 c) = step64 a+ split = error "Splitting of an Xorshift random generator is not implemented."+ genRange a = (fromEnum (minBound `asTypeOf` a),+ fromEnum (maxBound `asTypeOf` a))++-- | Generates a new Xorshift64 from the current time.+newXorshift64 :: IO Xorshift64+newXorshift64 = getRandomValue >>= return . makeXorshift64++-- | Generate a new 'Xorshift64' generator. This is essentially a wrapper around+-- the constructor.+makeXorshift64 :: Integral a => a -> Xorshift64+makeXorshift64 = Xorshift64 . fromIntegral++-- | Get the raw contents of the random generator. This function is preferable+-- over direct usage of the constructor itself, as the internal representation+-- of the random generator may change in future releases.+getInt64 :: Xorshift64 -> Int64+getInt64 (Xorshift64 a) = a++-- Generates a random value from current time. We try to archieve a good result+-- by summing all information of time.+getRandomValue :: IO Integer+getRandomValue = do UTCTime (ModifiedJulianDay day) time <- getCurrentTime+ let picosecs = truncate $ toRational time * 10^(12 :: Int)+ dayInPs = day * 86400 * 10^(12 :: Int)+ return $! picosecs + dayInPs++-- Iterates the random generator for 64 bits+step64 :: Xorshift64 -> Xorshift64+step64 (Xorshift64 a) = Xorshift64 d where+ b = a `xor` (shiftL a 13)+ c = b `xor` (shiftR b 7)+ d = c `xor` (shiftL c 17)
xorshift.cabal view
@@ -1,5 +1,5 @@ name: xorshift-version: 1+version: 2 Cabal-Version: >= 1.6 build-type: Simple @@ -8,10 +8,10 @@ license-file: "COPYING" author: Robert Clausecker <fuzxxl@gmail.com>-bug-reports: http://https://github.com/fuzxxl/Xorshift/issues+bug-reports: https://github.com/fuzxxl/Xorshift/issues maintainer: Robert Clausecker+homepage: https://github.com/fuzxxl/Xorshift -build-depends: base -any, random -any, time -any stability: homepage: package-url:@@ -19,14 +19,17 @@ description: The Xorshift random generator is a very fast generator that uses only XOR and bitshifting operations. This package contains a basic version with a periode of 2^32-1 for 32-bit numbers and a version with a periode of- 2^64-1 for 64-bit numbers. The author didn't tested the random generator,+ 2^64-1 for 64-bit numbers.+ .+ Although the author didn't tested the random generator, but according to it's specification the resulting numbers are of good quality. category: Math library- exposed-modules: Random.Xorshift+ build-depends: base >= 3 && < 5, random -any, time -any+ exposed-modules: Random.Xorshift Random.Xorshift.Int32 Random.Xorshift.Int64 exposed: True extensions: CPP, GeneralizedNewtypeDeriving hs-source-dirs: src@@ -39,4 +42,4 @@ source-repository this type: git location: git://github.com/fuzxxl/Xorshift.git- tag: release-1+ tag: release-2