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

Last change on this file was 12254, checked in by ehuelsmann, 16 years ago

Remove 'throws ConditionThrowable?' method annotations:

it's an unchecked exception now, so no need to declare it thrown.

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