A 2nd implementation conforming to vector creation [need optimization]
This commit is contained in:
@@ -14,14 +14,19 @@
|
||||
#include <v3.h>
|
||||
#include <v4.h>
|
||||
|
||||
/*
|
||||
* Defines for different version of the exercise
|
||||
*/
|
||||
#define V12 2
|
||||
#define V3 3
|
||||
#define V4 4
|
||||
|
||||
// Fail-safe verision selection
|
||||
#if !defined CODE_VERSION
|
||||
#define CODE_VERSION V4
|
||||
#endif
|
||||
|
||||
// matrix alias template dispatcher based on pre-define flag from compiler (see Makefile)
|
||||
#if CODE_VERSION == V12
|
||||
using namespace v12;
|
||||
using matrix = v12::matrix;
|
||||
|
||||
+249
-66
@@ -168,25 +168,42 @@ Matrix<DataType, IndexType, Type> make_Matrix(IndexType s) {
|
||||
return Matrix<DataType, IndexType, Type>(new DataType[Matrix<DataType, IndexType, Type>::capacity(s)], s);
|
||||
}
|
||||
|
||||
template<typename DataType, typename IndexType>
|
||||
using CooVal = std::tuple<DataType, IndexType, IndexType>;
|
||||
|
||||
/**
|
||||
* A simple sparse matrix implementation.
|
||||
*
|
||||
* We use CSC format and provide get/set functionalities for each (i,j) item
|
||||
* on the matrix. We also provide a () overload using a proxy SpMatVal object.
|
||||
* This way the user can:
|
||||
* \code
|
||||
* auto v = A(3,4);
|
||||
* A(3, 4) = 7;
|
||||
* \endcode
|
||||
*
|
||||
* We also provide getCol() and getRow() functions witch return a viwer/iterator to rows and
|
||||
* columns of the matrix. In the case of a symmetric matrix instead of a row we return the
|
||||
* equivalent column. This way we gain speed due to CSC format nature.
|
||||
*
|
||||
* @tparam DataType The type for values
|
||||
* @tparam IndexType The type for indexes
|
||||
* @tparam Type The Matrix type (FULL or SYMMETRIC)
|
||||
*/
|
||||
template<typename DataType, typename IndexType, MatrixType Type>
|
||||
struct SpMat {
|
||||
using dataType = DataType; //!< meta:export of underling data type
|
||||
using indexType = IndexType; //!< meta:export of underling index type
|
||||
static constexpr MatrixType matrixType = Type; //!< export of array type
|
||||
|
||||
friend class SpMatCol<DataType, IndexType>;
|
||||
friend class SpMatRow<DataType, IndexType>;
|
||||
friend class SpMatVal<DataType, IndexType>;
|
||||
friend struct SpMatCol<DataType, IndexType>;
|
||||
friend struct SpMatRow<DataType, IndexType>;
|
||||
friend struct SpMatVal<DataType, IndexType>;
|
||||
|
||||
/*!
|
||||
* \name Obj lifetime
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! allocation with init value ctor
|
||||
//! Default ctor with optional memory allocations
|
||||
SpMat(IndexType n=IndexType{}, IndexType nnz=IndexType{}) :
|
||||
values(nnz, DataType{}),
|
||||
rows(nnz, IndexType{}),
|
||||
@@ -194,6 +211,7 @@ struct SpMat {
|
||||
N(n),
|
||||
NNZ(nnz) { }
|
||||
|
||||
//! A ctor using csc array data
|
||||
SpMat(IndexType n, IndexType nnz, const IndexType* row, const IndexType* col) :
|
||||
values(nnz, 1),
|
||||
rows(row, row+nnz),
|
||||
@@ -201,6 +219,7 @@ struct SpMat {
|
||||
N(n),
|
||||
NNZ(nnz) { }
|
||||
|
||||
//! ctor using csc array data with value array
|
||||
SpMat(IndexType n, IndexType nnz, const DataType* v, const IndexType* row, const IndexType* col) :
|
||||
values(v, v+nnz),
|
||||
rows(row, row+nnz),
|
||||
@@ -208,6 +227,7 @@ struct SpMat {
|
||||
N(n),
|
||||
NNZ(nnz) { }
|
||||
|
||||
//! ctor vectors of row/col and default value for values array
|
||||
SpMat(IndexType n, IndexType nnz, const DataType v, const std::vector<IndexType>& row, const std::vector<IndexType>& col) :
|
||||
values(nnz, v),
|
||||
rows (row),
|
||||
@@ -219,38 +239,72 @@ struct SpMat {
|
||||
SpMat(SpMat&& a) noexcept { moves(std::move(a)); }
|
||||
//! move
|
||||
SpMat& operator=(SpMat&& a) noexcept { moves(std::move(a)); return *this; }
|
||||
SpMat(const SpMat& a) = delete; //!< No copy ctor
|
||||
SpMat& operator=(const SpMat& a) = delete; //!< No copy assignment
|
||||
SpMat(const SpMat& a) = delete; //!< make sure there are no copies
|
||||
SpMat& operator=(const SpMat& a) = delete; //!< make sure there are no copies
|
||||
//! @}
|
||||
|
||||
//! \name Data exposure
|
||||
//! @{
|
||||
|
||||
//! \return the dimension of the matrix
|
||||
IndexType size() noexcept { return N; }
|
||||
//! After construction size configuration tool
|
||||
IndexType size(IndexType n) {
|
||||
col_ptr.resize(n+1);
|
||||
return N = n;
|
||||
}
|
||||
//! \return the NNZ of the matrix
|
||||
IndexType capacity() noexcept { return NNZ; }
|
||||
//! After construction NNZ size configuration tool
|
||||
IndexType capacity(IndexType nnz) {
|
||||
values.reserve(nnz);
|
||||
rows.reserve(nnz);
|
||||
return NNZ;
|
||||
}
|
||||
// getters for row arrays of the struct (unused)
|
||||
std::vector<DataType>& getValues() noexcept { return values; }
|
||||
std::vector<IndexType>& getRows() noexcept { return rows; }
|
||||
std::vector<IndexType>& getCols() noexcept { return col_ptr; }
|
||||
|
||||
/*!
|
||||
* Return a proxy SpMatVal object with read and write capabilities.
|
||||
* @param i The row number
|
||||
* @param j The column number
|
||||
* @return tHE SpMatVal object
|
||||
*/
|
||||
SpMatVal<DataType, IndexType> operator()(IndexType i, IndexType j) {
|
||||
return SpMatVal<DataType, IndexType>(this, get(i, j), i, j);
|
||||
}
|
||||
|
||||
/*!
|
||||
* A read item functionality using binary search to find the correct row
|
||||
*
|
||||
* @param i The row number
|
||||
* @param j The column number
|
||||
* @return The value of the item or DataType{} if is not present.
|
||||
*/
|
||||
DataType get(IndexType i, IndexType j) {
|
||||
IndexType idx;
|
||||
bool found;
|
||||
std::tie(idx, found) =find_idx(rows, col_ptr[j], col_ptr[j+1], i);
|
||||
return (found) ? values[idx] : 0;
|
||||
IndexType end, idx =find_idx(rows, col_ptr[j], end=col_ptr[j+1], i);
|
||||
return (idx != end) ? values[idx] : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* A write item functionality.
|
||||
*
|
||||
* First we search if the matrix has already a value in (i, j) position.
|
||||
* If so we just change it to a new value. If not we add the item on the matrix.
|
||||
*
|
||||
* @note
|
||||
* We don't increase the NNZ value of the struct. We expect the user has already
|
||||
* change the NNZ value to the right one using @see capacity() function.
|
||||
*
|
||||
* @param i The row number
|
||||
* @param j The column number
|
||||
* @return The new value of the item .
|
||||
*/
|
||||
DataType set(DataType v, IndexType i, IndexType j) {
|
||||
IndexType idx; bool found;
|
||||
std::tie(idx, found) = find_idx(rows, col_ptr[j], col_ptr[j+1], i);
|
||||
std::tie(idx, found) = find2_idx(rows, col_ptr[j], col_ptr[j+1], i);
|
||||
if (found)
|
||||
return values[idx] = v; // we don't change NNZ even if we write "0"
|
||||
else {
|
||||
@@ -264,34 +318,47 @@ struct SpMat {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Get a view of a CSC column
|
||||
* @param j The column to get
|
||||
* @return The SpMatCol object @see SpMatCol
|
||||
*/
|
||||
SpMatCol<DataType, IndexType> getCol(IndexType j) {
|
||||
return SpMatCol<DataType, IndexType>(this, col_ptr[j], col_ptr[j+1]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get a view of a CSC row
|
||||
*
|
||||
* In case of a SYMMETRIC matrix we can return a column instead.
|
||||
*
|
||||
* @param j The row to get
|
||||
* @return The SpMatCol object @see SpMatCol
|
||||
*/
|
||||
template<MatrixType AT= Type>
|
||||
std::enable_if_t<AT==MatrixType::SYMMETRIC, SpMatCol<DataType, IndexType>>
|
||||
getRow(IndexType i) {
|
||||
return getCol(i);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get a view of a CSC row
|
||||
*
|
||||
* @param j The row to get
|
||||
* @return The SpMatRow object @see SpMatRow
|
||||
*/
|
||||
template<MatrixType AT= Type>
|
||||
std::enable_if_t<AT==MatrixType::FULL, SpMatCol<DataType, IndexType>>
|
||||
getRow(IndexType i) {
|
||||
return SpMatRow<DataType, IndexType>(this, i);
|
||||
}
|
||||
|
||||
// iterator support
|
||||
// values only iterator support
|
||||
DataType* begin() noexcept { return values.begin(); }
|
||||
DataType* end() noexcept { return values.end(); }
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
* \name Safe iteration API
|
||||
*
|
||||
* This api automates the iteration over the array based on
|
||||
* MatrixType
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! A small iteration helper
|
||||
template<typename F, typename... Args>
|
||||
void for_each_in (IndexType begin, IndexType end, F&& lambda, Args&&... args) {
|
||||
for (IndexType it=begin ; it<end ; ++it) {
|
||||
@@ -299,15 +366,45 @@ struct SpMat {
|
||||
}
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
// operations
|
||||
// friend operations for printing
|
||||
template<typename D, typename I, MatrixType T> friend void print(SpMat<D, I, T>& mat);
|
||||
template<typename D, typename I, MatrixType T> friend void print_dense(SpMat<D, I, T>& mat);
|
||||
|
||||
private:
|
||||
// index-find helper
|
||||
std::pair<IndexType, bool> find_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
|
||||
/*!
|
||||
* A small binary search implementation using index for begin-end instead of iterators.
|
||||
*
|
||||
* \param v Reference to vector to search
|
||||
* \param begin The vector's index to begin
|
||||
* \param end The vector's index to end
|
||||
* \param match What to search
|
||||
* @return The index of the item or end on failure.
|
||||
*/
|
||||
IndexType find_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
|
||||
IndexType b = begin, e = end-1;
|
||||
while (true) {
|
||||
IndexType m = (b+e)/2;
|
||||
if (v[m] == match) return m;
|
||||
else if (b >= e) return end;
|
||||
else {
|
||||
if (v[m] < match) b = m +1;
|
||||
else e = m -1;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
/*!
|
||||
* find helper for set using index for begin-end instead of iterators.
|
||||
*
|
||||
* We search for the item or a place to add the item.
|
||||
* So we return the index if we find it. Otherwise we return the place to add it.
|
||||
*
|
||||
* \param v Reference to vector to search
|
||||
* \param begin The vector's index to begin
|
||||
* \param end The vector's index to end
|
||||
* \param match What to search
|
||||
*/
|
||||
std::pair<IndexType, bool> find2_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
|
||||
for ( ; begin < end ; ++begin) {
|
||||
if (match == v[begin]) return std::make_pair(begin, true);
|
||||
else if (match < v[begin]) return std::make_pair(begin, false);
|
||||
@@ -324,38 +421,58 @@ private:
|
||||
}
|
||||
//! \name Data
|
||||
//! @{
|
||||
std::vector<DataType> values {};
|
||||
std::vector<IndexType> rows{};
|
||||
std::vector<IndexType> col_ptr{1,0};
|
||||
IndexType N{0};
|
||||
IndexType NNZ{0};
|
||||
std::vector<DataType> values {}; //!< vector to store the values of the matrix
|
||||
std::vector<IndexType> rows{}; //!< vector to store the row information
|
||||
std::vector<IndexType> col_ptr{1,0}; //!< vector to stor the column pointers
|
||||
IndexType N{0}; //!< The dimension of the matrix (square)
|
||||
IndexType NNZ{0}; //!< The NNZ (capacity of the matrix)
|
||||
//! @}
|
||||
};
|
||||
|
||||
/*!
|
||||
* A view/iterator hybrid object for SpMat columns.
|
||||
*
|
||||
* This object provides access to a column of a SpMat. The public functionalities
|
||||
* allow data access using indexes instead of iterators. We prefer indexes over iterators
|
||||
* because we can apply the same index to different inner vector of SpMat without conversion.
|
||||
*
|
||||
* @tparam DataType
|
||||
* @tparam IndexType
|
||||
*/
|
||||
template<typename DataType, typename IndexType>
|
||||
struct SpMatCol {
|
||||
using owner_t = SpMat<DataType, IndexType>;
|
||||
|
||||
/*!
|
||||
* ctor using column pointers for begin-end. own is pointer to SpMat.
|
||||
*/
|
||||
SpMatCol(owner_t* own, const IndexType begin, const IndexType end) noexcept :
|
||||
owner_(own), index_(begin), begin_(begin), end_(end) {
|
||||
vindex_ = vIndexCalc(index_);
|
||||
}
|
||||
SpMatCol() = default;
|
||||
SpMatCol(const SpMatCol&) = delete;
|
||||
SpMatCol& operator=(const SpMatCol&)= delete;
|
||||
SpMatCol(const SpMatCol&) = delete; //!< make sure there are no copies
|
||||
SpMatCol& operator=(const SpMatCol&)= delete; //!< make sure there are no copies
|
||||
SpMatCol(SpMatCol&&) = default;
|
||||
SpMatCol& operator=(SpMatCol&&) = default;
|
||||
|
||||
//! a simple dereference operator, like an iterator
|
||||
DataType operator* () {
|
||||
return get();
|
||||
}
|
||||
//! Increment operator acts on index(), like an iterator
|
||||
SpMatCol& operator++ () { advance(); return *this; }
|
||||
SpMatCol& operator++ (int) { SpMatCol& p = *this; advance(); return p; }
|
||||
|
||||
//! () operator acts as member access (like a view)
|
||||
DataType operator()(IndexType x) {
|
||||
return (x == index())? get() : DataType{};
|
||||
}
|
||||
//! = operator acts as member assignment (like a view)
|
||||
DataType operator= (DataType v) { return owner_->values[index_] = v; }
|
||||
// iterator like handlers
|
||||
// these return a virtual index value based on the items position on the full matrix
|
||||
// but the move of the index is just a ++ away.
|
||||
IndexType index() noexcept { return vindex_; }
|
||||
const IndexType index() const noexcept { return vindex_; }
|
||||
IndexType begin() noexcept { return vIndexCalc(begin_); }
|
||||
@@ -363,6 +480,13 @@ struct SpMatCol {
|
||||
IndexType end() noexcept { return owner_->N; }
|
||||
const IndexType end() const noexcept { return owner_->N; }
|
||||
|
||||
/*!
|
||||
* Multiplication operator
|
||||
* @tparam C Universal reference for the type right half site column
|
||||
*
|
||||
* @param c The right hand site matrix
|
||||
* @return The value of the inner product of two vectors
|
||||
*/
|
||||
template <typename C>
|
||||
DataType operator* (C&& c) {
|
||||
static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
|
||||
@@ -380,25 +504,42 @@ struct SpMatCol {
|
||||
}
|
||||
|
||||
private:
|
||||
//! small tool to increase the index pointers to SpMat matrix
|
||||
void advance() noexcept {
|
||||
++index_;
|
||||
vindex_ = vIndexCalc(index_);
|
||||
}
|
||||
//! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
|
||||
IndexType vIndexCalc(IndexType idx) {
|
||||
return (idx < end_) ? owner_->rows[idx] : end();
|
||||
}
|
||||
//! small get tool
|
||||
DataType get() { return owner_->values[index_]; }
|
||||
owner_t* owner_{nullptr};
|
||||
IndexType vindex_ {IndexType{}};
|
||||
IndexType index_{IndexType{}};
|
||||
IndexType begin_{IndexType{}};
|
||||
IndexType end_{IndexType{}};
|
||||
|
||||
owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
|
||||
IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
|
||||
IndexType index_ {IndexType{}}; //!< index to SpMat::rows
|
||||
IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
|
||||
IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
|
||||
};
|
||||
|
||||
/*!
|
||||
* A view/iterator hybrid object for SpMat rows.
|
||||
*
|
||||
* This object provides access to a column of a SpMat. The public functionalities
|
||||
* allow data access using indexes instead of iterators. We prefer indexes over iterators
|
||||
* because we can apply the same index to different inner vector of SpMat without conversion.
|
||||
*
|
||||
* @tparam DataType
|
||||
* @tparam IndexType
|
||||
*/
|
||||
template<typename DataType, typename IndexType>
|
||||
struct SpMatRow {
|
||||
using owner_t = SpMat<DataType, IndexType>;
|
||||
|
||||
/*!
|
||||
* ctor using virtual full matrix row index. own is pointer to SpMat.
|
||||
*/
|
||||
SpMatRow(owner_t* own, const IndexType row) noexcept :
|
||||
owner_(own), vindex_(IndexType{}), row_(row), index_(IndexType{}),
|
||||
begin_(IndexType{}), end_(owner_->NNZ) {
|
||||
@@ -410,20 +551,29 @@ struct SpMatRow {
|
||||
advance();
|
||||
}
|
||||
SpMatRow() = default;
|
||||
SpMatRow(const SpMatRow&) = delete;
|
||||
SpMatRow& operator=(const SpMatRow&)= delete;
|
||||
SpMatRow(const SpMatRow&) = delete; //!< make sure there are no copies
|
||||
SpMatRow& operator=(const SpMatRow&)= delete; //!< make sure there are no copies
|
||||
SpMatRow(SpMatRow&&) = default;
|
||||
SpMatRow& operator=(SpMatRow&&) = default;
|
||||
|
||||
//! a simple dereference operator, like an iterator
|
||||
DataType operator* () {
|
||||
return get();
|
||||
}
|
||||
//! Increment operator acts on index(), like an iterator
|
||||
//! here the increment is a O(N) process.
|
||||
SpMatRow& operator++ () { advance(); return *this; }
|
||||
SpMatRow& operator++ (int) { SpMatRow& p = *this; advance(); return p; }
|
||||
|
||||
//! () operator acts as member access (like a view)
|
||||
DataType operator()(IndexType x) {
|
||||
return (x == index())? get() : DataType{};
|
||||
}
|
||||
//! = operator acts as member assignment (like a view)
|
||||
DataType operator= (DataType v) { return owner_->values[index_] = v; }
|
||||
// iterator like handlers
|
||||
// these return a virtual index value based on the items position on the full matrix
|
||||
// but the move of the index is just a ++ away.
|
||||
IndexType index() noexcept { return vindex_; }
|
||||
const IndexType index() const noexcept { return vindex_; }
|
||||
IndexType begin() noexcept { return vIndexCalc(begin_); }
|
||||
@@ -431,6 +581,13 @@ struct SpMatRow {
|
||||
IndexType end() noexcept { return owner_->N; }
|
||||
const IndexType end() const noexcept { return owner_->N; }
|
||||
|
||||
/*!
|
||||
* Multiplication operator
|
||||
* @tparam C Universal reference for the type right half site column
|
||||
*
|
||||
* @param c The right hand site matrix
|
||||
* @return The value of the inner product of two vectors
|
||||
*/
|
||||
template <typename C>
|
||||
DataType operator* (C&& c) {
|
||||
static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
|
||||
@@ -447,70 +604,96 @@ struct SpMatRow {
|
||||
return v;
|
||||
}
|
||||
private:
|
||||
//! small tool to increase the index pointers to SpMat matrix
|
||||
//! We have to search the entire rows vector in SpMat to find the next
|
||||
//! virtual row position.
|
||||
//! time complexity O(N)
|
||||
void advance() noexcept {
|
||||
do
|
||||
++index_;
|
||||
while(index_ != end_ && owner_->rows[index_] != row_);
|
||||
vindex_ = vIndexCalc(index_);
|
||||
}
|
||||
//! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
|
||||
IndexType vIndexCalc(IndexType idx) {
|
||||
for(IndexType i =0 ; i<(owner_->N+1) ; ++i)
|
||||
if (idx < owner_->col_ptr[i])
|
||||
return i-1;
|
||||
return end();
|
||||
}
|
||||
//! small get tool
|
||||
DataType get() { return owner_->values[index_]; }
|
||||
owner_t* owner_ {nullptr};
|
||||
IndexType vindex_ {IndexType{}};
|
||||
IndexType row_ {IndexType{}};
|
||||
IndexType index_ {IndexType{}};
|
||||
IndexType begin_ {IndexType{}};
|
||||
IndexType end_ {IndexType{}};
|
||||
|
||||
owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
|
||||
IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
|
||||
IndexType row_ {IndexType{}}; //!< The virtual full matrix row of the object
|
||||
IndexType index_ {IndexType{}}; //!< index to SpMat::rows
|
||||
IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
|
||||
IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
|
||||
};
|
||||
|
||||
/*!
|
||||
* A proxy SpMat value object/view.
|
||||
*
|
||||
* This object acts as proxy to provide read/write access to an SpMat item.
|
||||
*
|
||||
* @tparam DataType The type of the values of the SpMat matrix
|
||||
* @tparam IndexType The type of the indexes of the SpMat matrix
|
||||
*/
|
||||
template<typename DataType, typename IndexType>
|
||||
struct SpMatVal {
|
||||
using owner_t = SpMat<DataType, IndexType>;
|
||||
|
||||
//!< ctor using all value-row-column data, plus a pointer to owner SpMat object
|
||||
SpMatVal(owner_t* own, DataType v, IndexType i, IndexType j) :
|
||||
owner_(own), v_(v), i_(i), j_(j) { }
|
||||
SpMatVal() = default;
|
||||
SpMatVal(const SpMatVal&) = delete;
|
||||
SpMatVal& operator=(const SpMatVal&) = delete;
|
||||
SpMatVal(const SpMatVal&) = delete; //!< make sure there are no copies
|
||||
SpMatVal& operator=(const SpMatVal&) = delete; //!< make sure there are no copies
|
||||
SpMatVal(SpMatVal&&) = default;
|
||||
SpMatVal& operator=(SpMatVal&&) = default;
|
||||
|
||||
//! Operator to return the DataType value implicitly
|
||||
operator DataType() { return v_; }
|
||||
//! Operator to write back to owner the assigned value
|
||||
//! for ex: A(2,3) = 5;
|
||||
SpMatVal& operator=(DataType v) {
|
||||
v_ = v;
|
||||
owner_->set(v_, i_, j_);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
owner_t* owner_{nullptr};;
|
||||
DataType v_{DataType{}};
|
||||
IndexType i_{IndexType{}};
|
||||
IndexType j_{IndexType{}};
|
||||
owner_t* owner_{nullptr}; //!< Pointer to owner SpMat. SpMatVal is just a view.
|
||||
DataType v_{DataType{}}; //!< The value of the row-column pair (for speed)
|
||||
IndexType i_{IndexType{}}; //!< The row
|
||||
IndexType j_{IndexType{}}; //!< the column
|
||||
};
|
||||
|
||||
|
||||
enum class InputMatrix{
|
||||
GENERATE,
|
||||
MTX
|
||||
};
|
||||
//! enumerator for input matrix type.
|
||||
enum class InputMatrix{ UNSPECIFIED, GENERATE, MTX };
|
||||
//! enumerator for output handling
|
||||
enum class OutputMode{ STD, FILE };
|
||||
|
||||
/*!
|
||||
* Session option for each invocation of the executable
|
||||
*/
|
||||
struct session_t {
|
||||
std::size_t size {0};
|
||||
double probability {0};
|
||||
InputMatrix inputMatrix {InputMatrix::GENERATE};
|
||||
std::ifstream mtxFile {};
|
||||
std::size_t print_size {80};
|
||||
bool timing {false};
|
||||
bool print {false};
|
||||
bool makeSymmetric {false};
|
||||
InputMatrix inputMatrix {InputMatrix::UNSPECIFIED}; //!< Source of the matrix
|
||||
std::ifstream mtxFile {}; //!< matrix file in MatrixMarket format
|
||||
std::size_t gen_size {}; //!< size of the matrix if we select to generate a random one
|
||||
double gen_prob {}; //!< probability of the binomial distribution for the matrix
|
||||
//!< if we generate one
|
||||
OutputMode outputMode {OutputMode::STD}; //!< Type of the output file
|
||||
std::ofstream outFile {}; //!< File to use for output
|
||||
std::size_t max_threads {}; //!< Maximum threads to use
|
||||
bool timing {false}; //!< Enable timing prints of the program
|
||||
bool verbose {false}; //!< Flag to enable verbose output to stdout
|
||||
bool makeSymmetric {true}; //!< symmetric matrix creation flag (true by default)
|
||||
bool validate_mtx {false}; //!< Flag to request mtx input data triangular validation.
|
||||
bool print_count {false}; //!< Flag to request total count printing
|
||||
bool mtx_print {false}; //!< matrix print flag
|
||||
std::size_t mtx_print_size {}; //!< matrix print size
|
||||
};
|
||||
|
||||
extern session_t session;
|
||||
|
||||
+108
-25
@@ -17,6 +17,10 @@
|
||||
#include <impl.hpp>
|
||||
#include <config.h>
|
||||
|
||||
/*!
|
||||
* A small RAII utility to memory allocation arrays.
|
||||
* @tparam T The type of pointer for the memory
|
||||
*/
|
||||
template <typename T>
|
||||
struct buffer_t {
|
||||
buffer_t(size_t s) { p = new T[s]; }
|
||||
@@ -34,8 +38,14 @@ private:
|
||||
T* p{nullptr};
|
||||
};
|
||||
|
||||
/*!
|
||||
* A toolbox for MatrixMarket format handling
|
||||
*/
|
||||
struct Mtx {
|
||||
|
||||
/*!
|
||||
* A template version of the coo2csc function provided by PDS lab stuff.
|
||||
*/
|
||||
template<typename I>
|
||||
static void coo2csc(I *row, I *col, I const* row_coo, I const* col_coo, I nnz, I n, I isOneBased) {
|
||||
// ----- cannot assume that input is already 0!
|
||||
@@ -70,6 +80,12 @@ struct Mtx {
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Utility to check if a matrix input is strictly triangular or not.
|
||||
* @tparam I Index type
|
||||
* @param file Reference to input file stream
|
||||
* @return The status of the operation
|
||||
*/
|
||||
template<typename I>
|
||||
static bool is_triangular (std::ifstream& file) {
|
||||
std::string line, token;
|
||||
@@ -105,6 +121,14 @@ struct Mtx {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* A utility to load an MatrixMarket file to memory
|
||||
* @tparam DataT The data type
|
||||
* @tparam IndexT The indexes type
|
||||
* @param M Reference to matrix for output
|
||||
* @param file Reference to input file stream to read from
|
||||
* @return The status of the operation
|
||||
*/
|
||||
template<typename DataT, typename IndexT, MatrixType MatrixT>
|
||||
static bool load (SpMat<DataT, IndexT, MatrixT>& M, std::ifstream& file) {
|
||||
std::string line, token;
|
||||
@@ -139,60 +163,119 @@ struct Mtx {
|
||||
if (line[0] == '%') continue;
|
||||
IndexT i, j;
|
||||
ss >> i >> j;
|
||||
if (session.makeSymmetric) {
|
||||
if (LU == Z) {
|
||||
LU = (i<j) ? UPPER: LOWER;
|
||||
}
|
||||
if ((LU==LOWER && j<i) || (LU==UPPER && i<j)) {
|
||||
coo_row[cnt] = i;
|
||||
coo_col[cnt++] = j;
|
||||
if (LU == Z) {
|
||||
LU = (i<j) ? UPPER: LOWER;
|
||||
}
|
||||
// ignore all values outside the triangle area
|
||||
if ((LU==LOWER && j<i) || (LU==UPPER && i<j)) {
|
||||
coo_row[cnt] = i;
|
||||
coo_col[cnt++] = j;
|
||||
if (session.makeSymmetric) {
|
||||
coo_row[cnt] = j;
|
||||
coo_col[cnt++] = i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
coo_row[cnt] = i;
|
||||
coo_col[cnt++] = j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
coo2csc(&row[0], &col[0], &coo_row[0], &coo_col[0], cnt, n1, 1);
|
||||
M = SpMat<DataT, IndexT, MatrixT>(n1, cnt, &row[0], &col[0]);
|
||||
return true;
|
||||
if (cnt) {
|
||||
// convert and construct
|
||||
coo2csc(&row[0], &col[0], &coo_row[0], &coo_col[0], cnt, n1, 1);
|
||||
M = SpMat<DataT, IndexT, MatrixT>(n1, cnt, &row[0], &col[0]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* A small timing utility based on chrono.
|
||||
*/
|
||||
struct Timing{
|
||||
using Tpoint = std::chrono::steady_clock::time_point;
|
||||
using microseconds = std::chrono::microseconds;
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using seconds = std::chrono::seconds;
|
||||
|
||||
|
||||
//! tool to mark the starting point
|
||||
Tpoint start () noexcept { return start_ = std::chrono::steady_clock::now(); }
|
||||
//! tool to mark the ending point
|
||||
Tpoint stop () noexcept { return stop_ = std::chrono::steady_clock::now(); }
|
||||
|
||||
auto dt () noexcept {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(stop_ - start_).count();
|
||||
}
|
||||
void print_dt () noexcept {
|
||||
auto t = stop_ - start_;
|
||||
if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
|
||||
std::cout << "time: " << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
|
||||
else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
|
||||
std::cout << "time: " << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
|
||||
else
|
||||
std::cout << "time: " << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
|
||||
|
||||
//! tool to print the time interval
|
||||
void print_dt (const char* what) noexcept {
|
||||
if (session.timing) {
|
||||
auto t = stop_ - start_;
|
||||
if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
|
||||
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
|
||||
else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
|
||||
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
|
||||
else
|
||||
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
|
||||
}
|
||||
}
|
||||
private:
|
||||
Tpoint start_;
|
||||
Tpoint stop_;
|
||||
};
|
||||
|
||||
/*!
|
||||
* A Logger for entire programm.
|
||||
*/
|
||||
struct Log {
|
||||
struct Endl {} endl; //!< a tag objec to to use it as a new line request.
|
||||
|
||||
//! We provide logging via << operator
|
||||
template<typename T>
|
||||
Log& operator<< (T&& t) {
|
||||
if (session.verbose) {
|
||||
if (line_) {
|
||||
std::cout << "[Log]: " << t;
|
||||
line_ = false;
|
||||
}
|
||||
else
|
||||
std::cout << t;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// overload for special end line handling
|
||||
Log& operator<< (Endl e) { (void)e;
|
||||
if (session.verbose) {
|
||||
std::cout << '\n';
|
||||
line_ = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
bool line_ {true};
|
||||
};
|
||||
|
||||
extern Log logger;
|
||||
|
||||
//! Total count result printing function
|
||||
template<typename F>
|
||||
void triangle_out (value_t s, F&& f) {
|
||||
f << "Total triangles: " << s << '\n';
|
||||
}
|
||||
|
||||
//! vector out result printing function
|
||||
template<typename F>
|
||||
void vector_out (std::vector<value_t>& v, F&& f) {
|
||||
size_t idx{};
|
||||
f << "id,c3\n";
|
||||
for (auto& it : v) f << idx++ <<',' << it << '\n';
|
||||
f << '\n';
|
||||
}
|
||||
|
||||
/*
|
||||
* Public non-template api.
|
||||
* We use matrix alias template. So it has to be defined somewhere
|
||||
*/
|
||||
void init_ER_graph (matrix& A, double p);
|
||||
void print_ER_graph (matrix& A);
|
||||
void print_graph (matrix& A);
|
||||
void threads_info ();
|
||||
|
||||
#endif /* UTILS_H_ */
|
||||
|
||||
@@ -9,13 +9,39 @@
|
||||
#ifndef V3_H_
|
||||
#define V3_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <impl.hpp>
|
||||
|
||||
#if defined CILK
|
||||
#include <cilk/cilk.h>
|
||||
#include <cilk/cilk_api.h>
|
||||
#include <cilk/reducer_opadd.h>
|
||||
|
||||
#elif defined OMP
|
||||
#include <omp.h>
|
||||
|
||||
#elif defined THREADS
|
||||
#include <thread>
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
namespace v3 {
|
||||
|
||||
//! Select a data representation suited for V3.
|
||||
using matrix = SpMat<int, int>;
|
||||
|
||||
int triang_count (matrix& A);
|
||||
|
||||
using index_t = typename matrix::indexType; //!< syntactic sugar alias for index type
|
||||
using value_t = typename matrix::dataType; //!< syntactic sugar alias for value type
|
||||
|
||||
/*
|
||||
* Common api for all the versions
|
||||
*/
|
||||
int nworkers();
|
||||
std::vector<value_t> triang_v(matrix& A);
|
||||
value_t triang_count (std::vector<value_t>& c);
|
||||
|
||||
};
|
||||
#endif /* V3_H_ */
|
||||
|
||||
@@ -9,13 +9,40 @@
|
||||
#ifndef V4_H_
|
||||
#define V4_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <impl.hpp>
|
||||
|
||||
#if defined CILK
|
||||
#include <cilk/cilk.h>
|
||||
#include <cilk/cilk_api.h>
|
||||
#include <cilk/reducer_opadd.h>
|
||||
|
||||
#elif defined OMP
|
||||
#include <omp.h>
|
||||
|
||||
#elif defined THREADS
|
||||
#include <thread>
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
namespace v4 {
|
||||
|
||||
//! Select a data representation suited for V3.
|
||||
using matrix = SpMat<int, int>;
|
||||
|
||||
int triang_count (matrix& A);
|
||||
|
||||
using index_t = typename matrix::indexType; //!< syntactic sugar alias for index type
|
||||
using value_t = typename matrix::dataType; //!< syntactic sugar alias for value type
|
||||
|
||||
/*
|
||||
* Common api for all the versions
|
||||
*/
|
||||
int nworkers();
|
||||
std::vector<value_t> triang_v(matrix& A);
|
||||
value_t triang_count (std::vector<value_t>& c);
|
||||
|
||||
};
|
||||
#endif /* V4_H_ */
|
||||
|
||||
Reference in New Issue
Block a user