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

ucar.ma2.SectionIterable Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */
package ucar.ma2;

import javax.annotation.concurrent.Immutable;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * A Section composed of List instead of List.
 * SectionIterable knows the fullShape of which it is a section.
 * The iteration is over the elements in the section, returning 1D index into the full shape.
 *
 * @author John
 * @since 8/23/2015
 */
@Immutable
public class SectionIterable implements Iterable {

  private final List ranges;
  private final int[] fullShape;

  public SectionIterable(List ranges, int[] fullShape) {
    assert ranges.size() == fullShape.length : ranges.size() +" != "+ fullShape.length;
    int count = 0;
    for (RangeIterator ri : ranges) {
      assert (ri.length() <= fullShape[count]);
      count++;
    }

    this.ranges = ranges;
    this.fullShape = fullShape;
  }

  public SectionIterable(List ranges, List fullShapeList) {
    assert ranges.size() == fullShapeList.size() : ranges.size() +" != "+ fullShapeList.size();
    int count = 0;
    this.fullShape = new int[fullShapeList.size()];
    for (RangeIterator ri : ranges) {
      assert (ri.length() <= fullShapeList.get(count));
      this.fullShape[count] = fullShapeList.get(count);
      count++;
    }

    this.ranges = ranges;
  }

  public SectionIterable(Section section, int[] fullShape) {
    this.ranges = new ArrayList<>();
    for (Range r : section.getRanges())
      this.ranges.add(r);
    this.fullShape = fullShape;
  }

  public int getRank() {
    return ranges.size();
  }

  public SectionIterable subSection(int start, int endExclusive) {
    int n = endExclusive - start;
    int[] subFullRange = new int[n];
    System.arraycopy(fullShape, start, subFullRange, 0, n);

    return new SectionIterable( ranges.subList(start, endExclusive), subFullRange);
  }

  public RangeIterator getRange(int i) {
    return ranges.get(i);
  }

  public int[] getShape() {
    int[] result = new int[getRank()];
    for (int i=0; i iterator() {
    return new SectionIterator();
  }

  /**
   * Iterate over a section, returning the index in an equivalent 1D array of shape[]
   * So this is a section in a (possibly) larger array described by shape[].
   * The index is in the "source" array.
   *
   * @return iterator over this section
   */
  public SectionIterator getIterator() {
    return new SectionIterator();
  }

  public class SectionIterator implements 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;

    SectionIterator() {
      int ss = 1;
      for (int i = getRank() - 1; i >= 0; i--) {  // fastest varying last
        stride[i] = ss;
        ss *= fullShape[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
    }

    public boolean hasNext() {
      return done < total;
    }

    public Integer next() {
      int next = currentElement();
      done++;
      if (done < total) incr(); // increment for next call
      return next;
    }

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

    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;
    }
  } // SectionIterator

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy