CMR  1.3.0
linear_algebra.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "gcd.hpp"
4 #include "matrix_transposed.hpp"
5 #include "matrix_permuted.hpp"
6 #include "matrix.hpp"
7 
8 namespace tu
9 {
10  template <typename Matrix>
11  void matrix_row_combine(Matrix& matrix, size_t row1, size_t row2, long long ul, long long ur, long long ll, long long lr)
12  {
13  assert(abs(ul * lr - ll * ur) == 1);
14  for (size_t c = 0; c < matrix.size2(); ++c)
15  {
16  long long x = matrix(row1, c);
17  long long y = matrix(row2, c);
18  if ((abs(x) > (1L << 31)) || (abs(y) > (1L << 31))
19  || (abs(ul) > (1L << 31)) || (abs(ur) > (1L << 31)))
20  {
21  throw std::runtime_error("Numbers too large.");
22  }
23  matrix(row1, c) = ul * x + ur * y;
24  matrix(row2, c) = ll * x + lr * y;
25  }
26  }
27 
28  template <typename Matrix>
29  bool matrix_row_gcd(Matrix& matrix, size_t row1, size_t row2, size_t column)
30  {
31  if (matrix(row2, column) == 0)
32  return false;
33 
34  long long x = matrix(row1, column);
35  long long y = matrix(row2, column);
36  if (x > (1L << 31) || x < -1 * (1L << 32) || y > (1L << 31) || y < -1 * (1L << 32))
37  {
38  throw std::runtime_error("Numbers too large.");
39  }
40  long long s, t;
41  long long g = gcd(x, y, s, t);
42  if (s == 0)
43  {
45  matrix_row_combine(matrix, row1, row2, 1, 0, -x / y, 1);
46  }
47  else
48  matrix_row_combine(matrix, row1, row2, s, t, y / g, -x / g);
49 
50  return true;
51  }
52 
53  template <typename Matrix>
54  bool matrix_column_gcd(Matrix& matrix, size_t column1, size_t column2, size_t row)
55  {
57  return matrix_row_gcd(transposed, column1, column2, row);
58  }
59 
60  template <typename InputMatrix, typename OutputMatrix>
61  size_t matrix_find_column_basis_and_transform_integral(const InputMatrix& input_matrix, OutputMatrix& output_matrix,
62  std::vector <size_t>& column_basis)
63  {
64  output_matrix = input_matrix;
65  column_basis.clear();
66  matrix_permuted <OutputMatrix> permuted_matrix(output_matrix);
67  size_t rank = 0;
68 
69  for (rank = 0; rank < permuted_matrix.size1(); ++rank)
70  {
72  bool found = false;
73  for (size_t c = rank; c < permuted_matrix.size2(); ++c)
74  {
75  if (matrix_column_zero(permuted_matrix, c, rank, permuted_matrix.size1()))
76  continue;
77 
78  found = true;
79  matrix_permute2(permuted_matrix, rank, c);
80  break;
81  }
82 
83  if (!found)
84  break;
85 
87  for (size_t r = rank; r < permuted_matrix.size1(); ++r)
88  {
89  if (permuted_matrix(r, rank) != 0)
90  {
91  matrix_permute1(output_matrix, rank, r);
92  break;
93  }
94  }
95 
97  for (size_t r = rank + 1; r < permuted_matrix.size1(); ++r)
98  {
99  matrix_row_gcd(permuted_matrix, rank, r, rank);
100  }
101  }
102 
103  for (size_t p = rank; p > 0; --p)
104  {
105  long long entry = permuted_matrix(p - 1, p - 1);
106  assert(entry != 0);
107  long long g = entry;
108  for (size_t c = p; c < permuted_matrix.size2(); ++c)
109  g = gcd(g, permuted_matrix(p - 1, c));
110  if (entry * g < 0)
111  g = -g;
112  assert(g != 0);
113  entry /= g;
114 
116  if (g != 1)
117  {
118  for (size_t c = p - 1; c < permuted_matrix.size2(); ++c)
119  {
120  assert(permuted_matrix(p - 1, c) % g == 0);
121  permuted_matrix(p - 1, c) /= g;
122  }
123  }
124 
126  for (size_t r = 0; r < p - 1; ++r)
127  {
128  long long factor = permuted_matrix(r, p - 1) / entry;
129  for (size_t c = p - 1; c < permuted_matrix.size2(); ++c)
130  {
131  permuted_matrix(r, c) -= factor * permuted_matrix(p - 1, c);
132  }
133  }
134  }
135 
136  output_matrix.resize(rank, output_matrix.size2());
137 
138  for (size_t r = 0; r < rank; ++r)
139  column_basis.push_back(permuted_matrix.perm2()(r));
140 
141  return rank;
142  }
143 
144 } /* namespace tu */
Base class for matrices whose entries have type V.
Definition: matrix.hpp:55
Definition: matrix_permuted.hpp:17
const permutation_type & perm2() const
Definition: matrix_permuted.hpp:92
size_type size2() const
Definition: matrix_permuted.hpp:65
size_type size1() const
Definition: matrix_permuted.hpp:56
Definition: matrix_transposed.hpp:47
Definition: algorithm.hpp:14
void matrix_permute1(MatrixType &matrix, size_t index1, size_t index2)
Definition: matrix.hpp:1723
T gcd(T a, T b, T &s, T &t)
Definition: gcd.hpp:29
bool matrix_row_gcd(Matrix &matrix, size_t row1, size_t row2, size_t column)
Definition: linear_algebra.hpp:29
bool matrix_column_gcd(Matrix &matrix, size_t column1, size_t column2, size_t row)
Definition: linear_algebra.hpp:54
matrix_transposed< MatrixType > make_transposed_matrix(MatrixType &matrix)
Definition: matrix_transposed.hpp:148
size_t matrix_find_column_basis_and_transform_integral(const InputMatrix &input_matrix, OutputMatrix &output_matrix, std::vector< size_t > &column_basis)
Definition: linear_algebra.hpp:61
bool matrix_column_zero(const Matrix &matrix, size_t column, size_t row_first, size_t row_beyond)
Definition: matrix.hpp:1689
void matrix_row_combine(Matrix &matrix, size_t row1, size_t row2, long long ul, long long ur, long long ll, long long lr)
Definition: linear_algebra.hpp:11
void matrix_permute2(MatrixType &matrix, size_t index1, size_t index2)
Definition: matrix.hpp:1740