module Synthesizer.Generic.Cut where
import qualified Synthesizer.Plain.Signal as Sig
import qualified Synthesizer.State.Signal as SigS
import qualified Synthesizer.FusionList.Signal as SigFL
import qualified Data.StorableVector.Lazy as Vector
import qualified Numeric.NonNegative.Class as NonNeg
import qualified Numeric.NonNegative.Chunky as Chunky
import Foreign.Storable (Storable)
import Data.Function (fix, )
import qualified Data.List as List
import Data.Tuple.HT (mapPair, )
import qualified Data.Monoid as Monoid
import Data.Monoid (Monoid, )
import qualified Prelude as P
import NumericPrelude
import Prelude
(Bool, Int, String, (++), error,
pred, (<=), (>=), (<),
(.), not, (||), (&&), )
class Read sig where
null :: sig -> Bool
length :: sig -> Int
class (Read sig, Monoid sig) => Transform sig where
take :: Int -> sig -> sig
drop :: Int -> sig -> sig
dropMarginRem :: Int -> Int -> sig -> (Int, sig)
splitAt :: Int -> sig -> (sig, sig)
reverse :: sig -> sig
instance Storable y => Read (Vector.Vector y) where
null = Vector.null
length = Vector.length
instance Storable y => Transform (Vector.Vector y) where
take = Vector.take
drop = Vector.drop
splitAt = Vector.splitAt
dropMarginRem = Vector.dropMarginRem
reverse = Vector.reverse
instance Read ([] y) where
null = List.null
length = List.length
instance Transform ([] y) where
take = List.take
drop = List.drop
dropMarginRem = Sig.dropMarginRem
splitAt = List.splitAt
reverse = List.reverse
instance Read (SigFL.T y) where
null = SigFL.null
length = SigFL.length
instance Transform (SigFL.T y) where
take = SigFL.take
drop = SigFL.drop
dropMarginRem = SigFL.dropMarginRem
splitAt = SigFL.splitAt
reverse = SigFL.reverse
instance Read (SigS.T y) where
null = SigS.null
length = SigS.length
instance Transform (SigS.T y) where
take = SigS.take
drop = SigS.drop
dropMarginRem = SigS.dropMarginRem
splitAt n =
mapPair (SigS.fromList, SigS.fromList) .
List.splitAt n . SigS.toList
reverse = SigS.reverse
instance (P.Integral a) => Read (Chunky.T a) where
null = List.null . Chunky.toChunks
length = sum . List.map (P.fromIntegral . P.toInteger) . Chunky.toChunks
intToChunky :: (NonNeg.C a) => String -> Int -> Chunky.T a
intToChunky name =
Chunky.fromNumber .
P.fromIntegral .
(\x ->
if x<0
then error ("Generic.Cut.NonNeg.Chunky."++name++": negative argument")
else x)
instance (P.Integral a, NonNeg.C a) => Transform (Chunky.T a) where
take n = P.min (intToChunky "take" n)
drop n x = x NonNeg.-| intToChunky "drop" n
dropMarginRem n m x =
let (z,d,b) =
Chunky.minMaxDiff
(intToChunky "dropMargin/n" n)
(x NonNeg.-| intToChunky "dropMargin/m" m)
in (if b then 0 else P.fromIntegral (Chunky.toNumber d),
x NonNeg.-| z)
splitAt n x =
let (z,d,b) = Chunky.minMaxDiff (intToChunky "splitAt" n) x
in (z, if b then d else Chunky.zero)
reverse = Chunky.fromChunks . P.reverse . Chunky.toChunks
empty :: (Monoid sig) => sig
empty = Monoid.mempty
cycle :: (Monoid sig) => sig -> sig
cycle x = fix (append x)
append :: (Monoid sig) => sig -> sig -> sig
append = Monoid.mappend
concat :: (Monoid sig) => [sig] -> sig
concat = Monoid.mconcat
lengthAtLeast :: (Transform sig) =>
Int -> sig -> Bool
lengthAtLeast n xs =
n<=0 || not (null (drop (pred n) xs))
lengthAtMost :: (Transform sig) =>
Int -> sig -> Bool
lengthAtMost n xs =
n>=0 && null (drop n xs)
sliceVertical :: (Transform sig) =>
Int -> sig -> SigS.T sig
sliceVertical n =
SigS.map (take n) .
SigS.takeWhile (not . null) .
SigS.iterate (drop n)