////////////////////////////////////////////////////////////////////////////////////// // This file is distributed under the University of Illinois/NCSA Open Source License. // See LICENSE file in top directory for details. // // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. // // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory // // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign ////////////////////////////////////////////////////////////////////////////////////// #ifndef QMCPLUSPLUS_MATRIXOPERATORS_H #define QMCPLUSPLUS_MATRIXOPERATORS_H #include "OhmmsPETE/OhmmsMatrix.h" #include "OhmmsPETE/OhmmsVector.h" #include "OhmmsPETE/TinyVector.h" #include "OhmmsPETE/Tensor.h" #include "CPU/BLAS.hpp" #include "CPU/SIMD/inner_product.hpp" namespace qmcplusplus { template inline T TESTDOT(const T* restrict f, const T* restrict l, const T* restrict b) { T s = 0; while (f != l) s += (*f++) * (*b++); return s; } namespace MatrixOperators { /** static function to perform C=AB for real matrices * * Call dgemm/zgemm/sgemm/cgemm via BLAS::gemm */ template inline void product(const Matrix& A, const Matrix& B, Matrix& C) { const char transa = 'N'; const char transb = 'N'; const T one(1.0); const T zero(0.0); BLAS::gemm(transa, transb, B.cols(), A.rows(), B.rows(), one, B.data(), B.cols(), A.data(), A.cols(), zero, C.data(), C.cols()); } template inline void product_ABt(const Matrix& A, const Matrix& B, Matrix& C) { const char transa = 't'; const char transb = 'n'; const T one(1.0); const T zero(0.0); BLAS::gemm(transa, transb, B.rows(), A.rows(), B.cols(), one, B.data(), B.cols(), A.data(), A.cols(), zero, C.data(), C.cols()); } template inline void product_AtB(const Matrix& A, const Matrix& B, Matrix& C) { const char transa = 'n'; const char transb = 't'; const T one(1.0); const T zero(0.0); BLAS::gemm(transa, transb, B.cols(), A.cols(), B.rows(), one, B.data(), B.cols(), A.data(), A.cols(), zero, C.data(), C.cols()); } inline void half_outerProduct(const Matrix& M, const Vector& B, int iat, Matrix& C) { for (int i = 0; i < C.rows(); i++) for (int j = 0; j < C.cols(); j++) C(iat, i) += M(i, j) * B[j]; //for (int i=0; i& M, const Vector& B, int iat, Matrix& C) { for (int i = 0; i < C.rows(); i++) for (int j = 0; j < C.cols(); j++) C(i, iat) += M(i, j) * B[j]; //for (int i=0; i& A, const Vector& B) { double tot = 0.0; for (int i = 0; i < A.size(); i++) tot += A[i] * B[i]; return tot; //return simd::dot(A.data(),B.data(),A.size()); } template inline void transpose(Matrix& A) { for (int i = 0; i < A.extent(0); i++) for (int j = 0; j < i; j++) std::swap(A(i, j), A(j, i)); } template inline void transpose(const Matrix& A, Matrix& B) { simd::transpose(A.data(), A.rows(), A.cols(), B.data(), B.rows(), B.cols()); } /// C = A*diag(B) template inline void diag_product(const Matrix& A, const Vector& B, Matrix& C) { for (int i = 0; i < C.rows(); ++i) for (int j = 0; j < C.cols(); ++j) C(i, j) = A(i, j) * B[j]; //works? //const int ccols = C.cols(); //const int ijmax = C.size(); //for (int ij=0; ij inline void diag_product(const Vector& A, const Matrix& B, Matrix& C) { for (int i = 0; i < C.rows(); ++i) for (int j = 0; j < C.cols(); ++j) C(i, j) = A[i] * B(i, j); //const int crows = C.rows(); //const int ccols = C.cols(); //for (int i=0,ijb=0; i& A, const Matrix>& B, Matrix& C) { std::cerr << " Undefined C=AB with real A and complex B " << std::endl; } /** static function to perform y=Ax for generic matrix and vector */ template inline void product(const Matrix& A, const Vector& x, T* restrict yptr) { const char transa = 'T'; const T one = 1.0; const T zero = 0.0; BLAS::gemv(transa, A.cols(), A.rows(), one, A.data(), A.cols(), x.data(), 1, zero, yptr, 1); } /** static function to perform y = A^t x for generic matrix and vector */ template inline void product_Atx(const Matrix& A, const Vector& x, T* restrict yptr) { const char transa = 'N'; const T one = 1.0; const T zero = 0.0; BLAS::gemv(transa, A.cols(), A.rows(), one, A.data(), A.cols(), x.data(), 1, zero, yptr, 1); } /** static function to perform y=Ax for generic matrix and vector */ template inline void product(const Matrix& A, const T* restrict xptr, T* restrict yptr) { const char transa = 'T'; const T one = 1.0; const T zero = 0.0; BLAS::gemv(transa, A.cols(), A.rows(), one, A.data(), A.cols(), xptr, 1, zero, yptr, 1); } /** static function to perform y = A^t x for generic matrix and vector */ template inline void product_Atx(const Matrix& A, const T* restrict xptr, T* restrict yptr) { const char transa = 'N'; const T one = 1.0; const T zero = 0.0; BLAS::gemv(transa, A.cols(), A.rows(), one, A.data(), A.cols(), xptr, 1, zero, yptr, 1); } /** static function to perform y=Ax for generic matrix and vector */ template inline void product(const Matrix& A, const TinyVector* xvPtr, TinyVector* restrict yptr) { const T one = 1.0; const T zero = 0.0; const char transa = 'N'; const char transb = 'N'; BLAS::gemm(transa, transb, D, A.rows(), A.cols(), one, xvPtr->begin(), D, A.data(), A.cols(), zero, yptr->begin(), D); } template inline void product(const Matrix& A, const Tensor* xvPtr, Tensor* restrict yptr) { const T one = 1.0; const T zero = 0.0; const char transa = 'N'; const char transb = 'N'; BLAS::gemm(transa, transb, D * D, A.rows(), A.cols(), one, xvPtr->begin(), D * D, A.data(), A.cols(), zero, yptr->begin(), D * D); } /** static function to perform y=Ax for generic matrix and vector */ template inline void product(const Matrix& A, const Vector>& x, TinyVector* restrict yptr) { const double one = 1.0; const double zero = 0.0; const char transa = 'N'; const char transb = 'N'; dgemm(transa, transb, D, A.rows(), x.size(), one, x.data()->begin(), D, A.data(), A.cols(), zero, yptr->begin(), D); } /** static function to perform y=Ax for generic matrix and vector */ template inline void product(const Matrix>& A, const Vector, D>>& x, TinyVector, D>* restrict yptr) { const char transa = 'N'; const char transb = 'N'; const std::complex zone(1.0, 0.0); const std::complex zero(0.0, 0.0); zgemm(transa, transb, D, A.rows(), x.size(), zone, x.data()->begin(), D, A.data(), A.cols(), zero, yptr->begin(), D); } /** static function to perform y=Ax for generic matrix and vector */ inline void product(const Matrix>& A, const Vector>& x, std::complex* restrict yptr) { const char transa = 'T'; const std::complex zone(1.0, 0.0); const std::complex zero(0.0, 0.0); zgemv(transa, A.cols(), A.rows(), zone, A.data(), A.cols(), x.data(), 1, zero, yptr, 1); } /** static function to perform y=Ax for generic matrix and vector */ inline void product(const Matrix>& A, const Vector& x, std::complex* restrict yptr) { const int n = A.rows(); const int m = A.cols(); const std::complex* restrict aptr = A.data(); for (int i = 0, ij = 0; i < n; ++i) { std::complex t = 0.0; for (int j = 0; j < m; ++j, ++ij) t += aptr[ij] * x[j]; yptr[i] = t; } } inline void product(const Matrix>& A, const std::complex* restrict x, std::complex* restrict yptr) { const char transa = 'T'; const std::complex zone(1.0, 0.0); const std::complex zero(0.0, 0.0); zgemv(transa, A.cols(), A.rows(), zone, A.data(), A.cols(), x, 1, zero, yptr, 1); } /** static function to perform y=Ax for generic matrix and vector */ inline void product(const Matrix& A, const Vector>& x, double* restrict yptr) { std::cerr << " Undefined C=AB with real A and complex x " << std::endl; } template inline void product(const Matrix& A, const Matrix& B, Matrix& C, std::vector& offset) { int nr = C.rows(); int nb = offset.size() - 1; for (int i = 0; i < nr; i++) { for (int b = 0; b < nb; b++) { int firstK = offset[b]; int lastK = offset[b + 1]; const T* restrict firstY = A[i] + firstK; const T* restrict lastY = A[i] + lastK; for (int k = firstK; k < lastK; k++) { C(i, k) = TESTDOT(firstY, lastY, B[k] + firstK); } } } } // template // inline statis void product(const Matrix& A, const T* restrict x, T* restrict y) // { // GEMV::apply(A.data(),x,y,A.rows(),A.cols()); // } } // namespace MatrixOperators /** API to handle gemv */ namespace simd { template inline void gemv(const Matrix& a, const T* restrict v, T* restrict b) { MatrixOperators::product(a, v, b); } template inline void gemv(const Matrix& a, const TinyVector* restrict v, TinyVector* restrict b) { MatrixOperators::product(a, v, b); } template inline void gemv(const Matrix& a, const Tensor* restrict v, Tensor* restrict b) { MatrixOperators::product(a, v, b); } } // namespace simd } // namespace qmcplusplus #endif