/* ----------------------------------------------------------------------- *//**
 *
 * @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;
};
