Apply clang-format

This commit is contained in:
Tobias Wood
2023-11-29 11:12:48 +00:00
parent 9ea520fc45
commit f38e16c193
534 changed files with 103368 additions and 116934 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -14,56 +14,66 @@
namespace Eigen {
namespace internal {
/** \ingroup SparseLU_Module
* \class SparseLUImpl
* Base class for sparseLU
*/
template <typename Scalar, typename StorageIndex>
class SparseLUImpl
{
public:
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
typedef Matrix<StorageIndex,Dynamic,1> IndexVector;
typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> ScalarMatrix;
typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
typedef typename ScalarVector::RealScalar RealScalar;
typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
typedef Ref<Matrix<StorageIndex,Dynamic,1> > BlockIndexVector;
typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
typedef SparseMatrix<Scalar,ColMajor,StorageIndex> MatrixType;
protected:
template <typename VectorType>
Index expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions);
Index memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu);
template <typename VectorType>
Index memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions);
void heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
void relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
Index snode_dfs(const Index jcol, const Index kcol,const MatrixType& mat, IndexVector& xprune, IndexVector& marker, GlobalLU_t& glu);
Index snode_bmod (const Index jcol, const Index fsupc, ScalarVector& dense, GlobalLU_t& glu);
Index pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu);
template <typename Traits>
void dfs_kernel(const StorageIndex jj, IndexVector& perm_r,
Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
IndexVector& xplore, GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits);
void panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
void panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu);
Index column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg, BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
Index column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv, BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu);
Index copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu);
void pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu);
void countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu);
void fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu);
template<typename , typename >
friend struct column_dfs_traits;
};
} // end namespace internal
} // namespace Eigen
/** \ingroup SparseLU_Module
* \class SparseLUImpl
* Base class for sparseLU
*/
template <typename Scalar, typename StorageIndex>
class SparseLUImpl {
public:
typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ScalarMatrix;
typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
typedef typename ScalarVector::RealScalar RealScalar;
typedef Ref<Matrix<Scalar, Dynamic, 1> > BlockScalarVector;
typedef Ref<Matrix<StorageIndex, Dynamic, 1> > BlockIndexVector;
typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
typedef SparseMatrix<Scalar, ColMajor, StorageIndex> MatrixType;
protected:
template <typename VectorType>
Index expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions);
Index memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu);
template <typename VectorType>
Index memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions);
void heap_relax_snode(const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants,
IndexVector& relax_end);
void relax_snode(const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants,
IndexVector& relax_end);
Index snode_dfs(const Index jcol, const Index kcol, const MatrixType& mat, IndexVector& xprune, IndexVector& marker,
GlobalLU_t& glu);
Index snode_bmod(const Index jcol, const Index fsupc, ScalarVector& dense, GlobalLU_t& glu);
Index pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c,
Index& pivrow, GlobalLU_t& glu);
template <typename Traits>
void dfs_kernel(const StorageIndex jj, IndexVector& perm_r, Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
IndexVector& xplore, GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits);
void panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg,
ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz,
IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
void panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, ScalarVector& dense,
ScalarVector& tempv, IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu);
Index column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg,
BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
Index column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv,
BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu);
Index copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz,
IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu);
void pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg,
const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu);
void countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu);
void fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu);
template <typename, typename>
friend struct column_dfs_traits;
};
} // end namespace internal
} // namespace Eigen
#endif

View File

@@ -7,10 +7,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
* -- SuperLU routine (version 3.1) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -36,194 +36,175 @@
namespace Eigen {
namespace internal {
enum { LUNoMarker = 3 };
enum {emptyIdxLU = -1};
inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b)
{
return (std::max)(m, (t+b)*w);
enum { emptyIdxLU = -1 };
inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b) { return (std::max)(m, (t + b) * w); }
template <typename Scalar>
inline Index LUTempSpace(Index& m, Index& w) {
return (2 * w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
}
template< typename Scalar>
inline Index LUTempSpace(Index&m, Index& w)
{
return (2*w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
}
/**
* Expand the existing storage to accommodate more fill-ins
* \param vec Valid pointer to the vector to allocate or expand
* \param[in,out] length At input, contain the current length of the vector that is to be increased. At output, length of the newly allocated vector
* \param[in] nbElts Current number of elements in the factors
* \param keep_prev 1: use length and do not expand the vector; 0: compute new_len and expand
* \param[in,out] num_expansions Number of times the memory has been expanded
*/
/**
* Expand the existing storage to accommodate more fill-ins
* \param vec Valid pointer to the vector to allocate or expand
* \param[in,out] length At input, contain the current length of the vector that is to be increased. At output, length
* of the newly allocated vector \param[in] nbElts Current number of elements in the factors \param keep_prev 1: use
* length and do not expand the vector; 0: compute new_len and expand \param[in,out] num_expansions Number of times the
* memory has been expanded
*/
template <typename Scalar, typename StorageIndex>
template <typename VectorType>
Index SparseLUImpl<Scalar,StorageIndex>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions)
{
float alpha = 1.5; // Ratio of the memory increase
Index new_len; // New size of the allocated memory
if(num_expansions == 0 || keep_prev)
new_len = length ; // First time allocate requested
else
new_len = (std::max)(length+1,Index(alpha * length));
VectorType old_vec; // Temporary vector to hold the previous values
if (nbElts > 0 )
old_vec = vec.segment(0,nbElts);
//Allocate or expand the current vector
Index SparseLUImpl<Scalar, StorageIndex>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev,
Index& num_expansions) {
float alpha = 1.5; // Ratio of the memory increase
Index new_len; // New size of the allocated memory
if (num_expansions == 0 || keep_prev)
new_len = length; // First time allocate requested
else
new_len = (std::max)(length + 1, Index(alpha * length));
VectorType old_vec; // Temporary vector to hold the previous values
if (nbElts > 0) old_vec = vec.segment(0, nbElts);
// Allocate or expand the current vector
#ifdef EIGEN_EXCEPTIONS
try
#endif
{
vec.resize(new_len);
vec.resize(new_len);
}
#ifdef EIGEN_EXCEPTIONS
catch(std::bad_alloc& )
catch (std::bad_alloc&)
#else
if(!vec.size())
if (!vec.size())
#endif
{
if (!num_expansions)
{
if (!num_expansions) {
// First time to allocate from LUMemInit()
// Let LUMemInit() deals with it.
return -1;
}
if (keep_prev)
{
if (keep_prev) {
// In this case, the memory length should not not be reduced
return new_len;
}
else
{
// Reduce the size and increase again
Index tries = 0; // Number of attempts
do
{
alpha = (alpha + 1)/2;
new_len = (std::max)(length+1,Index(alpha * length));
} else {
// Reduce the size and increase again
Index tries = 0; // Number of attempts
do {
alpha = (alpha + 1) / 2;
new_len = (std::max)(length + 1, Index(alpha * length));
#ifdef EIGEN_EXCEPTIONS
try
#endif
{
vec.resize(new_len);
vec.resize(new_len);
}
#ifdef EIGEN_EXCEPTIONS
catch(std::bad_alloc& )
catch (std::bad_alloc&)
#else
if (!vec.size())
#endif
{
tries += 1;
if ( tries > 10) return new_len;
tries += 1;
if (tries > 10) return new_len;
}
} while (!vec.size());
}
}
//Copy the previous values to the newly allocated space
if (nbElts > 0)
vec.segment(0, nbElts) = old_vec;
length = new_len;
if(num_expansions) ++num_expansions;
return 0;
// Copy the previous values to the newly allocated space
if (nbElts > 0) vec.segment(0, nbElts) = old_vec;
length = new_len;
if (num_expansions) ++num_expansions;
return 0;
}
/**
* \brief Allocate various working space for the numerical factorization phase.
* \param m number of rows of the input matrix
* \param n number of columns
* \param annz number of initial nonzeros in the matrix
* \param m number of rows of the input matrix
* \param n number of columns
* \param annz number of initial nonzeros in the matrix
* \param lwork if lwork=-1, this routine returns an estimated size of the required memory
* \param glu persistent data to facilitate multiple factors : will be deleted later ??
* \param fillratio estimated ratio of fill in the factors
* \param panel_size Size of a panel
* \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated memory when allocation failed, and 0 on success
* \note Unlike SuperLU, this routine does not support successive factorization with the same pattern and the same row permutation
* \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated
* memory when allocation failed, and 0 on success \note Unlike SuperLU, this routine does not support successive
* factorization with the same pattern and the same row permutation
*/
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar,StorageIndex>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu)
{
Index& num_expansions = glu.num_expansions; //No memory expansions so far
Index SparseLUImpl<Scalar, StorageIndex>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio,
Index panel_size, GlobalLU_t& glu) {
Index& num_expansions = glu.num_expansions; // No memory expansions so far
num_expansions = 0;
glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz+1) / n, m) * n; // estimated number of nonzeros in U
glu.nzlmax = (std::max)(Index(4), fillratio) * (annz+1) / 4; // estimated nnz in L factor
glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz + 1) / n, m) * n; // estimated number of nonzeros in U
glu.nzlmax = (std::max)(Index(4), fillratio) * (annz + 1) / 4; // estimated nnz in L factor
// Return the estimated size to the user if necessary
Index tempSpace;
tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
if (lwork == emptyIdxLU)
{
tempSpace = (2 * panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
if (lwork == emptyIdxLU) {
Index estimated_size;
estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace
+ (glu.nzlmax + glu.nzumax) * sizeof(Index) + (glu.nzlumax+glu.nzumax) * sizeof(Scalar) + n;
estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace + (glu.nzlmax + glu.nzumax) * sizeof(Index) +
(glu.nzlumax + glu.nzumax) * sizeof(Scalar) + n;
return estimated_size;
}
// Setup the required space
// Setup the required space
// First allocate Integer pointers for L\U factors
glu.xsup.resize(n+1);
glu.supno.resize(n+1);
glu.xlsub.resize(n+1);
glu.xlusup.resize(n+1);
glu.xusub.resize(n+1);
glu.xsup.resize(n + 1);
glu.supno.resize(n + 1);
glu.xlsub.resize(n + 1);
glu.xlusup.resize(n + 1);
glu.xusub.resize(n + 1);
// Reserve memory for L/U factors
do
{
if( (expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions)<0)
|| (expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions)<0)
|| (expand<IndexVector> (glu.lsub, glu.nzlmax, 0, 0, num_expansions)<0)
|| (expand<IndexVector> (glu.usub, glu.nzumax, 0, 1, num_expansions)<0) )
{
//Reduce the estimated size and retry
do {
if ((expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions) < 0) ||
(expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions) < 0) ||
(expand<IndexVector>(glu.lsub, glu.nzlmax, 0, 0, num_expansions) < 0) ||
(expand<IndexVector>(glu.usub, glu.nzumax, 0, 1, num_expansions) < 0)) {
// Reduce the estimated size and retry
glu.nzlumax /= 2;
glu.nzumax /= 2;
glu.nzlmax /= 2;
if (glu.nzlumax < annz ) return glu.nzlumax;
if (glu.nzlumax < annz) return glu.nzlumax;
}
} while (!glu.lusup.size() || !glu.ucol.size() || !glu.lsub.size() || !glu.usub.size());
++num_expansions;
return 0;
} // end LuMemInit
/**
* \brief Expand the existing storage
* \param vec vector to expand
} // end LuMemInit
/**
* \brief Expand the existing storage
* \param vec vector to expand
* \param[in,out] maxlen On input, previous size of vec (Number of elements to copy ). on output, new size
* \param nbElts current number of elements in the vector.
* \param memtype Type of the element to expand
* \param num_expansions Number of expansions
* \param num_expansions Number of expansions
* \return 0 on success, > 0 size of the memory allocated so far
*/
template <typename Scalar, typename StorageIndex>
template <typename VectorType>
Index SparseLUImpl<Scalar,StorageIndex>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions)
{
Index failed_size;
Index SparseLUImpl<Scalar, StorageIndex>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype,
Index& num_expansions) {
Index failed_size;
if (memtype == USUB)
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
else
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 0, num_expansions);
if (failed_size)
return failed_size;
return 0 ;
if (failed_size) return failed_size;
return 0;
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_SPARSELU_MEMORY
} // end namespace Eigen
#endif // EIGEN_SPARSELU_MEMORY

