/**************************************************************** **** **** This file belongs with the course **** Introduction to Scientific Programming in C++/Fortran2003 **** copyright 2016-9 Victor Eijkhout eijkhout@tacc.utexas.edu **** **** lapack.cxx : dense matrices ;with variant **** WRONG unfinished **** ****************************************************************/ #include using std::cin; using std::cout; #include using std::numeric_limits; #include using std::vector; #include using namespace std::chrono; #include using std::variant; using std::get; using std::get_if; #include "gsl/gsl-lite.hpp" using gsl::span; #ifdef CBLAS #include #else // dgemm: TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC extern "C" { void dgemm_(char*,char*,int*,int*,int*, double*,double*,int*, double*,int*, double*,double*,int*); } #endif class Matrix { private: int m,n,lda; variant< vector, span > data; public: Matrix(int m,int n,double v=0) : m(m),n(n),lda(m), data( vector(m*n,v) ) { cout << "alloc" << '\n'; }; Matrix(int m,int n,int lda,double *data) : m(m),n(n),lda(lda), data( span(data,lda*n) ) { cout << "span" << '\n'; }; double& at(int i,int j) { // zero-based if ( auto matrix_data = get_if>( &data ) ; matrix_data ) return ( matrix_data )->at(j*lda+i); else return ( get_if>( &data ) )->at(j*lda+i); }; #define AT(i,j,m,n,lda) (i)+(j)*(lda) double at(int i,int j) const { // zero-based if ( auto matrix_data = get_if>( &data ) ; matrix_data ) return ( matrix_data )->at(j*lda+i); else return ( get_if>( &data ) )->at(j*lda+i); }; auto get_double_data() { double *adata; if ( auto matrix_data = get_if>( &data ) ; matrix_data ) adata = ( matrix_data )->data(); else adata = ( get_if>( &data ) )->data(); return adata; }; Matrix Left(int j) { auto adata = get_double_data(); return Matrix(m,j,lda,adata); }; Matrix Right(int j) { auto adata = get_double_data(); return Matrix(m,n-j,lda,adata+j*lda); }; Matrix Top(int i) { auto adata = get_double_data(); return Matrix(i,n,lda,adata); }; Matrix Bot(int i) { auto adata = get_double_data(); return Matrix(m-i,n,lda,adata+i); }; Matrix operator+( Matrix other ) const { if (other.m!=m or other.n!=n) { cout << "Operator+: incompatible dimensions" << '\n'; throw(1); } Matrix out(m,n); for (int j=0; j::max(); for (int j=0; j::min(); for (int j=0; jmx) mx = v; } return mx; }; void MatMult( Matrix& other,Matrix& out ) { if (n!=other.m || m!=out.m || other.n!=out.n) { cout << "MatMult: incompatible dimensions" << '\n'; throw(1); } double alpha = 1., beta = 0.; auto adata = get_double_data(); auto bdata = other.get_double_data(); auto cdata = out.get_double_data(); #ifdef CBLAS cblas_dgemm ( CblasColMajor, CblasNoTrans, CblasNoTrans, m,other.n,n, alpha,adata,lda, bdata,other.lda, beta,cdata,out.lda); #else for (int i=0; i(end_time - start_time).count(); cout << "product took: " << duration << " milliseconds" << '\n'; cout << "checking:" << '\n'; auto min = C.min(), max = C.max(); cout << "C range: " << min << "--" << max << '\n'; } { auto start_time = high_resolution_clock::now(); A.RecursiveMatMult(B,C); auto end_time = high_resolution_clock::now(); auto duration = duration_cast(end_time - start_time).count(); cout << "recursive product took: " << duration << " milliseconds" << '\n'; cout << "checking:" << '\n'; auto min = C.min(), max = C.max(); cout << "C range: " << min << "--" << max << '\n'; } } return 0; }