content: {-# language CPP #-}
  {-# language QuasiQuotes #-}
  {-# language TemplateHaskell #-}
  {-# language UndecidableInstances #-}
  
  #ifndef ENABLE_INTERNAL_DOCUMENTATION
  {-# OPTIONS_HADDOCK hide #-}
  #endif
  
  module OpenCV.Internal.Core.Types.Mat.ToFrom
    ( MatShape
    , MatChannels
    , MatDepth
    , ToMat(..)
    , FromMat(..)
    ) where
  
  import           "base" Data.Proxy ( Proxy(..) )
  import           "base" Foreign.Storable ( Storable )
  import           "base" GHC.TypeLits
  import           "base" System.IO.Unsafe ( unsafePerformIO )
  import qualified "inline-c" Language.C.Inline as C
  import qualified "inline-c" Language.C.Inline.Unsafe as CU
  import qualified "inline-c-cpp" Language.C.Inline.Cpp as C
  import           "linear" Linear.Matrix ( M23, M33 )
  import           "linear" Linear.V2 ( V2(..) )
  import           "linear" Linear.V3 ( V3(..) )
  import           "linear" Linear.V4 ( V4 )
  import qualified "repa" Data.Array.Repa as Repa
  import           "this" OpenCV.Core.Types.Matx
  import           "this" OpenCV.Core.Types.Mat.Repa
  import           "this" OpenCV.Core.Types.Vec
  import           "this" OpenCV.Internal.C.Inline ( openCvCtx )
  import           "this" OpenCV.Internal.C.Types
  import           "this" OpenCV.Internal.Core.Types.Mat
  import           "this" OpenCV.Internal.Exception
  import           "this" OpenCV.TypeLevel
  import           "this" OpenCV.Unsafe
  
  
  --------------------------------------------------------------------------------
  
  C.context openCvCtx
  
  C.include "opencv2/core.hpp"
  C.include "haskell_opencv_matx_typedefs.hpp"
  C.using "namespace cv"
  
  --------------------------------------------------------------------------------
  
  type family MatShape    (a :: *) :: DS [DS Nat]
  type family MatChannels (a :: *) :: DS Nat
  type family MatDepth    (a :: *) :: DS *
  
  type instance MatShape    (Mat shape channels depth) = shape
  type instance MatChannels (Mat shape channels depth) = channels
  type instance MatDepth    (Mat shape channels depth) = depth
  
  type instance MatShape    (Matx m n depth) = ShapeT '[m, n]
  type instance MatChannels (Matx m n depth) = 'S 1
  type instance MatDepth    (Matx m n depth) = 'S depth
  
  type instance MatShape    (Vec dim depth) = ShapeT '[dim]
  type instance MatChannels (Vec dim depth) = 'S 1
  type instance MatDepth    (Vec dim depth) = 'S depth
  
  type instance MatShape    (M23 depth) = ShapeT [2, 3]
  type instance MatChannels (M23 depth) = 'S 1
  type instance MatDepth    (M23 depth) = 'S depth
  
  type instance MatShape    (M33 depth) = ShapeT [3, 3]
  type instance MatChannels (M33 depth) = 'S 1
  type instance MatDepth    (M33 depth) = 'S depth
  
  class ToMat a where
      toMat :: a -> Mat (MatShape a) (MatChannels a) (MatDepth a)
  
  class FromMat a where
      fromMat :: Mat (MatShape a) (MatChannels a) (MatDepth a) -> a
  
  instance ToMat   (Mat shape channels depth) where toMat   = id
  instance FromMat (Mat shape channels depth) where fromMat = id
  
  --------------------------------------------------------------------------------
  -- Matx instances
  
  #define MATX_TO_MAT(NAME)                          \
  instance ToMat NAME where {                        \
      toMat matx = unsafePerformIO $ fromPtr $       \
          withPtr matx $ \matxPtr ->                 \
            [CU.exp| Mat * {                         \
              new cv::Mat(*$(NAME * matxPtr), false) \
            }|];                                     \
  };
  
  MATX_TO_MAT(Matx12f)
  MATX_TO_MAT(Matx12d)
  MATX_TO_MAT(Matx13f)
  MATX_TO_MAT(Matx13d)
  MATX_TO_MAT(Matx14f)
  MATX_TO_MAT(Matx14d)
  MATX_TO_MAT(Matx16f)
  MATX_TO_MAT(Matx16d)
  MATX_TO_MAT(Matx21f)
  MATX_TO_MAT(Matx21d)
  MATX_TO_MAT(Matx22f)
  MATX_TO_MAT(Matx22d)
  MATX_TO_MAT(Matx23f)
  MATX_TO_MAT(Matx23d)
  MATX_TO_MAT(Matx31f)
  MATX_TO_MAT(Matx31d)
  MATX_TO_MAT(Matx32f)
  MATX_TO_MAT(Matx32d)
  MATX_TO_MAT(Matx33f)
  MATX_TO_MAT(Matx33d)
  MATX_TO_MAT(Matx34f)
  MATX_TO_MAT(Matx34d)
  MATX_TO_MAT(Matx41f)
  MATX_TO_MAT(Matx41d)
  MATX_TO_MAT(Matx43f)
  MATX_TO_MAT(Matx43d)
  MATX_TO_MAT(Matx44f)
  MATX_TO_MAT(Matx44d)
  MATX_TO_MAT(Matx51f)
  MATX_TO_MAT(Matx51d)
  MATX_TO_MAT(Matx61f)
  MATX_TO_MAT(Matx61d)
  MATX_TO_MAT(Matx66f)
  MATX_TO_MAT(Matx66d)
  
  --------------------------------------------------------------------------------
  -- Vec instances
  
  #define VEC_TO_MAT(NAME)                          \
  instance ToMat NAME where {                       \
      toMat vec = unsafePerformIO $ fromPtr $       \
          withPtr vec $ \vecPtr ->                  \
            [CU.exp| Mat * {                        \
              new cv::Mat(*$(NAME * vecPtr), false) \
            }|];                                    \
  };
  
  VEC_TO_MAT(Vec2i)
  VEC_TO_MAT(Vec2f)
  VEC_TO_MAT(Vec2d)
  VEC_TO_MAT(Vec3i)
  VEC_TO_MAT(Vec3f)
  VEC_TO_MAT(Vec3d)
  VEC_TO_MAT(Vec4i)
  VEC_TO_MAT(Vec4f)
  VEC_TO_MAT(Vec4d)
  
  --------------------------------------------------------------------------------
  -- Linear instances
  
  instance (Storable depth) => FromMat (M23 depth) where
      fromMat = repaToM23 . toRepa
  
  instance (Storable depth) => FromMat (M33 depth) where
      fromMat = repaToM33 . toRepa
  
  repaToM23 :: (Storable e) => Repa.Array (M '[ 'S 2, 'S 3 ] 1) Repa.DIM3 e -> M23 e
  repaToM23 a =
      V2 (V3 (i 0 0) (i 0 1) (i 0 2))
         (V3 (i 1 0) (i 1 1) (i 1 2))
    where
      i row col = Repa.unsafeIndex a $ Repa.ix3 0 col row
  
  repaToM33 :: (Storable e) => Repa.Array (M '[ 'S 3, 'S 3 ] 1) Repa.DIM3 e -> M33 e
  repaToM33 a =
      V3 (V3 (i 0 0) (i 0 1) (i 0 2))
         (V3 (i 1 0) (i 1 1) (i 1 2))
         (V3 (i 2 0) (i 2 1) (i 2 2))
    where
      i row col = Repa.unsafeIndex a $ Repa.ix3 0 col row
  
  instance (ToDepth (Proxy depth), Storable depth)
        => ToMat (M23 depth) where
      toMat (V2 (V3 i00 i01 i02)
                (V3 i10 i11 i12)
            ) =
        exceptError $ withMatM
          (Proxy :: Proxy [2, 3])
          (Proxy :: Proxy 1)
          (Proxy :: Proxy depth)
          (pure 0 :: V4 Double) $ \imgM -> do
            unsafeWrite imgM [0, 0] 0 i00
            unsafeWrite imgM [1, 0] 0 i10
            unsafeWrite imgM [0, 1] 0 i01
            unsafeWrite imgM [1, 1] 0 i11
            unsafeWrite imgM [0, 2] 0 i02
            unsafeWrite imgM [1, 2] 0 i12
  
  instance (ToDepth (Proxy depth), Storable depth)
        => ToMat (M33 depth) where
      toMat (V3 (V3 i00 i01 i02)
                (V3 i10 i11 i12)
                (V3 i20 i21 i22)
            ) =
        exceptError $ withMatM
          (Proxy :: Proxy [3, 3])
          (Proxy :: Proxy 1)
          (Proxy :: Proxy depth)
          (pure 0 :: V4 Double) $ \imgM -> do
            unsafeWrite imgM [0, 0] 0 i00
            unsafeWrite imgM [1, 0] 0 i10
            unsafeWrite imgM [2, 0] 0 i20
            unsafeWrite imgM [0, 1] 0 i01
            unsafeWrite imgM [1, 1] 0 i11
            unsafeWrite imgM [2, 1] 0 i21
            unsafeWrite imgM [0, 2] 0 i02
            unsafeWrite imgM [1, 2] 0 i12
            unsafeWrite imgM [2, 2] 0 i22
  