670 #ifdef MATLAB_MEX_FILE
675 #if !defined (NPRINT) || !defined (NDEBUG)
680 #define NULL ((void *) 0)
693 #define ID UF_long_id
694 #define Int_MAX UF_long_max
696 #define COLAMD_recommended amesos_colamd_l_recommended
697 #define COLAMD_set_defaults amesos_colamd_l_set_defaults
698 #define COLAMD_MAIN amesos_colamd_l
699 #define SYMAMD_MAIN amesos_symamd_l
700 #define COLAMD_report amesos_colamd_l_report
701 #define SYMAMD_report amesos_symamd_l_report
707 #define Int_MAX INT_MAX
709 #define COLAMD_recommended amesos_colamd_recommended
710 #define COLAMD_set_defaults amesos_colamd_set_defaults
711 #define COLAMD_MAIN amesos_colamd
712 #define SYMAMD_MAIN amesos_symamd
713 #define COLAMD_report amesos_colamd_report
714 #define SYMAMD_report amesos_symamd_report
781 #define PRIVATE static
783 #define DENSE_DEGREE(alpha,n) \
784 ((Int) MAX (16.0, (alpha) * sqrt ((double) (n))))
786 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
787 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
789 #define ONES_COMPLEMENT(r) (-(r)-1)
812 #define DEAD_PRINCIPAL (-1)
813 #define DEAD_NON_PRINCIPAL (-2)
816 #define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark)
817 #define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE)
818 #define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE)
819 #define COL_IS_DEAD(c) (Col [c].start < ALIVE)
820 #define COL_IS_ALIVE(c) (Col [c].start >= ALIVE)
821 #define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL)
822 #define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; }
823 #define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; }
824 #define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; }
830 #if defined (MATLAB_MEX_FILE) || defined (MATHWORKS)
832 #define INDEX(i) ((i)+1)
839 #define PRINTF(params) { if (amesos_colamd_printf != NULL) (void) amesos_colamd_printf params ; }
944 #define DEBUG0(params) { PRINTF (params) ; }
945 #define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; }
946 #define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; }
947 #define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; }
948 #define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; }
950 #ifdef MATLAB_MEX_FILE
951 #define ASSERT(expression) (mxAssert ((expression), ""))
953 #define ASSERT(expression) (assert (expression))
1004 #define DEBUG0(params) ;
1005 #define DEBUG1(params) ;
1006 #define DEBUG2(params) ;
1007 #define DEBUG3(params) ;
1008 #define DEBUG4(params) ;
1010 #define ASSERT(expression)
1040 static size_t t_add (
size_t a,
size_t b,
int *ok)
1042 (*ok) = (*ok) && ((a + b) >=
MAX (a,b)) ;
1043 return ((*ok) ? (a + b) : 0) ;
1047 static size_t t_mult (
size_t a,
size_t k,
int *ok)
1050 for (i = 0 ; i < k ; i++)
1052 s =
t_add (s, a, ok) ;
1058 #define COLAMD_C(n_col,ok) \
1059 ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int)))
1061 #define COLAMD_R(n_row,ok) \
1062 ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int)))
1076 if (
nnz < 0 || n_row < 0 || n_col < 0)
1083 s =
t_add (s, c, &ok) ;
1084 s =
t_add (s, r, &ok) ;
1085 s =
t_add (s, n_col, &ok) ;
1088 return (ok ? s : 0) ;
1158 void * (*allocate) (size_t, size_t),
1161 void (*release) (
void *)
1186 colamd_get_debug (
"symamd") ;
1193 DEBUG0 ((
"symamd: stats not present\n")) ;
1207 DEBUG0 ((
"symamd: A not present\n")) ;
1214 DEBUG0 ((
"symamd: p not present\n")) ;
1222 DEBUG0 ((
"symamd: n negative %d\n", n)) ;
1231 DEBUG0 ((
"symamd: number of entries negative %d\n", nnz)) ;
1239 DEBUG0 ((
"symamd: p[0] not zero %d\n", p [0])) ;
1248 knobs = default_knobs ;
1253 count = (
Int *) ((*allocate) (n+1,
sizeof (
Int))) ;
1257 DEBUG0 ((
"symamd: allocate count (size %d) failed\n", n+1)) ;
1261 mark = (
Int *) ((*allocate) (n+1,
sizeof (
Int))) ;
1265 (*release) ((
void *) count) ;
1266 DEBUG0 ((
"symamd: allocate mark (size %d) failed\n", n+1)) ;
1274 for (i = 0 ; i < n ; i++)
1279 for (j = 0 ; j < n ; j++)
1283 length = p [j+1] - p [j] ;
1290 (*release) ((
void *) count) ;
1291 (*release) ((
void *) mark) ;
1292 DEBUG0 ((
"symamd: col %d negative length %d\n", j, length)) ;
1296 for (pp = p [j] ; pp < p [j+1] ; pp++)
1299 if (i < 0 || i >= n)
1306 (*release) ((
void *) count) ;
1307 (*release) ((
void *) mark) ;
1308 DEBUG0 ((
"symamd: row %d col %d out of bounds\n", i, j)) ;
1312 if (i <= last_row || mark [i] == j)
1320 DEBUG1 ((
"symamd: row %d col %d unsorted/duplicate\n", i, j)) ;
1323 if (i > j && mark [i] != j)
1343 for (j = 1 ; j <= n ; j++)
1345 perm [j] = perm [j-1] + count [j-1] ;
1347 for (j = 0 ; j < n ; j++)
1349 count [j] = perm [j] ;
1357 M = (
Int *) ((*allocate) (Mlen,
sizeof (
Int))) ;
1358 DEBUG0 ((
"symamd: M is %d-by-%d with %d entries, Mlen = %g\n",
1359 n_row, n, mnz, (
double) Mlen)) ;
1364 (*release) ((
void *) count) ;
1365 (*release) ((
void *) mark) ;
1366 DEBUG0 ((
"symamd: allocate M (size %g) failed\n", (
double) Mlen)) ;
1375 for (j = 0 ; j < n ; j++)
1377 ASSERT (p [j+1] - p [j] >= 0) ;
1378 for (pp = p [j] ; pp < p [j+1] ; pp++)
1381 ASSERT (i >= 0 && i < n) ;
1385 M [count [i]++] = k ;
1386 M [count [j]++] = k ;
1395 DEBUG0 ((
"symamd: Duplicates in A.\n")) ;
1396 for (i = 0 ; i < n ; i++)
1400 for (j = 0 ; j < n ; j++)
1402 ASSERT (p [j+1] - p [j] >= 0) ;
1403 for (pp = p [j] ; pp < p [j+1] ; pp++)
1406 ASSERT (i >= 0 && i < n) ;
1407 if (i > j && mark [i] != j)
1410 M [count [i]++] = k ;
1411 M [count [j]++] = k ;
1421 (*release) ((
void *) count) ;
1422 (*release) ((
void *) mark) ;
1429 cknobs [i] = knobs [i] ;
1439 (void)
COLAMD_MAIN (n_row, n, (
Int) Mlen, M, perm, cknobs, stats) ;
1450 (*release) ((
void *) M) ;
1451 DEBUG0 ((
"symamd: done.\n")) ;
1499 colamd_get_debug (
"colamd") ;
1506 DEBUG0 ((
"colamd: stats not present\n")) ;
1520 DEBUG0 ((
"colamd: A not present\n")) ;
1527 DEBUG0 ((
"colamd: p not present\n")) ;
1535 DEBUG0 ((
"colamd: nrow negative %d\n", n_row)) ;
1543 DEBUG0 ((
"colamd: ncol negative %d\n", n_col)) ;
1552 DEBUG0 ((
"colamd: number of entries negative %d\n", nnz)) ;
1560 DEBUG0 ((
"colamd: p[0] not zero %d\n", p [0])) ;
1569 knobs = default_knobs ;
1581 need =
t_mult (nnz, 2, &ok) ;
1582 need =
t_add (need, n_col, &ok) ;
1583 need =
t_add (need, Col_size, &ok) ;
1584 need =
t_add (need, Row_size, &ok) ;
1586 if (!ok || need > (
size_t) Alen || need >
Int_MAX)
1592 DEBUG0 ((
"colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen));
1596 Alen -= Col_size + Row_size ;
1605 DEBUG0 ((
"colamd: Matrix invalid\n")) ;
1612 &n_row2, &n_col2, &max_deg) ;
1616 ngarbage =
find_ordering (n_row, n_col, Alen, Row, Col, A, p,
1617 n_col2, max_deg, 2*nnz, aggressive) ;
1628 DEBUG0 ((
"colamd: done.\n")) ;
1652 Int stats [COLAMD_STATS]
1705 for (col = 0 ; col < n_col ; col++)
1707 Col [col].start = p [col] ;
1708 Col [col].length = p [col+1] - p [col] ;
1710 if (Col [col].length < 0)
1716 DEBUG0 ((
"colamd: col %d length %d < 0\n", col, Col [col].length)) ;
1720 Col [col].shared1.thickness = 1 ;
1721 Col [col].shared2.score = 0 ;
1722 Col [col].shared3.prev =
EMPTY ;
1723 Col [col].shared4.degree_next =
EMPTY ;
1732 for (row = 0 ; row < n_row ; row++)
1734 Row [row].length = 0 ;
1735 Row [row].shared2.mark = -1 ;
1738 for (col = 0 ; col < n_col ; col++)
1743 cp_end = &A [p [col+1]] ;
1750 if (row < 0 || row >= n_row)
1756 DEBUG0 ((
"colamd: row %d col %d out of bounds\n", row, col)) ;
1760 if (row <= last_row || Row [row].shared2.mark == col)
1768 DEBUG1 ((
"colamd: row %d col %d unsorted/duplicate\n",row,col));
1771 if (Row [row].shared2.mark != col)
1773 Row [row].length++ ;
1779 Col [col].length-- ;
1783 Row [row].shared2.mark = col ;
1793 Row [0].start = p [n_col] ;
1794 Row [0].shared1.p = Row [0].start ;
1795 Row [0].shared2.mark = -1 ;
1796 for (row = 1 ; row < n_row ; row++)
1798 Row [row].start = Row [row-1].start + Row [row-1].length ;
1799 Row [row].shared1.p = Row [row].start ;
1800 Row [row].shared2.mark = -1 ;
1808 for (col = 0 ; col < n_col ; col++)
1811 cp_end = &A [p [col+1]] ;
1815 if (Row [row].shared2.mark != col)
1817 A [(Row [row].shared1.p)++] = col ;
1818 Row [row].shared2.mark = col ;
1826 for (col = 0 ; col < n_col ; col++)
1829 cp_end = &A [p [col+1]] ;
1832 A [(Row [*cp++].shared1.p)++] = col ;
1839 for (row = 0 ; row < n_row ; row++)
1841 Row [row].shared2.mark = 0 ;
1842 Row [row].shared1.degree = Row [row].length ;
1849 DEBUG0 ((
"colamd: reconstructing column form, matrix jumbled\n")) ;
1853 for (col = 0 ; col < n_col ; col++)
1855 p [col] = Col [col].length ;
1857 for (row = 0 ; row < n_row ; row++)
1859 rp = &A [Row [row].start] ;
1860 rp_end = rp + Row [row].length ;
1866 for (col = 0 ; col < n_col ; col++)
1880 p [0] = Col [0].start ;
1881 for (col = 1 ; col < n_col ; col++)
1885 Col [col].start = Col [col-1].start + Col [col-1].length ;
1886 p [col] = Col [col].start ;
1891 for (row = 0 ; row < n_row ; row++)
1893 rp = &A [Row [row].start] ;
1894 rp_end = rp + Row [row].length ;
1897 A [(p [*rp++])++] = row ;
1927 double knobs [COLAMD_KNOBS],
1945 Int dense_row_count ;
1946 Int dense_col_count ;
1961 dense_row_count = n_col-1 ;
1970 dense_col_count = n_row-1 ;
1978 DEBUG1 ((
"colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
1987 for (c = n_col-1 ; c >= 0 ; c--)
1997 DEBUG1 ((
"colamd: null columns killed: %d\n", n_col - n_col2)) ;
2002 for (c = n_col-1 ; c >= 0 ; c--)
2010 if (deg > dense_col_count)
2015 cp = &A [Col [c].
start] ;
2016 cp_end = cp + Col [c].length ;
2024 DEBUG1 ((
"colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
2028 for (r = 0 ; r < n_row ; r++)
2031 ASSERT (deg >= 0 && deg <= n_col) ;
2032 if (deg > dense_row_count || deg == 0)
2041 max_deg =
MAX (max_deg, deg) ;
2044 DEBUG1 ((
"colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
2054 for (c = n_col-1 ; c >= 0 ; c--)
2062 cp = &A [Col [c].
start] ;
2064 cp_end = cp + Col [c].length ;
2079 score =
MIN (score, n_col) ;
2082 col_length = (
Int) (new_cp - &A [Col [c].
start]) ;
2083 if (col_length == 0)
2087 DEBUG2 ((
"Newly null killed: %d\n", c)) ;
2088 Col [c].shared2.order = --n_col2 ;
2095 ASSERT (score <= n_col) ;
2096 Col [c].length = col_length ;
2097 Col [c].shared2.score = score ;
2100 DEBUG1 ((
"colamd: Dense, null, and newly-null columns killed: %d\n",
2109 debug_structures (n_row, n_col, Row, Col, A, n_col2) ;
2119 for (c = 0 ; c <= n_col ; c++)
2126 for (c = n_col-1 ; c >= 0 ; c--)
2131 DEBUG4 ((
"place %d score %d minscore %d ncol %d\n",
2132 c, Col [c].shared2.
score, min_score, n_col)) ;
2138 ASSERT (min_score >= 0) ;
2139 ASSERT (min_score <= n_col) ;
2141 ASSERT (score <= n_col) ;
2145 next_col = head [score] ;
2151 if (next_col !=
EMPTY)
2158 min_score =
MIN (min_score, score) ;
2168 DEBUG1 ((
"colamd: Live cols %d out of %d, non-princ: %d\n",
2169 debug_count, n_col, n_col-debug_count)) ;
2170 ASSERT (debug_count == n_col2) ;
2171 debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ;
2176 *p_n_col2 = n_col2 ;
2177 *p_n_row2 = n_row2 ;
2178 *p_max_deg = max_deg ;
2218 Int pivot_row_start ;
2219 Int pivot_row_degree ;
2220 Int pivot_row_length ;
2221 Int pivot_col_score ;
2234 Int set_difference ;
2238 Int pivot_col_thickness ;
2245 Int debug_step = 0 ;
2250 max_mark = INT_MAX - n_col ;
2251 tag_mark =
clear_mark (0, max_mark, n_row, Row) ;
2254 DEBUG1 ((
"colamd: Ordering, n_col2=%d\n", n_col2)) ;
2258 for (k = 0 ; k < n_col2 ; )
2262 if (debug_step % 100 == 0)
2264 DEBUG2 ((
"\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ;
2268 DEBUG3 ((
"\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ;
2271 debug_deg_lists (n_row, n_col, Row, Col, head,
2272 min_score, n_col2-k, max_deg) ;
2273 debug_matrix (n_row, n_col, Row, Col, A) ;
2279 ASSERT (min_score >= 0) ;
2280 ASSERT (min_score <= n_col) ;
2284 for (debug_d = 0 ; debug_d < min_score ; debug_d++)
2291 while (head [min_score] ==
EMPTY && min_score < n_col)
2295 pivot_col = head [min_score] ;
2296 ASSERT (pivot_col >= 0 && pivot_col <= n_col) ;
2297 next_col = Col [pivot_col].shared4.degree_next ;
2298 head [min_score] = next_col ;
2299 if (next_col !=
EMPTY)
2301 Col [next_col].shared3.prev =
EMPTY ;
2307 pivot_col_score = Col [pivot_col].shared2.score ;
2310 Col [pivot_col].shared2.order = k ;
2313 pivot_col_thickness = Col [pivot_col].shared1.thickness ;
2314 k += pivot_col_thickness ;
2315 ASSERT (pivot_col_thickness > 0) ;
2316 DEBUG3 ((
"Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ;
2320 needed_memory =
MIN (pivot_col_score, n_col - k) ;
2321 if (pfree + needed_memory >= Alen)
2326 ASSERT (pfree + needed_memory < Alen) ;
2328 tag_mark =
clear_mark (0, max_mark, n_row, Row) ;
2331 debug_matrix (n_row, n_col, Row, Col, A) ;
2338 pivot_row_start = pfree ;
2341 pivot_row_degree = 0 ;
2345 Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
2348 cp = &A [Col [pivot_col].start] ;
2349 cp_end = cp + Col [pivot_col].length ;
2358 rp = &A [Row [row].start] ;
2359 rp_end = rp + Row [row].length ;
2365 col_thickness = Col [col].shared1.thickness ;
2369 Col [col].shared1.thickness = -col_thickness ;
2373 pivot_row_degree += col_thickness ;
2380 Col [pivot_col].shared1.thickness = pivot_col_thickness ;
2381 max_deg =
MAX (max_deg, pivot_row_degree) ;
2385 debug_mark (n_row, Row, tag_mark, max_mark) ;
2391 cp = &A [Col [pivot_col].start] ;
2392 cp_end = cp + Col [pivot_col].length ;
2397 DEBUG3 ((
"Kill row in pivot col: %d\n", row)) ;
2403 pivot_row_length = pfree - pivot_row_start ;
2404 if (pivot_row_length > 0)
2407 pivot_row = A [Col [pivot_col].start] ;
2408 DEBUG3 ((
"Pivotal row is %d\n", pivot_row)) ;
2414 ASSERT (pivot_row_length == 0) ;
2416 ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;
2439 DEBUG3 ((
"** Computing set differences phase. **\n")) ;
2443 DEBUG3 ((
"Pivot row: ")) ;
2445 rp = &A [pivot_row_start] ;
2446 rp_end = rp + pivot_row_length ;
2451 DEBUG3 ((
"Col: %d\n", col)) ;
2454 col_thickness = -Col [col].shared1.thickness ;
2455 ASSERT (col_thickness > 0) ;
2456 Col [col].shared1.thickness = col_thickness ;
2460 cur_score = Col [col].shared2.score ;
2461 prev_col = Col [col].shared3.prev ;
2462 next_col = Col [col].shared4.degree_next ;
2463 ASSERT (cur_score >= 0) ;
2464 ASSERT (cur_score <= n_col) ;
2466 if (prev_col ==
EMPTY)
2468 head [cur_score] = next_col ;
2472 Col [prev_col].shared4.degree_next = next_col ;
2474 if (next_col !=
EMPTY)
2476 Col [next_col].shared3.prev = prev_col ;
2481 cp = &A [Col [col].start] ;
2482 cp_end = cp + Col [col].length ;
2487 row_mark = Row [row].shared2.mark ;
2493 ASSERT (row != pivot_row) ;
2494 set_difference = row_mark - tag_mark ;
2496 if (set_difference < 0)
2498 ASSERT (Row [row].shared1.degree <= max_deg) ;
2499 set_difference = Row [row].shared1.degree ;
2502 set_difference -= col_thickness ;
2503 ASSERT (set_difference >= 0) ;
2505 if (set_difference == 0 && aggressive)
2507 DEBUG3 ((
"aggressive absorption. Row: %d\n", row)) ;
2513 Row [row].shared2.mark = set_difference + tag_mark ;
2519 debug_deg_lists (n_row, n_col, Row, Col, head,
2520 min_score, n_col2-k-pivot_row_degree, max_deg) ;
2525 DEBUG3 ((
"** Adding set differences phase. **\n")) ;
2528 rp = &A [pivot_row_start] ;
2529 rp_end = rp + pivot_row_length ;
2537 cp = &A [Col [col].start] ;
2540 cp_end = cp + Col [col].length ;
2542 DEBUG4 ((
"Adding set diffs for Col: %d.\n", col)) ;
2548 ASSERT(row >= 0 && row < n_row) ;
2549 row_mark = Row [row].shared2.mark ;
2553 DEBUG4 ((
" Row %d, dead\n", row)) ;
2556 DEBUG4 ((
" Row %d, set diff %d\n", row, row_mark-tag_mark));
2557 ASSERT (row_mark >= tag_mark) ;
2563 cur_score += row_mark - tag_mark ;
2565 cur_score =
MIN (cur_score, n_col) ;
2569 Col [col].length = (
Int) (new_cp - &A [Col [col].
start]) ;
2573 if (Col [col].length == 0)
2575 DEBUG4 ((
"further mass elimination. Col: %d\n", col)) ;
2578 pivot_row_degree -= Col [col].shared1.thickness ;
2579 ASSERT (pivot_row_degree >= 0) ;
2581 Col [col].shared2.order = k ;
2583 k += Col [col].shared1.thickness ;
2589 DEBUG4 ((
"Preparing supercol detection for Col: %d.\n", col)) ;
2592 Col [col].shared2.score = cur_score ;
2597 DEBUG4 ((
" Hash = %d, n_col = %d.\n", hash, n_col)) ;
2600 head_column = head [hash] ;
2601 if (head_column >
EMPTY)
2605 first_col = Col [head_column].shared3.headhash ;
2606 Col [head_column].shared3.headhash = col ;
2611 first_col = - (head_column + 2) ;
2612 head [hash] = - (col + 2) ;
2614 Col [col].shared4.hash_next = first_col ;
2617 Col [col].shared3.hash = (
Int) hash ;
2626 DEBUG3 ((
"** Supercolumn detection phase. **\n")) ;
2634 Col, A, head, pivot_row_start, pivot_row_length) ;
2642 tag_mark =
clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ;
2646 debug_mark (n_row, Row, tag_mark, max_mark) ;
2651 DEBUG3 ((
"** Finalize scores phase. **\n")) ;
2654 rp = &A [pivot_row_start] ;
2657 rp_end = rp + pivot_row_length ;
2668 A [Col [col].start + (Col [col].length++)] = pivot_row ;
2673 cur_score = Col [col].shared2.score + pivot_row_degree ;
2678 max_score = n_col - k - Col [col].shared1.thickness ;
2681 cur_score -= Col [col].shared1.thickness ;
2684 cur_score =
MIN (cur_score, max_score) ;
2685 ASSERT (cur_score >= 0) ;
2688 Col [col].shared2.score = cur_score ;
2692 ASSERT (min_score >= 0) ;
2693 ASSERT (min_score <= n_col) ;
2694 ASSERT (cur_score >= 0) ;
2695 ASSERT (cur_score <= n_col) ;
2697 next_col = head [cur_score] ;
2698 Col [col].shared4.degree_next = next_col ;
2699 Col [col].shared3.prev =
EMPTY ;
2700 if (next_col !=
EMPTY)
2702 Col [next_col].shared3.prev = col ;
2704 head [cur_score] = col ;
2707 min_score =
MIN (min_score, cur_score) ;
2712 debug_deg_lists (n_row, n_col, Row, Col, head,
2713 min_score, n_col2-k, max_deg) ;
2718 if (pivot_row_degree > 0)
2722 Row [pivot_row].start = pivot_row_start ;
2723 Row [pivot_row].length = (
Int) (new_rp - &A[pivot_row_start]) ;
2724 ASSERT (Row [pivot_row].length > 0) ;
2725 Row [pivot_row].shared1.degree = pivot_row_degree ;
2726 Row [pivot_row].shared2.mark = 0 ;
2729 DEBUG1 ((
"Resurrect Pivot_row %d deg: %d\n",
2730 pivot_row, pivot_row_degree)) ;
2775 for (i = 0 ; i < n_col ; i++)
2818 for (c = 0 ; c < n_col ; c++)
2893 rp = &A [row_start] ;
2894 rp_end = rp + row_length ;
2904 hash = Col [col].shared3.hash ;
2909 head_column = head [hash] ;
2910 if (head_column >
EMPTY)
2912 first_col = Col [head_column].shared3.headhash ;
2916 first_col = - (head_column + 2) ;
2921 for (super_c = first_col ; super_c !=
EMPTY ;
2922 super_c = Col [super_c].shared4.hash_next)
2925 ASSERT (Col [super_c].shared3.hash == hash) ;
2926 length = Col [super_c].length ;
2933 for (c = Col [super_c].shared4.hash_next ;
2934 c !=
EMPTY ; c = Col [c].shared4.hash_next)
2938 ASSERT (Col [c].shared3.hash == hash) ;
2941 if (Col [c].length != length ||
2942 Col [c].shared2.score != Col [super_c].shared2.score)
2949 cp1 = &A [Col [super_c].start] ;
2950 cp2 = &A [Col [c].start] ;
2952 for (i = 0 ; i < length ; i++)
2959 if (*cp1++ != *cp2++)
2974 ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ;
2976 Col [super_c].shared1.thickness += Col [c].shared1.thickness ;
2977 Col [c].shared1.parent = super_c ;
2980 Col [c].shared2.order =
EMPTY ;
2982 Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;
2988 if (head_column >
EMPTY)
2991 Col [head_column].shared3.headhash =
EMPTY ;
2996 head [hash] =
EMPTY ;
3038 DEBUG2 ((
"Defrag..\n")) ;
3039 for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ;
3046 for (c = 0 ; c < n_col ; c++)
3050 psrc = &A [Col [c].start] ;
3054 Col [c].start = (
Int) (pdest - &A [0]) ;
3055 length = Col [c].length ;
3056 for (j = 0 ; j < length ; j++)
3064 Col [c].length = (
Int) (pdest - &A [Col [c].
start]) ;
3070 for (r = 0 ; r < n_row ; r++)
3083 psrc = &A [Row [r].start] ;
3084 Row [r].shared2.first_column = *psrc ;
3097 while (psrc < pfree)
3105 ASSERT (r >= 0 && r < n_row) ;
3107 *psrc = Row [r].shared2.first_column ;
3109 ASSERT (Row [r].length > 0) ;
3112 Row [r].start = (
Int) (pdest - &A [0]) ;
3113 length = Row [r].length ;
3114 for (j = 0 ; j < length ; j++)
3122 Row [r].length = (
Int) (pdest - &A [Row [r].
start]) ;
3123 ASSERT (Row [r].length > 0) ;
3130 ASSERT (debug_rows == 0) ;
3134 return ((
Int) (pdest - &A [0])) ;
3162 if (tag_mark <= 0 || tag_mark >= max_mark)
3164 for (r = 0 ; r < n_row ; r++)
3168 Row [r].shared2.mark = 0 ;
3185 Int stats [COLAMD_STATS]
3191 PRINTF ((
"\n%s version %d.%d, %s: ", method,
3196 PRINTF ((
"No statistics available.\n")) ;
3218 PRINTF((
"Matrix has unsorted or duplicate row indices.\n")) ;
3220 PRINTF((
"%s: number of duplicate or out-of-order row indices: %d\n",
3223 PRINTF((
"%s: last seen duplicate or out-of-order row index: %d\n",
3224 method,
INDEX (i2))) ;
3226 PRINTF((
"%s: last seen in column: %d",
3227 method,
INDEX (i1))) ;
3235 PRINTF((
"%s: number of dense or empty rows ignored: %d\n",
3238 PRINTF((
"%s: number of dense or empty columns ignored: %d\n",
3241 PRINTF((
"%s: number of garbage collections performed: %d\n",
3247 PRINTF((
"Array A (row indices of matrix) not present.\n")) ;
3252 PRINTF((
"Array p (column pointers for matrix) not present.\n")) ;
3257 PRINTF((
"Invalid number of rows (%d).\n", i1)) ;
3262 PRINTF((
"Invalid number of columns (%d).\n", i1)) ;
3267 PRINTF((
"Invalid number of nonzero entries (%d).\n", i1)) ;
3272 PRINTF((
"Invalid column pointer, p [0] = %d, must be zero.\n", i1));
3277 PRINTF((
"Array A too small.\n")) ;
3278 PRINTF((
" Need Alen >= %d, but given only Alen = %d.\n",
3285 ((
"Column %d has a negative number of nonzero entries (%d).\n",
3292 ((
"Row index (row %d) out of bounds (%d to %d) in column %d.\n",
3298 PRINTF((
"Out of memory.\n")) ;
3355 for (c = 0 ; c < n_col ; c++)
3361 DEBUG4 ((
"initial live col %5d %5d %5d\n", c, len, score)) ;
3365 cp = &A [Col [c].
start] ;
3375 i = Col [c].shared2.order ;
3376 ASSERT (i >= n_col2 && i < n_col) ;
3380 for (r = 0 ; r < n_row ; r++)
3389 rp = &A [Row [r].
start] ;
3438 if (n_col > 10000 && colamd_debug <= 0)
3443 DEBUG4 ((
"Degree lists: %d\n", min_score)) ;
3444 for (deg = 0 ; deg <= n_col ; deg++)
3452 while (col !=
EMPTY)
3461 DEBUG4 ((
"should %d have %d\n", should, have)) ;
3462 ASSERT (should == have) ;
3466 if (n_row > 10000 && colamd_debug <= 0)
3470 for (row = 0 ; row < n_row ; row++)
3505 ASSERT (tag_mark > 0 && tag_mark <= max_mark) ;
3506 if (n_row > 10000 && colamd_debug <= 0)
3510 for (r = 0 ; r < n_row ; r++)
3547 if (colamd_debug < 3)
3551 DEBUG3 ((
"DUMP MATRIX:\n")) ;
3552 for (r = 0 ; r < n_row ; r++)
3559 DEBUG3 ((
"start %d length %d degree %d\n",
3560 Row [r].
start, Row [r].length, Row [r].shared1.
degree)) ;
3561 rp = &A [Row [r].
start] ;
3562 rp_end = rp + Row [r].length ;
3570 for (c = 0 ; c < n_col ; c++)
3577 DEBUG3 ((
"start %d length %d shared1 %d shared2 %d\n",
3578 Col [c].
start, Col [c].length,
3580 cp = &A [Col [c].
start] ;
3581 cp_end = cp + Col [c].length ;
3597 f = fopen (
"debug",
"r") ;
3598 if (f == (FILE *)
NULL)
3604 fscanf (f,
"%d", &colamd_debug) ;
3607 DEBUG0 ((
"%s: debug version, D = %d (THIS WILL BE SLOW!)\n",
3608 method, colamd_debug)) ;
#define COLAMD_C(n_col, ok)
union Colamd_Row_struct::@17 shared2
PRIVATE void init_scoring(Int n_row, Int n_col, Colamd_Row Row[], Colamd_Col Col[], Int A[], Int head[], double knobs[COLAMD_KNOBS], Int *p_n_row2, Int *p_n_col2, Int *p_max_deg)
#define COLAMD_ERROR_ncol_negative
#define COLAMD_MAIN_VERSION
#define COLAMD_R(n_row, ok)
#define KILL_PRINCIPAL_COL(c)
UF_long CHOLMOD() nnz(cholmod_sparse *A, cholmod_common *Common)
#define COLAMD_ERROR_p0_nonzero
PRIVATE Int garbage_collection(Int n_row, Int n_col, Colamd_Row Row[], Colamd_Col Col[], Int A[], Int *pfree)
#define KILL_NON_PRINCIPAL_COL(c)
PRIVATE Int clear_mark(Int tag_mark, Int max_mark, Int n_row, Colamd_Row Row[])
#define COLAMD_ERROR_row_index_out_of_bounds
struct Colamd_Row_struct Colamd_Row
PRIVATE void detect_super_cols(Colamd_Col Col[], Int A[], Int head[], Int row_start, Int row_length)
union Colamd_Row_struct::@16 shared1
#define COL_IS_DEAD_PRINCIPAL(c)
PRIVATE Int find_ordering(Int n_row, Int n_col, Int Alen, Colamd_Row Row[], Colamd_Col Col[], Int A[], Int head[], Int n_col2, Int max_deg, Int pfree, Int aggressive)
PRIVATE void print_report(char *method, Int stats[COLAMD_STATS])
#define COLAMD_ERROR_nrow_negative
#define COLAMD_ERROR_out_of_memory
#define COLAMD_OK_BUT_JUMBLED
#define COLAMD_recommended
#define DENSE_DEGREE(alpha, n)
#define COLAMD_AGGRESSIVE
#define COLAMD_DEFRAG_COUNT
union Colamd_Col_struct::@13 shared2
#define COLAMD_ERROR_nnz_negative
int CHOLMOD() start(cholmod_common *Common)
PRIVATE Int init_rows_cols(Int n_row, Int n_col, Colamd_Row Row[], Colamd_Col Col[], Int A[], Int p[], Int stats[COLAMD_STATS])
#define COLAMD_ERROR_A_not_present
#define COLAMD_ERROR_A_too_small
#define ROW_IS_MARKED_DEAD(row_mark)
union Colamd_Col_struct::@12 shared1
#define COLAMD_SUB_VERSION
#define ONES_COMPLEMENT(r)
static size_t t_mult(size_t a, size_t k, int *ok)
#define ASSERT(expression)
static size_t t_add(size_t a, size_t b, int *ok)
#define COLAMD_ERROR_col_length_negative
#define COLAMD_set_defaults
struct Colamd_Col_struct Colamd_Col
union Colamd_Col_struct::@15 shared4
union Colamd_Col_struct::@14 shared3
PRIVATE void order_children(Int n_col, Colamd_Col Col[], Int p[])
#define COLAMD_ERROR_p_not_present