module Synthesizer.Generic.Cyclic where
import qualified Synthesizer.Generic.Filter.NonRecursive as FiltNRG
import qualified Synthesizer.Generic.Analysis as AnaG
import qualified Synthesizer.Generic.Signal as SigG
import qualified Synthesizer.Generic.Cut as CutG
import qualified Synthesizer.State.Signal as Sig
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()
fromSignal ::
(SigG.Write sig yv, Additive.C yv) =>
SigG.LazySize -> Int -> sig yv -> sig yv
fromSignal chunkSize n =
Sig.foldL SigG.mix (SigG.replicate chunkSize n zero) .
CutG.sliceVertical n
reverse ::
(SigG.Transform sig y) =>
sig y -> sig y
reverse sig =
SigG.switchL sig
(\y ys -> SigG.cons y (SigG.reverse ys)) sig
reperiodize ::
(SigG.Transform sig yv, Additive.C yv) =>
Int -> sig yv -> sig yv
reperiodize n =
Sig.foldL SigG.mix CutG.empty .
CutG.sliceVertical n
convolve ::
(SigG.Transform sig y, Ring.C y) =>
sig y -> sig y -> sig y
convolve x y =
reperiodize (CutG.length x) $
FiltNRG.karatsubaFinite (*) x y
filterNaive ::
(SigG.Transform sig y, Ring.C y) =>
sig y -> sig y -> sig y
filterNaive x y =
SigG.takeStateMatch y $
SigG.toState $
SigG.mapTails
(AnaG.scalarProduct x)
(SigG.append y y)
convolveNaive ::
(SigG.Transform sig y, Ring.C y) =>
sig y -> sig y -> sig y
convolveNaive x y =
SigG.takeStateMatch y $
SigG.toState $
SigG.mapTails
(AnaG.scalarProduct (SigG.reverse x))
(SigG.laxTail $ SigG.append y y)
type Pair y = (y,y)
convolvePair ::
(Ring.C y) =>
Pair y -> Pair y -> Pair y
convolvePair a b =
snd $ sumAndConvolvePair a b
sumAndConvolvePair ::
(Ring.C y) =>
Pair y -> Pair y -> ((y,y), Pair y)
sumAndConvolvePair (a0,a1) (b0,b1) =
let sa01 = a0+a1
sb01 = b0+b1
ab0ab1 = a0*b0+a1*b1
in ((sa01, sb01), (ab0ab1, sa01*sb01ab0ab1))
type Triple y = (y,y,y)
convolveTriple ::
(Ring.C y) =>
Triple y -> Triple y -> Triple y
convolveTriple a b =
snd $ sumAndConvolveTriple a b
sumAndConvolveTriple ::
(Ring.C y) =>
Triple y -> Triple y -> ((y,y), Triple y)
sumAndConvolveTriple (a0,a1,a2) (b0,b1,b2) =
let ab0 = a0*b0
dab12 = a1*b1 a2*b2
sa01 = a0+a1; sb01 = b0+b1; tab01 = sa01*sb01 ab0
sa02 = a0+a2; sb02 = b0+b2; tab02 = sa02*sb02 ab0
sa012 = sa01+a2
sb012 = sb01+b2
d0 = sa012*sb012 tab01 tab02
d1 = tab01 dab12
d2 = tab02 + dab12
in ((sa012, sb012), (d0, d1, d2))
sumAndConvolveTripleAlt ::
(Ring.C y) =>
Triple y -> Triple y -> ((y,y), Triple y)
sumAndConvolveTripleAlt (a0,a1,a2) (b0,b1,b2) =
let ab0 = a0*b0
ab1 = a1*b1
ab2 = a2*b2
sa01 = a0+a1; sb01 = b0+b1
ab01 = sa01*sb01 (ab0+ab1)
sa02 = a0+a2; sb02 = b0+b2
ab02 = sa02*sb02 (ab0+ab2)
sa12 = a1+a2; sb12 = b1+b2
ab12 = sa12*sb12 (ab1+ab2)
in ((sa01+a2, sb01+b2), (ab0+ab12, ab2+ab01, ab1+ab02))
type Quadruple y = (y,y,y,y)
convolveQuadruple ::
(Ring.C y) =>
Quadruple y -> Quadruple y -> Quadruple y
convolveQuadruple a b =
snd $ sumAndConvolveQuadruple a b
sumAndConvolveQuadruple ::
(Ring.C y) =>
Quadruple y -> Quadruple y -> ((y,y), Quadruple y)
sumAndConvolveQuadruple (a0,a1,a2,a3) (b0,b1,b2,b3) =
let ab0 = a0*b0
ab1 = a1*b1
sa01 = a0+a1; sb01 = b0+b1
ab01 = sa01*sb01 (ab0+ab1)
ab2 = a2*b2
ab3 = a3*b3
sa23 = a2+a3; sb23 = b2+b3
ab23 = sa23*sb23 (ab2+ab3)
c0 = ab0 + ab2 (ab1 + ab3)
c1 = ab01 + ab23
ab02 = (a0+a2)*(b0+b2)
ab13 = (a1+a3)*(b1+b3)
sa0123 = sa01+sa23
sb0123 = sb01+sb23
ab0123 = sa0123*sb0123 (ab02+ab13)
d0 = ab13 + c0
d1 = c1
d2 = ab02 c0
d3 = ab0123 c1
in ((sa0123, sb0123), (d0, d1, d2, d3))