moduleMath.LinearAlgebra.Sparse.Algorithms.Diagonal(isDiag,toDiag)whereimportData.MonoidimportData.IntMapasMhiding((!))importMath.LinearAlgebra.Sparse.MatriximportMath.LinearAlgebra.Sparse.VectorimportMath.LinearAlgebra.Sparse.Algorithms.Staircase-- | Checks if matrix has diagonal formisDiag::SparseMatrixα->BoolisDiagm=M.foldlWithKey'(\trueirow->true&&(keysrow==[i]))True(mxm)-- | Transforms matrix to diagonal form and returns also two protocol matrices:---- >>> let (d,t,u) = toDiag m in t × m × (trans u) == d-- True---- So, @t@ stores rows transformations and @u@ — columns transformationstoDiagm=toDiag_m(idMx(heightm))(idMx(widthm))toDiag_mtu|isZeroMxm=(m,t,u)|heightm/=heightt=error"height(mM) /= height(mT)"|widthm/=widthu=error"width(mM) /= width(mU)"|otherwise=let(s,t')=staircase'mtindmTruest'u-- Here s is a staircase matrix.-- If it is not diagonal, then transp(s) it brought to staircase-- form - this corresponds to the column elementary -- transformations of s - and so on, until the diagonal matrix -- is obtained (even number of `transp' to be applied).dmevenstu=case(even,isDiags,transs)of(True,True,_)->(s,t,u)(False,True,s')->(s',t,u)(True,False,s')->dmFalses''tu'where(s'',u')=staircase's'u(False,False,s')->dmTrues''t'uwhere(s'',t')=staircase's't