1 21 22 package org.armedbear.lisp; 23 24 public final class ComplexVector extends AbstractVector 27 { 28 private int capacity; 29 private int fillPointer = -1; private boolean isDisplaced; 31 32 private LispObject[] elements; 34 35 private AbstractArray array; 37 private int displacement; 38 39 public ComplexVector(int capacity) 40 { 41 elements = new LispObject[capacity]; 42 for (int i = capacity; i-- > 0;) 43 elements[i] = NIL; 44 this.capacity = capacity; 45 } 46 47 public ComplexVector(int capacity, AbstractArray array, int displacement) 48 { 49 this.capacity = capacity; 50 this.array = array; 51 this.displacement = displacement; 52 isDisplaced = true; 53 } 54 55 public LispObject typeOf() 56 { 57 return list3(Symbol.VECTOR, T, new Fixnum(capacity)); 58 } 59 60 public LispClass classOf() 61 { 62 return BuiltInClass.VECTOR; 63 } 64 65 public boolean hasFillPointer() 66 { 67 return fillPointer >= 0; 68 } 69 70 public int getFillPointer() 71 { 72 return fillPointer; 73 } 74 75 public void setFillPointer(int n) 76 { 77 fillPointer = n; 78 } 79 80 public void setFillPointer(LispObject obj) throws ConditionThrowable 81 { 82 if (obj == T) 83 fillPointer = capacity(); 84 else { 85 int n = Fixnum.getValue(obj); 86 if (n > capacity()) { 87 StringBuffer sb = new StringBuffer ("The new fill pointer ("); 88 sb.append(n); 89 sb.append(") exceeds the capacity of the vector ("); 90 sb.append(capacity()); 91 sb.append(")."); 92 signal(new LispError(sb.toString())); 93 } else if (n < 0) { 94 StringBuffer sb = new StringBuffer ("The new fill pointer ("); 95 sb.append(n); 96 sb.append(") is negative."); 97 signal(new LispError(sb.toString())); 98 } else 99 fillPointer = n; 100 } 101 } 102 103 public boolean isDisplaced() 104 { 105 return isDisplaced; 106 } 107 108 public LispObject arrayDisplacement() throws ConditionThrowable 109 { 110 LispObject value1, value2; 111 if (array != null) { 112 value1 = array; 113 value2 = new Fixnum(displacement); 114 } else { 115 value1 = NIL; 116 value2 = Fixnum.ZERO; 117 } 118 return LispThread.currentThread().setValues(value1, value2); 119 } 120 121 public LispObject getElementType() 122 { 123 return T; 124 } 125 126 public boolean isSimpleVector() 127 { 128 return false; 129 } 130 131 public int capacity() 132 { 133 return capacity; 134 } 135 136 public int length() 137 { 138 return fillPointer >= 0 ? fillPointer : capacity; 139 } 140 141 public LispObject elt(int index) throws ConditionThrowable 142 { 143 final int limit = length(); 144 if (index < 0 || index >= limit) 145 badIndex(index, limit); 146 return getRowMajor(index); 147 } 148 149 public LispObject AREF(LispObject index) throws ConditionThrowable 152 { 153 return getRowMajor(Fixnum.getValue(index)); 154 } 155 156 public LispObject getRowMajor(int index) throws ConditionThrowable 157 { 158 if (elements != null) { 159 try { 160 return elements[index]; 161 } 162 catch (ArrayIndexOutOfBoundsException e) { 163 badIndex(index, elements.length); 164 return NIL; } 166 } else 167 return array.getRowMajor(index + displacement); 168 } 169 170 public void setRowMajor(int index, LispObject newValue) throws ConditionThrowable 171 { 172 if (elements != null) { 173 try { 174 elements[index] = newValue; 175 } 176 catch (ArrayIndexOutOfBoundsException e) { 177 badIndex(index, elements.length); 178 } 179 } else 180 array.setRowMajor(index + displacement, newValue); 181 } 182 183 public LispObject subseq(int start, int end) throws ConditionThrowable 184 { 185 SimpleVector v = new SimpleVector(end - start); 186 int i = start, j = 0; 187 try { 188 while (i < end) 189 v.setRowMajor(j++, getRowMajor(i++)); 190 return v; 191 } 192 catch (ArrayIndexOutOfBoundsException e) { 193 return signal(new TypeError("Array index out of bounds: " + i + ".")); 194 } 195 } 196 197 public void fill(LispObject obj) throws ConditionThrowable 198 { 199 for (int i = capacity; i-- > 0;) 200 elements[i] = obj; 201 } 202 203 public void shrink(int n) throws ConditionThrowable 204 { 205 if (elements != null) { 206 if (n < elements.length) { 207 LispObject[] newArray = new LispObject[n]; 208 System.arraycopy(elements, 0, newArray, 0, n); 209 elements = newArray; 210 capacity = n; 211 return; 212 } 213 if (n == elements.length) 214 return; 215 } 216 signal(new LispError()); 217 } 218 219 public LispObject reverse() throws ConditionThrowable 220 { 221 int length = length(); 222 SimpleVector result = new SimpleVector(length); 223 int i, j; 224 for (i = 0, j = length - 1; i < length; i++, j--) 225 result.setRowMajor(i, getRowMajor(j)); 226 return result; 227 } 228 229 public LispObject nreverse() throws ConditionThrowable 230 { 231 int i = 0; 232 int j = length() - 1; 233 while (i < j) { 234 LispObject temp = elements[i]; 235 elements[i] = elements[j]; 236 elements[j] = temp; 237 ++i; 238 --j; 239 } 240 return this; 241 } 242 243 public LispObject vectorPushExtend(LispObject element) 244 throws ConditionThrowable 245 { 246 if (fillPointer < 0) 247 noFillPointer(); 248 if (fillPointer >= capacity) { 249 ensureCapacity(capacity * 2 + 1); 251 } 252 setRowMajor(fillPointer, element); 253 return new Fixnum(fillPointer++); 254 } 255 256 public LispObject vectorPushExtend(LispObject element, LispObject extension) 257 throws ConditionThrowable 258 { 259 int ext = Fixnum.getValue(extension); 260 if (fillPointer < 0) 261 noFillPointer(); 262 if (fillPointer >= capacity) { 263 ext = Math.max(ext, capacity + 1); 265 ensureCapacity(capacity + ext); 266 } 267 setRowMajor(fillPointer, element); 268 return new Fixnum(fillPointer++); 269 } 270 271 private final void ensureCapacity(int minCapacity) throws ConditionThrowable 272 { 273 if (elements != null) { 274 if (capacity < minCapacity) { 275 LispObject[] newArray = new LispObject[minCapacity]; 276 System.arraycopy(elements, 0, newArray, 0, capacity); 277 elements = newArray; 278 capacity = minCapacity; 279 } 280 } else { 281 Debug.assertTrue(array != null); 282 if (array.getTotalSize() - displacement < minCapacity) { 283 elements = new LispObject[minCapacity]; 285 final int limit = array.getTotalSize() - displacement; 286 for (int i = 0; i < limit; i++) 287 elements[i] = array.getRowMajor(displacement + i); 288 capacity = minCapacity; 289 array = null; 290 displacement = 0; 291 isDisplaced = false; 292 } 293 } 294 } 295 296 public AbstractVector adjustVector(int newCapacity, 297 LispObject initialElement, 298 LispObject initialContents) 299 throws ConditionThrowable 300 { 301 if (initialContents != NIL) { 302 LispObject[] newElements = new LispObject[newCapacity]; 306 if (initialContents.listp()) { 307 LispObject list = initialContents; 308 for (int i = 0; i < newCapacity; i++) { 309 newElements[i] = list.car(); 310 list = list.cdr(); 311 } 312 } else if (initialContents.vectorp()) { 313 for (int i = 0; i < newCapacity; i++) 314 newElements[i] = initialContents.elt(i); 315 } else 316 signal(new TypeError(initialContents, Symbol.SEQUENCE)); 317 elements = newElements; 318 } else { 319 if (elements == null) { 320 elements = new LispObject[newCapacity]; 322 final int limit = Math.min(capacity, newCapacity); 323 for (int i = 0; i < limit; i++) 324 elements[i] = array.getRowMajor(displacement + i); 325 } else if (capacity != newCapacity) { 326 LispObject[] newElements = new LispObject[newCapacity]; 327 System.arraycopy(elements, 0, newElements, 0, 328 Math.min(capacity, newCapacity)); 329 elements = newElements; 330 } 331 for (int i = capacity; i < newCapacity; i++) 333 elements[i] = initialElement; 334 } 335 capacity = newCapacity; 336 array = null; 337 displacement = 0; 338 isDisplaced = false; 339 return this; 340 } 341 342 public AbstractVector adjustVector(int newCapacity, 343 AbstractArray displacedTo, 344 int displacement) 345 throws ConditionThrowable 346 { 347 capacity = newCapacity; 348 array = displacedTo; 349 this.displacement = displacement; 350 elements = null; 351 isDisplaced = true; 352 return this; 353 } 354 } 355 | Popular Tags |