source: branches/0.20.x/abcl/src/org/armedbear/lisp/ComplexBitVector.java @ 12669

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