46 #ifndef EIGEN_COLAMD_H
47 #define EIGEN_COLAMD_H
108 template <
typename IndexType>
127 template <
typename IndexType>
165 template <
typename IndexType>
203 template <
typename IndexType>
208 template <
typename IndexType>
214 template <
typename IndexType>
215 static IndexType
init_rows_cols(IndexType n_row, IndexType n_col, RowStructure<IndexType> Row[],
216 ColStructure<IndexType>
col[], IndexType
A[], IndexType
p[], IndexType stats[
NStats]);
218 template <
typename IndexType>
219 static void init_scoring(IndexType n_row, IndexType n_col, RowStructure<IndexType> Row[], ColStructure<IndexType> Col[],
220 IndexType
A[], IndexType head[],
double knobs[
NKnobs], IndexType *p_n_row2,
221 IndexType *p_n_col2, IndexType *p_max_deg);
223 template <
typename IndexType>
224 static IndexType
find_ordering(IndexType n_row, IndexType n_col, IndexType Alen, RowStructure<IndexType> Row[],
225 ColStructure<IndexType> Col[], IndexType
A[], IndexType head[], IndexType n_col2,
226 IndexType max_deg, IndexType pfree);
228 template <
typename IndexType>
229 static void order_children(IndexType n_col, ColStructure<IndexType> Col[], IndexType
p[]);
231 template <
typename IndexType>
232 static void detect_super_cols(ColStructure<IndexType> Col[], IndexType
A[], IndexType head[], IndexType row_start,
233 IndexType row_length);
235 template <
typename IndexType>
236 static IndexType
garbage_collection(IndexType n_row, IndexType n_col, RowStructure<IndexType> Row[],
237 ColStructure<IndexType> Col[], IndexType
A[], IndexType *pfree);
239 template <
typename IndexType>
240 static inline IndexType
clear_mark(IndexType n_row, RowStructure<IndexType> Row[]);
244 #define COLAMD_DEBUG0(params) ;
245 #define COLAMD_DEBUG1(params) ;
246 #define COLAMD_DEBUG2(params) ;
247 #define COLAMD_DEBUG3(params) ;
248 #define COLAMD_DEBUG4(params) ;
250 #define COLAMD_ASSERT(expression) ((void)0)
266 template <
typename IndexType>
267 inline IndexType
recommended(IndexType nnz, IndexType n_row, IndexType n_col) {
268 if ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)
271 return (2 * (nnz) +
colamd_c(n_col) +
colamd_r(n_row) + (n_col) + ((nnz) / 5));
327 template <
typename IndexType>
328 static bool compute_ordering(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *
A, IndexType *
p,
343 double default_knobs[
NKnobs];
393 COLAMD_DEBUG0((
"colamd: number of entries negative %d\n", nnz));
408 knobs = default_knobs;
415 need = 2 * nnz + n_col + Col_size + Row_size;
422 COLAMD_DEBUG0((
"colamd: Need Alen >= %d, given only Alen = %d\n", need, Alen));
426 Alen -= Col_size + Row_size;
477 template <
typename IndexType>
506 if ((Col[
col].length) < 0)
516 Col[
col].shared1.thickness = 1;
517 Col[
col].shared2.score = 0;
519 Col[
col].shared4.degree_next =
Empty;
530 Row[
row].shared2.mark = -1;
537 cp_end = &
A[
p[
col + 1]];
539 while (cp < cp_end) {
543 if (row < 0 || row >= n_row) {
552 if (
row <= last_row || Row[
row].shared2.mark ==
col) {
562 if (Row[
row].shared2.mark !=
col) {
571 Row[
row].shared2.mark =
col;
581 Row[0].start =
p[n_col];
582 Row[0].shared1.p = Row[0].start;
583 Row[0].shared2.mark = -1;
585 Row[
row].start = Row[
row - 1].start + Row[
row - 1].length;
586 Row[
row].shared1.p = Row[
row].start;
587 Row[
row].shared2.mark = -1;
596 cp_end = &
A[
p[
col + 1]];
597 while (cp < cp_end) {
599 if (Row[
row].shared2.mark !=
col) {
600 A[(Row[
row].shared1.p)++] =
col;
601 Row[
row].shared2.mark =
col;
609 cp_end = &
A[
p[
col + 1]];
610 while (cp < cp_end) {
611 A[(Row[*cp++].shared1.p)++] =
col;
619 Row[
row].shared2.mark = 0;
620 Row[
row].shared1.degree = Row[
row].length;
626 COLAMD_DEBUG0((
"colamd: reconstructing column form, matrix jumbled\n"));
639 Col[
col].start = Col[
col - 1].start + Col[
col - 1].length;
646 rp = &
A[Row[
row].start];
647 rp_end = rp + Row[
row].length;
648 while (rp < rp_end) {
649 A[(
p[*rp++])++] =
row;
667 template <
typename IndexType>
690 IndexType col_length;
694 IndexType dense_row_count;
695 IndexType dense_col_count;
704 COLAMD_DEBUG1((
"colamd: densecount: %d %d\n", dense_row_count, dense_col_count));
713 for (
c = n_col - 1;
c >= 0;
c--) {
721 COLAMD_DEBUG1((
"colamd: null columns killed: %d\n", n_col - n_col2));
726 for (
c = n_col - 1;
c >= 0;
c--) {
728 if (Col[
c].is_dead()) {
732 if (deg > dense_col_count) {
737 cp_end = cp + Col[
c].length;
738 while (cp < cp_end) {
741 Col[
c].kill_principal();
744 COLAMD_DEBUG1((
"colamd: Dense and null columns killed: %d\n", n_col - n_col2));
748 for (
r = 0;
r < n_row;
r++) {
751 if (deg > dense_row_count || deg == 0) {
760 COLAMD_DEBUG1((
"colamd: Dense and null rows killed: %d\n", n_row - n_row2));
770 for (
c = n_col - 1;
c >= 0;
c--) {
772 if (Col[
c].is_dead()) {
778 cp_end = cp + Col[
c].length;
779 while (cp < cp_end) {
783 if (Row[
row].is_dead()) {
794 col_length = (IndexType)(new_cp - &
A[Col[
c].
start]);
795 if (col_length == 0) {
799 Col[
c].shared2.order = --n_col2;
800 Col[
c].kill_principal();
805 Col[
c].length = col_length;
806 Col[
c].shared2.score = score;
809 COLAMD_DEBUG1((
"colamd: Dense, null, and newly-null columns killed: %d\n", n_col - n_col2));
819 for (
c = 0;
c <= n_col;
c++) {
825 for (
c = n_col - 1;
c >= 0;
c--) {
827 if (Col[
c].is_alive()) {
828 COLAMD_DEBUG4((
"place %d score %d minscore %d ncol %d\n",
c, Col[
c].shared2.
score, min_score, n_col));
841 next_col = head[score];
847 if (next_col !=
Empty) {
861 *p_max_deg = max_deg;
873 template <
typename IndexType>
898 IndexType pivot_row_start;
899 IndexType pivot_row_degree;
900 IndexType pivot_row_length;
901 IndexType pivot_col_score;
902 IndexType needed_memory;
910 IndexType head_column;
914 IndexType set_difference;
916 IndexType col_thickness;
918 IndexType pivot_col_thickness;
925 max_mark = INT_MAX - n_col;
933 for (
k = 0;
k < n_col2; ) {
942 while (min_score < n_col && head[min_score] ==
Empty) {
945 pivot_col = head[min_score];
947 next_col = Col[pivot_col].shared4.degree_next;
948 head[min_score] = next_col;
949 if (next_col !=
Empty) {
950 Col[next_col].shared3.prev =
Empty;
957 pivot_col_score = Col[pivot_col].shared2.score;
960 Col[pivot_col].shared2.order =
k;
963 pivot_col_thickness = Col[pivot_col].shared1.thickness;
964 k += pivot_col_thickness;
970 if (pfree + needed_memory >= Alen) {
982 pivot_row_start = pfree;
985 pivot_row_degree = 0;
989 Col[pivot_col].shared1.thickness = -pivot_col_thickness;
992 cp = &
A[Col[pivot_col].start];
993 cp_end = cp + Col[pivot_col].length;
994 while (cp < cp_end) {
999 if (Row[
row].is_dead()) {
1002 rp = &
A[Row[
row].start];
1003 rp_end = rp + Row[
row].length;
1004 while (rp < rp_end) {
1008 col_thickness = Col[
col].shared1.thickness;
1009 if (col_thickness > 0 && Col[
col].is_alive()) {
1011 Col[
col].shared1.thickness = -col_thickness;
1015 pivot_row_degree += col_thickness;
1021 Col[pivot_col].shared1.thickness = pivot_col_thickness;
1027 cp = &
A[Col[pivot_col].start];
1028 cp_end = cp + Col[pivot_col].length;
1029 while (cp < cp_end) {
1038 pivot_row_length = pfree - pivot_row_start;
1039 if (pivot_row_length > 0) {
1041 pivot_row =
A[Col[pivot_col].start];
1048 COLAMD_ASSERT(Col[pivot_col].length > 0 || pivot_row_length == 0);
1071 COLAMD_DEBUG3((
"** Computing set differences phase. **\n"));
1077 rp = &
A[pivot_row_start];
1078 rp_end = rp + pivot_row_length;
1079 while (rp < rp_end) {
1085 col_thickness = -Col[
col].shared1.thickness;
1087 Col[
col].shared1.thickness = col_thickness;
1091 cur_score = Col[
col].shared2.score;
1092 prev_col = Col[
col].shared3.prev;
1093 next_col = Col[
col].shared4.degree_next;
1097 if (prev_col ==
Empty) {
1098 head[cur_score] = next_col;
1100 Col[prev_col].shared4.degree_next = next_col;
1102 if (next_col !=
Empty) {
1103 Col[next_col].shared3.prev = prev_col;
1108 cp = &
A[Col[
col].start];
1109 cp_end = cp + Col[
col].length;
1110 while (cp < cp_end) {
1114 if (Row[
row].is_dead()) {
1117 row_mark = Row[
row].shared2.mark;
1119 set_difference = row_mark - tag_mark;
1121 if (set_difference < 0) {
1123 set_difference = Row[
row].shared1.degree;
1126 set_difference -= col_thickness;
1129 if (set_difference == 0) {
1134 Row[
row].shared2.mark = set_difference + tag_mark;
1144 rp = &
A[pivot_row_start];
1145 rp_end = rp + pivot_row_length;
1146 while (rp < rp_end) {
1152 cp = &
A[Col[
col].start];
1155 cp_end = cp + Col[
col].length;
1159 while (cp < cp_end) {
1164 if (Row[
row].is_dead()) {
1167 row_mark = Row[
row].shared2.mark;
1174 cur_score += row_mark - tag_mark;
1180 Col[
col].length = (IndexType)(new_cp - &
A[Col[
col].
start]);
1184 if (Col[
col].length == 0) {
1187 Col[
col].kill_principal();
1188 pivot_row_degree -= Col[
col].shared1.thickness;
1191 Col[
col].shared2.order =
k;
1193 k += Col[
col].shared1.thickness;
1200 Col[
col].shared2.score = cur_score;
1208 head_column = head[hash];
1209 if (head_column >
Empty) {
1212 first_col = Col[head_column].shared3.headhash;
1213 Col[head_column].shared3.headhash =
col;
1216 first_col = -(head_column + 2);
1217 head[hash] = -(
col + 2);
1219 Col[
col].shared4.hash_next = first_col;
1222 Col[
col].shared3.hash = (IndexType)hash;
1237 Col[pivot_col].kill_principal();
1241 tag_mark += (max_deg + 1);
1242 if (tag_mark >= max_mark) {
1252 rp = &
A[pivot_row_start];
1255 rp_end = rp + pivot_row_length;
1256 while (rp < rp_end) {
1259 if (Col[
col].is_dead()) {
1264 A[Col[
col].start + (Col[
col].length++)] = pivot_row;
1269 cur_score = Col[
col].shared2.score + pivot_row_degree;
1274 max_score = n_col -
k - Col[
col].shared1.thickness;
1277 cur_score -= Col[
col].shared1.thickness;
1284 Col[
col].shared2.score = cur_score;
1293 next_col = head[cur_score];
1294 Col[
col].shared4.degree_next = next_col;
1296 if (next_col !=
Empty) {
1297 Col[next_col].shared3.prev =
col;
1299 head[cur_score] =
col;
1307 if (pivot_row_degree > 0) {
1310 Row[pivot_row].start = pivot_row_start;
1311 Row[pivot_row].length = (IndexType)(new_rp - &
A[pivot_row_start]);
1312 Row[pivot_row].shared1.degree = pivot_row_degree;
1313 Row[pivot_row].shared2.mark = 0;
1339 template <
typename IndexType>
1356 for (
i = 0;
i < n_col;
i++) {
1359 if (!Col[
i].is_dead_principal() && Col[
i].shared2.
order ==
Empty) {
1364 }
while (!Col[parent].is_dead_principal());
1395 for (
c = 0;
c < n_col;
c++) {
1432 template <
typename IndexType>
1439 IndexType row_start,
1440 IndexType row_length
1455 IndexType head_column;
1456 IndexType first_col;
1461 rp_end = rp + row_length;
1462 while (rp < rp_end) {
1464 if (Col[
col].is_dead()) {
1474 head_column = head[hash];
1475 if (head_column >
Empty) {
1478 first_col = -(head_column + 2);
1486 length = Col[super_c].
length;
1505 cp1 = &
A[Col[super_c].
start];
1506 cp2 = &
A[Col[
c].start];
1508 for (
i = 0;
i < length;
i++) {
1514 if (*cp1++ != *cp2++) {
1527 COLAMD_ASSERT(Col[
c].shared2.score == Col[super_c].shared2.score);
1529 Col[super_c].shared1.thickness += Col[
c].shared1.thickness;
1530 Col[
c].shared1.parent = super_c;
1531 Col[
c].kill_non_principal();
1533 Col[
c].shared2.order =
Empty;
1535 Col[prev_c].shared4.hash_next = Col[
c].shared4.hash_next;
1541 if (head_column >
Empty) {
1563 template <
typename IndexType>
1587 for (
c = 0;
c < n_col;
c++) {
1588 if (Col[
c].is_alive()) {
1589 psrc = &
A[Col[
c].start];
1593 Col[
c].start = (IndexType)(pdest - &
A[0]);
1594 length = Col[
c].length;
1595 for (
j = 0;
j < length;
j++) {
1597 if (Row[
r].is_alive()) {
1601 Col[
c].length = (IndexType)(pdest - &
A[Col[
c].
start]);
1607 for (
r = 0;
r < n_row;
r++) {
1608 if (Row[
r].is_alive()) {
1609 if (Row[
r].length == 0) {
1615 psrc = &
A[Row[
r].start];
1616 Row[
r].shared2.first_column = *psrc;
1627 while (psrc < pfree) {
1635 *psrc = Row[
r].shared2.first_column;
1640 Row[
r].start = (IndexType)(pdest - &
A[0]);
1641 length = Row[
r].length;
1642 for (
j = 0;
j < length;
j++) {
1644 if (Col[
c].is_alive()) {
1648 Row[
r].length = (IndexType)(pdest - &
A[Row[
r].
start]);
1656 return ((IndexType)(pdest - &
A[0]));
1667 template <
typename IndexType>
1679 for (
r = 0;
r < n_row;
r++) {
1680 if (Row[
r].is_alive()) {
1681 Row[
r].shared2.mark = 0;
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define COLAMD_ASSERT(expression)
Definition: Eigen_Colamd.h:250
#define COLAMD_DEBUG0(params)
Definition: Eigen_Colamd.h:244
#define COLAMD_DEBUG2(params)
Definition: Eigen_Colamd.h:246
#define COLAMD_DEBUG3(params)
Definition: Eigen_Colamd.h:247
#define COLAMD_DEBUG1(params)
Definition: Eigen_Colamd.h:245
#define COLAMD_DEBUG4(params)
Definition: Eigen_Colamd.h:248
float * p
Definition: Tutorial_Map_using.cpp:9
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
Data class to send an empty class over MPI.
Definition: MpiDataClass.h:110
char char char int int * k
Definition: level2_impl.h:374
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T maxi(const T &x, const T &y)
Definition: MathFunctions.h:926
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T mini(const T &x, const T &y)
Definition: MathFunctions.h:920
int c
Definition: calibrate.py:100
static IndexType garbage_collection(IndexType n_row, IndexType n_col, RowStructure< IndexType > Row[], ColStructure< IndexType > Col[], IndexType A[], IndexType *pfree)
Definition: Eigen_Colamd.h:1565
static void init_scoring(IndexType n_row, IndexType n_col, RowStructure< IndexType > Row[], ColStructure< IndexType > Col[], IndexType A[], IndexType head[], double knobs[NKnobs], IndexType *p_n_row2, IndexType *p_n_col2, IndexType *p_max_deg)
Definition: Eigen_Colamd.h:668
static IndexType find_ordering(IndexType n_row, IndexType n_col, IndexType Alen, RowStructure< IndexType > Row[], ColStructure< IndexType > Col[], IndexType A[], IndexType head[], IndexType n_col2, IndexType max_deg, IndexType pfree)
Definition: Eigen_Colamd.h:875
IndexType ones_complement(const IndexType r)
Definition: Eigen_Colamd.h:109
const int NKnobs
Definition: Eigen_Colamd.h:63
Status
Definition: Eigen_Colamd.h:89
@ ErrorRowIndexOutOfBounds
Definition: Eigen_Colamd.h:100
@ ErrorColLengthNegative
Definition: Eigen_Colamd.h:99
@ ErrorInternalError
Definition: Eigen_Colamd.h:102
@ ErrorANotPresent
Definition: Eigen_Colamd.h:92
@ ErrorNnzNegative
Definition: Eigen_Colamd.h:96
@ ErrorPNotPresent
Definition: Eigen_Colamd.h:93
@ ErrorNcolNegative
Definition: Eigen_Colamd.h:95
@ ErrorOutOfMemory
Definition: Eigen_Colamd.h:101
@ ErrorP0Nonzero
Definition: Eigen_Colamd.h:97
@ Ok
Definition: Eigen_Colamd.h:90
@ OkButJumbled
Definition: Eigen_Colamd.h:91
@ ErrorNrowNegative
Definition: Eigen_Colamd.h:94
@ ErrorATooSmall
Definition: Eigen_Colamd.h:98
static IndexType init_rows_cols(IndexType n_row, IndexType n_col, RowStructure< IndexType > Row[], ColStructure< IndexType > col[], IndexType A[], IndexType p[], IndexType stats[NStats])
Definition: Eigen_Colamd.h:479
static void order_children(IndexType n_col, ColStructure< IndexType > Col[], IndexType p[])
Definition: Eigen_Colamd.h:1340
IndexType colamd_r(IndexType n_row)
Definition: Eigen_Colamd.h:209
IndexType recommended(IndexType nnz, IndexType n_row, IndexType n_col)
Returns the recommended value of Alen.
Definition: Eigen_Colamd.h:267
static IndexType clear_mark(IndexType n_row, RowStructure< IndexType > Row[])
Definition: Eigen_Colamd.h:1669
KnobsStatsIndex
Definition: Eigen_Colamd.h:69
@ DenseRow
Definition: Eigen_Colamd.h:71
@ DefragCount
Definition: Eigen_Colamd.h:77
@ DenseCol
Definition: Eigen_Colamd.h:74
@ Info1
Definition: Eigen_Colamd.h:83
@ Info3
Definition: Eigen_Colamd.h:85
@ Info2
Definition: Eigen_Colamd.h:84
ColumnStatus
Definition: Eigen_Colamd.h:120
@ DeadNonPrincipal
Definition: Eigen_Colamd.h:120
@ DeadPrincipal
Definition: Eigen_Colamd.h:120
const int Empty
Definition: Eigen_Colamd.h:114
IndexType colamd_c(IndexType n_col)
Definition: Eigen_Colamd.h:204
static bool compute_ordering(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *A, IndexType *p, double knobs[NKnobs], IndexType stats[NStats])
Computes a column ordering using the column approximate minimum degree ordering.
Definition: Eigen_Colamd.h:328
const int NStats
Definition: Eigen_Colamd.h:66
RowColumnStatus
Definition: Eigen_Colamd.h:117
@ Dead
Definition: Eigen_Colamd.h:117
@ Alive
Definition: Eigen_Colamd.h:117
static void set_defaults(double knobs[NKnobs])
set default parameters The use of this routine is optional.
Definition: Eigen_Colamd.h:295
static void detect_super_cols(ColStructure< IndexType > Col[], IndexType A[], IndexType head[], IndexType row_start, IndexType row_length)
Definition: Eigen_Colamd.h:1433
Definition: Eigen_Colamd.h:49
void start(const unsigned &i)
(Re-)start i-th timer
Definition: oomph_utilities.cc:243
Definition: Eigen_Colamd.h:128
union internal::Colamd::ColStructure::@779 shared1
bool is_alive() const
Definition: Eigen_Colamd.h:156
bool is_dead_principal() const
Definition: Eigen_Colamd.h:158
IndexType score
Definition: Eigen_Colamd.h:139
IndexType order
Definition: Eigen_Colamd.h:140
IndexType prev
Definition: Eigen_Colamd.h:146
bool is_dead() const
Definition: Eigen_Colamd.h:154
IndexType start
Definition: Eigen_Colamd.h:129
union internal::Colamd::ColStructure::@780 shared2
void kill_non_principal()
Definition: Eigen_Colamd.h:162
IndexType parent
Definition: Eigen_Colamd.h:135
IndexType hash
Definition: Eigen_Colamd.h:145
IndexType thickness
Definition: Eigen_Colamd.h:133
IndexType hash_next
Definition: Eigen_Colamd.h:151
void kill_principal()
Definition: Eigen_Colamd.h:160
IndexType degree_next
Definition: Eigen_Colamd.h:150
union internal::Colamd::ColStructure::@782 shared4
union internal::Colamd::ColStructure::@781 shared3
IndexType headhash
Definition: Eigen_Colamd.h:143
IndexType length
Definition: Eigen_Colamd.h:131
Definition: Eigen_Colamd.h:166
bool is_alive() const
Definition: Eigen_Colamd.h:180
IndexType length
Definition: Eigen_Colamd.h:168
IndexType first_column
Definition: Eigen_Colamd.h:175
IndexType degree
Definition: Eigen_Colamd.h:170
bool is_dead() const
Definition: Eigen_Colamd.h:178
union internal::Colamd::RowStructure::@784 shared2
union internal::Colamd::RowStructure::@783 shared1
IndexType mark
Definition: Eigen_Colamd.h:174
void kill()
Definition: Eigen_Colamd.h:182
IndexType start
Definition: Eigen_Colamd.h:167
IndexType p
Definition: Eigen_Colamd.h:171
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2