source: branches/streams/abcl/src/org/armedbear/lisp/SimpleArray_T.java

Last change on this file was 14465, checked in by rschlatte, 12 years ago

new method program_error, analogous to type_error

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.0 KB
Line 
1/*
2 * SimpleArray_T.java
3 *
4 * Copyright (C) 2003-2007 Peter Graves
5 * $Id: SimpleArray_T.java 14465 2013-04-24 12:50:37Z rschlatte $
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38public final class SimpleArray_T extends AbstractArray
39{
40  private final int[] dimv;
41  private final LispObject elementType;
42  private final int totalSize;
43  final LispObject[] data;
44
45  public SimpleArray_T(int[] dimv, LispObject elementType)
46  {
47    this.dimv = dimv;
48    this.elementType = elementType;
49    totalSize = computeTotalSize(dimv);
50    data = new LispObject[totalSize];
51    for (int i = totalSize; i-- > 0;)
52      data[i] = Fixnum.ZERO;
53  }
54
55  public SimpleArray_T(int[] dimv,
56                       LispObject elementType,
57                       LispObject initialContents)
58
59  {
60    this.dimv = dimv;
61    this.elementType = elementType;
62    final int rank = dimv.length;
63    LispObject rest = initialContents;
64    for (int i = 0; i < rank; i++)
65      {
66        dimv[i] = rest.length();
67        rest = rest.elt(0);
68      }
69    totalSize = computeTotalSize(dimv);
70    data = new LispObject[totalSize];
71    setInitialContents(0, dimv, initialContents, 0);
72  }
73
74  public SimpleArray_T(int rank, LispObject initialContents)
75
76  {
77    if (rank < 2)
78      Debug.assertTrue(false);
79    dimv = new int[rank];
80    this.elementType = T;
81    LispObject rest = initialContents;
82    for (int i = 0; i < rank; i++)
83      {
84        dimv[i] = rest.length();
85        if (rest == NIL || rest.length() == 0)
86          break;
87        rest = rest.elt(0);
88      }
89    totalSize = computeTotalSize(dimv);
90    data = new LispObject[totalSize];
91    setInitialContents(0, dimv, initialContents, 0);
92  }
93
94  public SimpleArray_T(final int[] dimv, final LispObject[] initialData,
95          final LispObject elementType) {
96      this.dimv = dimv;
97      this.elementType = elementType;
98      this.data = initialData;
99      this.totalSize = computeTotalSize(dimv);
100  }
101
102  private int setInitialContents(int axis, int[] dims, LispObject contents,
103                                 int index)
104
105  {
106    if (dims.length == 0)
107      {
108        try
109          {
110            data[index] = contents;
111          }
112        catch (ArrayIndexOutOfBoundsException e)
113          {
114            error(new LispError("Bad initial contents for array."));
115            return -1;
116          }
117        ++index;
118      }
119    else
120      {
121        int dim = dims[0];
122        if (dim != contents.length())
123          {
124            error(new LispError("Bad initial contents for array."));
125            return -1;
126          }
127        int[] newDims = new int[dims.length-1];
128        for (int i = 1; i < dims.length; i++)
129          newDims[i-1] = dims[i];
130        if (contents.listp())
131          {
132            for (int i = contents.length();i-- > 0;)
133              {
134                LispObject content = contents.car();
135                index =
136                  setInitialContents(axis + 1, newDims, content, index);
137                contents = contents.cdr();
138              }
139          }
140        else
141          {
142            AbstractVector v = checkVector(contents);
143            final int length = v.length();
144            for (int i = 0; i < length; i++)
145              {
146                LispObject content = v.AREF(i);
147                index =
148                  setInitialContents(axis + 1, newDims, content, index);
149              }
150          }
151      }
152    return index;
153  }
154
155  @Override
156  public LispObject typeOf()
157  {
158    return list(Symbol.SIMPLE_ARRAY, elementType, getDimensions());
159  }
160
161  @Override
162  public LispObject classOf()
163  {
164    return BuiltInClass.SIMPLE_ARRAY;
165  }
166
167  @Override
168  public LispObject typep(LispObject typeSpecifier)
169  {
170    if (typeSpecifier == Symbol.SIMPLE_ARRAY)
171      return T;
172    if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY)
173      return T;
174    return super.typep(typeSpecifier);
175  }
176
177  @Override
178  public int getRank()
179  {
180    return dimv.length;
181  }
182
183  @Override
184  public LispObject getDimensions()
185  {
186    LispObject result = NIL;
187    for (int i = dimv.length; i-- > 0;)
188      result = new Cons(Fixnum.getInstance(dimv[i]), result);
189    return result;
190  }
191
192  @Override
193  public int getDimension(int n)
194  {
195    try
196      {
197        return dimv[n];
198      }
199    catch (ArrayIndexOutOfBoundsException e)
200      {
201        error(new TypeError("Bad array dimension " + n + "."));
202        return -1;
203      }
204  }
205
206  @Override
207  public LispObject getElementType()
208  {
209    return elementType;
210  }
211
212  @Override
213  public int getTotalSize()
214  {
215    return totalSize;
216  }
217
218  @Override
219  public boolean isAdjustable()
220  {
221    return false;
222  }
223
224  @Override
225  public LispObject AREF(int index)
226  {
227    try
228      {
229        return data[index];
230      }
231    catch (ArrayIndexOutOfBoundsException e)
232      {
233        return error(new TypeError("Bad row major index " + index + "."));
234      }
235  }
236
237  @Override
238  public void aset(int index, LispObject newValue)
239  {
240    try
241      {
242        data[index] = newValue;
243      }
244    catch (ArrayIndexOutOfBoundsException e)
245      {
246        error(new TypeError("Bad row major index " + index + "."));
247      }
248  }
249
250  @Override
251  public int getRowMajorIndex(int[] subscripts)
252  {
253    final int rank = dimv.length;
254    if (rank != subscripts.length)
255      {
256        StringBuilder sb = new StringBuilder("Wrong number of subscripts (");
257        sb.append(subscripts.length);
258        sb.append(") for array of rank ");
259        sb.append(rank);
260        sb.append('.');
261        program_error(sb.toString());
262      }
263    int sum = 0;
264    int size = 1;
265    for (int i = rank; i-- > 0;)
266      {
267        final int dim = dimv[i];
268        final int lastSize = size;
269        size *= dim;
270        int n = subscripts[i];
271        if (n < 0 || n >= dim)
272          {
273            StringBuilder sb = new StringBuilder("Invalid index ");
274            sb.append(n);
275            sb.append(" for array ");
276            sb.append(this);
277            sb.append('.');
278            program_error(sb.toString());
279          }
280        sum += n * lastSize;
281      }
282    return sum;
283  }
284
285  @Override
286  public LispObject get(int[] subscripts)
287  {
288    try
289      {
290        return data[getRowMajorIndex(subscripts)];
291      }
292    catch (ArrayIndexOutOfBoundsException e)
293      {
294        return error(new TypeError("Bad row major index " +
295                                   getRowMajorIndex(subscripts) + "."));
296      }
297  }
298
299  @Override
300  public void set(int[] subscripts, LispObject newValue)
301
302  {
303    try
304      {
305        data[getRowMajorIndex(subscripts)] = newValue;
306      }
307    catch (ArrayIndexOutOfBoundsException e)
308      {
309        error(new TypeError("Bad row major index " +
310                            getRowMajorIndex(subscripts) + "."));
311      }
312  }
313
314  @Override
315  public void fill(LispObject obj)
316  {
317    for (int i = totalSize; i-- > 0;)
318      data[i] = obj;
319  }
320
321  @Override
322  public String printObject()
323  {
324    return printObject(dimv);
325  }
326
327  @Override
328  public AbstractArray adjustArray(int[] dimv, LispObject initialElement,
329                                   LispObject initialContents)
330
331  {
332    if (initialContents != null)
333      return new SimpleArray_T(dimv, elementType, initialContents);
334    for (int i = 0; i < dimv.length; i++)
335      {
336        if (dimv[i] != this.dimv[i])
337          {
338            SimpleArray_T newArray = new SimpleArray_T(dimv, elementType);
339            if (initialElement != null)
340                newArray.fill(initialElement);
341            copyArray(this, newArray);
342            return newArray;
343          }
344      }
345    // New dimensions are identical to old dimensions, yet
346    // we're not mutable, so, we need to return a new array
347    return new SimpleArray_T(dimv, data.clone(), elementType);
348  }
349
350  // Copy a1 to a2 for index tuples that are valid for both arrays.
351  static void copyArray(AbstractArray a1, AbstractArray a2)
352
353  {
354    Debug.assertTrue(a1.getRank() == a2.getRank());
355    int[] subscripts = new int[a1.getRank()];
356    int axis = 0;
357    copySubArray(a1, a2, subscripts, axis);
358  }
359
360  private static void copySubArray(AbstractArray a1, AbstractArray a2,
361                                   int[] subscripts, int axis)
362
363  {
364    if (axis < subscripts.length)
365      {
366        final int limit =
367          Math.min(a1.getDimension(axis), a2.getDimension(axis));
368        for (int i = 0; i < limit; i++)
369          {
370            subscripts[axis] = i;
371            copySubArray(a1, a2, subscripts, axis + 1);
372          }
373      }
374    else
375      {
376        int i1 = a1.getRowMajorIndex(subscripts);
377        int i2 = a2.getRowMajorIndex(subscripts);
378        a2.aset(i2, a1.AREF(i1));
379      }
380  }
381
382  @Override
383  public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo,
384                                   int displacement)
385  {
386    return new ComplexArray(dimv, displacedTo, displacement);
387  }
388}
Note: See TracBrowser for help on using the repository browser.