47 #ifndef EIGEN_COLAMD_H 
   48 #define EIGEN_COLAMD_H 
   60 #define COLAMD_KNOBS 20 
   63 #define COLAMD_STATS 20  
   66 #define COLAMD_DENSE_ROW 0 
   69 #define COLAMD_DENSE_COL 1 
   72 #define COLAMD_DEFRAG_COUNT 2 
   75 #define COLAMD_STATUS 3 
   78 #define COLAMD_INFO1 4 
   79 #define COLAMD_INFO2 5 
   80 #define COLAMD_INFO3 6 
   84 #define COLAMD_OK_BUT_JUMBLED     (1) 
   85 #define COLAMD_ERROR_A_not_present    (-1) 
   86 #define COLAMD_ERROR_p_not_present    (-2) 
   87 #define COLAMD_ERROR_nrow_negative    (-3) 
   88 #define COLAMD_ERROR_ncol_negative    (-4) 
   89 #define COLAMD_ERROR_nnz_negative   (-5) 
   90 #define COLAMD_ERROR_p0_nonzero     (-6) 
   91 #define COLAMD_ERROR_A_too_small    (-7) 
   92 #define COLAMD_ERROR_col_length_negative  (-8) 
   93 #define COLAMD_ERROR_row_index_out_of_bounds  (-9) 
   94 #define COLAMD_ERROR_out_of_memory    (-10) 
   95 #define COLAMD_ERROR_internal_error   (-999) 
  101 #define ONES_COMPLEMENT(r) (-(r)-1) 
  105 #define COLAMD_EMPTY (-1) 
  112 #define DEAD_PRINCIPAL    (-1) 
  113 #define DEAD_NON_PRINCIPAL  (-2) 
  116 #define ROW_IS_DEAD(r)      ROW_IS_MARKED_DEAD (Row[r].shared2.mark) 
  117 #define ROW_IS_MARKED_DEAD(row_mark)  (row_mark < ALIVE) 
  118 #define ROW_IS_ALIVE(r)     (Row [r].shared2.mark >= ALIVE) 
  119 #define COL_IS_DEAD(c)      (Col [c].start < ALIVE) 
  120 #define COL_IS_ALIVE(c)     (Col [c].start >= ALIVE) 
  121 #define COL_IS_DEAD_PRINCIPAL(c)  (Col [c].start == DEAD_PRINCIPAL) 
  122 #define KILL_ROW(r)     { Row [r].shared2.mark = DEAD ; } 
  123 #define KILL_PRINCIPAL_COL(c)   { Col [c].start = DEAD_PRINCIPAL ; } 
  124 #define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } 
  131 template <
typename IndexType>
 
  165 template <
typename IndexType>
 
  201 template <
typename IndexType>
 
  205 template <
typename IndexType>
 
  210 template <
typename IndexType>
 
  211 static IndexType 
init_rows_cols (IndexType n_row, IndexType n_col, Colamd_Row<IndexType> Row [], colamd_col<IndexType> 
col [], IndexType 
A [], IndexType p [], IndexType stats[
COLAMD_STATS] ); 
 
  213 template <
typename IndexType>
 
  214 static void init_scoring (IndexType n_row, IndexType n_col, Colamd_Row<IndexType> Row [], colamd_col<IndexType> Col [], IndexType 
A [], IndexType 
head [], 
double knobs[
COLAMD_KNOBS], IndexType *p_n_row2, IndexType *p_n_col2, IndexType *p_max_deg);
 
  216 template <
typename IndexType>
 
  217 static IndexType 
find_ordering (IndexType n_row, IndexType n_col, IndexType Alen, Colamd_Row<IndexType> Row [], colamd_col<IndexType> Col [], IndexType 
A [], IndexType 
head [], IndexType n_col2, IndexType max_deg, IndexType pfree);
 
  219 template <
typename IndexType>
 
  220 static void order_children (IndexType n_col, colamd_col<IndexType> Col [], IndexType p []);
 
  222 template <
typename IndexType>
 
  223 static void detect_super_cols (colamd_col<IndexType> Col [], IndexType 
A [], IndexType 
head [], IndexType row_start, IndexType row_length ) ;
 
  225 template <
typename IndexType>
 
  226 static IndexType 
garbage_collection (IndexType n_row, IndexType n_col, Colamd_Row<IndexType> Row [], colamd_col<IndexType> Col [], IndexType 
A [], IndexType *pfree) ;
 
  228 template <
typename IndexType>
 
  229 static inline  IndexType 
