source: trunk/abcl/src/org/armedbear/lisp/SimpleArray_T.java @ 12192

Last change on this file since 12192 was 11714, checked in by ehuelsmann, 16 years ago

Use the Fixnum factory instead of creating new Fixnums all over the place.

Patch by: Douglas Miles (logicmoo at gmail.com)

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