51 #ifndef EIGEN_COLAMD_H 52 #define EIGEN_COLAMD_H 64 #define COLAMD_KNOBS 20 67 #define COLAMD_STATS 20 70 #define COLAMD_DENSE_ROW 0 73 #define COLAMD_DENSE_COL 1 76 #define COLAMD_DEFRAG_COUNT 2 79 #define COLAMD_STATUS 3 82 #define COLAMD_INFO1 4 83 #define COLAMD_INFO2 5 84 #define COLAMD_INFO3 6 88 #define COLAMD_OK_BUT_JUMBLED (1) 89 #define COLAMD_ERROR_A_not_present (-1) 90 #define COLAMD_ERROR_p_not_present (-2) 91 #define COLAMD_ERROR_nrow_negative (-3) 92 #define COLAMD_ERROR_ncol_negative (-4) 93 #define COLAMD_ERROR_nnz_negative (-5) 94 #define COLAMD_ERROR_p0_nonzero (-6) 95 #define COLAMD_ERROR_A_too_small (-7) 96 #define COLAMD_ERROR_col_length_negative (-8) 97 #define COLAMD_ERROR_row_index_out_of_bounds (-9) 98 #define COLAMD_ERROR_out_of_memory (-10) 99 #define COLAMD_ERROR_internal_error (-999) 105 #define COLAMD_MAX(a,b) (((a) > (b)) ? (a) : (b)) 106 #define COLAMD_MIN(a,b) (((a) < (b)) ? (a) : (b)) 108 #define ONES_COMPLEMENT(r) (-(r)-1) 112 #define COLAMD_EMPTY (-1) 119 #define DEAD_PRINCIPAL (-1) 120 #define DEAD_NON_PRINCIPAL (-2) 123 #define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) 124 #define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) 125 #define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) 126 #define COL_IS_DEAD(c) (Col [c].start < ALIVE) 127 #define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) 128 #define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) 129 #define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } 130 #define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } 131 #define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } 138 template <
typename Index>
172 template <
typename Index>
208 template <
typename Index>
210 {
return Index( ((n_col) + 1) *
sizeof (
colamd_col<Index>) /
sizeof (Index) ) ; }
212 template <
typename Index>
217 template <
typename Index>
220 template <
typename Index>
223 template <
typename Index>
226 template <
typename Index>
229 template <
typename Index>
232 template <
typename Index>
235 template <
typename Index>
240 #define COLAMD_DEBUG0(params) ; 241 #define COLAMD_DEBUG1(params) ; 242 #define COLAMD_DEBUG2(params) ; 243 #define COLAMD_DEBUG3(params) ; 244 #define COLAMD_DEBUG4(params) ; 246 #define COLAMD_ASSERT(expression) ((void) 0) 263 template <
typename Index>
266 if ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)
269 return (2 * (nnz) +
colamd_c (n_col) +
colamd_r (n_row) + (n_col) + ((nnz) / 5));
328 template <
typename Index>
329 static bool colamd(Index n_row, Index n_col, Index Alen, Index *A, Index *p,
double knobs[COLAMD_KNOBS], Index stats[COLAMD_STATS])
397 COLAMD_DEBUG0 ((
"colamd: number of entries negative %d\n", nnz)) ;
414 knobs = default_knobs ;
421 need = 2*nnz + n_col + Col_size + Row_size ;
429 COLAMD_DEBUG0 ((
"colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen));
433 Alen -= Col_size + Row_size ;
449 &n_row2, &n_col2, &max_deg) ;
454 n_col2, max_deg, 2*nnz) ;
488 template <
typename Index>
489 static Index init_rows_cols
514 for (col = 0 ; col < n_col ; col++)
516 Col [
col].start = p [
col] ;
517 Col [
col].length = p [col+1] - p [
col] ;
529 Col [
col].shared1.thickness = 1 ;
530 Col [
col].shared2.score = 0 ;
541 for (row = 0 ; row < n_row ; row++)
543 Row [
row].length = 0 ;
544 Row [
row].shared2.mark = -1 ;
547 for (col = 0 ; col < n_col ; col++)
552 cp_end = &A [p [col+1]] ;
559 if (row < 0 || row >= n_row)
565 COLAMD_DEBUG0 ((
"colamd: row %d col %d out of bounds\n", row, col)) ;
569 if (row <= last_row || Row [row].
shared2.mark == col)
577 COLAMD_DEBUG1 ((
"colamd: row %d col %d unsorted/duplicate\n",row,col));
580 if (Row [row].
shared2.mark != col)
592 Row [
row].shared2.mark =
col ;
602 Row [0].start = p [n_col] ;
603 Row [0].shared1.p = Row [0].start ;
604 Row [0].shared2.mark = -1 ;
605 for (row = 1 ; row < n_row ; row++)
607 Row [
row].start = Row [row-1].start + Row [row-1].length ;
608 Row [
row].shared1.p = Row [
row].start ;
609 Row [
row].shared2.mark = -1 ;
617 for (col = 0 ; col < n_col ; col++)
620 cp_end = &A [p [col+1]] ;
624 if (Row [row].
shared2.mark != col)
626 A [(Row [
row].shared1.p)++] = col ;
627 Row [
row].shared2.mark =
col ;
635 for (col = 0 ; col < n_col ; col++)
638 cp_end = &A [p [col+1]] ;
641 A [(Row [*cp++].shared1.p)++] = col ;
648 for (row = 0 ; row < n_row ; row++)
650 Row [
row].shared2.mark = 0 ;
651 Row [
row].shared1.degree = Row [
row].length ;
658 COLAMD_DEBUG0 ((
"colamd: reconstructing column form, matrix jumbled\n")) ;
668 p [0] = Col [0].start ;
669 for (col = 1 ; col < n_col ; col++)
673 Col [
col].start = Col [col-1].start + Col [col-1].length ;
674 p [
col] = Col [
col].start ;
679 for (row = 0 ; row < n_row ; row++)
681 rp = &A [Row [
row].start] ;
682 rp_end = rp + Row [
row].length ;
685 A [(p [*rp++])++] = row ;
704 template <
typename Index>
715 double knobs [COLAMD_KNOBS],
733 Index dense_row_count ;
734 Index dense_col_count ;
744 COLAMD_DEBUG1 ((
"colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
753 for (c = n_col-1 ; c >= 0 ; c--)
763 COLAMD_DEBUG1 ((
"colamd: null columns killed: %d\n", n_col - n_col2)) ;
768 for (c = n_col-1 ; c >= 0 ; c--)
776 if (deg > dense_col_count)
781 cp = &A [Col [c].
start] ;
782 cp_end = cp + Col [c].length ;
790 COLAMD_DEBUG1 ((
"colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
794 for (r = 0 ; r < n_row ; r++)
798 if (deg > dense_row_count || deg == 0)
810 COLAMD_DEBUG1 ((
"colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
820 for (c = n_col-1 ; c >= 0 ; c--)
828 cp = &A [Col [c].
start] ;
830 cp_end = cp + Col [c].length ;
848 col_length = (Index) (new_cp - &A [Col [c].
start]) ;
854 Col [c].shared2.order = --n_col2 ;
862 Col [c].length = col_length ;
863 Col [c].shared2.score =
score ;
866 COLAMD_DEBUG1 ((
"colamd: Dense, null, and newly-null columns killed: %d\n",
878 for (c = 0 ; c <= n_col ; c++)
885 for (c = n_col-1 ; c >= 0 ; c--)
891 c, Col [c].
shared2.score, min_score, n_col)) ;
904 next_col = head [
score] ;
928 *p_max_deg = max_deg ;
941 template <
typename Index>
942 static Index find_ordering
967 Index pivot_row_start ;
968 Index pivot_row_degree ;
969 Index pivot_row_length ;
970 Index pivot_col_score ;
971 Index needed_memory ;
983 Index set_difference ;
985 Index col_thickness ;
987 Index pivot_col_thickness ;
995 max_mark = INT_MAX - n_col ;
1003 for (k = 0 ; k < n_col2 ; )
1014 while (head [min_score] ==
COLAMD_EMPTY && min_score < n_col)
1018 pivot_col = head [min_score] ;
1020 next_col = Col [pivot_col].shared4.degree_next ;
1021 head [min_score] = next_col ;
1031 pivot_col_score = Col [pivot_col].shared2.score ;
1034 Col [pivot_col].shared2.order = k ;
1037 pivot_col_thickness = Col [pivot_col].shared1.thickness ;
1038 k += pivot_col_thickness ;
1043 needed_memory =
COLAMD_MIN (pivot_col_score, n_col - k) ;
1044 if (pfree + needed_memory >= Alen)
1058 pivot_row_start = pfree ;
1061 pivot_row_degree = 0 ;
1065 Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
1068 cp = &A [Col [pivot_col].start] ;
1069 cp_end = cp + Col [pivot_col].length ;
1080 rp = &A [Row [
row].start] ;
1081 rp_end = rp + Row [
row].length ;
1087 col_thickness = Col [
col].shared1.thickness ;
1091 Col [
col].shared1.thickness = -col_thickness ;
1095 pivot_row_degree += col_thickness ;
1101 Col [pivot_col].shared1.thickness = pivot_col_thickness ;
1102 max_deg =
COLAMD_MAX (max_deg, pivot_row_degree) ;
1108 cp = &A [Col [pivot_col].start] ;
1109 cp_end = cp + Col [pivot_col].length ;
1120 pivot_row_length = pfree - pivot_row_start ;
1121 if (pivot_row_length > 0)
1124 pivot_row = A [Col [pivot_col].start] ;
1156 COLAMD_DEBUG3 ((
"** Computing set differences phase. **\n")) ;
1162 rp = &A [pivot_row_start] ;
1163 rp_end = rp + pivot_row_length ;
1171 col_thickness = -Col [
col].shared1.thickness ;
1173 Col [
col].shared1.thickness = col_thickness ;
1177 cur_score = Col [
col].shared2.score ;
1178 prev_col = Col [
col].shared3.prev ;
1179 next_col = Col [
col].shared4.degree_next ;
1185 head [cur_score] = next_col ;
1189 Col [prev_col].shared4.degree_next = next_col ;
1193 Col [next_col].shared3.prev = prev_col ;
1198 cp = &A [Col [
col].start] ;
1199 cp_end = cp + Col [
col].length ;
1204 row_mark = Row [
row].shared2.mark ;
1211 set_difference = row_mark - tag_mark ;
1213 if (set_difference < 0)
1216 set_difference = Row [
row].shared1.degree ;
1219 set_difference -= col_thickness ;
1222 if (set_difference == 0)
1230 Row [
row].shared2.mark = set_difference + tag_mark ;
1241 rp = &A [pivot_row_start] ;
1242 rp_end = rp + pivot_row_length ;
1250 cp = &A [Col [
col].start] ;
1253 cp_end = cp + Col [
col].length ;
1262 row_mark = Row [
row].shared2.mark ;
1274 cur_score += row_mark - tag_mark ;
1280 Col [
col].length = (Index) (new_cp - &A [Col [col].
start]) ;
1284 if (Col [col].
length == 0)
1286 COLAMD_DEBUG4 ((
"further mass elimination. Col: %d\n", col)) ;
1289 pivot_row_degree -= Col [
col].shared1.thickness ;
1292 Col [
col].shared2.order = k ;
1294 k += Col [
col].shared1.thickness ;
1300 COLAMD_DEBUG4 ((
"Preparing supercol detection for Col: %d.\n", col)) ;
1303 Col [
col].shared2.score = cur_score ;
1308 COLAMD_DEBUG4 ((
" Hash = %d, n_col = %d.\n", hash, n_col)) ;
1311 head_column = head [
hash] ;
1316 first_col = Col [head_column].shared3.headhash ;
1317 Col [head_column].shared3.headhash =
col ;
1322 first_col = - (head_column + 2) ;
1323 head [
hash] = - (col + 2) ;
1325 Col [
col].shared4.hash_next = first_col ;
1328 Col [
col].shared3.hash = (Index) hash ;
1347 tag_mark += (max_deg + 1) ;
1348 if (tag_mark >= max_mark)
1359 rp = &A [pivot_row_start] ;
1362 rp_end = rp + pivot_row_length ;
1373 A [Col [
col].start + (Col [
col].length++)] = pivot_row ;
1378 cur_score = Col [
col].shared2.score + pivot_row_degree ;
1383 max_score = n_col - k - Col [
col].shared1.thickness ;
1386 cur_score -= Col [
col].shared1.thickness ;
1389 cur_score =
COLAMD_MIN (cur_score, max_score) ;
1393 Col [
col].shared2.score = cur_score ;
1402 next_col = head [cur_score] ;
1403 Col [
col].shared4.degree_next = next_col ;
1407 Col [next_col].shared3.prev =
col ;
1409 head [cur_score] =
col ;
1412 min_score =
COLAMD_MIN (min_score, cur_score) ;
1418 if (pivot_row_degree > 0)
1422 Row [pivot_row].start = pivot_row_start ;
1423 Row [pivot_row].length = (Index) (new_rp - &A[pivot_row_start]) ;
1424 Row [pivot_row].shared1.degree = pivot_row_degree ;
1425 Row [pivot_row].shared2.mark = 0 ;
1452 template <
typename Index>
1471 for (i = 0 ; i < n_col ; i++)
1514 for (c = 0 ; c < n_col ; c++)
1553 template <
typename Index>
1583 rp = &A [row_start] ;
1584 rp_end = rp + row_length ;
1599 head_column = head [
hash] ;
1606 first_col = - (head_column + 2) ;
1616 length = Col [super_c].
length ;
1623 for (c = Col [super_c].
shared4.hash_next ;
1631 if (Col [c].length != length ||
1639 cp1 = &A [Col [super_c].
start] ;
1640 cp2 = &A [Col [c].start] ;
1642 for (i = 0 ; i <
length ; i++)
1649 if (*cp1++ != *cp2++)
1666 Col [super_c].shared1.thickness += Col [c].shared1.thickness ;
1667 Col [c].shared1.parent = super_c ;
1672 Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;
1704 template <
typename Index>
1705 static Index garbage_collection
1729 for (c = 0 ; c < n_col ; c++)
1733 psrc = &A [Col [c].start] ;
1737 Col [c].start = (Index) (pdest - &A [0]) ;
1738 length = Col [c].length ;
1739 for (j = 0 ; j <
length ; j++)
1747 Col [c].length = (Index) (pdest - &A [Col [c].
start]) ;
1753 for (r = 0 ; r < n_row ; r++)
1757 if (Row [r].length == 0)
1766 psrc = &A [Row [r].start] ;
1767 Row [r].shared2.first_column = *psrc ;
1779 while (psrc < pfree)
1789 *psrc = Row [r].shared2.first_column ;
1794 Row [r].start = (Index) (pdest - &A [0]) ;
1795 length = Row [r].length ;
1796 for (j = 0 ; j <
length ; j++)
1804 Row [r].length = (Index) (pdest - &A [Row [r].
start]) ;
1813 return ((Index) (pdest - &A [0])) ;
1825 template <
typename Index>
1826 static inline Index clear_mark
1838 for (r = 0 ; r < n_row ; r++)
1842 Row [r].shared2.mark = 0 ;
static Index init_rows_cols(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > col[], Index A[], Index p[], Index stats[COLAMD_STATS])
#define COLAMD_DEBUG1(params)
union internal::colamd_col::@380 shared2
union internal::Colamd_Row::@383 shared1
Index colamd_c(Index n_col)
#define KILL_NON_PRINCIPAL_COL(c)
static void detect_super_cols(colamd_col< Index > Col[], Index A[], Index head[], Index row_start, Index row_length)
static void order_children(Index n_col, colamd_col< Index > Col[], Index p[])
Index colamd_recommended(Index nnz, Index n_row, Index n_col)
Returns the recommended value of Alen.
#define COLAMD_ERROR_A_not_present
static void init_scoring(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index head[], double knobs[COLAMD_KNOBS], Index *p_n_row2, Index *p_n_col2, Index *p_max_deg)
static void detect_super_cols(colamd_col< Index > Col[], Index A[], Index head[], Index row_start, Index row_length)
#define ROW_IS_MARKED_DEAD(row_mark)
#define COLAMD_ERROR_row_index_out_of_bounds
#define COLAMD_ERROR_nnz_negative
#define COLAMD_DEBUG0(params)
static Index clear_mark(Index n_row, Colamd_Row< Index > Row[])
#define COLAMD_ERROR_nrow_negative
#define COLAMD_DEFRAG_COUNT
static Index garbage_collection(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index *pfree)
static void init_scoring(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index head[], double knobs[COLAMD_KNOBS], Index *p_n_row2, Index *p_n_col2, Index *p_max_deg)
#define COLAMD_OK_BUT_JUMBLED
#define COLAMD_DEBUG2(params)
#define COLAMD_ERROR_p0_nonzero
static Index garbage_collection(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index *pfree)
union internal::colamd_col::@381 shared3
union internal::colamd_col::@382 shared4
static bool colamd(Index n_row, Index n_col, Index Alen, Index *A, Index *p, double knobs[COLAMD_KNOBS], Index stats[COLAMD_STATS])
Computes a column ordering using the column approximate minimum degree ordering.
#define COLAMD_ASSERT(expression)
#define COLAMD_ERROR_ncol_negative
static Index find_ordering(Index n_row, Index n_col, Index Alen, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index head[], Index n_col2, Index max_deg, Index pfree)
#define COLAMD_DEBUG3(params)
SegmentReturnType head(Index vecSize)
static void colamd_set_defaults(double knobs[COLAMD_KNOBS])
set default parameters The use of this routine is optional.
#define COLAMD_ERROR_p_not_present
static Index find_ordering(Index n_row, Index n_col, Index Alen, Colamd_Row< Index > Row[], colamd_col< Index > Col[], Index A[], Index head[], Index n_col2, Index max_deg, Index pfree)
Index colamd_r(Index n_row)
#define COLAMD_ERROR_A_too_small
#define COL_IS_DEAD_PRINCIPAL(c)
union internal::colamd_col::@379 shared1
static Index init_rows_cols(Index n_row, Index n_col, Colamd_Row< Index > Row[], colamd_col< Index > col[], Index A[], Index p[], Index stats[COLAMD_STATS])
#define COLAMD_ERROR_col_length_negative
#define KILL_PRINCIPAL_COL(c)
static void order_children(Index n_col, colamd_col< Index > Col[], Index p[])
#define ONES_COMPLEMENT(r)
static Index clear_mark(Index n_row, Colamd_Row< Index > Row[])
#define COLAMD_DEBUG4(params)