View File

@@ -7,26 +7,26 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
/*
* NOTE: This file comes from a partly modified version of files slu_[s,d,c,z]defs.h
* -- SuperLU routine (version 4.1) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
* November, 2010
*
*
* Global data structures used in LU factorization -
*
*
* nsuper: #supernodes = nsuper + 1, numbered [0, nsuper].
* (xsup,supno): supno[i] is the supernode no to which i belongs;
* xsup(s) points to the beginning of the s-th supernode.
* e.g. supno 0 1 2 2 3 3 3 4 4 4 4 4 (n=12)
* xsup 0 1 2 4 7 12
* Note: dfs will be performed on supernode rep. relative to the new
* Note: dfs will be performed on supernode rep. relative to the new
* row pivoting ordering
*
* (xlsub,lsub): lsub[*] contains the compressed subscript of
* rectangular supernodes; xlsub[j] points to the starting
* location of the j-th column in lsub[*]. Note that xlsub
* location of the j-th column in lsub[*]. Note that xlsub
* is indexed by column.
* Storage: original row subscripts
*
@@ -74,40 +74,40 @@
namespace Eigen {
namespace internal {
enum MemType {LUSUP, UCOL, LSUB, USUB, LLVL, ULVL};
enum MemType { LUSUP, UCOL, LSUB, USUB, LLVL, ULVL };
template <typename IndexVector, typename ScalarVector>
struct LU_GlobalLU_t {
typedef typename IndexVector::Scalar StorageIndex;
IndexVector xsup; //First supernode column ... xsup(s) points to the beginning of the s-th supernode
IndexVector supno; // Supernode number corresponding to this column (column to supernode mapping)
ScalarVector lusup; // nonzero values of L ordered by columns
IndexVector lsub; // Compressed row indices of L rectangular supernodes.
IndexVector xlusup; // pointers to the beginning of each column in lusup
IndexVector xlsub; // pointers to the beginning of each column in lsub
Index nzlmax; // Current max size of lsub
Index nzlumax; // Current max size of lusup
ScalarVector ucol; // nonzero values of U ordered by columns
IndexVector usub; // row indices of U columns in ucol
IndexVector xusub; // Pointers to the beginning of each column of U in ucol
Index nzumax; // Current max size of ucol
Index n; // Number of columns in the matrix
Index num_expansions;
typedef typename IndexVector::Scalar StorageIndex;
IndexVector xsup; // First supernode column ... xsup(s) points to the beginning of the s-th supernode
IndexVector supno; // Supernode number corresponding to this column (column to supernode mapping)
ScalarVector lusup; // nonzero values of L ordered by columns
IndexVector lsub; // Compressed row indices of L rectangular supernodes.
IndexVector xlusup; // pointers to the beginning of each column in lusup
IndexVector xlsub; // pointers to the beginning of each column in lsub
Index nzlmax; // Current max size of lsub
Index nzlumax; // Current max size of lusup
ScalarVector ucol; // nonzero values of U ordered by columns
IndexVector usub; // row indices of U columns in ucol
IndexVector xusub; // Pointers to the beginning of each column of U in ucol
Index nzumax; // Current max size of ucol
Index n; // Number of columns in the matrix
Index num_expansions;
};
// Values to set for performance
struct perfvalues {
Index panel_size; // a panel consists of at most <panel_size> consecutive columns
Index relax; // To control degree of relaxing supernodes. If the number of nodes (columns)
// in a subtree of the elimination tree is less than relax, this subtree is considered
// as one supernode regardless of the row structures of those columns
Index maxsuper; // The maximum size for a supernode in complete LU
Index rowblk; // The minimum row dimension for 2-D blocking to be used;
Index colblk; // The minimum column dimension for 2-D blocking to be used;
Index fillfactor; // The estimated fills factors for L and U, compared with A
};
Index panel_size; // a panel consists of at most <panel_size> consecutive columns
Index relax; // To control degree of relaxing supernodes. If the number of nodes (columns)
// in a subtree of the elimination tree is less than relax, this subtree is considered
// as one supernode regardless of the row structures of those columns
Index maxsuper; // The maximum size for a supernode in complete LU
Index rowblk; // The minimum row dimension for 2-D blocking to be used;
Index colblk; // The minimum column dimension for 2-D blocking to be used;
Index fillfactor; // The estimated fills factors for L and U, compared with A
};
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_LU_STRUCTS
} // end namespace Eigen
#endif // EIGEN_LU_STRUCTS

View File

@@ -19,359 +19,301 @@ namespace internal {
/** \ingroup SparseLU_Module
* \brief a class to manipulate the L supernodal factor from the SparseLU factorization
*
* This class contain the data to easily store
* and manipulate the supernodes during the factorization and solution phase of Sparse LU.
*
* This class contain the data to easily store
* and manipulate the supernodes during the factorization and solution phase of Sparse LU.
* Only the lower triangular matrix has supernodes.
*
*
* NOTE : This class corresponds to the SCformat structure in SuperLU
*
*
*/
/* TODO
* InnerIterator as for sparsematrix
* SuperInnerIterator to iterate through all supernodes
* InnerIterator as for sparsematrix
* SuperInnerIterator to iterate through all supernodes
* Function for triangular solve
*/
template <typename Scalar_, typename StorageIndex_>
class MappedSuperNodalMatrix
{
public:
typedef Scalar_ Scalar;
typedef StorageIndex_ StorageIndex;
typedef Matrix<StorageIndex,Dynamic,1> IndexVector;
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
public:
MappedSuperNodalMatrix()
{
}
MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
{
setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
}
~MappedSuperNodalMatrix()
{
}
/**
* Set appropriate pointers for the lower triangular supernodal matrix
* These infos are available at the end of the numerical factorization
* FIXME This class will be modified such that it can be use in the course
* of the factorization.
*/
void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
{
m_row = m;
m_col = n;
m_nzval = nzval.data();
m_nzval_colptr = nzval_colptr.data();
m_rowind = rowind.data();
m_rowind_colptr = rowind_colptr.data();
m_nsuper = col_to_sup(n);
m_col_to_sup = col_to_sup.data();
m_sup_to_col = sup_to_col.data();
}
/**
* Number of rows
*/
Index rows() const { return m_row; }
/**
* Number of columns
*/
Index cols() const { return m_col; }
/**
* Return the array of nonzero values packed by column
*
* The size is nnz
*/
Scalar* valuePtr() { return m_nzval; }
const Scalar* valuePtr() const
{
return m_nzval;
}
/**
* Return the pointers to the beginning of each column in \ref valuePtr()
*/
StorageIndex* colIndexPtr()
{
return m_nzval_colptr;
}
const StorageIndex* colIndexPtr() const
{
return m_nzval_colptr;
}
/**
* Return the array of compressed row indices of all supernodes
*/
StorageIndex* rowIndex() { return m_rowind; }
const StorageIndex* rowIndex() const
{
return m_rowind;
}
/**
* Return the location in \em rowvaluePtr() which starts each column
*/
StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
const StorageIndex* rowIndexPtr() const
{
return m_rowind_colptr;
}
/**
* Return the array of column-to-supernode mapping
*/
StorageIndex* colToSup() { return m_col_to_sup; }
const StorageIndex* colToSup() const
{
return m_col_to_sup;
}
/**
* Return the array of supernode-to-column mapping
*/
StorageIndex* supToCol() { return m_sup_to_col; }
const StorageIndex* supToCol() const
{
return m_sup_to_col;
}
/**
* Return the number of supernodes
*/
Index nsuper() const
{
return m_nsuper;
}
class InnerIterator;
template<typename Dest>
void solveInPlace( MatrixBase<Dest>&X) const;
template<bool Conjugate, typename Dest>
void solveTransposedInPlace( MatrixBase<Dest>&X) const;
class MappedSuperNodalMatrix {
public:
typedef Scalar_ Scalar;
typedef StorageIndex_ StorageIndex;
typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
protected:
Index m_row; // Number of rows
Index m_col; // Number of columns
Index m_nsuper; // Number of supernodes
Scalar* m_nzval; //array of nonzero values packed by column
StorageIndex* m_nzval_colptr; //nzval_colptr[j] Stores the location in nzval[] which starts column j
StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
StorageIndex* m_rowind_colptr; //rowind_colptr[j] stores the location in rowind[] which starts column j
StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
StorageIndex* m_sup_to_col; //sup_to_col[s] points to the starting column of the s-th supernode
private :
public:
MappedSuperNodalMatrix() {}
MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
}
~MappedSuperNodalMatrix() {}
/**
* Set appropriate pointers for the lower triangular supernodal matrix
* These infos are available at the end of the numerical factorization
* FIXME This class will be modified such that it can be use in the course
* of the factorization.
*/
void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
m_row = m;
m_col = n;
m_nzval = nzval.data();
m_nzval_colptr = nzval_colptr.data();
m_rowind = rowind.data();
m_rowind_colptr = rowind_colptr.data();
m_nsuper = col_to_sup(n);
m_col_to_sup = col_to_sup.data();
m_sup_to_col = sup_to_col.data();
}
/**
* Number of rows
*/
Index rows() const { return m_row; }
/**
* Number of columns
*/
Index cols() const { return m_col; }
/**
* Return the array of nonzero values packed by column
*
* The size is nnz
*/
Scalar* valuePtr() { return m_nzval; }
const Scalar* valuePtr() const { return m_nzval; }
/**
* Return the pointers to the beginning of each column in \ref valuePtr()
*/
StorageIndex* colIndexPtr() { return m_nzval_colptr; }
const StorageIndex* colIndexPtr() const { return m_nzval_colptr; }
/**
* Return the array of compressed row indices of all supernodes
*/
StorageIndex* rowIndex() { return m_rowind; }
const StorageIndex* rowIndex() const { return m_rowind; }
/**
* Return the location in \em rowvaluePtr() which starts each column
*/
StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
const StorageIndex* rowIndexPtr() const { return m_rowind_colptr; }
/**
* Return the array of column-to-supernode mapping
*/
StorageIndex* colToSup() { return m_col_to_sup; }
const StorageIndex* colToSup() const { return m_col_to_sup; }
/**
* Return the array of supernode-to-column mapping
*/
StorageIndex* supToCol() { return m_sup_to_col; }
const StorageIndex* supToCol() const { return m_sup_to_col; }
/**
* Return the number of supernodes
*/
Index nsuper() const { return m_nsuper; }
class InnerIterator;
template <typename Dest>
void solveInPlace(MatrixBase<Dest>& X) const;
template <bool Conjugate, typename Dest>
void solveTransposedInPlace(MatrixBase<Dest>& X) const;
protected:
Index m_row; // Number of rows
Index m_col; // Number of columns
Index m_nsuper; // Number of supernodes
Scalar* m_nzval; // array of nonzero values packed by column
StorageIndex* m_nzval_colptr; // nzval_colptr[j] Stores the location in nzval[] which starts column j
StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
StorageIndex* m_rowind_colptr; // rowind_colptr[j] stores the location in rowind[] which starts column j
StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
StorageIndex* m_sup_to_col; // sup_to_col[s] points to the starting column of the s-th supernode
private:
};
/**
* \brief InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L
*
*/
template<typename Scalar, typename StorageIndex>
class MappedSuperNodalMatrix<Scalar,StorageIndex>::InnerIterator
{
public:
InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
* \brief InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L
*
*/
template <typename Scalar, typename StorageIndex>
class MappedSuperNodalMatrix<Scalar, StorageIndex>::InnerIterator {
public:
InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
: m_matrix(mat),
m_outer(outer),
m_supno(mat.colToSup()[outer]),
m_idval(mat.colIndexPtr()[outer]),
m_startidval(m_idval),
m_endidval(mat.colIndexPtr()[outer+1]),
m_endidval(mat.colIndexPtr()[outer + 1]),
m_idrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]]),
m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]+1])
{}
inline InnerIterator& operator++()
{
m_idval++;
m_idrow++;
return *this;
}
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
inline Index row() const { return index(); }
inline Index col() const { return m_outer; }
inline Index supIndex() const { return m_supno; }
inline operator bool() const
{
return ( (m_idval < m_endidval) && (m_idval >= m_startidval)
&& (m_idrow < m_endidrow) );
}
protected:
const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
const Index m_outer; // Current column
const Index m_supno; // Current SuperNode number
Index m_idval; // Index to browse the values in the current column
const Index m_startidval; // Start of the column value
const Index m_endidval; // End of the column value
Index m_idrow; // Index to browse the row indices
Index m_endidrow; // End index of row indices of the current column
m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]] + 1]) {}
inline InnerIterator& operator++() {
m_idval++;
m_idrow++;
return *this;
}
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
inline Index row() const { return index(); }
inline Index col() const { return m_outer; }
inline Index supIndex() const { return m_supno; }
inline operator bool() const {
return ((m_idval < m_endidval) && (m_idval >= m_startidval) && (m_idrow < m_endidrow));
}
protected:
const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
const Index m_outer; // Current column
const Index m_supno; // Current SuperNode number
Index m_idval; // Index to browse the values in the current column
const Index m_startidval; // Start of the column value
const Index m_endidval; // End of the column value
Index m_idrow; // Index to browse the row indices
Index m_endidrow; // End index of row indices of the current column
};
/**
* \brief Solve with the supernode triangular matrix
*
*
*/
template<typename Scalar, typename Index_>
template<typename Dest>
void MappedSuperNodalMatrix<Scalar,Index_>::solveInPlace( MatrixBase<Dest>&X) const
{
/* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
// eigen_assert(X.rows() <= NumTraits<Index>::highest());
// eigen_assert(X.cols() <= NumTraits<Index>::highest());
Index n = int(X.rows());
Index nrhs = Index(X.cols());
const Scalar * Lval = valuePtr(); // Nonzero values
Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
work.setZero();
for (Index k = 0; k <= nsuper(); k ++)
{
Index fsupc = supToCol()[k]; // First column of the current supernode
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
Index irow; //Current index row
if (nsupc == 1 )
{
for (Index j = 0; j < nrhs; j++)
{
InnerIterator it(*this, fsupc);
++it; // Skip the diagonal element
for (; it; ++it)
{
irow = it.row();
X(irow, j) -= X(fsupc, j) * it.value();
}
}
}
else
{
// The supernode has more than one column
Index luptr = colIndexPtr()[fsupc];
Index lda = colIndexPtr()[fsupc+1] - luptr;
// Triangular solve
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
U = A.template triangularView<UnitLower>().solve(U);
// Matrix-vector product
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
work.topRows(nrow).noalias() = A * U;
//Begin Scatter
for (Index j = 0; j < nrhs; j++)
{
Index iptr = istart + nsupc;
for (Index i = 0; i < nrow; i++)
{
irow = rowIndex()[iptr];
X(irow, j) -= work(i, j); // Scatter operation
work(i, j) = Scalar(0);
iptr++;
}
}
}
}
}
template<typename Scalar, typename Index_>
template<bool Conjugate, typename Dest>
void MappedSuperNodalMatrix<Scalar,Index_>::solveTransposedInPlace( MatrixBase<Dest>&X) const
{
using numext::conj;
Index n = int(X.rows());
template <typename Scalar, typename Index_>
template <typename Dest>
void MappedSuperNodalMatrix<Scalar, Index_>::solveInPlace(MatrixBase<Dest>& X) const {
/* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
// eigen_assert(X.rows() <= NumTraits<Index>::highest());
// eigen_assert(X.cols() <= NumTraits<Index>::highest());
Index n = int(X.rows());
Index nrhs = Index(X.cols());
const Scalar * Lval = valuePtr(); // Nonzero values
Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
const Scalar* Lval = valuePtr(); // Nonzero values
Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
work.setZero();
for (Index k = nsuper(); k >= 0; k--)
{
Index fsupc = supToCol()[k]; // First column of the current supernode
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
Index irow; //Current index row
for (Index k = 0; k <= nsuper(); k++) {
Index fsupc = supToCol()[k]; // First column of the current supernode
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
Index irow; // Current index row
if (nsupc == 1 )
{
for (Index j = 0; j < nrhs; j++)
{
if (nsupc == 1) {
for (Index j = 0; j < nrhs; j++) {
InnerIterator it(*this, fsupc);
++it; // Skip the diagonal element
for (; it; ++it)
{
++it; // Skip the diagonal element
for (; it; ++it) {
irow = it.row();
X(fsupc,j) -= X(irow, j) * (Conjugate?conj(it.value()):it.value());
X(irow, j) -= X(fsupc, j) * it.value();
}
}
} else {
// The supernode has more than one column
Index luptr = colIndexPtr()[fsupc];
Index lda = colIndexPtr()[fsupc + 1] - luptr;
// Triangular solve
Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr]), nsupc, nsupc,
OuterStride<>(lda));
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
U = A.template triangularView<UnitLower>().solve(U);
// Matrix-vector product
new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr + nsupc]), nrow,
nsupc, OuterStride<>(lda));
work.topRows(nrow).noalias() = A * U;
// Begin Scatter
for (Index j = 0; j < nrhs; j++) {
Index iptr = istart + nsupc;
for (Index i = 0; i < nrow; i++) {
irow = rowIndex()[iptr];
X(irow, j) -= work(i, j); // Scatter operation
work(i, j) = Scalar(0);
iptr++;
}
}
}
else
{
}
}
template <typename Scalar, typename Index_>
template <bool Conjugate, typename Dest>
void MappedSuperNodalMatrix<Scalar, Index_>::solveTransposedInPlace(MatrixBase<Dest>& X) const {
using numext::conj;
Index n = int(X.rows());
Index nrhs = Index(X.cols());
const Scalar* Lval = valuePtr(); // Nonzero values
Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
work.setZero();
for (Index k = nsuper(); k >= 0; k--) {
Index fsupc = supToCol()[k]; // First column of the current supernode
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
Index irow; // Current index row
if (nsupc == 1) {
for (Index j = 0; j < nrhs; j++) {
InnerIterator it(*this, fsupc);
++it; // Skip the diagonal element
for (; it; ++it) {
irow = it.row();
X(fsupc, j) -= X(irow, j) * (Conjugate ? conj(it.value()) : it.value());
}
}
} else {
// The supernode has more than one column
Index luptr = colIndexPtr()[fsupc];
Index lda = colIndexPtr()[fsupc+1] - luptr;
Index lda = colIndexPtr()[fsupc + 1] - luptr;
//Begin Gather
for (Index j = 0; j < nrhs; j++)
{
// Begin Gather
for (Index j = 0; j < nrhs; j++) {
Index iptr = istart + nsupc;
for (Index i = 0; i < nrow; i++)
{
for (Index i = 0; i < nrow; i++) {
irow = rowIndex()[iptr];
work.topRows(nrow)(i,j)= X(irow,j); // Gather operation
work.topRows(nrow)(i, j) = X(irow, j); // Gather operation
iptr++;
}
}
// Matrix-vector product with transposed submatrix
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr + nsupc]), nrow, nsupc,
OuterStride<>(lda));
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
if(Conjugate)
if (Conjugate)
U = U - A.adjoint() * work.topRows(nrow);
else
U = U - A.transpose() * work.topRows(nrow);
// Triangular solve (of transposed diagonal block)
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
if(Conjugate)
new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr]), nsupc, nsupc,
OuterStride<>(lda));
if (Conjugate)
U = A.adjoint().template triangularView<UnitUpper>().solve(U);
else
U = A.transpose().template triangularView<UnitUpper>().solve(U);
}
}
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
} // end namespace Eigen
#endif // EIGEN_SPARSELU_MATRIX_H
#endif // EIGEN_SPARSELU_MATRIX_H

View File

@@ -7,7 +7,6 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSELU_UTILS_H
#define EIGEN_SPARSELU_UTILS_H
@@ -21,63 +20,56 @@ namespace internal {
* \brief Count Nonzero elements in the factors
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu)
{
nnzL = 0;
nnzU = (glu.xusub)(n);
Index nsuper = (glu.supno)(n);
Index jlen;
Index i, j, fsupc;
if (n <= 0 ) return;
// For each supernode
for (i = 0; i <= nsuper; i++)
{
fsupc = glu.xsup(i);
jlen = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
for (j = fsupc; j < glu.xsup(i+1); j++)
{
nnzL += jlen;
nnzU += j - fsupc + 1;
jlen--;
}
}
void SparseLUImpl<Scalar, StorageIndex>::countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu) {
nnzL = 0;
nnzU = (glu.xusub)(n);
Index nsuper = (glu.supno)(n);
Index jlen;
Index i, j, fsupc;
if (n <= 0) return;
// For each supernode
for (i = 0; i <= nsuper; i++) {
fsupc = glu.xsup(i);
jlen = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
for (j = fsupc; j < glu.xsup(i + 1); j++) {
nnzL += jlen;
nnzU += j - fsupc + 1;
jlen--;
}
}
}
/**
* \brief Fix up the data storage lsub for L-subscripts.
*
* It removes the subscripts sets for structural pruning,
* \brief Fix up the data storage lsub for L-subscripts.
*
* It removes the subscripts sets for structural pruning,
* and applies permutation to the remaining subscripts
*
*
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu)
{
Index fsupc, i, j, k, jstart;
StorageIndex nextl = 0;
Index nsuper = (glu.supno)(n);
// For each supernode
for (i = 0; i <= nsuper; i++)
{
fsupc = glu.xsup(i);
jstart = glu.xlsub(fsupc);
glu.xlsub(fsupc) = nextl;
for (j = jstart; j < glu.xlsub(fsupc + 1); j++)
{
glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
void SparseLUImpl<Scalar, StorageIndex>::fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu) {
Index fsupc, i, j, k, jstart;
StorageIndex nextl = 0;
Index nsuper = (glu.supno)(n);
// For each supernode
for (i = 0; i <= nsuper; i++) {
fsupc = glu.xsup(i);
jstart = glu.xlsub(fsupc);
glu.xlsub(fsupc) = nextl;
for (j = jstart; j < glu.xlsub(fsupc + 1); j++) {
glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
nextl++;
}
for (k = fsupc+1; k < glu.xsup(i+1); k++)
glu.xlsub(k) = nextl; // other columns in supernode i
for (k = fsupc + 1; k < glu.xsup(i + 1); k++) glu.xlsub(k) = nextl; // other columns in supernode i
}
glu.xlsub(n) = nextl;
glu.xlsub(n) = nextl;
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_SPARSELU_UTILS_H
} // end namespace Eigen
#endif // EIGEN_SPARSELU_UTILS_H

View File

@@ -8,10 +8,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of xcolumn_bmod.c file in SuperLU
/*
* NOTE: This file is the modified version of xcolumn_bmod.c file in SuperLU
* -- SuperLU routine (version 3.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -39,146 +39,139 @@ namespace Eigen {
namespace internal {
/**
* \brief Performs numeric block updates (sup-col) in topological order
*
*
* \param jcol current column to update
* \param nseg Number of segments in the U part
* \param dense Store the full representation of the column
* \param tempv working array
* \param tempv working array
* \param segrep segment representative ...
* \param repfnz ??? First nonzero column in each row ??? ...
* \param fpanelc First column in the current panel
* \param glu Global LU data.
* \return 0 - successful return
* \param glu Global LU data.
* \return 0 - successful return
* > 0 - number of bytes allocated when run out of space
*
*
*/
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar,StorageIndex>::column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv,
BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu)
{
Index jsupno, k, ksub, krep, ksupno;
Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
Index SparseLUImpl<Scalar, StorageIndex>::column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense,
ScalarVector& tempv, BlockIndexVector segrep,
BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu) {
Index jsupno, k, ksub, krep, ksupno;
Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
/* krep = representative of current k-th supernode
* fsupc = first supernodal column
* nsupc = number of columns in a supernode
* nsupr = number of rows in a supernode
* luptr = location of supernodal LU-block in storage
* kfnz = first nonz in the k-th supernodal segment
* no_zeros = no lf leading zeros in a supernodal U-segment
*/
* fsupc = first supernodal column
* nsupc = number of columns in a supernode
* nsupr = number of rows in a supernode
* luptr = location of supernodal LU-block in storage
* kfnz = first nonz in the k-th supernodal segment
* no_zeros = no lf leading zeros in a supernodal U-segment
*/
jsupno = glu.supno(jcol);
// For each nonzero supernode segment of U[*,j] in topological order
k = nseg - 1;
Index d_fsupc; // distance between the first column of the current panel and the
// first column of the current snode
Index fst_col; // First column within small LU update
Index segsize;
for (ksub = 0; ksub < nseg; ksub++)
{
krep = segrep(k); k--;
ksupno = glu.supno(krep);
if (jsupno != ksupno )
{
// outside the rectangular supernode
fsupc = glu.xsup(ksupno);
fst_col = (std::max)(fsupc, fpanelc);
// Distance from the current supernode to the current panel;
// For each nonzero supernode segment of U[*,j] in topological order
k = nseg - 1;
Index d_fsupc; // distance between the first column of the current panel and the
// first column of the current snode
Index fst_col; // First column within small LU update
Index segsize;
for (ksub = 0; ksub < nseg; ksub++) {
krep = segrep(k);
k--;
ksupno = glu.supno(krep);
if (jsupno != ksupno) {
// outside the rectangular supernode
fsupc = glu.xsup(ksupno);
fst_col = (std::max)(fsupc, fpanelc);
// Distance from the current supernode to the current panel;
// d_fsupc = 0 if fsupc > fpanelc
d_fsupc = fst_col - fsupc;
luptr = glu.xlusup(fst_col) + d_fsupc;
lptr = glu.xlsub(fsupc) + d_fsupc;
kfnz = repfnz(krep);
kfnz = (std::max)(kfnz, fpanelc);
segsize = krep - kfnz + 1;
nsupc = krep - fst_col + 1;
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
d_fsupc = fst_col - fsupc;
luptr = glu.xlusup(fst_col) + d_fsupc;
lptr = glu.xlsub(fsupc) + d_fsupc;
kfnz = repfnz(krep);
kfnz = (std::max)(kfnz, fpanelc);
segsize = krep - kfnz + 1;
nsupc = krep - fst_col + 1;
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
nrow = nsupr - d_fsupc - nsupc;
Index lda = glu.xlusup(fst_col+1) - glu.xlusup(fst_col);
// Perform a triangular solver and block update,
Index lda = glu.xlusup(fst_col + 1) - glu.xlusup(fst_col);
// Perform a triangular solver and block update,
// then scatter the result of sup-col update to dense
no_zeros = kfnz - fst_col;
if(segsize==1)
no_zeros = kfnz - fst_col;
if (segsize == 1)
LU_kernel_bmod<1>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else
LU_kernel_bmod<Dynamic>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
} // end if jsupno
} // end for each segment
} // end if jsupno
} // end for each segment
// Process the supernodal portion of L\U[*,j]
nextlu = glu.xlusup(jcol);
nextlu = glu.xlusup(jcol);
fsupc = glu.xsup(jsupno);
// copy the SPA dense into L\U[*,j]
Index mem;
new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
Index mem;
new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
Index offset = internal::first_multiple<Index>(new_next, internal::packet_traits<Scalar>::size) - new_next;
if(offset)
new_next += offset;
while (new_next > glu.nzlumax )
{
mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
if (mem) return mem;
if (offset) new_next += offset;
while (new_next > glu.nzlumax) {
mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
if (mem) return mem;
}
for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc+1); isub++)
{
for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc + 1); isub++) {
irow = glu.lsub(isub);
glu.lusup(nextlu) = dense(irow);
dense(irow) = Scalar(0.0);
++nextlu;
dense(irow) = Scalar(0.0);
++nextlu;
}
if(offset)
{
glu.lusup.segment(nextlu,offset).setZero();
if (offset) {
glu.lusup.segment(nextlu, offset).setZero();
nextlu += offset;
}
glu.xlusup(jcol + 1) = StorageIndex(nextlu); // close L\U(*,jcol);
glu.xlusup(jcol + 1) = StorageIndex(nextlu); // close L\U(*,jcol);
/* For more updates within the panel (also within the current supernode),
* should start from the first column of the panel, or the first column
* of the supernode, whichever is bigger. There are two cases:
* 1) fsupc < fpanelc, then fst_col <-- fpanelc
* 2) fsupc >= fpanelc, then fst_col <-- fsupc
*/
fst_col = (std::max)(fsupc, fpanelc);
if (fst_col < jcol)
{
fst_col = (std::max)(fsupc, fpanelc);
if (fst_col < jcol) {
// Distance between the current supernode and the current panel
// d_fsupc = 0 if fsupc >= fpanelc
d_fsupc = fst_col - fsupc;
lptr = glu.xlsub(fsupc) + d_fsupc;
luptr = glu.xlusup(fst_col) + d_fsupc;
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc); // leading dimension
nsupc = jcol - fst_col; // excluding jcol
nrow = nsupr - d_fsupc - nsupc;
// points to the beginning of jcol in snode L\U(jsupno)
ufirst = glu.xlusup(jcol) + d_fsupc;
Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
MappedMatrixBlock A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
u = A.template triangularView<UnitLower>().solve(u);
new (&A) MappedMatrixBlock ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
d_fsupc = fst_col - fsupc;
lptr = glu.xlsub(fsupc) + d_fsupc;
luptr = glu.xlusup(fst_col) + d_fsupc;
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); // leading dimension
nsupc = jcol - fst_col; // excluding jcol
nrow = nsupr - d_fsupc - nsupc;
// points to the beginning of jcol in snode L\U(jsupno)
ufirst = glu.xlusup(jcol) + d_fsupc;
Index lda = glu.xlusup(jcol + 1) - glu.xlusup(jcol);
MappedMatrixBlock A(&(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda));
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
u = A.template triangularView<UnitLower>().solve(u);
new (&A) MappedMatrixBlock(&(glu.lusup.data()[luptr + nsupc]), nrow, nsupc, OuterStride<>(lda));
VectorBlock<ScalarVector> l(glu.lusup, ufirst + nsupc, nrow);
l.noalias() -= A * u;
} // End if fst_col
return 0;
} // End if fst_col
return 0;
}
} // end namespace internal
} // end namespace Eigen
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_COLUMN_BMOD_H
#endif // SPARSELU_COLUMN_BMOD_H

