21#ifndef EIGEN_SPARSE_AMD_H
22#define EIGEN_SPARSE_AMD_H
25#include "./InternalHeaderCheck.h"
32inline T amd_flip(
const T& i) {
36inline T amd_unflip(
const T& i) {
37 return i < 0 ? amd_flip(i) : i;
39template <
typename T0,
typename T1>
40inline bool amd_marked(
const T0* w,
const T1& j) {
43template <
typename T0,
typename T1>
44inline void amd_mark(
const T0* w,
const T1& j) {
45 return w[j] = amd_flip(w[j]);
49template <
typename StorageIndex>
50static StorageIndex cs_wclear(StorageIndex mark, StorageIndex lemax, StorageIndex* w, StorageIndex n) {
52 if (mark < 2 || (mark + lemax < 0)) {
53 for (k = 0; k < n; k++)
54 if (w[k] != 0) w[k] = 1;
61template <
typename StorageIndex>
62StorageIndex cs_tdfs(StorageIndex j, StorageIndex k, StorageIndex* head,
const StorageIndex* next, StorageIndex* post,
63 StorageIndex* stack) {
64 StorageIndex i, p, top = 0;
65 if (!head || !next || !post || !stack)
return (-1);
91template <
typename Scalar,
typename StorageIndex>
92void minimum_degree_ordering(SparseMatrix<Scalar, ColMajor, StorageIndex>& C,
93 PermutationMatrix<Dynamic, Dynamic, StorageIndex>& perm) {
96 StorageIndex d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1, k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi,
97 nvj, nvk, mark, wnvi, ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t, h;
99 StorageIndex n = StorageIndex(C.cols());
100 dense = std::max<StorageIndex>(16, StorageIndex(10 *
sqrt(
double(n))));
101 dense = (std::min)(n - 2, dense);
103 StorageIndex cnz = StorageIndex(C.nonZeros());
105 t = cnz + cnz / 5 + 2 * n;
109 ei_declare_aligned_stack_constructed_variable(StorageIndex, W, 8 * (n + 1), 0);
110 StorageIndex* len = W;
111 StorageIndex* nv = W + (n + 1);
112 StorageIndex* next = W + 2 * (n + 1);
113 StorageIndex* head = W + 3 * (n + 1);
114 StorageIndex* elen = W + 4 * (n + 1);
115 StorageIndex* degree = W + 5 * (n + 1);
116 StorageIndex* w = W + 6 * (n + 1);
117 StorageIndex* hhead = W + 7 * (n + 1);
118 StorageIndex* last = perm.indices().data();
121 StorageIndex* Cp = C.outerIndexPtr();
122 StorageIndex* Ci = C.innerIndexPtr();
123 for (k = 0; k < n; k++) len[k] = Cp[k + 1] - Cp[k];
127 for (i = 0; i <= n; i++) {
137 mark = internal::cs_wclear<StorageIndex>(0, 0, w, n);
140 for (i = 0; i < n; i++) {
141 bool has_diag =
false;
142 for (p = Cp[i]; p < Cp[i + 1]; ++p)
149 if (d == 1 && has_diag)
155 }
else if (d > dense || !has_diag)
163 if (head[d] != -1) last[head[d]] = i;
176 for (k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {
178 if (next[k] != -1) last[next[k]] = -1;
179 head[mindeg] = next[k];
185 if (elenk > 0 && cnz + mindeg >= nzmax) {
186 for (j = 0; j < n; j++) {
187 if ((p = Cp[j]) >= 0)
193 for (q = 0, p = 0; p < cnz;)
195 if ((j = amd_flip(Ci[p++])) >= 0)
199 for (k3 = 0; k3 < len[j] - 1; k3++) Ci[q++] = Ci[p++];
209 pk1 = (elenk == 0) ? p : cnz;
211 for (k1 = 1; k1 <= elenk + 1; k1++) {
221 for (k2 = 1; k2 <= ln; k2++) {
223 if ((nvi = nv[i]) <= 0)
continue;
227 if (next[i] != -1) last[next[i]] = last[i];
230 next[last[i]] = next[i];
232 head[degree[i]] = next[i];
240 if (elenk != 0) cnz = pk2;
247 mark = internal::cs_wclear<StorageIndex>(mark, lemax, w, n);
248 for (pk = pk1; pk < pk2; pk++)
251 if ((eln = elen[i]) <= 0)
continue;
254 for (p = Cp[i]; p <= Cp[i] + eln - 1; p++)
259 }
else if (w[e] != 0)
261 w[e] = degree[e] + wnvi;
267 for (pk = pk1; pk < pk2; pk++)
271 p2 = p1 + elen[i] - 1;
273 for (h = 0, d = 0, p = p1; p <= p2; p++)
289 elen[i] = pn - p1 + 1;
292 for (p = p2 + 1; p < p4; p++)
295 if ((nvj = nv[j]) <= 0)
continue;
310 degree[i] = std::min<StorageIndex>(degree[i], d);
314 len[i] = pn - p1 + 1;
322 lemax = std::max<StorageIndex>(lemax, dk);
323 mark = internal::cs_wclear<StorageIndex>(mark + lemax, lemax, w, n);
326 for (pk = pk1; pk < pk2; pk++) {
328 if (nv[i] >= 0)
continue;
332 for (; i != -1 && next[i] != -1; i = next[i], mark++) {
335 for (p = Cp[i] + 1; p <= Cp[i] + ln - 1; p++) w[Ci[p]] = mark;
337 for (j = next[i]; j != -1;)
339 ok = (len[j] == ln) && (elen[j] == eln);
340 for (p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++) {
341 if (w[Ci[p]] != mark) ok = 0;
360 for (p = pk1, pk = pk1; pk < pk2; pk++)
363 if ((nvi = -nv[i]) <= 0)
continue;
365 d = degree[i] + dk - nvi;
366 d = std::min<StorageIndex>(d, n - nel - nvi);
367 if (head[d] != -1) last[head[d]] = i;
371 mindeg = std::min<StorageIndex>(mindeg, d);
376 if ((len[k] = p - pk1) == 0)
381 if (elenk != 0) cnz = p;
385 for (i = 0; i < n; i++) Cp[i] = amd_flip(Cp[i]);
386 for (j = 0; j <= n; j++) head[j] = -1;
387 for (j = n; j >= 0; j--)
389 if (nv[j] > 0)
continue;
390 next[j] = head[Cp[j]];
393 for (e = n; e >= 0; e--)
395 if (nv[e] <= 0)
continue;
397 next[e] = head[Cp[e]];
401 for (k = 0, i = 0; i <= n; i++)
403 if (Cp[i] == -1) k = internal::cs_tdfs<StorageIndex>(i, k, head, next, perm.indices().data(), w);
406 perm.indices().conservativeResize(n);
Namespace containing all symbols from the Eigen library.
Definition Core:137
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)