199 lines
5.9 KiB
C++

/*!
* \file utils.h
* \brief Utilities to handle matrix files, chrono, etc...
*
* \author
* Christos Choutouridis AEM:8997
* <cchoutou@ece.auth.gr>
*/
#ifndef UTILS_H_
#define UTILS_H_
#include <string>
#include <sstream>
#include <iostream>
#include <chrono>
#include <random>
#include <impl.hpp>
#include <config.h>
template <typename T>
struct buffer_t {
buffer_t(size_t s) { p = new T[s]; }
~buffer_t() { delete[] p; }
buffer_t() = default;
buffer_t(buffer_t&&) = default;
buffer_t& operator=(buffer_t&&) = default;
buffer_t(const buffer_t&) = delete;
buffer_t& operator=(const buffer_t&) = delete;
T* allocate(size_t s) { return p = new T[s]; }
T* operator() () { return p; }
T& operator[] (size_t i){ return p[i]; }
private:
T* p{nullptr};
};
struct Mtx {
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!
for (I l = 0; l < n+1; l++) col[l] = 0;
// ----- find the correct column sizes
for (I l = 0; l < nnz; l++)
col[col_coo[l] - isOneBased]++;
// ----- cumulative sum
for (I i = 0, cumsum = 0; i < n; i++) {
I temp = col[i];
col[i] = cumsum;
cumsum += temp;
}
col[n] = nnz;
// ----- copy the row indices to the correct place
for (I l = 0; l < nnz; l++) {
I col_l;
col_l = col_coo[l] - isOneBased;
I dst = col[col_l];
row[dst] = row_coo[l] - isOneBased;
col[col_l]++;
}
// ----- revert the column pointers
for (I i = 0, last = 0; i < n; i++) {
I temp = col[i];
col[i] = last;
last = temp;
}
}
template<typename I>
static bool is_triangular (std::ifstream& file) {
std::string line, token;
enum state_en {HEADER, SIZE, DATA} state = HEADER;
enum LU_t {Z, LOWER, UPPER} LU = Z;
while (std::getline (file, line, '\n')) {
std::stringstream ss(line);
switch (state) {
case HEADER:
ss >> token;
if (token != "%%MatrixMarket") return false;
else state = SIZE;
break;
case SIZE:
if (line[0] == '%') continue;
else state = DATA;
break;
case DATA:
if (line[0] == '%') continue;
I i, j;
ss >> i >> j;
switch (LU) {
case Z: LU = (i<j) ? UPPER: LOWER; break;
case LOWER: if (i<=j) return false; break;
case UPPER: if (j<=i) return false; break;
}
break;
}
}
file.clear(); // rewind
file.seekg(0);
return true;
}
template<typename DataT, typename IndexT, MatrixType MatrixT>
static bool load (SpMat<DataT, IndexT, MatrixT>& M, std::ifstream& file) {
std::string line, token;
enum state_en {HEADER, SIZE, DATA} state = HEADER;
enum LU_t {Z, LOWER, UPPER} LU = Z;
IndexT n1, n2, nnz;
buffer_t<IndexT> col{}, row{}, coo_col{}, coo_row{};
IndexT cnt{};
while (std::getline (file, line, '\n')) {
std::stringstream ss(line);
switch (state) {
case HEADER:
ss >> token;
if (token != "%%MatrixMarket") return false;
else state = SIZE;
break;
case SIZE:
if (line[0] == '%') continue;
else {
ss >> n1 >> n2 >> nnz;
if (session.makeSymmetric)
nnz *= 2;
col.allocate(nnz);
row.allocate(nnz);
coo_col.allocate(nnz);
coo_row.allocate(nnz);
state = DATA;
}
break;
case DATA:
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;
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;
}
};
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;
Tpoint start () noexcept { return start_ = std::chrono::steady_clock::now(); }
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";
}
private:
Tpoint start_;
Tpoint stop_;
};
void init_ER_graph (matrix& A, double p);
void print_ER_graph (matrix& A);
#endif /* UTILS_H_ */