source: trunk/abcl/src/org/armedbear/lisp/SimpleArray_ByteBuffer.java

Last change on this file was 15350, checked in by Mark Evenson, 4 years ago

Refactor naming for coerce methods

File size: 10.1 KB
Line 
1/*
2 * SimpleArray_ByteBuffer.java
3 *
4 * Copyright (C) 2020 easye
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 * As a special exception, the copyright holders of this library give you
21 * permission to link this library with independent modules to produce an
22 * executable, regardless of the license terms of these independent
23 * modules, and to copy and distribute the resulting executable under
24 * terms of your choice, provided that you also meet, for each linked
25 * independent module, the terms and conditions of the license of that
26 * module.  An independent module is a module which is not derived from
27 * or based on this library.  If you modify this library, you may extend
28 * this exception to your version of the library, but you are not
29 * obligated to do so.  If you do not wish to do so, delete this
30 * exception statement from your version.
31 */
32
33package org.armedbear.lisp;
34
35import static org.armedbear.lisp.Lisp.*;
36
37import java.nio.ByteBuffer;
38
39public final class SimpleArray_ByteBuffer
40  extends AbstractArray
41{
42  private final int[] dimv;
43  private final int totalSize;
44  final ByteBuffer data;
45  private boolean directAllocation;
46
47  public SimpleArray_ByteBuffer(int[] dimv) {
48    this(dimv, false);
49  }
50
51  public SimpleArray_ByteBuffer(int[] dimv, boolean directAllocation) {
52    this.dimv = dimv;
53    this.directAllocation = directAllocation;
54    totalSize = computeTotalSize(dimv);
55    if (directAllocation) { 
56      data = ByteBuffer.allocateDirect(totalSize);
57    } else {
58      data = ByteBuffer.allocate(totalSize);
59    }
60  }
61
62  public SimpleArray_ByteBuffer(int[] dimv, LispObject initialContents) {
63    this(dimv, initialContents, false);
64  }
65
66  public SimpleArray_ByteBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) {
67    this.dimv = dimv;
68    final int rank = dimv.length;
69    this.directAllocation = directAllocation;
70    LispObject rest = initialContents;
71    for (int i = 0; i < rank; i++) {
72      dimv[i] = rest.length();
73      rest = rest.elt(0);
74    }
75    totalSize = computeTotalSize(dimv);
76    if (directAllocation) {
77      data = ByteBuffer.allocateDirect(totalSize);
78    } else {
79      data = ByteBuffer.allocate(totalSize);
80    }
81    setInitialContents(0, dimv, initialContents, 0);
82  }
83
84  public SimpleArray_ByteBuffer(int rank, LispObject initialContents) {
85    this(rank, initialContents, false);
86  }
87 
88  public SimpleArray_ByteBuffer(int rank, LispObject initialContents, boolean directAllocation) {
89    if (rank < 2) {
90      Debug.assertTrue(false);
91    }
92    dimv = new int[rank];
93    LispObject rest = initialContents;
94    for (int i = 0; i < rank; i++) {
95      dimv[i] = rest.length();
96      if (rest == NIL || rest.length() == 0)
97        break;
98      rest = rest.elt(0);
99    }
100    totalSize = computeTotalSize(dimv);
101    if (directAllocation) {
102      data = ByteBuffer.allocateDirect(totalSize);
103    } else {
104      data = ByteBuffer.allocate(totalSize);
105    }
106    setInitialContents(0, dimv, initialContents, 0);
107  }
108
109  private int setInitialContents(int axis, int[] dims, LispObject contents,
110                                 int index) {
111    if (dims.length == 0) {
112      try {
113        data.put(index, coerceToJavaByte(contents));
114      } catch (IndexOutOfBoundsException e) {
115        error(new LispError("Bad initial contents for array."));
116        return -1;
117      }
118      ++index;
119    } else {
120      int dim = dims[0];
121      if (dim != contents.length()) {
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        for (int i = contents.length();i-- > 0;) {
130          LispObject content = contents.car();
131          index
132            = setInitialContents(axis + 1, newDims, content, index);
133          contents = contents.cdr();
134        }
135      } else {
136        AbstractVector v = checkVector(contents);
137        final int length = v.length();
138        for (int i = 0; i < length; i++) {
139          LispObject content = v.AREF(i);
140          index
141            = setInitialContents(axis + 1, newDims, content, index);
142        }
143      }
144    }
145    return index;
146  }
147
148  @Override
149  public LispObject typeOf() {
150    return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_8, getDimensions());
151  }
152
153  @Override
154  public LispObject classOf() {
155    return BuiltInClass.SIMPLE_ARRAY;
156  }
157
158  @Override
159  public LispObject typep(LispObject typeSpecifier) {
160    if (typeSpecifier == Symbol.SIMPLE_ARRAY)
161      return T;
162    if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY)
163      return T;
164    return super.typep(typeSpecifier);
165  }
166
167  @Override
168  public int getRank() {
169    return dimv.length;
170  }
171
172  @Override
173  public LispObject getDimensions() {
174    LispObject result = NIL;
175    for (int i = dimv.length; i-- > 0;)
176      result = new Cons(Fixnum.getInstance(dimv[i]), result);
177    return result;
178  }
179
180  @Override
181  public int getDimension(int n) {
182    try {
183      return dimv[n];
184    } catch (ArrayIndexOutOfBoundsException e) {
185      error(new TypeError("Bad array dimension " + n + "."));
186      return -1;
187    }
188  }
189
190  @Override
191  public LispObject getElementType() {
192    return UNSIGNED_BYTE_8;
193  }
194
195  @Override
196  public int getTotalSize() {
197    return totalSize;
198  }
199
200  @Override
201  public boolean isAdjustable() {
202    return false;
203  }
204
205  @Override
206  public LispObject AREF(int index) {
207    try {
208      return coerceFromJavaByte(data.get(index));
209    } catch (IndexOutOfBoundsException e) {
210      return error(new TypeError("Bad row major index " + index + "."));
211    }
212  }
213
214  @Override
215  public void aset(int index, LispObject newValue) {
216    try {
217      data.put(index, coerceToJavaByte(newValue));
218    } catch (IndexOutOfBoundsException e) {
219      error(new TypeError("Bad row major index " + index + "."));
220    }
221  }
222
223  @Override
224  public int getRowMajorIndex(int[] subscripts) {
225    final int rank = dimv.length;
226    if (rank != subscripts.length) {
227      StringBuffer sb = new StringBuffer("Wrong number of subscripts (");
228      sb.append(subscripts.length);
229      sb.append(") for array of rank ");
230      sb.append(rank);
231      sb.append('.');
232      program_error(sb.toString());
233    }
234    int sum = 0;
235    int size = 1;
236    for (int i = rank; i-- > 0;) {
237      final int dim = dimv[i];
238      final int lastSize = size;
239      size *= dim;
240      int n = subscripts[i];
241      if (n < 0 || n >= dim) {
242        StringBuffer sb = new StringBuffer("Invalid index ");
243        sb.append(n);
244        sb.append(" for array ");
245        sb.append(this);
246        sb.append('.');
247        program_error(sb.toString());
248      }
249      sum += n * lastSize;
250    }
251    return sum;
252  }
253
254  @Override
255  public LispObject get(int[] subscripts) {
256    try {
257      return coerceFromJavaByte(data.get(getRowMajorIndex(subscripts)));
258    } catch (IndexOutOfBoundsException e) {
259      return error(new TypeError("Bad row major index " +
260                                 getRowMajorIndex(subscripts) + "."));
261    }
262  }
263
264  @Override
265  public void set(int[] subscripts, LispObject newValue) {
266    try {
267      data.put(getRowMajorIndex(subscripts),coerceToJavaByte(newValue));
268    } catch (IndexOutOfBoundsException e) {
269      error(new TypeError("Bad row major index " +
270                          getRowMajorIndex(subscripts) + "."));
271    }
272  }
273
274  @Override
275  public void fill(LispObject obj) {
276    if (!(obj instanceof Fixnum)) {
277      type_error(obj, Symbol.FIXNUM);
278      // Not reached.
279      return;
280    }
281    int n = ((Fixnum) obj).value;
282    if (n < 0 || n > 255) {
283      type_error(obj, UNSIGNED_BYTE_8);
284      // Not reached.
285      return;
286    }
287    for (int i = totalSize; i-- > 0;)
288      data.put(i, (byte) n);
289  }
290
291  @Override
292  public String printObject() {
293    if (Symbol.PRINT_READABLY.symbolValue() != NIL) {
294      error(new PrintNotReadable(list(Keyword.OBJECT, this)));
295      // Not reached.
296      return null;
297    }
298    return printObject(dimv);
299  }
300
301  public AbstractArray adjustArray(int[] dimv, LispObject initialElement,
302                                   LispObject initialContents) {
303    if (initialContents != null)
304      return new SimpleArray_ByteBuffer(dimv, initialContents);
305    for (int i = 0; i < dimv.length; i++) {
306      if (dimv[i] != this.dimv[i]) {
307        SimpleArray_ByteBuffer newArray
308          = new SimpleArray_ByteBuffer(dimv);
309        if (initialElement != null)
310          newArray.fill(initialElement);
311        copyArray(this, newArray);
312        return newArray;
313      }
314    }
315    // New dimensions are identical to old dimensions.
316    return this;
317  }
318
319  // Copy a1 to a2 for index tuples that are valid for both arrays.
320  static void copyArray(AbstractArray a1, AbstractArray a2) {
321    Debug.assertTrue(a1.getRank() == a2.getRank());
322    int[] subscripts = new int[a1.getRank()];
323    int axis = 0;
324    copySubArray(a1, a2, subscripts, axis);
325  }
326
327  private static void copySubArray(AbstractArray a1, AbstractArray a2,
328                                   int[] subscripts, int axis) {
329    if (axis < subscripts.length) {
330      final int limit
331        = Math.min(a1.getDimension(axis), a2.getDimension(axis));
332      for (int i = 0; i < limit; i++) {
333        subscripts[axis] = i;
334        copySubArray(a1, a2, subscripts, axis + 1);
335      }
336    } else {
337      int i1 = a1.getRowMajorIndex(subscripts);
338      int i2 = a2.getRowMajorIndex(subscripts);
339      a2.aset(i2, a1.AREF(i1));
340    }
341  }
342
343  public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo,
344                                   int displacement) {
345    return new ComplexArray(dimv, displacedTo, displacement);
346  }
347}
Note: See TracBrowser for help on using the repository browser.