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)