matrix/utility.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2020-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 // Copyright (c) 2020-2021 Ilias Khairullin <ilias@nil.foundation>
5 //
6 // MIT License
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 //---------------------------------------------------------------------------//
26 
27 #ifndef CRYPTO3_ALGEBRA_MATRIX_UTILITY_HPP
28 #define CRYPTO3_ALGEBRA_MATRIX_UTILITY_HPP
29 
31 
32 #include <tuple>
33 
34 namespace nil {
35  namespace crypto3 {
36  namespace algebra {
37 
51  template<typename F, typename T, typename... Matrices,
52  typename U = std::invoke_result_t<F, T, typename Matrices::value_type...>,
53  std::size_t N = detail::all_same_value<std::size_t, Matrices::column_size...>::value,
54  std::size_t M = detail::all_same_value<std::size_t, Matrices::row_size...>::value>
55  constexpr matrix<U, N, M> elementwise(F f, const matrix<T, N, M> &m, const Matrices &...matrices) {
56  matrix<U, N, M> op_applied = {};
57  for (std::size_t i = 0; i < N; ++i) {
58  for (std::size_t j = 0; j < M; ++j) {
59  op_applied[i][j] = std::apply(f, std::forward_as_tuple(m[i][j], matrices[i][j]...));
60  }
61  }
62  return op_applied;
63  }
64 
71  template<typename T, typename U, std::size_t N, std::size_t M>
72  constexpr matrix<T, N, M> cast(const matrix<U, N, M> &m) {
73  return elementwise([](const U u) { return static_cast<T>(u); }, m);
74  }
75 
83  template<std::size_t N, std::size_t M, typename F>
84  constexpr decltype(auto) generate(F &&f) {
86  for (std::size_t i = 0; i < N; ++i) {
87  for (std::size_t j = 0; j < M; ++j) {
88  generated[i][j] = std::apply(f, std::forward_as_tuple(i, j));
89  }
90  }
91  return generated;
92  }
93 
101  template<std::size_t N, std::size_t M, typename T>
102  constexpr matrix<T, N, M> fill(T value) {
103  return generate<N, M>([value](std::size_t, std::size_t) { return value; });
104  }
105 
110  template<typename T, std::size_t N>
111  const /*expr*/ matrix<T, N, N> identity = generate<N, N>([](std::size_t i, std::size_t j) {
112  return T(i == j ? 1 : 0);
113  });
114 
115  template<typename T, std::size_t N>
117  return generate<N, N>([](std::size_t i, std::size_t j) { return T(i == j ? 1 : 0); });
118  }
119 
131  template<std::size_t Row, std::size_t Col, std::size_t M, std::size_t N, typename T>
133  return generate<M * Row, N * Col>([&m](std::size_t i, std::size_t j) { return m[i % M][j % N]; });
134  }
135 
146  template<std::size_t M, std::size_t N, typename T>
147  constexpr matrix<T, M, N> swaprow(matrix<T, M, N> m, std::size_t a, std::size_t b) {
148  for (int i = 0; i < N; i++) {
149  T tmp = m[a][i];
150  m[a][i] = m[b][i];
151  m[b][i] = tmp;
152  }
153  return m;
154  }
155 
166  template<std::size_t M, std::size_t N, typename T>
167  constexpr matrix<T, M, N> swapcol(matrix<T, M, N> m, std::size_t a, std::size_t b) {
168  for (int i = 0; i < N; i++) {
169  T tmp = m[i][a];
170  m[i][a] = m[i][b];
171  m[i][b] = tmp;
172  }
173  return m;
174  }
175 
185  template<std::size_t M, std::size_t N, std::size_t P, typename T>
187  return generate<M, N + P>(
188  [&a, &b](std::size_t i, std::size_t j) { return j < N ? a[i][j] : b[i][j - N]; });
189  }
190 
201  template<std::size_t M, std::size_t N, std::size_t P, typename T>
203  return generate<M + N, P>(
204  [&a, &b](std::size_t i, std::size_t j) { return i < M ? a[i][j] : b[i - M][j]; });
205  }
206 
216  template<std::size_t P, std::size_t Q, std::size_t M, std::size_t N, typename T>
217  constexpr matrix<T, P, Q> submat(const matrix<T, M, N> &m, std::size_t a, std::size_t b) {
218  if ((a + P > M) || (b + Q > N))
219  throw "index out of range";
220  return generate<P, Q>([&m, &a, &b](std::size_t i, std::size_t j) { return m[a + i][b + j]; });
221  }
222 
229  template<std::size_t P, std::size_t Q, std::size_t M, std::size_t N, typename T>
231  static_assert(P * Q == M * N, "Reshaped matrix must preserve size! P*Q != M*N");
232  return generate<P, Q>(
233  [&m](std::size_t i, std::size_t j) { return m[(i * Q + j) / N][(i * Q + j) % N]; });
234  }
235 
242  template<typename T, std::size_t N>
243  constexpr matrix<T, N, 1> as_column(const vector<T, N> &v) {
244  return generate<N, 1>([&v](auto i, auto) { return v[i]; });
245  }
246 
253  template<typename T, std::size_t N>
254  constexpr matrix<T, 1, N> as_row(const vector<T, N> &v) {
255  return generate<1, N>([&v](auto, auto j) { return v[j]; });
256  }
257 
260  } // namespace algebra
261  } // namespace crypto3
262 } // namespace nil
263 
264 #endif // CRYPTO3_ALGEBRA_MATRIX_UTILITY_HPP
constexpr matrix< T, M+N, P > vertcat(const matrix< T, M, P > &a, const matrix< T, N, P > &b)
vertically concatenates two matrices
Definition: matrix/utility.hpp:202
constexpr matrix< T, M, N > swapcol(matrix< T, M, N > m, std::size_t a, std::size_t b)
swaps columns of a matrix
Definition: matrix/utility.hpp:167
constexpr decltype(auto) generate(F &&f)
generates a matrix as a function of its indices
Definition: matrix/utility.hpp:84
constexpr matrix< T, M, N+P > horzcat(const matrix< T, M, N > &a, const matrix< T, M, P > &b)
horizontally concatenates two matrices
Definition: matrix/utility.hpp:186
constexpr matrix< T, N, N > get_identity()
Definition: matrix/utility.hpp:116
constexpr matrix< T, P, Q > reshape(const matrix< T, M, N > &m)
reshapes a matrix
Definition: matrix/utility.hpp:230
constexpr matrix< U, N, M > elementwise(F f, const matrix< T, N, M > &m, const Matrices &...matrices)
applies a function elementwise between many matrices
Definition: matrix/utility.hpp:55
constexpr matrix< T, N, M > fill(T value)
generates a matrix containing a single value
Definition: matrix/utility.hpp:102
constexpr matrix< T, M, N > swaprow(matrix< T, M, N > m, std::size_t a, std::size_t b)
swaps rows of a matrix
Definition: matrix/utility.hpp:147
constexpr matrix< T, M *Row, N *Col > repmat(const matrix< T, M, N > &m)
repeats a matrix
Definition: matrix/utility.hpp:132
constexpr matrix< T, N, 1 > as_column(const vector< T, N > &v)
converts a vector into a column vector
Definition: matrix/utility.hpp:243
constexpr matrix< T, 1, N > as_row(const vector< T, N > &v)
converts a vector into a row vector
Definition: matrix/utility.hpp:254
constexpr matrix< T, P, Q > submat(const matrix< T, M, N > &m, std::size_t a, std::size_t b)
extracts the submatrix of a matrix
Definition: matrix/utility.hpp:217
constexpr matrix< T, N, M > cast(const matrix< U, N, M > &m)
casts a vector to another type
Definition: matrix/utility.hpp:72
const matrix< T, N, N > identity
the matrix identity
Definition: matrix/utility.hpp:111
Definition: pair.hpp:31
A container representing a matrix.
Definition: matrix.hpp:52
A container representing a vector.
Definition: vector.hpp:50