source: branches/0.19.x/abcl/src/org/armedbear/lisp/ComplexVector.java

Last change on this file was 12288, checked in by vvoutilainen, 16 years ago

Don't extend Lisp in LispObject, static import Lisp wherever
necessary. Patch by Douglas R. Miles.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.4 KB
Line 
1/*
2 * ComplexVector.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: ComplexVector.java 12288 2009-11-29 22:00:12Z vvoutilainen $
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38// A vector that is displaced to another array, has a fill pointer, and/or is
39// expressly adjustable. It can hold elements of any type.
40public final class ComplexVector extends AbstractVector
41{
42    private int capacity;
43    private int fillPointer = -1; // -1 indicates no fill pointer.
44    private boolean isDisplaced;
45
46    // For non-displaced arrays.
47    private LispObject[] elements;
48
49    // For displaced arrays.
50    private AbstractArray array;
51    private int displacement;
52
53    public ComplexVector(int capacity)
54    {
55        elements = new LispObject[capacity];
56        for (int i = capacity; i-- > 0;)
57            elements[i] = Fixnum.ZERO;
58        this.capacity = capacity;
59    }
60
61    public ComplexVector(int capacity, AbstractArray array, int displacement)
62    {
63        this.capacity = capacity;
64        this.array = array;
65        this.displacement = displacement;
66        isDisplaced = true;
67    }
68
69    @Override
70    public LispObject typeOf()
71    {
72        return list(Symbol.VECTOR, T, Fixnum.getInstance(capacity));
73    }
74
75    @Override
76    public LispObject classOf()
77    {
78        return BuiltInClass.VECTOR;
79    }
80
81    @Override
82    public boolean hasFillPointer()
83    {
84        return fillPointer >= 0;
85    }
86
87    @Override
88    public int getFillPointer()
89    {
90        return fillPointer;
91    }
92
93    @Override
94    public void setFillPointer(int n)
95    {
96        fillPointer = n;
97    }
98
99    @Override
100    public void setFillPointer(LispObject obj)
101    {
102        if (obj == T)
103            fillPointer = capacity();
104        else {
105            int n = Fixnum.getValue(obj);
106            if (n > capacity()) {
107                StringBuffer sb = new StringBuffer("The new fill pointer (");
108                sb.append(n);
109                sb.append(") exceeds the capacity of the vector (");
110                sb.append(capacity());
111                sb.append(").");
112                error(new LispError(sb.toString()));
113            } else if (n < 0) {
114                StringBuffer sb = new StringBuffer("The new fill pointer (");
115                sb.append(n);
116                sb.append(") is negative.");
117                error(new LispError(sb.toString()));
118            } else
119                fillPointer = n;
120        }
121    }
122
123    @Override
124    public boolean isDisplaced()
125    {
126        return isDisplaced;
127    }
128
129    @Override
130    public LispObject arrayDisplacement()
131    {
132        LispObject value1, value2;
133        if (array != null) {
134            value1 = array;
135            value2 = Fixnum.getInstance(displacement);
136        } else {
137            value1 = NIL;
138            value2 = Fixnum.ZERO;
139        }
140        return LispThread.currentThread().setValues(value1, value2);
141    }
142
143    @Override
144    public LispObject getElementType()
145    {
146        return T;
147    }
148
149    @Override
150    public boolean isSimpleVector()
151    {
152        return false;
153    }
154
155    @Override
156    public int capacity()
157    {
158        return capacity;
159    }
160
161    @Override
162    public int length()
163    {
164        return fillPointer >= 0 ? fillPointer : capacity;
165    }
166
167    @Override
168    public LispObject elt(int index)
169    {
170        final int limit = length();
171        if (index < 0 || index >= limit)
172            badIndex(index, limit);
173        return AREF(index);
174    }
175
176    // Ignores fill pointer.
177    @Override
178    public LispObject AREF(int index)
179    {
180        if (elements != null) {
181            try {
182                return elements[index];
183            }
184            catch (ArrayIndexOutOfBoundsException e) {
185                badIndex(index, elements.length);
186                return NIL; // Not reached.
187            }
188        } else {
189            // Displaced array.
190            if (index < 0 || index >= capacity)
191                badIndex(index, capacity);
192            return array.AREF(index + displacement);
193        }
194    }
195
196    // Ignores fill pointer.
197    // FIXME inline
198    @Override
199    public LispObject AREF(LispObject index)
200    {
201        return AREF(Fixnum.getValue(index));
202    }
203
204    @Override
205    public void aset(int index, LispObject newValue)
206    {
207        if (elements != null) {
208            try {
209                elements[index] = newValue;
210            }
211            catch (ArrayIndexOutOfBoundsException e) {
212                badIndex(index, elements.length);
213            }
214        } else {
215            // Displaced array.
216            if (index < 0 || index >= capacity)
217                badIndex(index, capacity);
218            else
219                array.aset(index + displacement, newValue);
220        }
221    }
222
223    @Override
224    public LispObject subseq(int start, int end)
225    {
226        SimpleVector v = new SimpleVector(end - start);
227        int i = start, j = 0;
228        try {
229            while (i < end)
230                v.aset(j++, AREF(i++));
231            return v;
232        }
233        catch (ArrayIndexOutOfBoundsException e) {
234            return error(new TypeError("Array index out of bounds: " + i + "."));
235        }
236    }
237
238    @Override
239    public void fill(LispObject obj)
240    {
241        for (int i = capacity; i-- > 0;)
242            elements[i] = obj;
243    }
244
245    @Override
246    public void shrink(int n)
247    {
248        if (elements != null) {
249            if (n < elements.length) {
250                LispObject[] newArray = new LispObject[n];
251                System.arraycopy(elements, 0, newArray, 0, n);
252                elements = newArray;
253                capacity = n;
254                return;
255            }
256            if (n == elements.length)
257                return;
258        }
259        error(new LispError());
260    }
261
262    @Override
263    public LispObject reverse()
264    {
265        int length = length();
266        SimpleVector result = new SimpleVector(length);
267        int i, j;
268        for (i = 0, j = length - 1; i < length; i++, j--)
269            result.aset(i, AREF(j));
270        return result;
271    }
272
273    @Override
274    public LispObject nreverse()
275    {
276        if (elements != null) {
277            int i = 0;
278            int j = length() - 1;
279            while (i < j) {
280                LispObject temp = elements[i];
281                elements[i] = elements[j];
282                elements[j] = temp;
283                ++i;
284                --j;
285            }
286        } else {
287            // Displaced array.
288            int length = length();
289            LispObject[] data = new LispObject[length];
290            int i, j;
291            for (i = 0, j = length - 1; i < length; i++, j--)
292                data[i] = AREF(j);
293            elements = data;
294            capacity = length;
295            array = null;
296            displacement = 0;
297            isDisplaced = false;
298            fillPointer = -1;
299        }
300        return this;
301    }
302
303    @Override
304    public void vectorPushExtend(LispObject element)
305
306    {
307        if (fillPointer < 0)
308            noFillPointer();
309        if (fillPointer >= capacity) {
310            // Need to extend vector.
311            ensureCapacity(capacity * 2 + 1);
312        }
313        aset(fillPointer++, element);
314    }
315
316    @Override
317    public LispObject VECTOR_PUSH_EXTEND(LispObject element)
318
319    {
320        vectorPushExtend(element);
321        return Fixnum.getInstance(fillPointer - 1);
322    }
323
324    @Override
325    public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)
326
327    {
328        int ext = Fixnum.getValue(extension);
329        if (fillPointer < 0)
330            noFillPointer();
331        if (fillPointer >= capacity) {
332            // Need to extend vector.
333            ext = Math.max(ext, capacity + 1);
334            ensureCapacity(capacity + ext);
335        }
336        aset(fillPointer, element);
337        return Fixnum.getInstance(fillPointer++);
338    }
339
340    private final void ensureCapacity(int minCapacity)
341    {
342        if (elements != null) {
343            if (capacity < minCapacity) {
344                LispObject[] newArray = new LispObject[minCapacity];
345                System.arraycopy(elements, 0, newArray, 0, capacity);
346                elements = newArray;
347                capacity = minCapacity;
348            }
349        } else {
350            // Displaced array.
351            Debug.assertTrue(array != null);
352            if (capacity < minCapacity ||
353                array.getTotalSize() - displacement < minCapacity)
354            {
355                // Copy array.
356                elements = new LispObject[minCapacity];
357                final int limit =
358                    Math.min(capacity, array.getTotalSize() - displacement);
359                for (int i = 0; i < limit; i++)
360                    elements[i] = array.AREF(displacement + i);
361                capacity = minCapacity;
362                array = null;
363                displacement = 0;
364                isDisplaced = false;
365            }
366        }
367    }
368
369    @Override
370    public AbstractVector adjustArray(int newCapacity,
371                                       LispObject initialElement,
372                                       LispObject initialContents)
373
374    {
375        if (initialContents != null) {
376            // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE-
377            // ARRAY. In this case none of the original contents of array
378            // appears in the resulting array."
379            LispObject[] newElements = new LispObject[newCapacity];
380            if (initialContents.listp()) {
381                LispObject list = initialContents;
382                for (int i = 0; i < newCapacity; i++) {
383                    newElements[i] = list.car();
384                    list = list.cdr();
385                }
386            } else if (initialContents.vectorp()) {
387                for (int i = 0; i < newCapacity; i++)
388                    newElements[i] = initialContents.elt(i);
389            } else
390                error(new TypeError(initialContents, Symbol.SEQUENCE));
391            elements = newElements;
392        } else {
393            if (elements == null) {
394                // Displaced array. Copy existing elements.
395                elements = new LispObject[newCapacity];
396                final int limit = Math.min(capacity, newCapacity);
397                for (int i = 0; i < limit; i++)
398                    elements[i] = array.AREF(displacement + i);
399            } else if (capacity != newCapacity) {
400                LispObject[] newElements = new LispObject[newCapacity];
401                System.arraycopy(elements, 0, newElements, 0,
402                                 Math.min(capacity, newCapacity));
403                elements = newElements;
404            }
405            // Initialize new elements (if any).
406            if (initialElement != null)
407                for (int i = capacity; i < newCapacity; i++)
408                    elements[i] = initialElement;
409        }
410        capacity = newCapacity;
411        array = null;
412        displacement = 0;
413        isDisplaced = false;
414        return this;
415    }
416
417    @Override
418    public AbstractVector adjustArray(int newCapacity,
419                                       AbstractArray displacedTo,
420                                       int displacement)
421
422    {
423        capacity = newCapacity;
424        array = displacedTo;
425        this.displacement = displacement;
426        elements = null;
427        isDisplaced = true;
428        return this;
429    }
430}
Note: See TracBrowser for help on using the repository browser.