source: branches/0.16.x/abcl/src/org/armedbear/lisp/ComplexBitVector.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: 12.2 KB
Line 
1/*
2 * ComplexBitVector.java
3 *
4 * Copyright (C) 2003-2005 Peter Graves
5 * $Id: ComplexBitVector.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., 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
36public final class ComplexBitVector extends AbstractBitVector
37{
38    private int fillPointer = -1; // -1 indicates no fill pointer.
39    private boolean isDisplaced;
40
41    // For displaced bit vectors.
42    private AbstractArray array;
43    private int displacement;
44
45    public ComplexBitVector(int capacity) throws ConditionThrowable
46    {
47        this.capacity = capacity;
48        int size = capacity >>> 6;
49        if ((capacity & LONG_MASK) != 0)
50            ++size;
51        bits = new long[size];
52    }
53
54    public ComplexBitVector(int capacity, AbstractArray array, int displacement)
55    {
56        this.capacity = capacity;
57        this.array = array;
58        this.displacement = displacement;
59        isDisplaced = true;
60    }
61
62    @Override
63    public LispObject typeOf()
64    {
65        return list(Symbol.BIT_VECTOR, Fixnum.getInstance(capacity));
66    }
67
68    @Override
69    public boolean hasFillPointer()
70    {
71        return fillPointer >= 0;
72    }
73
74    @Override
75    public int getFillPointer()
76    {
77        return fillPointer;
78    }
79
80    @Override
81    public void setFillPointer(int n)
82    {
83        fillPointer = n;
84    }
85
86    @Override
87    public void setFillPointer(LispObject obj) throws ConditionThrowable
88    {
89        if (obj == T)
90            fillPointer = capacity();
91        else {
92            int n = Fixnum.getValue(obj);
93            if (n > capacity()) {
94                StringBuffer sb = new StringBuffer("The new fill pointer (");
95                sb.append(n);
96                sb.append(") exceeds the capacity of the vector (");
97                sb.append(capacity());
98                sb.append(").");
99                error(new LispError(sb.toString()));
100            } else if (n < 0) {
101                StringBuffer sb = new StringBuffer("The new fill pointer (");
102                sb.append(n);
103                sb.append(") is negative.");
104                error(new LispError(sb.toString()));
105            } else
106                fillPointer = n;
107        }
108    }
109
110    @Override
111    public LispObject arrayDisplacement() throws ConditionThrowable
112    {
113        LispObject value1, value2;
114        if (array != null) {
115            value1 = array;
116            value2 = Fixnum.getInstance(displacement);
117        } else {
118            value1 = NIL;
119            value2 = Fixnum.ZERO;
120        }
121        return LispThread.currentThread().setValues(value1, value2);
122    }
123
124    @Override
125    public int length()
126    {
127        return fillPointer >= 0 ? fillPointer : capacity;
128    }
129
130    @Override
131    public LispObject elt(int index) throws ConditionThrowable
132    {
133        if (index >= length())
134            badIndex(index, length());
135        return AREF(index);
136    }
137
138    @Override
139    public LispObject AREF(int index) throws ConditionThrowable
140    {
141        if (index < 0 || index >= capacity)
142            badIndex(index, capacity);
143        if (bits != null) {
144            int offset = index >> 6;
145            return (bits[offset] & (1L << index)) != 0 ? Fixnum.ONE : Fixnum.ZERO;
146        } else {
147            // Displaced bit vector.
148            return array.AREF(index + displacement);
149        }
150    }
151
152    @Override
153    protected int getBit(int index) throws ConditionThrowable
154    {
155        if (bits != null) {
156            int offset = index >> 6;
157            return (bits[offset] & (1L << index)) != 0 ? 1 : 0;
158        } else
159            return Fixnum.getValue(array.AREF(index + displacement));
160    }
161
162    @Override
163    public void aset(int index, LispObject newValue) throws ConditionThrowable
164    {
165        if (index < 0 || index >= capacity)
166            badIndex(index, capacity);
167        if (newValue instanceof Fixnum) {
168            switch (((Fixnum)newValue).value) {
169                case 0:
170                    if (bits != null) {
171                        final int offset = index >> 6;
172                        bits[offset] &= ~(1L << index);
173                    } else
174                        clearBit(index);
175                    return;
176                case 1:
177                    if (bits != null) {
178                        final int offset = index >> 6;
179                        bits[offset] |= 1L << index;
180                    } else
181                        setBit(index);
182                    return;
183            }
184        }
185            // Fall through...
186        type_error(newValue, Symbol.BIT);
187    }
188
189    @Override
190    protected void setBit(int index) throws ConditionThrowable
191    {
192        if (bits != null) {
193            int offset = index >> 6;
194            bits[offset] |= 1L << index;
195        } else
196            array.aset(index + displacement, Fixnum.ONE);
197    }
198
199    @Override
200    protected void clearBit(int index) throws ConditionThrowable
201    {
202        if (bits != null) {
203            int offset = index >> 6;
204            bits[offset] &= ~(1L << index);
205        } else
206            array.aset(index + displacement, Fixnum.ZERO);
207    }
208
209    @Override
210    public void shrink(int n) throws ConditionThrowable
211    {
212        if (bits != null) {
213            if (n < capacity) {
214                int size = n >>> 6;
215                if ((n & LONG_MASK) != 0)
216                    ++size;
217                if (size < bits.length) {
218                    long[] newbits = new long[size];
219                    System.arraycopy(bits, 0, newbits, 0, size);
220                    bits = newbits;
221                }
222                capacity = n;
223                return;
224            }
225            if (n == capacity)
226                return;
227        }
228        error(new LispError());
229    }
230
231    @Override
232    public boolean isSimpleVector()
233    {
234        return false;
235    }
236
237    // FIXME
238    @Override
239    public void vectorPushExtend(LispObject element) throws ConditionThrowable
240    {
241        final int fp = getFillPointer();
242        if (fp < 0)
243            noFillPointer();
244        if (fp >= capacity()) {
245            // Need to extend vector.
246            ensureCapacity(capacity() * 2 + 1);
247        }
248        aset(fp, element);
249        setFillPointer(fp + 1);
250    }
251
252    // FIXME
253    @Override
254    public LispObject VECTOR_PUSH_EXTEND(LispObject element)
255        throws ConditionThrowable
256    {
257        vectorPushExtend(element);
258        return Fixnum.getInstance(getFillPointer() - 1);
259    }
260
261    // FIXME
262    @Override
263    public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)
264        throws ConditionThrowable
265    {
266        int ext = Fixnum.getValue(extension);
267        final int fp = getFillPointer();
268        if (fp < 0)
269            noFillPointer();
270        if (fp >= capacity()) {
271            // Need to extend vector.
272            ext = Math.max(ext, capacity() + 1);
273            ensureCapacity(capacity() + ext);
274        }
275        aset(fp, element);
276        setFillPointer(fp + 1);
277        return Fixnum.getInstance(fp);
278    }
279
280    private final void ensureCapacity(int minCapacity) throws ConditionThrowable
281    {
282        if (bits != null) {
283            if (capacity < minCapacity) {
284                int size = minCapacity >>> 6;
285                if ((minCapacity & LONG_MASK) != 0)
286                    ++size;
287                long[] newBits = new long[size];
288                System.arraycopy(bits, 0, newBits, 0, bits.length);
289                bits = newBits;
290                capacity = minCapacity;
291            }
292        } else {
293            Debug.assertTrue(array != null);
294            if (capacity < minCapacity ||
295                array.getTotalSize() - displacement < minCapacity)
296            {
297                // Copy array.
298                int size = minCapacity >>> 6;
299                if ((minCapacity & LONG_MASK) != 0)
300                    ++size;
301                bits = new long[size];
302                final int limit =
303                    Math.min(capacity, array.getTotalSize() - displacement);
304                for (int i = 0; i < limit; i++) {
305                    int n = Fixnum.getValue(array.AREF(displacement + i));
306                    if (n == 1)
307                        setBit(i);
308                    else
309                        clearBit(i);
310                }
311                capacity = minCapacity;
312                array = null;
313                displacement = 0;
314                isDisplaced = false;
315            }
316        }
317    }
318
319    @Override
320    public AbstractVector adjustArray(int newCapacity,
321                                       LispObject initialElement,
322                                       LispObject initialContents)
323        throws ConditionThrowable
324    {
325        if (bits == null) {
326            // Copy array.
327            int size = capacity >>> 6;
328            if ((capacity & LONG_MASK) != 0)
329                ++size;
330            bits = new long[size];
331            for (int i = 0; i < capacity; i++) {
332                int n = Fixnum.getValue(array.AREF(displacement + i));
333                if (n == 1)
334                    setBit(i);
335                else
336                    clearBit(i);
337            }
338            array = null;
339            displacement = 0;
340            isDisplaced = false;
341        }
342        if (capacity != newCapacity) {
343            int size = newCapacity >>> 6;
344            if ((newCapacity & LONG_MASK) != 0)
345                ++size;
346            if (initialContents != null) {
347                bits = new long[size];
348                capacity = newCapacity;
349                if (initialContents.listp()) {
350                    LispObject list = initialContents;
351                    for (int i = 0; i < newCapacity; i++) {
352                        aset(i, list.car());
353                        list = list.cdr();
354                    }
355                } else if (initialContents.vectorp()) {
356                    for (int i = 0; i < newCapacity; i++)
357                        aset(i, initialContents.elt(i));
358                } else
359                    type_error(initialContents, Symbol.SEQUENCE);
360            } else {
361                long[] newBits = new long[size];
362                System.arraycopy(bits, 0, newBits, 0,
363                                 Math.min(bits.length, newBits.length));
364                bits = newBits;
365                if (newCapacity > capacity && initialElement != null) {
366                    int n = Fixnum.getValue(initialElement);
367                    if (n == 1)
368                        for (int i = capacity; i < newCapacity; i++)
369                            setBit(i);
370                    else
371                        for (int i = capacity; i < newCapacity; i++)
372                            clearBit(i);
373                }
374            }
375            capacity = newCapacity;
376        }
377        return this;
378    }
379
380    @Override
381    public AbstractVector adjustArray(int size, AbstractArray displacedTo,
382                                       int displacement)
383        throws ConditionThrowable
384    {
385        capacity = size;
386        array = displacedTo;
387        this.displacement = displacement;
388        bits = null;
389        isDisplaced = true;
390        return this;
391    }
392}
Note: See TracBrowser for help on using the repository browser.