blob: 4bfe7c50390c231ebe5c6f7150d91f5813bd2117 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @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 EigenType, class Handle, int MapOptions = Eigen::Unaligned>
class HandleMap : public Eigen::Map<EigenType, MapOptions> {
public:
typedef Eigen::Map<EigenType, MapOptions> 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<Scalar*>(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 <class Derived>
HandleMap(const Eigen::MapBase<Derived>& inMappedData,
typename boost::enable_if_c<Derived::IsVectorAtCompileTime>::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 <class Derived>
HandleMap(const Eigen::MapBase<Derived>& inMappedData,
typename boost::enable_if_c<!Derived::IsVectorAtCompileTime>::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<Scalar*>(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<Scalar*>(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<EigenType>::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)