source: branches/1.1.x/src/org/armedbear/lisp/ComplexBitVector.java

Last change on this file 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.