{-
Module      : Data.Matrix.SmithNormalForm 
Description : A simple implementation of Smith normal form over the integers.
Copyright   : (c) Brian Hwang 2021
License     : MIT
Stability   : stable
-}
module Data.Matrix.SmithNormalForm
    ( smithNormalForm
    , invariantFactors
    ) where

import qualified Data.Matrix as M
import qualified Data.Vector as V

import qualified Data.Matrix.SmithNormalForm.Internal

-- | Returns the Smith normal form of an matrix, i.e. a diagonal matrix
-- obtained by applying elementary row and column operations
-- whose diagonal entries \([d_1,..,d_n]\) are such that \(d_k | d_{k+1}\)
-- (Does not assume that the matrix is square.)
smithNormalForm :: Integral a => M.Matrix a -> M.Matrix a
smithNormalForm :: Matrix a -> Matrix a
smithNormalForm = Matrix a -> Matrix a
forall a. Integral a => Matrix a -> Matrix a
Data.Matrix.SmithNormalForm.Internal.smithNF 


-- | Given a matrix M, returns the invariant factors of M, i.e. the list of
-- diagonal entries of the Smith normal form of M.
invariantFactors :: Integral a => M.Matrix a -> [a]
invariantFactors :: Matrix a -> [a]
invariantFactors = Vector a -> [a]
forall a. Vector a -> [a]
V.toList (Vector a -> [a]) -> (Matrix a -> Vector a) -> Matrix a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix a -> Vector a
forall a. Matrix a -> Vector a
M.getDiag (Matrix a -> Vector a)
-> (Matrix a -> Matrix a) -> Matrix a -> Vector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix a -> Matrix a
forall a. Integral a => Matrix a -> Matrix a
smithNormalForm