001: // Copyright (c) 2001, 2002 Per M.A. Bothner and Brainfood Inc.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.lists;
005:
006: /** A class to handle general multi-dimensional arrays.
007: * This class is <strong>unfinished</strong>.
008: * If the number of dimensions (the "rank") is one, should use
009: * a class that implements Sequence.
010: * GeneralArray uses a SimpleVector 'base' to store the actual data, and
011: * provides general linear mapping from the array indexes to an
012: * element index in the 'base' SimpleVector. Thus such uperations as
013: * transposing an array can be implement as just creating a simple
014: * re-mapping of the indexes. */
015:
016: public class GeneralArray extends AbstractSequence implements Array //, Consumable
017: // Should implement Collection?
018: // Note this intentionally does not implement Sequence.
019: {
020: SimpleVector base;
021: int[] dimensions;
022: int[] strides;
023: int[] lowBounds;
024: static final int[] zeros = new int[8];
025: int offset;
026: boolean simple = true;
027:
028: public static Array makeSimple(int[] lowBounds, int[] dimensions,
029: SimpleVector base) {
030: int d = dimensions.length;
031: if (lowBounds == null) {
032: lowBounds = zeros;
033: if (d > lowBounds.length)
034: lowBounds = new int[d];
035: }
036: if (d == 1 && lowBounds[0] == 0)
037: return base;
038: GeneralArray array = new GeneralArray();
039: int[] strides = new int[d];
040: int n = 1;
041: for (int i = d; --i >= 0;) {
042: strides[i] = n;
043: n *= dimensions[i];
044: }
045: array.strides = strides;
046: array.dimensions = dimensions;
047: array.lowBounds = lowBounds;
048: array.base = base;
049: return array;
050: }
051:
052: public GeneralArray() {
053: }
054:
055: public GeneralArray(int[] dimensions) {
056: int total = 1;
057: int rank = dimensions.length;
058: if (rank <= zeros.length)
059: lowBounds = zeros;
060: else
061: lowBounds = new int[rank];
062: int[] strides = new int[rank];
063: for (int i = rank; --i >= 0;) {
064: strides[i] = total;
065: total *= dimensions[i];
066: }
067: base = new FVector(total);
068: this .dimensions = dimensions;
069: this .offset = 0;
070: }
071:
072: public int rank() {
073: return dimensions.length;
074: }
075:
076: /** Calculate corresponding index in base array. */
077: public int getEffectiveIndex(int[] indexes) {
078: int result = offset;
079: for (int i = dimensions.length; --i >= 0;) {
080: int index = indexes[i];
081: int low = lowBounds[i];
082: if (index < low || (index -= low) >= dimensions[i])
083: throw new IndexOutOfBoundsException();
084: result += strides[i] * index;
085: }
086: return result;
087: }
088:
089: public Object get(int index) {
090: return getRowMajor(index);
091: }
092:
093: public int createPos(int index, boolean isAfter) {
094: int total = offset;
095: for (int i = dimensions.length; --i >= 0;) {
096: int dim = dimensions[i];
097: int cur = index % dim;
098: index = index / dim;
099: total = total + strides[i] * cur;
100: }
101: return (total << 1) | (isAfter ? 1 : 0);
102: }
103:
104: public Object getRowMajor(int index) {
105: if (simple)
106: return base.get(index);
107: int total = offset;
108: for (int i = dimensions.length; --i >= 0;) {
109: int dim = dimensions[i];
110: int cur = index % dim;
111: index = index / dim;
112: total = total + strides[i] * cur;
113: }
114: return base.get(total);
115: }
116:
117: public Object get(int[] indexes) {
118: return base.get(getEffectiveIndex(indexes));
119: }
120:
121: public Object set(int[] indexes, Object value) {
122: return base.set(getEffectiveIndex(indexes), value);
123: }
124:
125: /** See java.util.Collection. */
126: public int size() {
127: int total = 1;
128: for (int i = dimensions.length; --i >= 0;)
129: total *= dimensions[i];
130: return total;
131: }
132:
133: public int getLowBound(int dim) {
134: return lowBounds[dim];
135: }
136:
137: public int getSize(int dim) {
138: return dimensions[dim];
139: }
140:
141: public Array transpose(int[] lowBounds, int[] dimensions,
142: int offset0, int[] factors) {
143: GeneralArray array = dimensions.length == 1
144: && lowBounds[0] == 0 ? new GeneralArray1()
145: : new GeneralArray();
146: array.offset = offset0;
147: array.strides = factors;
148: array.dimensions = dimensions;
149: array.lowBounds = lowBounds;
150: array.base = base;
151: array.simple = false;
152: return array;
153: }
154:
155: public static void toString(Array array, StringBuffer sbuf) {
156: sbuf.append("#<array");
157: int r = array.rank();
158: for (int i = 0; i < r; i++) {
159: sbuf.append(' ');
160: int lo = array.getLowBound(i);
161: int sz = array.getSize(i);
162: if (lo != 0) {
163: sbuf.append(lo);
164: sbuf.append(':');
165: }
166: sbuf.append(lo + sz);
167: }
168: sbuf.append('>');
169: }
170:
171: public String toString() {
172: StringBuffer sbuf = new StringBuffer();
173: toString(this, sbuf);
174: return sbuf.toString();
175: }
176: }
|