blob: b787267ed99aec9f41118dd5846386c704326114 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @file Array_const.hpp
*
* @brief The MADlib Array class -- a thin wrapper around
* boost::const_multi_array_ref
*
*//* ----------------------------------------------------------------------- */
/**
* @brief A thin wrapper around boost::multi_array_ref, the Boost class for
* multi-dimensional arrays
*
* @internal Unfortunately, we have some duplicate code from Array.
* A clean solution would be to have Array_const a superclass of Array.
* However, \c const_multi_array_ref is not a virtual superclass of
* \c multi_array_ref, so this is not feasible.
*/
template <typename T, std::size_t NumDims>
class Array_const : public const_multi_array_ref<T, NumDims> {
public:
typedef boost::multi_array_types::index index;
typedef boost::multi_array_types::size_type size_type;
typedef boost::array<index, NumDims> extent_list;
typedef boost::detail::multi_array::extent_gen<NumDims> extent_gen;
inline Array_const(
const Array_const<T, NumDims> &inArray)
: const_multi_array_ref<T, NumDims>(
inArray),
mMemoryHandle(AbstractHandle::cloneIfNotGlobal(inArray.mMemoryHandle))
{ }
inline Array_const(
const Array<T, NumDims> &inArray)
: const_multi_array_ref<T, NumDims>(
inArray),
mMemoryHandle(inArray.memoryHandle())
{ }
inline Array_const(
const MemHandleSPtr inHandle,
const extent_gen &ranges)
: const_multi_array_ref<T, NumDims>(
static_cast<T*>(inHandle->ptr()),
ranges),
mMemoryHandle(inHandle)
{ }
inline Array_const(
AllocatorSPtr inAllocator,
const extent_gen &ranges)
: const_multi_array_ref<T, NumDims>(
NULL,
ranges),
mMemoryHandle(
inAllocator->allocateArray(getNumElements(ranges),
static_cast<T*>(NULL) /* pure type parameter */)) {
this->set_base_ptr(mMemoryHandle->ptr());
}
inline Array_const &rebind(
const MemHandleSPtr inHandle,
const extent_gen &ranges) {
mMemoryHandle = inHandle;
return internalRebind(ranges);
}
inline Array_const &rebind(
AllocatorSPtr inAllocator,
const extent_gen &ranges) {
mMemoryHandle = inAllocator->allocateArray(getNumElements(ranges),
static_cast<T*>(NULL) /* pure type parameter */);
return internalRebind(ranges);
}
inline MemHandleSPtr memoryHandle() const {
return mMemoryHandle;
}
protected:
static inline extent_list getExtentList(const extent_gen &ranges) {
// calculate the extents
extent_list extents;
std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
extents.begin(),
boost::mem_fun_ref(&multi_array_ref<T, NumDims>::extent_range::size));
return extents;
}
static inline size_type getNumElements(const extent_gen &ranges) {
extent_list extents = getExtentList(ranges);
return std::accumulate(extents.begin(), extents.end(),
size_type(1), std::multiplies<size_type>());
}
inline Array_const &internalRebind(const extent_gen &ranges) {
this->set_base_ptr(static_cast<T*>(mMemoryHandle->ptr()));
// See init_from_extent_gen()
// get the index_base values
std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
multi_array_ref<T, NumDims>::index_base_list_.begin(),
boost::mem_fun_ref(&multi_array_ref<T, NumDims>::extent_range::start));
// calculate the extents
init_multi_array_ref(getExtentList(ranges).begin());
return *this;
}
protected:
MemHandleSPtr mMemoryHandle;
};