{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{- |
This is like "Synthesizer.LLVM.CausalParameterized.Controlled"
but for vectorised signals.
-}
module Synthesizer.LLVM.CausalParameterized.ControlledPacked (
   CtrlS.process,
   processCtrlRate,
   ) where

import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlS
import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
import qualified Synthesizer.LLVM.Frame.SerialVector as Serial

import qualified LLVM.DSL.Parameter as Param

import qualified LLVM.Extra.Tuple as Tuple
import qualified LLVM.Extra.Marshal as Marshal
import qualified LLVM.Extra.Memory as Memory
import qualified LLVM.Extra.ScalarOrVector as SoV

import qualified LLVM.Core as LLVM
import LLVM.Core (Value, IsFloating)

import qualified Algebra.Field as Field

import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()


processCtrlRate ::
   (CtrlS.C parameter av bv,
    Serial.Read av, n ~ Serial.Size av,
    Serial.C    bv, n ~ Serial.Size bv,
    Memory.C parameter,
    Marshal.C r, Field.C r, IsFloating r, SoV.IntegerConstant r,
    Tuple.ValueOf r ~ Value r, LLVM.CmpRet r, LLVM.IsPrimitive r) =>
   Param.T p r ->
   (Param.T p r -> SigP.T p parameter) ->
   CausalP.T p av bv
processCtrlRate reduct ctrlGen = Serial.withSize $ \n ->
   CausalP.applyFst CtrlS.process
      (SigP.interpolateConstant
         (fmap (/ fromIntegral n) reduct)
         (ctrlGen reduct))