001: /*
002: * SimpleArray.java
003: *
004: * Copyright (C) 2003-2004 Peter Graves
005: * $Id: SimpleArray.java,v 1.8 2004/05/27 20:29:41 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.lisp;
023:
024: public final class SimpleArray extends AbstractArray {
025: private final int[] dimv;
026: private final LispObject elementType;
027: private final int totalSize;
028: private final LispObject[] data;
029:
030: public SimpleArray(int[] dimv, LispObject elementType) {
031: this .dimv = dimv;
032: this .elementType = elementType;
033: totalSize = computeTotalSize(dimv);
034: data = new LispObject[totalSize];
035: final LispObject initialElement;
036: if (elementType == Symbol.BIT)
037: initialElement = Fixnum.ZERO;
038: else
039: initialElement = NIL;
040: for (int i = totalSize; i-- > 0;)
041: data[i] = initialElement;
042: }
043:
044: public SimpleArray(int[] dimv, LispObject elementType,
045: LispObject initialContents) throws ConditionThrowable {
046: this .dimv = dimv;
047: this .elementType = elementType;
048: final int rank = dimv.length;
049: LispObject rest = initialContents;
050: for (int i = 0; i < rank; i++) {
051: dimv[i] = rest.length();
052: rest = rest.elt(0);
053: }
054: totalSize = computeTotalSize(dimv);
055: data = new LispObject[totalSize];
056: setInitialContents(0, dimv, initialContents, 0);
057: }
058:
059: public SimpleArray(int rank, LispObject initialContents)
060: throws ConditionThrowable {
061: if (rank < 2)
062: Debug.assertTrue(false);
063: dimv = new int[rank];
064: this .elementType = T;
065: LispObject rest = initialContents;
066: for (int i = 0; i < rank; i++) {
067: dimv[i] = rest.length();
068: if (rest == NIL)
069: break;
070: rest = rest.elt(0);
071: }
072: totalSize = computeTotalSize(dimv);
073: data = new LispObject[totalSize];
074: setInitialContents(0, dimv, initialContents, 0);
075: }
076:
077: private int setInitialContents(int axis, int[] dims,
078: LispObject contents, int index) throws ConditionThrowable {
079: if (dims.length == 0) {
080: try {
081: data[index] = contents;
082: } catch (ArrayIndexOutOfBoundsException e) {
083: signal(new LispError("Bad initial contents for array."));
084: return -1;
085: }
086: ++index;
087: } else {
088: int dim = dims[0];
089: if (dim != contents.length()) {
090: signal(new LispError("Bad initial contents for array."));
091: return -1;
092: }
093: int[] newDims = new int[dims.length - 1];
094: for (int i = 1; i < dims.length; i++)
095: newDims[i - 1] = dims[i];
096: if (contents.listp()) {
097: for (int i = contents.length(); i-- > 0;) {
098: LispObject content = contents.car();
099: index = setInitialContents(axis + 1, newDims,
100: content, index);
101: contents = contents.cdr();
102: }
103: } else {
104: AbstractVector v = checkVector(contents);
105: final int length = v.length();
106: for (int i = 0; i < length; i++) {
107: LispObject content = v.getRowMajor(i);
108: index = setInitialContents(axis + 1, newDims,
109: content, index);
110: }
111: }
112: }
113: return index;
114: }
115:
116: public LispObject typeOf() {
117: return list3(Symbol.SIMPLE_ARRAY, elementType, getDimensions());
118: }
119:
120: public LispClass classOf() {
121: return BuiltInClass.ARRAY;
122: }
123:
124: public LispObject typep(LispObject typeSpecifier)
125: throws ConditionThrowable {
126: if (typeSpecifier == Symbol.SIMPLE_ARRAY)
127: return T;
128: return super .typep(typeSpecifier);
129: }
130:
131: public int getRank() {
132: return dimv.length;
133: }
134:
135: public LispObject getDimensions() {
136: LispObject result = NIL;
137: for (int i = dimv.length; i-- > 0;)
138: result = new Cons(new Fixnum(dimv[i]), result);
139: return result;
140: }
141:
142: public int getDimension(int n) throws ConditionThrowable {
143: try {
144: return dimv[n];
145: } catch (ArrayIndexOutOfBoundsException e) {
146: signal(new TypeError("Bad array dimension " + n + "."));
147: return -1;
148: }
149: }
150:
151: public LispObject getElementType() {
152: return elementType;
153: }
154:
155: public int getTotalSize() {
156: return totalSize;
157: }
158:
159: public boolean isAdjustable() {
160: return false;
161: }
162:
163: public LispObject getRowMajor(int index) throws ConditionThrowable {
164: try {
165: return data[index];
166: } catch (ArrayIndexOutOfBoundsException e) {
167: return signal(new TypeError("Bad row major index " + index
168: + "."));
169: }
170: }
171:
172: public void setRowMajor(int index, LispObject newValue)
173: throws ConditionThrowable {
174: try {
175: data[index] = newValue;
176: } catch (ArrayIndexOutOfBoundsException e) {
177: signal(new TypeError("Bad row major index " + index + "."));
178: }
179: }
180:
181: public int getRowMajorIndex(int[] subscripts)
182: throws ConditionThrowable {
183: final int rank = dimv.length;
184: if (rank != subscripts.length) {
185: StringBuffer sb = new StringBuffer(
186: "Wrong number of subscripts (");
187: sb.append(subscripts.length);
188: sb.append(") for array of rank ");
189: sb.append(rank);
190: sb.append('.');
191: signal(new ProgramError(sb.toString()));
192: }
193: int sum = 0;
194: int size = 1;
195: for (int i = rank; i-- > 0;) {
196: final int dim = dimv[i];
197: final int lastSize = size;
198: size *= dim;
199: int n = subscripts[i];
200: if (n < 0 || n >= dim) {
201: StringBuffer sb = new StringBuffer("Invalid index ");
202: sb.append(n);
203: sb.append(" for array ");
204: sb.append(this );
205: sb.append('.');
206: signal(new ProgramError(sb.toString()));
207: }
208: sum += n * lastSize;
209: }
210: return sum;
211: }
212:
213: public LispObject get(int[] subscripts) throws ConditionThrowable {
214: try {
215: return data[getRowMajorIndex(subscripts)];
216: } catch (ArrayIndexOutOfBoundsException e) {
217: return signal(new TypeError("Bad row major index "
218: + getRowMajorIndex(subscripts) + "."));
219: }
220: }
221:
222: public void set(int[] subscripts, LispObject newValue)
223: throws ConditionThrowable {
224: try {
225: data[getRowMajorIndex(subscripts)] = newValue;
226: } catch (ArrayIndexOutOfBoundsException e) {
227: signal(new TypeError("Bad row major index "
228: + getRowMajorIndex(subscripts) + "."));
229: }
230: }
231:
232: public void fill(LispObject obj) {
233: for (int i = totalSize; i-- > 0;)
234: data[i] = obj;
235: }
236:
237: public String writeToString() throws ConditionThrowable {
238: StringBuffer sb = new StringBuffer();
239: sb.append('#');
240: sb.append(dimv.length);
241: sb.append('A');
242: appendContents(dimv, 0, sb);
243: return sb.toString();
244: }
245:
246: public AbstractArray adjustArray(int[] dimv,
247: LispObject initialElement, LispObject initialContents)
248: throws ConditionThrowable {
249: if (initialContents != NIL)
250: return new SimpleArray(dimv, elementType, initialContents);
251: for (int i = 0; i < dimv.length; i++) {
252: if (dimv[i] != this .dimv[i]) {
253: SimpleArray newArray = new SimpleArray(dimv,
254: elementType);
255: newArray.fill(initialElement);
256: copyArray(this , newArray);
257: return newArray;
258: }
259: }
260: // New dimensions are identical to old dimensions.
261: return this ;
262: }
263:
264: // Copy a1 to a2 for index tuples that are valid for both arrays.
265: private static void copyArray(AbstractArray a1, AbstractArray a2)
266: throws ConditionThrowable {
267: Debug.assertTrue(a1.getRank() == a2.getRank());
268: int[] subscripts = new int[a1.getRank()];
269: int axis = 0;
270: copySubArray(a1, a2, subscripts, axis);
271: }
272:
273: private static void copySubArray(AbstractArray a1,
274: AbstractArray a2, int[] subscripts, int axis)
275: throws ConditionThrowable {
276: if (axis < subscripts.length) {
277: final int limit = Math.min(a1.getDimension(axis), a2
278: .getDimension(axis));
279: for (int i = 0; i < limit; i++) {
280: subscripts[axis] = i;
281: copySubArray(a1, a2, subscripts, axis + 1);
282: }
283: } else {
284: int i1 = a1.getRowMajorIndex(subscripts);
285: int i2 = a2.getRowMajorIndex(subscripts);
286: a2.setRowMajor(i2, a1.getRowMajor(i1));
287: }
288: }
289:
290: public AbstractArray adjustArray(int[] dimv,
291: AbstractArray displacedTo, int displacement) {
292: return new ComplexArray(dimv, displacedTo, displacement);
293: }
294: }
|