92 ErrorANotPresent = -1,
93 ErrorPNotPresent = -2,
94 ErrorNrowNegative = -3,
95 ErrorNcolNegative = -4,
96 ErrorNnzNegative = -5,
99 ErrorColLengthNegative = -8,
100 ErrorRowIndexOutOfBounds = -9,
101 ErrorOutOfMemory = -10,
102 ErrorInternalError = -999
108template <
typename IndexType>
109IndexType ones_complement(
const IndexType r) {
117enum RowColumnStatus { Alive = 0, Dead = -1 };
120enum ColumnStatus { DeadPrincipal = -1, DeadNonPrincipal = -2 };
127template <
typename IndexType>
150 IndexType degree_next;
154 inline bool is_dead()
const {
return start < Alive; }
156 inline bool is_alive()
const {
return start >= Alive; }
158 inline bool is_dead_principal()
const {
return start == DeadPrincipal; }
160 inline void kill_principal() { start = DeadPrincipal; }
162 inline void kill_non_principal() { start = DeadNonPrincipal; }
165template <
typename IndexType>
175 IndexType first_column;
178 inline bool is_dead()
const {
return shared2.mark < Alive; }
180 inline bool is_alive()
const {
return shared2.mark >= Alive; }
182 inline void kill() { shared2.mark = Dead; }
203template <
typename IndexType>
204inline IndexType colamd_c(IndexType n_col) {
205 return IndexType(((n_col) + 1) *
sizeof(ColStructure<IndexType>) /
sizeof(IndexType));
208template <
typename IndexType>
209inline IndexType colamd_r(IndexType n_row) {
210 return IndexType(((n_row) + 1) *
sizeof(RowStructure<IndexType>) /
sizeof(IndexType));
214template <
typename IndexType>
215static IndexType init_rows_cols(IndexType n_row, IndexType n_col, RowStructure<IndexType> Row[],
216 ColStructure<IndexType> col[], IndexType A[], IndexType p[], IndexType stats[NStats]);
218template <
typename IndexType>
219static 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);
223template <
typename IndexType>
224static 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);
228template <
typename IndexType>
229static void order_children(IndexType n_col, ColStructure<IndexType> Col[], IndexType p[]);
231template <
typename IndexType>
232static void detect_super_cols(ColStructure<IndexType> Col[], IndexType A[], IndexType head[], IndexType row_start,
233 IndexType row_length);
235template <
typename IndexType>
236static IndexType garbage_collection(IndexType n_row, IndexType n_col, RowStructure<IndexType> Row[],
237 ColStructure<IndexType> Col[], IndexType A[], IndexType *pfree);
239template <
typename IndexType>
240static 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)
266template <
typename IndexType>
267inline 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));
295static inline void set_defaults(
double knobs[NKnobs]) {
303 for (i = 0; i < NKnobs; i++) {
306 knobs[Colamd::DenseRow] = 0.5;
307 knobs[Colamd::DenseCol] = 0.5;
327template <
typename IndexType>
328static bool compute_ordering(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *A, IndexType *p,
329 double knobs[NKnobs], IndexType stats[NStats]) {
337 Colamd::RowStructure<IndexType> *Row;
338 Colamd::ColStructure<IndexType> *Col;
343 double default_knobs[NKnobs];
348 COLAMD_DEBUG0((
"colamd: stats not present\n"));
351 for (i = 0; i < NStats; i++) {
354 stats[Colamd::Status] = Colamd::Ok;
355 stats[Colamd::Info1] = -1;
356 stats[Colamd::Info2] = -1;
360 stats[Colamd::Status] = Colamd::ErrorANotPresent;
361 COLAMD_DEBUG0((
"colamd: A not present\n"));
367 stats[Colamd::Status] = Colamd::ErrorPNotPresent;
368 COLAMD_DEBUG0((
"colamd: p not present\n"));
374 stats[Colamd::Status] = Colamd::ErrorNrowNegative;
375 stats[Colamd::Info1] = n_row;
376 COLAMD_DEBUG0((
"colamd: nrow negative %d\n", n_row));
382 stats[Colamd::Status] = Colamd::ErrorNcolNegative;
383 stats[Colamd::Info1] = n_col;
384 COLAMD_DEBUG0((
"colamd: ncol negative %d\n", n_col));
391 stats[Colamd::Status] = Colamd::ErrorNnzNegative;
392 stats[Colamd::Info1] = nnz;
393 COLAMD_DEBUG0((
"colamd: number of entries negative %d\n", nnz));
398 stats[Colamd::Status] = Colamd::ErrorP0Nonzero;
399 stats[Colamd::Info1] = p[0];
400 COLAMD_DEBUG0((
"colamd: p[0] not zero %d\n", p[0]));
407 set_defaults(default_knobs);
408 knobs = default_knobs;
413 Col_size = colamd_c(n_col);
414 Row_size = colamd_r(n_row);
415 need = 2 * nnz + n_col + Col_size + Row_size;
419 stats[Colamd::Status] = Colamd::ErrorATooSmall;
420 stats[Colamd::Info1] = need;
421 stats[Colamd::Info2] = Alen;
422 COLAMD_DEBUG0((
"colamd: Need Alen >= %d, given only Alen = %d\n", need, Alen));
426 Alen -= Col_size + Row_size;
427 Col = (ColStructure<IndexType> *)&A[Alen];
428 Row = (RowStructure<IndexType> *)&A[Alen + Col_size];
432 if (!Colamd::init_rows_cols(n_row, n_col, Row, Col, A, p, stats)) {
434 COLAMD_DEBUG0((
"colamd: Matrix invalid\n"));
440 Colamd::init_scoring(n_row, n_col, Row, Col, A, p, knobs, &n_row2, &n_col2, &max_deg);
444 ngarbage = Colamd::find_ordering(n_row, n_col, Alen, Row, Col, A, p, n_col2, max_deg, 2 * nnz);
448 Colamd::order_children(n_col, Col, p);
452 stats[Colamd::DenseRow] = n_row - n_row2;
453 stats[Colamd::DenseCol] = n_col - n_col2;
454 stats[Colamd::DefragCount] = ngarbage;
455 COLAMD_DEBUG0((
"colamd: done.\n"));
477template <
typename IndexType>
478static IndexType init_rows_cols
484 RowStructure<IndexType> Row[],
485 ColStructure<IndexType> Col[],
488 IndexType stats[NStats]
502 for (col = 0; col < n_col; col++) {
503 Col[col].start = p[col];
504 Col[col].length = p[col + 1] - p[col];
506 if ((Col[col].length) < 0)
509 stats[Colamd::Status] = Colamd::ErrorColLengthNegative;
510 stats[Colamd::Info1] = col;
511 stats[Colamd::Info2] = Col[col].length;
512 COLAMD_DEBUG0((
"colamd: col %d length %d < 0\n", col, Col[col].length));
516 Col[col].shared1.thickness = 1;
517 Col[col].shared2.score = 0;
518 Col[col].shared3.prev = Empty;
519 Col[col].shared4.degree_next = Empty;
528 for (row = 0; row < n_row; row++) {
530 Row[row].shared2.mark = -1;
533 for (col = 0; col < n_col; col++) {
537 cp_end = &A[p[col + 1]];
539 while (cp < cp_end) {
543 if (row < 0 || row >= n_row) {
544 stats[Colamd::Status] = Colamd::ErrorRowIndexOutOfBounds;
545 stats[Colamd::Info1] = col;
546 stats[Colamd::Info2] = row;
547 stats[Colamd::Info3] = n_row;
548 COLAMD_DEBUG0((
"colamd: row %d col %d out of bounds\n", row, col));
552 if (row <= last_row || Row[row].shared2.mark == col) {
555 stats[Colamd::Status] = Colamd::OkButJumbled;
556 stats[Colamd::Info1] = col;
557 stats[Colamd::Info2] = row;
558 (stats[Colamd::Info3])++;
559 COLAMD_DEBUG1((
"colamd: row %d col %d unsorted/duplicate\n", row, 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;
584 for (row = 1; row < n_row; row++) {
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;
592 if (stats[Status] == OkButJumbled) {
594 for (col = 0; col < n_col; col++) {
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;
607 for (col = 0; col < n_col; col++) {
609 cp_end = &A[p[col + 1]];
610 while (cp < cp_end) {
611 A[(Row[*cp++].shared1.p)++] = col;
618 for (row = 0; row < n_row; row++) {
619 Row[row].shared2.mark = 0;
620 Row[row].shared1.degree = Row[row].length;
625 if (stats[Status] == OkButJumbled) {
626 COLAMD_DEBUG0((
"colamd: reconstructing column form, matrix jumbled\n"));
636 for (col = 1; col < n_col; col++) {
639 Col[col].start = Col[col - 1].start + Col[col - 1].length;
640 p[col] = Col[col].start;
645 for (row = 0; row < n_row; row++) {
646 rp = &A[Row[row].start];
647 rp_end = rp + Row[row].length;
648 while (rp < rp_end) {
649 A[(p[*rp++])++] = row;
667template <
typename IndexType>
668static void init_scoring(
673 RowStructure<IndexType> Row[],
674 ColStructure<IndexType> Col[],
677 double knobs[NKnobs],
690 IndexType col_length;
694 IndexType dense_row_count;
695 IndexType dense_col_count;
702 dense_row_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs[Colamd::DenseRow] * n_col), n_col));
703 dense_col_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs[Colamd::DenseCol] * n_row), n_row));
704 COLAMD_DEBUG1((
"colamd: densecount: %d %d\n", dense_row_count, dense_col_count));
713 for (c = n_col - 1; c >= 0; c--) {
717 Col[c].shared2.order = --n_col2;
718 Col[c].kill_principal();
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) {
734 Col[c].shared2.order = --n_col2;
736 cp = &A[Col[c].start];
737 cp_end = cp + Col[c].length;
738 while (cp < cp_end) {
739 Row[*cp++].shared1.degree--;
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++) {
749 deg = Row[r].shared1.degree;
750 COLAMD_ASSERT(deg >= 0 && deg <= n_col);
751 if (deg > dense_row_count || deg == 0) {
757 max_deg = numext::maxi(max_deg, deg);
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()) {
776 cp = &A[Col[c].start];
778 cp_end = cp + Col[c].length;
779 while (cp < cp_end) {
783 if (Row[row].is_dead()) {
789 score += Row[row].shared1.degree - 1;
791 score = numext::mini(score, n_col);
794 col_length = (IndexType)(new_cp - &A[Col[c].start]);
795 if (col_length == 0) {
798 COLAMD_DEBUG2((
"Newly null killed: %d\n", c));
799 Col[c].shared2.order = --n_col2;
800 Col[c].kill_principal();
803 COLAMD_ASSERT(score >= 0);
804 COLAMD_ASSERT(score <= n_col);
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));
832 score = Col[c].shared2.score;
834 COLAMD_ASSERT(min_score >= 0);
835 COLAMD_ASSERT(min_score <= n_col);
836 COLAMD_ASSERT(score >= 0);
837 COLAMD_ASSERT(score <= n_col);
838 COLAMD_ASSERT(head[score] >= Empty);
841 next_col = head[score];
842 Col[c].shared3.prev = Empty;
843 Col[c].shared4.degree_next = next_col;
847 if (next_col != Empty) {
848 Col[next_col].shared3.prev = c;
853 min_score = numext::mini(min_score, score);
861 *p_max_deg = max_deg;
873template <
typename IndexType>
874static IndexType find_ordering
881 RowStructure<IndexType> Row[],
882 ColStructure<IndexType> Col[],
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;
926 tag_mark = Colamd::clear_mark(n_row, Row);
929 COLAMD_DEBUG1((
"colamd: Ordering, n_col2=%d\n", n_col2));
933 for (k = 0; k < n_col2; ) {
937 COLAMD_ASSERT(min_score >= 0);
938 COLAMD_ASSERT(min_score <= n_col);
939 COLAMD_ASSERT(head[min_score] >= Empty);
942 while (min_score < n_col && head[min_score] == Empty) {
945 pivot_col = head[min_score];
946 COLAMD_ASSERT(pivot_col >= 0 && pivot_col <= n_col);
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;
953 COLAMD_ASSERT(Col[pivot_col].is_alive());
954 COLAMD_DEBUG3((
"Pivot col: %d\n", pivot_col));
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;
965 COLAMD_ASSERT(pivot_col_thickness > 0);
969 needed_memory = numext::mini(pivot_col_score, n_col - k);
970 if (pfree + needed_memory >= Alen) {
971 pfree = Colamd::garbage_collection(n_row, n_col, Row, Col, A, &A[pfree]);
974 COLAMD_ASSERT(pfree + needed_memory < Alen);
976 tag_mark = Colamd::clear_mark(n_row, Row);
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) {
997 COLAMD_DEBUG4((
"Pivot col pattern %d %d\n", Row[row].is_alive(), row));
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;
1012 COLAMD_ASSERT(pfree < Alen);
1015 pivot_row_degree += col_thickness;
1021 Col[pivot_col].shared1.thickness = pivot_col_thickness;
1022 max_deg = numext::maxi(max_deg, pivot_row_degree);
1027 cp = &A[Col[pivot_col].start];
1028 cp_end = cp + Col[pivot_col].length;
1029 while (cp < cp_end) {
1032 COLAMD_DEBUG3((
"Kill row in pivot col: %d\n", row));
1038 pivot_row_length = pfree - pivot_row_start;
1039 if (pivot_row_length > 0) {
1041 pivot_row = A[Col[pivot_col].start];
1042 COLAMD_DEBUG3((
"Pivotal row is %d\n", pivot_row));
1046 COLAMD_ASSERT(pivot_row_length == 0);
1048 COLAMD_ASSERT(Col[pivot_col].length > 0 || pivot_row_length == 0);
1071 COLAMD_DEBUG3((
"** Computing set differences phase. **\n"));
1075 COLAMD_DEBUG3((
"Pivot row: "));
1077 rp = &A[pivot_row_start];
1078 rp_end = rp + pivot_row_length;
1079 while (rp < rp_end) {
1081 COLAMD_ASSERT(Col[col].is_alive() && col != pivot_col);
1082 COLAMD_DEBUG3((
"Col: %d\n", col));
1085 col_thickness = -Col[col].shared1.thickness;
1086 COLAMD_ASSERT(col_thickness > 0);
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;
1094 COLAMD_ASSERT(cur_score >= 0);
1095 COLAMD_ASSERT(cur_score <= n_col);
1096 COLAMD_ASSERT(cur_score >= Empty);
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;
1118 COLAMD_ASSERT(row != pivot_row);
1119 set_difference = row_mark - tag_mark;
1121 if (set_difference < 0) {
1122 COLAMD_ASSERT(Row[row].shared1.degree <= max_deg);
1123 set_difference = Row[row].shared1.degree;
1126 set_difference -= col_thickness;
1127 COLAMD_ASSERT(set_difference >= 0);
1129 if (set_difference == 0) {
1130 COLAMD_DEBUG3((
"aggressive absorption. Row: %d\n", row));
1134 Row[row].shared2.mark = set_difference + tag_mark;
1141 COLAMD_DEBUG3((
"** Adding set differences phase. **\n"));
1144 rp = &A[pivot_row_start];
1145 rp_end = rp + pivot_row_length;
1146 while (rp < rp_end) {
1149 COLAMD_ASSERT(Col[col].is_alive() && col != pivot_col);
1152 cp = &A[Col[col].start];
1155 cp_end = cp + Col[col].length;
1157 COLAMD_DEBUG4((
"Adding set diffs for Col: %d.\n", col));
1159 while (cp < cp_end) {
1162 COLAMD_ASSERT(row >= 0 && row < n_row);
1164 if (Row[row].is_dead()) {
1167 row_mark = Row[row].shared2.mark;
1168 COLAMD_ASSERT(row_mark > tag_mark);
1174 cur_score += row_mark - tag_mark;
1176 cur_score = numext::mini(cur_score, n_col);
1180 Col[col].length = (IndexType)(new_cp - &A[Col[col].start]);
1184 if (Col[col].length == 0) {
1185 COLAMD_DEBUG4((
"further mass elimination. Col: %d\n", col));
1187 Col[col].kill_principal();
1188 pivot_row_degree -= Col[col].shared1.thickness;
1189 COLAMD_ASSERT(pivot_row_degree >= 0);
1191 Col[col].shared2.order = k;
1193 k += Col[col].shared1.thickness;
1197 COLAMD_DEBUG4((
"Preparing supercol detection for Col: %d.\n", col));
1200 Col[col].shared2.score = cur_score;
1205 COLAMD_DEBUG4((
" Hash = %d, n_col = %d.\n", hash, n_col));
1206 COLAMD_ASSERT(hash <= n_col);
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;
1223 COLAMD_ASSERT(Col[col].is_alive());
1231 COLAMD_DEBUG3((
"** Supercolumn detection phase. **\n"));
1233 Colamd::detect_super_cols(Col, A, head, pivot_row_start, pivot_row_length);
1237 Col[pivot_col].kill_principal();
1241 tag_mark += (max_deg + 1);
1242 if (tag_mark >= max_mark) {
1243 COLAMD_DEBUG2((
"clearing tag_mark\n"));
1244 tag_mark = Colamd::clear_mark(n_row, Row);
1249 COLAMD_DEBUG3((
"** Finalize scores phase. **\n"));
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;
1280 cur_score = numext::mini(cur_score, max_score);
1281 COLAMD_ASSERT(cur_score >= 0);
1284 Col[col].shared2.score = cur_score;
1288 COLAMD_ASSERT(min_score >= 0);
1289 COLAMD_ASSERT(min_score <= n_col);
1290 COLAMD_ASSERT(cur_score >= 0);
1291 COLAMD_ASSERT(cur_score <= n_col);
1292 COLAMD_ASSERT(head[cur_score] >= Empty);
1293 next_col = head[cur_score];
1294 Col[col].shared4.degree_next = next_col;
1295 Col[col].shared3.prev = Empty;
1296 if (next_col != Empty) {
1297 Col[next_col].shared3.prev = col;
1299 head[cur_score] = col;
1302 min_score = numext::mini(min_score, cur_score);
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;
1339template <
typename IndexType>
1340static inline void order_children(
1344 ColStructure<IndexType> Col[],
1356 for (i = 0; i < n_col; i++) {
1358 COLAMD_ASSERT(col_is_dead(Col, i));
1359 if (!Col[i].is_dead_principal() && Col[i].shared2.order == Empty) {
1363 parent = Col[parent].shared1.parent;
1364 }
while (!Col[parent].is_dead_principal());
1370 order = Col[parent].shared2.order;
1373 COLAMD_ASSERT(Col[c].shared2.order == Empty);
1376 Col[c].shared2.order = order++;
1378 Col[c].shared1.parent = parent;
1381 c = Col[c].shared1.parent;
1386 }
while (Col[c].shared2.order == Empty);
1389 Col[parent].shared2.order = order;
1395 for (c = 0; c < n_col; c++) {
1396 p[Col[c].shared2.order] = c;
1432template <
typename IndexType>
1433static void detect_super_cols(
1436 ColStructure<IndexType> Col[],
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()) {
1469 hash = Col[col].shared3.hash;
1470 COLAMD_ASSERT(hash <= n_col);
1474 head_column = head[hash];
1475 if (head_column > Empty) {
1476 first_col = Col[head_column].shared3.headhash;
1478 first_col = -(head_column + 2);
1483 for (super_c = first_col; super_c != Empty; super_c = Col[super_c].shared4.hash_next) {
1484 COLAMD_ASSERT(Col[super_c].is_alive());
1485 COLAMD_ASSERT(Col[super_c].shared3.hash == hash);
1486 length = Col[super_c].length;
1493 for (c = Col[super_c].shared4.hash_next; c != Empty; c = Col[c].shared4.hash_next) {
1494 COLAMD_ASSERT(c != super_c);
1495 COLAMD_ASSERT(Col[c].is_alive());
1496 COLAMD_ASSERT(Col[c].shared3.hash == hash);
1499 if (Col[c].length != length || Col[c].shared2.score != Col[super_c].shared2.score) {
1505 cp1 = &A[Col[super_c].start];
1506 cp2 = &A[Col[c].start];
1508 for (i = 0; i < length; i++) {
1510 COLAMD_ASSERT(cp1->is_alive());
1511 COLAMD_ASSERT(cp2->is_alive());
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) {
1543 Col[head_column].shared3.headhash = Empty;
1563template <
typename IndexType>
1564static IndexType garbage_collection
1570 RowStructure<IndexType> Row[],
1571 ColStructure<IndexType> Col[],
1587 for (c = 0; c < n_col; c++) {
1588 if (Col[c].is_alive()) {
1589 psrc = &A[Col[c].start];
1592 COLAMD_ASSERT(pdest <= psrc);
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) {
1611 COLAMD_DEBUG3((
"Defrag row kill\n"));
1615 psrc = &A[Row[r].start];
1616 Row[r].shared2.first_column = *psrc;
1617 COLAMD_ASSERT(Row[r].is_alive());
1619 *psrc = ones_complement(r);
1627 while (psrc < pfree) {
1632 r = ones_complement(*psrc);
1633 COLAMD_ASSERT(r >= 0 && r < n_row);
1635 *psrc = Row[r].shared2.first_column;
1636 COLAMD_ASSERT(Row[r].is_alive());
1639 COLAMD_ASSERT(pdest <= psrc);
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]);
1652 COLAMD_ASSERT(debug_rows == 0);
1656 return ((IndexType)(pdest - &A[0]));
1667template <
typename IndexType>
1668static inline IndexType clear_mark
1673 RowStructure<IndexType> Row[]
1679 for (r = 0; r < n_row; r++) {
1680 if (Row[r].is_alive()) {
1681 Row[r].shared2.mark = 0;
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1