-- |
-- Module      :  ELynx.Tools.LinearAlgebra
-- Copyright   :  (c) Dominik Schrempf 2021
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  dominik.schrempf@gmail.com
-- Stability   :  unstable
-- Portability :  portable
--
-- Creation date: Thu Feb 14 13:33:13 2019.
--
-- Tools for matrices from 'Numeric.LinearAlgebra'.
module ELynx.Tools.LinearAlgebra
  ( -- * Linear Algebra
    matrixSeparateSymSkew,
    matrixSetDiagToZero,
    dispv,
    dispm,
    dispmi,
  )
where

import Data.List
import Numeric.LinearAlgebra

-- | Separate a square matrix into a symmetric and a skew-symmetric matrix.
matrixSeparateSymSkew :: Matrix R -> (Matrix R, Matrix R)
matrixSeparateSymSkew :: Matrix R -> (Matrix R, Matrix R)
matrixSeparateSymSkew Matrix R
m = (Matrix R
mSym, Matrix R
mSkew)
  where
    trM :: Matrix R
trM = Matrix R -> Matrix R
forall m mt. Transposable m mt => m -> mt
tr Matrix R
m
    mSym :: Matrix R
mSym = R -> Matrix R -> Matrix R
forall t (c :: * -> *). Linear t c => t -> c t -> c t
scale R
0.5 (Matrix R -> Matrix R) -> Matrix R -> Matrix R
forall a b. (a -> b) -> a -> b
$ Matrix R
m Matrix R -> Matrix R -> Matrix R
forall a. Num a => a -> a -> a
+ Matrix R
trM
    mSkew :: Matrix R
mSkew = R -> Matrix R -> Matrix R
forall t (c :: * -> *). Linear t c => t -> c t -> c t
scale R
0.5 (Matrix R -> Matrix R) -> Matrix R -> Matrix R
forall a b. (a -> b) -> a -> b
$ Matrix R
m Matrix R -> Matrix R -> Matrix R
forall a. Num a => a -> a -> a
- Matrix R
trM

-- | Set the diagonal entries of a matrix to zero.
matrixSetDiagToZero :: Matrix R -> Matrix R
matrixSetDiagToZero :: Matrix R -> Matrix R
matrixSetDiagToZero Matrix R
m = Matrix R
m Matrix R -> Matrix R -> Matrix R
forall a. Num a => a -> a -> a
- Vector R -> Matrix R
forall a. (Num a, Element a) => Vector a -> Matrix a
diag (Matrix R -> Vector R
forall t. Element t => Matrix t -> Vector t
takeDiag Matrix R
m)
{-# INLINE matrixSetDiagToZero #-}

-- | Display a vector with given precision.
dispv :: Int -> Vector R -> String
dispv :: Int -> Vector R -> String
dispv Int
p Vector R
v = [String] -> String
forall a. [a] -> a
head ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
tail ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ String -> [String]
lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ Int -> Matrix R -> String
dispf Int
p (Vector R -> Matrix R
forall a. Storable a => Vector a -> Matrix a
asRow Vector R
v)

-- | Display a matrix with given precision.
dispm :: Int -> Matrix R -> String
dispm :: Int -> Matrix R -> String
dispm Int
p Matrix R
m = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
init ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ String -> [String]
lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ Int -> Matrix R -> String
dispf Int
p Matrix R
m

-- | Display a matrix with given precision and indent.
dispmi :: Int -> Int -> Matrix R -> String
dispmi :: Int -> Int -> Matrix R -> String
dispmi Int
p Int
i Matrix R
m =
  String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
' ' String -> String -> String
forall a. [a] -> [a] -> [a]
++) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
tail ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ String -> [String]
lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ Int -> Matrix R -> String
dispf Int
p Matrix R
m