module Internal.Random (
    Seed,
    RandDist(..),
    randomVector,
    gaussianSample,
    uniformSample,
    rand, randn
) where
import Internal.Vectorized
import Internal.Vector
import Internal.Matrix
import Internal.Numeric
import Internal.Algorithms
import System.Random(randomIO)
gaussianSample :: Seed
               -> Int 
               -> Vector Double 
               -> Herm Double   
               -> Matrix Double 
gaussianSample seed n med cov = m where
    c = dim med
    meds = konst' 1 n `outer` med
    rs = reshape c $ randomVector seed Gaussian (c * n)
    m = rs `mXm` chol cov `add` meds
uniformSample :: Seed
               -> Int 
               -> [(Double,Double)] 
               -> Matrix Double 
uniformSample seed n rgs = m where
    (as,bs) = unzip rgs
    a = fromList as
    cs = zipWith subtract as bs
    d = dim a
    dat = toRows $ reshape n $ randomVector seed Uniform (n*d)
    am = konst' 1 n `outer` a
    m = fromColumns (zipWith scale cs dat) `add` am
randm :: RandDist
     -> Int 
     -> Int 
     -> IO (Matrix Double)
randm d r c = do
    seed <- randomIO
    return (reshape c $ randomVector seed d (r*c))
rand :: Int -> Int -> IO (Matrix Double)
rand = randm Uniform
randn :: Int -> Int -> IO (Matrix Double)
randn = randm Gaussian