1 21 22 package org.armedbear.lisp; 23 24 public final class SimpleArray extends AbstractArray 25 { 26 private final int[] dimv; 27 private final LispObject elementType; 28 private final int totalSize; 29 private final LispObject[] data; 30 31 public SimpleArray(int[] dimv, LispObject elementType) 32 { 33 this.dimv = dimv; 34 this.elementType = elementType; 35 totalSize = computeTotalSize(dimv); 36 data = new LispObject[totalSize]; 37 final LispObject initialElement; 38 if (elementType == Symbol.BIT) 39 initialElement = Fixnum.ZERO; 40 else 41 initialElement = NIL; 42 for (int i = totalSize; i-- > 0;) 43 data[i] = initialElement; 44 } 45 46 public SimpleArray(int[] dimv, 47 LispObject elementType, 48 LispObject initialContents) 49 throws ConditionThrowable 50 { 51 this.dimv = dimv; 52 this.elementType = elementType; 53 final int rank = dimv.length; 54 LispObject rest = initialContents; 55 for (int i = 0; i < rank; i++) { 56 dimv[i] = rest.length(); 57 rest = rest.elt(0); 58 } 59 totalSize = computeTotalSize(dimv); 60 data = new LispObject[totalSize]; 61 setInitialContents(0, dimv, initialContents, 0); 62 } 63 64 public SimpleArray(int rank, LispObject initialContents) 65 throws ConditionThrowable 66 { 67 if (rank < 2) 68 Debug.assertTrue(false); 69 dimv = new int[rank]; 70 this.elementType = T; 71 LispObject rest = initialContents; 72 for (int i = 0; i < rank; i++) { 73 dimv[i] = rest.length(); 74 if (rest == NIL) 75 break; 76 rest = rest.elt(0); 77 } 78 totalSize = computeTotalSize(dimv); 79 data = new LispObject[totalSize]; 80 setInitialContents(0, dimv, initialContents, 0); 81 } 82 83 private int setInitialContents(int axis, int[] dims, LispObject contents, 84 int index) 85 throws ConditionThrowable 86 { 87 if (dims.length == 0) { 88 try { 89 data[index] = contents; 90 } 91 catch (ArrayIndexOutOfBoundsException e) { 92 signal(new LispError("Bad initial contents for array.")); 93 return -1; 94 } 95 ++index; 96 } else { 97 int dim = dims[0]; 98 if (dim != contents.length()) { 99 signal(new LispError("Bad initial contents for array.")); 100 return -1; 101 } 102 int[] newDims = new int[dims.length-1]; 103 for (int i = 1; i < dims.length; i++) 104 newDims[i-1] = dims[i]; 105 if (contents.listp()) { 106 for (int i = contents.length();i-- > 0;) { 107 LispObject content = contents.car(); 108 index = 109 setInitialContents(axis + 1, newDims, content, index); 110 contents = contents.cdr(); 111 } 112 } else { 113 AbstractVector v = checkVector(contents); 114 final int length = v.length(); 115 for (int i = 0; i < length; i++) { 116 LispObject content = v.getRowMajor(i); 117 index = 118 setInitialContents(axis + 1, newDims, content, index); 119 } 120 } 121 } 122 return index; 123 } 124 125 public LispObject typeOf() 126 { 127 return list3(Symbol.SIMPLE_ARRAY, elementType, getDimensions()); 128 } 129 130 public LispClass classOf() 131 { 132 return BuiltInClass.ARRAY; 133 } 134 135 public LispObject typep(LispObject typeSpecifier) throws ConditionThrowable 136 { 137 if (typeSpecifier == Symbol.SIMPLE_ARRAY) 138 return T; 139 return super.typep(typeSpecifier); 140 } 141 142 public int getRank() 143 { 144 return dimv.length; 145 } 146 147 public LispObject getDimensions() 148 { 149 LispObject result = NIL; 150 for (int i = dimv.length; i-- > 0;) 151 result = new Cons(new Fixnum(dimv[i]), result); 152 return result; 153 } 154 155 public int getDimension(int n) throws ConditionThrowable 156 { 157 try { 158 return dimv[n]; 159 } 160 catch (ArrayIndexOutOfBoundsException e) { 161 signal(new TypeError("Bad array dimension " + n + ".")); 162 return -1; 163 } 164 } 165 166 public LispObject getElementType() 167 { 168 return elementType; 169 } 170 171 public int getTotalSize() 172 { 173 return totalSize; 174 } 175 176 public boolean isAdjustable() 177 { 178 return false; 179 } 180 181 public LispObject getRowMajor(int index) throws ConditionThrowable 182 { 183 try { 184 return data[index]; 185 } 186 catch (ArrayIndexOutOfBoundsException e) { 187 return signal(new TypeError("Bad row major index " + index + ".")); 188 } 189 } 190 191 public void setRowMajor(int index, LispObject newValue) throws ConditionThrowable 192 { 193 try { 194 data[index] = newValue; 195 } 196 catch (ArrayIndexOutOfBoundsException e) { 197 signal(new TypeError("Bad row major index " + index + ".")); 198 } 199 } 200 201 public int getRowMajorIndex(int[] subscripts) throws ConditionThrowable 202 { 203 final int rank = dimv.length; 204 if (rank != subscripts.length) { 205 StringBuffer sb = new StringBuffer ("Wrong number of subscripts ("); 206 sb.append(subscripts.length); 207 sb.append(") for array of rank "); 208 sb.append(rank); 209 sb.append('.'); 210 signal(new ProgramError(sb.toString())); 211 } 212 int sum = 0; 213 int size = 1; 214 for (int i = rank; i-- > 0;) { 215 final int dim = dimv[i]; 216 final int lastSize = size; 217 size *= dim; 218 int n = subscripts[i]; 219 if (n < 0 || n >= dim) { 220 StringBuffer sb = new StringBuffer ("Invalid index "); 221 sb.append(n); 222 sb.append(" for array "); 223 sb.append(this); 224 sb.append('.'); 225 signal(new ProgramError(sb.toString())); 226 } 227 sum += n * lastSize; 228 } 229 return sum; 230 } 231 232 public LispObject get(int[] subscripts) throws ConditionThrowable 233 { 234 try { 235 return data[getRowMajorIndex(subscripts)]; 236 } 237 catch (ArrayIndexOutOfBoundsException e) { 238 return signal(new TypeError("Bad row major index " + 239 getRowMajorIndex(subscripts) + ".")); 240 } 241 } 242 243 public void set(int[] subscripts, LispObject newValue) 244 throws ConditionThrowable 245 { 246 try { 247 data[getRowMajorIndex(subscripts)] = newValue; 248 } 249 catch (ArrayIndexOutOfBoundsException e) { 250 signal(new TypeError("Bad row major index " + 251 getRowMajorIndex(subscripts) + ".")); 252 } 253 } 254 255 public void fill(LispObject obj) 256 { 257 for (int i = totalSize; i-- > 0;) 258 data[i] = obj; 259 } 260 261 public String writeToString() throws ConditionThrowable 262 { 263 StringBuffer sb = new StringBuffer (); 264 sb.append('#'); 265 sb.append(dimv.length); 266 sb.append('A'); 267 appendContents(dimv, 0, sb); 268 return sb.toString(); 269 } 270 271 public AbstractArray adjustArray(int[] dimv, LispObject initialElement, 272 LispObject initialContents) 273 throws ConditionThrowable 274 { 275 if (initialContents != NIL) 276 return new SimpleArray(dimv, elementType, initialContents); 277 for (int i = 0; i < dimv.length; i++) { 278 if (dimv[i] != this.dimv[i]) { 279 SimpleArray newArray = new SimpleArray(dimv, elementType); 280 newArray.fill(initialElement); 281 copyArray(this, newArray); 282 return newArray; 283 } 284 } 285 return this; 287 } 288 289 private static void copyArray(AbstractArray a1, AbstractArray a2) 291 throws ConditionThrowable 292 { 293 Debug.assertTrue(a1.getRank() == a2.getRank()); 294 int[] subscripts = new int[a1.getRank()]; 295 int axis = 0; 296 copySubArray(a1, a2, subscripts, axis); 297 } 298 299 private static void copySubArray(AbstractArray a1, AbstractArray a2, 300 int[] subscripts, int axis) 301 throws ConditionThrowable 302 { 303 if (axis < subscripts.length) { 304 final int limit = 305 Math.min(a1.getDimension(axis), a2.getDimension(axis)); 306 for (int i = 0; i < limit; i++) { 307 subscripts[axis] = i; 308 copySubArray(a1, a2, subscripts, axis + 1); 309 } 310 } else { 311 int i1 = a1.getRowMajorIndex(subscripts); 312 int i2 = a2.getRowMajorIndex(subscripts); 313 a2.setRowMajor(i2, a1.getRowMajor(i1)); 314 } 315 } 316 317 public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, 318 int displacement) 319 { 320 return new ComplexArray(dimv, displacedTo, displacement); 321 } 322 } 323 | Popular Tags |