// $Id: IndexIterator.java,v 1.2 2002-05-29 20:32:39 steve Exp $ /* * Copyright 1997-2000 Unidata Program Center/University Corporation for * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307, * support@unidata.ucar.edu. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package ucar.multiarray; /** * An IndexIterator is a helper class used for stepping through the * index values of a MultiArray. * <p> * This is like an odometer. The number of columns or rings on the odometer * is the length of the constructor argument. The number of values on * each ring of the odometer is specified in the limits argument of * the constructor. * <p> * Currently no synchronized methods. * * @see MultiArray * @author $Author: steve $ * @version $Revision: 1.2 $ $Date: 2002-05-29 20:32:39 $ */ public class IndexIterator { /** * Return <code>true</code> iff the argument * is the zero index. */ static public boolean isZero(int [] iv) { for(int ii = 0; ii < iv.length; ii++) if(iv[ii] != 0) return false; return true; } /** * Return <code>true</code> iff the arguments have * same values. */ static public boolean equals(int [] lhs, int [] rhs) { if(lhs == rhs) return true; // else if(lhs.length != rhs.length) return false; // else for(int ii = 0; ii < lhs.length; ii++) if(lhs[ii] != rhs[ii]) return false; return true; } /** * Creates a new IndexIterator whose variation is bounded by the * component values of the argument. * @param theLimits typically <code>ma.getLengths()</code> * for some MultiArray <code>ma</code> */ public IndexIterator(int [] theLimits) { counter = new int[theLimits.length]; limits = theLimits; // N.B. Not a copy ncycles = 0; } /** * Creates a new IndexIterator with initial counter value, * whose variation is bounded by the * component values of the <code>limits</code> argument. * @param initCounter the initial value. * @param theLimits typically <code>ma.getLengths()</code> * for some MultiArray <code>ma</code> */ public IndexIterator(int [] initCounter, int [] theLimits) { if(initCounter == null) counter = new int[theLimits.length]; else counter = (int []) initCounter.clone(); limits = theLimits; // N.B. Not a copy ncycles = 0; } /** * If the IndexIterator has not yet "rolled over", * return <code>true</code>. * Useful for loop end detection. */ public boolean notDone() { if(ncycles > 0) return false; return true; } /** * Return the current counter value. * N.B. Not a copy! */ public int [] value() { return counter; } /** * Increment the counter value */ public void incr() { int digit = counter.length -1; if(digit < 0) { // counter is zero length array <==> scalar ncycles++; return; } while(digit >= 0) { counter[digit]++; if(counter[digit] < limits[digit]) break; // normal exit // else, carry counter[digit] = 0; if(digit == 0) { ncycles++; // rolled over break; } // else digit--; } } /** * Increment the counter value * @param nsteps the number of times to increment the value. */ public void advance(int nsteps) { // TODO: make this smarter and faster; while(nsteps-- > 0) incr(); } public String toString() { StringBuffer buf = new StringBuffer(); final int last = counter.length -1; for(int ii = 0; ii <= last; ii++) { buf.append(counter[ii]); if(ii == last) break; // normal loop exit buf.append(" "); } return buf.toString(); } /** * Test */ public static void main (String args[]) { /* * Translate the command line args into an array of int. */ int [] edges = new int[args.length]; int ii; for(ii = 0; ii < args.length; ii++) { final Integer av = new Integer(args[ii]); edges[ii] = av.intValue(); } System.out.println(edges); /* * Example usage */ IndexIterator odo = new IndexIterator(edges); for(ii = 0; odo.notDone(); odo.incr(), ii++) { System.out.println(odo); } System.out.print("\t"); System.out.println(ii); } /** * The counter value. Initialized to zero. The length * is the same as limits.length. */ protected final int[] counter; /** * (Reference to) the constructor argument which determines * counter value variation. * <code>for 0 <= ii < limits.length, counter[ii] < limits[ii]</code> */ protected final int[] limits; /** * A "carry" indicator, * the number of times the counter value has rolled over. */ protected int ncycles; }