{-# LANGUAGE ScopedTypeVariables #-}
module Data.Sized.Sampled where
import Data.Ratio
import Data.Sized.Signed as S
import Data.Sized.Matrix as M
import Data.Sized.Ix
data Sampled m n = Sampled (Signed n) Rational
toMatrix :: (Size n) => Sampled m n -> Matrix n Bool
toMatrix (Sampled sig _) = S.toMatrix sig
fromMatrix :: forall n m . (Size n, Size m) => Matrix n Bool -> Sampled m n
fromMatrix m = mkSampled (fromIntegral scale * fromIntegral val / fromIntegral precision)
where val :: Signed n
val = S.fromMatrix m
scale :: Integer
scale = fromIntegral (size (undefined :: m))
precision :: Integer
precision = 2 ^ (fromIntegral (size (undefined :: n) - 1) :: Integer)
mkSampled :: forall n m . (Size n, Size m) => Rational -> Sampled m n
mkSampled v = Sampled val (fromIntegral scale * fromIntegral val / fromIntegral precision)
where scale :: Integer
scale = fromIntegral (size (undefined :: m))
precision :: Integer
precision = 2 ^ (fromIntegral (size (undefined :: n) - 1) :: Integer)
val0 :: Rational
val0 = v / fromIntegral scale
val1 :: Integer
val1 = round (val0 * fromIntegral precision)
val = if val1 >= precision then maxBound
else if val1 <= -precision then minBound
else fromInteger val1
instance (Size ix) => Eq (Sampled m ix) where
(Sampled a _) == (Sampled b _) = a == b
instance (Size ix) => Ord (Sampled m ix) where
(Sampled a _) `compare` (Sampled b _) = a `compare` b
instance (Size ix) => Show (Sampled m ix) where
show (Sampled _ s) = show (fromRational s :: Double)
instance (Size ix, Size m) => Read (Sampled m ix) where
readsPrec i str = [ (mkSampled a,r) | (a,r) <- readsPrec i str ]
instance (Size ix, Size m) => Num (Sampled m ix) where
(Sampled _ a) + (Sampled _ b) = mkSampled $ a + b
(Sampled _ a) - (Sampled _ b) = mkSampled $ a - b
(Sampled _ a) * (Sampled _ b) = mkSampled $ a * b
abs (Sampled _ n) = mkSampled $ abs n
signum (Sampled _ n) = mkSampled $ signum n
fromInteger n = mkSampled (fromInteger n)
instance (Size ix, Size m) => Real (Sampled m ix) where
toRational (Sampled _ n) = toRational n
instance (Size ix, Size m) => Fractional (Sampled m ix) where
fromRational n = mkSampled n
recip (Sampled _ n) = mkSampled $ recip n
instance (Size ix, Size m) => Enum (Sampled m ix) where
fromEnum (Sampled n _) = fromEnum n
toEnum n = mkSampled (fromIntegral scale * fromIntegral val / fromIntegral precision)
where val :: Signed ix
val = fromIntegral n
scale :: Integer
scale = fromIntegral (size (undefined :: m))
precision :: Integer
precision = 2 ^ (fromIntegral (size (undefined :: ix) - 1) :: Integer)