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