1 /* 2 * ComplexVector_UnsignedByte32.java 3 * 4 * Copyright (C) 2002-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 // A specialized vector of element type (UNSIGNED-BYTE 32) that is displaced to 39 // another array, has a fill pointer, and/or is expressly adjustable. 40 public final class ComplexVector_UnsignedByte32 extends AbstractVector 41 { 42 private int capacity; 43 private int fillPointer = -1; // -1 indicates no fill pointer. 44 private boolean isDisplaced; 45 46 // For non-displaced arrays. 47 private LispObject[] elements; 48 49 // For displaced arrays. 50 private AbstractArray array; 51 private int displacement; 52 ComplexVector_UnsignedByte32(int capacity)53 public ComplexVector_UnsignedByte32(int capacity) 54 { 55 elements = new LispObject[capacity]; 56 for (int i = capacity; i-- > 0;) 57 elements[i] = Fixnum.ZERO; 58 this.capacity = capacity; 59 } 60 ComplexVector_UnsignedByte32(int capacity, AbstractArray array, int displacement)61 public ComplexVector_UnsignedByte32(int capacity, AbstractArray array, 62 int displacement) 63 { 64 this.capacity = capacity; 65 this.array = array; 66 this.displacement = displacement; 67 isDisplaced = true; 68 } 69 70 @Override typeOf()71 public LispObject typeOf() 72 { 73 return list(Symbol.VECTOR, UNSIGNED_BYTE_32, Fixnum.getInstance(capacity)); 74 } 75 76 @Override classOf()77 public LispObject classOf() 78 { 79 return BuiltInClass.VECTOR; 80 } 81 82 @Override hasFillPointer()83 public boolean hasFillPointer() 84 { 85 return fillPointer >= 0; 86 } 87 88 @Override getFillPointer()89 public int getFillPointer() 90 { 91 return fillPointer; 92 } 93 94 @Override setFillPointer(int n)95 public void setFillPointer(int n) 96 { 97 fillPointer = n; 98 } 99 100 @Override setFillPointer(LispObject obj)101 public void setFillPointer(LispObject obj) 102 { 103 if (obj == T) 104 fillPointer = capacity(); 105 else { 106 int n = Fixnum.getValue(obj); 107 if (n > capacity()) { 108 StringBuffer sb = new StringBuffer("The new fill pointer ("); 109 sb.append(n); 110 sb.append(") exceeds the capacity of the vector ("); 111 sb.append(capacity()); 112 sb.append(")."); 113 error(new LispError(sb.toString())); 114 } else if (n < 0) { 115 StringBuffer sb = new StringBuffer("The new fill pointer ("); 116 sb.append(n); 117 sb.append(") is negative."); 118 error(new LispError(sb.toString())); 119 } else 120 fillPointer = n; 121 } 122 } 123 124 @Override isDisplaced()125 public boolean isDisplaced() 126 { 127 return isDisplaced; 128 } 129 130 @Override arrayDisplacement()131 public LispObject arrayDisplacement() 132 { 133 LispObject value1, value2; 134 if (array != null) { 135 value1 = array; 136 value2 = Fixnum.getInstance(displacement); 137 } else { 138 value1 = NIL; 139 value2 = Fixnum.ZERO; 140 } 141 return LispThread.currentThread().setValues(value1, value2); 142 } 143 144 @Override getElementType()145 public LispObject getElementType() 146 { 147 return UNSIGNED_BYTE_32; 148 } 149 150 @Override isSimpleVector()151 public boolean isSimpleVector() 152 { 153 return false; 154 } 155 156 @Override capacity()157 public int capacity() 158 { 159 return capacity; 160 } 161 162 @Override length()163 public int length() 164 { 165 return fillPointer >= 0 ? fillPointer : capacity; 166 } 167 168 @Override elt(int index)169 public LispObject elt(int index) 170 { 171 final int limit = length(); 172 if (index < 0 || index >= limit) 173 badIndex(index, limit); 174 return AREF(index); 175 } 176 177 // Ignores fill pointer. 178 @Override AREF(int index)179 public LispObject AREF(int index) 180 { 181 if (elements != null) { 182 try { 183 return elements[index]; 184 } 185 catch (ArrayIndexOutOfBoundsException e) { 186 badIndex(index, elements.length); 187 return NIL; // Not reached. 188 } 189 } else { 190 // Displaced array. 191 if (index < 0 || index >= capacity) 192 badIndex(index, capacity); 193 return array.AREF(index + displacement); 194 } 195 } 196 197 @Override aset(int index, LispObject newValue)198 public void aset(int index, LispObject newValue) 199 { 200 if (elements != null) { 201 try { 202 elements[index] = newValue; 203 } 204 catch (ArrayIndexOutOfBoundsException e) { 205 badIndex(index, elements.length); 206 } 207 } else { 208 // Displaced array. 209 if (index < 0 || index >= capacity) 210 badIndex(index, capacity); 211 else 212 array.aset(index + displacement, newValue); 213 } 214 } 215 216 @Override subseq(int start, int end)217 public LispObject subseq(int start, int end) 218 { 219 SimpleVector v = new SimpleVector(end - start); 220 int i = start, j = 0; 221 try { 222 while (i < end) 223 v.aset(j++, AREF(i++)); 224 return v; 225 } 226 catch (ArrayIndexOutOfBoundsException e) { 227 return error(new TypeError("Array index out of bounds: " + i + ".")); 228 } 229 } 230 231 @Override fill(LispObject obj)232 public void fill(LispObject obj) 233 { 234 if (!(obj instanceof LispInteger)) { 235 type_error(obj, Symbol.INTEGER); 236 // Not reached. 237 return; 238 } 239 if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { 240 type_error(obj, UNSIGNED_BYTE_32); 241 } 242 for (int i = capacity; i-- > 0;) 243 elements[i] = obj; 244 } 245 246 @Override shrink(int n)247 public void shrink(int n) 248 { 249 if (elements != null) { 250 if (n < elements.length) { 251 LispObject[] newArray = new LispObject[n]; 252 System.arraycopy(elements, 0, newArray, 0, n); 253 elements = newArray; 254 capacity = n; 255 return; 256 } 257 if (n == elements.length) 258 return; 259 } 260 error(new LispError()); 261 } 262 263 @Override reverse()264 public LispObject reverse() 265 { 266 int length = length(); 267 SimpleVector result = new SimpleVector(length); 268 int i, j; 269 for (i = 0, j = length - 1; i < length; i++, j--) 270 result.aset(i, AREF(j)); 271 return result; 272 } 273 274 @Override nreverse()275 public LispObject nreverse() 276 { 277 if (elements != null) { 278 int i = 0; 279 int j = length() - 1; 280 while (i < j) { 281 LispObject temp = elements[i]; 282 elements[i] = elements[j]; 283 elements[j] = temp; 284 ++i; 285 --j; 286 } 287 } else { 288 // Displaced array. 289 int length = length(); 290 LispObject[] data = new LispObject[length]; 291 int i, j; 292 for (i = 0, j = length - 1; i < length; i++, j--) 293 data[i] = AREF(j); 294 elements = data; 295 capacity = length; 296 array = null; 297 displacement = 0; 298 isDisplaced = false; 299 fillPointer = -1; 300 } 301 return this; 302 } 303 304 @Override vectorPushExtend(LispObject element)305 public void vectorPushExtend(LispObject element) 306 307 { 308 if (fillPointer < 0) 309 noFillPointer(); 310 if (fillPointer >= capacity) { 311 // Need to extend vector. 312 ensureCapacity(capacity * 2 + 1); 313 } 314 aset(fillPointer, element); 315 ++fillPointer; 316 } 317 318 @Override VECTOR_PUSH_EXTEND(LispObject element)319 public LispObject VECTOR_PUSH_EXTEND(LispObject element) 320 321 { 322 vectorPushExtend(element); 323 return Fixnum.getInstance(fillPointer - 1); 324 } 325 326 @Override VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)327 public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) 328 329 { 330 int ext = Fixnum.getValue(extension); 331 if (fillPointer < 0) 332 noFillPointer(); 333 if (fillPointer >= capacity) { 334 // Need to extend vector. 335 ext = Math.max(ext, capacity + 1); 336 ensureCapacity(capacity + ext); 337 } 338 aset(fillPointer, element); 339 return Fixnum.getInstance(fillPointer++); 340 } 341 ensureCapacity(int minCapacity)342 private final void ensureCapacity(int minCapacity) 343 { 344 if (elements != null) { 345 if (capacity < minCapacity) { 346 LispObject[] newArray = new LispObject[minCapacity]; 347 System.arraycopy(elements, 0, newArray, 0, capacity); 348 elements = newArray; 349 capacity = minCapacity; 350 } 351 } else { 352 // Displaced array. 353 Debug.assertTrue(array != null); 354 if (capacity < minCapacity || 355 array.getTotalSize() - displacement < minCapacity) 356 { 357 // Copy array. 358 elements = new LispObject[minCapacity]; 359 final int limit = 360 Math.min(capacity, array.getTotalSize() - displacement); 361 for (int i = 0; i < limit; i++) 362 elements[i] = array.AREF(displacement + i); 363 capacity = minCapacity; 364 array = null; 365 displacement = 0; 366 isDisplaced = false; 367 } 368 } 369 } 370 371 @Override adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents)372 public AbstractVector adjustArray(int newCapacity, 373 LispObject initialElement, 374 LispObject initialContents) 375 376 { 377 if (initialContents != null) { 378 // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- 379 // ARRAY. In this case none of the original contents of array 380 // appears in the resulting array." 381 LispObject[] newElements = new LispObject[newCapacity]; 382 if (initialContents.listp()) { 383 LispObject list = initialContents; 384 for (int i = 0; i < newCapacity; i++) { 385 newElements[i] = list.car(); 386 list = list.cdr(); 387 } 388 } else if (initialContents.vectorp()) { 389 for (int i = 0; i < newCapacity; i++) 390 newElements[i] = initialContents.elt(i); 391 } else 392 type_error(initialContents, Symbol.SEQUENCE); 393 elements = newElements; 394 } else { 395 if (elements == null) { 396 // Displaced array. Copy existing elements. 397 elements = new LispObject[newCapacity]; 398 final int limit = Math.min(capacity, newCapacity); 399 for (int i = 0; i < limit; i++) 400 elements[i] = array.AREF(displacement + i); 401 } else if (capacity != newCapacity) { 402 LispObject[] newElements = new LispObject[newCapacity]; 403 System.arraycopy(elements, 0, newElements, 0, 404 Math.min(capacity, newCapacity)); 405 elements = newElements; 406 } 407 // Initialize new elements (if aapplicable). 408 if (initialElement != null) { 409 for (int i = capacity; i < newCapacity; i++) 410 elements[i] = initialElement; 411 } 412 } 413 capacity = newCapacity; 414 array = null; 415 displacement = 0; 416 isDisplaced = false; 417 return this; 418 } 419 420 @Override adjustArray(int newCapacity, AbstractArray displacedTo, int displacement)421 public AbstractVector adjustArray(int newCapacity, 422 AbstractArray displacedTo, 423 int displacement) 424 425 { 426 capacity = newCapacity; 427 array = displacedTo; 428 this.displacement = displacement; 429 elements = null; 430 isDisplaced = true; 431 return this; 432 } 433 } 434