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

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

Further (INCOMPLETE) work on byte vectors

GOAL: completely remove allocation of any UnsignedByte32 in

make_array.java. Surprised that it mostly works this way…

Fix directAllocation for SimpleArray_CharBuffer.

TODO: ensure that :nio-buffer argument is used in all cases.

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