{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} module Synthesizer.LLVM.Filter.Chebyshev ( parameterA, parameterB, Cascade.ParameterValue, Cascade.causal, Cascade.causalPacked, Cascade.causalP, Cascade.causalPackedP, Cascade.fixSize, ) where import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2 import qualified Synthesizer.Plain.Filter.Recursive.Chebyshev as Chebyshev import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core import Synthesizer.Plain.Filter.Recursive (Passband, ) import qualified Synthesizer.LLVM.Simple.Value as Value import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Control as U import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Core as LLVM import LLVM.Core (Value, valueOf, IsSized, SizeOf, IsFloating, CodeGenFunction, ) import Data.Word (Word32, ) import qualified Type.Data.Num.Decimal as TypeNum import Type.Data.Num.Decimal.Number ((:*:), ) import Type.Base.Proxy (Proxy, ) import qualified Synthesizer.LLVM.Complex as ComplexL import qualified Number.Complex as Complex import qualified Algebra.Transcendental as Trans import NumericPrelude.Numeric import NumericPrelude.Base {- | 'n' must be at least one in order to allow amplification by the first partial filter. -} parameterA, parameterB :: (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a, TypeNum.Positive n, TypeNum.Natural n, TypeNum.Positive (n :*: SizeOf a), IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize, (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.Positive paramSize) => Proxy n -> Passband -> Value a -> Value a -> CodeGenFunction r (Cascade.ParameterValue n a) parameterA n kind ratio freq = do pv <- parameter Chebyshev.partialParameterA n kind ratio freq -- adjust amplification of the first filter filt0 <- Filt2.decomposeParameter =<< LLVM.extractvalue pv (0::Word32) fmap Cascade.ParameterValue $ flip (LLVM.insertvalue pv) (0::Word32) =<< Filt2.composeParameter =<< Value.flatten (Filt2Core.amplify (Value.constantValue ratio) (Value.unfold filt0)) parameterB n kind ratio freq = fmap Cascade.ParameterValue $ parameter Chebyshev.partialParameterB n kind ratio freq parameter :: (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a, Value.T (Value a) ~ av, TypeNum.Positive n, TypeNum.Natural n, TypeNum.Positive (n :*: SizeOf a), IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize, (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.Positive paramSize) => (Passband -> Int -> av -> Complex.T av -> av -> Filt2Core.Parameter av) -> Proxy n -> Passband -> Value a -> Value a -> CodeGenFunction r (Value (Cascade.ParameterStruct n a)) parameter partialParameter n kind ratio freq = do let order = 2 * TypeNum.integralFromProxy n let sines = Cascade.constArray n $ map ComplexL.constOf $ Chebyshev.makeCirclePoints order psine <- LLVM.malloc LLVM.store sines psine s <- LLVM.getElementPtr0 psine (valueOf (0::Word32), ()) ps <- LLVM.malloc p <- LLVM.getElementPtr0 ps (valueOf (0::Word32), ()) let len = valueOf $ (TypeNum.integralFromProxy n :: Word32) _ <- U.arrayLoop len p s $ \ptri si -> do c <- LLVM.load si flip LLVM.store ptri =<< Filt2.composeParameter =<< Value.flatten (partialParameter kind order (Value.constantValue ratio) (ComplexL.unfold c) (Value.constantValue freq)) A.advanceArrayElementPtr si pv <- LLVM.load ps LLVM.free psine LLVM.free ps return pv