#include <complex>
#include <array>
#include <vector>
#include <iomanip>
#include <iostream>
#include <string>
template <typename nt_t>
const std::vector<rsb_coo_idx_t> IA{0,n-1};
const std::vector<rsb_coo_idx_t> JA{0,n-1};
const std::vector<nt_t> VA{1,1};
const rsb_real_t mtxocc = mtx._get_storage_bytes();
const rsb_real_t opocc =
sizeof(nt_t)*nrhs*(mtx.cols()+mtx.rows());
const nt_t pone = 1;
std::cout << "# Matrix sized " << mtx.rows() << "x" << mtx.cols() << ", " << nnzA << " nnz built in " << dt << " s and occupies " << mtxocc << " bytes " << std::endl;
#if defined(RSB_LIBRSB_VER_DATE) && (RSB_LIBRSB_VER_DATE)
#endif
} )
{
std::vector<rsb_time_t> dta;
const long long nnz_ops = ( mtx._is_complex() ? 6 : 1 );
const auto flops_c = ( beta != pone ? nnz_ops*n*nrhs : 0LL );
for ( const auto nt : {1,rnt} )
{
const std::vector<nt_t> B(nrhs*mtx.cols(),1.);
std::vector<nt_t> C(nrhs*mtx.rows(),0.);
mtx.spmm(transA,alpha,nrhs,order,B.data(),ldB,beta,C.data(),ldC);
mtx.spmm(transA,alpha,nrhs,order,B.data(),ldB,beta,C.data(),ldC);
dta.push_back(dt);
}
std::cout << "# type=" << mtx.rsbtype() << " nt=1," << rnt << " n=" << n << " nrhs=" << nrhs << " order=" << oc << " alpha=" << alpha << " beta=" << beta << " dt=" << dta[0] << ".." << dta[1] << " spmm-scalability=" << dta[0]/dta[1] << " nnz/s=" << nnzA/dta[0] << ".." << nnzA/dta[1] << " flops=" << flops_c/dta[0] << ".." << flops_c/dta[1] << " occ.=" << opocc << " " << std::endl;
}
}
auto main(
const int argc,
char * argv[]) ->
int {
const rsb_coo_idx_t n { argc > 1 ? std::stoi(argv[1]) : 1000000};
const int alpha { argc > 3 ? std::stoi(argv[3]) : 1};
const int beta { argc > 4 ? std::stoi(argv[4]) : 1};
#ifdef RSB_NUMERICAL_TYPE_DOUBLE_COMPLEX
bench<std::complex<double>>(n,nrhs,alpha,beta);
#endif
#ifdef RSB_NUMERICAL_TYPE_DOUBLE
bench<double>(n,nrhs,alpha,beta);
#endif
#ifdef RSB_NUMERICAL_TYPE_FLOAT_COMPLEX
bench<std::complex<float>>(n,nrhs,alpha,beta);
#endif
#ifdef RSB_NUMERICAL_TYPE_FLOAT
bench<float>(n,nrhs,alpha,beta);
#endif
}