• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

haskell / random / 295

27 Nov 2023 12:22AM UTC coverage: 71.879% (-0.1%) from 71.978%
295

push

github

web-flow
Merge pull request #155 from haskell/lehins/mkStdGen64

Add `mkStdGen64`.

0 of 1 new or added line in 1 file covered. (0.0%)

3 existing lines in 1 file now uncovered.

524 of 729 relevant lines covered (71.88%)

1.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.98
/src/System/Random/Internal.hs
1
{-# LANGUAGE BangPatterns #-}
2
{-# LANGUAGE CPP #-}
3
{-# LANGUAGE DefaultSignatures #-}
4
{-# LANGUAGE FlexibleContexts #-}
5
{-# LANGUAGE FlexibleInstances #-}
6
{-# LANGUAGE MultiParamTypeClasses #-}
7
{-# LANGUAGE GHCForeignImportPrim #-}
8
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9
{-# LANGUAGE MagicHash #-}
10
{-# LANGUAGE RankNTypes #-}
11
{-# LANGUAGE ScopedTypeVariables #-}
12
{-# LANGUAGE Trustworthy #-}
13
{-# LANGUAGE TypeOperators #-}
14
{-# LANGUAGE UnboxedTuples #-}
15
{-# LANGUAGE UndecidableInstances #-}
16
{-# LANGUAGE UnliftedFFITypes #-}
17
{-# LANGUAGE TypeFamilyDependencies #-}
18
{-# OPTIONS_HADDOCK hide, not-home #-}
19

20
-- |
21
-- Module      :  System.Random.Internal
22
-- Copyright   :  (c) The University of Glasgow 2001
23
-- License     :  BSD-style (see the file LICENSE in the 'random' repository)
24
-- Maintainer  :  libraries@haskell.org
25
-- Stability   :  stable
26
--
27
-- This library deals with the common task of pseudo-random number generation.
28
module System.Random.Internal
29
  (-- * Pure and monadic pseudo-random number generator interfaces
30
    RandomGen(..)
31
  , StatefulGen(..)
32
  , FrozenGen(..)
33
  , ThawedGen(..)
34
  , splitGen
35
  , splitMutableGen
36

37
  -- ** Standard pseudo-random number generator
38
  , StdGen(..)
39
  , mkStdGen
40
  , mkStdGen64
41
  , theStdGen
42

43
  -- * Monadic adapters for pure pseudo-random number generators
44
  -- ** Pure adapter
45
  , StateGen(..)
46
  , StateGenM(..)
47
  , runStateGen
48
  , runStateGen_
49
  , runStateGenT
50
  , runStateGenT_
51
  , runStateGenST
52
  , runStateGenST_
53

54
  -- * Pseudo-random values of various types
55
  , Uniform(..)
56
  , uniformViaFiniteM
57
  , UniformRange(..)
58
  , uniformDouble01M
59
  , uniformDoublePositive01M
60
  , uniformFloat01M
61
  , uniformFloatPositive01M
62
  , uniformEnumM
63
  , uniformEnumRM
64
  , uniformListM
65
  , uniformListRM
66
  , isInRangeOrd
67
  , isInRangeEnum
68

69
  -- * Generators for sequences of pseudo-random bytes
70
  , uniformByteStringM
71
  , uniformShortByteStringM
72
  , uniformByteArray
73
  , uniformFillMutableByteArray
74
  , uniformByteString
75
  , genByteArrayST
76
  , genShortByteStringIO
77
  , genShortByteStringST
78
  , defaultUnsafeUniformFillMutableByteArray
79
  -- ** Helpers for dealing with MutableByteArray
80
  , newMutableByteArray
81
  , newPinnedMutableByteArray
82
  , freezeMutableByteArray
83
  , writeWord8
84
  ) where
85

86
import Control.Arrow
87
import Control.DeepSeq (NFData)
88
import Control.Monad (replicateM, when, (>=>))
89
import Control.Monad.Cont (ContT, runContT)
90
import Control.Monad.Identity (IdentityT (runIdentityT))
91
import Control.Monad.ST
92
import Control.Monad.State.Strict (MonadState(..), State, StateT(..), execStateT, runState)
93
import Control.Monad.Trans (lift, MonadTrans)
94
import Data.Array.Byte (ByteArray(..), MutableByteArray(..))
95
import Data.Bits
96
import Data.ByteString.Short.Internal (ShortByteString(SBS), fromShort)
97
import Data.IORef (IORef, newIORef)
98
import Data.Int
99
import Data.Word
100
import Foreign.C.Types
101
import Foreign.Storable (Storable)
102
import GHC.Exts
103
import GHC.Generics
104
import GHC.IO (IO(..))
105
import GHC.ST (ST(..))
106
import GHC.Word
107
import Numeric.Natural (Natural)
108
import System.IO.Unsafe (unsafePerformIO)
109
import System.Random.GFinite (Cardinality(..), GFinite(..))
110
import qualified System.Random.SplitMix as SM
111
import qualified System.Random.SplitMix32 as SM32
112
import Data.Kind
113
#if __GLASGOW_HASKELL__ >= 802
114
import Data.ByteString.Internal (ByteString(PS))
115
import GHC.ForeignPtr
116
#else
117
import Data.ByteString (ByteString)
118
#endif
119

120
-- Needed for WORDS_BIGENDIAN
121
#include "MachDeps.h"
122

123

124
-- | 'RandomGen' is an interface to pure pseudo-random number generators.
125
--
126
-- 'StdGen' is the standard 'RandomGen' instance provided by this library.
127
--
128
-- @since 1.0.0
129
{-# DEPRECATED next "No longer used" #-}
130
{-# DEPRECATED genRange "No longer used" #-}
131
class RandomGen g where
132
  {-# MINIMAL split,(genWord32|genWord64|(next,genRange)) #-}
133
  -- | Returns an 'Int' that is uniformly distributed over the range returned by
134
  -- 'genRange' (including both end points), and a new generator. Using 'next'
135
  -- is inefficient as all operations go via 'Integer'. See
136
  -- [here](https://alexey.kuleshevi.ch/blog/2019/12/21/random-benchmarks) for
137
  -- more details. It is thus deprecated.
138
  --
139
  -- @since 1.0.0
140
  next :: g -> (Int, g)
141
  next g = runStateGen g (uniformRM (genRange g))
×
142

143
  -- | Returns a 'Word8' that is uniformly distributed over the entire 'Word8'
144
  -- range.
145
  --
146
  -- @since 1.2.0
147
  genWord8 :: g -> (Word8, g)
148
  genWord8 = first fromIntegral . genWord32
2✔
149
  {-# INLINE genWord8 #-}
150

151
  -- | Returns a 'Word16' that is uniformly distributed over the entire 'Word16'
152
  -- range.
153
  --
154
  -- @since 1.2.0
155
  genWord16 :: g -> (Word16, g)
156
  genWord16 = first fromIntegral . genWord32
2✔
157
  {-# INLINE genWord16 #-}
158

159
  -- | Returns a 'Word32' that is uniformly distributed over the entire 'Word32'
160
  -- range.
161
  --
162
  -- @since 1.2.0
163
  genWord32 :: g -> (Word32, g)
164
  genWord32 = randomIvalIntegral (minBound, maxBound)
×
165
  -- Once `next` is removed, this implementation should be used instead:
166
  -- first fromIntegral . genWord64
167
  {-# INLINE genWord32 #-}
168

169
  -- | Returns a 'Word64' that is uniformly distributed over the entire 'Word64'
170
  -- range.
171
  --
172
  -- @since 1.2.0
173
  genWord64 :: g -> (Word64, g)
174
  genWord64 g =
×
175
    case genWord32 g of
×
176
      (l32, g') ->
177
        case genWord32 g' of
×
178
          (h32, g'') ->
179
            ((fromIntegral h32 `shiftL` 32) .|. fromIntegral l32, g'')
×
180
  {-# INLINE genWord64 #-}
181

182
  -- | @genWord32R upperBound g@ returns a 'Word32' that is uniformly
183
  -- distributed over the range @[0, upperBound]@.
184
  --
185
  -- @since 1.2.0
186
  genWord32R :: Word32 -> g -> (Word32, g)
187
  genWord32R m g = runStateGen g (unbiasedWordMult32 m)
2✔
188
  {-# INLINE genWord32R #-}
189

190
  -- | @genWord64R upperBound g@ returns a 'Word64' that is uniformly
191
  -- distributed over the range @[0, upperBound]@.
192
  --
193
  -- @since 1.2.0
194
  genWord64R :: Word64 -> g -> (Word64, g)
195
  genWord64R m g = runStateGen g (unsignedBitmaskWithRejectionM uniformWord64 m)
2✔
196
  {-# INLINE genWord64R #-}
197

198
  -- | Same as @`uniformByteArray` `False`@, but for `ShortByteString`.
199
  --
200
  -- @genShortByteString n g@ returns a 'ShortByteString' of length @n@ filled with
201
  -- pseudo-random bytes.
202
  --
203
  -- /Note/ - This function will be removed from the type class in the next major release as
204
  -- it is no longer needed because of `unsafeUniformFillMutableByteArray`.
205
  --
206
  --
207
  -- @since 1.2.0
208
  genShortByteString :: Int -> g -> (ShortByteString, g)
209
  genShortByteString n g =
2✔
210
    case uniformByteArray False n g of
2✔
211
      (ByteArray ba#, g') -> (SBS ba#, g')
2✔
212
  {-# INLINE genShortByteString #-}
213

214
  unsafeUniformFillMutableByteArray ::
215
       MutableByteArray s
216
    -- ^ Mutable array to fill with random bytes
217
    -> Int
218
    -- ^ Offset into a mutable array from the beginning in number of bytes. Offset must
219
    -- be non-negative, but this will not be checked
220
    -> Int
221
    -- ^ Number of randomly generated bytes to write into the array. Number of bytes
222
    -- must be non-negative and less then the total size of the array, minus the
223
    -- offset. This also will be checked.
224
    -> g
225
    -> ST s g
226
  unsafeUniformFillMutableByteArray = defaultUnsafeUniformFillMutableByteArray
×
227
  {-# INLINE unsafeUniformFillMutableByteArray #-}
228

229
  -- | Yields the range of values returned by 'next'.
230
  --
231
  -- It is required that:
232
  --
233
  -- *   If @(a, b) = 'genRange' g@, then @a < b@.
234
  -- *   'genRange' must not examine its argument so the value it returns is
235
  --     determined only by the instance of 'RandomGen'.
236
  --
237
  -- The default definition spans the full range of 'Int'.
238
  --
239
  -- @since 1.0.0
240
  genRange :: g -> (Int, Int)
241
  genRange _ = (minBound, maxBound)
×
242

243
  -- | Returns two distinct pseudo-random number generators.
244
  --
245
  -- Implementations should take care to ensure that the resulting generators
246
  -- are not correlated. Some pseudo-random number generators are not
247
  -- splittable. In that case, the 'split' implementation should fail with a
248
  -- descriptive 'error' message.
249
  --
250
  -- @since 1.0.0
251
  split :: g -> (g, g)
252

253

254
-- | 'StatefulGen' is an interface to monadic pseudo-random number generators.
255
--
256
-- @since 1.2.0
257
class Monad m => StatefulGen g m where
258
  {-# MINIMAL (uniformWord32|uniformWord64) #-}
259
  -- | @uniformWord32R upperBound g@ generates a 'Word32' that is uniformly
260
  -- distributed over the range @[0, upperBound]@.
261
  --
262
  -- @since 1.2.0
263
  uniformWord32R :: Word32 -> g -> m Word32
264
  uniformWord32R = unsignedBitmaskWithRejectionM uniformWord32
×
265
  {-# INLINE uniformWord32R #-}
266

267
  -- | @uniformWord64R upperBound g@ generates a 'Word64' that is uniformly
268
  -- distributed over the range @[0, upperBound]@.
269
  --
270
  -- @since 1.2.0
271
  uniformWord64R :: Word64 -> g -> m Word64
272
  uniformWord64R = unsignedBitmaskWithRejectionM uniformWord64
×
273
  {-# INLINE uniformWord64R #-}
274

275
  -- | Generates a 'Word8' that is uniformly distributed over the entire 'Word8'
276
  -- range.
277
  --
278
  -- The default implementation extracts a 'Word8' from 'uniformWord32'.
279
  --
280
  -- @since 1.2.0
281
  uniformWord8 :: g -> m Word8
282
  uniformWord8 = fmap fromIntegral . uniformWord32
×
283
  {-# INLINE uniformWord8 #-}
284

285
  -- | Generates a 'Word16' that is uniformly distributed over the entire
286
  -- 'Word16' range.
287
  --
288
  -- The default implementation extracts a 'Word16' from 'uniformWord32'.
289
  --
290
  -- @since 1.2.0
291
  uniformWord16 :: g -> m Word16
292
  uniformWord16 = fmap fromIntegral . uniformWord32
×
293
  {-# INLINE uniformWord16 #-}
294

295
  -- | Generates a 'Word32' that is uniformly distributed over the entire
296
  -- 'Word32' range.
297
  --
298
  -- The default implementation extracts a 'Word32' from 'uniformWord64'.
299
  --
300
  -- @since 1.2.0
301
  uniformWord32 :: g -> m Word32
302
  uniformWord32 = fmap fromIntegral . uniformWord64
×
303
  {-# INLINE uniformWord32 #-}
304

305
  -- | Generates a 'Word64' that is uniformly distributed over the entire
306
  -- 'Word64' range.
307
  --
308
  -- The default implementation combines two 'Word32' from 'uniformWord32' into
309
  -- one 'Word64'.
310
  --
311
  -- @since 1.2.0
312
  uniformWord64 :: g -> m Word64
313
  uniformWord64 g = do
×
314
    l32 <- uniformWord32 g
×
315
    h32 <- uniformWord32 g
×
316
    pure (shiftL (fromIntegral h32) 32 .|. fromIntegral l32)
×
317
  {-# INLINE uniformWord64 #-}
318

319
  -- | @uniformByteArrayM n g@ generates a 'ByteArray' of length @n@
320
  -- filled with pseudo-random bytes.
321
  --
322
  -- @since 1.3.0
323
  uniformByteArrayM ::
324
       Bool -- ^ Should `ByteArray` be allocated as pinned memory or not
325
    -> Int -- ^ Size of the newly created `ByteArray` in number of bytes.
326
    -> g -- ^ Generator to use for filling in the newly created `ByteArray`
327
    -> m ByteArray
328
  default uniformByteArrayM ::
329
    (RandomGen f, FrozenGen f m, g ~ MutableGen f m) => Bool -> Int -> g -> m ByteArray
330
  uniformByteArrayM isPinned n g = modifyGen g (uniformByteArray isPinned n)
2✔
331
  {-# INLINE uniformByteArrayM #-}
332

333
  -- | @uniformShortByteString n g@ generates a 'ShortByteString' of length @n@
334
  -- filled with pseudo-random bytes.
335
  --
336
  -- @since 1.2.0
337
  uniformShortByteString :: Int -> g -> m ShortByteString
338
  uniformShortByteString = uniformShortByteStringM
×
339
  {-# INLINE uniformShortByteString #-}
340
{-# DEPRECATED uniformShortByteString "In favor of `uniformShortByteStringM`" #-}
341

342

343
-- | This class is designed for mutable pseudo-random number generators that have a frozen
344
-- imutable counterpart that can be manipulated in pure code.
345
--
346
-- It also works great with frozen generators that are based on pure generators that have
347
-- a `RandomGen` instance.
348
--
349
-- Here are a few laws, which are important for this type class:
350
--
351
-- * Roundtrip and complete destruction on overwrite:
352
--
353
-- @
354
-- overwriteGen mg fg >> freezeGen mg = pure fg
355
-- @
356
--
357
-- * Modification of a mutable generator:
358
--
359
-- @
360
-- overwriteGen mg fg = modifyGen mg (const ((), fg)
361
-- @
362
--
363
-- * Freezing of a mutable generator:
364
--
365
-- @
366
-- freezeGen mg = modifyGen mg (\fg -> (fg, fg))
367
-- @
368
--
369
-- @since 1.2.0
370
class StatefulGen (MutableGen f m) m => FrozenGen f m where
371
  {-# MINIMAL (modifyGen|(freezeGen,overwriteGen)) #-}
372
  -- | Represents the state of the pseudo-random number generator for use with
373
  -- 'thawGen' and 'freezeGen'.
374
  --
375
  -- @since 1.2.0
376
  type MutableGen f m = (g :: Type) | g -> f
377

378
  -- | Saves the state of the pseudo-random number generator as a frozen seed.
379
  --
380
  -- @since 1.2.0
381
  freezeGen :: MutableGen f m -> m f
382
  freezeGen mg = modifyGen mg (\fg -> (fg, fg))
×
383
  {-# INLINE freezeGen #-}
384

385
  -- | Apply a pure function to the frozen pseudo-random number generator.
386
  --
387
  -- @since 1.3.0
388
  modifyGen :: MutableGen f m -> (f -> (a, f)) -> m a
389
  modifyGen mg f = do
×
390
    fg <- freezeGen mg
×
391
    case f fg of
×
392
      (a, !fg') -> a <$ overwriteGen mg fg'
×
393
  {-# INLINE modifyGen #-}
394

395
  -- | Overwrite contents of the mutable pseudo-random number generator with the
396
  -- supplied frozen one
397
  --
398
  -- @since 1.3.0
399
  overwriteGen :: MutableGen f m -> f -> m ()
400
  overwriteGen mg fg = modifyGen mg (const ((), fg))
2✔
401
  {-# INLINE overwriteGen #-}
402

403
-- | Functionality for thawing frozen generators is not part of the `FrozenGen` class,
404
-- becase not all mutable generators support functionality of creating new mutable
405
-- generators, which is what thawing is in its essence. For this reason `StateGen` does
406
-- not have an instance for this type class, but it has one for `FrozenGen`.
407
--
408
-- Here is an important law that relates this type class to `FrozenGen`
409
--
410
-- * Roundtrip and independence of mutable generators:
411
--
412
-- @
413
-- traverse thawGen fgs >>= traverse freezeGen = pure fgs
414
-- @
415
--
416
-- @since 1.3.0
417
class FrozenGen f m => ThawedGen f m where
418
  -- | Create a new mutable pseudo-random number generator from its frozen state.
419
  --
420
  -- @since 1.2.0
421
  thawGen :: f -> m (MutableGen f m)
422

423
-- | Splits a pseudo-random number generator into two. Overwrites the mutable
424
-- pseudo-random number generator with one of the immutable pseudo-random number
425
-- generators produced by a `split` function and returns the other.
426
--
427
-- @since 1.3.0
428
splitGen :: (RandomGen f, FrozenGen f m) => MutableGen f m -> m f
429
splitGen = flip modifyGen split
2✔
430

431
-- | Splits a pseudo-random number generator into two. Overwrites the mutable wrapper with
432
-- one of the resulting generators and returns the other as a new mutable generator.
433
--
434
-- @since 1.3.0
435
splitMutableGen :: (RandomGen f, ThawedGen f m) => MutableGen f m -> m (MutableGen f m)
436
splitMutableGen = splitGen >=> thawGen
2✔
437

438
-- | Efficiently generates a sequence of pseudo-random bytes in a platform
439
-- independent manner.
440
--
441
-- @since 1.3.0
442
uniformByteArray ::
443
     RandomGen g
444
  => Bool -- ^ Should byte array be allocted in pinned or unpinned memory.
445
  -> Int -- ^ Number of bytes to generate
446
  -> g -- ^ Pure pseudo-random numer generator
447
  -> (ByteArray, g)
448
uniformByteArray isPinned n0 g =
2✔
449
  runST $ do
2✔
450
    let !n = max 0 n0
2✔
451
    mba <-
452
      if isPinned
2✔
453
        then newPinnedMutableByteArray n
2✔
454
        else newMutableByteArray n
2✔
455
    g' <- unsafeUniformFillMutableByteArray mba 0 n g
2✔
456
    ba <- freezeMutableByteArray mba
2✔
457
    pure (ba, g')
2✔
458
{-# INLINE uniformByteArray #-}
459

460
-- | Using an `ST` action that generates 8 bytes at a type fill in a new `ByteArray` in
461
-- architecture agnostic manner.
462
--
463
-- @since 1.3.0
464
genByteArrayST :: Bool -> Int -> ST s Word64 -> ST s ByteArray
465
genByteArrayST isPinned n0 action = do
×
466
  let !n = max 0 n0
×
467
  mba <- if isPinned
×
468
    then newPinnedMutableByteArray n
×
469
    else newMutableByteArray n
×
470
  runIdentityT $ defaultUnsafeUniformFillMutableByteArrayT mba 0 n (lift action)
×
471
  freezeMutableByteArray mba
×
472
{-# INLINE genByteArrayST #-}
473

474
-- | Fill in a slice of a mutable byte array with randomly generated bytes. This function
475
-- does not fail, instead it adjust the offset and number of bytes to generate into a valid
476
-- range.
477
--
478
-- @since 1.3.0
479
uniformFillMutableByteArray ::
480
     RandomGen g
481
  => MutableByteArray s
482
  -- ^ Mutable array to fill with random bytes
483
  -> Int
484
  -- ^ Offset into a mutable array from the beginning in number of bytes. Offset will be
485
  -- clamped into the range between 0 and the total size of the mutable array
486
  -> Int
487
  -- ^ Number of randomly generated bytes to write into the array. This number will be
488
  -- clamped between 0 and the total size of the array without the offset.
489
  -> g
490
  -> ST s g
491
uniformFillMutableByteArray mba i0 n g = do
2✔
492
  !sz <- getSizeOfMutableByteArray mba
2✔
493
  let !offset = max 0 (min sz i0)
2✔
494
      !numBytes = min (sz - offset) (max 0 n)
2✔
495
  unsafeUniformFillMutableByteArray mba offset numBytes g
2✔
496
{-# INLINE uniformFillMutableByteArray #-}
497

498
defaultUnsafeUniformFillMutableByteArrayT ::
499
     (Monad (t (ST s)), MonadTrans t)
500
  => MutableByteArray s
501
  -> Int
502
  -> Int
503
  -> t (ST s) Word64
504
  -> t (ST s) ()
505
defaultUnsafeUniformFillMutableByteArrayT mba offset n gen64 = do
2✔
506
  let !n64 = n `quot` 8
2✔
507
      !endIx64 = offset + n64 * 8
2✔
508
      !nrem = n `rem` 8
2✔
509
  let go !i =
2✔
510
        when (i < endIx64) $ do
2✔
511
          w64 <- gen64
2✔
512
          -- Writing 8 bytes at a time in a Little-endian order gives us
513
          -- platform portability
514
          lift $ writeWord64LE mba i w64
2✔
515
          go (i + 8)
2✔
516
  go offset
2✔
517
  when (nrem > 0) $ do
2✔
518
    let !endIx = offset + n
2✔
519
    w64 <- gen64
2✔
520
    -- In order to not mess up the byte order we write 1 byte at a time in
521
    -- Little endian order. It is tempting to simply generate as many bytes as we
522
    -- still need using smaller generators (eg. uniformWord8), but that would
523
    -- result in inconsistent tail when total length is slightly varied.
524
    lift $ writeByteSliceWord64LE mba (endIx - nrem) endIx w64
2✔
525
{-# INLINEABLE defaultUnsafeUniformFillMutableByteArrayT #-}
526
{-# SPECIALIZE defaultUnsafeUniformFillMutableByteArrayT
527
  :: MutableByteArray s
528
  -> Int
529
  -> Int
530
  -> IdentityT (ST s) Word64
531
  -> IdentityT (ST s) () #-}
532
{-# SPECIALIZE defaultUnsafeUniformFillMutableByteArrayT
533
  :: MutableByteArray s
534
  -> Int
535
  -> Int
536
  -> StateT g (ST s) Word64
537
  -> StateT g (ST s) () #-}
538

539
-- | Efficiently generates a sequence of pseudo-random bytes in a platform
540
-- independent manner.
541
--
542
-- @since 1.2.0
543
defaultUnsafeUniformFillMutableByteArray ::
544
     RandomGen g
545
  => MutableByteArray s
546
  -> Int -- ^ Starting offset
547
  -> Int -- ^ Number of random bytes to write into the array
548
  -> g -- ^ ST action that can generate 8 random bytes at a time
549
  -> ST s g
550
defaultUnsafeUniformFillMutableByteArray mba i0 n g =
2✔
551
  flip execStateT g
2✔
552
    $ defaultUnsafeUniformFillMutableByteArrayT mba i0 n (state genWord64)
2✔
553
{-# INLINE defaultUnsafeUniformFillMutableByteArray #-}
554

555

556
-- | Generates a pseudo-random 'ByteString' of the specified size.
557
--
558
-- @since 1.3.0
559
uniformByteString :: RandomGen g => Int -> g -> (ByteString, g)
560
uniformByteString n g =
2✔
561
  case uniformByteArray True n g of
2✔
562
    (byteArray, g') ->
563
      (shortByteStringToByteString $ byteArrayToShortByteString byteArray, g')
2✔
564
{-# INLINE uniformByteString #-}
565

566
-- Architecture independent helpers:
567

568
st_ :: (State# s -> State# s) -> ST s ()
569
st_ m# = ST $ \s# -> (# m# s#, () #)
1✔
570
{-# INLINE st_ #-}
571

572
ioToST :: IO a -> ST RealWorld a
573
ioToST (IO m#) = ST m#
×
574
{-# INLINE ioToST #-}
575

576
newMutableByteArray :: Int -> ST s (MutableByteArray s)
577
newMutableByteArray (I# n#) =
2✔
578
  ST $ \s# ->
2✔
579
    case newByteArray# n# s# of
2✔
580
      (# s'#, mba# #) -> (# s'#, MutableByteArray mba# #)
2✔
581
{-# INLINE newMutableByteArray #-}
582

583
newPinnedMutableByteArray :: Int -> ST s (MutableByteArray s)
584
newPinnedMutableByteArray (I# n#) =
2✔
585
  ST $ \s# ->
2✔
586
    case newPinnedByteArray# n# s# of
2✔
587
      (# s'#, mba# #) -> (# s'#, MutableByteArray mba# #)
2✔
588
{-# INLINE newPinnedMutableByteArray #-}
589

590
freezeMutableByteArray :: MutableByteArray s -> ST s ByteArray
591
freezeMutableByteArray (MutableByteArray mba#) =
2✔
592
  ST $ \s# ->
2✔
593
    case unsafeFreezeByteArray# mba# s# of
2✔
594
      (# s'#, ba# #) -> (# s'#, ByteArray ba# #)
2✔
595

596
writeWord8 :: MutableByteArray s -> Int -> Word8 -> ST s ()
597
writeWord8 (MutableByteArray mba#) (I# i#) (W8# w#) = st_ (writeWord8Array# mba# i# w#)
2✔
598
{-# INLINE writeWord8 #-}
599

600
writeByteSliceWord64LE :: MutableByteArray s -> Int -> Int -> Word64 -> ST s ()
601
writeByteSliceWord64LE mba fromByteIx toByteIx = go fromByteIx
2✔
602
  where
603
    go !i !z =
2✔
604
      when (i < toByteIx) $ do
2✔
605
        writeWord8 mba i (fromIntegral z :: Word8)
2✔
606
        go (i + 1) (z `shiftR` 8)
2✔
607
{-# INLINE writeByteSliceWord64LE #-}
608

609
-- On big endian machines we need to write one byte at a time for consistency with little
610
-- endian machines. Also for GHC versions prior to 8.6 we don't have primops that can
611
-- write with byte offset, eg. writeWord8ArrayAsWord64# and writeWord8ArrayAsWord32#, so we
612
-- also must fallback to writing one byte a time. Such fallback results in about 3 times
613
-- slow down, which is not the end of the world.
614
writeWord64LE :: MutableByteArray s -> Int -> Word64 -> ST s ()
615
#if defined WORDS_BIGENDIAN || !(__GLASGOW_HASKELL__ >= 806)
616
writeWord64LE mba i w64 =
617
  writeByteSliceWord64LE mba i (i + 8) w64
618
#else
619
writeWord64LE (MutableByteArray mba#) (I# i#) w64@(W64# w64#)
2✔
620
  | wordSizeInBits == 64 = st_ (writeWord8ArrayAsWord64# mba# i# w64#)
1✔
621
  | otherwise = do
×
622
    let !(W32# w32l#) = fromIntegral w64
×
623
        !(W32# w32u#) = fromIntegral (w64 `shiftR` 32)
×
624
    st_ (writeWord8ArrayAsWord32# mba# i# w32l#)
×
625
    st_ (writeWord8ArrayAsWord32# mba# (i# +# 4#) w32u#)
×
626
#endif
627
{-# INLINE writeWord64LE #-}
628

629
getSizeOfMutableByteArray :: MutableByteArray s -> ST s Int
630
getSizeOfMutableByteArray (MutableByteArray mba#) =
2✔
631
#if __GLASGOW_HASKELL__ >=802
632
  ST $ \s ->
2✔
633
    case getSizeofMutableByteArray# mba# s of
2✔
634
      (# s', n# #) -> (# s', I# n# #)
2✔
635
#else
636
  pure $! I# (sizeofMutableByteArray# mba#)
637
#endif
638
{-# INLINE getSizeOfMutableByteArray #-}
639

640
byteArrayToShortByteString :: ByteArray -> ShortByteString
641
byteArrayToShortByteString (ByteArray ba#) = SBS ba#
2✔
642
{-# INLINE byteArrayToShortByteString #-}
643

644
-- | Convert a ShortByteString to ByteString by casting, whenever memory is pinned,
645
-- otherwise make a copy into a new pinned ByteString
646
shortByteStringToByteString :: ShortByteString -> ByteString
647
shortByteStringToByteString ba =
2✔
648
#if __GLASGOW_HASKELL__ < 802
649
  fromShort ba
650
#else
651
  let !(SBS ba#) = ba in
2✔
652
  if isTrue# (isByteArrayPinned# ba#)
1✔
653
    then pinnedByteArrayToByteString ba#
2✔
654
    else fromShort ba
×
655
{-# INLINE shortByteStringToByteString #-}
656

657
pinnedByteArrayToByteString :: ByteArray# -> ByteString
658
pinnedByteArrayToByteString ba# =
2✔
659
  PS (pinnedByteArrayToForeignPtr ba#) 0 (I# (sizeofByteArray# ba#))
2✔
660
{-# INLINE pinnedByteArrayToByteString #-}
661

662
pinnedByteArrayToForeignPtr :: ByteArray# -> ForeignPtr a
663
pinnedByteArrayToForeignPtr ba# =
2✔
664
  ForeignPtr (byteArrayContents# ba#) (PlainPtr (unsafeCoerce# ba#))
1✔
665
{-# INLINE pinnedByteArrayToForeignPtr #-}
666
#endif
667

668
-- | Same as 'genShortByteStringIO', but runs in 'ST'.
669
--
670
-- @since 1.2.0
671
genShortByteStringST :: Int -> ST s Word64 -> ST s ShortByteString
672
genShortByteStringST n0 action = byteArrayToShortByteString <$> genByteArrayST False n0 action
×
673
{-# INLINE genShortByteStringST #-}
674

675
-- | Efficiently fills in a new `ShortByteString` in a platform independent manner.
676
--
677
-- @since 1.2.0
678
genShortByteStringIO ::
679
     Int -- ^ Number of bytes to generate
680
  -> IO Word64 -- ^ IO action that can generate 8 random bytes at a time
681
  -> IO ShortByteString
682
genShortByteStringIO n ioAction = stToIO $ genShortByteStringST n (ioToST ioAction)
×
683
{-# INLINE genShortByteStringIO #-}
684

685
-- | @uniformShortByteString n g@ generates a 'ShortByteString' of length @n@
686
-- filled with pseudo-random bytes.
687
--
688
-- @since 1.3.0
689
uniformShortByteStringM :: StatefulGen g m => Int -> g -> m ShortByteString
690
uniformShortByteStringM n g = byteArrayToShortByteString <$> uniformByteArrayM False n g
2✔
691
{-# INLINE uniformShortByteStringM #-}
692

693
-- | Generates a pseudo-random 'ByteString' of the specified size.
694
--
695
-- @since 1.2.0
696
uniformByteStringM :: StatefulGen g m => Int -> g -> m ByteString
697
uniformByteStringM n g =
2✔
698
  shortByteStringToByteString . byteArrayToShortByteString
2✔
699
    <$> uniformByteArrayM True n g
2✔
700
{-# INLINE uniformByteStringM #-}
701

702

703
-- | Opaque data type that carries the type of a pure pseudo-random number
704
-- generator.
705
--
706
-- @since 1.2.0
707
data StateGenM g = StateGenM
708

709
-- | Wrapper for pure state gen, which acts as an immutable seed for the corresponding
710
-- stateful generator `StateGenM`
711
--
712
-- @since 1.2.0
713
newtype StateGen g = StateGen { unStateGen :: g }
2✔
714
  deriving (Eq, Ord, Show, RandomGen, Storable, NFData)
×
715

716
instance (RandomGen g, MonadState g m) => StatefulGen (StateGenM g) m where
717
  uniformWord32R r _ = state (genWord32R r)
2✔
718
  {-# INLINE uniformWord32R #-}
719
  uniformWord64R r _ = state (genWord64R r)
2✔
720
  {-# INLINE uniformWord64R #-}
721
  uniformWord8 _ = state genWord8
2✔
722
  {-# INLINE uniformWord8 #-}
723
  uniformWord16 _ = state genWord16
2✔
724
  {-# INLINE uniformWord16 #-}
725
  uniformWord32 _ = state genWord32
2✔
726
  {-# INLINE uniformWord32 #-}
727
  uniformWord64 _ = state genWord64
2✔
728
  {-# INLINE uniformWord64 #-}
729

730
instance (RandomGen g, MonadState g m) => FrozenGen (StateGen g) m where
731
  type MutableGen (StateGen g) m = StateGenM g
732
  freezeGen _ = fmap StateGen get
×
733
  modifyGen _ f = state (coerce f)
2✔
734
  {-# INLINE modifyGen #-}
735
  overwriteGen _ f = put (coerce f)
×
736
  {-# INLINE overwriteGen #-}
737

738
-- | Runs a monadic generating action in the `State` monad using a pure
739
-- pseudo-random number generator.
740
--
741
-- ====__Examples__
742
--
743
-- >>> import System.Random.Stateful
744
-- >>> let pureGen = mkStdGen 137
745
-- >>> runStateGen pureGen randomM :: (Int, StdGen)
746
-- (7879794327570578227,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
747
--
748
-- @since 1.2.0
749
runStateGen :: RandomGen g => g -> (StateGenM g -> State g a) -> (a, g)
750
runStateGen g f = runState (f StateGenM) g
1✔
751
{-# INLINE runStateGen #-}
752

753
-- | Runs a monadic generating action in the `State` monad using a pure
754
-- pseudo-random number generator. Returns only the resulting pseudo-random
755
-- value.
756
--
757
-- ====__Examples__
758
--
759
-- >>> import System.Random.Stateful
760
-- >>> let pureGen = mkStdGen 137
761
-- >>> runStateGen_ pureGen randomM :: Int
762
-- 7879794327570578227
763
--
764
-- @since 1.2.0
765
runStateGen_ :: RandomGen g => g -> (StateGenM g -> State g a) -> a
766
runStateGen_ g = fst . runStateGen g
2✔
767
{-# INLINE runStateGen_ #-}
768

769
-- | Runs a monadic generating action in the `StateT` monad using a pure
770
-- pseudo-random number generator.
771
--
772
-- ====__Examples__
773
--
774
-- >>> import System.Random.Stateful
775
-- >>> let pureGen = mkStdGen 137
776
-- >>> runStateGenT pureGen randomM :: IO (Int, StdGen)
777
-- (7879794327570578227,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
778
--
779
-- @since 1.2.0
780
runStateGenT :: RandomGen g => g -> (StateGenM g -> StateT g m a) -> m (a, g)
781
runStateGenT g f = runStateT (f StateGenM) g
1✔
782
{-# INLINE runStateGenT #-}
783

784
-- | Runs a monadic generating action in the `StateT` monad using a pure
785
-- pseudo-random number generator. Returns only the resulting pseudo-random
786
-- value.
787
--
788
-- ====__Examples__
789
--
790
-- >>> import System.Random.Stateful
791
-- >>> let pureGen = mkStdGen 137
792
-- >>> runStateGenT_ pureGen randomM :: IO Int
793
-- 7879794327570578227
794
--
795
-- @since 1.2.1
796
runStateGenT_ :: (RandomGen g, Functor f) => g -> (StateGenM g -> StateT g f a) -> f a
797
runStateGenT_ g = fmap fst . runStateGenT g
2✔
798
{-# INLINE runStateGenT_ #-}
799

800
-- | Runs a monadic generating action in the `ST` monad using a pure
801
-- pseudo-random number generator.
802
--
803
-- @since 1.2.0
804
runStateGenST :: RandomGen g => g -> (forall s . StateGenM g -> StateT g (ST s) a) -> (a, g)
805
runStateGenST g action = runST $ runStateGenT g action
2✔
806
{-# INLINE runStateGenST #-}
807

808
-- | Runs a monadic generating action in the `ST` monad using a pure
809
-- pseudo-random number generator. Same as `runStateGenST`, but discards the
810
-- resulting generator.
811
--
812
-- @since 1.2.1
813
runStateGenST_ :: RandomGen g => g -> (forall s . StateGenM g -> StateT g (ST s) a) -> a
814
runStateGenST_ g action = runST $ runStateGenT_ g action
×
815
{-# INLINE runStateGenST_ #-}
816

817

818
-- | Generates a list of pseudo-random values.
819
--
820
-- ====__Examples__
821
--
822
-- >>> import System.Random.Stateful
823
-- >>> let pureGen = mkStdGen 137
824
-- >>> g <- newIOGenM pureGen
825
-- >>> uniformListM 10 g :: IO [Bool]
826
-- [True,True,True,True,False,True,True,False,False,False]
827
--
828
-- @since 1.2.0
829
uniformListM :: (StatefulGen g m, Uniform a) => Int -> g -> m [a]
830
uniformListM n gen = replicateM n (uniformM gen)
2✔
831
{-# INLINE uniformListM #-}
832

833

834
-- | Generates a list of pseudo-random values in a specified range.
835
--
836
-- ====__Examples__
837
--
838
-- >>> import System.Random.Stateful
839
-- >>> let pureGen = mkStdGen 137
840
-- >>> g <- newIOGenM pureGen
841
-- >>> uniformListRM 10 (20, 30) g :: IO [Int]
842
-- [23,21,28,25,28,28,26,25,29,27]
843
--
844
-- @since 1.3.0
845
uniformListRM :: (StatefulGen g m, UniformRange a) => Int -> (a, a) -> g -> m [a]
846
uniformListRM n range gen = replicateM n (uniformRM range gen)
1✔
847
{-# INLINE uniformListRM #-}
848

849

850
-- | The standard pseudo-random number generator.
851
newtype StdGen = StdGen { unStdGen :: SM.SMGen }
×
852
  deriving (Show, RandomGen, NFData)
×
853

854
instance Eq StdGen where
855
  StdGen x1 == StdGen x2 = SM.unseedSMGen x1 == SM.unseedSMGen x2
2✔
856

857
instance RandomGen SM.SMGen where
858
  next = SM.nextInt
×
859
  {-# INLINE next #-}
860
  genWord32 = SM.nextWord32
2✔
861
  {-# INLINE genWord32 #-}
862
  genWord64 = SM.nextWord64
2✔
863
  {-# INLINE genWord64 #-}
864
  split = SM.splitSMGen
2✔
865
  {-# INLINE split #-}
866
  -- Despite that this is the same default implementation as in the type class definition,
867
  -- for some mysterious reason without this overwrite, performance of ByteArray generation
868
  -- slows down by a factor of x4:
869
  unsafeUniformFillMutableByteArray = defaultUnsafeUniformFillMutableByteArray
2✔
870
  {-# INLINE unsafeUniformFillMutableByteArray #-}
871

872
instance RandomGen SM32.SMGen where
873
  next = SM32.nextInt
×
874
  {-# INLINE next #-}
875
  genWord32 = SM32.nextWord32
×
876
  {-# INLINE genWord32 #-}
877
  genWord64 = SM32.nextWord64
×
878
  {-# INLINE genWord64 #-}
879
  split = SM32.splitSMGen
×
880
  {-# INLINE split #-}
881

882
-- | Constructs a 'StdGen' deterministically.
883
mkStdGen :: Int -> StdGen
884
mkStdGen = StdGen . SM.mkSMGen . fromIntegral
2✔
885

886
-- | Constructs a 'StdGen' deterministically from a `Word64` seed.
887
--
888
-- The difference between `mkStdGen` is that `mkStdGen64` will work the same on 64-bit and
889
-- 32-bit architectures, while the former can only use 32-bit of information for
890
-- initializing the psuedo-random number generator on 32-bit operating systems
891
--
892
-- @since 1.3.0
893
mkStdGen64 :: Word64 -> StdGen
NEW
894
mkStdGen64 = StdGen . SM.mkSMGen
×
895

896
-- | Global mutable veriable with `StdGen`
897
theStdGen :: IORef StdGen
898
theStdGen = unsafePerformIO $ SM.initSMGen >>= newIORef . StdGen
2✔
899
{-# NOINLINE theStdGen #-}
900

901

902
-- | The class of types for which a uniformly distributed value can be drawn
903
-- from all possible values of the type.
904
--
905
-- @since 1.2.0
906
class Uniform a where
907
  -- | Generates a value uniformly distributed over all possible values of that
908
  -- type.
909
  --
910
  -- There is a default implementation via 'Generic':
911
  --
912
  -- >>> :set -XDeriveGeneric -XDeriveAnyClass
913
  -- >>> import GHC.Generics (Generic)
914
  -- >>> import System.Random.Stateful
915
  -- >>> data MyBool = MyTrue | MyFalse deriving (Show, Generic, Finite, Uniform)
916
  -- >>> data Action = Code MyBool | Eat (Maybe Bool) | Sleep deriving (Show, Generic, Finite, Uniform)
917
  -- >>> gen <- newIOGenM (mkStdGen 42)
918
  -- >>> uniformListM 10 gen :: IO [Action]
919
  -- [Code MyTrue,Code MyTrue,Eat Nothing,Code MyFalse,Eat (Just False),Eat (Just True),Eat Nothing,Eat (Just False),Sleep,Code MyFalse]
920
  --
921
  -- @since 1.2.0
922
  uniformM :: StatefulGen g m => g -> m a
923

924
  default uniformM :: (StatefulGen g m, Generic a, GUniform (Rep a)) => g -> m a
925
  uniformM = fmap to . (`runContT` pure) . guniformM
×
926
  {-# INLINE uniformM #-}
927

928
-- | Default implementation of 'Uniform' type class for 'Generic' data.
929
-- It's important to use 'ContT', because without it 'fmap' and '>>=' remain
930
-- polymorphic too long and GHC fails to inline or specialize it, ending up
931
-- building full 'Rep' a structure in memory. 'ContT'
932
-- makes 'fmap' and '>>=' used in 'guniformM' monomorphic, so GHC is able to
933
-- specialize 'Generic' instance reasonably close to a handwritten one.
934
class GUniform f where
935
  guniformM :: StatefulGen g m => g -> ContT r m (f a)
936

937
instance GUniform f => GUniform (M1 i c f) where
938
  guniformM = fmap M1 . guniformM
×
939
  {-# INLINE guniformM #-}
940

941
instance Uniform a => GUniform (K1 i a) where
942
  guniformM = fmap K1 . lift . uniformM
×
943
  {-# INLINE guniformM #-}
944

945
instance GUniform U1 where
946
  guniformM = const $ return U1
×
947
  {-# INLINE guniformM #-}
948

949
instance (GUniform f, GUniform g) => GUniform (f :*: g) where
950
  guniformM g = (:*:) <$> guniformM g <*> guniformM g
×
951
  {-# INLINE guniformM #-}
952

953
instance (GFinite f, GFinite g) => GUniform (f :+: g) where
954
  guniformM = lift . finiteUniformM
×
955
  {-# INLINE guniformM #-}
956

957
finiteUniformM :: forall g m f a. (StatefulGen g m, GFinite f) => g -> m (f a)
958
finiteUniformM = fmap toGFinite . case gcardinality (proxy# :: Proxy# f) of
×
959
  Shift n
960
    | n <= 64 -> fmap toInteger . unsignedBitmaskWithRejectionM uniformWord64 (bit n - 1)
×
961
    | otherwise -> boundedByPowerOf2ExclusiveIntegralM n
×
962
  Card n
963
    | n <= bit 64 -> fmap toInteger . unsignedBitmaskWithRejectionM uniformWord64 (fromInteger n - 1)
×
964
    | otherwise -> boundedExclusiveIntegralM n
×
965
{-# INLINE finiteUniformM #-}
966

967
-- | A definition of 'Uniform' for 'System.Random.Finite' types.
968
-- If your data has several fields of sub-'Word' cardinality,
969
-- this instance may be more efficient than one, derived via 'Generic' and 'GUniform'.
970
--
971
-- >>> :set -XDeriveGeneric -XDeriveAnyClass
972
-- >>> import GHC.Generics (Generic)
973
-- >>> import System.Random.Stateful
974
-- >>> data Triple = Triple Word8 Word8 Word8 deriving (Show, Generic, Finite)
975
-- >>> instance Uniform Triple where uniformM = uniformViaFiniteM
976
-- >>> gen <- newIOGenM (mkStdGen 42)
977
-- >>> uniformListM 5 gen :: IO [Triple]
978
-- [Triple 60 226 48,Triple 234 194 151,Triple 112 96 95,Triple 51 251 15,Triple 6 0 208]
979
--
980
uniformViaFiniteM :: (StatefulGen g m, Generic a, GFinite (Rep a)) => g -> m a
981
uniformViaFiniteM = fmap to . finiteUniformM
×
982
{-# INLINE uniformViaFiniteM #-}
983

984
-- | The class of types for which a uniformly distributed value can be drawn
985
-- from a range.
986
--
987
-- @since 1.2.0
988
class UniformRange a where
989
  -- | Generates a value uniformly distributed over the provided range, which
990
  -- is interpreted as inclusive in the lower and upper bound.
991
  --
992
  -- *   @uniformRM (1 :: Int, 4 :: Int)@ generates values uniformly from the
993
  --     set \(\{1,2,3,4\}\)
994
  --
995
  -- *   @uniformRM (1 :: Float, 4 :: Float)@ generates values uniformly from
996
  --     the set \(\{x\;|\;1 \le x \le 4\}\)
997
  --
998
  -- The following law should hold to make the function always defined:
999
  --
1000
  -- > uniformRM (a, b) = uniformRM (b, a)
1001
  --
1002
  -- The range is understood as defined by means of 'isInRange', so
1003
  --
1004
  -- > isInRange (a, b) <$> uniformRM (a, b) gen == pure True
1005
  --
1006
  -- but beware of
1007
  -- [floating point number caveats](System-Random-Stateful.html#fpcaveats).
1008
  --
1009
  -- There is a default implementation via 'Generic':
1010
  --
1011
  -- >>> :set -XDeriveGeneric -XDeriveAnyClass
1012
  -- >>> import GHC.Generics (Generic)
1013
  -- >>> import Data.Word (Word8)
1014
  -- >>> import Control.Monad (replicateM)
1015
  -- >>> import System.Random.Stateful
1016
  -- >>> gen <- newIOGenM (mkStdGen 42)
1017
  -- >>> data Tuple = Tuple Bool Word8 deriving (Show, Generic, UniformRange)
1018
  -- >>> replicateM 10 (uniformRM (Tuple False 100, Tuple True 150) gen)
1019
  -- [Tuple False 102,Tuple True 118,Tuple False 115,Tuple True 113,Tuple True 126,Tuple False 127,Tuple True 130,Tuple False 113,Tuple False 150,Tuple False 125]
1020
  --
1021
  -- @since 1.2.0
1022
  uniformRM :: StatefulGen g m => (a, a) -> g -> m a
1023

1024
  -- | A notion of (inclusive) ranges prescribed to @a@.
1025
  --
1026
  -- Ranges are symmetric:
1027
  --
1028
  -- > isInRange (lo, hi) x == isInRange (hi, lo) x
1029
  --
1030
  -- Ranges include their endpoints:
1031
  --
1032
  -- > isInRange (lo, hi) lo == True
1033
  --
1034
  -- When endpoints coincide, there is nothing else:
1035
  --
1036
  -- > isInRange (x, x) y == x == y
1037
  --
1038
  -- Endpoints are endpoints:
1039
  --
1040
  -- > isInRange (lo, hi) x ==>
1041
  -- > isInRange (lo, x) hi == x == hi
1042
  --
1043
  -- Ranges are transitive relations:
1044
  --
1045
  -- > isInRange (lo, hi) lo' && isInRange (lo, hi) hi' && isInRange (lo', hi') x
1046
  -- > ==> isInRange (lo, hi) x
1047
  --
1048
  -- There is a default implementation of 'isInRange' via 'Generic'. Other helper function
1049
  -- that can be used for implementing this function are `isInRangeOrd` and
1050
  -- `isInRangeEnum`
1051
  --
1052
  -- @since 1.3.0
1053
  isInRange :: (a, a) -> a -> Bool
1054

1055
  default uniformRM :: (StatefulGen g m, Generic a, GUniformRange (Rep a)) => (a, a) -> g -> m a
1056
  uniformRM (a, b) = fmap to . (`runContT` pure) . guniformRM (from a, from b)
2✔
1057
  {-# INLINE uniformRM #-}
1058

1059
  default isInRange :: (Generic a, GUniformRange (Rep a)) => (a, a) -> a -> Bool
1060
  isInRange (a, b) x = gisInRange (from a, from b) (from x)
2✔
1061
  {-# INLINE isInRange #-}
1062

1063
class GUniformRange f where
1064
  guniformRM :: StatefulGen g m => (f a, f a) -> g -> ContT r m (f a)
1065
  gisInRange :: (f a, f a) -> f a -> Bool
1066

1067
instance GUniformRange f => GUniformRange (M1 i c f) where
1068
  guniformRM (M1 a, M1 b) = fmap M1 . guniformRM (a, b)
2✔
1069
  {-# INLINE guniformRM #-}
1070
  gisInRange (M1 a, M1 b) (M1 x) = gisInRange (a, b) x
2✔
1071

1072
instance UniformRange a => GUniformRange (K1 i a) where
1073
  guniformRM (K1 a, K1 b) = fmap K1 . lift . uniformRM (a, b)
2✔
1074
  {-# INLINE guniformRM #-}
1075
  gisInRange (K1 a, K1 b) (K1 x) = isInRange (a, b) x
2✔
1076

1077
instance GUniformRange U1 where
1078
  guniformRM = const $ const $ return U1
×
1079
  {-# INLINE guniformRM #-}
1080
  gisInRange = const $ const True
2✔
1081

1082
instance (GUniformRange f, GUniformRange g) => GUniformRange (f :*: g) where
1083
  guniformRM (x1 :*: y1, x2 :*: y2) g =
2✔
1084
    (:*:) <$> guniformRM (x1, x2) g <*> guniformRM (y1, y2) g
1✔
1085
  {-# INLINE guniformRM #-}
1086
  gisInRange (x1 :*: y1, x2 :*: y2) (x3 :*: y3) =
2✔
1087
    gisInRange (x1, x2) x3 && gisInRange (y1, y2) y3
2✔
1088

1089
-- | Utilize `Ord` instance to decide if a value is within the range. Designed to be used
1090
-- for implementing `isInRange`
1091
--
1092
-- @since 1.3.0
1093
isInRangeOrd :: Ord a => (a, a) -> a -> Bool
1094
isInRangeOrd (a, b) x = min a b <= x && x <= max a b
2✔
1095

1096
-- | Utilize `Enum` instance to decide if a value is within the range. Designed to be used
1097
-- for implementing `isInRange`
1098
--
1099
-- @since 1.3.0
1100
isInRangeEnum :: Enum a => (a, a) -> a -> Bool
1101
isInRangeEnum (a, b) x = isInRangeOrd (fromEnum a, fromEnum b) (fromEnum x)
×
1102

1103
instance UniformRange Integer where
1104
  uniformRM = uniformIntegralM
2✔
1105
  {-# INLINE uniformRM #-}
1106
  isInRange = isInRangeOrd
2✔
1107

1108
instance UniformRange Natural where
1109
  uniformRM = uniformIntegralM
2✔
1110
  {-# INLINE uniformRM #-}
1111
  isInRange = isInRangeOrd
2✔
1112

1113
instance Uniform Int8 where
1114
  uniformM = fmap (fromIntegral :: Word8 -> Int8) . uniformWord8
2✔
1115
  {-# INLINE uniformM #-}
1116
instance UniformRange Int8 where
1117
  uniformRM = signedBitmaskWithRejectionRM (fromIntegral :: Int8 -> Word8) fromIntegral
2✔
1118
  {-# INLINE uniformRM #-}
1119
  isInRange = isInRangeOrd
2✔
1120

1121
instance Uniform Int16 where
1122
  uniformM = fmap (fromIntegral :: Word16 -> Int16) . uniformWord16
2✔
1123
  {-# INLINE uniformM #-}
1124
instance UniformRange Int16 where
1125
  uniformRM = signedBitmaskWithRejectionRM (fromIntegral :: Int16 -> Word16) fromIntegral
2✔
1126
  {-# INLINE uniformRM #-}
1127
  isInRange = isInRangeOrd
2✔
1128

1129
instance Uniform Int32 where
1130
  uniformM = fmap (fromIntegral :: Word32 -> Int32) . uniformWord32
2✔
1131
  {-# INLINE uniformM #-}
1132
instance UniformRange Int32 where
1133
  uniformRM = signedBitmaskWithRejectionRM (fromIntegral :: Int32 -> Word32) fromIntegral
2✔
1134
  {-# INLINE uniformRM #-}
1135
  isInRange = isInRangeOrd
2✔
1136

1137
instance Uniform Int64 where
1138
  uniformM = fmap (fromIntegral :: Word64 -> Int64) . uniformWord64
2✔
1139
  {-# INLINE uniformM #-}
1140
instance UniformRange Int64 where
1141
  uniformRM = signedBitmaskWithRejectionRM (fromIntegral :: Int64 -> Word64) fromIntegral
2✔
1142
  {-# INLINE uniformRM #-}
1143
  isInRange = isInRangeOrd
2✔
1144

1145
wordSizeInBits :: Int
1146
wordSizeInBits = finiteBitSize (0 :: Word)
1✔
1147

1148
instance Uniform Int where
1149
  uniformM
2✔
1150
    | wordSizeInBits == 64 =
1✔
1151
      fmap (fromIntegral :: Word64 -> Int) . uniformWord64
2✔
1152
    | otherwise =
×
1153
      fmap (fromIntegral :: Word32 -> Int) . uniformWord32
×
1154
  {-# INLINE uniformM #-}
1155

1156
instance UniformRange Int where
1157
  uniformRM = signedBitmaskWithRejectionRM (fromIntegral :: Int -> Word) fromIntegral
2✔
1158
  {-# INLINE uniformRM #-}
1159
  isInRange = isInRangeOrd
2✔
1160

1161
instance Uniform Word where
1162
  uniformM
2✔
1163
    | wordSizeInBits == 64 =
1✔
1164
      fmap (fromIntegral :: Word64 -> Word) . uniformWord64
2✔
1165
    | otherwise =
×
1166
      fmap (fromIntegral :: Word32 -> Word) . uniformWord32
×
1167
  {-# INLINE uniformM #-}
1168

1169
instance UniformRange Word where
1170
  uniformRM = unsignedBitmaskWithRejectionRM
2✔
1171
  {-# INLINE uniformRM #-}
1172
  isInRange = isInRangeOrd
2✔
1173

1174
instance Uniform Word8 where
1175
  uniformM = uniformWord8
2✔
1176
  {-# INLINE uniformM #-}
1177
instance UniformRange Word8 where
1178
  uniformRM = unbiasedWordMult32RM
2✔
1179
  {-# INLINE uniformRM #-}
1180
  isInRange = isInRangeOrd
2✔
1181

1182
instance Uniform Word16 where
1183
  uniformM = uniformWord16
2✔
1184
  {-# INLINE uniformM #-}
1185
instance UniformRange Word16 where
1186
  uniformRM = unbiasedWordMult32RM
2✔
1187
  {-# INLINE uniformRM #-}
1188
  isInRange = isInRangeOrd
2✔
1189

1190
instance Uniform Word32 where
1191
  uniformM  = uniformWord32
2✔
1192
  {-# INLINE uniformM #-}
1193
instance UniformRange Word32 where
1194
  uniformRM = unbiasedWordMult32RM
2✔
1195
  {-# INLINE uniformRM #-}
1196
  isInRange = isInRangeOrd
2✔
1197

1198
instance Uniform Word64 where
1199
  uniformM  = uniformWord64
2✔
1200
  {-# INLINE uniformM #-}
1201
instance UniformRange Word64 where
1202
  uniformRM = unsignedBitmaskWithRejectionRM
2✔
1203
  {-# INLINE uniformRM #-}
1204
  isInRange = isInRangeOrd
2✔
1205

1206
#if __GLASGOW_HASKELL__ >= 802
1207
instance Uniform CBool where
1208
  uniformM = fmap CBool . uniformM
×
1209
  {-# INLINE uniformM #-}
1210
instance UniformRange CBool where
1211
  uniformRM (CBool b, CBool t) = fmap CBool . uniformRM (b, t)
2✔
1212
  {-# INLINE uniformRM #-}
1213
  isInRange = isInRangeOrd
2✔
1214
#endif
1215

1216
instance Uniform CChar where
1217
  uniformM = fmap CChar . uniformM
2✔
1218
  {-# INLINE uniformM #-}
1219
instance UniformRange CChar where
1220
  uniformRM (CChar b, CChar t) = fmap CChar . uniformRM (b, t)
2✔
1221
  {-# INLINE uniformRM #-}
1222
  isInRange = isInRangeOrd
2✔
1223

1224
instance Uniform CSChar where
1225
  uniformM = fmap CSChar . uniformM
2✔
1226
  {-# INLINE uniformM #-}
1227
instance UniformRange CSChar where
1228
  uniformRM (CSChar b, CSChar t) = fmap CSChar . uniformRM (b, t)
2✔
1229
  {-# INLINE uniformRM #-}
1230
  isInRange = isInRangeOrd
2✔
1231

1232
instance Uniform CUChar where
1233
  uniformM = fmap CUChar . uniformM
2✔
1234
  {-# INLINE uniformM #-}
1235
instance UniformRange CUChar where
1236
  uniformRM (CUChar b, CUChar t) = fmap CUChar . uniformRM (b, t)
2✔
1237
  {-# INLINE uniformRM #-}
1238
  isInRange = isInRangeOrd
2✔
1239

1240
instance Uniform CShort where
1241
  uniformM = fmap CShort . uniformM
2✔
1242
  {-# INLINE uniformM #-}
1243
instance UniformRange CShort where
1244
  uniformRM (CShort b, CShort t) = fmap CShort . uniformRM (b, t)
2✔
1245
  {-# INLINE uniformRM #-}
1246
  isInRange = isInRangeOrd
2✔
1247

1248
instance Uniform CUShort where
1249
  uniformM = fmap CUShort . uniformM
2✔
1250
  {-# INLINE uniformM #-}
1251
instance UniformRange CUShort where
1252
  uniformRM (CUShort b, CUShort t) = fmap CUShort . uniformRM (b, t)
2✔
1253
  {-# INLINE uniformRM #-}
1254
  isInRange = isInRangeOrd
2✔
1255

1256
instance Uniform CInt where
1257
  uniformM = fmap CInt . uniformM
2✔
1258
  {-# INLINE uniformM #-}
1259
instance UniformRange CInt where
1260
  uniformRM (CInt b, CInt t) = fmap CInt . uniformRM (b, t)
2✔
1261
  {-# INLINE uniformRM #-}
1262
  isInRange = isInRangeOrd
2✔
1263

1264
instance Uniform CUInt where
1265
  uniformM = fmap CUInt . uniformM
2✔
1266
  {-# INLINE uniformM #-}
1267
instance UniformRange CUInt where
1268
  uniformRM (CUInt b, CUInt t) = fmap CUInt . uniformRM (b, t)
2✔
1269
  {-# INLINE uniformRM #-}
1270
  isInRange = isInRangeOrd
2✔
1271

1272
instance Uniform CLong where
1273
  uniformM = fmap CLong . uniformM
2✔
1274
  {-# INLINE uniformM #-}
1275
instance UniformRange CLong where
1276
  uniformRM (CLong b, CLong t) = fmap CLong . uniformRM (b, t)
2✔
1277
  {-# INLINE uniformRM #-}
1278
  isInRange = isInRangeOrd
2✔
1279

1280
instance Uniform CULong where
1281
  uniformM = fmap CULong . uniformM
2✔
1282
  {-# INLINE uniformM #-}
1283
instance UniformRange CULong where
1284
  uniformRM (CULong b, CULong t) = fmap CULong . uniformRM (b, t)
2✔
1285
  {-# INLINE uniformRM #-}
1286
  isInRange = isInRangeOrd
2✔
1287

1288
instance Uniform CPtrdiff where
1289
  uniformM = fmap CPtrdiff . uniformM
2✔
1290
  {-# INLINE uniformM #-}
1291
instance UniformRange CPtrdiff where
1292
  uniformRM (CPtrdiff b, CPtrdiff t) = fmap CPtrdiff . uniformRM (b, t)
2✔
1293
  {-# INLINE uniformRM #-}
1294
  isInRange = isInRangeOrd
2✔
1295

1296
instance Uniform CSize where
1297
  uniformM = fmap CSize . uniformM
2✔
1298
  {-# INLINE uniformM #-}
1299
instance UniformRange CSize where
1300
  uniformRM (CSize b, CSize t) = fmap CSize . uniformRM (b, t)
2✔
1301
  {-# INLINE uniformRM #-}
1302
  isInRange = isInRangeOrd
2✔
1303

1304
instance Uniform CWchar where
1305
  uniformM = fmap CWchar . uniformM
2✔
1306
  {-# INLINE uniformM #-}
1307
instance UniformRange CWchar where
1308
  uniformRM (CWchar b, CWchar t) = fmap CWchar . uniformRM (b, t)
2✔
1309
  {-# INLINE uniformRM #-}
1310
  isInRange = isInRangeOrd
2✔
1311

1312
instance Uniform CSigAtomic where
1313
  uniformM = fmap CSigAtomic . uniformM
2✔
1314
  {-# INLINE uniformM #-}
1315
instance UniformRange CSigAtomic where
1316
  uniformRM (CSigAtomic b, CSigAtomic t) = fmap CSigAtomic . uniformRM (b, t)
2✔
1317
  {-# INLINE uniformRM #-}
1318
  isInRange = isInRangeOrd
2✔
1319

1320
instance Uniform CLLong where
1321
  uniformM = fmap CLLong . uniformM
2✔
1322
  {-# INLINE uniformM #-}
1323
instance UniformRange CLLong where
1324
  uniformRM (CLLong b, CLLong t) = fmap CLLong . uniformRM (b, t)
2✔
1325
  {-# INLINE uniformRM #-}
1326
  isInRange = isInRangeOrd
2✔
1327

1328
instance Uniform CULLong where
1329
  uniformM = fmap CULLong . uniformM
2✔
1330
  {-# INLINE uniformM #-}
1331
instance UniformRange CULLong where
1332
  uniformRM (CULLong b, CULLong t) = fmap CULLong . uniformRM (b, t)
2✔
1333
  {-# INLINE uniformRM #-}
1334
  isInRange = isInRangeOrd
2✔
1335

1336
instance Uniform CIntPtr where
1337
  uniformM = fmap CIntPtr . uniformM
2✔
1338
  {-# INLINE uniformM #-}
1339
instance UniformRange CIntPtr where
1340
  uniformRM (CIntPtr b, CIntPtr t) = fmap CIntPtr . uniformRM (b, t)
2✔
1341
  {-# INLINE uniformRM #-}
1342
  isInRange = isInRangeOrd
2✔
1343

1344
instance Uniform CUIntPtr where
1345
  uniformM = fmap CUIntPtr . uniformM
2✔
1346
  {-# INLINE uniformM #-}
1347
instance UniformRange CUIntPtr where
1348
  uniformRM (CUIntPtr b, CUIntPtr t) = fmap CUIntPtr . uniformRM (b, t)
2✔
1349
  {-# INLINE uniformRM #-}
1350
  isInRange = isInRangeOrd
2✔
1351

1352
instance Uniform CIntMax where
1353
  uniformM = fmap CIntMax . uniformM
2✔
1354
  {-# INLINE uniformM #-}
1355
instance UniformRange CIntMax where
1356
  uniformRM (CIntMax b, CIntMax t) = fmap CIntMax . uniformRM (b, t)
2✔
1357
  {-# INLINE uniformRM #-}
1358
  isInRange = isInRangeOrd
2✔
1359

1360
instance Uniform CUIntMax where
1361
  uniformM = fmap CUIntMax . uniformM
2✔
1362
  {-# INLINE uniformM #-}
1363
instance UniformRange CUIntMax where
1364
  uniformRM (CUIntMax b, CUIntMax t) = fmap CUIntMax . uniformRM (b, t)
2✔
1365
  {-# INLINE uniformRM #-}
1366
  isInRange = isInRangeOrd
2✔
1367

1368
-- | See [Floating point number caveats](System-Random-Stateful.html#fpcaveats).
1369
instance UniformRange CFloat where
1370
  uniformRM (CFloat l, CFloat h) = fmap CFloat . uniformRM (l, h)
2✔
1371
  {-# INLINE uniformRM #-}
1372
  isInRange = isInRangeOrd
2✔
1373

1374
-- | See [Floating point number caveats](System-Random-Stateful.html#fpcaveats).
1375
instance UniformRange CDouble where
1376
  uniformRM (CDouble l, CDouble h) = fmap CDouble . uniformRM (l, h)
2✔
1377
  {-# INLINE uniformRM #-}
1378
  isInRange = isInRangeOrd
2✔
1379

1380
-- The `chr#` and `ord#` are the prim functions that will be called, regardless of which
1381
-- way you gonna do the `Char` conversion, so it is better to call them directly and
1382
-- bypass all the hoops. Also because `intToChar` and `charToInt` are internal functions
1383
-- and are called on valid character ranges it is impossible to generate an invalid
1384
-- `Char`, therefore it is totally fine to omit all the unnecessary checks involved in
1385
-- other paths of conversion.
1386
word32ToChar :: Word32 -> Char
1387
#if __GLASGOW_HASKELL__ < 902
1388
word32ToChar (W32# w#) = C# (chr# (word2Int# w#))
2✔
1389
#else
1390
word32ToChar (W32# w#) = C# (chr# (word2Int# (word32ToWord# w#)))
1391
#endif
1392
{-# INLINE word32ToChar #-}
1393

1394
charToWord32 :: Char -> Word32
1395
#if __GLASGOW_HASKELL__ < 902
1396
charToWord32 (C# c#) = W32# (int2Word# (ord# c#))
2✔
1397
#else
1398
charToWord32 (C# c#) = W32# (wordToWord32# (int2Word# (ord# c#)))
1399
#endif
1400
{-# INLINE charToWord32 #-}
1401

1402
instance Uniform Char where
1403
  uniformM g = word32ToChar <$> unbiasedWordMult32 (charToWord32 maxBound) g
2✔
1404
  {-# INLINE uniformM #-}
1405
instance UniformRange Char where
1406
  uniformRM (l, h) g =
2✔
1407
    word32ToChar <$> unbiasedWordMult32RM (charToWord32 l, charToWord32 h) g
1✔
1408
  {-# INLINE uniformRM #-}
1409
  isInRange = isInRangeOrd
2✔
1410

1411
instance Uniform () where
1412
  uniformM = const $ pure ()
×
1413
  {-# INLINE uniformM #-}
1414
instance UniformRange () where
1415
  uniformRM = const $ const $ pure ()
2✔
1416
  {-# INLINE uniformRM #-}
1417

1418
instance Uniform Bool where
1419
  uniformM = fmap wordToBool . uniformWord8
2✔
1420
    where wordToBool w = (w .&. 1) /= 0
2✔
1421
          {-# INLINE wordToBool #-}
1422
  {-# INLINE uniformM #-}
1423
instance UniformRange Bool where
1424
  uniformRM (False, False) _g = return False
2✔
1425
  uniformRM (True, True)   _g = return True
2✔
1426
  uniformRM _               g = uniformM g
1✔
1427
  {-# INLINE uniformRM #-}
1428
  isInRange = isInRangeOrd
2✔
1429

1430
-- | See [Floating point number caveats](System-Random-Stateful.html#fpcaveats).
1431
instance UniformRange Double where
1432
  uniformRM (l, h) g
2✔
1433
    | l == h = return l
2✔
1434
    | isInfinite l || isInfinite h =
2✔
1435
      -- Optimisation exploiting absorption:
1436
      --   (-Infinity) + (anything but +Infinity) = -Infinity
1437
      --   (anything but -Infinity) + (+Infinity) = +Infinity
1438
      --                (-Infinity) + (+Infinity) = NaN
1439
      return $! h + l
2✔
1440
    | otherwise = do
1✔
1441
      x <- uniformDouble01M g
1✔
1442
      return $ x * l + (1 -x) * h
2✔
1443
  {-# INLINE uniformRM #-}
1444
  isInRange = isInRangeOrd
2✔
1445

1446
-- | Generates uniformly distributed 'Double' in the range \([0, 1]\).
1447
--   Numbers are generated by generating uniform 'Word64' and dividing
1448
--   it by \(2^{64}\). It's used to implement 'UniformRange' instance for
1449
--   'Double'.
1450
--
1451
-- @since 1.2.0
1452
uniformDouble01M :: forall g m. StatefulGen g m => g -> m Double
1453
uniformDouble01M g = do
2✔
1454
  w64 <- uniformWord64 g
1✔
1455
  return $ fromIntegral w64 / m
2✔
1456
  where
1457
    m = fromIntegral (maxBound :: Word64) :: Double
2✔
1458
{-# INLINE uniformDouble01M #-}
1459

1460
-- | Generates uniformly distributed 'Double' in the range
1461
--   \((0, 1]\). Number is generated as \(2^{-64}/2+\operatorname{uniformDouble01M}\).
1462
--   Constant is 1\/2 of smallest nonzero value which could be generated
1463
--   by 'uniformDouble01M'.
1464
--
1465
-- @since 1.2.0
1466
uniformDoublePositive01M :: forall g m. StatefulGen g m => g -> m Double
1467
uniformDoublePositive01M g = (+ d) <$> uniformDouble01M g
1✔
1468
  where
1469
    -- We add small constant to shift generated value from zero. It's
1470
    -- selected as 1/2 of smallest possible nonzero value
1471
    d = 2.710505431213761e-20 -- 2**(-65)
2✔
1472
{-# INLINE uniformDoublePositive01M #-}
1473

1474
-- | See [Floating point number caveats](System-Random-Stateful.html#fpcaveats).
1475
instance UniformRange Float where
1476
  uniformRM (l, h) g
2✔
1477
    | l == h = return l
2✔
1478
    | isInfinite l || isInfinite h =
2✔
1479
      -- Optimisation exploiting absorption:
1480
      --   (-Infinity) + (anything but +Infinity) = -Infinity
1481
      --   (anything but -Infinity) + (+Infinity) = +Infinity
1482
      --                (-Infinity) + (+Infinity) = NaN
1483
      return $! h + l
2✔
1484
    | otherwise = do
1✔
1485
      x <- uniformFloat01M g
1✔
1486
      return $ x * l + (1 - x) * h
2✔
1487
  {-# INLINE uniformRM #-}
1488
  isInRange = isInRangeOrd
2✔
1489

1490
-- | Generates uniformly distributed 'Float' in the range \([0, 1]\).
1491
--   Numbers are generated by generating uniform 'Word32' and dividing
1492
--   it by \(2^{32}\). It's used to implement 'UniformRange' instance for 'Float'.
1493
--
1494
-- @since 1.2.0
1495
uniformFloat01M :: forall g m. StatefulGen g m => g -> m Float
1496
uniformFloat01M g = do
2✔
1497
  w32 <- uniformWord32 g
1✔
1498
  return $ fromIntegral w32 / m
2✔
1499
  where
1500
    m = fromIntegral (maxBound :: Word32) :: Float
2✔
1501
{-# INLINE uniformFloat01M #-}
1502

1503
-- | Generates uniformly distributed 'Float' in the range
1504
--   \((0, 1]\). Number is generated as \(2^{-32}/2+\operatorname{uniformFloat01M}\).
1505
--   Constant is 1\/2 of smallest nonzero value which could be generated
1506
--   by 'uniformFloat01M'.
1507
--
1508
-- @since 1.2.0
1509
uniformFloatPositive01M :: forall g m. StatefulGen g m => g -> m Float
1510
uniformFloatPositive01M g = (+ d) <$> uniformFloat01M g
1✔
1511
  where
1512
    -- See uniformDoublePositive01M
1513
    d = 1.1641532182693481e-10 -- 2**(-33)
2✔
1514
{-# INLINE uniformFloatPositive01M #-}
1515

1516
-- | Generates uniformly distributed 'Enum'.
1517
-- One can use it to define a 'Uniform' instance:
1518
--
1519
-- > data Colors = Red | Green | Blue deriving (Enum, Bounded)
1520
-- > instance Uniform Colors where uniformM = uniformEnumM
1521
--
1522
-- @since 1.3.0
1523
uniformEnumM :: forall a g m. (Enum a, Bounded a, StatefulGen g m) => g -> m a
1524
uniformEnumM g = toEnum <$> uniformRM (fromEnum (minBound :: a), fromEnum (maxBound :: a)) g
×
1525
{-# INLINE uniformEnumM #-}
1526

1527
-- | Generates uniformly distributed 'Enum' in the given range.
1528
-- One can use it to define a 'UniformRange' instance:
1529
--
1530
-- > data Colors = Red | Green | Blue deriving (Enum)
1531
-- > instance UniformRange Colors where
1532
-- >   uniformRM = uniformEnumRM
1533
-- >   inInRange (lo, hi) x = isInRange (fromEnum lo, fromEnum hi) (fromEnum x)
1534
--
1535
-- @since 1.3.0
1536
uniformEnumRM :: forall a g m. (Enum a, StatefulGen g m) => (a, a) -> g -> m a
1537
uniformEnumRM (l, h) g = toEnum <$> uniformRM (fromEnum l, fromEnum h) g
1✔
1538
{-# INLINE uniformEnumRM #-}
1539

1540
-- The two integer functions below take an [inclusive,inclusive] range.
1541
randomIvalIntegral :: (RandomGen g, Integral a) => (a, a) -> g -> (a, g)
1542
randomIvalIntegral (l, h) = randomIvalInteger (toInteger l, toInteger h)
×
1543

1544
{-# SPECIALIZE randomIvalInteger :: (Num a) =>
1545
    (Integer, Integer) -> StdGen -> (a, StdGen) #-}
1546

1547
randomIvalInteger :: (RandomGen g, Num a) => (Integer, Integer) -> g -> (a, g)
1548
randomIvalInteger (l, h) rng
×
1549
 | l > h     = randomIvalInteger (h,l) rng
×
1550
 | otherwise = case f 1 0 rng of (v, rng') -> (fromInteger (l + v `mod` k), rng')
×
1551
     where
1552
       (genlo, genhi) = genRange rng
×
1553
       b = fromIntegral genhi - fromIntegral genlo + 1 :: Integer
×
1554

1555
       -- Probabilities of the most likely and least likely result
1556
       -- will differ at most by a factor of (1 +- 1/q). Assuming the RandomGen
1557
       -- is uniform, of course
1558

1559
       -- On average, log q / log b more pseudo-random values will be generated
1560
       -- than the minimum
1561
       q = 1000 :: Integer
×
1562
       k = h - l + 1
×
1563
       magtgt = k * q
×
1564

1565
       -- generate pseudo-random values until we exceed the target magnitude
1566
       f mag v g | mag >= magtgt = (v, g)
×
1567
                 | otherwise = v' `seq`f (mag*b) v' g' where
×
1568
                        (x,g') = next g
×
1569
                        v' = v * b + (fromIntegral x - fromIntegral genlo)
×
1570

1571
-- | Generate an integral in the range @[l, h]@ if @l <= h@ and @[h, l]@
1572
-- otherwise.
1573
uniformIntegralM :: forall a g m. (Bits a, Integral a, StatefulGen g m) => (a, a) -> g -> m a
1574
uniformIntegralM (l, h) gen = case l `compare` h of
2✔
1575
  LT -> do
2✔
1576
    let limit = h - l
2✔
1577
    bounded <- case toIntegralSized limit :: Maybe Word64 of
2✔
1578
      Just limitAsWord64 ->
1579
        -- Optimisation: if 'limit' fits into 'Word64', generate a bounded
1580
        -- 'Word64' and then convert to 'Integer'
1581
        fromIntegral <$> unsignedBitmaskWithRejectionM uniformWord64 limitAsWord64 gen
1✔
1582
      Nothing -> boundedExclusiveIntegralM (limit + 1) gen
1✔
1583
    return $ l + bounded
2✔
1584
  GT -> uniformIntegralM (h, l) gen
1✔
1585
  EQ -> pure l
2✔
1586
{-# INLINEABLE uniformIntegralM #-}
1587
{-# SPECIALIZE uniformIntegralM :: StatefulGen g m => (Integer, Integer) -> g -> m Integer #-}
1588
{-# SPECIALIZE uniformIntegralM :: StatefulGen g m => (Natural, Natural) -> g -> m Natural #-}
1589

1590
-- | Generate an integral in the range @[0, s)@ using a variant of Lemire's
1591
-- multiplication method.
1592
--
1593
-- Daniel Lemire. 2019. Fast Random Integer Generation in an Interval. In ACM
1594
-- Transactions on Modeling and Computer Simulation
1595
-- https://doi.org/10.1145/3230636
1596
--
1597
-- PRECONDITION (unchecked): s > 0
1598
boundedExclusiveIntegralM :: forall a g m . (Bits a, Integral a, StatefulGen g m) => a -> g -> m a
1599
boundedExclusiveIntegralM s gen = go
2✔
1600
  where
1601
    n = integralWordSize s
2✔
1602
    -- We renamed 'L' from the paper to 'k' here because 'L' is not a valid
1603
    -- variable name in Haskell and 'l' is already used in the algorithm.
1604
    k = wordSizeInBits * n
2✔
1605
    twoToK = (1 :: a) `shiftL` k
2✔
1606
    modTwoToKMask = twoToK - 1
2✔
1607

1608
    t = (twoToK - s) `rem` s -- `rem`, instead of `mod` because `twoToK >= s` is guaranteed
2✔
1609
    go :: (Bits a, Integral a, StatefulGen g m) => m a
1610
    go = do
2✔
1611
      x <- uniformIntegralWords n gen
1✔
1612
      let m = x * s
2✔
1613
      -- m .&. modTwoToKMask == m `mod` twoToK
1614
      let l = m .&. modTwoToKMask
2✔
1615
      if l < t
1✔
1616
        then go
×
1617
        -- m `shiftR` k == m `quot` twoToK
1618
        else return $ m `shiftR` k
2✔
1619
{-# INLINE boundedExclusiveIntegralM #-}
1620

1621
-- | boundedByPowerOf2ExclusiveIntegralM s ~ boundedExclusiveIntegralM (bit s)
1622
boundedByPowerOf2ExclusiveIntegralM ::
1623
  forall a g m. (Bits a, Integral a, StatefulGen g m) => Int -> g -> m a
1624
boundedByPowerOf2ExclusiveIntegralM s gen = do
×
1625
  let n = (s + wordSizeInBits - 1) `quot` wordSizeInBits
×
1626
  x <- uniformIntegralWords n gen
×
1627
  return $ x .&. (bit s - 1)
×
1628
{-# INLINE boundedByPowerOf2ExclusiveIntegralM #-}
1629

1630
-- | @integralWordSize i@ returns that least @w@ such that
1631
-- @i <= WORD_SIZE_IN_BITS^w@.
1632
integralWordSize :: (Bits a, Num a) => a -> Int
1633
integralWordSize = go 0
2✔
1634
  where
1635
    go !acc i
2✔
1636
      | i == 0 = acc
2✔
1637
      | otherwise = go (acc + 1) (i `shiftR` wordSizeInBits)
1✔
1638
{-# INLINE integralWordSize #-}
1639

1640
-- | @uniformIntegralWords n@ is a uniformly pseudo-random integral in the range
1641
-- @[0, WORD_SIZE_IN_BITS^n)@.
1642
uniformIntegralWords :: forall a g m. (Bits a, Integral a, StatefulGen g m) => Int -> g -> m a
1643
uniformIntegralWords n gen = go 0 n
2✔
1644
  where
1645
    go !acc i
2✔
1646
      | i == 0 = return acc
2✔
1647
      | otherwise = do
1✔
1648
        (w :: Word) <- uniformM gen
1✔
1649
        go ((acc `shiftL` wordSizeInBits) .|. fromIntegral w) (i - 1)
2✔
1650
{-# INLINE uniformIntegralWords #-}
1651

1652
-- | Uniformly generate an 'Integral' in an inclusive-inclusive range.
1653
--
1654
-- Only use for integrals size less than or equal to that of 'Word32'.
1655
unbiasedWordMult32RM :: forall a g m. (Integral a, StatefulGen g m) => (a, a) -> g -> m a
1656
unbiasedWordMult32RM (b, t) g
2✔
1657
  | b <= t    = (+b) . fromIntegral <$> unbiasedWordMult32 (fromIntegral (t - b)) g
1✔
1658
  | otherwise = (+t) . fromIntegral <$> unbiasedWordMult32 (fromIntegral (b - t)) g
1✔
1659
{-# INLINE unbiasedWordMult32RM #-}
1660

1661
-- | Uniformly generate Word32 in @[0, s]@.
1662
unbiasedWordMult32 :: forall g m. StatefulGen g m => Word32 -> g -> m Word32
1663
unbiasedWordMult32 s g
2✔
1664
  | s == maxBound = uniformWord32 g
1✔
1665
  | otherwise = unbiasedWordMult32Exclusive (s+1) g
1✔
1666
{-# INLINE unbiasedWordMult32 #-}
1667

1668
-- | See [Lemire's paper](https://arxiv.org/pdf/1805.10941.pdf),
1669
-- [O\'Neill's
1670
-- blogpost](https://www.pcg-random.org/posts/bounded-rands.html) and
1671
-- more directly [O\'Neill's github
1672
-- repo](https://github.com/imneme/bounded-rands/blob/3d71f53c975b1e5b29f2f3b05a74e26dab9c3d84/bounded32.cpp#L234).
1673
-- N.B. The range is [0,r) **not** [0,r].
1674
unbiasedWordMult32Exclusive :: forall g m . StatefulGen g m => Word32 -> g -> m Word32
1675
unbiasedWordMult32Exclusive r g = go
2✔
1676
  where
1677
    t :: Word32
1678
    t = (-r) `mod` r -- Calculates 2^32 `mod` r!!!
2✔
1679
    go :: StatefulGen g m => m Word32
1680
    go = do
2✔
1681
      x <- uniformWord32 g
2✔
1682
      let m :: Word64
1683
          m = fromIntegral x * fromIntegral r
2✔
1684
          l :: Word32
1685
          l = fromIntegral m
2✔
1686
      if l >= t then return (fromIntegral $ m `shiftR` 32) else go
2✔
1687
{-# INLINE unbiasedWordMult32Exclusive #-}
1688

1689
-- | This only works for unsigned integrals
1690
unsignedBitmaskWithRejectionRM ::
1691
     forall a g m . (FiniteBits a, Num a, Ord a, Uniform a, StatefulGen g m)
1692
  => (a, a)
1693
  -> g
1694
  -> m a
1695
unsignedBitmaskWithRejectionRM (bottom, top) gen
2✔
1696
  | bottom == top = pure top
2✔
1697
  | otherwise = (b +) <$> unsignedBitmaskWithRejectionM uniformM r gen
1✔
1698
  where
1699
    (b, r) = if bottom > top then (top, bottom - top) else (bottom, top - bottom)
2✔
1700
{-# INLINE unsignedBitmaskWithRejectionRM #-}
1701

1702
-- | This works for signed integrals by explicit conversion to unsigned and abusing
1703
-- overflow. It uses `unsignedBitmaskWithRejectionM`, therefore it requires functions that
1704
-- take the value to unsigned and back.
1705
signedBitmaskWithRejectionRM ::
1706
     forall a b g m. (Num a, Num b, Ord b, Ord a, FiniteBits a, StatefulGen g m, Uniform a)
1707
  => (b -> a) -- ^ Convert signed to unsigned. @a@ and @b@ must be of the same size.
1708
  -> (a -> b) -- ^ Convert unsigned to signed. @a@ and @b@ must be of the same size.
1709
  -> (b, b) -- ^ Range.
1710
  -> g -- ^ Generator.
1711
  -> m b
1712
signedBitmaskWithRejectionRM toUnsigned fromUnsigned (bottom, top) gen
2✔
1713
  | bottom == top = pure top
2✔
1714
  | otherwise =
×
1715
    (b +) . fromUnsigned <$> unsignedBitmaskWithRejectionM uniformM r gen
1✔
1716
    -- This works in all cases, see Appendix 1 at the end of the file.
1717
  where
1718
    (b, r) =
1719
      if bottom > top
2✔
1720
        then (top, toUnsigned bottom - toUnsigned top)
2✔
1721
        else (bottom, toUnsigned top - toUnsigned bottom)
2✔
1722
{-# INLINE signedBitmaskWithRejectionRM #-}
1723

1724

1725
-- | Detailed explanation about the algorithm employed here can be found in this post:
1726
-- http://web.archive.org/web/20200520071940/https://www.pcg-random.org/posts/bounded-rands.html
1727
unsignedBitmaskWithRejectionM ::
1728
  forall a g m. (Ord a, FiniteBits a, Num a, StatefulGen g m) => (g -> m a) -> a -> g -> m a
1729
unsignedBitmaskWithRejectionM genUniformM range gen = go
2✔
1730
  where
1731
    mask :: a
1732
    mask = complement zeroBits `shiftR` countLeadingZeros (range .|. 1)
2✔
1733
    go = do
2✔
1734
      x <- genUniformM gen
1✔
1735
      let x' = x .&. mask
2✔
1736
      if x' > range
2✔
1737
        then go
2✔
1738
        else pure x'
2✔
1739
{-# INLINE unsignedBitmaskWithRejectionM #-}
1740

1741
-------------------------------------------------------------------------------
1742
-- 'Uniform' instances for tuples
1743
-------------------------------------------------------------------------------
1744

1745
instance (Uniform a, Uniform b) => Uniform (a, b) where
1746
  uniformM g = (,) <$> uniformM g <*> uniformM g
1✔
1747
  {-# INLINE uniformM #-}
1748

1749
instance (Uniform a, Uniform b, Uniform c) => Uniform (a, b, c) where
1750
  uniformM g = (,,) <$> uniformM g <*> uniformM g <*> uniformM g
1✔
1751
  {-# INLINE uniformM #-}
1752

1753
instance (Uniform a, Uniform b, Uniform c, Uniform d) => Uniform (a, b, c, d) where
1754
  uniformM g = (,,,) <$> uniformM g <*> uniformM g <*> uniformM g <*> uniformM g
1✔
1755
  {-# INLINE uniformM #-}
1756

1757
instance (Uniform a, Uniform b, Uniform c, Uniform d, Uniform e) => Uniform (a, b, c, d, e) where
1758
  uniformM g = (,,,,) <$> uniformM g <*> uniformM g <*> uniformM g <*> uniformM g <*> uniformM g
1✔
1759
  {-# INLINE uniformM #-}
1760

1761
instance (Uniform a, Uniform b, Uniform c, Uniform d, Uniform e, Uniform f) =>
1762
  Uniform (a, b, c, d, e, f) where
1763
  uniformM g = (,,,,,)
2✔
1764
               <$> uniformM g
1✔
1765
               <*> uniformM g
1✔
1766
               <*> uniformM g
1✔
1767
               <*> uniformM g
1✔
1768
               <*> uniformM g
1✔
1769
               <*> uniformM g
1✔
1770
  {-# INLINE uniformM #-}
1771

1772
instance (Uniform a, Uniform b, Uniform c, Uniform d, Uniform e, Uniform f, Uniform g) =>
1773
  Uniform (a, b, c, d, e, f, g) where
1774
  uniformM g = (,,,,,,)
2✔
1775
               <$> uniformM g
1✔
1776
               <*> uniformM g
1✔
1777
               <*> uniformM g
1✔
1778
               <*> uniformM g
1✔
1779
               <*> uniformM g
1✔
1780
               <*> uniformM g
1✔
1781
               <*> uniformM g
1✔
1782
  {-# INLINE uniformM #-}
1783

1784
instance (UniformRange a, UniformRange b) => UniformRange (a, b)
1785
instance (UniformRange a, UniformRange b, UniformRange c) => UniformRange (a, b, c)
1786
instance (UniformRange a, UniformRange b, UniformRange c, UniformRange d) => UniformRange (a, b, c, d)
1787
instance (UniformRange a, UniformRange b, UniformRange c, UniformRange d, UniformRange e) => UniformRange (a, b, c, d, e)
1788
instance (UniformRange a, UniformRange b, UniformRange c, UniformRange d, UniformRange e, UniformRange f) => UniformRange (a, b, c, d, e, f)
1789
instance (UniformRange a, UniformRange b, UniformRange c, UniformRange d, UniformRange e, UniformRange f, UniformRange g) => UniformRange (a, b, c, d, e, f, g)
1790

1791
-- Appendix 1.
1792
--
1793
-- @top@ and @bottom@ are signed integers of bit width @n@. @toUnsigned@
1794
-- converts a signed integer to an unsigned number of the same bit width @n@.
1795
--
1796
--     range = toUnsigned top - toUnsigned bottom
1797
--
1798
-- This works out correctly thanks to modular arithmetic. Conceptually,
1799
--
1800
--     toUnsigned x | x >= 0 = x
1801
--     toUnsigned x | x <  0 = 2^n + x
1802
--
1803
-- The following combinations are possible:
1804
--
1805
-- 1. @bottom >= 0@ and @top >= 0@
1806
-- 2. @bottom < 0@ and @top >= 0@
1807
-- 3. @bottom < 0@ and @top < 0@
1808
--
1809
-- Note that @bottom >= 0@ and @top < 0@ is impossible because of the
1810
-- invariant @bottom < top@.
1811
--
1812
-- For any signed integer @i@ of width @n@, we have:
1813
--
1814
--     -2^(n-1) <= i <= 2^(n-1) - 1
1815
--
1816
-- Considering each combination in turn, we have
1817
--
1818
-- 1. @bottom >= 0@ and @top >= 0@
1819
--
1820
--     range = (toUnsigned top - toUnsigned bottom) `mod` 2^n
1821
--                 --^ top    >= 0, so toUnsigned top    == top
1822
--                 --^ bottom >= 0, so toUnsigned bottom == bottom
1823
--           = (top - bottom) `mod` 2^n
1824
--                 --^ top <= 2^(n-1) - 1 and bottom >= 0
1825
--                 --^ top - bottom <= 2^(n-1) - 1
1826
--                 --^ 0 < top - bottom <= 2^(n-1) - 1
1827
--           = top - bottom
1828
--
1829
-- 2. @bottom < 0@ and @top >= 0@
1830
--
1831
--     range = (toUnsigned top - toUnsigned bottom) `mod` 2^n
1832
--                 --^ top    >= 0, so toUnsigned top    == top
1833
--                 --^ bottom <  0, so toUnsigned bottom == 2^n + bottom
1834
--           = (top - (2^n + bottom)) `mod` 2^n
1835
--                 --^ summand -2^n cancels out in calculation modulo 2^n
1836
--           = (top - bottom) `mod` 2^n
1837
--                 --^ top <= 2^(n-1) - 1 and bottom >= -2^(n-1)
1838
--                 --^ top - bottom <= (2^(n-1) - 1) - (-2^(n-1)) = 2^n - 1
1839
--                 --^ 0 < top - bottom <= 2^n - 1
1840
--           = top - bottom
1841
--
1842
-- 3. @bottom < 0@ and @top < 0@
1843
--
1844
--     range = (toUnsigned top - toUnsigned bottom) `mod` 2^n
1845
--                 --^ top    < 0, so toUnsigned top    == 2^n + top
1846
--                 --^ bottom < 0, so toUnsigned bottom == 2^n + bottom
1847
--           = ((2^n + top) - (2^n + bottom)) `mod` 2^n
1848
--                 --^ summand 2^n cancels out in calculation modulo 2^n
1849
--           = (top - bottom) `mod` 2^n
1850
--                 --^ top <= -1
1851
--                 --^ bottom >= -2^(n-1)
1852
--                 --^ top - bottom <= -1 - (-2^(n-1)) = 2^(n-1) - 1
1853
--                 --^ 0 < top - bottom <= 2^(n-1) - 1
1854
--           = top - bottom
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc