/* ----------------------------------------------------------------------- *//** * * @file HandleMap_proto.hpp * *//* ----------------------------------------------------------------------- */ #ifndef MADLIB_DBAL_EIGEN_HANDLEMAP_PROTO_HPP #define MADLIB_DBAL_EIGEN_HANDLEMAP_PROTO_HPP namespace madlib { namespace dbal { namespace eigen_integration { /** * @brief Wrapper class for linear-algebra types based on Eigen */ template class HandleMap : public Eigen::Map { public: typedef Eigen::Map Base; typedef typename Base::Scalar Scalar; typedef typename Base::Index Index; using Base::operator=; /** * @brief Default constructor * * Using the HandleMap before a rebind() is undefined and will likely * crash the application. */ inline HandleMap() : Base(NULL, 1, 1), mMemoryHandle(NULL) { } /** * @brief Initialize HandleMap backed by the given handle without dimension * information * * We do not assume that Handle has member functions other than ptr(), * e.g. TransparentHandle does not have size(). So we set dummy dimension * information here. */ inline HandleMap(const Handle &inHandle) : Base(const_cast(inHandle.ptr()), 1, 1), mMemoryHandle(inHandle) { } /* * FIXME These two functions do not work when Handle cannot be constructed * by a single argument of type Scalar*, e.g. they work for * Handle=TransparentHanle (MappedColumnVector, etc.), * but not Handle=ArrayHandle (NativeMatrix, etc.). */ /** * @brief Initialize HandleMap using Eigen mapped expressions * * For example, this allows construction of MappedColumnVector from * MappedMatrix::col(int) or NativeColumnVector, etc. */ template HandleMap(const Eigen::MapBase& inMappedData, typename boost::enable_if_c::type* = 0) : Base(inMappedData.data(), inMappedData.size()), mMemoryHandle(inMappedData.data()) { madlib_assert(inMappedData.innerStride() == 1, std::runtime_error("HandleMap does not support non-contiguous " "memory blocks.")); } template HandleMap(const Eigen::MapBase& inMappedData, typename boost::enable_if_c::type* = 0) : Base(inMappedData.data(), inMappedData.rows(), inMappedData.cols()), mMemoryHandle(inMappedData.data()) { madlib_assert(inMappedData.innerStride() == 1 && ((Derived::IsRowMajor && inMappedData.outerStride() == inMappedData.cols()) || (!Derived::IsRowMajor && inMappedData.outerStride() == inMappedData.rows())), std::runtime_error("HandleMap does not support non-contiguous " "memory blocks.")); } /** * @brief Initialize HandleMap backed by the given handle * * This ignores any size information Handle may have. This * constructor can be used with any Handle. */ HandleMap(const Handle &inHandle, Index inNumElem) : Base(const_cast(inHandle.ptr()), inNumElem), mMemoryHandle(inHandle) { } /** * @brief Initialize HandleMap backed by the given handle * * This ignores any size information Handle may have. This * constructor can be used with any Handle. * * @internal * We need to do a const cast here: There is no alternative to * initializing from "const Handle&", but the base class constructor * needs a non-const value. We therefore make sure that a * non-mutable handle can only be assigned if EigenType is a * constant type. See the static assert below. */ HandleMap(const Handle &inHandle, Index inNumRows, Index inNumCols) : Base(const_cast(inHandle.ptr()), inNumRows, inNumCols), mMemoryHandle(inHandle) { } HandleMap& operator=(const HandleMap& other); HandleMap& rebind(const Handle &inHandle); HandleMap& rebind(const Handle &inHandle, Index inSize); HandleMap& rebind(const Handle &inHandle, Index inRows, Index inCols); HandleMap& rebind(Index inSize); HandleMap& rebind(Index inRows, Index inCols); const Handle &memoryHandle() const; bool isNull() const { return mMemoryHandle.isNull(); } protected: Handle mMemoryHandle; private: BOOST_STATIC_ASSERT_MSG( Handle::isMutable || boost::is_const::value, "non-const matrix cannot be backed by immutable handle"); }; } // namespace eigen_integration } // namespace dbal } // namespace madlib #endif // defined(MADLIB_DBAL_EIGEN_HANDLEMAP_PROTO_HPP)