All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.ma2.Section Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */

package ucar.ma2;

import java.util.*;
import java.util.stream.Collectors;

/**
 * A section of multidimensional array indices.
 * Represented as List.
 * Immutable if makeImmutable() was called.
 *
 * @author caron
 */
public class Section {

  /**
   * Return a Section guaranteed to be non null, with no null Ranges, and within the bounds set by shape.
   * A section with no nulls is called "filled".
   * If s is already filled, return it, otherwise return a new Section, filled from the shape.
   *
   * @param s     the original Section, may be null or not filled
   * @param shape use this as default shape if any of the ranges are null.
   * @return a filled Section
   * @throws InvalidRangeException if shape and s and shape rank dont match, or if s has invalid range compared to shape
   */
  static public Section fill(Section s, int[] shape) throws InvalidRangeException {
    // want all
    if (s == null)
      return new Section(shape);

    String errs = s.checkInRange(shape);
//    if (errs != null)
//      throw new InvalidRangeException(errs);

    // if s is already filled, use it
    boolean ok = true;
    for (int i = 0; i < shape.length; i++)
      ok &= (s.getRange(i) != null);
    if (ok) return s;

    // fill in any nulls
    return new Section(s.getRanges(), shape);
  }

  static public Section make(List rangeIter) {
    List ranges = new ArrayList<>();
    for (RangeIterator iter : rangeIter) {
      if (iter instanceof Range)
        ranges.add((Range) iter);
      else
        throw new IllegalArgumentException("Can deal with non Range yet");
    }
    return new Section(ranges);
  }

  //////////////////////////////////////////////////////////////////////////////
  private List list;
  private boolean immutable = false;

  /**
   * Create Section from a shape array, assumes 0 origin.
   *
   * @param shape array of lengths for each Range. 0 = EMPTY, < 0 = VLEN
   */
  public Section(int[] shape) {
    list = new ArrayList<>();
    for (int aShape : shape) {
      if (aShape > 0)
        list.add(new Range(aShape));
      else if (aShape == 0)
        list.add(Range.EMPTY);
      else {
        list.add(Range.VLEN);
      }
    }
  }

  /**
   * Create Section from a shape and origin arrays.
   *
   * @param origin array of start for each Range
   * @param shape  array of lengths for each Range
   * @throws InvalidRangeException if origin < 0, or shape < 1.
   */
  public Section(int[] origin, int[] shape) throws InvalidRangeException {
    list = new ArrayList<>();
    for (int i = 0; i < shape.length; i++) {
      if (shape[i] > 0)
        list.add(new Range(origin[i], origin[i] + shape[i] - 1));
      else if (shape[i] == 0)
        list.add(Range.EMPTY);
      else {
        list.add(Range.VLEN);
      }
    }
  }

  public Section(long[] originLong, int[] shape) throws InvalidRangeException {
    list = new ArrayList<>();
    for (int i = 0; i < shape.length; i++) {
      if (shape[i] > 0)
        list.add(new Range(originLong[i], originLong[i] + shape[i] - 1));
      else if (shape[i] == 0)
        list.add(Range.EMPTY);
      else {
        list.add(Range.VLEN);
      }
    }
  }

  /**
   * Create Section from a shape, origin, and stride arrays.
   *
   * @param origin array of start for each Range
   * @param size   array of lengths for each Range (last = origin + size -1)
   * @param stride stride between consecutive elements, must be > 0
   * @throws InvalidRangeException if origin < 0, or shape < 1.
   */
  public Section(int[] origin, int[] size, int[] stride) throws InvalidRangeException {
    list = new ArrayList<>();
    for (int i = 0; i < size.length; i++) {
      if (size[i] > 0)
        list.add(new Range(origin[i], origin[i] + size[i] - 1, stride[i]));
      else if (size[i] == 0)
        list.add(Range.EMPTY);
      else {
        list.add(Range.VLEN);
      }
    }
  }

  /**
   * Create Section from a List.
   *
   * @param from the list of Range
   */
  public Section(List from) {
    list = new ArrayList<>(from);
  }

  /**
   * Create Section from a variable length list of Ranges
   *
   * @param ranges the list
   */
  public Section(Range... ranges) {
    list = new ArrayList<>();
    Collections.addAll(list, ranges);
  }

