1 /* 2 * ComplexBitVector.java 3 * 4 * Copyright (C) 2003-2005 Peter Graves 5 * $Id$ 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 34 package org.armedbear.lisp; 35 36 import static org.armedbear.lisp.Lisp.*; 37 38 public 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 ComplexBitVector(int capacity)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 ComplexBitVector(int capacity, AbstractArray array, int displacement)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 typeOf()65 public LispObject typeOf() 66 { 67 return list(Symbol.BIT_VECTOR, Fixnum.getInstance(capacity)); 68 } 69 70 @Override hasFillPointer()71 public boolean hasFillPointer() 72 { 73 return fillPointer >= 0; 74 } 75 76 @Override getFillPointer()77 public int getFillPointer() 78 { 79 return fillPointer; 80 } 81 82 @Override setFillPointer(int n)83 public void setFillPointer(int n) 84 { 85 fillPointer = n; 86 } 87 88 @Override setFillPointer(LispObject obj)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 arrayDisplacement()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 length()127 public int length() 128 { 129 return fillPointer >= 0 ? fillPointer : capacity; 130 } 131 132 @Override elt(int index)133 public LispObject elt(int index) 134 { 135 if (index >= length()) 136 badIndex(index, length()); 137 return AREF(index); 138 } 139 140 @Override AREF(int index)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 getBit(int index)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 aset(int index, LispObject newValue)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 setBit(int index)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 clearBit(int index)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 shrink(int n)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 isSimpleVector()234 public boolean isSimpleVector() 235 { 236 return false; 237 } 238 239 // FIXME 240 @Override vectorPushExtend(LispObject element)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 VECTOR_PUSH_EXTEND(LispObject element)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 VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)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 ensureCapacity(int minCapacity)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 adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents)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 adjustArray(int size, AbstractArray displacedTo, int displacement)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 } 395