clear_mark (IndexType n_row, Colamd_Row<IndexType> Row [] ) ;
 
  233 #define COLAMD_DEBUG0(params) ; 
  234 #define COLAMD_DEBUG1(params) ; 
  235 #define COLAMD_DEBUG2(params) ; 
  236 #define COLAMD_DEBUG3(params) ; 
  237 #define COLAMD_DEBUG4(params) ; 
  239 #define COLAMD_ASSERT(expression) ((void) 0) 
  256 template <
typename IndexType>
 
  259   if ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)
 
  262     return (2 * (nnz) + 
colamd_c (n_col) + 
colamd_r (n_row) + (n_col) + ((nnz) / 5)); 
 
  321 template <
typename IndexType>
 
  390     COLAMD_DEBUG0 ((
"colamd: number of entries negative %d\n", nnz)) ;
 
  407     knobs = default_knobs ;
 
  414   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 ;
 
  442                 &n_row2, &n_col2, &max_deg) ;
 
  447                             n_col2, max_deg, 2*nnz) ;
 
  481 template <
typename IndexType>
 
  509     Col [
col].start = p [
col] ;
 
  512     if ((Col [
col].length) < 0) 
 
  522     Col [
col].shared1.thickness = 1 ;
 
  523     Col [
col].shared2.score = 0 ;
 
  536     Row [
row].length = 0 ;
 
  537     Row [
row].shared2.mark = -1 ;
 
  545     cp_end = &
A [p [
col+1]] ;
 
  552       if (row < 0 || row >= n_row)
 
  562       if (
row <= last_row || Row [
row].shared2.mark == 
col)
 
  573       if (Row [
row].shared2.mark != 
col)
 
  585       Row [
row].shared2.mark = 
col ;
 
  595   Row [0].start = p [n_col] ;
 
  596   Row [0].shared1.p = Row [0].start ;
 
  597   Row [0].shared2.mark = -1 ;
 
  600     Row [
row].start = Row [
row-1].start + Row [
row-1].length ;
 
  601     Row [
row].shared1.p = Row [
row].start ;
 
  602     Row [
row].shared2.mark = -1 ;
 
  613       cp_end = &
A [p [
col+1]] ;
 
  617         if (Row [
row].shared2.mark != 
col)
 
  619           A [(Row [
row].shared1.p)++] = 
col ;
 
  620           Row [
row].shared2.mark = 
col ;
 
  631       cp_end = &
A [p [
col+1]] ;
 
  634         A [(Row [*cp++].shared1.p)++] = 
col ;
 
  643     Row [
row].shared2.mark = 0 ;
 
  644     Row [
row].shared1.degree = Row [
row].length ;
 
  651     COLAMD_DEBUG0 ((
"colamd: reconstructing column form, matrix jumbled\n")) ;
 
  661     p [0] = Col [0].start ;
 
  666       Col [
col].start = Col [
col-1].start + Col [
col-1].length ;
 
  667       p [
col] = Col [
col].start ;
 
  674       rp = &
A [Row [
row].start] ;
 
  675       rp_end = rp + Row [
row].length ;
 
  678         A [(p [*rp++])++] = 
row ;
 
  697 template <
