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>
   213 template <
typename IndexType>
   216 template <
typename IndexType>
   219 template <
typename IndexType>
   222 template <
typename IndexType>
   225 template <
typename IndexType>
   228 template <
typename IndexType>
   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>
   322 static bool colamd(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *A, IndexType *p, 
double knobs[COLAMD_KNOBS], IndexType stats[COLAMD_STATS])
   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>
   482 static IndexType init_rows_cols  
   507   for (col = 0 ; col < n_col ; col++)
   509     Col [
col].start = p [
col] ;
   510     Col [
col].length = p [col+1] - p [
col] ;
   512     if ((Col [col].
length) < 0) 
   518       COLAMD_DEBUG0 ((
"colamd: col %d length %d < 0\n", col, Col [col].length)) ;
   522     Col [
col].shared1.thickness = 1 ;
   523     Col [
col].shared2.score = 0 ;
   534   for (row = 0 ; row < n_row ; row++)
   536     Row [
row].length = 0 ;
   537     Row [
row].shared2.mark = -1 ;
   540   for (col = 0 ; col < n_col ; col++)
   545     cp_end = &A [p [col+1]] ;
   552       if (row < 0 || row >= n_row)
   558         COLAMD_DEBUG0 ((
"colamd: row %d col %d out of bounds\n", row, col)) ;
   562       if (row <= last_row || Row [row].
shared2.mark == col)
   570         COLAMD_DEBUG1 ((
"colamd: row %d col %d unsorted/duplicate\n",row,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 ;
   598   for (row = 1 ; row < n_row ; row++)
   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 ;
   610     for (col = 0 ; col < n_col ; col++)
   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 ;
   628     for (col = 0 ; col < n_col ; col++)
   631       cp_end = &A [p [col+1]] ;
   634         A [(Row [*cp++].shared1.p)++] = col ;
   641   for (row = 0 ; row < n_row ; row++)
   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 ;
   662     for (col = 1 ; col < n_col ; col++)
   666       Col [
col].start = Col [col-1].start + Col [col-1].length ;
   667       p [
col] = Col [
col].start ;
   672     for (row = 0 ; row < n_row ; row++)
   674       rp = &A [Row [
row].start] ;
   675       rp_end = rp + Row [
row].length ;
   678         A [(p [*rp++])++] = row ;
   697 template <
typename IndexType>
   708     double knobs [COLAMD_KNOBS],
   722   IndexType col_length ;    
   726   IndexType dense_row_count ; 
   727   IndexType dense_col_count ; 
   728   IndexType min_score ;   
   735   dense_row_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs [
COLAMD_DENSE_ROW] * n_col), n_col)) ;
   736   dense_col_count = numext::maxi(IndexType(0), numext::mini(IndexType(knobs [
COLAMD_DENSE_COL] * n_row), n_row)) ;
   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)
   774       cp = &A [Col [c].
start] ;
   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)
   800       max_deg = numext::maxi(max_deg, deg) ;
   803   COLAMD_DEBUG1 ((
"colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
   813   for (c = n_col-1 ; c >= 0 ; c--)
   821     cp = &A [Col [c].
start] ;
   823     cp_end = cp + Col [c].length ;
   838       score = numext::mini(score, n_col) ;
   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] ;
   910       min_score = numext::mini(min_score, score) ;
   921   *p_max_deg = max_deg ;
   934 template <
typename IndexType>
   935 static IndexType find_ordering 
   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 ; )
  1007     while (head [min_score] == 
COLAMD_EMPTY && min_score < n_col)
  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 ;
  1095     max_deg = numext::maxi(max_deg, pivot_row_degree) ;
  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] ;
  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 ;
  1269         cur_score = numext::mini(cur_score, n_col) ;
  1273       Col [
col].length = (IndexType) (new_cp - &A [Col [col].
start]) ;
  1277       if (Col [col].
length == 0)
  1279         COLAMD_DEBUG4 ((
"further mass elimination. Col: %d\n", col)) ;
  1282         pivot_row_degree -= Col [
col].shared1.thickness ;
  1285         Col [
col].shared2.order = k ;
  1287         k += Col [
col].shared1.thickness ;
  1293         COLAMD_DEBUG4 ((
"Preparing supercol detection for Col: %d.\n", col)) ;
  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) ;
  1316           head [
hash] = - (col + 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 ;
  1382       cur_score = numext::mini(cur_score, max_score) ;
  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 ;
  1402       head [cur_score] = 
col ;
  1405       min_score = numext::mini(min_score, cur_score) ;
  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 ;
  1616       for (c = Col [super_c].
shared4.hash_next ;
  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++)
  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>
  1698 static IndexType garbage_collection  
  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>
  1819 static inline  IndexType clear_mark  
  1831   for (r = 0 ; r < n_row ; r++)
  1835       Row [r].shared2.mark = 0 ;
 
union internal::colamd_col::@503 shared2
#define COLAMD_DEBUG1(params)
static void detect_super_cols(colamd_col< IndexType > Col [], IndexType A [], IndexType head [], IndexType row_start, IndexType row_length)
union internal::colamd_col::@505 shared4
static IndexType garbage_collection(IndexType n_row, IndexType n_col, Colamd_Row< IndexType > Row [], colamd_col< IndexType > Col [], IndexType A [], IndexType *pfree)
static IndexType garbage_collection(IndexType n_row, IndexType n_col, Colamd_Row< IndexType > Row [], colamd_col< IndexType > Col [], IndexType A [], IndexType *pfree)
#define KILL_NON_PRINCIPAL_COL(c)
static void detect_super_cols(colamd_col< IndexType > Col [], IndexType A [], IndexType head [], IndexType row_start, IndexType row_length)
#define COLAMD_ERROR_A_not_present
EIGEN_DEVICE_FUNC ColXpr col(Index i)
This is the const version of col(). */. 
static IndexType clear_mark(IndexType n_row, Colamd_Row< IndexType > Row [])
#define ROW_IS_MARKED_DEAD(row_mark)
#define COLAMD_ERROR_row_index_out_of_bounds
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])
#define COLAMD_ERROR_nnz_negative
#define COLAMD_DEBUG0(params)
static IndexType clear_mark(IndexType n_row, Colamd_Row< IndexType > Row [])
#define COLAMD_ERROR_nrow_negative
union internal::colamd_col::@504 shared3
#define COLAMD_DEFRAG_COUNT
union internal::Colamd_Row::@506 shared1
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)
#define COLAMD_OK_BUT_JUMBLED
static bool colamd(IndexType n_row, IndexType n_col, IndexType Alen, IndexType *A, IndexType *p, double knobs[COLAMD_KNOBS], IndexType stats[COLAMD_STATS])
Computes a column ordering using the column approximate minimum degree ordering. 
union internal::colamd_col::@502 shared1
#define COLAMD_DEBUG2(params)
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])
EIGEN_DEVICE_FUNC SegmentReturnType head(Index n)
This is the const version of head(Index). 
#define COLAMD_ERROR_p0_nonzero
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)
#define COLAMD_ASSERT(expression)
#define COLAMD_ERROR_ncol_negative
IndexType colamd_r(IndexType n_row)
#define COLAMD_DEBUG3(params)
static void colamd_set_defaults(double knobs[COLAMD_KNOBS])
set default parameters The use of this routine is optional. 
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)
IndexType colamd_c(IndexType n_col)
#define COLAMD_ERROR_p_not_present
EIGEN_DEVICE_FUNC RowXpr row(Index i)
This is the const version of row(). */. 
#define COLAMD_ERROR_A_too_small
#define COL_IS_DEAD_PRINCIPAL(c)
#define COLAMD_ERROR_col_length_negative
static void order_children(IndexType n_col, colamd_col< IndexType > Col [], IndexType p [])
#define KILL_PRINCIPAL_COL(c)
#define ONES_COMPLEMENT(r)
IndexType colamd_recommended(IndexType nnz, IndexType n_row, IndexType n_col)
Returns the recommended value of Alen. 
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)
static void order_children(IndexType n_col, colamd_col< IndexType > Col [], IndexType p [])
#define COLAMD_DEBUG4(params)