{-# OPTIONS --without-K --safe --sized-types #-}
module Data.Nat.PseudoRandom.LCG where
open import Codata.Stream using (Stream; unfold)
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _^_; _≟_)
open import Data.Nat.DivMod using (_%_)
open import Data.Product using (<_,_>)
open import Data.List.Base using (List; []; _∷_)
open import Function.Base using (id)
open import Relation.Nullary.Decidable using (False)
record Generator : Set where
field multiplier : ℕ
increment : ℕ
modulus : ℕ
{modulus≢0} : False (modulus ≟ 0)
step : Generator → ℕ → ℕ
step gen x =
let open Generator gen in
((multiplier * x + increment) % modulus) {modulus≢0}
stream : Generator → ℕ → Stream ℕ _
stream gen = unfold < step gen , id >
list : ℕ → Generator → ℕ → List ℕ
list zero gen x = []
list (suc k) gen x = x ∷ list k gen (step gen x)
glibc : Generator
glibc = record
{ multiplier = 1103515245
; increment = 12345
; modulus = 2 ^ 31
}
random0 : Generator
random0 = record
{ multiplier = 8121
; increment = 28411
; modulus = 134456
}