Mackey  V3.3
A C++ library for computing RO(G) graded homology
Smith.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <vector>
3 #include "Types/Aliases.hpp"
6 
7 namespace mackey {
8 
9  namespace implementation_details {
11  template<typename T, typename S>
12  struct Row_Column_Operation {
13  typedef S storage_t;
14  //if scalar=0 then this indicates a swap: start<->end
15  //otherwise this indicates an operation: end->end-scalar*start
16  T scalar;
17  S start;
18  S end;
19  Row_Column_Operation() = default;
20  Row_Column_Operation(T scalar, S start, S end) :scalar(scalar), start(start), end(end) {}
21  };
22 
24  template<typename scalar, typename storage>
25  struct Pivot {
26  scalar value;
27  storage row, col;
28  Pivot() = default;
29  template<typename T, bool a, bool b>
30  Pivot(IteratorNNZ<T, a, b> it) : value(it.value()), row(it.row()), col(it.col()) {}
31  };
32 
33  //Depending on whether we do full/partial pivoting or we use dense/sparse matrices, the Smith Normal Form may only conditionally need certain members
34  template<typename T, bool partial_pivoting = SFINAE::is_finite_cyclic<scalar_t<T>>::value, bool sparse = SFINAE::is_Sparse<T>::value>
35  struct smith_conditional_members;
36 
37  template<typename T>
38  struct smith_conditional_members<T, 0, 0> {
39  std::vector<int64_t> Cnorm;
40  std::vector<int64_t> Rnorm;
41  };
42 
43  template<typename T>
44  struct smith_conditional_members<T, 0, 1> {
45  std::vector<int64_t> Cnorm;
46  std::vector<int64_t> Rnorm;
47  char current;
48  Eigen::SparseMatrix<scalar_t<T>, 1, storage_t<T>> S_row;
49  std::vector<Row_Column_Operation<scalar_t<T>, storage_t<T>>> Pops, Qops;
50  };
51 
52  template<typename T>
53  struct smith_conditional_members<T, 1, 0> {
54  bool donerow;
55  std::vector<int64_t> Cnorm;
56  };
57 
58  template<typename T>
59  struct smith_conditional_members<T, 1, 1> {
60  bool donerow;
61  std::vector<Row_Column_Operation<scalar_t<T>, storage_t<T>>> Pops, Qops;
62  };
63  }
64 
76  template <typename _S, typename _R, typename _C>
77  struct SmithNormalForm : implementation_details::smith_conditional_members<_S> {
78  public:
80  _R P;
81  _R Qi;
82  _C Q;
83  _C Pi;
84 
94  SmithNormalForm(const _S& S, bool do_P = 1, bool do_Q = 1, bool do_sort = 1, bool do_verify = 0);
95 
96  private:
97 
98  void verify(const _S&) const;
99 
100  typedef _S S_t;
101  typedef _R R_t;
102  typedef _C C_t;
103  typedef typename S_t::StorageIndex ind;
104 
105  S_t S;
106  const ind M;
107  const ind N;
108  const bool doP;
109  const bool doQ;
110 
111  implementation_details::Pivot<scalar_t<S_t>, ind> piv;
112 
113  static constexpr bool partial_pivoting = SFINAE::is_finite_cyclic<typename S_t::Scalar>::value;
114  static constexpr bool sparse = SFINAE::is_Sparse<_S>::value;
115  static constexpr bool C_exists = !partial_pivoting || !sparse;
116  static constexpr bool R_exists = !partial_pivoting;
117 
118  typedef std::conditional_t<sparse && !partial_pivoting, typename Eigen::SparseMatrix<scalar_t<S_t>, 1, ind>, int*> S_row_t;
119 
120  int64_t metric(ind i, ind j) const;
121 
122  void initialize();
123  void initialize_norms();
124  bool initial_pivoting_per_loop(ind start);
125  bool doneRow(ind start);
126  bool doneCol(ind start);
127 
128  void eliminateRow(ind start);
129  void eliminateCol(ind start);
130  template<bool row, bool col, char increase_decrease_zero, typename iter>
131  void update_norms(iter it);
132 
133  void renderPQ();
134 
135  void row_pivot(ind start, bool tail = 0);
136  void col_pivot(ind start, bool tail = 0);
137 
138  void update(int = 0);
139 
140  template<bool onlyrow, bool onlycolumn>
141  void find_and_set_pivot(ind start);
142 
143  void sorter();
144  void compute();
145  };
146 
147 }
148 #include "impl/Smith.ipp"
Contains general template aliases.
decltype(test_finite_cyclic(std::declval< T >())) is_finite_cyclic
Detects if T=Z<N>
Definition: SFINAE.hpp:86
decltype(test_Sparse(std::declval< T * >())) is_Sparse
Detects if T is a sparse matrix.
Definition: SFINAE.hpp:78
Everything in this library is under this namespace.
Definition: Box.hpp:9
std::vector< T > tail(const T *const &ptr, int size, int start)
Given vector or array returns vector starting from index start.
Eigen::Matrix< scalar_t< T >, 1,-1 > row_vector_t
Dense row matrix.
Definition: Aliases.hpp:22
typename T::StorageIndex storage_t
Storage type of matrix.
Definition: Aliases.hpp:18
The Smith Normal Form and its coefficient matrices.
Definition: Smith.hpp:77
SmithNormalForm(const _S &S, bool do_P=1, bool do_Q=1, bool do_sort=1, bool do_verify=0)
Constructor computes the Smith Normal Form.
_R Qi
One of the coefficient matrices (A=Pi*S*Qi)
Definition: Smith.hpp:81
row_vector_t< _S > diagonal
The diagonal of the Smith normal form.
Definition: Smith.hpp:79
_R P
One of the coefficient matrices (S=P*A*Q)
Definition: Smith.hpp:80
_C Pi
One of the coefficient matrices (A=Pi*S*Qi)
Definition: Smith.hpp:83
_C Q
One of the coefficient matrices (S=P*A*Q)
Definition: Smith.hpp:82