KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > SimpleArray


1 /*
2  * SimpleArray.java
3  *
4  * Copyright (C) 2003-2004 Peter Graves
5  * $Id: SimpleArray.java,v 1.8 2004/05/27 20:29:41 piso Exp $
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
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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc sb = new StringBuffer JavaDoc("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 JavaDoc sb = new StringBuffer JavaDoc("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 JavaDoc 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 JavaDoc 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 JavaDoc writeToString() throws ConditionThrowable
262     {
263         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
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         // New dimensions are identical to old dimensions.
286
return this;
287     }
288
289     // Copy a1 to a2 for index tuples that are valid for both arrays.
290
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