{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} module Synthesizer.LLVM.Filter.Chebyshev ( parameterA, parameterB, Cascade.ParameterValue, 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 Types.Data.Bool as TypeBool import qualified Types.Data.Num as TypeNum import Types.Data.Num.Ops ((:*:), ) import qualified Synthesizer.LLVM.Complex as ComplexL import qualified Number.Complex as Complex import qualified Algebra.Transcendental as Trans -- import qualified Algebra.Field as Field -- import qualified Algebra.Module as Module -- import qualified Algebra.Ring as Ring 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.PositiveT n, TypeNum.IsNatural n ~ TypeBool.True, TypeNum.PositiveT (n :*: SizeOf a), IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize, (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.PositiveT paramSize) => 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, TypeNum.PositiveT n, TypeNum.IsNatural n ~ TypeBool.True, TypeNum.PositiveT (n :*: SizeOf a), IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize, (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.PositiveT paramSize) => (Int -> Value.T (Value a) -> Value.T (Value a) -> Complex.T (Value.T (Value a)) -> Filt2Core.Parameter (Value.T (Value a))) -> n -> Passband -> Value a -> Value a -> CodeGenFunction r (Value (Cascade.ParameterStruct n a)) parameter partialParameter n kind ratio freq = do let order = 2 * TypeNum.fromIntegerT n let sines = (flip const :: n -> LLVM.Value (LLVM.Array n a) -> LLVM.Value (LLVM.Array n a)) n $ LLVM.value $ LLVM.constArray $ 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.fromIntegerT n :: Word32) _ <- U.arrayLoop len p s $ \ptri si -> do c <- LLVM.load si flip LLVM.store ptri =<< Filt2.composeParameter =<< Value.flatten (Filt2Core.adjustPassband kind (flip (partialParameter 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