typename IndexType>
 
  722   IndexType col_length ;    
 
  726   IndexType dense_row_count ; 
 
  727   IndexType dense_col_count ; 
 
  728   IndexType min_score ;   
 
  737   COLAMD_DEBUG1 ((
"colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
 
  746   for (
c = n_col-1 ; 
c >= 0 ; 
c--)
 
  756   COLAMD_DEBUG1 ((
"colamd: null columns killed: %d\n", n_col - n_col2)) ;
 
  761   for (
c = n_col-1 ; 
c >= 0 ; 
c--)
 
  769     if (deg > dense_col_count)
 
  775       cp_end = cp + Col [
c].length ;
 
  783   COLAMD_DEBUG1 ((
"colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
 
  787   for (r = 0 ; r < n_row ; r++)
 
  791     if (deg > dense_row_count || deg == 0)
 
  803   COLAMD_DEBUG1 ((
"colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
 
  813   for (
c = n_col-1 ; 
c >= 0 ; 
c--)
 
  823     cp_end = cp + Col [
c].length ;
 
  841     col_length = (IndexType) (new_cp - &
A [Col [
c].start]) ;
 
  847       Col [
c].shared2.order = --n_col2 ;
 
  855       Col [
c].length = col_length ;
 
  856       Col [
c].shared2.score = score ;
 
  859   COLAMD_DEBUG1 ((
"colamd: Dense, null, and newly-null columns killed: %d\n",
 
  871   for (
c = 0 ; 
c <= n_col ; 
c++)
 
  878   for (
c = n_col-1 ; 
c >= 0 ; 
c--)
 
  884                       c, Col [
c].shared2.
score, min_score, n_col)) ;
 
  897       next_col = 
head [score] ;
 
  921   *p_max_deg = max_deg ;
 
  934 template <
typename IndexType>
 
  954   IndexType pivot_col ;   
 
  957   IndexType pivot_row ;   
 
  960   IndexType pivot_row_start ; 
 
  961   IndexType pivot_row_degree ;  
 
  962   IndexType pivot_row_length ;  
 
  963   IndexType pivot_col_score ; 
 
  964   IndexType needed_memory ;   
 
  969   IndexType max_score ;   
 
  970   IndexType cur_score ;   
 
  972   IndexType head_column ;   
 
  973   IndexType first_col ;   
 
  976   IndexType set_difference ;  
 
  977   IndexType min_score ;   
 
  978   IndexType col_thickness ;   
 
  980   IndexType pivot_col_thickness ; 
 
  988   max_mark = INT_MAX - n_col ;  
 
  996   for (k = 0 ; k < n_col2 ; )
 
 1011     pivot_col = 
head [min_score] ;
 
 1013     next_col = Col [pivot_col].shared4.degree_next ;
 
 1014     head [min_score] = next_col ;
 
 1024     pivot_col_score = Col [pivot_col].shared2.score ;
 
 1027     Col [pivot_col].shared2.order = k ;
 
 1030     pivot_col_thickness = Col [pivot_col].shared1.thickness ;
 
 1031     k += pivot_col_thickness ;
 
 1036     needed_memory = 
numext::mini(pivot_col_score, n_col - k) ;
 
 1037     if (pfree + needed_memory >= Alen)
 
 1051     pivot_row_start = pfree ;
 
 1054     pivot_row_degree = 0 ;
 
 1058     Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
 
 1061     cp = &
A [Col [pivot_col].start] ;
 
 1062     cp_end = cp + Col [pivot_col].length ;
 
 1073       rp = &
A [Row [
row].start] ;
 
 1074       rp_end = rp + Row [
row].length ;
 
 1080         col_thickness = Col [
col].shared1.thickness ;
 
 1084           Col [
col].shared1.thickness = -col_thickness ;
 
 1088           pivot_row_degree += col_thickness ;
 
 1094     Col [pivot_col].shared1.thickness = pivot_col_thickness ;
 
 1101     cp = &
A [Col [pivot_col].start] ;
 
 1102     cp_end = cp + Col [pivot_col].length ;
 
 1113     pivot_row_length = pfree - pivot_row_start ;
 
 1114     if (pivot_row_length > 0)
 
 1117       pivot_row = 
A [Col [pivot_col].start] ;
 
 1126     COLAMD_ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;
 
 1149     COLAMD_DEBUG3 ((
"** Computing set differences phase. **\n")) ;
 
 1155     rp = &
A [pivot_row_start] ;
 
 1156     rp_end = rp + pivot_row_length ;
 
 1164       col_thickness = -Col [
col].shared1.thickness ;
 
 1166       Col [
col].shared1.thickness = col_thickness ;
 
 1170       cur_score = Col [
col].shared2.score ;
 
 1171       prev_col = Col [
col].shared3.prev ;
 
 1172       next_col = Col [
col].shared4.degree_next ;
 
 1178         head [cur_score] = next_col ;
 
 1182         Col [prev_col].shared4.degree_next = next_col ;
 
 1186         Col [next_col].shared3.prev = prev_col ;
 
 1191       cp = &
A [Col [
col].start] ;
 
 1192       cp_end = cp + Col [
col].length ;
 
 1197         row_mark = Row [
row].shared2.mark ;
 
 1204         set_difference = row_mark - tag_mark ;
 
 1206         if (set_difference < 0)
 
 1209           set_difference = Row [
row].shared1.degree ;
 
 1212         set_difference -= col_thickness ;
 
 1215         if (set_difference == 0)
 
 1223           Row [
row].shared2.mark = set_difference + tag_mark ;
 
 1234     rp = &
A [pivot_row_start] ;
 
 1235     rp_end = rp + pivot_row_length ;
 
 1243       cp = &
A [Col [
col].start] ;
 
 1246       cp_end = cp + Col [
col].length ;
 
 1255         row_mark = Row [
row].shared2.mark ;
 
 1267         cur_score += row_mark - tag_mark ;
 
 1273       Col [
col].length = (IndexType) (new_cp - &
A [Col [
col].start]) ;
 
 1277       if (Col [
col].length == 0)
 
 1282         pivot_row_degree -= Col [
col].shared1.thickness ;
 
 1285         Col [
col].shared2.order = k ;
 
 1287         k += Col [
col].shared1.thickness ;
 
 1296         Col [
col].shared2.score = cur_score ;
 
 1301         COLAMD_DEBUG4 ((
" Hash = %d, n_col = %d.\n", hash, n_col)) ;
 
 1304         head_column = 
head [hash] ;
 
 1309           first_col = Col [head_column].shared3.headhash ;
 
 1310           Col [head_column].shared3.headhash = 
col ;
 
 1315           first_col = - (head_column + 2) ;
 
 1318         Col [
col].shared4.hash_next = first_col ;
 
 1321         Col [
col].shared3.hash = (IndexType) hash ;
 
 1340     tag_mark += (max_deg + 1) ;
 
 1341     if (tag_mark >= max_mark)
 
 1352     rp = &
A [pivot_row_start] ;
 
 1355     rp_end = rp + pivot_row_length ;
 
 1366       A [Col [
col].start + (Col [
col].length++)] = pivot_row ;
 
 1371       cur_score = Col [
col].shared2.score + pivot_row_degree ;
 
 1376       max_score = n_col - k - Col [
col].shared1.thickness ;
 
 1379       cur_score -= Col [
col].shared1.thickness ;
 
 1386       Col [
col].shared2.score = cur_score ;
 
 1395       next_col = 
head [cur_score] ;
 
 1396       Col [
col].shared4.degree_next = next_col ;
 
 1400         Col [next_col].shared3.prev = 
col ;
 
 1411     if (pivot_row_degree > 0)
 
 1415       Row [pivot_row].start  = pivot_row_start ;
 
 1416       Row [pivot_row].length = (IndexType) (new_rp - &
A[pivot_row_start]) ;
 
 1417       Row [pivot_row].shared1.degree = pivot_row_degree ;
 
 1418       Row [pivot_row].shared2.mark = 0 ;
 
 1445 template <
typename IndexType>
 
 1464   for (i = 0 ; i < n_col ; i++)
 
 1507   for (
c = 0 ; 
c < n_col ; 
c++)
 
 1546 template <
typename IndexType>
 
 1554   IndexType row_start,    
 
 1555   IndexType row_length    
 
 1571   IndexType head_column ;   
 
 1572   IndexType first_col ;   
 
 1576   rp = &
A [row_start] ;
 
 1577   rp_end = rp + row_length ;
 
 1592     head_column = 
head [hash] ;
 
 1599       first_col = - (head_column + 2) ;
 
 1609       length = Col [super_c].
length ;
 
 1624         if (Col [
c].length != length ||
 
 1632         cp1 = &
A [Col [super_c].
start] ;
 
 1633         cp2 = &
A [Col [
c].start] ;
 
 1635         for (i = 0 ; i < length ; i++)
 
 1642           if (*cp1++ != *cp2++)
 
 1657         COLAMD_ASSERT (Col [
c].shared2.score == Col [super_c].shared2.score) ;
 
 1659         Col [super_c].shared1.thickness += Col [
c].shared1.thickness ;
 
 1660         Col [
c].shared1.parent = super_c ;
 
 1665         Col [prev_c].shared4.hash_next = Col [
c].shared4.hash_next ;
 
 1697 template <
typename IndexType>
 
 1722   for (
c = 0 ; 
c < n_col ; 
c++)
 
 1726       psrc = &
A [Col [
c].start] ;
 
 1730       Col [
c].start = (IndexType) (pdest - &
A [0]) ;
 
 1731       length = Col [
c].length ;
 
 1732       for (j = 0 ; j < length ; j++)
 
 1740       Col [
c].length = (IndexType) (pdest - &
A [Col [
c].start]) ;
 
 1746   for (r = 0 ; r < n_row ; r++)
 
 1750       if (Row [r].length == 0)
 
 1759         psrc = &
A [Row [r].start] ;
 
 1760         Row [r].shared2.first_column = *psrc ;
 
 1772   while (psrc < pfree)
 
 1782       *psrc = Row [r].shared2.first_column ;
 
 1787       Row [r].start = (IndexType) (pdest - &
A [0]) ;
 
 1788       length = Row [r].length ;
 
 1789       for (j = 0 ; j < length ; j++)
 
 1797       Row [r].length = (IndexType) (pdest - &
A [Row [r].start]) ;
 
 1806   return ((IndexType) (pdest - &
A [0])) ;
 
 1818 template <
typename IndexType>
 
 1831   for (r = 0 ; r < n_row ; r++)
 
 1835       Row [r].shared2.mark = 0 ;