packages feed

synthesizer-core-0.9: src/Synthesizer/ChunkySize.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Synthesizer.ChunkySize where

import qualified Synthesizer.Generic.Cut as Cut

import qualified Number.NonNegativeChunky as Chunky
import qualified Numeric.NonNegative.Chunky as Chunky98

import qualified Algebra.ToInteger    as ToInteger
import qualified Algebra.ToRational   as ToRational
import qualified Algebra.Absolute     as Absolute
import qualified Algebra.RealIntegral as RealIntegral
import qualified Algebra.IntegralDomain as Integral
import qualified Algebra.NonNegative  as NonNeg
import qualified Algebra.ZeroTestable as ZeroTestable
import qualified Algebra.Ring     as Ring
import qualified Algebra.Additive as Additive
import qualified Algebra.Monoid   as Monoid
import Algebra.Ring ((*), )
import Algebra.Additive ((+), (-), )

import qualified Data.StorableVector.Lazy as SigSt
import qualified Data.StorableVector.Lazy.Pattern as SigStV

import qualified Data.List as List
import Data.Monoid (Monoid, mappend, mempty, )
import Data.Semigroup (Semigroup, (<>), )

import qualified Test.QuickCheck as QC

import qualified Prelude as P
import Prelude (Eq, Ord, Show, Int, fmap, max, min, id, (.), ($), (==), )


{- |
This type is used for specification of the maximum size of strict packets.
Packets can be smaller, can have different sizes in one signal.
In some kinds of streams, like lists and stateful generators,
the packet size is always 1.
The packet size is not just a burden caused by efficiency,
but we need control over packet size in applications with feedback.

ToDo: Make the element type of the corresponding signal a type parameter.
This helps to distinguish chunk sizes of scalar and vectorised signals.
-}
newtype LazySize = LazySize Int
   deriving (Eq, Ord, Show,
             Additive.C, Ring.C, ZeroTestable.C,
             ToInteger.C, ToRational.C, Absolute.C,
             RealIntegral.C, Integral.C)

instance Semigroup LazySize where
   LazySize a <> LazySize b = LazySize (a + b)

instance Monoid LazySize where
   mempty = LazySize 0
   mappend = (<>)

instance Monoid.C LazySize where
   idt = LazySize 0
   LazySize a <*> LazySize b = LazySize (a + b)

instance NonNeg.C LazySize where
   split = NonNeg.splitDefault (\(LazySize n) -> n) LazySize

instance QC.Arbitrary LazySize where
   arbitrary =
      case SigSt.defaultChunkSize of
         SigSt.ChunkSize n -> fmap LazySize (QC.choose (1, 2 * n))

instance Cut.Consume LazySize where
   null (LazySize n) = n==0
   length (LazySize n) = n

instance Cut.Transform LazySize where
   {-# INLINE take #-}
   take m (LazySize n) = LazySize $ min (max 0 m) n
   {-# INLINE drop #-}
   drop m (LazySize n) = LazySize $ max 0 $ n - max 0 m
   {-# INLINE splitAt #-}
   splitAt m x =
      let y = Cut.take m x
      in  (y, x-y)
   {-# INLINE dropMarginRem #-}
   dropMarginRem n m x@(LazySize xs) =
      let d = min m $ max 0 $ xs - n
      in  (m-d, Cut.drop d x)
   {-# INLINE reverse #-}
   reverse = id


type T = Chunky.T LazySize


fromStorableVectorSize ::
   SigStV.LazySize -> T
fromStorableVectorSize =
   Chunky.fromChunks .
   List.map (\(SigSt.ChunkSize size) -> (LazySize size)) .
   Chunky98.toChunks

toStorableVectorSize ::
   T -> SigStV.LazySize
toStorableVectorSize =
   Chunky98.fromChunks .
   List.map (\(LazySize size) -> (SigSt.ChunkSize size)) .
   Chunky.toChunks

toNullList :: T -> [()]
toNullList =
   List.concatMap (\(LazySize n) -> List.replicate n ()) .
   Chunky.toChunks