IndexSetPointSequence::IndexSetPointSequence(LocalArray &points) :
IndexSet(points.getElementCount(1), points.getElementCount(0)) {
    _numberOfRegions = 0;
    uint64_t indexLength = _numberOfIndices * _numberOfDimensions;
    _indexList = new uint64_t[indexLength];
    if (_indexList == NULL)
        throw ENotEnoughMemory();
    memcpy(_indexList, points.getData(), indexLength * sizeof (uint64_t));
    this->initConstantIterators();
    if (_begin == NULL || _end == NULL || _curr == NULL)
        throw ENotEnoughMemory();
}
IndexSetRegionSequence::IndexSetRegionSequence(LocalArray &lower,
        LocalArray &upper) :
IndexSet(lower.getElementCount(1), computeNumberOfIndices(lower, upper)) {
    this->initConstantIterators();
    if (_begin == NULL || _end == NULL || _curr == NULL)
        throw ENotEnoughMemory();
}
uint64_t IndexSetRegionSequence::computeNumberOfIndices(LocalArray &lower,
        LocalArray &upper) {
    unsigned numberOfDimensions = lower.getElementCount(1);
    _numberOfRegions = lower.getElementCount(0);
    if (numberOfDimensions == 0 || _numberOfRegions == 0)
        throw EInvalidArgument();
    if (upper.getElementCount(1) != numberOfDimensions
            || upper.getElementCount(0) != _numberOfRegions)
        throw EInvalidArgument();
    _lowerIndexList = new uint64_t[numberOfDimensions * _numberOfRegions];
    _upperIndexList = new uint64_t[numberOfDimensions * _numberOfRegions];
    if (_lowerIndexList == NULL || _upperIndexList == NULL)
        throw ENotEnoughMemory();
    if (lower.getElementType() == ArrayShape::UINT64)
        memcpy(_lowerIndexList, lower.getData(),
                sizeof (uint64_t) * numberOfDimensions * _numberOfRegions);
    else {
        LocalArray properTyped(ArrayShape::UINT64, lower);
        memcpy(_lowerIndexList, properTyped.getData(),
                sizeof (uint64_t) * numberOfDimensions * _numberOfRegions);
    }
    if (upper.getElementType() == ArrayShape::UINT64)
        memcpy(_upperIndexList, upper.getData(),
                sizeof (uint64_t) * numberOfDimensions * _numberOfRegions);
    else {
        LocalArray properTyped(ArrayShape::UINT64, upper);
        memcpy(_upperIndexList, properTyped.getData(),
                sizeof (uint64_t) * numberOfDimensions * _numberOfRegions);
    }

    uint64_t result = 0;
    uint64_t k = 0;
    for (uint64_t iRegion = 0; iRegion < _numberOfRegions; iRegion++) {
        uint64_t currentRegionSize = 1;
        for (unsigned iDim = 0; iDim < numberOfDimensions; iDim++) {
            uint64_t currentLower = _lowerIndexList[k];
            uint64_t currentUpper = _upperIndexList[k];
            k++;
            if (currentUpper < currentLower)
                throw EInvalidRegionDescriptor(iDim, iRegion, 
                        currentLower, currentUpper, 1);
            currentRegionSize *= currentUpper - currentLower + 1;
        }
        result += currentRegionSize;
    }
    return result;
}