module RealDice.RNG
( RDGen,
randomIntR,
randomFloat,
randomDouble,
mkRDGen,
mkRDGenCustom,
)
where
import RealDice.Generate.BalancedTables (rdIntsPrime)
import RealDice.Manipulate.GetValueFromRNGTable (getIntByIndex)
import RealDice.Manipulate.RandomizeList (randomizeList)
data RDGen where
RDGen :: {RDGen -> Int
index :: Int, RDGen -> [Int]
rngTable :: [Int]} -> RDGen
mkRDGen :: Int -> RDGen
mkRDGen :: Int -> RDGen
mkRDGen Int
i = Int -> [Int] -> RDGen
mkRDGenCustom Int
i [Int]
rdIntsPrime
mkRDGenCustom :: Int -> [Int] -> RDGen
mkRDGenCustom :: Int -> [Int] -> RDGen
mkRDGenCustom Int
i [] = RDGen {index :: Int
index = Int
i, rngTable :: [Int]
rngTable = [Int]
rdIntsPrime}
mkRDGenCustom Int
i [Int]
table = RDGen {index :: Int
index = Int
i, rngTable :: [Int]
rngTable = [Int]
table}
randomIntR :: (Int, Int) -> RDGen -> (Int, RDGen)
randomIntR :: (Int, Int) -> RDGen -> (Int, RDGen)
randomIntR (Int
minResult, Int
maxResult) RDGen
rng
| Int
minResult Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxResult = (Int
0, RDGen
rng)
| Bool
otherwise =
( Int -> [Int] -> Int
getIntByIndex
(Int -> [Int] -> Int
getIntByIndex (RDGen -> Int
index RDGen
rng) (RDGen -> [Int]
rngTable RDGen
rng))
([Int] -> [Int]
randomizeList [Int
minResult .. Int
maxResult]),
RDGen {index :: Int
index = RDGen -> Int
index RDGen
rng Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, rngTable :: [Int]
rngTable = RDGen -> [Int]
rngTable RDGen
rng}
)
randomFloat :: Int -> RDGen -> (Float, RDGen)
randomFloat :: Int -> RDGen -> (Float, RDGen)
randomFloat Int
decimalPrecision RDGen
rng
| Int
decimalPrecision Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = (Float
0, RDGen
rng)
| Bool
otherwise = (Int, Float) -> RDGen -> (Float, RDGen)
randomFloatSinglePass (Int
decimalPrecision, Float
0) RDGen
rng
randomFloatSinglePass :: (Int, Float) -> RDGen -> (Float, RDGen)
randomFloatSinglePass :: (Int, Float) -> RDGen -> (Float, RDGen)
randomFloatSinglePass (Int
0, Float
currentFloat) RDGen
rng = (Float
currentFloat, RDGen
rng)
randomFloatSinglePass (Int
decimalPlace, Float
currentFloat) RDGen
rng = do
let randomDigit :: Int
randomDigit = Int -> [Int] -> Int
getIntByIndex (Int -> [Int] -> Int
getIntByIndex (RDGen -> Int
index RDGen
rng) (RDGen -> [Int]
rngTable RDGen
rng)) ([Int] -> [Int]
randomizeList [Int
0 .. Int
9])
(Int, Float) -> RDGen -> (Float, RDGen)
randomFloatSinglePass
( Int
decimalPlace Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1,
Float
currentFloat Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
randomDigit Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
10 Float -> Int -> Float
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
decimalPlace))
)
(RDGen {index :: Int
index = RDGen -> Int
index RDGen
rng Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, rngTable :: [Int]
rngTable = RDGen -> [Int]
rngTable RDGen
rng})
randomDouble :: Int -> RDGen -> (Double, RDGen)
randomDouble :: Int -> RDGen -> (Double, RDGen)
randomDouble Int
decimalPrecision RDGen
rng
| Int
decimalPrecision Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = (Double
0, RDGen
rng)
| Bool
otherwise = (Int, Double) -> RDGen -> (Double, RDGen)
randomDoubleSinglePass (Int
decimalPrecision, Double
0) RDGen
rng
randomDoubleSinglePass :: (Int, Double) -> RDGen -> (Double, RDGen)
randomDoubleSinglePass :: (Int, Double) -> RDGen -> (Double, RDGen)
randomDoubleSinglePass (Int
0, Double
currentDouble) RDGen
rng = (Double
currentDouble, RDGen
rng)
randomDoubleSinglePass (Int
decimalPlace, Double
currentDouble) RDGen
rng = do
let randomDigit :: Int
randomDigit = Int -> [Int] -> Int
getIntByIndex (Int -> [Int] -> Int
getIntByIndex (RDGen -> Int
index RDGen
rng) (RDGen -> [Int]
rngTable RDGen
rng)) ([Int] -> [Int]
randomizeList [Int
0 .. Int
9])
(Int, Double) -> RDGen -> (Double, RDGen)
randomDoubleSinglePass
( Int
decimalPlace Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1,
Double
currentDouble Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
randomDigit Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
10 Double -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
decimalPlace))
)
(RDGen {index :: Int
index = RDGen -> Int
index RDGen
rng Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, rngTable :: [Int]
rngTable = RDGen -> [Int]
rngTable RDGen
rng})