source: trunk/abcl/src/org/armedbear/lisp/ComplexVector_UnsignedByte32.java @ 11714

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

Use the Fixnum factory instead of creating new Fixnums all over the place.

Patch by: Douglas Miles (logicmoo at gmail.com)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.1 KB
Line 
1/*
2 * ComplexVector_UnsignedByte32.java
3 *
4 * Copyright (C) 2002-2005 Peter Graves
5 * $Id: ComplexVector_UnsignedByte32.java 11714 2009-03-23 20:05:37Z 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 specialized vector of element type (UNSIGNED-BYTE 32) that is displaced to
37// another array, has a fill pointer, and/or is expressly adjustable.
38public final class ComplexVector_UnsignedByte32 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_UnsignedByte32(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_UnsignedByte32(int capacity, AbstractArray array,
60                                        int displacement)
61    {
62        this.capacity = capacity;
63        this.array = array;
64        this.displacement = displacement;
65        isDisplaced = true;
66    }
67
68    @Override
69    public LispObject typeOf()
70    {
71        return list(Symbol.VECTOR, UNSIGNED_BYTE_32, Fixnum.getInstance(capacity));
72    }
73
74    @Override
75    public LispObject classOf()
76    {
77        return BuiltInClass.VECTOR;
78    }
79
80    @Override
81    public boolean hasFillPointer()
82    {
83        return fillPointer >= 0;
84    }
85
86    @Override
87    public int getFillPointer()
88    {
89        return fillPointer;
90    }
91
92    @Override
93    public void setFillPointer(int n)
94    {
95        fillPointer = n;
96    }
97
98    @Override
99    public void setFillPointer(LispObject obj) throws ConditionThrowable
100    {
101        if (obj == T)
102            fillPointer = capacity();
103        else {
104            int n = Fixnum.getValue(obj);
105            if (n > capacity()) {
106                StringBuffer sb = new StringBuffer("The new fill pointer (");
107                sb.append(n);
108                sb.append(") exceeds the capacity of the vector (");
109                sb.append(capacity());
110                sb.append(").");
111                error(new LispError(sb.toString()));
112            } else if (n < 0) {
113                StringBuffer sb = new StringBuffer("The new fill pointer (");
114                sb.append(n);
115                sb.append(") is negative.");
116                error(new LispError(sb.toString()));
117            } else
118                fillPointer = n;
119        }
120    }
121
122    @Override
123    public boolean isDisplaced()
124    {
125        return isDisplaced;
126    }
127
128    @Override
129    public LispObject arrayDisplacement() throws ConditionThrowable
130    {
131        LispObject value1, value2;
132        if (array != null) {
133            value1 = array;
134            value2 = Fixnum.getInstance(displacement);
135        } else {
136            value1 = NIL;
137            value2 = Fixnum.ZERO;
138        }
139        return LispThread.currentThread().setValues(value1, value2);
140    }
141
142    @Override
143    public LispObject getElementType()
144    {
145        return UNSIGNED_BYTE_32;
146    }
147
148    @Override
149    public boolean isSimpleVector()
150    {
151        return false;
152    }
153
154    @Override
155    public int capacity()
156    {
157        return capacity;
158    }
159
160    @Override
161    public int length()
162    {
163        return fillPointer >= 0 ? fillPointer : capacity;
164    }
165
166    @Override
167    public LispObject elt(int index) throws ConditionThrowable
168    {
169        final int limit = length();
170        if (index < 0 || index >= limit)
171            badIndex(index, limit);
172        return AREF(index);
173    }
174
175    // Ignores fill pointer.
176    @Override
177    public LispObject AREF(int index) throws ConditionThrowable
178    {
179        if (elements != null) {
180            try {
181                return elements[index];
182            }
183            catch (ArrayIndexOutOfBoundsException e) {
184                badIndex(index, elements.length);
185                return NIL; // Not reached.
186            }
187        } else {
188            // Displaced array.
189            if (index < 0 || index >= capacity)
190                badIndex(index, capacity);
191            return array.AREF(index + displacement);
192        }
193    }
194
195    // Ignores fill pointer.
196    // FIXME inline
197    @Override
198    public LispObject AREF(LispObject index) throws ConditionThrowable
199    {
200        return AREF(Fixnum.getValue(index));
201    }
202
203    @Override
204    public void aset(int index, LispObject newValue) throws ConditionThrowable
205    {
206        if (elements != null) {
207            try {
208                elements[index] = newValue;
209            }
210            catch (ArrayIndexOutOfBoundsException e) {
211                badIndex(index, elements.length);
212            }
213        } else {
214            // Displaced array.
215            if (index < 0 || index >= capacity)
216                badIndex(index, capacity);
217            else
218                array.aset(index + displacement, newValue);
219        }
220    }
221
222    @Override
223    public LispObject subseq(int start, int end) throws ConditionThrowable
224    {
225        SimpleVector v = new SimpleVector(end - start);
226        int i = start, j = 0;
227        try {
228            while (i < end)
229                v.aset(j++, AREF(i++));
230            return v;
231        }
232        catch (ArrayIndexOutOfBoundsException e) {
233            return error(new TypeError("Array index out of bounds: " + i + "."));
234        }
235    }
236
237    @Override
238    public void fill(LispObject obj) throws ConditionThrowable
239    {
240        for (int i = capacity; i-- > 0;)
241            elements[i] = obj;
242    }
243
244    @Override
245    public void shrink(int n) throws ConditionThrowable
246    {
247        if (elements != null) {
248            if (n < elements.length) {
249                LispObject[] newArray = new LispObject[n];
250                System.arraycopy(elements, 0, newArray, 0, n);
251                elements = newArray;
252                capacity = n;
253                return;
254            }
255            if (n == elements.length)
256                return;
257        }
258        error(new LispError());
259    }
260
261    @Override
262    public LispObject reverse() throws ConditionThrowable
263    {
264        int length = length();
265        SimpleVector result = new SimpleVector(length);
266        int i, j;
267        for (i = 0, j = length - 1; i < length; i++, j--)
268            result.aset(i, AREF(j));
269        return result;
270    }
271
272    @Override
273    public LispObject nreverse() throws ConditionThrowable
274    {
275        if (elements != null) {
276            int i = 0;
277            int j = length() - 1;
278            while (i < j) {
279                LispObject temp = elements[i];
280                elements[i] = elements[j];
281                elements[j] = temp;
282                ++i;
283                --j;
284            }
285        } else {
286            // Displaced array.
287            int length = length();
288            LispObject[] data = new LispObject[length];
289            int i, j;
290            for (i = 0, j = length - 1; i < length; i++, j--)
291                data[i] = AREF(j);
292            elements = data;
293            capacity = length;
294            array = null;
295            displacement = 0;
296            isDisplaced = false;
297            fillPointer = -1;
298        }
299        return this;
300    }
301
302    @Override
303    public void vectorPushExtend(LispObject element)
304        throws ConditionThrowable
305    {
306        if (fillPointer < 0)
307            noFillPointer();
308        if (fillPointer >= capacity) {
309            // Need to extend vector.
310            ensureCapacity(capacity * 2 + 1);
311        }
312        aset(fillPointer, element);
313        ++fillPointer;
314    }
315
316    @Override
317    public LispObject VECTOR_PUSH_EXTEND(LispObject element)
318        throws ConditionThrowable
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        throws ConditionThrowable
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) throws ConditionThrowable
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        throws ConditionThrowable
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 aapplicable).
406            if (initialElement != null) {
407                for (int i = capacity; i < newCapacity; i++)
408                    elements[i] = initialElement;
409            }
410        }
411        capacity = newCapacity;
412        array = null;
413        displacement = 0;
414        isDisplaced = false;
415        return this;
416    }
417
418    @Override
419    public AbstractVector adjustArray(int newCapacity,
420                                       AbstractArray displacedTo,
421                                       int displacement)
422        throws ConditionThrowable
423    {
424        capacity = newCapacity;
425        array = displacedTo;
426        this.displacement = displacement;
427        elements = null;
428        isDisplaced = true;
429        return this;
430    }
431}
Note: See TracBrowser for help on using the repository browser.