  /**
   * Copy Constructor.
   * Returned copy is mutable
   *
   * @param from the Section to copy
   */
  public Section(Section from) {
    list = new ArrayList<>(from.getRanges());
  }

  /**
   * Create Section from a List.
   *
   * @param from  the list of Range
   * @param shape use this as default shape if any of the ranges are null.
   * @throws InvalidRangeException if shape and range list done match
   */
  public Section(List from, int[] shape) throws InvalidRangeException {
    list = new ArrayList<>(from);
    setDefaults(shape);
  }

  /* public Section subsection(int startElement, int endElement) throws InvalidRangeException {
    int[] shape = getShape();
    Index index = Index.factory( shape);
    index.setCurrentCounter(startElement);
    int[] startShape = index.getCurrentCounter();
    index.setCurrentCounter(endElement);
    int[] endShape = index.getCurrentCounter();
    Section result = new Section();
    for (int i=0; i
   * The sectionSpec string uses fortran90 array section syntax, namely:
   * 
   *   sectionSpec := dims
   *   dims := dim | dim, dims
   *   dim := ':' | slice | start ':' end | start ':' end ':' stride
   *   slice := INTEGER
   *   start := INTEGER
   *   stride := INTEGER
   *   end := INTEGER
   *
   * where nonterminals are in lower case, terminals are in upper case, literals are in single quotes.
   *
   * Meaning of index selector :
   *  ':' = all
   *  slice = hold index to that value
   *  start:end = all indices from start to end inclusive
   *  start:end:stride = all indices from start to end inclusive with given stride
   *
   * 
* * @param sectionSpec the token to parse, eg "(1:20,:,3,10:20:2)", parenthesis optional * @throws InvalidRangeException when the Range is illegal * @throws IllegalArgumentException when sectionSpec is misformed */ public Section(String sectionSpec) throws InvalidRangeException { list = new ArrayList<>(); Range range; StringTokenizer stoke = new StringTokenizer(sectionSpec, "(),"); // LOOK deal with scatterRange {1,2,3} while (stoke.hasMoreTokens()) { String s = stoke.nextToken().trim(); if (s.equals(":")) range = null; // all else if (s.indexOf(':') < 0) { // just a number : slice try { int index = Integer.parseInt(s); range = new Range(index, index); } catch (NumberFormatException e) { throw new IllegalArgumentException(" illegal selector: " + s + " part of <" + sectionSpec + ">"); } } else { // gotta be "start : end" or "start : end : stride" StringTokenizer stoke2 = new StringTokenizer(s, ":"); String s1 = stoke2.nextToken(); String s2 = stoke2.nextToken(); String s3 = stoke2.hasMoreTokens() ? stoke2.nextToken() : null; try { int index1 = Integer.parseInt(s1); int index2 = Integer.parseInt(s2); int stride = (s3 != null) ? Integer.parseInt(s3) : 1; range = new Range(index1, index2, stride); } catch (NumberFormatException e) { throw new IllegalArgumentException(" illegal selector: " + s + " part of <" + sectionSpec + ">"); } } list.add(range); } } /** * Create a new Section by compacting each Range. * first = first/stride, last=last/stride, stride=1. * * @return compacted Section * @throws InvalidRangeException elements must be nonnegative, 0 <= first <= last */ public Section compact() throws InvalidRangeException { List results = new ArrayList<>(getRank()); for (Range r : list) { results.add(r.compact()); } return new Section(results); } /* * Create a new Section by compacting each Range. * first = first/stride, last=last/stride, stride=1. * * @return compacted Section * @throws InvalidRangeException elements must be nonnegative, 0 <= first <= last * public Section removeVlen() throws InvalidRangeException { boolean need = false; for (Range r : list) { if (r == Range.VLEN) need = true; } if (!need) return this; List results = new ArrayList<>(getRank()); for (Range r : list) { if (r != Range.VLEN) results.add(r); } return new Section(results); } */ /** * Create a new Section by composing with a Section that is reletive to this Section. * * @param want Section reletive to this one. If null, return this. If individual ranges are null, use corresponding Range in this. * @return new Section, composed * @throws InvalidRangeException if want.getRank() not equal to this.getRank(), or invalid component Range */ public Section compose(Section want) throws InvalidRangeException { // all nulls if (want == null) return this; // LOOK maybe a copy ?? if (want.getRank() != getRank()) throw new InvalidRangeException("Invalid Section rank"); // check individual nulls List results = new ArrayList<>(getRank()); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = want.getRange(j); if (r == null) results.add(base); else results.add(base.compose(r)); } return new Section(results); } /** * Create a new Section by intersection with another Section * * @param other Section other section * @return new Section, composed * @throws InvalidRangeException if want.getRank() not equal to this.getRank(), or invalid component Range */ public Section intersect(Section other) throws InvalidRangeException { if (!compatibleRank(other)) throw new InvalidRangeException("Invalid Section rank"); // check individual nulls List results = new ArrayList<>(getRank()); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = other.getRange(j); results.add(base.intersect(r)); } return new Section(results); } /** * Compute the element offset of an intersecting subrange of this. * @param intersect the subrange * @return element offset * @throws InvalidRangeException */ public int offset(Section intersect) throws InvalidRangeException { if (!compatibleRank(intersect)) throw new InvalidRangeException("Incompatible Section rank"); int result = 0; int stride = 1; for (int j = list.size() - 1; j >= 0; j--) { Range base = list.get(j); Range r = intersect.getRange(j); int offset = base.index(r.first()); result += offset * stride; stride *= base.length(); } return result; } public long offsetLong(Section intersect) throws InvalidRangeException { if (!compatibleRank(intersect)) throw new InvalidRangeException("Incompatible Section rank"); long result = 0; int stride = 1; for (int j = list.size() - 1; j >= 0; j--) { Range base = list.get(j); Range r = intersect.getRange(j); long offset = base.indexLong(r.firstLong()); result += offset * stride; stride *= base.length(); } return result; } /** * Create a new Section by union with another Section * * @param other Section other section * @return new Section, union of the two * @throws InvalidRangeException if want.getRank() not equal to this.getRank(), or invalid component Range */ public Section union(Section other) throws InvalidRangeException { if (other.getRank() != getRank()) throw new InvalidRangeException("Invalid Section rank"); List results = new ArrayList<>(getRank()); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = other.getRange(j); results.add(base.union(r)); } return new Section(results); } /** * Create a new Section by shifting each range by newOrigin.first() * The result is then a reletive offset from the newOrigin. * * @param newOrigin this becomes the origin of the result * @return new Section, shifted * @throws InvalidRangeException if want.getRank() not equal to this.getRank() */ public Section shiftOrigin(Section newOrigin) throws InvalidRangeException { if (newOrigin.getRank() != getRank()) throw new InvalidRangeException("Invalid Section rank"); // check individual nulls List results = new ArrayList<>(getRank()); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = newOrigin.getRange(j); results.add(base.shiftOrigin(r.first())); } return new Section(results); } public Section shiftOrigin(int[] newOrigin) throws InvalidRangeException { if (newOrigin.length != getRank()) throw new InvalidRangeException("Invalid Section rank"); List results = new ArrayList<>(getRank()); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); results.add(base.shiftOrigin(-newOrigin[j])); } return new Section(results); } /** * See if this Section intersects with another Section. ignores strides, vlen * * @param other another section * @return true if intersection is non-empty * @throws InvalidRangeException if want.getRank() not equal to this.getRank(), * */ public boolean intersects(Section other) throws InvalidRangeException { if (!compatibleRank(other)) throw new InvalidRangeException("Invalid Section rank"); for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = other.getRange(j); if (base == Range.VLEN || r == Range.VLEN) continue; if (!base.intersects(r)) return false; } return true; } /** * See if this Section contains another Section. ignores strides * Must have same rank and last >= other.last. * * @param other another section * @return true if its a subset */ public boolean contains(Section other) { if (other.getRank() != getRank()) return false; for (int j = 0; j < list.size(); j++) { Range base = list.get(j); Range r = other.getRange(j); if (base.first() > r.first()) return false; if (base.last() < r.last()) return false; } return true; } /** * Convert List of Ranges to String Spec. * Inverse of new Section(String sectionSpec) * * @return index section String specification */ public String toString() { Formatter sbuff = new Formatter(); for (int i = 0; i < list.size(); i++) { Range r = list.get(i); if (i > 0) sbuff.format(","); if (r == null) sbuff.format(":"); else { sbuff.format("%s", r.toString()); } } return sbuff.toString(); } public String show() { Formatter sbuff = new Formatter(); for (int i = 0; i < list.size(); i++) { Range r = list.get(i); if (i > 0) sbuff.format("%n"); if (r == null) sbuff.format(":"); else { if (r.getName() != null) sbuff.format("%s=", r.getName()); sbuff.format("%s", r.toString()); } } return sbuff.toString(); } /** * No-arg Constructor */ public Section() { list = new ArrayList<>(); } /////////////////////////////////////////////////////// // these make it mutable /** * Append a null Range to the Section - meaning "all" * * @return this */ public Section appendRange() { if (immutable) throw new IllegalStateException("Cant modify"); list.add(null); return this; } /** * Append a Range to the Section * * @return this */ public Section appendRange(Range r) { if (immutable) throw new IllegalStateException("Cant modify"); list.add(r); return this; } /** * Append a new Range(0,size-1) to the Section * * @param size add this Range * @return this * @throws InvalidRangeException if size < 1 */ public Section appendRange(int size) throws InvalidRangeException { if (immutable) throw new IllegalStateException("Cant modify"); if (size > 0) list.add(new Range(size)); else if (size == 0) list.add(Range.EMPTY); else list.add(Range.VLEN); return this; } /** * Append a new Range(first, last) to the Section * * @param first starting index * @param last last index, inclusive * @return this * @throws InvalidRangeException if last < first */ public Section appendRange(int first, int last) throws InvalidRangeException { if (immutable) throw new IllegalStateException("Cant modify"); if (last < 0) list.add(Range.VLEN); else list.add(new Range(first, last)); return this; } /** * Append a new Range(first,last,stride) to the Section * * @param first starting index * @param last last index, inclusive * @param stride stride * @return this * @throws InvalidRangeException if last < first */ public Section appendRange(int first, int last, int stride) throws InvalidRangeException { if (immutable) throw new IllegalStateException("Cant modify"); list.add(new Range(first, last, stride)); return this; } /** * Append a new Range(name,first,last,stride) to the Section * * @param name name of Range * @param first starting index * @param last last index, inclusive * @param stride stride * @return this * @throws InvalidRangeException if last < first */ public Section appendRange(String name, int first, int last, int stride) throws InvalidRangeException { if (immutable) throw new IllegalStateException("Cant modify"); list.add(new Range(name, first, last, stride)); return this; } /** * Insert a range at the specified index in the list. * * @param index insert here in the list, existing ranges at or after this index get shifted by one * @param r insert this Range * @return this * @throws IndexOutOfBoundsException if bad index */ public Section insertRange(int index, Range r) { if (immutable) throw new IllegalStateException("Cant modify"); list.add(index, r); return this; } /** * Remove a range at the specified index in the list. * * @param index remove here in the list, existing ranges after this index get shifted by one * @return this * @throws IndexOutOfBoundsException if bad index */ public Section removeRange(int index) { if (immutable) throw new IllegalStateException("Cant modify"); list.remove(index); return this; } /** * Set the range at the specified index in the list, previous Range is discarded * * @param index list index, must be in interval [0,size). * @param r insert this Range * @return this * @throws IndexOutOfBoundsException if bad index */ public Section setRange(int index, Range r) { if (immutable) throw new IllegalStateException("Cant modify"); list.set(index, r); return this; } /** * Replace a range at the specified index in the list. * * @param index replace here in the list. * @param r use this Range * @return this * @throws IndexOutOfBoundsException if bad index */ public Section replaceRange(int index, Range r) { if (immutable) throw new IllegalStateException("Cant modify"); list.set(index, r); return this; } /** * Remove any ranges of length 1 * * @return new Section if any Range had length 1, else this */ public Section reduce() { if (immutable) throw new IllegalStateException("Cant modify"); boolean needed = false; for (Range r : list) { if (r.length() == 1) needed = true; } if (!needed) return this; List newList = list.stream().filter(r -> r.length() > 1).collect(Collectors.toList()); return new Section(newList); } /** * If any of the ranges are null, which means "all", set the Range from the * corresponding length in shape[]. * * @param shape default length for each Range; must have matching rank. * @throws InvalidRangeException if rank is wrong */ public void setDefaults(int[] shape) throws InvalidRangeException { if (immutable) throw new IllegalStateException("Cant modify"); if (shape.length != list.size()) throw new InvalidRangeException(" shape[] must have same rank as Section"); // check that any individual Range is null for (int i = 0; i < shape.length; i++) { Range r = list.get(i); if (r == null) { if (shape[i] > 0) list.set(i, new Range(shape[i])); else if (shape[i] == 0) list.set(i, Range.EMPTY); else { list.set(i, Range.VLEN); } } } } /** * Makes the object immutable, so can be safely shared * * @return this Section */ public Section makeImmutable() { if (immutable) return this; immutable = true; list = Collections.unmodifiableList(list); return this; } /////////////////////////////////// end mutable methods // replace with these: public Section subSection(int fromIndex, int endExclusive) { return new Section( list.subList(fromIndex, endExclusive)); } public Section removeLast() { int size = list.size(); return subSection(size-2, size-1); } public Section removeVlen() { int size = list.size(); if (list.get(size-1) == Range.VLEN) return removeLast(); else return this; } public Section removeFirst(Section parentSection) { int parentSize = parentSection.getRank(); assert parentSize <= list.size(); if (parentSize == list.size()) return new Section(); // scalar return subSection(parentSize, list.size()); } public Section prepend(Section parentSection) { if (parentSection == null) return this; List ranges = new ArrayList<>(parentSection.getRanges()); ranges.addAll(getRanges()); return new Section(ranges); } public boolean isImmutable() { return immutable; } public boolean isVariableLength() { for (Range aFrom : list) if (aFrom == Range.VLEN) return true; return false; } /** * @deprecated dont assume evenly strided */ public boolean isStrided() { for (Range r : list) { if (r != null && r.stride() != 1) return false; } return true; } /** * Get shape array using the Range.length() values. * * @return int[] shape */ public int[] getShape() { int[] result = new int[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i).length(); } return result; } /** * Get origin array using the Range.first() values. * * @return int[] origin */ public int[] getOrigin() { int[] result = new int[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i).first(); } return result; } public long[] getOriginLong() { long[] result = new long[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i).firstLong(); } return result; } /** * Get stride array using the Range.stride() values. * * @return int[] stride * @deprecated dont assume evenly strided */ public int[] getStride() { int[] result = new int[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i).stride(); } return result; } /** * Get origin of the ith Range * * @param i index of Range * @return origin of ith Range */ public int getOrigin(int i) { return list.get(i).first(); } /** * Get length of the ith Range * * @param i index of Range * @return length of ith Range */ public int getShape(int i) { return list.get(i).length(); } /** * Get stride of the ith Range * * @param i index of Range * @return stride of ith Range * @deprecated dont assume evenly strided */ public int getStride(int i) { return list.get(i).stride(); } /** * Get rank - number of Ranges. * * @return rank */ public int getRank() { return list.size(); } /** * Compare this section with another upto the vlen in either */ public boolean compatibleRank(Section other) { return (getRank() == other.getRank()); /*if((isVariableLength() && other.isVariableLength()) || (!isVariableLength() && !other.isVariableLength())) return getRank() == other.getRank(); else if(isVariableLength() && !other.isVariableLength()) return getVlenRank() == other.getRank(); else // !isVariableLength() && other.isVariableLength() return getRank() == other.getVlenRank(); */ } /** * Compute total number of elements represented by the section. * Any VLEN or EMPTY Ranges are skipped. * * @return total number of elements */ public long computeSize() { long product = 1; for (Range r : list) { if (r == Range.VLEN) continue; product *= r.length(); } return product; } static public long computeSize(int[] shape) { long product = 1; for (int len : shape) { product *= len; } return product; } /** * Get the list of Ranges. * * @return the List */ public List getRanges() { return list; } /** * Get the ith Range * * @param i index into the list of Ranges * @return ith Range */ public Range getRange(int i) { return list.get(i); } /** * Find a Range by its name. * * @param rangeName find this Range * @return named Range or null */ public Range find(String rangeName) { for (Range r : list) { if (rangeName.equals(r.getName())) return r; } return null; } public Section addRangeNames(List rangeNames) throws InvalidRangeException { if (rangeNames.size() != getRank()) throw new InvalidRangeException("Invalid number of Range Names"); int count = 0; Section result = new Section(); for (Range r : getRanges()) { Range nr = r.setName(rangeNames.get(count++)); result.appendRange(nr); } return result; } /** * Check if this Section is legal for the given shape. * [Note: modified by dmh to address the case of unlimited * where the size is zero] * * @param shape range must fit within this shape, rank must match. * @return error message if illegal, null if all ok */ public String checkInRange(int shape[]) { if (list.size() != shape.length) return "Number of ranges in section (" + list.size() + ") must be = " + shape.length; for (int i = 0; i < list.size(); i++) { Range r = list.get(i); if (r == null) continue; if (r == Range.VLEN) continue; if (r == Range.EMPTY) { if (shape[i] != 0) return "Illegal Range for dimension " + i + ": empty range only for unlimited dimension len = 0"; else continue; } if (r.last() >= shape[i]) return "Illegal Range for dimension " + i + ": last requested " + r.last() + " > max " + (shape[i] - 1); } return null; } /** * Is this section equivilent to the given shape. * All non-null ranges must have origin 0 and length = shape[i] * * @param shape the given shape. * @return true if equivilent * @throws InvalidRangeException if section rank doesnt match shape length */ public boolean equivalent(int[] shape) throws InvalidRangeException { if (getRank() != shape.length) throw new InvalidRangeException("Invalid Section rank"); for (int i = 0; i < list.size(); i++) { Range r = list.get(i); if (r == null) continue; if (r.first() != 0) return false; if (r.length() != shape[i]) return false; } return true; } public boolean conformal(Section other) { if (computeSize() != other.computeSize()) return false; Section reduceThis = this.reduce(); Section reduceOther = other.reduce(); return reduceThis.equalShape(reduceOther); } public boolean equalShape(Section other) { if (computeSize() != other.computeSize()) return false; if (getRank() != other.getRank()) return false; for (int i = 0; i < getRank(); i++) { Range r = getRange(i); Range or = other.getRange(i); if (r.length() != or.length()) return false; } return true; } /** * Sections with equals Ranges are equal. */ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Section)) return false; Section os = (Section) o; if (getRank() != os.getRank()) return false; for (int i = 0; i < getRank(); i++) { Range r = getRange(i); Range or = os.getRange(i); if ((r == null) && (or != null)) return false; if ((or == null) && (r != null)) return false; if (r == null) continue; // then or is also null if (!r.equals(or)) return false; } return true; } /** * Override Object.hashCode() to agree with equals. */ public int hashCode() { int result = 17; for (Range r : list) if (r != null) result += 37 * result + r.hashCode(); return result; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Iterate over a section, returning the index in an equivalent 1D array of shape[], and optionally the corresponding index[n] * So this is a section in a (possibly) larger array described by shape[]. * The index is in the "source" array. * * @param shape total array shape * @return iterator over this section */ public Iterator getIterator(int[] shape) { return new Iterator(shape); } public class Iterator { private int[] odo = new int[getRank()]; // odometer - the current element LOOK could use Index, but must upgrade to using Range private List> rangeIterList = new ArrayList<>(); private int[] stride = new int[getRank()]; private long done, total; Iterator(int[] shape) { int ss = 1; for (int i = getRank() - 1; i >= 0; i--) { // fastest varying last stride[i] = ss; ss *= shape[i]; } for (int i = 0; i < getRank(); i++) { java.util.Iterator iter = getRange(i).iterator(); odo[i] = iter.next(); rangeIterList.add(iter); } done = 0; total = Index.computeSize(getShape()); // total in the section } /** * Return true if there are more elements * * @return true if there are more elements */ public boolean hasNext() { return done < total; } /** * Get the position in the equivalant 1D array of shape[] * * @param index if not null, return the current nD index * @return the current position in a 1D array */ public int next(int[] index) { int next = currentElement(); if (index != null) System.arraycopy(odo, 0, index, 0, odo.length); done++; if (done < total) incr(); // increment for next call return next; } /* * Get the current index in the result array, ie in this section * * @return result index * public int getResultIndex() { return (int) done - 1; } */ private void incr() { int digit = getRank() - 1; while (digit >= 0) { java.util.Iterator iter = rangeIterList.get(digit); if (iter.hasNext()) { odo[digit] = iter.next(); break; // normal exit } // else, carry to next digit in the odometer java.util.Iterator iterReset = getRange(digit).iterator(); odo[digit] = iterReset.next(); rangeIterList.set(digit, iterReset); digit--; assert digit >= 0; // catch screw-ups } } private int currentElement() { int value = 0; for (int ii = 0; ii < getRank(); ii++) value += odo[ii] * stride[ii]; return value; } } // Section.Iterator }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy