Changeset 2968 for trunk


Ignore:
Timestamp:
07/12/07 14:56:50 (13 years ago)
Author:
curtis
Message:

Rewrite cache strategy logic.

Location:
trunk/loci/formats/cache
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/cache/Cache.java

    r2961 r2968  
    9393    if (pos.length != currentPos.length) { 
    9494      throw new CacheException("pos length mismatch (is " + 
    95         pos.length + ", expected " + currentPos.length); 
     95        pos.length + ", expected " + currentPos.length + ")"); 
    9696    } 
    9797    int[] len = strategy.getLengths(); 
     
    172172        System.out.println("  source"); 
    173173        System.out.println("  position"); 
    174         System.out.println("  forward"); 
    175         System.out.println("  backward"); 
     174        System.out.println("  range"); 
    176175        System.out.println("  priority"); 
    177176        System.out.println("  read"); 
     
    193192        System.out.println("strategy = " + strategy.getClass().getName()); 
    194193        printArray("\tpriorities", strategy.getPriorities()); 
    195         System.out.println("\tforwardFirst = " + strategy.getForwardFirst()); 
    196         printArray("\tforward", strategy.getForward()); 
    197         printArray("\tbackward", strategy.getBackward()); 
     194        int[] order = strategy.getOrder(); 
     195        System.out.print("\torder ="); 
     196        for (int i=0; i<order.length; i++) { 
     197          switch (order[i]) { 
     198            case ICacheStrategy.CENTERED_ORDER: 
     199              System.out.print(" C"); 
     200              break; 
     201            case ICacheStrategy.FORWARD_ORDER: 
     202              System.out.print(" F"); 
     203              break; 
     204            case ICacheStrategy.BACKWARD_ORDER: 
     205              System.out.print(" B"); 
     206              break; 
     207            default: 
     208              System.out.print(" ?"); 
     209          } 
     210        } 
     211        System.out.println(); 
     212        printArray("\trange", strategy.getRange()); 
    198213        printArray("\tlengths", strategy.getLengths()); 
    199214        // output source information 
     
    255270        cache.setCurrentPos(new int[] {z, c, t}); 
    256271      } 
    257       else if (cmd.equals("forward")) { 
     272      else if (cmd.equals("range")) { 
    258273        System.out.print("Z: "); 
    259274        int z = Integer.parseInt(r.readLine().trim()); 
     
    262277        System.out.print("T: "); 
    263278        int t = Integer.parseInt(r.readLine().trim()); 
    264         cache.getStrategy().setForward(z, 0); 
    265         cache.getStrategy().setForward(c, 1); 
    266         cache.getStrategy().setForward(t, 2); 
    267       } 
    268       else if (cmd.equals("backward")) { 
    269         System.out.print("Z: "); 
    270         int z = Integer.parseInt(r.readLine().trim()); 
    271         System.out.print("C: "); 
    272         int c = Integer.parseInt(r.readLine().trim()); 
    273         System.out.print("T: "); 
    274         int t = Integer.parseInt(r.readLine().trim()); 
    275         cache.getStrategy().setBackward(z, 0); 
    276         cache.getStrategy().setBackward(c, 1); 
    277         cache.getStrategy().setBackward(t, 2); 
     279        cache.getStrategy().setRange(z, 0); 
    278280      } 
    279281      else if (cmd.equals("priority")) { 
  • trunk/loci/formats/cache/CacheStrategy.java

    r2961 r2968  
    66 
    77import java.util.Arrays; 
    8  
    9 public abstract class CacheStrategy implements ICacheStrategy { 
     8import java.util.Comparator; 
     9import loci.formats.FormatTools; 
     10 
     11public abstract class CacheStrategy implements Comparator, ICacheStrategy { 
    1012 
    1113  // -- Constants -- 
    1214 
    13   public static final int DEFAULT_FORWARD = 20; 
    14   public static final int DEFAULT_BACKWARD = 10; 
     15  public static final int DEFAULT_RANGE = 10; 
    1516 
    1617  // -- Fields -- 
    17   
     18 
    1819  /** Length of each dimensional axis. */ 
    1920  protected int[] lengths; 
    2021 
    21   /** Whether or not forward slices should be loaded first. */ 
    22   protected boolean forwardFirst; 
    23  
    24   /** Number of planes to cache forward along each axis. */ 
    25   protected int[] forward; 
    26  
    27   /** Number of planes to cache backward along each axis. */ 
    28   protected int[] backward; 
     22  /** The order in which slices should be loaded along each axis. */ 
     23  protected int[] order; 
     24 
     25  /** Number of planes to cache along each axis. */ 
     26  protected int[] range; 
    2927 
    3028  /** Priority for caching each axis. Controls axis caching order. */ 
    3129  protected int[] priorities; 
    3230 
     31  /** 
     32   * The list of dimensional positions to consider caching, 
     33   * in order of preference based on strategy, axis priority and slice order. 
     34   */ 
     35  private int[][] positions; 
     36 
     37  /** 
     38   * Whether load order array needs to be recomputed 
     39   * before building the next load list. 
     40   */ 
     41  private boolean dirty; 
     42 
    3343  // -- Constructors -- 
    3444 
     45  /** Constructs a cache strategy. */ 
    3546  public CacheStrategy(int[] lengths) { 
    3647    this.lengths = lengths; 
    37     forwardFirst = true; 
    38     forward = new int[lengths.length]; 
    39     Arrays.fill(forward, DEFAULT_FORWARD); 
    40     backward = new int[lengths.length]; 
    41     Arrays.fill(backward, DEFAULT_BACKWARD); 
     48    order = new int[lengths.length]; 
     49    Arrays.fill(order, CENTERED_ORDER); 
     50    range = new int[lengths.length]; 
     51    Arrays.fill(range, DEFAULT_RANGE); 
    4252    priorities = new int[lengths.length]; 
    4353    Arrays.fill(priorities, NORMAL_PRIORITY); 
    44   } 
    45  
    46   // -- Abstract ICacheStrategy API methods -- 
     54    positions = getPossiblePositions(); 
     55    dirty = true; 
     56  } 
     57 
     58  // -- Abstract CacheStrategy API methods -- 
     59 
     60  protected abstract int[][] getPossiblePositions(); 
     61 
     62  // -- CacheStrategy API methods -- 
     63 
     64  public int raster(int[] pos) { 
     65    return FormatTools.positionToRaster(lengths, pos); 
     66  } 
     67 
     68  public int[] pos(int raster) { 
     69    return FormatTools.rasterToPosition(lengths, raster); 
     70  } 
     71 
     72  public int[] pos(int raster, int[] pos) { 
     73    return FormatTools.rasterToPosition(lengths, raster, pos); 
     74  } 
     75 
     76  public int length() { return FormatTools.getRasterLength(lengths); } 
     77 
     78  /** 
     79   * Computes the distance from the given axis value to the 
     80   * axis center, taking into account the axis ordering scheme. 
     81   */ 
     82  public int distance(int axis, int value) { 
     83    switch (order[axis]) { 
     84      case CENTERED_ORDER: 
     85        if (value == 0) return 0; 
     86        int vb = lengths[axis] - value; 
     87        return value <= vb ? 2 * value - 1 : 2 * vb; 
     88      case FORWARD_ORDER: 
     89        return value; 
     90      case BACKWARD_ORDER: 
     91        return lengths[axis] - value; 
     92      default: 
     93        throw new IllegalStateException("unknown order: " + order[axis]); 
     94    } 
     95  } 
     96 
     97  // -- Comparator API methods -- 
     98 
     99  /** 
     100   * Default comparator orders dimensional positions based on distance from the 
     101   * current position, taking into account axis priorities and slice ordering. 
     102   */ 
     103  public int compare(Object o1, Object o2) { 
     104    int[] p1 = (int[]) o1; 
     105    int[] p2 = (int[]) o2; 
     106 
     107    // compare sum of axis distances for each priority 
     108    for (int p=MAX_PRIORITY; p>=MIN_PRIORITY; p--) { 
     109      int dist1 = 0, dist2 = 0; 
     110      for (int i=0; i<p1.length; i++) { 
     111        if (priorities[i] == p) { 
     112          dist1 += distance(i, p1[i]); 
     113          dist2 += distance(i, p2[i]); 
     114        } 
     115      } 
     116      int diff = dist1 - dist2; 
     117      if (diff != 0) return diff; 
     118    } 
     119 
     120    // compare number of diverging axes for each priority 
     121    for (int p=MAX_PRIORITY; p>=MIN_PRIORITY; p--) { 
     122      int div1 = 0, div2 = 0; 
     123      for (int i=0; i<p1.length; i++) { 
     124        if (priorities[i] == p) { 
     125          if (p1[i] != 0) div1++; 
     126          if (p2[i] != 0) div2++; 
     127        } 
     128      } 
     129      int diff = div1 - div2; 
     130      if (diff != 0) return diff; 
     131    } 
     132 
     133    return 0; 
     134  } 
     135 
     136  // -- ICacheStrategy API methods -- 
    47137 
    48138  /* @see ICacheStrategy#getLoadList(int[]) */ 
    49   public abstract int[][] getLoadList(int[] pos) throws CacheException;  
    50  
    51   // -- ICacheStrategy API methods -- 
     139  public int[][] getLoadList(int[] pos) throws CacheException { 
     140    int[][] loadList = null; 
     141    synchronized (positions) { 
     142      if (dirty) { 
     143        // reorder the positions list 
     144        Arrays.sort(positions, this); 
     145        dirty = false; 
     146      } 
     147 
     148      // build load list from current pos, positions list, load order and range 
     149      int count = 0; 
     150      for (int i=0; i<positions.length; i++) { 
     151        int[] ipos = positions[i]; 
     152 
     153        // compute total distance from current pos 
     154        int dist = 0; 
     155        for (int j=0; j<ipos.length; j++) { 
     156          if (distance(j, ipos[j]) > range[j]) continue; // out of range 
     157        } 
     158 
     159        // position is in range 
     160        count++; 
     161      } 
     162 
     163      loadList = new int[count][lengths.length]; 
     164      int c = 0; 
     165 
     166      // populate load list 
     167      for (int i=0; i<positions.length; i++) { 
     168        int[] ipos = positions[i]; 
     169 
     170        // compute total distance from current pos 
     171        int dist = 0; 
     172        for (int j=0; j<ipos.length; j++) { 
     173          if (distance(j, ipos[j]) > range[j]) continue; // out of range 
     174          int value = (pos[j] + ipos[j]) % lengths[j]; // normalize axis value 
     175          loadList[c][j] = value; 
     176        } 
     177        c++; 
     178      } 
     179    } 
     180    return loadList; 
     181  } 
    52182 
    53183  /* @see ICacheStrategy#getPriorities() */ 
     
    56186  /* @see ICacheStrategy#setPriority() */ 
    57187  public void setPriority(int priority, int axis) { 
    58     priorities[axis] = priority;  
    59   } 
    60  
    61   /* @see ICacheStrategy#getForwardFirst() */ 
    62   public boolean getForwardFirst() { return forwardFirst; } 
    63  
    64   /* @see ICacheStrategy#setForwardFirst(boolean) */ 
    65   public void setForwardFirst(boolean forwardFirst) { 
    66     this.forwardFirst = forwardFirst; 
    67   } 
    68  
    69   /* @see ICacheStrategy#getForward() */ 
    70   public int[] getForward() { return forward; } 
    71  
    72   /* @see ICacheStrategy#setForward(int, int) */ 
    73   public void setForward(int planes, int axis) { 
    74     forward[axis] = planes; 
    75   } 
    76  
    77   /* @see ICacheStrategy#getBackward() */ 
    78   public int[] getBackward() { return backward; } 
    79  
    80   /* @see ICacheStrategy#setBackward(int, int) */ 
    81   public void setBackward(int planes, int axis) { 
    82     backward[axis] = planes; 
     188    if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) { 
     189      throw new IllegalArgumentException( 
     190        "Invalid priority for axis #" + axis + ": " + priority); 
     191    } 
     192    synchronized (positions) { 
     193      priorities[axis] = priority; 
     194      dirty = true; 
     195    } 
     196  } 
     197 
     198  /* @see ICacheStrategy#getOrder() */ 
     199  public int[] getOrder() { return order; } 
     200 
     201  /* @see ICacheStrategy#getOrder() */ 
     202  public void setOrder(int order, int axis) { 
     203    if (order != CENTERED_ORDER && 
     204      order != FORWARD_ORDER && order != BACKWARD_ORDER) 
     205    { 
     206      throw new IllegalArgumentException( 
     207        "Invalid order for axis #" + axis + ": " + order); 
     208    } 
     209    synchronized (positions) { 
     210      this.order[axis] = order; 
     211      dirty = true; 
     212    } 
     213  } 
     214 
     215  /* @see ICacheStrategy#getRange() */ 
     216  public int[] getRange() { return range; } 
     217 
     218  /* @see ICacheStrategy#setRange(int, int) */ 
     219  public void setRange(int planes, int axis) { 
     220    if (planes < 0) { 
     221      throw new IllegalArgumentException( 
     222        "Invalid range for axis #" + axis + ": " + planes); 
     223    } 
     224    range[axis] = planes; 
    83225  } 
    84226 
     
    86228  public int[] getLengths() { return lengths; } 
    87229 
    88   // -- Utility methods -- 
    89  
    90   public static int nextPriority(int ndx, int[] priorities) { 
    91     int basePriority = priorities[ndx]; 
    92     for (int i=0; i<priorities.length; i++) { 
    93       if (priorities[i] >= basePriority && i != ndx) { 
    94         if (priorities[i] != basePriority || i >= ndx) {  
    95           return i; 
    96         }  
    97       } 
    98     } 
    99     return -1;  
    100   } 
    101  
    102230} 
  • trunk/loci/formats/cache/CrosshairStrategy.java

    r2961 r2968  
    44 
    55package loci.formats.cache; 
    6  
    7 import java.util.Arrays; 
    8 import java.util.Vector; 
    96 
    107/** 
     
    2118 * <p> 
    2219 * To illustrate the crosshair strategy, here is a diagram showing a case 
    23  * in 2D with 56 dimensional positions (7Z x 8T). Forward first option is set 
    24  * to false, forward value is 2 for both Z and T, backward value is also 2 for 
    25  * both, and priority is normal for both. 
     20 * in 2D with 56 dimensional positions (7Z x 8T). For both Z and T, order is 
     21 * centered, range is 2, and priority is normal. 
    2622 * The numbers indicate the order planes will be cached, with "0" 
    2723 * corresponding to the current dimensional position. 
     
    3228 *    1 |           8 
    3329 *    2 |           4 
    34  *    3 |     6  2  0  1  5 
    35  *    4 |           3 
    36  *    5 |           7 
     30 *    3 |     7  3  0  1  5 
     31 *    4 |           2 
     32 *    5 |           6 
    3733 *    6 | 
    3834 * </pre> 
    3935 */ 
    4036public class CrosshairStrategy extends CacheStrategy { 
    41  
    42   // -- Static fields -- 
    43  
    44   /** Persistent Vector for calling {@link #getLoadList(int[])} efficiently. */ 
    45   private static ThreadLocal listVector = new ThreadLocal() { 
    46     protected synchronized Object initialValue() { 
    47       return new Vector(); 
    48     } 
    49   }; 
    5037 
    5138  // -- Constructor -- 
     
    5441  public CrosshairStrategy(int[] lengths) { super(lengths); } 
    5542 
    56   // -- ICacheStrategy API methods -- 
     43  // -- CacheStrategy API methods -- 
    5744 
    58   /* @see loci.formats.cache.ICacheStrategy#getLoadList(int[]) */ 
    59   public int[][] getLoadList(int[] pos) throws CacheException { 
    60     int[] positions = new int[pos.length]; 
    61     int[] begins = new int[pos.length]; 
    62     int[] ends = new int[pos.length]; 
    63     int total = 0;  
    64     for (int i=0; i<positions.length; i++) { 
    65       positions[i] = pos[i]; 
    66       total += (forward[i] + backward[i]);  
    67       begins[i] = pos[i] - backward[i]; 
    68       ends[i] = pos[i] + forward[i]; 
    69      
    70       if (begins[i] < 0) begins[i] += lengths[i]; 
    71       if (ends[i] >= lengths[i]) ends[i] %= lengths[i]; 
    72     } 
    73  
    74     int count = 0; 
    75  
    76     Vector list = (Vector) listVector.get(); 
    77     list.clear(); 
    78  
    79     int firstNdx = 0; 
    80     for (int i=0; i<priorities.length; i++) { 
    81       if (priorities[i] == HIGH_PRIORITY) { 
    82         firstNdx = i; 
    83         break; 
     45  /* @see CacheStrategy#getPossiblePositions() */ 
     46  protected int[][] getPossiblePositions() { 
     47    // only positions diverging along a single axis can ever be cached 
     48    int len = 1; 
     49    for (int i=0; i<lengths.length; i++) len += lengths[i] - 1; 
     50    int[][] p = new int[len][lengths.length]; 
     51    for (int i=0, c=0; i<lengths.length; i++) { 
     52      for (int j=1; j<lengths[i]; j++) { 
     53        p[++c][i] = j; 
    8454      } 
    8555    } 
    86  
    87     while (count < total) { 
    88       int[] tmp = new int[positions.length]; 
    89       System.arraycopy(positions, 0, tmp, 0, positions.length); 
    90       list.add(tmp);  
    91       positions =  
    92         increment(positions, firstNdx, begins[firstNdx], ends[firstNdx]); 
    93       if (Arrays.equals(positions, pos)) { 
    94         firstNdx = nextPriority(firstNdx, priorities);  
    95       } 
    96  
    97       count++; 
    98     } 
    99  
    100     return (int[][]) list.toArray(new int[0][0]); 
    101   } 
    102  
    103   // -- Helper methods -- 
    104  
    105   private int[] increment(int[] pos, int ndx, int begin, int end) { 
    106     if (forwardFirst) { 
    107       pos[ndx]++; 
    108       if (pos[ndx] == end) { 
    109         pos[ndx] = begin; 
    110       } 
    111       if (pos[ndx] == lengths[ndx]) pos[ndx] = 0; 
    112     } 
    113     else { 
    114       pos[ndx]--; 
    115       if (pos[ndx] == begin) { 
    116         pos[ndx] = end; 
    117       } 
    118       if (pos[ndx] == -1) pos[ndx] = lengths[ndx] - 1;  
    119     } 
    120     return pos;  
     56    return p; 
    12157  } 
    12258 
  • trunk/loci/formats/cache/ICacheStrategy.java

    r2961 r2968  
    1515  int MAX_PRIORITY = 10; 
    1616 
     17  int CENTERED_ORDER = 0; 
     18  int FORWARD_ORDER = 1; 
     19  int BACKWARD_ORDER = -1; 
     20 
    1721  // -- ICacheStrategy API methods -- 
    1822 
    1923  /**  
    20    * Get the indices of the objects to cache,  
     24   * Gets the indices of the objects to cache,  
    2125   * surrounding the object with the given index. 
    2226   */ 
    2327  int[][] getLoadList(int[] pos) throws CacheException; 
    2428 
    25   /** Retrieve the priority for caching each axis. */ 
     29  /** Retrieves the priority for caching each axis. */ 
    2630  int[] getPriorities(); 
    2731 
    28   /** Set the priority for caching the given axis. */ 
     32  /** Sets the priority for caching the given axis. */ 
    2933  void setPriority(int priority, int axis); 
    3034 
    31   /** Return true if forward slices should be loaded first. */ 
    32   boolean getForwardFirst(); 
     35  /** 
     36   * Retrieves the order in which slices should be loaded along each axis. 
     37   * @return An array whose constituents are each one of:<ul> 
     38   *   <li>CENTERED_ORDER</li> 
     39   *   <li>FORWARD_ORDER</li> 
     40   *   <li>BACKWARD_ORDER</li> 
     41   */ 
     42  int[] getOrder(); 
    3343 
    34   /** Set whether or not forward slices should be loaded first. */ 
    35   void setForwardFirst(boolean forwardFirst); 
     44  /** 
     45   * Sets the order in which slices should be loaded along each axis. 
     46   * @param order One of:<ul> 
     47   *   <li>CENTERED_ORDER</li> 
     48   *   <li>FORWARD_ORDER</li> 
     49   *   <li>BACKWARD_ORDER</li> 
     50   * @param axis The axis for which to set the order. 
     51   */ 
     52  void setOrder(int order, int axis); 
    3653 
    37   /** Retrieve the number of planes to cache forward along each axis. */ 
    38   int[] getForward(); 
     54  /** Retrieves the number of planes to cache along each axis. */ 
     55  int[] getRange(); 
    3956 
    40   /** Set the number of planes to cache forward along the given axis. */ 
    41   void setForward(int planes, int axis); 
     57  /** Sets the number of planes to cache along the given axis. */ 
     58  void setRange(int planes, int axis); 
    4259 
    43   /** Retrieve the number of planes to cache backward along each axis. */ 
    44   int[] getBackward(); 
    45  
    46   /** Set the number of planes to cache backward along the given axis. */ 
    47   void setBackward(int planes, int axis); 
    48  
    49   /** Get the lengths of all the axes. */ 
     60  /** Gets the lengths of all the axes. */ 
    5061  int[] getLengths(); 
    5162 
  • trunk/loci/formats/cache/RectangleStrategy.java

    r2961 r2968  
    44 
    55package loci.formats.cache; 
    6  
    7 import java.util.Arrays; 
    8 import java.util.Vector; 
    96 
    107/** 
     
    2219 * <p> 
    2320 * To illustrate the rectangle strategy, here is a diagram showing a case 
    24  * in 2D with 56 dimensional positions (7Z x 8T). Forward first option is set 
    25  * to false, forward value is 2 for both Z and T, backward value is also 2 for 
    26  * both, and priority is normal for both. 
     21 * in 2D with 56 dimensional positions (7Z x 8T). For both Z and T, order is 
     22 * centered, range is 5, and priority is normal. 
    2723 * The numbers indicate the order planes will be cached, with "0" 
    2824 * corresponding to the current dimensional position. 
     
    3127 *    Z /------------------------ 
    3228 *    0 | 
    33  *    1 |    24 16 12 15 23 
    34  *    2 |    20  8  4  7 19 
    35  *    3 |    10  2  0  1  9 
    36  *    4 |    18  6  3  5 17 
    37  *    5 |    22 14 11 13 21 
     29 *    1 |    24 20  7 16 23 
     30 *    2 |    19 14  4  9 17 
     31 *    3 |    10  3  0  1  6 
     32 *    4 |    15  8  2  5 12 
     33 *    5 |    22 18 11 13 21 
    3834 *    6 | 
    3935 * </pre> 
    4036 */ 
    4137public class RectangleStrategy extends CacheStrategy { 
    42  
    43   // -- Static fields -- 
    44  
    45   /** Persistent Vector for calling {@link #getLoadList(int[])} efficiently. */ 
    46   private static ThreadLocal listVector = new ThreadLocal() { 
    47     protected synchronized Object initialValue() { 
    48       return new Vector(); 
    49     } 
    50   }; 
    51  
    52   // -- Fields -- 
    53  
    54   private int[] begins; 
    55   private int[] ends; 
    5638 
    5739  // -- Constructor -- 
     
    6042  public RectangleStrategy(int[] lengths) { super(lengths); } 
    6143 
    62   // -- ICacheStrategy API methods -- 
     44  // -- CacheStrategy API methods -- 
    6345 
    64   /* @see loci.formats.cache.ICacheStrategy#getLoadList(int[]) */ 
    65   public int[][] getLoadList(int[] pos) throws CacheException { 
    66     int[] positions = new int[pos.length]; 
    67     begins = new int[pos.length]; 
    68     ends = new int[pos.length]; 
    69  
    70     int total = 1; 
    71  
    72     for (int i=0; i<pos.length; i++) { 
    73       positions[i] = pos[i]; 
    74       begins[i] = pos[i] - backward[i]; 
    75       ends[i] = pos[i] + forward[i]; 
    76       if (begins[i] < 0) begins[i] = 0; 
    77       total *= (ends[i] - begins[i] + 1);  
    78       if (begins[i] < 0) begins[i] += lengths[i]; 
    79       if (ends[i] >= lengths[i]) ends[i] %= lengths[i]; 
    80     } 
    81  
    82     int count = 0; 
    83  
    84     Vector list = (Vector) listVector.get(); 
    85     list.clear(); 
    86  
    87     int firstNdx = 0; 
    88     for (int i=0; i<priorities.length; i++) { 
    89       if (priorities[i] == HIGH_PRIORITY) { 
    90         firstNdx = i; 
    91         break; 
    92       }       
    93     } 
    94  
    95     while (count < total) { 
    96       int[] tmp = new int[positions.length]; 
    97       System.arraycopy(positions, 0, tmp, 0, positions.length); 
    98       list.add(tmp); 
    99       positions = increment(positions, firstNdx); 
    100       if (Arrays.equals(positions, pos)) { 
    101         firstNdx = nextPriority(firstNdx, priorities); 
    102       } 
    103       if (firstNdx == -1) { 
    104         count = total; 
    105         break; 
    106       } 
    107       count++;  
    108     } 
    109  
    110     return (int[][]) list.toArray(new int[0][0]); 
    111   } 
    112  
    113   // -- Helper methods -- 
    114     
    115   private int[] increment(int[] pos, int ndx) { 
    116     if (ndx == -1) return pos;  
    117     if (forwardFirst) { 
    118       pos[ndx]++; 
    119       if (pos[ndx] == lengths[ndx]) pos[ndx] = 0;  
    120       if (pos[ndx] > ends[ndx]) { 
    121         pos[ndx] = begins[ndx]; 
    122         return increment(pos, nextPriority(ndx, priorities)); 
    123       } 
    124     } 
    125     else { 
    126       pos[ndx]--; 
    127       if (pos[ndx] == -1) pos[ndx] = lengths[ndx] - 1;  
    128       if (pos[ndx] < begins[ndx]) { 
    129         pos[ndx] = ends[ndx]; 
    130         return increment(pos, nextPriority(ndx, priorities)); 
    131       } 
    132     } 
    133     return pos;  
     46  /* @see CacheStrategy#getPossiblePositions() */ 
     47  protected int[][] getPossiblePositions() { 
     48    // with sufficient range, any position could be cached 
     49    int[][] p = new int[length()][lengths.length]; 
     50    for (int i=0; i<p.length; i++) pos(i, p[i]); 
     51    return p; 
    13452  } 
    13553 
Note: See TracChangeset for help on using the changeset viewer.