A triangle counting assignment for A.U.TH Parallel and distributed systems class.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

703 lines
26 KiB

  1. /**
  2. * \file impl.hpp
  3. * \brief Implementation common header file
  4. *
  5. * \author
  6. * Christos Choutouridis AEM:8997
  7. * <cchoutou@ece.auth.gr>
  8. */
  9. #ifndef IMPL_HPP_
  10. #define IMPL_HPP_
  11. #include <type_traits>
  12. #include <utility>
  13. #include <algorithm>
  14. #include <vector>
  15. #include <tuple>
  16. #include <cstddef>
  17. #include <iostream>
  18. #include <fstream>
  19. using std::size_t;
  20. /*
  21. * Small helper to strip types
  22. */
  23. template<typename T>
  24. struct remove_cvref {
  25. typedef std::remove_cv_t<std::remove_reference_t<T>> type;
  26. };
  27. template<typename T>
  28. using remove_cvref_t = typename remove_cvref<T>::type;
  29. /*!
  30. * Enumerator to denote the storage type of the array to use.
  31. */
  32. enum class MatrixType {
  33. FULL, /*!< Matrix is asymmetric */
  34. SYMMETRIC, /*!< Matrix is symmetric */
  35. };
  36. /*
  37. * Forward type declerations
  38. */
  39. template<typename DataType, typename IndexType, MatrixType Type = MatrixType::SYMMETRIC> struct Matrix;
  40. template<typename DataType, typename IndexType, MatrixType Type = MatrixType::SYMMETRIC> struct SpMat;
  41. template<typename DataType, typename IndexType> struct SpMatCol;
  42. template<typename DataType, typename IndexType> struct SpMatRow;
  43. template<typename DataType, typename IndexType> struct SpMatVal;
  44. /*!
  45. * 2D-array wrapper for v1 and v2 part of the exercise t use as RAII
  46. * and copy-prevention.
  47. *
  48. * This is a very thin abstraction layer over a native array.
  49. * This is tested using compiler explorer and our template produce
  50. * almost identical assembly.
  51. *
  52. * The penalty hit we have is due to the fact that we use a one dimension array
  53. * and we have to calculate the actual position from an (i,j) pair.
  54. * The use of 1D array was our intention from the beginning, so the penalty
  55. * was pretty much unavoidable.
  56. *
  57. * \tparam DataType The underling data type of the array
  58. * \tparam Type The storage type of the array
  59. * \arg FULL For full matrix
  60. * \arg SYMMETRIC For symmetric matrix (we use only the lower part)
  61. */
  62. template<typename DataType, typename IndexType, MatrixType Type>
  63. struct Matrix {
  64. using dataType = DataType; //!< meta:export of underling data type
  65. using indexType = IndexType; //!< meta:export of underling index type
  66. static constexpr MatrixType matrixType = Type; //!< export of array type
  67. /*!
  68. * \name Obj lifetime
  69. */
  70. //! @{
  71. //! Constructor using data type and size
  72. Matrix(DataType* t, IndexType s) noexcept : m_(t), size_(s) { }
  73. //! RAII deleter
  74. ~Matrix() { delete m_; }
  75. //! move ctor
  76. Matrix(Matrix&& a) noexcept { a.swap(*this); }
  77. //! move
  78. Matrix& operator=(Matrix&& a) noexcept { a.swap(*this); return *this; }
  79. Matrix(const Matrix& a) = delete; //!< No copy ctor
  80. Matrix& operator=(const Matrix& a) = delete; //!< No copy
  81. //! @}
  82. //! \name Data exposure
  83. //! @{
  84. //! memory capacity of the matrix with diagonal data
  85. template<MatrixType AT=Type> std::enable_if_t<AT==MatrixType::SYMMETRIC, IndexType>
  86. static constexpr capacity(IndexType N) noexcept { return (N+1)*N/2; }
  87. //! memory capacity for full matrix
  88. template<MatrixType AT=Type> std::enable_if_t<AT==MatrixType::FULL, IndexType>
  89. static constexpr capacity(IndexType N) noexcept { return N*N; }
  90. //! Get the size of each dimension
  91. IndexType size() noexcept { return size_; }
  92. /*
  93. * virtual 2D accessors
  94. */
  95. template<MatrixType AT=Type>
  96. std::enable_if_t <AT==MatrixType::SYMMETRIC, DataType>
  97. get (IndexType i, IndexType j) {
  98. if (i<j) return m_[j*(j+1)/2 + i]; // Upper, use opposite index
  99. else return m_[i*(i+1)/2 + j]; // Lower, use our notation
  100. }
  101. template<MatrixType AT=Type>
  102. std::enable_if_t <AT==MatrixType::FULL, DataType>
  103. get(IndexType i, IndexType j) {
  104. return m_[i*size_ + j];
  105. }
  106. template<MatrixType AT=Type>
  107. std::enable_if_t <AT==MatrixType::SYMMETRIC, DataType>
  108. set(DataType v, IndexType i, IndexType j) {
  109. if (i<j) return m_[j*(j+1)/2 + i] =v; // Upper, use opposite index
  110. else return m_[i*(i+1)/2 + j] =v; // Lower, use our notation
  111. }
  112. template<MatrixType AT=Type>
  113. std::enable_if_t <AT==MatrixType::FULL, DataType>
  114. set(DataType v, IndexType i, IndexType j) {
  115. return m_[i*size_ + j] =v;
  116. }
  117. DataType operator()(IndexType i, IndexType j) { return get(i, j); }
  118. // a basic serial iterator support
  119. DataType* begin() noexcept { return m_; }
  120. DataType* end() noexcept { return m_ + Matrix::capacity(size_); }
  121. //! @}
  122. /*!
  123. * \name Safe iteration API
  124. *
  125. * This api automates the iteration over the array based on
  126. * MatrixType
  127. */
  128. //! @{
  129. template<typename F, typename... Args>
  130. void for_each_in (IndexType begin, IndexType end, F&& lambda, Args&&... args) {
  131. for (IndexType it=begin ; it<end ; ++it) {
  132. std::forward<F>(lambda)(std::forward<Args>(args)..., it);
  133. }
  134. }
  135. //! @}
  136. // move helper
  137. void swap(Matrix& src) noexcept {
  138. std::swap(m_, src.m_);
  139. std::swap(size_, src.size_);
  140. }
  141. private:
  142. DataType* m_; //!< Pointer to actual data.
  143. IndexType size_; //!< the virtual size of each dimension.
  144. };
  145. /*!
  146. * RAII allocation helper, the smart_ptr way.
  147. */
  148. template<typename DataType, typename IndexType, MatrixType Type = MatrixType::SYMMETRIC>
  149. Matrix<DataType, IndexType, Type> make_Matrix(IndexType s) {
  150. return Matrix<DataType, IndexType, Type>(new DataType[Matrix<DataType, IndexType, Type>::capacity(s)], s);
  151. }
  152. /**
  153. * A simple sparse matrix implementation.
  154. *
  155. * We use CSC format and provide get/set functionalities for each (i,j) item
  156. * on the matrix. We also provide a () overload using a proxy SpMatVal object.
  157. * This way the user can:
  158. * \code
  159. * auto v = A(3,4);
  160. * A(3, 4) = 7;
  161. * \endcode
  162. *
  163. * We also provide getCol() and getRow() functions witch return a viwer/iterator to rows and
  164. * columns of the matrix. In the case of a symmetric matrix instead of a row we return the
  165. * equivalent column. This way we gain speed due to CSC format nature.
  166. *
  167. * @tparam DataType The type for values
  168. * @tparam IndexType The type for indexes
  169. * @tparam Type The Matrix type (FULL or SYMMETRIC)
  170. */
  171. template<typename DataType, typename IndexType, MatrixType Type>
  172. struct SpMat {
  173. using dataType = DataType; //!< meta:export of underling data type
  174. using indexType = IndexType; //!< meta:export of underling index type
  175. static constexpr MatrixType matrixType = Type; //!< export of array type
  176. friend struct SpMatCol<DataType, IndexType>;
  177. friend struct SpMatRow<DataType, IndexType>;
  178. friend struct SpMatVal<DataType, IndexType>;
  179. /*!
  180. * \name Obj lifetime
  181. */
  182. //! @{
  183. //! Default ctor with optional memory allocations
  184. SpMat(IndexType n=IndexType{}, IndexType nnz=IndexType{}) :
  185. values(nnz, DataType{}),
  186. rows(nnz, IndexType{}),
  187. col_ptr((n)? n+1:2, IndexType{}),
  188. N(n),
  189. NNZ(nnz) { }
  190. //! A ctor using csc array data
  191. SpMat(IndexType n, IndexType nnz, const IndexType* row, const IndexType* col) :
  192. values(nnz, 1),
  193. rows(row, row+nnz),
  194. col_ptr(col, col+n+1),
  195. N(n),
  196. NNZ(nnz) { }
  197. //! ctor using csc array data with value array
  198. SpMat(IndexType n, IndexType nnz, const DataType* v, const IndexType* row, const IndexType* col) :
  199. values(v, v+nnz),
  200. rows(row, row+nnz),
  201. col_ptr(col, col+n+1),
  202. N(n),
  203. NNZ(nnz) { }
  204. //! ctor vectors of row/col and default value for values array
  205. SpMat(IndexType n, IndexType nnz, const DataType v, const std::vector<IndexType>& row, const std::vector<IndexType>& col) :
  206. values(nnz, v),
  207. rows (row),
  208. col_ptr(col),
  209. N(n),
  210. NNZ(nnz) { }
  211. //! move ctor
  212. SpMat(SpMat&& a) noexcept { moves(std::move(a)); }
  213. //! move
  214. SpMat& operator=(SpMat&& a) noexcept { moves(std::move(a)); return *this; }
  215. SpMat(const SpMat& a) = delete; //!< make sure there are no copies
  216. SpMat& operator=(const SpMat& a) = delete; //!< make sure there are no copies
  217. //! @}
  218. //! \name Data exposure
  219. //! @{
  220. //! \return the dimension of the matrix
  221. IndexType size() noexcept { return N; }
  222. //! After construction size configuration tool
  223. IndexType size(IndexType n) {
  224. col_ptr.resize(n+1);
  225. return N = n;
  226. }
  227. //! \return the NNZ of the matrix
  228. IndexType capacity() noexcept { return NNZ; }
  229. //! After construction NNZ size configuration tool
  230. IndexType capacity(IndexType nnz) {
  231. values.reserve(nnz);
  232. rows.reserve(nnz);
  233. return NNZ;
  234. }
  235. // getters for row arrays of the struct (unused)
  236. std::vector<DataType>& getValues() noexcept { return values; }
  237. std::vector<IndexType>& getRows() noexcept { return rows; }
  238. std::vector<IndexType>& getCols() noexcept { return col_ptr; }
  239. /*!
  240. * Return a proxy SpMatVal object with read and write capabilities.
  241. * @param i The row number
  242. * @param j The column number
  243. * @return tHE SpMatVal object
  244. */
  245. SpMatVal<DataType, IndexType> operator()(IndexType i, IndexType j) {
  246. return SpMatVal<DataType, IndexType>(this, get(i, j), i, j);
  247. }
  248. /*!
  249. * A read item functionality using binary search to find the correct row
  250. *
  251. * @param i The row number
  252. * @param j The column number
  253. * @return The value of the item or DataType{} if is not present.
  254. */
  255. DataType get(IndexType i, IndexType j) {
  256. IndexType end, idx =find_idx(rows, col_ptr[j], end=col_ptr[j+1], i);
  257. return (idx != end) ? values[idx] : 0;
  258. }
  259. /*!
  260. * A write item functionality.
  261. *
  262. * First we search if the matrix has already a value in (i, j) position.
  263. * If so we just change it to a new value. If not we add the item on the matrix.
  264. *
  265. * @note
  266. * We don't increase the NNZ value of the struct. We expect the user has already
  267. * change the NNZ value to the right one using @see capacity() function.
  268. *
  269. * @param i The row number
  270. * @param j The column number
  271. * @return The new value of the item .
  272. */
  273. DataType set(DataType v, IndexType i, IndexType j) {
  274. IndexType idx; bool found;
  275. std::tie(idx, found) = find2_idx(rows, col_ptr[j], col_ptr[j+1], i);
  276. if (found)
  277. return values[idx] = v; // we don't change NNZ even if we write "0"
  278. else {
  279. values.insert(values.begin()+idx, v);
  280. rows.insert(rows.begin()+idx, i);
  281. std::transform(col_ptr.begin()+j+1, col_ptr.end(), col_ptr.begin()+j+1, [](IndexType it) {
  282. return ++it;
  283. });
  284. ++NNZ; // we increase the NNZ even if we write "0"
  285. return v;
  286. }
  287. }
  288. /*!
  289. * Get a view of a CSC column
  290. * @param j The column to get
  291. * @return The SpMatCol object @see SpMatCol
  292. */
  293. SpMatCol<DataType, IndexType> getCol(IndexType j) {
  294. return SpMatCol<DataType, IndexType>(this, col_ptr[j], col_ptr[j+1]);
  295. }
  296. /*!
  297. * Get a view of a CSC row
  298. *
  299. * In case of a SYMMETRIC matrix we can return a column instead.
  300. *
  301. * @param j The row to get
  302. * @return The SpMatCol object @see SpMatCol
  303. */
  304. template<MatrixType AT= Type>
  305. std::enable_if_t<AT==MatrixType::SYMMETRIC, SpMatCol<DataType, IndexType>>
  306. getRow(IndexType i) {
  307. return getCol(i);
  308. }
  309. /*!
  310. * Get a view of a CSC row
  311. *
  312. * @param j The row to get
  313. * @return The SpMatRow object @see SpMatRow
  314. */
  315. template<MatrixType AT= Type>
  316. std::enable_if_t<AT==MatrixType::FULL, SpMatCol<DataType, IndexType>>
  317. getRow(IndexType i) {
  318. return SpMatRow<DataType, IndexType>(this, i);
  319. }
  320. // values only iterator support
  321. DataType* begin() noexcept { return values.begin(); }
  322. DataType* end() noexcept { return values.end(); }
  323. //! @}
  324. //! A small iteration helper
  325. template<typename F, typename... Args>
  326. void for_each_in (IndexType begin, IndexType end, F&& lambda, Args&&... args) {
  327. for (IndexType it=begin ; it<end ; ++it) {
  328. std::forward<F>(lambda)(std::forward<Args>(args)..., it);
  329. }
  330. }
  331. // friend operations for printing
  332. template<typename D, typename I, MatrixType T> friend void print(SpMat<D, I, T>& mat);
  333. template<typename D, typename I, MatrixType T> friend void print_dense(SpMat<D, I, T>& mat);
  334. private:
  335. /*!
  336. * A small binary search implementation using index for begin-end instead of iterators.
  337. *
  338. * \param v Reference to vector to search
  339. * \param begin The vector's index to begin
  340. * \param end The vector's index to end
  341. * \param match What to search
  342. * @return The index of the item or end on failure.
  343. */
  344. IndexType find_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
  345. IndexType b = begin, e = end-1;
  346. while (true) {
  347. IndexType m = (b+e)/2;
  348. if (v[m] == match) return m;
  349. else if (b >= e) return end;
  350. else {
  351. if (v[m] < match) b = m +1;
  352. else e = m -1;
  353. }
  354. }
  355. return end;
  356. }
  357. /*!
  358. * find helper for set using index for begin-end instead of iterators.
  359. *
  360. * We search for the item or a place to add the item.
  361. * So we return the index if we find it. Otherwise we return the place to add it.
  362. *
  363. * \param v Reference to vector to search
  364. * \param begin The vector's index to begin
  365. * \param end The vector's index to end
  366. * \param match What to search
  367. */
  368. std::pair<IndexType, bool> find2_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
  369. for ( ; begin < end ; ++begin) {
  370. if (match == v[begin]) return std::make_pair(begin, true);
  371. else if (match < v[begin]) return std::make_pair(begin, false);
  372. }
  373. return std::make_pair(end, false);
  374. }
  375. // move helper
  376. void moves(SpMat&& src) noexcept {
  377. values = std::move(src.values);
  378. rows = std::move(src.rows);
  379. col_ptr = std::move(src.col_ptr);
  380. N = std::move(src.N); // redundant for primitives
  381. NNZ = std::move(src.NNZ); //
  382. }
  383. //! \name Data
  384. //! @{
  385. std::vector<DataType> values {}; //!< vector to store the values of the matrix
  386. std::vector<IndexType> rows{}; //!< vector to store the row information
  387. std::vector<IndexType> col_ptr{1,0}; //!< vector to stor the column pointers
  388. IndexType N{0}; //!< The dimension of the matrix (square)
  389. IndexType NNZ{0}; //!< The NNZ (capacity of the matrix)
  390. //! @}
  391. };
  392. /*!
  393. * A view/iterator hybrid object for SpMat columns.
  394. *
  395. * This object provides access to a column of a SpMat. The public functionalities
  396. * allow data access using indexes instead of iterators. We prefer indexes over iterators
  397. * because we can apply the same index to different inner vector of SpMat without conversion.
  398. *
  399. * @tparam DataType
  400. * @tparam IndexType
  401. */
  402. template<typename DataType, typename IndexType>
  403. struct SpMatCol {
  404. using owner_t = SpMat<DataType, IndexType>;
  405. /*!
  406. * ctor using column pointers for begin-end. own is pointer to SpMat.
  407. */
  408. SpMatCol(owner_t* own, const IndexType begin, const IndexType end) noexcept :
  409. owner_(own), index_(begin), begin_(begin), end_(end) {
  410. vindex_ = vIndexCalc(index_);
  411. }
  412. SpMatCol() = default;
  413. SpMatCol(const SpMatCol&) = delete; //!< make sure there are no copies
  414. SpMatCol& operator=(const SpMatCol&)= delete; //!< make sure there are no copies
  415. SpMatCol(SpMatCol&&) = default;
  416. SpMatCol& operator=(SpMatCol&&) = default;
  417. //! a simple dereference operator, like an iterator
  418. DataType operator* () {
  419. return get();
  420. }
  421. //! Increment operator acts on index(), like an iterator
  422. SpMatCol& operator++ () { advance(); return *this; }
  423. SpMatCol& operator++ (int) { SpMatCol& p = *this; advance(); return p; }
  424. //! () operator acts as member access (like a view)
  425. DataType operator()(IndexType x) {
  426. return (x == index())? get() : DataType{};
  427. }
  428. //! = operator acts as member assignment (like a view)
  429. DataType operator= (DataType v) { return owner_->values[index_] = v; }
  430. // iterator like handlers
  431. // these return a virtual index value based on the items position on the full matrix
  432. // but the move of the index is just a ++ away.
  433. IndexType index() noexcept { return vindex_; }
  434. const IndexType index() const noexcept { return vindex_; }
  435. IndexType begin() noexcept { return vIndexCalc(begin_); }
  436. const IndexType begin() const noexcept { return vIndexCalc(begin_); }
  437. IndexType end() noexcept { return owner_->N; }
  438. const IndexType end() const noexcept { return owner_->N; }
  439. /*!
  440. * Multiplication operator
  441. * @tparam C Universal reference for the type right half site column
  442. *
  443. * @param c The right hand site matrix
  444. * @return The value of the inner product of two vectors
  445. */
  446. template <typename C>
  447. DataType operator* (C&& c) {
  448. static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
  449. DataType v{};
  450. while (index() != end() && c.index() != c.end()) {
  451. if (index() < c.index()) advance();
  452. else if (index() > c.index()) ++c;
  453. else { //index() == c.index()
  454. v += get() * *c;
  455. ++c;
  456. advance();
  457. }
  458. }
  459. return v;
  460. }
  461. private:
  462. //! small tool to increase the index pointers to SpMat matrix
  463. void advance() noexcept {
  464. ++index_;
  465. vindex_ = vIndexCalc(index_);
  466. }
  467. //! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
  468. IndexType vIndexCalc(IndexType idx) {
  469. return (idx < end_) ? owner_->rows[idx] : end();
  470. }
  471. //! small get tool
  472. DataType get() { return owner_->values[index_]; }
  473. owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
  474. IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
  475. IndexType index_ {IndexType{}}; //!< index to SpMat::rows
  476. IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
  477. IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
  478. };
  479. /*!
  480. * A view/iterator hybrid object for SpMat rows.
  481. *
  482. * This object provides access to a column of a SpMat. The public functionalities
  483. * allow data access using indexes instead of iterators. We prefer indexes over iterators
  484. * because we can apply the same index to different inner vector of SpMat without conversion.
  485. *
  486. * @tparam DataType
  487. * @tparam IndexType
  488. */
  489. template<typename DataType, typename IndexType>
  490. struct SpMatRow {
  491. using owner_t = SpMat<DataType, IndexType>;
  492. /*!
  493. * ctor using virtual full matrix row index. own is pointer to SpMat.
  494. */
  495. SpMatRow(owner_t* own, const IndexType row) noexcept :
  496. owner_(own), vindex_(IndexType{}), row_(row), index_(IndexType{}),
  497. begin_(IndexType{}), end_(owner_->NNZ) {
  498. // place begin
  499. while(begin_ != end_ && owner_->rows[begin_] != row_)
  500. ++begin_;
  501. // place index_ and vindex_
  502. if (owner_->rows[index_] != row_)
  503. advance();
  504. }
  505. SpMatRow() = default;
  506. SpMatRow(const SpMatRow&) = delete; //!< make sure there are no copies
  507. SpMatRow& operator=(const SpMatRow&)= delete; //!< make sure there are no copies
  508. SpMatRow(SpMatRow&&) = default;
  509. SpMatRow& operator=(SpMatRow&&) = default;
  510. //! a simple dereference operator, like an iterator
  511. DataType operator* () {
  512. return get();
  513. }
  514. //! Increment operator acts on index(), like an iterator
  515. //! here the increment is a O(N) process.
  516. SpMatRow& operator++ () { advance(); return *this; }
  517. SpMatRow& operator++ (int) { SpMatRow& p = *this; advance(); return p; }
  518. //! () operator acts as member access (like a view)
  519. DataType operator()(IndexType x) {
  520. return (x == index())? get() : DataType{};
  521. }
  522. //! = operator acts as member assignment (like a view)
  523. DataType operator= (DataType v) { return owner_->values[index_] = v; }
  524. // iterator like handlers
  525. // these return a virtual index value based on the items position on the full matrix
  526. // but the move of the index is just a ++ away.
  527. IndexType index() noexcept { return vindex_; }
  528. const IndexType index() const noexcept { return vindex_; }
  529. IndexType begin() noexcept { return vIndexCalc(begin_); }
  530. const IndexType begin() const noexcept { return vIndexCalc(begin_); }
  531. IndexType end() noexcept { return owner_->N; }
  532. const IndexType end() const noexcept { return owner_->N; }
  533. /*!
  534. * Multiplication operator
  535. * @tparam C Universal reference for the type right half site column
  536. *
  537. * @param c The right hand site matrix
  538. * @return The value of the inner product of two vectors
  539. */
  540. template <typename C>
  541. DataType operator* (C&& c) {
  542. static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
  543. DataType v{};
  544. while (index() != end() && c.index() != c.end()) {
  545. if (index() < c.index()) advance();
  546. else if (index() > c.index()) ++c;
  547. else { //index() == c.index()
  548. v += get()* *c;
  549. ++c;
  550. advance();
  551. }
  552. }
  553. return v;
  554. }
  555. private:
  556. //! small tool to increase the index pointers to SpMat matrix
  557. //! We have to search the entire rows vector in SpMat to find the next
  558. //! virtual row position.
  559. //! time complexity O(N)
  560. void advance() noexcept {
  561. do
  562. ++index_;
  563. while(index_ != end_ && owner_->rows[index_] != row_);
  564. vindex_ = vIndexCalc(index_);
  565. }
  566. //! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
  567. IndexType vIndexCalc(IndexType idx) {
  568. for(IndexType i =0 ; i<(owner_->N+1) ; ++i)
  569. if (idx < owner_->col_ptr[i])
  570. return i-1;
  571. return end();
  572. }
  573. //! small get tool
  574. DataType get() { return owner_->values[index_]; }
  575. owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
  576. IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
  577. IndexType row_ {IndexType{}}; //!< The virtual full matrix row of the object
  578. IndexType index_ {IndexType{}}; //!< index to SpMat::rows
  579. IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
  580. IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
  581. };
  582. /*!
  583. * A proxy SpMat value object/view.
  584. *
  585. * This object acts as proxy to provide read/write access to an SpMat item.
  586. *
  587. * @tparam DataType The type of the values of the SpMat matrix
  588. * @tparam IndexType The type of the indexes of the SpMat matrix
  589. */
  590. template<typename DataType, typename IndexType>
  591. struct SpMatVal {
  592. using owner_t = SpMat<DataType, IndexType>;
  593. //!< ctor using all value-row-column data, plus a pointer to owner SpMat object
  594. SpMatVal(owner_t* own, DataType v, IndexType i, IndexType j) :
  595. owner_(own), v_(v), i_(i), j_(j) { }
  596. SpMatVal() = default;
  597. SpMatVal(const SpMatVal&) = delete; //!< make sure there are no copies
  598. SpMatVal& operator=(const SpMatVal&) = delete; //!< make sure there are no copies
  599. SpMatVal(SpMatVal&&) = default;
  600. SpMatVal& operator=(SpMatVal&&) = default;
  601. //! Operator to return the DataType value implicitly
  602. operator DataType() { return v_; }
  603. //! Operator to write back to owner the assigned value
  604. //! for ex: A(2,3) = 5;
  605. SpMatVal& operator=(DataType v) {
  606. v_ = v;
  607. owner_->set(v_, i_, j_);
  608. return *this;
  609. }
  610. private:
  611. owner_t* owner_{nullptr}; //!< Pointer to owner SpMat. SpMatVal is just a view.
  612. DataType v_{DataType{}}; //!< The value of the row-column pair (for speed)
  613. IndexType i_{IndexType{}}; //!< The row
  614. IndexType j_{IndexType{}}; //!< the column
  615. };
  616. //! enumerator for input matrix type.
  617. enum class InputMatrix{ UNSPECIFIED, GENERATE, MTX };
  618. //! enumerator for output handling
  619. enum class OutputMode{ STD, FILE };
  620. /*!
  621. * Session option for each invocation of the executable
  622. */
  623. struct session_t {
  624. InputMatrix inputMatrix {InputMatrix::UNSPECIFIED}; //!< Source of the matrix
  625. std::ifstream mtxFile {}; //!< matrix file in MatrixMarket format
  626. std::size_t gen_size {}; //!< size of the matrix if we select to generate a random one
  627. double gen_prob {}; //!< probability of the binomial distribution for the matrix
  628. //!< if we generate one
  629. OutputMode outputMode {OutputMode::STD}; //!< Type of the output file
  630. std::ofstream outFile {}; //!< File to use for output
  631. std::size_t max_threads {}; //!< Maximum threads to use
  632. bool timing {false}; //!< Enable timing prints of the program
  633. bool verbose {false}; //!< Flag to enable verbose output to stdout
  634. bool makeSymmetric {true}; //!< symmetric matrix creation flag (true by default)
  635. bool validate_mtx {false}; //!< Flag to request mtx input data triangular validation.
  636. bool print_count {false}; //!< Flag to request total count printing
  637. bool mtx_print {false}; //!< matrix print flag
  638. std::size_t mtx_print_size {}; //!< matrix print size
  639. };
  640. extern session_t session;
  641. #endif /* IMPL_HPP_ */