packages feed

fpnla-examples-0.1: src/FPNLA/Operations/LAPACK/Strategies/POTRF/BlocksSeq.hs

{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables   #-}

module FPNLA.Operations.LAPACK.Strategies.POTRF.BlocksSeq (

) where


import           FPNLA.Matrix                                 (Matrix,
                                                               MatrixVector,
                                                               cantCols_m,
                                                               cantRows_m,
                                                               elem_m,
                                                               fromCols_vm,
                                                               generate_m,
                                                               subMatrix_m,
                                                               toCols_vm,
                                                               transpose_m)
import           FPNLA.Operations.BLAS                        (GEMM (gemm),
                                                               SYRK (syrk),
                                                               TRSM (trsm))
import           FPNLA.Operations.LAPACK                      (POTRF (potrf))
import           FPNLA.Operations.LAPACK.Strategies.DataTypes (CholLLVBlocksSeq,
                                                               SqrBlockContext,
                                                               getSqrBlockDim)
import           FPNLA.Operations.Parameters                  (Elt, ResM,
                                                               TransType (..),
                                                               TriangType (..),
                                                               UnitType (..),
                                                               blasResultM,
                                                               getResultDataM)
import           FPNLA.Utils                                  (iif)

--import Debug.Trace

--trace' s a = trace (s ++ ": " ++ (show a)) a

instance (Elt e, MatrixVector m v e, POTRF potrfs m v e, SYRK syrks m v e,
         GEMM gemms m v e, TRSM trsms m v e) =>
         POTRF (CholLLVBlocksSeq syrks gemms trsms potrfs) m v e where
    potrf ctx (Lower mA)
        =  blasResultM $ chol_blk_l ctx 0 mA (generate_m 0 0 undefined)
        where
            chol_blk_l ctx@(block_ctx, syrk_ctx, gemm_ctx, trsm_ctx, potrf_ctx) k mA mAL
                | k == 0           =  let  mA11'  = call_chol_unb (Lower mA11)
                                           mA21'  = transpose_m $ call_trsm 1 (NoTrans . Lower $ NoUnit mA11') (transpose_m mA21)
                                           mAx1   = iif (k == cantBlocks - 1) mA11' $ concatByCol_m mA11' mA21'
                                      in chol_blk_l ctx (k + 1) mA mAx1
                | k == cantBlocks  =  mAL
                | otherwise        =  chol_blk_l ctx (k + 1) mA mAL'

                where
                    mA_dim      = cantCols_m mA
                    mA10        = subMatrix_m (block * k) 0 block (block*k) mAL
                    mA11        = subMatrix_m (block * k) (block * k) block block mA
                    mA11'       = call_syrk (-1) (NoTrans mA10) 1 (Lower mA11)
                    mA11''      = call_chol_unb (Lower mA11')
                    mA20        = subMatrix_m ((k + 1) * block) 0 (mA_dim - (k + 1)*block) (k*block) mAL
                    mA21        = subMatrix_m ((k + 1) * block) (k * block) (mA_dim - (k + 1)*block) block mA
                    mA21'       = call_gemm  (NoTrans mA20) (Trans mA10) (-1) 1 mA21
                    mA21''      = transpose_m $ call_trsm 1 (NoTrans . Lower $ NoUnit mA11'') (transpose_m mA21')

                    mAx1        = add_zeros k block . iif (k == cantBlocks - 1) mA11'' $ concatByCol_m mA11'' mA21''

                    mAL'        = fromCols_vm $ (toCols_vm mAL :: [v e]) ++ (toCols_vm mAx1 :: [v e])

                    call_syrk m1 alpha beta m2 = getResultDataM (syrk syrk_ctx m1 alpha beta m2 :: ResM syrks v m e)
                    call_chol_unb m = getResultDataM (potrf potrf_ctx m :: ResM potrfs v m e)
                    call_gemm m1 m2 alpha beta m3 = getResultDataM (gemm gemm_ctx m1 m2 alpha beta m3 :: ResM gemms v m e)
                    call_trsm alpha m1 m2 = getResultDataM (trsm trsm_ctx alpha m1 m2 :: ResM trsms v m e)

                    add_zeros :: (Matrix m e) => Int -> Int -> m e -> m e
                    add_zeros k block = concatByCol_m (generate_m (k*block) block (\_ _ -> 0) :: m e)

                    block       = getSqrBlockDim block_ctx
                    cantBlocks  = mA_dim `div` block

concatByCol_m :: (Matrix m e) => m e -> m e -> m e
concatByCol_m m1 m2 = let rows_m1 = cantRows_m m1
                          cols_m1 = cantCols_m m1
                          rows_m2 = cantRows_m m2
                      in generate_m (rows_m1 + rows_m2) cols_m1
                                    (\i j -> iif (i >= rows_m1) (elem_m (i - rows_m1) j m2)
                                                                (elem_m i j m1))