cdm/src/main/java/ucar/ma2/Index.java
Index section(List<Range> ranges) throws InvalidRangeException {

    // check ranges are valid
    if (ranges.size() != rank)
      throw new InvalidRangeException("Bad ranges [] length");
    for (int ii = 0; ii < rank; ii++) {
      Range r = ranges.get(ii);
      if (r == null)
        continue;
      if (r == Range.VLEN)
        continue;
      if ((r.first() < 0) || (r.first() >= shape[ii]))
        throw new InvalidRangeException("Bad range starting value at index " + ii + " == " + r.first());
      if ((r.last() < 0) || (r.last() >= shape[ii]))
        throw new InvalidRangeException("Bad range ending value at index " + ii + " == " + r.last());
    }

    int reducedRank = rank;
    for (Range r : ranges) {
      if ((r != null) && (r.length() == 1))
        reducedRank--;
    }
    Index newindex = Index.factory(reducedRank);
    newindex.offset = offset;

    // calc shape, size, and index transformations
    // calc strides into original (backing) store
    int newDim = 0;
    for (int ii = 0; ii < rank; ii++) {
      Range r = ranges.get(ii);
      if (r == null) {          // null range means use the whole original dimension
        newindex.shape[newDim] = shape[ii];
        newindex.stride[newDim] = stride[ii];
        //if (name != null) newindex.name[newDim] = name[ii];
        newDim++;
      } else if (r.length() != 1) {
        newindex.shape[newDim] = r.length();
        newindex.stride[newDim] = stride[ii] * r.stride();
        newindex.offset += stride[ii] * r.first();
        //if (name != null) newindex.name[newDim] = name[ii];
        newDim++;
      } else {
        newindex.offset += stride[ii] * r.first();   // constant due to rank reduction
      }
    }
    newindex.size = computeSize(newindex.shape);
    newindex.fastIterator = fastIterator && (newindex.size == size); // if equal, then its not a real subset, so can still use fastIterator
    newindex.precalc(); // any subclass-specific optimizations
    return newindex;
  }
Index section(List<Range> ranges) throws InvalidRangeException {

    // check ranges are valid
    if (ranges.size() != rank)
      throw new InvalidRangeException("Bad ranges [] length");
    for (int ii = 0; ii < rank; ii++) {
      Range r = ranges.get(ii);
      if (r == null)
        continue;
      if (r == Range.VLEN)
        continue;
      if ((r.first() < 0) || (r.first() >= shape[ii]))
        throw new InvalidRangeException("Bad range starting value at index " + ii + " == " + r.first());
      if ((r.last() < 0) || (r.last() >= shape[ii]))
        throw new InvalidRangeException("Bad range ending value at index " + ii + " == " + r.last());
    }

    int reducedRank = rank;
    for (Range r : ranges) {
      if ((r != null) && (r.length() == 1))
        reducedRank--;
    }
    Index newindex = Index.factory(reducedRank);
    newindex.offset = offset;

    // calc shape, size, and index transformations
    // calc strides into original (backing) store
    int newDim = 0;
    for (int ii = 0; ii < rank; ii++) {
      Range r = ranges.get(ii);
      if (r == null) {          // null range means use the whole original dimension
        newindex.shape[newDim] = shape[ii];
        newindex.stride[newDim] = stride[ii];
        //if (name != null) newindex.name[newDim] = name[ii];
        newDim++;
      } else if (r.length() != 1) {
        newindex.shape[newDim] = r.length();
        newindex.stride[newDim] = stride[ii] * r.stride();
        newindex.offset += stride[ii] * r.first();
        //if (name != null) newindex.name[newDim] = name[ii];
        newDim++;
      } else {
        newindex.offset += stride[ii] * r.first();   // constant due to rank reduction
      }
    }
    newindex.size = computeSize(newindex.shape);
    newindex.fastIterator = fastIterator && (newindex.size == size); // if equal, then its not a real subset, so can still use fastIterator
    newindex.precalc(); // any subclass-specific optimizations
    return newindex;
  }
create a new Index based on a subsection of this one, with rank reduction if
dimension length == 1.

@param ranges array of Ranges that specify the array subset.
Must be same rank as original Array.
A particular Range: 1) may be a subset; 2) may be null, meaning use entire Range.
@return new Index, with same or smaller rank as original.
@throws InvalidRangeException if ranges dont match current shape