001: /*
002: * Array.java
003: *
004: * Copyright (C) 2003 Peter Graves
005: * $Id: Array.java,v 1.6 2003/11/15 11:03:32 beedlem 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 Array extends AbstractArray {
025: private final int[] dimv;
026: private final LispObject[] data;
027:
028: public Array(int[] dimv) {
029: this .dimv = dimv;
030: int size = computeTotalSize(dimv);
031: data = new LispObject[size];
032: for (int i = 0; i < size; i++)
033: data[i] = NIL;
034: }
035:
036: public Array(int[] dimv, LispObject initialContents)
037: throws ConditionThrowable {
038: this .dimv = dimv;
039: final int rank = dimv.length;
040: LispObject rest = initialContents;
041: for (int i = 0; i < rank; i++) {
042: dimv[i] = rest.length();
043: rest = rest.elt(0);
044: }
045: int size = computeTotalSize(dimv);
046: data = new LispObject[size];
047: setInitialContents(0, dimv, initialContents, 0);
048: }
049:
050: public Array(int rank, LispObject initialContents)
051: throws ConditionThrowable {
052: if (rank == 0) {
053: dimv = new int[0];
054: data = new LispObject[1];
055: data[0] = initialContents;
056: } else {
057: dimv = new int[rank];
058: LispObject rest = initialContents;
059: for (int i = 0; i < rank; i++) {
060: dimv[i] = rest.length();
061: if (rest == NIL)
062: break;
063: rest = rest.elt(0);
064: }
065: int size = computeTotalSize(dimv);
066: data = new LispObject[size];
067: setInitialContents(0, dimv, initialContents, 0);
068: }
069: }
070:
071: private int setInitialContents(int axis, int[] dims,
072: LispObject contents, int index) throws ConditionThrowable {
073: if (dims.length == 0) {
074: try {
075: data[index] = contents;
076: } catch (ArrayIndexOutOfBoundsException e) {
077: throw new ConditionThrowable(new LispError(
078: "bad initial contents for array"));
079: }
080: ++index;
081: } else {
082: int dim = dims[0];
083: if (dim != contents.length())
084: throw new ConditionThrowable(new LispError(
085: "bad initial contents for array"));
086: int[] newDims = new int[dims.length - 1];
087: for (int i = 1; i < dims.length; i++)
088: newDims[i - 1] = dims[i];
089: if (contents.listp()) {
090: for (int i = contents.length(); i-- > 0;) {
091: LispObject content = contents.car();
092: index = setInitialContents(axis + 1, newDims,
093: content, index);
094: contents = contents.cdr();
095: }
096: } else {
097: AbstractVector v = checkVector(contents);
098: final int length = v.length();
099: for (int i = 0; i < length; i++) {
100: LispObject content = v.get(i);
101: index = setInitialContents(axis + 1, newDims,
102: content, index);
103: }
104: }
105: }
106: return index;
107: }
108:
109: // FIXME Need to detect overflow.
110: private static int computeTotalSize(int[] dimensions) {
111: int size = 1;
112: for (int i = dimensions.length; i-- > 0;)
113: size *= dimensions[i];
114: return size;
115: }
116:
117: public LispObject typeOf() {
118: return list3(Symbol.SIMPLE_ARRAY, T, getDimensions());
119: }
120:
121: public LispClass classOf() {
122: return BuiltInClass.ARRAY;
123: }
124:
125: public LispObject typep(LispObject typeSpecifier)
126: throws ConditionThrowable {
127: if (typeSpecifier == Symbol.SIMPLE_ARRAY)
128: return T;
129: return super .typep(typeSpecifier);
130: }
131:
132: public int getRank() {
133: return dimv.length;
134: }
135:
136: public LispObject getDimensions() {
137: LispObject result = NIL;
138: for (int i = dimv.length; i-- > 0;)
139: result = new Cons(new Fixnum(dimv[i]), result);
140: return result;
141: }
142:
143: public int getDimension(int n) throws ConditionThrowable {
144: try {
145: return dimv[n];
146: } catch (ArrayIndexOutOfBoundsException e) {
147: throw new ConditionThrowable(new TypeError(
148: "bad array dimension"));
149: }
150: }
151:
152: public LispObject getElementType() {
153: return T;
154: }
155:
156: public int getTotalSize() {
157: return data.length;
158: }
159:
160: public LispObject getRowMajor(int index) throws ConditionThrowable {
161: try {
162: return data[index];
163: } catch (ArrayIndexOutOfBoundsException e) {
164: throw new ConditionThrowable(new TypeError(
165: "bad row major index " + index));
166: }
167: }
168:
169: public void setRowMajor(int index, LispObject newValue)
170: throws ConditionThrowable {
171: try {
172: data[index] = newValue;
173: } catch (ArrayIndexOutOfBoundsException e) {
174: throw new ConditionThrowable(new TypeError(
175: "bad row major index " + index));
176: }
177: }
178:
179: public void fill(LispObject obj) {
180: for (int i = data.length; i-- > 0;)
181: data[i] = obj;
182: }
183:
184: public String toString() {
185: StringBuffer sb = new StringBuffer();
186: sb.append('#');
187: sb.append(dimv.length);
188: sb.append('A');
189: appendContents(dimv, 0, sb);
190: return sb.toString();
191: }
192: }
|