419 if (order < 0 || order > 3) {
420 std::string msg =
"Invalid ordering type "+
gammalib::str(order)+
421 "specified. The ordering type must be comprised in "
422 "[0,3]. Please specify a valid ordering type.";
427 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
428 std::cout << std::endl <<
"GSparseSymbolic::cs_amd entered" << std::endl;
429 std::cout <<
" order ......................: " << order << std::endl;
430 std::cout <<
" number of rows .............: " << A->
m_rows << std::endl;
431 std::cout <<
" number of columns ..........: " << A->
m_cols << std::endl;
432 std::cout <<
" number of non-zero elements : " << A->
m_elements << std::endl;
437 int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
438 k2, k3, jlast, ln, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
439 ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q;
452 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
453 std::cout <<
" Step 1: Construct matrix C" << std::endl;
469 dense = (int)
CS_MAX(16, 10 *
sqrt((
double)n));
470 dense =
CS_MIN(n-2, dense);
473 if (order == 1 && n == m) {
480 else if (order == 2) {
487 for (p2 = 0, j = 0; j < m; j++) {
490 if (ATp[j+1] - p > dense) {
493 for ( ; p < ATp[j+1]; p++) {
521 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
522 std::cout <<
" Matrix C " << C << std::endl;
529 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
530 std::cout <<
" Dropped diagonal entries from matrix C " << C << std::endl;
538 int* P =
new int[n+1];
541 int wrk_size = 8*(n+1);
542 int* wrk_int =
new int[wrk_size];
545 int elbow_room = cnz/5 + 2*n;
555 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
556 std::cout <<
" Added elbow room to matrix C " << C << std::endl;
561 int* nv = wrk_int + (n+1);
562 int* next = wrk_int + 2*(n+1);
563 int* head = wrk_int + 3*(n+1);
564 int* elen = wrk_int + 4*(n+1);
565 int* degree = wrk_int + 5*(n+1);
566 int* w = wrk_int + 6*(n+1);
567 int* hhead = wrk_int + 7*(n+1);
576 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
577 std::cout <<
" Step 2: Initialize quotient graph" << std::endl;
581 for (k = 0 ; k < n ; k++) {
582 len[k] = Cp[k+1] - Cp[k];
587 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
588 std::cout <<
" Non-zero elements per column: ";
589 for (k = 0 ; k <= n ; k++) {
590 std::cout <<
" " << len[k];
592 std::cout << std::endl;
596 for (i = 0 ; i <= n ; i++) {
621 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
622 std::cout <<
" Step 3: Initialize degree lists" << std::endl;
626 for (i = 0 ; i < n ; i++) {
640 else if (d > dense) {
650 if (head[d] != -1) last[head[d]] = i;
663 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
664 std::cout <<
" Step 4: Build permutations" << std::endl;
671 for (k = -1; mindeg < n && (k = head [mindeg]) == -1; mindeg++) ;
672 if (next[k] != -1) last [next[k]] = -1;
673 head[mindeg] = next[k];
679 if (elenk > 0 && cnz + mindeg >= nzmax) {
682 for (j = 0; j < n; j++) {
684 if ((p = Cp[j]) >= 0) {
691 for (q = 0, p = 0; p < cnz; ) {
693 if ((j =
CS_FLIP(Ci[p++])) >= 0) {
696 for (k3 = 0; k3 < len[j]-1; k3++) {
709 pk1 = (elenk == 0) ? p : cnz;
711 for (k1 = 1; k1 <= elenk + 1; k1++) {
726 for (k2 = 1 ; k2 <= ln ; k2++) {
728 if ((nvi = nv [i]) <= 0) {
735 last[next[i]] = last[i];
740 next[last[i]] = next[i];
743 head[degree[i]] = next[i];
768 for (pk = pk1 ; pk < pk2 ; pk++) {
771 if ((eln = elen[i]) <= 0) {
778 for (p = Cp[i]; p <= Cp[i] + eln - 1; p++) {
783 else if (w[e] != 0) {
784 w[e] = degree[e] + wnvi;
791 for (pk = pk1; pk < pk2; pk++) {
795 p2 = p1 + elen [i] - 1;
799 for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) {
817 elen[i] = pn - p1 + 1;
822 for (p = p2 + 1 ; p < p4 ; p++) {
824 if ((nvj = nv[j]) <= 0) {
843 degree[i] =
CS_MIN(degree[i], d);
847 len[i] = pn - p1 + 1;
858 lemax =
CS_MAX(lemax, dk);
861 mark =
cs_wclear(mark+lemax, lemax, w, n);
864 for (pk = pk1 ; pk < pk2 ; pk++) {
875 for ( ; i != -1 && next[i] != -1 ; i = next[i], mark++) {
878 for (p = Cp[i]+1 ; p <= Cp[i] + ln-1 ; p++) {
884 for (j = next[i]; j != -1; ) {
885 ok = (len[j] == ln) && (elen[j] == eln);
886 for (p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++) {
887 if (w[Ci[p]] != mark) {
913 for (p = pk1, pk = pk1; pk < pk2; pk++) {
915 if ((nvi = -nv[i]) <= 0) {
919 d = degree[i] + dk - nvi;
920 d =
CS_MIN(d, n - nel - nvi);
927 mindeg =
CS_MIN(mindeg, d);
936 if ((len [k] = p-pk1) == 0) {
952 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
953 std::cout <<
" Step 5: Postordering" << std::endl;
957 for (i = 0; i < n; i++) {
960 for (j = 0 ; j <= n ; j++) {
965 for (j = n ; j >= 0 ; j--) {
969 next[j] = head [Cp[j]];
974 for (e = n ; e >= 0 ; e--) {
979 next[e] = head[Cp[e]];
990 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
991 std::cout <<
" Step 6: Postorder the assembly tree" << std::endl;
995 for (k = 0, i = 0 ; i <= n ; i++) {
997 k =
cs_tdfs(i, k, head, next, P, w);
1005 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
1006 std::cout <<
" Permutation:" << std::endl;
1007 for (i = 0; i < n; ++i) {
1008 std::cout <<
" " << P[i];
1011 std::cout <<
"GSparseSymbolic::cs_amd finished" << std::endl;
1036 int i, j, k, J, p, q, jleaf;
1040 if (!parent || !post) {
1049 int* colcount =
new int[n];
1050 int* delta = colcount;
1053 int wrk_size = 4*n + (ata ? (n+m+1) : 0);
1054 int* wrk_int =
new int[wrk_size];
1060 int* ancestor = wrk_int;
1061 int* maxfirst = wrk_int + n;
1062 int* prevleaf = wrk_int + 2*n;
1063 int* first = wrk_int + 3*n;
1066 for (k = 0; k < wrk_size; ++k) {
1071 for (k = 0; k < n; k++) {
1073 delta[j] = (first[j] == -1) ? 1 : 0;
1074 for ( ; j != -1 && first[j] == -1; j = parent[j]) {
1089 init_ata(&AT, post, wrk_int, &head, &next);
1093 for (i = 0; i < n; i++) {
1098 for (k = 0; k < n; k++) {
1100 if (parent[j] != -1) {
1103 for (J =
HEAD(k,j); J != -1; J =
NEXT(J)) {
1106 for (p = ATp[J]; p < ATp[J+1]; p++) {
1108 q =
cs_leaf(i, j, first, maxfirst, prevleaf, ancestor, &jleaf);
1117 if (parent[j] != -1) {
1118 ancestor[j] = parent[j];
1123 for (j = 0; j < n; j++) {
1124 if (parent[j] != -1) {
1125 colcount[parent[j]] += colcount[j];