// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2006-2008 Benoit Jacob <[email protected]> // Copyright (C) 2008-2011 Gael Guennebaud <[email protected]> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERAL_PRODUCT_H #define EIGEN_GENERAL_PRODUCT_H // IWYU pragma: private #include "./InternalHeaderCheck.h" namespace Eigen { enum { … }; // Define the threshold value to fallback from the generic matrix-matrix product // implementation (heavy) to the lightweight coeff-based product one. // See generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct> // in products/GeneralMatrixMatrix.h for more details. // TODO This threshold should also be used in the compile-time selector below. #ifndef EIGEN_GEMM_TO_COEFFBASED_THRESHOLD // This default value has been obtained on a Haswell architecture. #define EIGEN_GEMM_TO_COEFFBASED_THRESHOLD … #endif namespace internal { template <int Rows, int Cols, int Depth> struct product_type_selector; template <int Size, int MaxSize> struct product_size_category { … }; template <typename Lhs, typename Rhs> struct product_type { … }; /* The following allows to select the kind of product at compile time * based on the three dimensions of the product. * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */ // FIXME I'm not sure the current mapping is the ideal one. product_type_selector<M, N, 1>; product_type_selector<M, 1, 1>; product_type_selector<1, N, 1>; product_type_selector<1, 1, Depth>; template <> struct product_type_selector<1, 1, 1> { … }; template <> struct product_type_selector<Small, 1, Small> { … }; template <> struct product_type_selector<1, Small, Small> { … }; template <> struct product_type_selector<Small, Small, Small> { … }; template <> struct product_type_selector<Small, Small, 1> { … }; template <> struct product_type_selector<Small, Large, 1> { … }; template <> struct product_type_selector<Large, Small, 1> { … }; template <> struct product_type_selector<1, Large, Small> { … }; template <> struct product_type_selector<1, Large, Large> { … }; template <> struct product_type_selector<1, Small, Large> { … }; template <> struct product_type_selector<Large, 1, Small> { … }; template <> struct product_type_selector<Large, 1, Large> { … }; template <> struct product_type_selector<Small, 1, Large> { … }; template <> struct product_type_selector<Small, Small, Large> { … }; template <> struct product_type_selector<Large, Small, Large> { … }; template <> struct product_type_selector<Small, Large, Large> { … }; template <> struct product_type_selector<Large, Large, Large> { … }; template <> struct product_type_selector<Large, Small, Small> { … }; template <> struct product_type_selector<Small, Large, Small> { … }; template <> struct product_type_selector<Large, Large, Small> { … }; } // end namespace internal /*********************************************************************** * Implementation of Inner Vector Vector Product ***********************************************************************/ // FIXME : maybe the "inner product" could return a Scalar // instead of a 1x1 matrix ?? // Pro: more natural for the user // Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix // product ends up to a row-vector times col-vector product... To tackle this use // case, we could have a specialization for Block<MatrixType,1,1> with: operator=(Scalar x); /*********************************************************************** * Implementation of Outer Vector Vector Product ***********************************************************************/ /*********************************************************************** * Implementation of General Matrix Vector Product ***********************************************************************/ /* According to the shape/flags of the matrix we have to distinghish 3 different cases: * 1 - the matrix is col-major, BLAS compatible and M is large => call fast BLAS-like colmajor routine * 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine * 3 - all other cases are handled using a simple loop along the outer-storage direction. * Therefore we need a lower level meta selector. * Furthermore, if the matrix is the rhs, then the product has to be transposed. */ namespace internal { template <int Side, int StorageOrder, bool BlasCompatible> struct gemv_dense_selector; } // end namespace internal namespace internal { template <typename Scalar, int Size, int MaxSize, bool Cond> struct gemv_static_vector_if; gemv_static_vector_if<Scalar, Size, MaxSize, false>; gemv_static_vector_if<Scalar, Size, Dynamic, true>; gemv_static_vector_if<Scalar, Size, MaxSize, true>; // The vector is on the left => transposition gemv_dense_selector<OnTheLeft, StorageOrder, BlasCompatible>; template <> struct gemv_dense_selector<OnTheRight, ColMajor, true> { … }; template <> struct gemv_dense_selector<OnTheRight, RowMajor, true> { … }; template <> struct gemv_dense_selector<OnTheRight, ColMajor, false> { … }; template <> struct gemv_dense_selector<OnTheRight, RowMajor, false> { … }; } // end namespace internal /*************************************************************************** * Implementation of matrix base methods ***************************************************************************/ /** \returns the matrix product of \c *this and \a other. * * \note If instead of the matrix product you want the coefficient-wise product, see Cwise::operator*(). * * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() */ template <typename Derived> template <typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Product<Derived, OtherDerived> MatrixBase<Derived>::operator*( const MatrixBase<OtherDerived>& other) const { … } /** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. * * The returned product will behave like any other expressions: the coefficients of the product will be * computed once at a time as requested. This might be useful in some extremely rare cases when only * a small and no coherent fraction of the result's coefficients have to be computed. * * \warning This version of the matrix product can be much much slower. So use it only if you know * what you are doing and that you measured a true speed improvement. * * \sa operator*(const MatrixBase&) */ template <typename Derived> template <typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Product<Derived, OtherDerived, LazyProduct> MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived>& other) const { … } } // end namespace Eigen #endif // EIGEN_PRODUCT_H