packages feed

fpnla-examples-0.1: src/FPNLA/Operations/BLAS/Strategies/TRSM/DefSeq.hs

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

module FPNLA.Operations.BLAS.Strategies.TRSM.DefSeq () where


import           FPNLA.Matrix                               (MatrixVector,
                                                             dim_m, elem_v,
                                                             fromCols_vm,
                                                             fromList_v,
                                                             toCols_vm)
import           FPNLA.Operations.BLAS                      (TRSM (trsm))
import           FPNLA.Operations.BLAS.Strategies.DataTypes (DefSeq)
import           FPNLA.Operations.Parameters                (Elt, TransType (NoTrans, Trans, ConjTrans), TriangType (Upper, Lower),
                                                             UnitType,
                                                             blasResultM,
                                                             dimTransUnit_m,
                                                             dimUnit_m,
                                                             elemTransUnit_m,
                                                             unTransT,
                                                             unTriangT)

forwardElim :: (Elt e, MatrixVector m v e) => e -> TransType (UnitType (m e)) -> v e -> v e
forwardElim alpha pmA vB = fromList_v res
    where
        cr = fst . dimTransUnit_m $ pmA -- Cantidad de ecuaciones
        res = solve cr -- Usada para la evaluacion perezosa
        solve 0 = []
        solve i = calcX i : solve (i-1)
        calcX i -- Calcula el elemento X_i
            | v_ind == 0  = 0 -- Devuelve 0 si el valor del vector vale 0.
            | otherwise   = (v_ind - sumValues 0 res) / elemTransUnit_m ind ind pmA
            where
                  ind = cr - i -- Indice real
                  ind_v = ind
                  eqr = cr - i -- Cantidad de ecuaciones resueltas
                  v_ind = alpha * elem_v ind_v vB
                  sumValues j (x:xs)
                      | j < eqr = x * elemTransUnit_m ind j pmA + sumValues (j+1) xs
                      | otherwise = 0
--
backwardElim :: (Elt e, MatrixVector m v e) => e -> TransType (UnitType (m e)) -> v e -> v e
backwardElim alpha pmA vB = fromList_v $ reverse res
    where
        cr = fst . dimTransUnit_m $ pmA -- Cantidad de ecuaciones
        res = solve cr -- Usada para la evaluación perezosa
        solve 0 = []
        solve i = calcX i : solve (i-1)
        calcX i -- Calcula el elemento X_[cr - i]
            | v_ind == 0  = 0 -- Devuelve 0 si el valor del vector vale 0.
            | otherwise   = (v_ind - sumValues (cr-1) res) / elemTransUnit_m ind ind pmA
            where
                  ind = i - 1 -- Indice real
                  eqr = cr - i -- Cantidad de ecuaciones resueltas
                  v_ind = alpha * elem_v ind vB
                  sumValues j (x:xs)
                      | j > cr - 1 - eqr = x * elemTransUnit_m ind j pmA + sumValues (j-1) xs
                      | otherwise = 0
--
instance (Elt e, MatrixVector m v e) => TRSM DefSeq m v e where
    trsm _ alpha pmA mB
        | rowsmA /= colsmA = error "trsm: matrix A must be squared"
        | colsmA /= rowsmB = error "trsm: incompatible ranges"
        | otherwise = blasResultM . fromCols_vm . map (selectStrat pmA) $ (toCols_vm mB :: [v e])
        where
            (rowsmA, colsmA) = dimUnit_m . snd . unTriangT . snd . unTransT $ pmA
            rowsmB = fst . dim_m $ mB
            selectStrat (NoTrans (Lower umA)) = forwardElim alpha (NoTrans umA)
            selectStrat (Trans (Lower umA)) = backwardElim alpha (Trans umA)
            selectStrat (ConjTrans (Lower umA)) = backwardElim alpha (ConjTrans umA)
            selectStrat (NoTrans (Upper umA)) = backwardElim alpha (NoTrans umA)
            selectStrat (Trans (Upper umA)) = forwardElim alpha (Trans umA)
            selectStrat (ConjTrans (Upper umA)) = forwardElim alpha (ConjTrans umA)