View File

@@ -7,10 +7,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]column_dfs.c file in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]column_dfs.c file in SuperLU
* -- SuperLU routine (version 2.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -30,7 +30,8 @@
#ifndef SPARSELU_COLUMN_DFS_H
#define SPARSELU_COLUMN_DFS_H
template <typename Scalar, typename StorageIndex> class SparseLUImpl;
template <typename Scalar, typename StorageIndex>
class SparseLUImpl;
// IWYU pragma: private
#include "./InternalHeaderCheck.h"
@@ -38,145 +39,130 @@ namespace Eigen {
namespace internal {
template<typename IndexVector, typename ScalarVector>
struct column_dfs_traits : no_assignment_operator
{
template <typename IndexVector, typename ScalarVector>
struct column_dfs_traits : no_assignment_operator {
typedef typename ScalarVector::Scalar Scalar;
typedef typename IndexVector::Scalar StorageIndex;
column_dfs_traits(Index jcol, Index& jsuper, typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& glu, SparseLUImpl<Scalar, StorageIndex>& luImpl)
: m_jcol(jcol), m_jsuper_ref(jsuper), m_glu(glu), m_luImpl(luImpl)
{}
bool update_segrep(Index /*krep*/, Index /*jj*/)
{
return true;
}
void mem_expand(IndexVector& lsub, Index& nextl, Index chmark)
{
if (nextl >= m_glu.nzlmax)
m_luImpl.memXpand(lsub, m_glu.nzlmax, nextl, LSUB, m_glu.num_expansions);
if (chmark != (m_jcol-1)) m_jsuper_ref = emptyIdxLU;
column_dfs_traits(Index jcol, Index& jsuper, typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& glu,
SparseLUImpl<Scalar, StorageIndex>& luImpl)
: m_jcol(jcol), m_jsuper_ref(jsuper), m_glu(glu), m_luImpl(luImpl) {}
bool update_segrep(Index /*krep*/, Index /*jj*/) { return true; }
void mem_expand(IndexVector& lsub, Index& nextl, Index chmark) {
if (nextl >= m_glu.nzlmax) m_luImpl.memXpand(lsub, m_glu.nzlmax, nextl, LSUB, m_glu.num_expansions);
if (chmark != (m_jcol - 1)) m_jsuper_ref = emptyIdxLU;
}
enum { ExpandMem = true };
Index m_jcol;
Index& m_jsuper_ref;
typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& m_glu;
SparseLUImpl<Scalar, StorageIndex>& m_luImpl;
};
/**
* \brief Performs a symbolic factorization on column jcol and decide the supernode boundary
*
*
* A supernode representative is the last column of a supernode.
* The nonzeros in U[*,j] are segments that end at supernodes representatives.
* The routine returns a list of the supernodal representatives
* in topological order of the dfs that generates them.
* The location of the first nonzero in each supernodal segment
* (supernodal entry location) is also returned.
*
* The nonzeros in U[*,j] are segments that end at supernodes representatives.
* The routine returns a list of the supernodal representatives
* in topological order of the dfs that generates them.
* The location of the first nonzero in each supernodal segment
* (supernodal entry location) is also returned.
*
* \param m number of rows in the matrix
* \param jcol Current column
* \param jcol Current column
* \param perm_r Row permutation
* \param maxsuper Maximum number of column allowed in a supernode
* \param [in,out] nseg Number of segments in current U[*,j] - new segments appended
* \param lsub_col defines the rhs vector to start the dfs
* \param [in,out] segrep Segment representatives - new segments appended
* \param [in,out] segrep Segment representatives - new segments appended
* \param repfnz First nonzero location in each row
* \param xprune
* \param xprune
* \param marker marker[i] == jj, if i was visited during dfs of current column jj;
* \param parent
* \param xplore working array
* \param glu global LU data
* \param glu global LU data
* \return 0 success
* > 0 number of bytes allocated when run out of space
*
*
*/
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar,StorageIndex>::column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg,
BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
{
Index jsuper = glu.supno(jcol);
Index nextl = glu.xlsub(jcol);
VectorBlock<IndexVector> marker2(marker, 2*m, m);
Index SparseLUImpl<Scalar, StorageIndex>::column_dfs(const Index m, const Index jcol, IndexVector& perm_r,
Index maxsuper, Index& nseg, BlockIndexVector lsub_col,
IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
IndexVector& marker, IndexVector& parent, IndexVector& xplore,
GlobalLU_t& glu) {
Index jsuper = glu.supno(jcol);
Index nextl = glu.xlsub(jcol);
VectorBlock<IndexVector> marker2(marker, 2 * m, m);
column_dfs_traits<IndexVector, ScalarVector> traits(jcol, jsuper, glu, *this);
// For each nonzero in A(*,jcol) do dfs
for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false) ; k++)
{
Index krow = lsub_col(k);
lsub_col(k) = emptyIdxLU;
Index kmark = marker2(krow);
// krow was visited before, go to the next nonz;
// For each nonzero in A(*,jcol) do dfs
for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false); k++) {
Index krow = lsub_col(k);
lsub_col(k) = emptyIdxLU;
Index kmark = marker2(krow);
// krow was visited before, go to the next nonz;
if (kmark == jcol) continue;
dfs_kernel(StorageIndex(jcol), perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent,
xplore, glu, nextl, krow, traits);
} // for each nonzero ...
dfs_kernel(StorageIndex(jcol), perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent, xplore, glu, nextl,
krow, traits);
} // for each nonzero ...
Index fsupc;
StorageIndex nsuper = glu.supno(jcol);
StorageIndex jcolp1 = StorageIndex(jcol) + 1;
Index jcolm1 = jcol - 1;
// check to see if j belongs in the same supernode as j-1
if ( jcol == 0 )
{ // Do nothing for column 0
nsuper = glu.supno(0) = 0 ;
}
else
{
fsupc = glu.xsup(nsuper);
StorageIndex jptr = glu.xlsub(jcol); // Not yet compressed
StorageIndex jm1ptr = glu.xlsub(jcolm1);
if (jcol == 0) { // Do nothing for column 0
nsuper = glu.supno(0) = 0;
} else {
fsupc = glu.xsup(nsuper);
StorageIndex jptr = glu.xlsub(jcol); // Not yet compressed
StorageIndex jm1ptr = glu.xlsub(jcolm1);
// Use supernodes of type T2 : see SuperLU paper
if ( (nextl-jptr != jptr-jm1ptr-1) ) jsuper = emptyIdxLU;
if ((nextl - jptr != jptr - jm1ptr - 1)) jsuper = emptyIdxLU;
// Make sure the number of columns in a supernode doesn't
// exceed threshold
if ( (jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
if ((jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
/* If jcol starts a new supernode, reclaim storage space in
* glu.lsub from previous supernode. Note we only store
* the subscript set of the first and last columns of
* glu.lsub from previous supernode. Note we only store
* the subscript set of the first and last columns of
* a supernode. (first for num values, last for pruning)
*/
if (jsuper == emptyIdxLU)
{ // starts a new supernode
if ( (fsupc < jcolm1-1) )
{ // >= 3 columns in nsuper
StorageIndex ito = glu.xlsub(fsupc+1);
glu.xlsub(jcolm1) = ito;
StorageIndex istop = ito + jptr - jm1ptr;
xprune(jcolm1) = istop; // initialize xprune(jcol-1)
glu.xlsub(jcol) = istop;
for (StorageIndex ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito)
glu.lsub(ito) = glu.lsub(ifrom);
if (jsuper == emptyIdxLU) { // starts a new supernode
if ((fsupc < jcolm1 - 1)) { // >= 3 columns in nsuper
StorageIndex ito = glu.xlsub(fsupc + 1);
glu.xlsub(jcolm1) = ito;
StorageIndex istop = ito + jptr - jm1ptr;
xprune(jcolm1) = istop; // initialize xprune(jcol-1)
glu.xlsub(jcol) = istop;
for (StorageIndex ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito) glu.lsub(ito) = glu.lsub(ifrom);
nextl = ito; // = istop + length(jcol)
}
nsuper++;
glu.supno(jcol) = nsuper;
} // if a new supernode
} // end else: jcol > 0
nsuper++;
glu.supno(jcol) = nsuper;
} // if a new supernode
} // end else: jcol > 0
// Tidy up the pointers before exit
glu.xsup(nsuper+1) = jcolp1;
glu.supno(jcolp1) = nsuper;
glu.xsup(nsuper + 1) = jcolp1;
glu.supno(jcolp1) = nsuper;
xprune(jcol) = StorageIndex(nextl); // Initialize upper bound for pruning
glu.xlsub(jcolp1) = StorageIndex(nextl);
return 0;
glu.xlsub(jcolp1) = StorageIndex(nextl);
return 0;
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
} // end namespace Eigen
#endif

View File

@@ -6,10 +6,10 @@
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU
* -- SuperLU routine (version 2.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -37,74 +37,70 @@ namespace internal {
/**
* \brief Performs numeric block updates (sup-col) in topological order
*
*
* \param jcol current column to update
* \param nseg Number of segments in the U part
* \param segrep segment representative ...
* \param repfnz First nonzero column in each row ...
* \param perm_r Row permutation
* \param perm_r Row permutation
* \param dense Store the full representation of the column
* \param glu Global LU data.
* \return 0 - successful return
* \param glu Global LU data.
* \return 0 - successful return
* > 0 - number of bytes allocated when run out of space
*
*
*/
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar,StorageIndex>::copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep,
BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu)
{
Index ksub, krep, ksupno;
Index SparseLUImpl<Scalar, StorageIndex>::copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep,
BlockIndexVector repfnz, IndexVector& perm_r,
BlockScalarVector dense, GlobalLU_t& glu) {
Index ksub, krep, ksupno;
Index jsupno = glu.supno(jcol);
// For each nonzero supernode segment of U[*,j] in topological order
Index k = nseg - 1, i;
StorageIndex nextu = glu.xusub(jcol);
Index kfnz, isub, segsize;
Index new_next,irow;
Index fsupc, mem;
for (ksub = 0; ksub < nseg; ksub++)
{
krep = segrep(k); k--;
ksupno = glu.supno(krep);
if (jsupno != ksupno ) // should go into ucol();
// For each nonzero supernode segment of U[*,j] in topological order
Index k = nseg - 1, i;
StorageIndex nextu = glu.xusub(jcol);
Index kfnz, isub, segsize;
Index new_next, irow;
Index fsupc, mem;
for (ksub = 0; ksub < nseg; ksub++) {
krep = segrep(k);
k--;
ksupno = glu.supno(krep);
if (jsupno != ksupno) // should go into ucol();
{
kfnz = repfnz(krep);
if (kfnz != emptyIdxLU)
{ // Nonzero U-segment
fsupc = glu.xsup(ksupno);
isub = glu.xlsub(fsupc) + kfnz - fsupc;
segsize = krep - kfnz + 1;
new_next = nextu + segsize;
while (new_next > glu.nzumax)
{
mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
if (mem) return mem;
mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
if (mem) return mem;
kfnz = repfnz(krep);
if (kfnz != emptyIdxLU) { // Nonzero U-segment
fsupc = glu.xsup(ksupno);
isub = glu.xlsub(fsupc) + kfnz - fsupc;
segsize = krep - kfnz + 1;
new_next = nextu + segsize;
while (new_next > glu.nzumax) {
mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
if (mem) return mem;
mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
if (mem) return mem;
}
for (i = 0; i < segsize; i++)
{
irow = glu.lsub(isub);
glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
glu.ucol(nextu) = dense(irow);
dense(irow) = Scalar(0.0);
for (i = 0; i < segsize; i++) {
irow = glu.lsub(isub);
glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
glu.ucol(nextu) = dense(irow);
dense(irow) = Scalar(0.0);
nextu++;
isub++;
}
} // end nonzero U-segment
} // end if jsupno
} // end for each segment
glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
return 0;
} // end nonzero U-segment
} // end if jsupno
} // end for each segment
glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
return 0;
}
} // namespace internal
} // end namespace Eigen
} // namespace internal
} // end namespace Eigen
#endif // SPARSELU_COPY_TO_UCOL_H
#endif // SPARSELU_COPY_TO_UCOL_H

View File

@@ -34,77 +34,67 @@
namespace Eigen {
namespace internal {
/**
/**
* \brief Identify the initial relaxed supernodes
*
* This routine applied to a symmetric elimination tree.
*
* This routine applied to a symmetric elimination tree.
* It assumes that the matrix has been reordered according to the postorder of the etree
* \param n The number of columns
* \param et elimination tree
* \param relax_columns Maximum number of columns allowed in a relaxed snode
* \param et elimination tree
* \param relax_columns Maximum number of columns allowed in a relaxed snode
* \param descendants Number of descendants of each node in the etree
* \param relax_end last column in a supernode
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
{
// The etree may not be postordered, but its heap ordered
void SparseLUImpl<Scalar, StorageIndex>::heap_relax_snode(const Index n, IndexVector& et, const Index relax_columns,
IndexVector& descendants, IndexVector& relax_end) {
// The etree may not be postordered, but its heap ordered
IndexVector post;
internal::treePostorder(StorageIndex(n), et, post); // Post order etree
IndexVector inv_post(n+1);
for (StorageIndex i = 0; i < n+1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
// Renumber etree in postorder
internal::treePostorder(StorageIndex(n), et, post); // Post order etree
IndexVector inv_post(n + 1);
for (StorageIndex i = 0; i < n + 1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
// Renumber etree in postorder
IndexVector iwork(n);
IndexVector et_save(n+1);
for (Index i = 0; i < n; ++i)
{
IndexVector et_save(n + 1);
for (Index i = 0; i < n; ++i) {
iwork(post(i)) = post(et(i));
}
et_save = et; // Save the original etree
et = iwork;
et_save = et; // Save the original etree
et = iwork;
// compute the number of descendants of each node in the etree
relax_end.setConstant(emptyIdxLU);
Index j, parent;
Index j, parent;
descendants.setZero();
for (j = 0; j < n; j++)
{
for (j = 0; j < n; j++) {
parent = et(j);
if (parent != n) // not the dummy root
if (parent != n) // not the dummy root
descendants(parent) += descendants(j) + 1;
}
// Identify the relaxed supernodes by postorder traversal of the etree
Index snode_start; // beginning of a snode
Index snode_start; // beginning of a snode
StorageIndex k;
StorageIndex l;
for (j = 0; j < n; )
{
StorageIndex l;
for (j = 0; j < n;) {
parent = et(j);
snode_start = j;
while ( parent != n && descendants(parent) < relax_columns )
{
j = parent;
snode_start = j;
while (parent != n && descendants(parent) < relax_columns) {
j = parent;
parent = et(j);
}
// Found a supernode in postordered etree, j is the last column
// Found a supernode in postordered etree, j is the last column
k = StorageIndex(n);
for (Index i = snode_start; i <= j; ++i)
k = (std::min)(k, inv_post(i));
for (Index i = snode_start; i <= j; ++i) k = (std::min)(k, inv_post(i));
l = inv_post(j);
if ( (l - k) == (j - snode_start) ) // Same number of columns in the snode
if ((l - k) == (j - snode_start)) // Same number of columns in the snode
{
// This is also a supernode in the original etree
relax_end(k) = l; // Record last column
}
else
{
for (Index i = snode_start; i <= j; ++i)
{
relax_end(k) = l; // Record last column
} else {
for (Index i = snode_start; i <= j; ++i) {
l = inv_post(i);
if (descendants(i) == 0)
{
if (descendants(i) == 0) {
relax_end(l) = l;
}
}
@@ -112,13 +102,13 @@ void SparseLUImpl<Scalar,StorageIndex>::heap_relax_snode (const Index n, IndexVe
j++;
// Search for a new leaf
while (descendants(j) != 0 && j < n) j++;
} // End postorder traversal of the etree
} // End postorder traversal of the etree
// Recover the original etree
et = et_save;
et = et_save;
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_HEAP_RELAX_SNODE_H
} // end namespace Eigen
#endif // SPARSELU_HEAP_RELAX_SNODE_H

View File

@@ -16,117 +16,118 @@
namespace Eigen {
namespace internal {
template <int SegSizeAtCompileTime> struct LU_kernel_bmod
{
template <int SegSizeAtCompileTime>
struct LU_kernel_bmod {
/** \internal
* \brief Performs numeric block updates from a given supernode to a single column
*
* \param segsize Size of the segment (and blocks ) to use for updates
* \param[in,out] dense Packed values of the original matrix
* \param tempv temporary vector to use for updates
* \param lusup array containing the supernodes
* \param lda Leading dimension in the supernode
* \param nrow Number of rows in the rectangular part of the supernode
* \param lsub compressed row subscripts of supernodes
* \param lptr pointer to the first column of the current supernode in lsub
* \param no_zeros Number of nonzeros elements before the diagonal part of the supernode
*/
* \brief Performs numeric block updates from a given supernode to a single column
*
* \param segsize Size of the segment (and blocks ) to use for updates
* \param[in,out] dense Packed values of the original matrix
* \param tempv temporary vector to use for updates
* \param lusup array containing the supernodes
* \param lda Leading dimension in the supernode
* \param nrow Number of rows in the rectangular part of the supernode
* \param lsub compressed row subscripts of supernodes
* \param lptr pointer to the first column of the current supernode in lsub
* \param no_zeros Number of nonzeros elements before the diagonal part of the supernode
*/
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
static EIGEN_DONT_INLINE void run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
static EIGEN_DONT_INLINE void run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv,
ScalarVector& lusup, Index& luptr, const Index lda, const Index nrow,
IndexVector& lsub, const Index lptr, const Index no_zeros);
};
template <int SegSizeAtCompileTime>
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
{
EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const Index segsize, BlockScalarVector& dense,
ScalarVector& tempv, ScalarVector& lusup, Index& luptr,
const Index lda, const Index nrow, IndexVector& lsub,
const Index lptr, const Index no_zeros) {
typedef typename ScalarVector::Scalar Scalar;
// First, copy U[*,j] segment from dense(*) to tempv(*)
// The result of triangular solve is in tempv[*];
// The result of matric-vector update is in dense[*]
Index isub = lptr + no_zeros;
// The result of triangular solve is in tempv[*];
// The result of matric-vector update is in dense[*]
Index isub = lptr + no_zeros;
Index i;
Index irow;
for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
{
irow = lsub(isub);
tempv(i) = dense(irow);
++isub;
for (i = 0; i < ((SegSizeAtCompileTime == Dynamic) ? segsize : SegSizeAtCompileTime); i++) {
irow = lsub(isub);
tempv(i) = dense(irow);
++isub;
}
// Dense triangular solve -- start effective triangle
luptr += lda * no_zeros + no_zeros;
// Form Eigen matrix and vector
Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
u = A.template triangularView<UnitLower>().solve(u);
// Dense matrix-vector product y <-- B*x
luptr += lda * no_zeros + no_zeros;
// Form Eigen matrix and vector
Map<Matrix<Scalar, SegSizeAtCompileTime, SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A(
&(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda));
Map<Matrix<Scalar, SegSizeAtCompileTime, 1> > u(tempv.data(), segsize);
u = A.template triangularView<UnitLower>().solve(u);
// Dense matrix-vector product y <-- B*x
luptr += segsize;
const Index PacketSize = internal::packet_traits<Scalar>::size;
Index ldl = internal::first_multiple(nrow, PacketSize);
Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
Index aligned_offset = internal::first_default_aligned(tempv.data()+segsize, PacketSize);
Index aligned_with_B_offset = (PacketSize-internal::first_default_aligned(B.data(), PacketSize))%PacketSize;
Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
Map<Matrix<Scalar, Dynamic, SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B(&(lusup.data()[luptr]), nrow,
segsize, OuterStride<>(lda));
Index aligned_offset = internal::first_default_aligned(tempv.data() + segsize, PacketSize);
Index aligned_with_B_offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
Map<Matrix<Scalar, Dynamic, 1>, 0, OuterStride<> > l(tempv.data() + segsize + aligned_offset + aligned_with_B_offset,
nrow, OuterStride<>(ldl));
l.noalias() = B * u;
// Scatter tempv[] into SPA dense[] as a temporary storage
// Scatter tempv[] into SPA dense[] as a temporary storage
isub = lptr + no_zeros;
for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
{
irow = lsub(isub++);
for (i = 0; i < ((SegSizeAtCompileTime == Dynamic) ? segsize : SegSizeAtCompileTime); i++) {
irow = lsub(isub++);
dense(irow) = tempv(i);
}
// Scatter l into SPA dense[]
for (i = 0; i < nrow; i++)
{
irow = lsub(isub++);
for (i = 0; i < nrow; i++) {
irow = lsub(isub++);
dense(irow) -= l(i);
}
}
}
template <> struct LU_kernel_bmod<1>
{
template <>
struct LU_kernel_bmod<1> {
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
static EIGEN_DONT_INLINE void run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
static EIGEN_DONT_INLINE void run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/,
ScalarVector& lusup, Index& luptr, const Index lda, const Index nrow,
IndexVector& lsub, const Index lptr, const Index no_zeros);
};
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
EIGEN_DONT_INLINE void LU_kernel_bmod<1>::run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
{
EIGEN_DONT_INLINE void LU_kernel_bmod<1>::run(const Index /*segsize*/, BlockScalarVector& dense,
ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr,
const Index no_zeros) {
typedef typename ScalarVector::Scalar Scalar;
typedef typename IndexVector::Scalar StorageIndex;
Scalar f = dense(lsub(lptr + no_zeros));
luptr += lda * no_zeros + no_zeros + 1;
const Scalar* a(lusup.data() + luptr);
const StorageIndex* irow(lsub.data()+lptr + no_zeros + 1);
const StorageIndex* irow(lsub.data() + lptr + no_zeros + 1);
Index i = 0;
for (; i+1 < nrow; i+=2)
{
for (; i + 1 < nrow; i += 2) {
Index i0 = *(irow++);
Index i1 = *(irow++);
Scalar a0 = *(a++);
Scalar a1 = *(a++);
Scalar d0 = dense.coeff(i0);
Scalar d1 = dense.coeff(i1);
d0 -= f*a0;
d1 -= f*a1;
d0 -= f * a0;
d1 -= f * a1;
dense.coeffRef(i0) = d0;
dense.coeffRef(i1) = d1;
}
if(i<nrow)
dense.coeffRef(*(irow++)) -= f * *(a++);
if (i < nrow) dense.coeffRef(*(irow++)) -= f * *(a++);
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_KERNEL_BMOD_H
} // end namespace Eigen
#endif // SPARSELU_KERNEL_BMOD_H

View File

@@ -8,10 +8,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU
* -- SuperLU routine (version 3.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -39,187 +39,177 @@ namespace internal {
/**
* \brief Performs numeric block updates (sup-panel) in topological order.
*
*
* Before entering this routine, the original nonzeros in the panel
* were already copied into the spa[m,w]
*
*
* \param m number of rows in the matrix
* \param w Panel size
* \param jcol Starting column of the panel
* \param nseg Number of segments in the U part
* \param dense Store the full representation of the panel
* \param tempv working array
* \param dense Store the full representation of the panel
* \param tempv working array
* \param segrep segment representative... first row in the segment
* \param repfnz First nonzero rows
* \param glu Global LU data.
*
*
* \param glu Global LU data.
*
*
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::panel_bmod(const Index m, const Index w, const Index jcol,
const Index nseg, ScalarVector& dense, ScalarVector& tempv,
IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu)
{
Index ksub,jj,nextl_col;
Index fsupc, nsupc, nsupr, nrow;
Index krep, kfnz;
Index lptr; // points to the row subscripts of a supernode
Index luptr; // ...
Index segsize,no_zeros ;
void SparseLUImpl<Scalar, StorageIndex>::panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg,
ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep,
IndexVector& repfnz, GlobalLU_t& glu) {
Index ksub, jj, nextl_col;
Index fsupc, nsupc, nsupr, nrow;
Index krep, kfnz;
Index lptr; // points to the row subscripts of a supernode
Index luptr; // ...
Index segsize, no_zeros;
// For each nonz supernode segment of U[*,j] in topological order
Index k = nseg - 1;
Index k = nseg - 1;
const Index PacketSize = internal::packet_traits<Scalar>::size;
for (ksub = 0; ksub < nseg; ksub++)
{ // For each updating supernode
for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode
/* krep = representative of current k-th supernode
* fsupc = first supernodal column
* nsupc = number of columns in a supernode
* nsupr = number of rows in a supernode
*/
krep = segrep(k); k--;
fsupc = glu.xsup(glu.supno(krep));
nsupc = krep - fsupc + 1;
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
nrow = nsupr - nsupc;
lptr = glu.xlsub(fsupc);
krep = segrep(k);
k--;
fsupc = glu.xsup(glu.supno(krep));
nsupc = krep - fsupc + 1;
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
nrow = nsupr - nsupc;
lptr = glu.xlsub(fsupc);
// loop over the panel columns to detect the actual number of columns and rows
Index u_rows = 0;
Index u_cols = 0;
for (jj = jcol; jj < jcol + w; jj++)
{
nextl_col = (jj-jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
kfnz = repfnz_col(krep);
if ( kfnz == emptyIdxLU )
continue; // skip any zero segment
for (jj = jcol; jj < jcol + w; jj++) {
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
kfnz = repfnz_col(krep);
if (kfnz == emptyIdxLU) continue; // skip any zero segment
segsize = krep - kfnz + 1;
u_cols++;
u_rows = (std::max)(segsize,u_rows);
u_rows = (std::max)(segsize, u_rows);
}
if(nsupc >= 2)
{
if (nsupc >= 2) {
Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
// gather U
Index u_col = 0;
for (jj = jcol; jj < jcol + w; jj++)
{
nextl_col = (jj-jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if ( kfnz == emptyIdxLU )
continue; // skip any zero segment
for (jj = jcol; jj < jcol + w; jj++) {
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if (kfnz == emptyIdxLU) continue; // skip any zero segment
segsize = krep - kfnz + 1;
luptr = glu.xlusup(fsupc);
no_zeros = kfnz - fsupc;
luptr = glu.xlusup(fsupc);
no_zeros = kfnz - fsupc;
Index isub = lptr + no_zeros;
Index off = u_rows-segsize;
for (Index i = 0; i < off; i++) U(i,u_col) = 0;
for (Index i = 0; i < segsize; i++)
{
Index irow = glu.lsub(isub);
U(i+off,u_col) = dense_col(irow);
++isub;
Index off = u_rows - segsize;
for (Index i = 0; i < off; i++) U(i, u_col) = 0;
for (Index i = 0; i < segsize; i++) {
Index irow = glu.lsub(isub);
U(i + off, u_col) = dense_col(irow);
++isub;
}
u_col++;
}
// solve U = A^-1 U
luptr = glu.xlusup(fsupc);
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc);
no_zeros = (krep - u_rows + 1) - fsupc;
luptr += lda * no_zeros + no_zeros;
MappedMatrixBlock A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda));
U = A.template triangularView<UnitLower>().solve(U);
// update
luptr += u_rows;
MappedMatrixBlock B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda));
eigen_assert(tempv.size() > w * ldu + nrow * w + 1);
Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
Index offset = (PacketSize-internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
MappedMatrixBlock L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl));
L.noalias() = B * U;
// scatter U and L
u_col = 0;
for (jj = jcol; jj < jcol + w; jj++)
{
nextl_col = (jj-jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if ( kfnz == emptyIdxLU )
continue; // skip any zero segment
for (jj = jcol; jj < jcol + w; jj++) {
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if (kfnz == emptyIdxLU) continue; // skip any zero segment
segsize = krep - kfnz + 1;
no_zeros = kfnz - fsupc;
no_zeros = kfnz - fsupc;
Index isub = lptr + no_zeros;
Index off = u_rows-segsize;
for (Index i = 0; i < segsize; i++)
{
Index irow = glu.lsub(isub++);
dense_col(irow) = U.coeff(i+off,u_col);
U.coeffRef(i+off,u_col) = 0;
Index off = u_rows - segsize;
for (Index i = 0; i < segsize; i++) {
Index irow = glu.lsub(isub++);
dense_col(irow) = U.coeff(i + off, u_col);
U.coeffRef(i + off, u_col) = 0;
}
// Scatter l into SPA dense[]
for (Index i = 0; i < nrow; i++)
{
Index irow = glu.lsub(isub++);
dense_col(irow) -= L.coeff(i,u_col);
L.coeffRef(i,u_col) = 0;
for (Index i = 0; i < nrow; i++) {
Index irow = glu.lsub(isub++);
dense_col(irow) -= L.coeff(i, u_col);
L.coeffRef(i, u_col) = 0;
}
u_col++;
}
}
else // level 2 only
} else // level 2 only
{
// Sequence through each column in the panel
for (jj = jcol; jj < jcol + w; jj++)
{
nextl_col = (jj-jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if ( kfnz == emptyIdxLU )
continue; // skip any zero segment
for (jj = jcol; jj < jcol + w; jj++) {
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
kfnz = repfnz_col(krep);
if (kfnz == emptyIdxLU) continue; // skip any zero segment
segsize = krep - kfnz + 1;
luptr = glu.xlusup(fsupc);
Index lda = glu.xlusup(fsupc+1)-glu.xlusup(fsupc);// nsupr
// Perform a trianglar solve and block update,
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr
// Perform a trianglar solve and block update,
// then scatter the result of sup-col update to dense[]
no_zeros = kfnz - fsupc;
if(segsize==1) LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else if(segsize==2) LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else if(segsize==3) LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
} // End for each column in the panel
no_zeros = kfnz - fsupc;
if (segsize == 1)
LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else if (segsize == 2)
LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else if (segsize == 3)
LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
else
LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr,
no_zeros);
} // End for each column in the panel
}
} // End for each updating supernode
} // end panel bmod
} // end namespace internal
} // End for each updating supernode
} // end panel bmod
} // end namespace Eigen
} // end namespace internal
#endif // SPARSELU_PANEL_BMOD_H
} // end namespace Eigen
#endif // SPARSELU_PANEL_BMOD_H

View File

@@ -7,10 +7,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
* -- SuperLU routine (version 2.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -36,19 +36,14 @@
namespace Eigen {
namespace internal {
template<typename IndexVector>
struct panel_dfs_traits
{
template <typename IndexVector>
struct panel_dfs_traits {
typedef typename IndexVector::Scalar StorageIndex;
panel_dfs_traits(Index jcol, StorageIndex* marker)
: m_jcol(jcol), m_marker(marker)
{}
bool update_segrep(Index krep, StorageIndex jj)
{
if(m_marker[krep]<m_jcol)
{
m_marker[krep] = jj;
panel_dfs_traits(Index jcol, StorageIndex* marker) : m_jcol(jcol), m_marker(marker) {}
bool update_segrep(Index krep, StorageIndex jj) {
if (m_marker[krep] < m_jcol) {
m_marker[krep] = jj;
return true;
}
return false;
@@ -59,147 +54,127 @@ struct panel_dfs_traits
StorageIndex* m_marker;
};
template <typename Scalar, typename StorageIndex>
template <typename Traits>
void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexVector& perm_r,
Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
IndexVector& xplore, GlobalLU_t& glu,
Index& nextl_col, Index krow, Traits& traits
)
{
void SparseLUImpl<Scalar, StorageIndex>::dfs_kernel(const StorageIndex jj, IndexVector& perm_r, Index& nseg,
IndexVector& panel_lsub, IndexVector& segrep,
Ref<IndexVector> repfnz_col, IndexVector& xprune,
Ref<IndexVector> marker, IndexVector& parent, IndexVector& xplore,
GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits) {
StorageIndex kmark = marker(krow);
// For each unmarked krow of jj
marker(krow) = jj;
StorageIndex kperm = perm_r(krow);
if (kperm == emptyIdxLU ) {
marker(krow) = jj;
StorageIndex kperm = perm_r(krow);
if (kperm == emptyIdxLU) {
// krow is in L : place it in structure of L(*, jj)
panel_lsub(nextl_col++) = StorageIndex(krow); // krow is indexed into A
traits.mem_expand(panel_lsub, nextl_col, kmark);
}
else
{
} else {
// krow is in U : if its supernode-representative krep
// has been explored, update repfnz(*)
// krep = supernode representative of the current row
StorageIndex krep = glu.xsup(glu.supno(kperm)+1) - 1;
StorageIndex krep = glu.xsup(glu.supno(kperm) + 1) - 1;
// First nonzero element in the current column:
StorageIndex myfnz = repfnz_col(krep);
if (myfnz != emptyIdxLU )
{
StorageIndex myfnz = repfnz_col(krep);
if (myfnz != emptyIdxLU) {
// Representative visited before
if (myfnz > kperm ) repfnz_col(krep) = kperm;
}
else
{
if (myfnz > kperm) repfnz_col(krep) = kperm;
} else {
// Otherwise, perform dfs starting at krep
StorageIndex oldrep = emptyIdxLU;
parent(krep) = oldrep;
repfnz_col(krep) = kperm;
StorageIndex xdfs = glu.xlsub(krep);
Index maxdfs = xprune(krep);
StorageIndex oldrep = emptyIdxLU;
parent(krep) = oldrep;
repfnz_col(krep) = kperm;
StorageIndex xdfs = glu.xlsub(krep);
Index maxdfs = xprune(krep);
StorageIndex kpar;
do
{
do {
// For each unmarked kchild of krep
while (xdfs < maxdfs)
{
StorageIndex kchild = glu.lsub(xdfs);
xdfs++;
StorageIndex chmark = marker(kchild);
if (chmark != jj )
{
marker(kchild) = jj;
StorageIndex chperm = perm_r(kchild);
if (chperm == emptyIdxLU)
{
while (xdfs < maxdfs) {
StorageIndex kchild = glu.lsub(xdfs);
xdfs++;
StorageIndex chmark = marker(kchild);
if (chmark != jj) {
marker(kchild) = jj;
StorageIndex chperm = perm_r(kchild);
if (chperm == emptyIdxLU) {
// case kchild is in L: place it in L(*, j)
panel_lsub(nextl_col++) = kchild;
traits.mem_expand(panel_lsub, nextl_col, chmark);
}
else
{
} else {
// case kchild is in U :
// chrep = its supernode-rep. If its rep has been explored,
// chrep = its supernode-rep. If its rep has been explored,
// update its repfnz(*)
StorageIndex chrep = glu.xsup(glu.supno(chperm)+1) - 1;
myfnz = repfnz_col(chrep);
if (myfnz != emptyIdxLU)
{ // Visited before
if (myfnz > chperm)
repfnz_col(chrep) = chperm;
}
else
{ // Cont. dfs at snode-rep of kchild
xplore(krep) = xdfs;
oldrep = krep;
krep = chrep; // Go deeper down G(L)
parent(krep) = oldrep;
repfnz_col(krep) = chperm;
xdfs = glu.xlsub(krep);
maxdfs = xprune(krep);
} // end if myfnz != -1
} // end if chperm == -1
} // end if chmark !=jj
} // end while xdfs < maxdfs
StorageIndex chrep = glu.xsup(glu.supno(chperm) + 1) - 1;
myfnz = repfnz_col(chrep);
if (myfnz != emptyIdxLU) { // Visited before
if (myfnz > chperm) repfnz_col(chrep) = chperm;
} else { // Cont. dfs at snode-rep of kchild
xplore(krep) = xdfs;
oldrep = krep;
krep = chrep; // Go deeper down G(L)
parent(krep) = oldrep;
repfnz_col(krep) = chperm;
xdfs = glu.xlsub(krep);
maxdfs = xprune(krep);
} // end if myfnz != -1
} // end if chperm == -1
} // end if chmark !=jj
} // end while xdfs < maxdfs
// krow has no more unexplored nbrs :
// Place snode-rep krep in postorder DFS, if this
// segment is seen for the first time. (Note that
// Place snode-rep krep in postorder DFS, if this
// segment is seen for the first time. (Note that
// "repfnz(krep)" may change later.)
// Baktrack dfs to its parent
if(traits.update_segrep(krep,jj))
//if (marker1(krep) < jcol )
if (traits.update_segrep(krep, jj))
// if (marker1(krep) < jcol )
{
segrep(nseg) = krep;
++nseg;
//marker1(krep) = jj;
segrep(nseg) = krep;
++nseg;
// marker1(krep) = jj;
}
kpar = parent(krep); // Pop recursion, mimic recursion
if (kpar == emptyIdxLU)
break; // dfs done
krep = kpar;
xdfs = xplore(krep);
maxdfs = xprune(krep);
} while (kpar != emptyIdxLU); // Do until empty stack
} // end if (myfnz = -1)
kpar = parent(krep); // Pop recursion, mimic recursion
if (kpar == emptyIdxLU) break; // dfs done
krep = kpar;
xdfs = xplore(krep);
maxdfs = xprune(krep);
} // end if (kperm == -1)
} while (kpar != emptyIdxLU); // Do until empty stack
} // end if (myfnz = -1)
} // end if (kperm == -1)
}
/**
* \brief Performs a symbolic factorization on a panel of columns [jcol, jcol+w)
*
*
* A supernode representative is the last column of a supernode.
* The nonzeros in U[*,j] are segments that end at supernodes representatives
*
* The routine returns a list of the supernodal representatives
* in topological order of the dfs that generates them. This list is
* a superset of the topological order of each individual column within
*
* The routine returns a list of the supernodal representatives
* in topological order of the dfs that generates them. This list is
* a superset of the topological order of each individual column within
* the panel.
* The location of the first nonzero in each supernodal segment
* (supernodal entry location) is also returned. Each column has
* a separate list for this purpose.
*
* The location of the first nonzero in each supernodal segment
* (supernodal entry location) is also returned. Each column has
* a separate list for this purpose.
*
* Two markers arrays are used for dfs :
* marker[i] == jj, if i was visited during dfs of current column jj;
* marker1[i] >= jcol, if i was visited by earlier columns in this panel;
*
* marker1[i] >= jcol, if i was visited by earlier columns in this panel;
*
* \param[in] m number of rows in the matrix
* \param[in] w Panel size
* \param[in] jcol Starting column of the panel
@@ -207,7 +182,7 @@ void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexV
* \param[in] perm_r Row permutation
* \param[out] nseg Number of U segments
* \param[out] dense Accumulate the column vectors of the panel
* \param[out] panel_lsub Subscripts of the row in the panel
* \param[out] panel_lsub Subscripts of the row in the panel
* \param[out] segrep Segment representative i.e first nonzero row of each segment
* \param[out] repfnz First nonzero location in each row
* \param[out] xprune The pruned elimination tree
@@ -215,47 +190,46 @@ void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexV
* \param parent The elimination tree
* \param xplore work vector
* \param glu The global data structure
*
*
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
{
Index nextl_col; // Next available position in panel_lsub[*,jj]
// Initialize pointers
VectorBlock<IndexVector> marker1(marker, m, m);
nseg = 0;
void SparseLUImpl<Scalar, StorageIndex>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A,
IndexVector& perm_r, Index& nseg, ScalarVector& dense,
IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz,
IndexVector& xprune, IndexVector& marker, IndexVector& parent,
IndexVector& xplore, GlobalLU_t& glu) {
Index nextl_col; // Next available position in panel_lsub[*,jj]
// Initialize pointers
VectorBlock<IndexVector> marker1(marker, m, m);
nseg = 0;
panel_dfs_traits<IndexVector> traits(jcol, marker1.data());
// For each column in the panel
for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++)
{
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
VectorBlock<ScalarVector> dense_col(dense,nextl_col, m); // Accumulate a column vector here
// For each column in the panel
for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++) {
nextl_col = (jj - jcol) * m;
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Accumulate a column vector here
// For each nnz in A[*, jj] do depth first search
for (typename MatrixType::InnerIterator it(A, jj); it; ++it)
{
Index krow = it.row();
for (typename MatrixType::InnerIterator it(A, jj); it; ++it) {
Index krow = it.row();
dense_col(krow) = it.value();
StorageIndex kmark = marker(krow);
if (kmark == jj)
continue; // krow visited before, go to the next nonzero
dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent,
xplore, glu, nextl_col, krow, traits);
}// end for nonzeros in column jj
} // end for column jj
StorageIndex kmark = marker(krow);
if (kmark == jj) continue; // krow visited before, go to the next nonzero
dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent, xplore, glu, nextl_col, krow,
traits);
} // end for nonzeros in column jj
} // end for column jj
}
} // end namespace internal
} // end namespace Eigen
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_PANEL_DFS_H
#endif // SPARSELU_PANEL_DFS_H

View File

@@ -7,10 +7,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of xpivotL.c file in SuperLU
/*
* NOTE: This file is the modified version of xpivotL.c file in SuperLU
* -- SuperLU routine (version 3.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -35,10 +35,10 @@
namespace Eigen {
namespace internal {
/**
* \brief Performs the numerical pivotin on the current column of L, and the CDIV operation.
*
*
* Pivot policy :
* (1) Compute thresh = u * max_(i>=j) abs(A_ij);
* (2) IF user specifies pivot row k and abs(A_kj) >= thresh THEN
@@ -47,64 +47,63 @@ namespace internal {
* pivot row = j;
* ELSE
* pivot row = m;
*
*
* Note: If you absolutely want to use a given pivot order, then set u=0.0.
*
*
* \param jcol The current column of L
* \param diagpivotthresh diagonal pivoting threshold
* \param[in,out] perm_r Row permutation (threshold pivoting)
* \param[in] iperm_c column permutation - used to finf diagonal of Pc*A*Pc'
* \param[out] pivrow The pivot row
* \param glu Global LU data
* \return 0 if success, i > 0 if U(i,i) is exactly zero
*
* \return 0 if success, i > 0 if U(i,i) is exactly zero
*
*/
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar,StorageIndex>::pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu)
{
Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
Index nsupr = glu.xlsub(fsupc+1) - lptr; // Number of rows in the supernode
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc); // leading dimension
Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
StorageIndex* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
// Determine the largest abs numerical value for partial pivoting
Index diagind = iperm_c(jcol); // diagonal index
Index SparseLUImpl<Scalar, StorageIndex>::pivotL(const Index jcol, const RealScalar& diagpivotthresh,
IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow,
GlobalLU_t& glu) {
Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
Index nsupr = glu.xlsub(fsupc + 1) - lptr; // Number of rows in the supernode
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // leading dimension
Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
StorageIndex* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
// Determine the largest abs numerical value for partial pivoting
Index diagind = iperm_c(jcol); // diagonal index
RealScalar pivmax(-1.0);
Index pivptr = nsupc;
Index diag = emptyIdxLU;
Index pivptr = nsupc;
Index diag = emptyIdxLU;
RealScalar rtemp;
Index isub, icol, itemp, k;
Index isub, icol, itemp, k;
for (isub = nsupc; isub < nsupr; ++isub) {
using std::abs;
rtemp = abs(lu_col_ptr[isub]);
if (rtemp > pivmax) {
pivmax = rtemp;
pivmax = rtemp;
pivptr = isub;
}
}
if (lsub_ptr[isub] == diagind) diag = isub;
}
// Test for singularity
if ( pivmax <= RealScalar(0.0) ) {
if (pivmax <= RealScalar(0.0)) {
// if pivmax == -1, the column is structurally empty, otherwise it is only numerically zero
pivrow = pivmax < RealScalar(0.0) ? diagind : lsub_ptr[pivptr];
perm_r(pivrow) = StorageIndex(jcol);
return (jcol+1);
return (jcol + 1);
}
RealScalar thresh = diagpivotthresh * pivmax;
// Choose appropriate pivotal element
RealScalar thresh = diagpivotthresh * pivmax;
// Choose appropriate pivotal element
{
// Test if the diagonal element can be used as a pivot (given the threshold value)
if (diag >= 0 )
{
if (diag >= 0) {
// Diagonal element exists
using std::abs;
rtemp = abs(lu_col_ptr[diag]);
@@ -112,29 +111,26 @@ Index SparseLUImpl<Scalar,StorageIndex>::pivotL(const Index jcol, const RealScal
}
pivrow = lsub_ptr[pivptr];
}
// Record pivot row
perm_r(pivrow) = StorageIndex(jcol);
// Interchange row subscripts
if (pivptr != nsupc )
{
std::swap( lsub_ptr[pivptr], lsub_ptr[nsupc] );
if (pivptr != nsupc) {
std::swap(lsub_ptr[pivptr], lsub_ptr[nsupc]);
// Interchange numerical values as well, for the two rows in the whole snode
// such that L is indexed the same way as A
for (icol = 0; icol <= nsupc; icol++)
{
itemp = pivptr + icol * lda;
for (icol = 0; icol <= nsupc; icol++) {
itemp = pivptr + icol * lda;
std::swap(lu_sup_ptr[itemp], lu_sup_ptr[nsupc + icol * lda]);
}
}
// cdiv operations
Scalar temp = Scalar(1.0) / lu_col_ptr[nsupc];
for (k = nsupc+1; k < nsupr; k++)
lu_col_ptr[k] *= temp;
for (k = nsupc + 1; k < nsupr; k++) lu_col_ptr[k] *= temp;
return 0;
}
} // end namespace internal
} // end namespace Eigen
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_PIVOTL_H
#endif // SPARSELU_PIVOTL_H

View File

@@ -7,10 +7,10 @@
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/*
* NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU
/*
* NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU
* -- SuperLU routine (version 2.0) --
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
* and Lawrence Berkeley National Lab.
@@ -40,100 +40,91 @@ namespace internal {
* \brief Prunes the L-structure.
*
* It prunes the L-structure of supernodes whose L-structure contains the current pivot row "pivrow"
*
*
*
*
* \param jcol The current column of L
* \param[in] perm_r Row permutation
* \param[out] pivrow The pivot row
* \param nseg Number of segments
* \param segrep
* \param segrep
* \param repfnz
* \param[out] xprune
* \param[out] xprune
* \param glu Global LU data
*
*
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg,
const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu)
{
void SparseLUImpl<Scalar, StorageIndex>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow,
const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz,
IndexVector& xprune, GlobalLU_t& glu) {
// For each supernode-rep irep in U(*,j]
Index jsupno = glu.supno(jcol);
Index i,irep,irep1;
bool movnum, do_prune = false;
Index kmin = 0, kmax = 0, minloc, maxloc,krow;
for (i = 0; i < nseg; i++)
{
irep = segrep(i);
irep1 = irep + 1;
do_prune = false;
// Don't prune with a zero U-segment
if (repfnz(irep) == emptyIdxLU) continue;
Index jsupno = glu.supno(jcol);
Index i, irep, irep1;
bool movnum, do_prune = false;
Index kmin = 0, kmax = 0, minloc, maxloc, krow;
for (i = 0; i < nseg; i++) {
irep = segrep(i);
irep1 = irep + 1;
do_prune = false;
// Don't prune with a zero U-segment
if (repfnz(irep) == emptyIdxLU) continue;
// If a snode overlaps with the next panel, then the U-segment
// is fragmented into two parts -- irep and irep1. We should let
// pruning occur at the rep-column in irep1s snode.
if (glu.supno(irep) == glu.supno(irep1) ) continue; // don't prune
// is fragmented into two parts -- irep and irep1. We should let
// pruning occur at the rep-column in irep1s snode.
if (glu.supno(irep) == glu.supno(irep1)) continue; // don't prune
// If it has not been pruned & it has a nonz in row L(pivrow,i)
if (glu.supno(irep) != jsupno )
{
if ( xprune (irep) >= glu.xlsub(irep1) )
{
if (glu.supno(irep) != jsupno) {
if (xprune(irep) >= glu.xlsub(irep1)) {
kmin = glu.xlsub(irep);
kmax = glu.xlsub(irep1) - 1;
for (krow = kmin; krow <= kmax; krow++)
{
if (glu.lsub(krow) == pivrow)
{
do_prune = true;
break;
kmax = glu.xlsub(irep1) - 1;
for (krow = kmin; krow <= kmax; krow++) {
if (glu.lsub(krow) == pivrow) {
do_prune = true;
break;
}
}
}
if (do_prune)
{
if (do_prune) {
// do a quicksort-type partition
// movnum=true means that the num values have to be exchanged
movnum = false;
if (irep == glu.xsup(glu.supno(irep)) ) // Snode of size 1
movnum = true;
while (kmin <= kmax)
{
movnum = false;
if (irep == glu.xsup(glu.supno(irep))) // Snode of size 1
movnum = true;
while (kmin <= kmax) {
if (perm_r(glu.lsub(kmax)) == emptyIdxLU)
kmax--;
else if ( perm_r(glu.lsub(kmin)) != emptyIdxLU)
kmax--;
else if (perm_r(glu.lsub(kmin)) != emptyIdxLU)
kmin++;
else
{
else {
// kmin below pivrow (not yet pivoted), and kmax
// above pivrow: interchange the two suscripts
std::swap(glu.lsub(kmin), glu.lsub(kmax));
// If the supernode has only one column, then we
std::swap(glu.lsub(kmin), glu.lsub(kmax));
// If the supernode has only one column, then we
// only keep one set of subscripts. For any subscript
// intercnahge performed, similar interchange must be
// done on the numerical values.
if (movnum)
{
minloc = glu.xlusup(irep) + ( kmin - glu.xlsub(irep) );
maxloc = glu.xlusup(irep) + ( kmax - glu.xlsub(irep) );
std::swap(glu.lusup(minloc), glu.lusup(maxloc));
// intercnahge performed, similar interchange must be
// done on the numerical values.
if (movnum) {
minloc = glu.xlusup(irep) + (kmin - glu.xlsub(irep));
maxloc = glu.xlusup(irep) + (kmax - glu.xlsub(irep));
std::swap(glu.lusup(minloc), glu.lusup(maxloc));
}
kmin++;
kmax--;
}
} // end while
xprune(irep) = StorageIndex(kmin); //Pruning
} // end if do_prune
} // end pruning
} // End for each U-segment
} // end while
xprune(irep) = StorageIndex(kmin); // Pruning
} // end if do_prune
} // end pruning
} // End for each U-segment
}
} // end namespace internal
} // end namespace Eigen
} // end namespace internal
} // end namespace Eigen
#endif // SPARSELU_PRUNEL_H
#endif // SPARSELU_PRUNEL_H

View File

@@ -34,53 +34,48 @@
namespace Eigen {
namespace internal {
/**
/**
* \brief Identify the initial relaxed supernodes
*
* This routine is applied to a column elimination tree.
*
* This routine is applied to a column elimination tree.
* It assumes that the matrix has been reordered according to the postorder of the etree
* \param n the number of columns
* \param et elimination tree
* \param relax_columns Maximum number of columns allowed in a relaxed snode
* \param et elimination tree
* \param relax_columns Maximum number of columns allowed in a relaxed snode
* \param descendants Number of descendants of each node in the etree
* \param relax_end last column in a supernode
*/
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar,StorageIndex>::relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
{
void SparseLUImpl<Scalar, StorageIndex>::relax_snode(const Index n, IndexVector& et, const Index relax_columns,
IndexVector& descendants, IndexVector& relax_end) {
// compute the number of descendants of each node in the etree
Index parent;
Index parent;
relax_end.setConstant(emptyIdxLU);
descendants.setZero();
for (Index j = 0; j < n; j++)
{
for (Index j = 0; j < n; j++) {
parent = et(j);
if (parent != n) // not the dummy root
if (parent != n) // not the dummy root
descendants(parent) += descendants(j) + 1;
}
// Identify the relaxed supernodes by postorder traversal of the etree
Index snode_start; // beginning of a snode
for (Index j = 0; j < n; )
{
Index snode_start; // beginning of a snode
for (Index j = 0; j < n;) {
parent = et(j);
snode_start = j;
while ( parent != n && descendants(parent) < relax_columns )
{
j = parent;
snode_start = j;
while (parent != n && descendants(parent) < relax_columns) {
j = parent;
parent = et(j);
}
// Found a supernode in postordered etree, j is the last column
relax_end(snode_start) = StorageIndex(j); // Record last column
// Found a supernode in postordered etree, j is the last column
relax_end(snode_start) = StorageIndex(j); // Record last column
j++;
// Search for a new leaf
while (descendants(j) != 0 && j < n) j++;
} // End postorder traversal of the etree
} // End postorder traversal of the etree
}
} // end namespace internal
} // end namespace internal
} // end namespace Eigen
} // end namespace Eigen
#endif