source: branches/0.16.x/abcl/src/org/armedbear/lisp/SimpleVector.java

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

Convert using ClassCastException? to checking instanceof.
Performance tests show this approach to be faster.
Patch by Douglas R. Miles. I modified the patch to
remove tabs, so indentation may be slightly off in places.
That's something that we need to handle separately, abcl
doesn't have a clear indentation policy.

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