001: /*
002: * DisplacedArray.java
003: *
004: * Copyright (C) 2003 Peter Graves
005: * $Id: DisplacedArray.java,v 1.6 2003/11/15 11:03:29 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 DisplacedArray extends AbstractArray {
025: private final int[] dimv;
026: private final int size;
027: private final AbstractArray array;
028: private final int offset;
029:
030: public DisplacedArray(int[] dimv, AbstractArray array, int offset) {
031: this .dimv = dimv;
032: size = computeTotalSize(dimv);
033: this .array = array;
034: this .offset = offset;
035: }
036:
037: private static int computeTotalSize(int[] dimensions) {
038: int size = 1;
039: for (int i = dimensions.length; i-- > 0;)
040: size *= dimensions[i];
041: return size;
042: }
043:
044: public LispObject typeOf() {
045: if (dimv.length == 1) {
046: if (array instanceof LispString)
047: return Symbol.STRING;
048: if (array instanceof BitVector)
049: return Symbol.BIT_VECTOR;
050: return list3(Symbol.VECTOR, T, new Fixnum(size));
051: }
052: return list3(Symbol.ARRAY, T, getDimensions());
053: }
054:
055: public LispObject typep(LispObject type) throws ConditionThrowable {
056: if (type == Symbol.VECTOR || type == BuiltInClass.VECTOR)
057: return VECTORP();
058: if (type == Symbol.BIT_VECTOR
059: || type == BuiltInClass.BIT_VECTOR)
060: return BIT_VECTOR_P();
061: if (type == Symbol.SEQUENCE || type == BuiltInClass.SEQUENCE)
062: return VECTORP();
063: return super .typep(type);
064: }
065:
066: public LispObject BIT_VECTOR_P() {
067: if (dimv.length == 1)
068: return array.BIT_VECTOR_P();
069: return NIL;
070: }
071:
072: public LispObject STRINGP() {
073: if (dimv.length == 1)
074: return array.STRINGP();
075: return NIL;
076: }
077:
078: public boolean vectorp() {
079: return dimv.length == 1;
080: }
081:
082: public int length() throws ConditionThrowable {
083: if (dimv.length == 1)
084: return size;
085: throw new ConditionThrowable(new TypeError(this , "sequence"));
086: }
087:
088: public LispObject elt(int index) throws ConditionThrowable {
089: if (dimv.length == 1)
090: return getRowMajor(index);
091: throw new ConditionThrowable(new TypeError(this , "sequence"));
092: }
093:
094: public LispObject AREF(LispObject index) throws ConditionThrowable {
095: if (dimv.length == 1)
096: return getRowMajor(Fixnum.getValue(index));
097: StringBuffer sb = new StringBuffer("AREF: ");
098: sb.append("wrong number of subscripts (1) for array of rank ");
099: sb.append(getRank());
100: throw new ConditionThrowable(new ProgramError(sb.toString()));
101: }
102:
103: public int getRank() {
104: return dimv.length;
105: }
106:
107: public LispObject getDimensions() {
108: LispObject result = NIL;
109: for (int i = dimv.length; i-- > 0;)
110: result = new Cons(new Fixnum(dimv[i]), result);
111: return result;
112: }
113:
114: public int getDimension(int n) throws ConditionThrowable {
115: try {
116: return dimv[n];
117: } catch (ArrayIndexOutOfBoundsException e) {
118: throw new ConditionThrowable(new TypeError(
119: "bad array dimension"));
120: }
121: }
122:
123: public LispObject getElementType() {
124: return array.getElementType();
125: }
126:
127: public int getTotalSize() {
128: return size;
129: }
130:
131: public LispObject getRowMajor(int index) throws ConditionThrowable {
132: if (index >= 0 && index < size)
133: return array.getRowMajor(index + offset);
134: throw new ConditionThrowable(new TypeError(
135: "bad row major index " + index));
136: }
137:
138: public void setRowMajor(int index, LispObject newValue)
139: throws ConditionThrowable {
140: if (index >= 0 && index < size)
141: array.setRowMajor(index + offset, newValue);
142: else
143: throw new ConditionThrowable(new TypeError(
144: "bad row major index " + index));
145: }
146:
147: public String toString() {
148: StringBuffer sb = new StringBuffer();
149: sb.append('#');
150: sb.append(dimv.length);
151: sb.append('A');
152: appendContents(dimv, 0, sb);
153: return sb.toString();
154: }
155:
156: // ### array-displacement
157: // array-displacement array => displaced-to, displaced-index-offset
158: private static final Primitive1 ARRAY_DISPLACEMENT = new Primitive1(
159: "array-displacement") {
160: public LispObject execute(LispObject arg)
161: throws ConditionThrowable {
162: AbstractArray array = checkArray(arg);
163: LispObject[] values = new LispObject[2];
164: if (array instanceof DisplacedArray) {
165: DisplacedArray da = (DisplacedArray) array;
166: values[0] = da.array;
167: values[1] = new Fixnum(da.offset);
168: } else {
169: values[0] = NIL;
170: values[1] = Fixnum.ZERO;
171: }
172: LispThread.currentThread().setValues(values);
173: return values[0];
174: }
175: };
176: }
|