packages feed

dynobud-1.9.0.0: src/Dyno/View/MapFun.hs

{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Dyno.View.MapFun
       ( mapFun
       , mapFun'
       ) where

import qualified Data.Foldable as F
import qualified Data.Map as M
import Data.Proxy
import Data.Sequence ( Seq )
import qualified Data.Sequence as S
import qualified Data.Traversable as T
import qualified Data.Vector as V

import qualified Casadi.Function as C
import Casadi.Option

import qualified Casadi.Core.Classes.Function as F
import qualified Casadi.Core.Classes.Map as C

import Dyno.TypeVecs ( Dim )
import qualified Dyno.TypeVecs as TV
import Dyno.View.Fun
import Dyno.View.HList
import Dyno.View.JVec ( JVec )
import Dyno.View.M ( M )
import Dyno.View.Scheme ( Scheme )
import Dyno.View.View ( View )

class ParScheme f where
  type Par f (n :: k) :: * -> *

-- normal
instance (View f, View g) => ParScheme (M f g) where
  type Par (M f g) n = M f (JVec n g)

-- multiple inputs/outputs
instance (ParScheme f, ParScheme g) => ParScheme (f :*: g) where
  type Par (f :*: g) n = (Par f n) :*: (Par g n)

-- | symbolic fmap
mapFun :: forall fun f g n
          . ( FunClass fun
            , Scheme (Par f n), Scheme (Par g n)
            , Dim n )
          => Proxy n
          -> String
          -> fun f g
          -> M.Map String Opt
          -> IO (Fun (Par f n) (Par g n))
mapFun _ name f' opts0 = do
  opts <- T.mapM mkGeneric opts0 :: IO (M.Map String GenericType)
  let Fun f = toFun f'
      n = TV.reflectDim (Proxy :: Proxy n)
  fm <- F.function_map__1 f name n opts :: IO C.Function
  checkFunDimensionsWith "mapFun'" (Fun fm)
-- {-# NOINLINE mapFun #-}


class ParScheme' f0 f1 where
  repeated :: Proxy f0 -> Proxy f1 -> Seq Bool

-- normal
instance (View f, View g) => ParScheme' (M f g) (M f (JVec n g)) where
  repeated _ _ = S.singleton True

-- non-repeated
instance View f => ParScheme' (M f g) (M f g) where
  repeated _ _ = S.singleton False

-- multiple inputs/output
instance (ParScheme' f0 f1, ParScheme' g0 g1) => ParScheme' (f0 :*: g0) (f1 :*: g1) where
  repeated pfg0 pfg1 = repeated pf0 pf1 S.>< repeated pg0 pg1
    where
      splitProxy :: Proxy (f :*: g) -> (Proxy f, Proxy g)
      splitProxy _ = (Proxy, Proxy)

      (pf0, pg0) = splitProxy pfg0
      (pf1, pg1) = splitProxy pfg1

-- | symbolic fmap which can do non-repeated inputs/outputs
mapFun' :: forall fun i0 i1 o0 o1 n
          . ( FunClass fun
            , ParScheme' i0 i1, ParScheme' o0 o1
            , Scheme i0, Scheme o0
            , Scheme i1, Scheme o1
            , Dim n
            )
          => Proxy n
          -> String
          -> fun i0 o0
          -> M.Map String Opt
          -> IO (Fun i1 o1)
mapFun' _ name f0 opts0 = do
--  let fds = checkFunDimensions f0
--  putStrLn "mapFun'' input dimensions:"
--  case fds of
--   Left msg -> putStrLn msg
--   Right msg -> putStrLn msg
  _ <- checkFunDimensionsWith "mapFun'' input fun" (toFun f0)
  opts <- T.mapM mkGeneric opts0 :: IO (M.Map String GenericType)
  let n = TV.reflectDim (Proxy :: Proxy n)
      repeatedIn =
        V.fromList $ F.toList $ repeated (Proxy :: Proxy i0) (Proxy :: Proxy i1)
      repeatedOut =
        V.fromList $ F.toList $ repeated (Proxy :: Proxy o0) (Proxy :: Proxy o1)
--  putStrLn $ "repeated in: " ++ show repeatedIn
--  putStrLn $ "repeated out: " ++ show repeatedOut

  fm <- C.map__1 name (unFun (toFun f0)) n repeatedIn repeatedOut opts :: IO C.Map
  checkFunDimensionsWith "mapFun''" (Fun (F.castFunction fm))
-- {-# NOINLINE mapFun' #-}