KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > ComplexVector


1 /*
2  * ComplexVector.java
3  *
4  * Copyright (C) 2002-2004 Peter Graves
5  * $Id: ComplexVector.java,v 1.13 2004/05/27 17:10:36 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 // A vector that is displaced to another array, has a fill pointer, and/or is
25
// expressly adjustable. It can hold elements of any type.
26
public final class ComplexVector extends AbstractVector
27 {
28     private int capacity;
29     private int fillPointer = -1; // -1 indicates no fill pointer.
30
private boolean isDisplaced;
31
32     // For non-displaced arrays.
33
private LispObject[] elements;
34
35     // For displaced arrays.
36
private AbstractArray array;
37     private int displacement;
38
39     public ComplexVector(int capacity)
40     {
41         elements = new LispObject[capacity];
42         for (int i = capacity; i-- > 0;)
43             elements[i] = NIL;
44         this.capacity = capacity;
45     }
46
47     public ComplexVector(int capacity, AbstractArray array, int displacement)
48     {
49         this.capacity = capacity;
50         this.array = array;
51         this.displacement = displacement;
52         isDisplaced = true;
53     }
54
55     public LispObject typeOf()
56     {
57         return list3(Symbol.VECTOR, T, new Fixnum(capacity));
58     }
59
60     public LispClass classOf()
61     {
62         return BuiltInClass.VECTOR;
63     }
64
65     public boolean hasFillPointer()
66     {
67         return fillPointer >= 0;
68     }
69
70     public int getFillPointer()
71     {
72         return fillPointer;
73     }
74
75     public void setFillPointer(int n)
76     {
77         fillPointer = n;
78     }
79
80     public void setFillPointer(LispObject obj) throws ConditionThrowable
81     {
82         if (obj == T)
83             fillPointer = capacity();
84         else {
85             int n = Fixnum.getValue(obj);
86             if (n > capacity()) {
87                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The new fill pointer (");
88                 sb.append(n);
89                 sb.append(") exceeds the capacity of the vector (");
90                 sb.append(capacity());
91                 sb.append(").");
92                 signal(new LispError(sb.toString()));
93             } else if (n < 0) {
94                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The new fill pointer (");
95                 sb.append(n);
96                 sb.append(") is negative.");
97                 signal(new LispError(sb.toString()));
98             } else
99                 fillPointer = n;
100         }
101     }
102
103     public boolean isDisplaced()
104     {
105         return isDisplaced;
106     }
107
108     public LispObject arrayDisplacement() throws ConditionThrowable
109     {
110         LispObject value1, value2;
111         if (array != null) {
112             value1 = array;
113             value2 = new Fixnum(displacement);
114         } else {
115             value1 = NIL;
116             value2 = Fixnum.ZERO;
117         }
118         return LispThread.currentThread().setValues(value1, value2);
119     }
120
121     public LispObject getElementType()
122     {
123         return T;
124     }
125
126     public boolean isSimpleVector()
127     {
128         return false;
129     }
130
131     public int capacity()
132     {
133         return capacity;
134     }
135
136     public int length()
137     {
138         return fillPointer >= 0 ? fillPointer : capacity;
139     }
140
141     public LispObject elt(int index) throws ConditionThrowable
142     {
143         final int limit = length();
144         if (index < 0 || index >= limit)
145             badIndex(index, limit);
146         return getRowMajor(index);
147     }
148
149     // Ignores fill pointer.
150
// FIXME inline
151
public LispObject AREF(LispObject index) throws ConditionThrowable
152     {
153         return getRowMajor(Fixnum.getValue(index));
154     }
155
156     public LispObject getRowMajor(int index) throws ConditionThrowable
157     {
158         if (elements != null) {
159             try {
160                 return elements[index];
161             }
162             catch (ArrayIndexOutOfBoundsException JavaDoc e) {
163                 badIndex(index, elements.length);
164                 return NIL; // Not reached.
165
}
166         } else
167             return array.getRowMajor(index + displacement);
168     }
169
170     public void setRowMajor(int index, LispObject newValue) throws ConditionThrowable
171     {
172         if (elements != null) {
173             try {
174                 elements[index] = newValue;
175             }
176             catch (ArrayIndexOutOfBoundsException JavaDoc e) {
177                 badIndex(index, elements.length);
178             }
179         } else
180             array.setRowMajor(index + displacement, newValue);
181     }
182
183     public LispObject subseq(int start, int end) throws ConditionThrowable
184     {
185         SimpleVector v = new SimpleVector(end - start);
186         int i = start, j = 0;
187         try {
188             while (i < end)
189                 v.setRowMajor(j++, getRowMajor(i++));
190             return v;
191         }
192         catch (ArrayIndexOutOfBoundsException JavaDoc e) {
193             return signal(new TypeError("Array index out of bounds: " + i + "."));
194         }
195     }
196
197     public void fill(LispObject obj) throws ConditionThrowable
198     {
199         for (int i = capacity; i-- > 0;)
200             elements[i] = obj;
201     }
202
203     public void shrink(int n) throws ConditionThrowable
204     {
205         if (elements != null) {
206             if (n < elements.length) {
207                 LispObject[] newArray = new LispObject[n];
208                 System.arraycopy(elements, 0, newArray, 0, n);
209                 elements = newArray;
210                 capacity = n;
211                 return;
212             }
213             if (n == elements.length)
214                 return;
215         }
216         signal(new LispError());
217     }
218
219     public LispObject reverse() throws ConditionThrowable
220     {
221         int length = length();
222         SimpleVector result = new SimpleVector(length);
223         int i, j;
224         for (i = 0, j = length - 1; i < length; i++, j--)
225             result.setRowMajor(i, getRowMajor(j));
226         return result;
227     }
228
229     public LispObject nreverse() throws ConditionThrowable
230     {
231         int i = 0;
232         int j = length() - 1;
233         while (i < j) {
234             LispObject temp = elements[i];
235             elements[i] = elements[j];
236             elements[j] = temp;
237             ++i;
238             --j;
239         }
240         return this;
241     }
242
243     public LispObject vectorPushExtend(LispObject element)
244         throws ConditionThrowable
245     {
246         if (fillPointer < 0)
247             noFillPointer();
248         if (fillPointer >= capacity) {
249             // Need to extend vector.
250
ensureCapacity(capacity * 2 + 1);
251         }
252         setRowMajor(fillPointer, element);
253         return new Fixnum(fillPointer++);
254     }
255
256     public LispObject vectorPushExtend(LispObject element, LispObject extension)
257         throws ConditionThrowable
258     {
259         int ext = Fixnum.getValue(extension);
260         if (fillPointer < 0)
261             noFillPointer();
262         if (fillPointer >= capacity) {
263             // Need to extend vector.
264
ext = Math.max(ext, capacity + 1);
265             ensureCapacity(capacity + ext);
266         }
267         setRowMajor(fillPointer, element);
268         return new Fixnum(fillPointer++);
269     }
270
271     private final void ensureCapacity(int minCapacity) throws ConditionThrowable
272     {
273         if (elements != null) {
274             if (capacity < minCapacity) {
275                 LispObject[] newArray = new LispObject[minCapacity];
276                 System.arraycopy(elements, 0, newArray, 0, capacity);
277                 elements = newArray;
278                 capacity = minCapacity;
279             }
280         } else {
281             Debug.assertTrue(array != null);
282             if (array.getTotalSize() - displacement < minCapacity) {
283                 // Copy array.
284
elements = new LispObject[minCapacity];
285                 final int limit = array.getTotalSize() - displacement;
286                 for (int i = 0; i < limit; i++)
287                     elements[i] = array.getRowMajor(displacement + i);
288                 capacity = minCapacity;
289                 array = null;
290                 displacement = 0;
291                 isDisplaced = false;
292             }
293         }
294     }
295
296     public AbstractVector adjustVector(int newCapacity,
297                                        LispObject initialElement,
298                                        LispObject initialContents)
299         throws ConditionThrowable
300     {
301         if (initialContents != NIL) {
302             // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE-
303
// ARRAY. In this case none of the original contents of array
304
// appears in the resulting array."
305
LispObject[] newElements = new LispObject[newCapacity];
306             if (initialContents.listp()) {
307                 LispObject list = initialContents;
308                 for (int i = 0; i < newCapacity; i++) {
309                     newElements[i] = list.car();
310                     list = list.cdr();
311                 }
312             } else if (initialContents.vectorp()) {
313                 for (int i = 0; i < newCapacity; i++)
314                     newElements[i] = initialContents.elt(i);
315             } else
316                 signal(new TypeError(initialContents, Symbol.SEQUENCE));
317             elements = newElements;
318         } else {
319             if (elements == null) {
320                 // Displaced array. Copy existing elements.
321
elements = new LispObject[newCapacity];
322                 final int limit = Math.min(capacity, newCapacity);
323                 for (int i = 0; i < limit; i++)
324                     elements[i] = array.getRowMajor(displacement + i);
325             } else if (capacity != newCapacity) {
326                 LispObject[] newElements = new LispObject[newCapacity];
327                 System.arraycopy(elements, 0, newElements, 0,
328                                  Math.min(capacity, newCapacity));
329                 elements = newElements;
330             }
331             // Initialize new elements (if any).
332
for (int i = capacity; i < newCapacity; i++)
333                 elements[i] = initialElement;
334         }
335         capacity = newCapacity;
336         array = null;
337         displacement = 0;
338         isDisplaced = false;
339         return this;
340     }
341
342     public AbstractVector adjustVector(int newCapacity,
343                                        AbstractArray displacedTo,
344                                        int displacement)
345         throws ConditionThrowable
346     {
347         capacity = newCapacity;
348         array = displacedTo;
349         this.displacement = displacement;
350         elements = null;
351         isDisplaced = true;
352         return this;
353     }
354 }
355
Popular Tags