// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2014 Eric Martin // // 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_MATRIXMAPPER_H #define EIGEN_MATRIXMAPPER_H // To support both matrices and tensors, we need a way to abstractly access an // element of a matrix (where the matrix might be an implicitly flattened // tensor). This file abstracts the logic needed to access elements in a row // major or column major matrix. namespace Eigen { namespace internal { template class BlasVectorMapper { public: EIGEN_ALWAYS_INLINE BlasVectorMapper(Scalar *data) : m_data(data) {} EIGEN_ALWAYS_INLINE Scalar operator()(Index i) const { return m_data[i]; } template EIGEN_ALWAYS_INLINE Packet load(Index i) const { return ploadt(m_data + i); } template bool aligned(Index i) const { return (size_t(m_data+i)%sizeof(Packet))==0; } protected: Scalar* m_data; }; // We need a fast way to iterate down columns (if column major) that doesn't // involves performing a multiplication for each lookup. template class BlasLinearMapper { public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data) : m_data(data) {} EIGEN_ALWAYS_INLINE void prefetch(int i) const { internal::prefetch(&operator()(i)); } EIGEN_ALWAYS_INLINE Scalar& operator()(Index i) const { return m_data[i]; } EIGEN_ALWAYS_INLINE Packet loadPacket(Index i) const { return ploadt(m_data + i); } EIGEN_ALWAYS_INLINE HalfPacket loadHalfPacket(Index i) const { return ploadt(m_data + i); } EIGEN_ALWAYS_INLINE void storePacket(Index i, Packet p) const { pstoret(m_data + i, p); } protected: Scalar* m_data; }; // This mapper allows access into matrix by coordinates i and j. template class blas_data_mapper { public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; typedef BlasLinearMapper LinearMapper; typedef BlasVectorMapper VectorMapper; EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride) : m_data(data), m_stride(stride) {} EIGEN_ALWAYS_INLINE blas_data_mapper getSubMapper(Index i, Index j) const { return blas_data_mapper(&operator()(i, j), m_stride); } EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j) const { return LinearMapper(&operator()(i, j)); } EIGEN_ALWAYS_INLINE VectorMapper getVectorMapper(Index i, Index j) const { return VectorMapper(&operator()(i, j)); } EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j) const { return m_data[StorageOrder==RowMajor ? j + i*m_stride : i + j*m_stride]; } EIGEN_ALWAYS_INLINE Packet loadPacket(Index i, Index j) const { return ploadt(&operator()(i, j)); } EIGEN_ALWAYS_INLINE HalfPacket loadHalfPacket(Index i, Index j) const { return ploadt(&operator()(i, j)); } template EIGEN_ALWAYS_INLINE void scatterPacket(Index i, Index j, SubPacket p) const { pscatter(&operator()(i, j), p, m_stride); } template EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j) const { return pgather(&operator()(i, j), m_stride); } const Index stride() const { return m_stride; } Index firstAligned(Index size) const { if (size_t(m_data)%sizeof(Scalar)) { return -1; } return internal::first_aligned(m_data, size); } protected: Scalar* EIGEN_RESTRICT m_data; const Index m_stride; }; // This is just a convienent way to work with // blas_data_mapper template class const_blas_data_mapper : public blas_data_mapper { public: EIGEN_ALWAYS_INLINE const_blas_data_mapper(const Scalar *data, Index stride) : blas_data_mapper(data, stride) {} EIGEN_ALWAYS_INLINE const_blas_data_mapper getSubMapper(Index i, Index j) const { return const_blas_data_mapper(&(this->operator()(i, j)), this->m_stride); } }; } // end namespace internal } // end namespace eigen #endif //EIGEN_MATRIXMAPPER_H