cortexlib  v0.2.0
matrix.hxx
Go to the documentation of this file.
1 // -*- C++ -*- Header compatibility <matrix.hxx>
2 
15 
16 #ifndef CORTEX_MATRIX
17 # define CORTEX_MATRIX
18 
19 #include <iterators/normal.hxx>
20 
21 #include <algorithm>
22 #include <compare>
23 #include <functional>
24 #include <initializer_list>
25 #include <memory>
26 #include <utility>
27 #include <vector>
28 
29 namespace cxl
30 {
41  template <typename T, typename Alloc = std::allocator<T>>
42  class matrix
43  {
44  public:
45  using value_type = T;
46  using size_type = std::size_t;
47  using difference_type = std::ptrdiff_t;
48 
49  using allocator_type = Alloc;
50  using alloc_traits = typename std::allocator_traits<Alloc>;
51 
52  using reference = T&;
53  using const_reference = const T&;
54  using pointer = typename alloc_traits::pointer;
55  using const_pointer = typename alloc_traits::const_pointer;
56 
59  using reverse_iterator = std::reverse_iterator<iterator>;
60  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
61 
62  private:
63  size_type m_num_rows;
64  size_type m_num_columns;
65 
66  allocator_type m_allocator;
67  pointer m_start;
68  pointer m_finish;
69 
70  public:
71 
75  constexpr
76  matrix() noexcept
77  : m_num_rows{ size_type{} }
78  , m_num_columns{ size_type{} }
79  , m_allocator{ allocator_type{} }
80  , m_start{ pointer{} }
81  , m_finish{ pointer{} }
82  { }
83 
90  explicit constexpr
91  matrix(const allocator_type& alloc) noexcept
92  : m_num_rows{ size_type{} }
93  , m_num_columns{ size_type{} }
94  , m_allocator{ alloc }
95  , m_start{ pointer{} }
96  , m_finish{ pointer{} }
97  { }
98 
114  explicit constexpr
116  : m_num_rows{ num_rows }
117  , m_num_columns{ num_columns }
118  , m_allocator{ alloc }
119  , m_start{ _M_allocate(_M_size_check(num_rows, num_columns)) }
120  , m_finish{ m_start + size() }
121  {
122  if constexpr (std::is_default_constructible_v<value_type>)
123  std::ranges::uninitialized_default_construct(*this);
124  else
125  std::ranges::uninitialized_fill(*this, value_type{});
126  }
127 
138  explicit constexpr
140  : m_num_rows{ num_rows }
141  , m_num_columns{ num_columns }
142  , m_allocator{ alloc }
143  , m_start{ _M_allocate(_M_size_check(num_rows, num_columns)) }
144  , m_finish{ m_start + size() }
145  { std::ranges::uninitialized_fill(*this, fill_value); }
146 
153  constexpr
154  matrix(const matrix& other)
155  : m_num_rows{ other.m_num_rows }
156  , m_num_columns{ other.m_num_columns}
157  , m_allocator{ other.m_allocator }
158  , m_start{ _M_allocate(_M_size_check(m_num_rows, m_num_columns)) }
159  , m_finish{ m_start + size() }
160  { std::ranges::uninitialized_copy(other, *this); }
161 
169  explicit constexpr
170  matrix(const matrix& other, const allocator_type& alloc)
171  : m_num_rows{ other.m_num_rows }
172  , m_num_columns{ other.m_num_columns }
173  , m_allocator{ alloc }
174  , m_start{ _M_allocate(_M_size_check(other.m_num_rows, other.m_num_columns)) }
175  , m_finish{ m_start + size() }
176  { std::ranges::uninitialized_copy(other, *this); }
177 
185  constexpr
186  matrix(matrix&& other) noexcept
187  : m_num_rows{ other.m_num_rows }
188  , m_num_columns{ other.m_num_columns }
189  , m_allocator{ std::move(other.m_allocator) }
190  , m_start{ other.m_start }
191  , m_finish{ other.m_finish }
192  {
193  other.m_start = pointer{};
194  other.m_finish = pointer{};
195  other.m_allocator = allocator_type{};
196  other.m_num_rows = size_type{};
197  other.m_num_columns = size_type{};
198  }
199 
209  explicit constexpr
210  matrix(matrix&& other, const allocator_type& alloc) noexcept
211  : m_num_rows{ other.m_num_rows }
212  , m_num_columns{ other.m_num_columns }
213  , m_allocator{ alloc }
214  , m_start{ other.m_start }
215  , m_finish{ other.m_finish }
216  {
217  other.m_start = pointer{};
218  other.m_finish = pointer{};
219  other.m_allocator = allocator_type{};
220  other.m_num_rows = size_type{};
221  other.m_num_columns = size_type{};
222  other.m_size = size_type{};
223  }
224 
235  constexpr
236  matrix(std::initializer_list<std::initializer_list<value_type>> list, [[maybe_unused]] const allocator_type& alloc = allocator_type{})
237  : m_num_rows{ list.size() }
238  , m_num_columns{ list.begin()->size() }
239  , m_allocator{ alloc }
240  , m_start{ _M_allocate(_M_size_check(m_num_rows, m_num_columns)) }
241  , m_finish{ m_start + size() }
242  {
243  auto offset{ 0uL };
244  for (auto row{ list.begin() }; row != list.end(); ++row)
245  {
246  if (row->size() != this->m_num_columns)
247  throw std::invalid_argument("The size of the inner std::initializer_list must be same size as the number of columns in the matrix");
248 
249  std::uninitialized_move_n(row->begin(), this->m_num_columns, m_start + offset);
250  offset += this->m_num_columns;
251  }
252  }
253 
262  explicit constexpr
263  matrix(const std::tuple<size_type, size_type>& dimensions, [[maybe_unused]] const allocator_type& alloc = allocator_type{})
264  : m_num_rows{ std::get<0>(dimensions) }
265  , m_num_columns{ std::get<1>(dimensions) }
266  , m_allocator{ alloc }
267  , m_start{ _M_allocate(_M_size_check(m_num_rows, m_num_columns)) }
268  , m_finish{ m_start + size() }
269  {
270  if constexpr (std::is_default_constructible_v<value_type>)
271  std::ranges::uninitialized_default_construct(*this);
272  else
273  std::ranges::uninitialized_fill(*this, value_type{});
274  }
275 
284  constexpr auto
285  operator= (const matrix& other)
286  -> matrix&
287  {
288  if (*this != other)
289  {
290  std::ranges::destroy(*this);
291  _M_deallocate(m_start, size());
292 
293  m_num_rows = other.m_num_rows;
294  m_num_columns = other.m_num_columns;
295  m_allocator = other.m_allocator;
296  m_start = _M_allocate(_M_size_check(m_num_rows, m_num_columns));
297  m_finish = m_start + size();
298  std::ranges::uninitialized_copy(other, *this);
299  }
300  return *this;
301  }
302 
312  constexpr auto
313  operator= (matrix&& other) noexcept
314  -> matrix&
315  {
316  if (*this != other)
317  {
318  std::ranges::destroy(*this);
319  _M_deallocate(m_start, size());
320 
321  m_num_rows = other.m_num_rows;
322  m_num_columns = other.m_num_columns;
323  m_allocator = std::move(other.m_allocator);
324  m_start = other.m_start;
325  m_finish = other.m_finish;
326 
327  other.m_start = pointer{};
328  other.m_finish = pointer{};
329  other.m_allocator = allocator_type{};
330  other.m_num_rows = size_type{};
331  other.m_num_columns = size_type{};
332  }
333  return *this;
334  }
335 
346  constexpr auto
347  operator= (std::initializer_list<std::initializer_list<value_type>> list)
348  -> matrix&
349  {
350  std::ranges::destroy(*this);
351  _M_deallocate(m_start, size());
352 
353  m_allocator = allocator_type{};
354  m_num_rows = list.size();
355  m_num_columns = list.begin()->size();
356  m_start = _M_allocate(_M_size_check(m_num_rows, m_num_columns));
357  m_finish = m_start + size();
358 
359  auto offset{ 0uL };
360  for (auto row{ list.begin() }; row != list.end(); ++row)
361  {
362  if (row->size() != this->m_num_columns)
363  throw std::invalid_argument("The size of the inner std::initializer_list must be same size as the number of columns in the matrix");
364 
365  std::uninitialized_move_n(row->begin(), this->m_num_columns, m_start + offset);
366  offset += this->m_num_columns;
367  }
368 
369  return *this;
370  }
371 
376 #if __cplusplus >= 202202L
377  constexpr
378 #else
380 #endif
381  {
382  if (m_start)
383  {
384  std::ranges::destroy(*this);
385  _M_deallocate(m_start, size());
386  }
387 
388  m_num_rows = size_type{};
389  m_num_columns = size_type{};
390  m_start = pointer{};
391  m_finish = pointer{};
392  m_allocator = allocator_type{};
393  }
394 
405  constexpr auto
406  assign(std::initializer_list<std::initializer_list<value_type>> list)
407  -> void
408  {
409  auto new_rows { list.size() };
410  auto new_columns { list.begin()->size() };
411 
412  std::ranges::destroy(*this);
413 
414  if (new_rows != m_num_rows || new_columns != m_num_columns)
415  {
416  if (m_start)
417  _M_deallocate(m_start, size());
418 
419  m_start = _M_allocate(_M_size_check(new_rows, new_columns));
420  m_finish = m_start + _M_size_check(new_rows, new_columns);
421  }
422 
423  m_num_rows = new_rows;
424  m_num_columns = new_columns;
425 
426  auto offset{ 0uL };
427  for (auto row{ list.begin() }; row != list.end(); ++row)
428  {
429  if (row->size() != this->m_num_columns)
430  throw std::invalid_argument("The size of the inner std::initializer_list must be same size as the number of columns in the matrix");
431 
432  std::uninitialized_move_n(row->begin(), this->m_num_columns, m_start + offset);
433  offset += this->m_num_columns;
434  }
435  }
436 
443  constexpr auto
444  resize(size_type new_rows, size_type new_columns)
445  -> void
446  { resize(new_rows, new_columns, value_type{}); }
447 
464  constexpr auto
465  resize(size_type new_rows, size_type new_columns, const_reference fill_value)
466  -> void
467  {
468  auto old_size{ size() };
469  auto new_size{ _M_size_check(new_rows, new_columns) };
470 
471  auto new_start{ _M_allocate(new_size) };
472  auto new_finish{ new_start + new_size };
473 
474 
475  if (new_size > alloc_traits::max_size(m_allocator))
476  throw std::length_error("matrix resize too large");
477  else
478  if (old_size < new_size)
479  {
480  if (auto old_finish_pos_in_new{ new_start + old_size }; m_start)
481  {
482  std::ranges::uninitialized_copy(m_start, m_finish, new_start, old_finish_pos_in_new);
483  std::ranges::uninitialized_fill(old_finish_pos_in_new, new_finish, fill_value);
484  }
485  else
486  std::ranges::uninitialized_fill(new_start, new_finish, fill_value);
487  }
488  else if (old_size > new_size)
489  {
490  if (auto size_diff { old_size - new_size }; m_start)
491  std::ranges::uninitialized_copy(m_start, m_finish - size_diff, new_start, new_finish);
492  else
493  std::ranges::uninitialized_fill(new_start, new_finish, fill_value);
494  }
495 
496  std::ranges::destroy(*this);
497  _M_deallocate(m_start, old_size);
498 
499  m_start = new_start;
500  m_finish = new_finish;
501 
502  m_num_rows = new_rows;
503  m_num_columns = new_columns;
504  }
505 
513  [[maybe_unused]] constexpr auto
515  -> iterator
516  {
517  auto pos { this->begin() + (position - this->cbegin()) };
518  std::ranges::destroy_at(std::addressof(*pos));
519  std::ranges::uninitialized_fill(pos, pos + 1, value_type{});
520 
521  return position;
522  }
523 
532  [[maybe_unused]] constexpr auto
534  -> iterator
535  {
536  const auto bgn { this->begin() };
537  const auto cbgn { this->cbegin() };
538 
539  auto fst { bgn + (first - cbgn) };
540  auto lst { bgn + (last - cbgn) };
541 
542  std::ranges::destroy(fst, lst);
543  return std::ranges::uninitialized_fill(fst, lst, value_type{});
544  }
545 
552  constexpr auto
553  clear()
554  -> void
555  {
556  if (size())
557  {
558  erase(begin(), end());
559 
560  _M_deallocate(m_start, size());
561  m_num_rows = size_type{};
562  m_num_columns = size_type{};
563  m_finish = pointer{};
564  m_start = pointer{};
565  }
566  }
567 
578  constexpr auto
579  reshape(size_type new_rows, size_type new_columns)
580  -> void
581  {
582  auto new_size{ _M_size_check(new_rows, new_columns) };
583 
584  if (new_size != size())
585  throw std::length_error("Cannot reshape matrix that has different total size");
586  else
587  resize(new_rows, new_columns);
588  }
589 
598  void swap(matrix& other) noexcept
599  {
600  matrix tmp = std::move(other);
601  other = std::move(*this);
602  *this = std::move(tmp);
603  }
604 
610  constexpr auto
611  get_allocator() const noexcept
612  -> allocator_type
613  { return m_allocator; }
614 
620  constexpr auto
621  size() const noexcept
622  -> size_type
623  {
624  return empty() ? size_type{ 0 }
625  : m_num_rows * m_num_columns != 0uL
626  ? m_num_rows * m_num_columns
627  : std::max(m_num_rows, m_num_columns);
628  }
629 
635  constexpr auto
636  num_rows() const noexcept
637  -> size_type
638  { return m_num_rows; }
639 
645  constexpr auto
646  num_columns() const noexcept
647  -> size_type
648  { return m_num_columns; }
649 
656  constexpr auto
657  max_size() const noexcept
658  -> size_type
659  { return alloc_traits::max_size(m_allocator); }
660 
666  constexpr auto
667  shape() const noexcept
668  -> std::tuple<size_type, size_type>
669  { return std::make_tuple(m_num_rows, m_num_columns); }
670 
677  constexpr auto
678  is_square() const noexcept
679  -> bool
680  { return m_num_rows == m_num_columns; }
681 
687  constexpr auto
688  empty() const noexcept
689  -> bool
690  { return m_start == m_finish; }
691 
697  constexpr auto
698  data() noexcept
699  -> pointer
700  { return _M_data_ptr(m_start); }
701 
707  constexpr auto
708  data() const noexcept
709  -> const_pointer
710  { return _M_data_ptr(m_start); }
711 
721  constexpr auto
722  at(size_type row, size_type column)
723  -> reference
724  {
725  _M_range_check(row, column);
726  return *(m_start + _M_index(row, column));
727  }
728 
738  constexpr auto
739  at(size_type row, size_type column) const
740  -> const_reference
741  {
742  _M_range_check(row, column);
743  return *(m_start + _M_index(row, column));
744  }
745 
754  constexpr auto
756  -> reference
757  { return at(row, column); }
758 
767  constexpr auto
768  operator() (size_type row, size_type column) const
769  -> const_reference
770  { return at(row, column); }
771 
778  constexpr auto
779  front() noexcept
780  -> reference
781  { return *begin(); }
782 
789  constexpr auto
790  front() const noexcept
791  -> const_reference
792  { return *begin(); }
793 
800  constexpr auto
801  back() noexcept
802  -> reference
803  { return *(end() - 1); }
804 
811  constexpr auto
812  back() const noexcept
813  -> const_reference
814  { return *(end() - 1); }
815 
822  constexpr auto
823  begin() noexcept
824  -> iterator
825  { return iterator(m_start); }
826 
833  constexpr auto
834  begin() const noexcept
835  -> const_iterator
836  { return const_iterator(m_start); }
837 
844  constexpr auto
845  cbegin() const noexcept
846  -> const_iterator
847  { return const_iterator(m_start); }
848 
855  constexpr auto
856  rbegin() noexcept
858  { return reverse_iterator(end()); }
859 
866  constexpr auto
867  rbegin() const noexcept
869  { return const_reverse_iterator(end()); }
870 
877  constexpr auto
878  crbegin() const noexcept
880  { return const_reverse_iterator(end()); }
881 
888  constexpr auto
889  end() noexcept
890  -> iterator
891  { return iterator(m_finish); }
892 
899  constexpr auto
900  end() const noexcept
901  -> const_iterator
902  { return const_iterator(m_finish); }
903 
910  constexpr auto
911  cend() const noexcept
912  -> const_iterator
913  { return const_iterator(m_finish); }
914 
921  constexpr auto
922  rend() noexcept
924  { return reverse_iterator(begin()); }
925 
932  constexpr auto
933  rend() const noexcept
935  { return const_reverse_iterator(begin()); }
936 
943  constexpr auto
944  crend() const noexcept
946  { return const_reverse_iterator(begin()); }
947 
956  // constexpr auto
957  // transpose()
958  // {
959  // matrix<value_type> result(this->num_columns(), this->num_rows());
960 
961  // if (empty())
962  // return result;
963 
964  // std::ranges::copy(*this, result.column_begin());
965 
966  // return result;
967  // }
968 
977  template<std::copy_constructible F>
978  constexpr auto
979  map(F func) const
981  {
982  if (empty())
984  else
985  {
987  std::ranges::transform(*this, result.begin(), func);
988  return result;
989  }
990  }
991 
1003  template<std::ranges::input_range Rng, std::copy_constructible F>
1004  constexpr auto
1005  map(Rng&& rng, F func) const
1006  -> matrix<std::invoke_result_t<F, value_type, typename std::remove_cvref_t<decltype(*std::ranges::begin(rng))>>>
1007  {
1008  using range_elem_t = typename std::remove_cvref_t<decltype(*std::ranges::begin(rng))>;
1009 
1010  if (empty())
1012  else
1013  {
1015  std::ranges::transform(*this, rng, result.begin(), func);
1016  return result;
1017  }
1018  }
1019 
1033  template<std::input_iterator It, std::sentinel_for<It> Sn, std::copy_constructible Fn>
1034  constexpr auto
1035  map(It first, Sn last, Fn func) const
1037  {
1038  using iterator_elem_t = typename std::remove_cvref_t<typename std::iterator_traits<It>::value_type>;
1039 
1040  if (empty())
1042  else
1043  {
1045  std::ranges::transform(this->begin(), this->end(), first, last, result.begin(), func);
1046  return result;
1047  }
1048  }
1049 
1058  // constexpr auto vflip() const
1059  // {
1060  // if (empty())
1061  // return matrix<value_type>{};
1062  // else
1063  // {
1064  // matrix<value_type> result(this->num_rows(), this->num_columns());
1065 
1066  // for (auto cidx { 0u }; cidx < this->num_columns(); ++cidx)
1067  // std::ranges::copy(this->column_begin(cidx), this->column_end(cidx), result.column_rbegin(cidx));
1068 
1069  // return result;
1070  // }
1071  // }
1072 
1081  // constexpr auto hflip() const
1082  // {
1083  // if (empty())
1084  // return matrix<value_type>{};
1085  // else
1086  // {
1087  // matrix<value_type> result(this->num_rows(), this->num_columns());
1088  // for (auto ridx { 0u }; ridx < this->num_rows(); ++ridx)
1089  // std::ranges::copy(this->row_begin(ridx), this->row_end(ridx), result.row_rbegin(ridx));
1090 
1091  // return result;
1092  // }
1093  // }
1094 
1102  // constexpr auto rrotate() const
1103  // {
1104  // if (empty())
1105  // return matrix<value_type>{};
1106  // else
1107  // {
1108  // matrix<value_type> result(this->num_columns(), this->num_rows());
1109 
1110  // for (auto cidx { 0u }; cidx < this->num_columns(); ++cidx)
1111  // std::ranges::copy(this->column_begin(cidx), this->column_end(cidx), result.row_rbegin(cidx));
1112 
1113  // return result;
1114  // }
1115  // }
1116 
1124  // constexpr auto lrotate() const
1125  // {
1126  // if (empty())
1127  // return matrix<value_type>{};
1128  // else
1129  // {
1130  // matrix<value_type> result(this->num_columns(), this->num_rows());
1131 
1132  // for (auto ridx { 0u }; ridx < this->num_rows(); ++ridx)
1133  // std::ranges::copy(this->row_begin(ridx), this->row_end(ridx), result.column_rbegin(ridx));
1134 
1135  // return result;
1136  // }
1137  // }
1138 
1139  private:
1149  constexpr auto
1150  _M_allocate(size_type n)
1151  -> pointer
1152  { return n != 0 ? alloc_traits::allocate(m_allocator, n) : pointer{}; }
1153 
1163  constexpr auto
1164  _M_deallocate(pointer ptr, [[maybe_unused]] size_type n)
1165  -> void
1166  {
1167  if (ptr)
1168  alloc_traits::deallocate(m_allocator, ptr, n);
1169  }
1170 
1180  constexpr auto
1181  _M_range_check(size_type row, size_type column) const
1182  -> void
1183  {
1184  if (row >= m_num_rows || column >= m_num_columns)
1185  throw std::out_of_range("matrix::_M_range_check - index out of range.");
1186  }
1187 
1188  constexpr auto
1189  _M_size_check(size_type row, size_type column) const
1190  -> size_type
1191  {
1192  if (row == 0uL)
1193  throw std::invalid_argument{ "BoxView::_M_size_check - row size cannot be zero" };
1194  else if (column == 0uL)
1195  throw std::invalid_argument{ "BoxView::_M_size_check - column size cannot be zero" };
1196  else
1197  return row * column;
1198  }
1199 
1200  constexpr auto
1201  _M_index(size_type row, size_type column) const noexcept
1202  -> size_type
1203  { return row * m_num_columns + column; }
1204 
1210  template <typename U>
1211  constexpr auto
1212  _M_data_ptr(U* ptr) const noexcept
1213  -> U*
1214  { return ptr; }
1215 
1216 #if __cplusplus >= 201103L
1226  template <typename Ptr>
1227  constexpr auto
1228  _M_data_ptr(Ptr ptr) const
1229  -> typename std::pointer_traits<Ptr>::element_type*
1230  { return empty() ? nullptr : std::to_address(*ptr); }
1231 #else
1232 
1241  template <typename U>
1242  constexpr auto
1243  _M_data_ptr(U* ptr) noexcept
1244  -> U*
1245  { return ptr; }
1246 #endif //< __cplusplus >= 201103L
1247 
1248  }; //< class matrix
1249 
1261  template <typename ElemL, typename ElemR>
1262  requires requires(ElemL lhsE, ElemR rhsE) {
1263  { lhsE == rhsE } -> std::convertible_to<bool>;
1264  }
1265  constexpr inline auto
1266  operator== (const matrix<ElemL>& lhs, const matrix<ElemR>& rhs) noexcept(
1267  noexcept(std::declval<ElemL>() == std::declval<ElemR>())
1268  && noexcept(std::ranges::equal(lhs, rhs))) -> bool
1269  {
1270  if (lhs.shape() != rhs.shape())
1271  return false;
1272  return std::ranges::equal(lhs, rhs);
1273  }
1274 
1286  template <typename ElemL, typename ElemR>
1287  constexpr inline auto
1288  operator<=> (const matrix<ElemL>& lhs, const matrix<ElemR>& rhs)
1289  { return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::compare_three_way{}); }
1290 
1301  template<typename E, std::copy_constructible F>
1302  constexpr auto
1303  operator|| (const matrix<E>& bx, F f) noexcept
1305  { return bx.map(f); }
1306 
1307 } //< namespace cxl
1308 
1309 namespace std
1310 {
1321  template <typename T>
1322  constexpr inline auto
1324  noexcept( noexcept(x.swap(y)) ) -> void
1325  { x.swap(y); }
1326 }
1327 
1328 #endif //< CORTEX_MATRIX_H
matrix - Two Dimensional Array
Definition: matrix.hxx:43
constexpr auto front() noexcept -> reference
Front.
Definition: matrix.hxx:779
T & reference
Definition: matrix.hxx:52
constexpr auto operator()(size_type row, size_type column) -> reference
Point based element access operator.
Definition: matrix.hxx:755
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Reverse Begin Iterator (const)
Definition: matrix.hxx:867
constexpr auto is_square() const noexcept -> bool
Is Square Predicate.
Definition: matrix.hxx:678
constexpr auto data() const noexcept -> const_pointer
Data.
Definition: matrix.hxx:708
constexpr matrix(size_type num_rows, size_type num_columns, const_reference fill_value, const allocator_type &alloc=allocator_type())
Explicit Value and Size Constructor.
Definition: matrix.hxx:139
~matrix()
Destructor.
Definition: matrix.hxx:379
constexpr auto back() const noexcept -> const_reference
Back.
Definition: matrix.hxx:812
constexpr auto reshape(size_type new_rows, size_type new_columns) -> void
Reshape current matrix elements to new dimensions.
Definition: matrix.hxx:579
cxl::normal_iterator< pointer, matrix > iterator
Definition: matrix.hxx:57
std::size_t size_type
Definition: matrix.hxx:46
constexpr auto shape() const noexcept -> std::tuple< size_type, size_type >
Dimensions.
Definition: matrix.hxx:667
constexpr matrix(const matrix &other)
Copy Constructor.
Definition: matrix.hxx:154
constexpr matrix(const allocator_type &alloc) noexcept
Allocator Constructor.
Definition: matrix.hxx:91
constexpr auto crbegin() const noexcept -> const_reverse_iterator
Constant Reverse Begin Iterator.
Definition: matrix.hxx:878
constexpr matrix(std::initializer_list< std::initializer_list< value_type >> list, [[maybe_unused]] const allocator_type &alloc=allocator_type{})
Initialiser List Constructor.
Definition: matrix.hxx:236
constexpr auto erase(const_iterator position) -> iterator
Erases element indicated by position.
Definition: matrix.hxx:514
constexpr auto cbegin() const noexcept -> const_iterator
Constant Begin Iterator.
Definition: matrix.hxx:845
Alloc allocator_type
Definition: matrix.hxx:49
constexpr matrix(matrix &&other, const allocator_type &alloc) noexcept
Move Constructor with Alternative Allocator.
Definition: matrix.hxx:210
constexpr auto empty() const noexcept -> bool
Empty.
Definition: matrix.hxx:688
void swap(matrix &other) noexcept
Swaps two Matrices of the same type.
Definition: matrix.hxx:598
constexpr auto begin() noexcept -> iterator
Begin Iterator.
Definition: matrix.hxx:823
constexpr auto cend() const noexcept -> const_iterator
Constant End Iterator.
Definition: matrix.hxx:911
std::reverse_iterator< iterator > reverse_iterator
Definition: matrix.hxx:59
cxl::normal_iterator< const_pointer, matrix > const_iterator
Definition: matrix.hxx:58
T value_type
Definition: matrix.hxx:45
constexpr auto crend() const noexcept -> const_reverse_iterator
Constant Reverse End Iterator.
Definition: matrix.hxx:944
constexpr matrix() noexcept
Default Constructor.
Definition: matrix.hxx:76
constexpr auto operator=(const matrix &other) -> matrix &
Copy Assignment.
Definition: matrix.hxx:285
constexpr auto back() noexcept -> reference
Back.
Definition: matrix.hxx:801
constexpr auto num_rows() const noexcept -> size_type
Number of rows.
Definition: matrix.hxx:636
constexpr matrix(const matrix &other, const allocator_type &alloc)
Copy Constructor with Alternative Allocator.
Definition: matrix.hxx:170
constexpr auto max_size() const noexcept -> size_type
Max matrix Size.
Definition: matrix.hxx:657
constexpr matrix(size_type num_rows, size_type num_columns, const allocator_type &alloc=allocator_type{})
Default Size Constructor.
Definition: matrix.hxx:115
const T & const_reference
Definition: matrix.hxx:53
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: matrix.hxx:60
constexpr auto resize(size_type new_rows, size_type new_columns, const_reference fill_value) -> void
Resizes Matrices memory.
Definition: matrix.hxx:465
std::ptrdiff_t difference_type
Definition: matrix.hxx:47
constexpr auto map(F func) const -> matrix< std::invoke_result_t< F, value_type >>
matrix Transpose
Definition: matrix.hxx:979
constexpr auto get_allocator() const noexcept -> allocator_type
Get Allocator.
Definition: matrix.hxx:611
constexpr auto rend() noexcept -> reverse_iterator
Reverse End Iterator.
Definition: matrix.hxx:922
typename std::allocator_traits< Alloc > alloc_traits
Definition: matrix.hxx:50
typename alloc_traits::pointer pointer
Definition: matrix.hxx:54
constexpr auto begin() const noexcept -> const_iterator
Begin Iterator (const)
Definition: matrix.hxx:834
constexpr auto at(size_type row, size_type column) const -> const_reference
Point based element access.
Definition: matrix.hxx:739
constexpr auto map(Rng &&rng, F func) const -> matrix< std::invoke_result_t< F, value_type, typename std::remove_cvref_t< decltype(*std::ranges::begin(rng))>>>
matrix map with range
Definition: matrix.hxx:1005
constexpr auto num_columns() const noexcept -> size_type
Number of Columns.
Definition: matrix.hxx:646
constexpr auto resize(size_type new_rows, size_type new_columns) -> void
Resizes the matrix memory.
Definition: matrix.hxx:444
constexpr auto clear() -> void
Clears the matrix elements.
Definition: matrix.hxx:553
constexpr auto rend() const noexcept -> const_reverse_iterator
Reverse End Iterator (const)
Definition: matrix.hxx:933
typename alloc_traits::const_pointer const_pointer
Definition: matrix.hxx:55
constexpr auto end() noexcept -> iterator
End Iterator.
Definition: matrix.hxx:889
constexpr auto data() noexcept -> pointer
Data.
Definition: matrix.hxx:698
constexpr matrix(const std::tuple< size_type, size_type > &dimensions, [[maybe_unused]] const allocator_type &alloc=allocator_type{})
Dimension Constructor.
Definition: matrix.hxx:263
constexpr auto assign(std::initializer_list< std::initializer_list< value_type >> list) -> void
Initialiser List Assign.
Definition: matrix.hxx:406
constexpr auto rbegin() noexcept -> reverse_iterator
Reverse Begin Iterator.
Definition: matrix.hxx:856
constexpr matrix(matrix &&other) noexcept
Move Constructor.
Definition: matrix.hxx:186
constexpr auto front() const noexcept -> const_reference
Front.
Definition: matrix.hxx:790
constexpr auto end() const noexcept -> const_iterator
End Iterator (const)
Definition: matrix.hxx:900
constexpr auto at(size_type row, size_type column) -> reference
Point based element access.
Definition: matrix.hxx:722
constexpr auto map(It first, Sn last, Fn func) const -> matrix< std::invoke_result_t< Fn, value_type, typename std::remove_cvref_t< typename std::iterator_traits< It >::value_type >>>
Map - Iterator Pair.
Definition: matrix.hxx:1035
constexpr auto size() const noexcept -> size_type
matrix Size
Definition: matrix.hxx:621
constexpr auto erase(const_iterator first, const_iterator last) -> iterator
Erases elements between first and last.
Definition: matrix.hxx:533
Normal Iterator.
Definition: normal.hxx:48
Definition: matrix.hxx:30
constexpr auto operator||(const matrix< E > &bx, F f) noexcept -> matrix< std::invoke_result_t< F, E >>
Map Operator.
Definition: matrix.hxx:1303
requires requires(ElemL lhsE, ElemR rhsE)
Compares two Matrices for equality.
Definition: matrix.hxx:1262
constexpr auto operator<=>(const matrix< ElemL > &lhs, const matrix< ElemR > &rhs)
Spaceship Operator for matrix.
Definition: matrix.hxx:1288
constexpr auto operator==(const matrix< ElemL > &lhs, const matrix< ElemR > &rhs) noexcept(noexcept(std::declval< ElemL >()==std::declval< ElemR >()) &&noexcept(std::ranges::equal(lhs, rhs))) -> bool
Definition: matrix.hxx:1266
Definition: matrix.hxx:1310
constexpr auto swap(cxl::matrix< T > &x, cxl::matrix< T > &y) noexcept(noexcept(x.swap(y))) -> void
Uses std::swap to swap the contents of two matrices.
Definition: matrix.hxx:1323
Adapts a non-object iterator to an object iterator without changing its semantics.