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

Last change on this file was 15734, checked in by Mark Evenson, 8 months ago

Implement vector-to-vector REPLACE as a primitive

File size: 9.6 KB
Line 
1/*
2 * BasicVector_IntBuffer.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.IntBuffer;
38import java.nio.ByteBuffer;
39
40// A basic vector is a specialized vector that is not displaced to another
41// array, has no fill pointer, and is not expressly adjustable.
42public final class BasicVector_IntBuffer
43  extends AbstractVector
44{
45  private int capacity;
46  private IntBuffer elements;
47  private boolean directAllocation;
48
49  public BasicVector_IntBuffer(int capacity) {
50    this(capacity, false);
51  }
52
53  public BasicVector_IntBuffer(int capacity, boolean directAllocation) {
54    this.directAllocation = directAllocation;
55    if (directAllocation) {
56      ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4);
57      elements = b.asIntBuffer();
58    } else {
59      elements = IntBuffer.allocate(capacity);
60    }
61    this.capacity = capacity;
62  }
63
64  public BasicVector_IntBuffer(LispObject[] array, boolean directAllocation) {
65    capacity = array.length;
66    this.directAllocation = directAllocation;
67    if (directAllocation) {
68      ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4);
69      elements = b.asIntBuffer();
70    } else {
71      elements = IntBuffer.allocate(capacity);
72    }
73    for (int i = array.length; i-- > 0;) {
74      // FIXME: if  LispObeject is a number that can't fit into an int
75      elements.put(i, (int)(array[i].longValue() & 0xffffffffL)); 
76    }
77  }
78
79  public BasicVector_IntBuffer(ByteBuffer buffer, boolean directAllocation) {
80    this.directAllocation = directAllocation;
81    elements = buffer.asIntBuffer();
82    capacity = ((java.nio.Buffer)buffer).limit() / 4;
83  }
84
85  public BasicVector_IntBuffer(IntBuffer buffer) {
86    this(buffer, false);
87  }
88
89  public BasicVector_IntBuffer(IntBuffer buffer, boolean directAllocation) {
90    this.directAllocation = directAllocation;
91    elements = buffer;
92    capacity = ((java.nio.Buffer)buffer).limit();
93  }
94
95  @Override
96  public LispObject typeOf() {
97    return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32,
98                new Cons(Fixnum.getInstance(capacity)));
99  }
100
101  @Override
102  public LispObject classOf() {
103    return BuiltInClass.VECTOR;
104  }
105
106  @Override
107  public LispObject typep(LispObject type) {
108    if (type == Symbol.SIMPLE_ARRAY)
109      return T;
110    if (type == BuiltInClass.SIMPLE_ARRAY)
111      return T;
112    return super.typep(type);
113  }
114
115  @Override
116  public LispObject getElementType() {
117    return UNSIGNED_BYTE_32;
118  }
119
120  @Override
121  public boolean isSimpleVector() {
122    return false;
123  }
124
125  @Override
126  public boolean hasFillPointer() {
127    return false;
128  }
129
130  @Override
131  public boolean isAdjustable() {
132    return false;
133  }
134
135  @Override
136  public int capacity() {
137    return capacity;
138  }
139
140  @Override
141  public int length() {
142    return capacity;
143  }
144
145  @Override
146  public LispObject elt(int index) {
147    try {
148      return number(((long)elements.get(index)) & 0xffffffffL);
149    } catch (IndexOutOfBoundsException e) {
150      badIndex(index, capacity);
151      return NIL; // Not reached.
152    }
153  }
154
155  @Override
156  public int aref(int index) {
157    try {
158      // FIXME: this shouldn't be used? 
159      return number(((long)elements.get(index)) & 0xffffffffL).intValue(); 
160    } catch (IndexOutOfBoundsException e) {
161      badIndex(index, ((java.nio.Buffer)elements).limit()); 
162      return -1; // Not reached.
163    }
164  }
165
166  @Override
167  public long aref_long(int index) {
168    try {
169      return ((long)elements.get(index)) & 0xffffffffL;
170    } catch (IndexOutOfBoundsException e) {
171      badIndex(index, ((java.nio.Buffer)elements).limit());
172      return -1; // Not reached.
173    }
174  }
175
176  @Override
177  public LispObject AREF(int index) {
178    try {
179      return number(((long)elements.get(index)) & 0xffffffffL);
180    } catch (IndexOutOfBoundsException e) {
181      badIndex(index, ((java.nio.Buffer)elements).limit());
182      return NIL; // Not reached.
183    }
184  }
185
186  @Override
187  public void aset(int index, LispObject newValue) {
188    try {
189      if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) {
190        type_error(newValue, UNSIGNED_BYTE_32);
191      }
192      elements.put(index, (int)(newValue.longValue() & 0xffffffffL));
193    } catch (IndexOutOfBoundsException e) {
194      badIndex(index, capacity);
195    }
196  }
197
198  @Override
199  public LispObject subseq(int start, int end) {
200    BasicVector_IntBuffer v = new BasicVector_IntBuffer(end - start);
201    int i = start, j = 0;
202    try {
203      while (i < end) {
204        v.elements.put(j++, elements.get(i++));
205      }
206      return v;
207    } catch (IndexOutOfBoundsException e) {
208      // FIXME
209      return error(new TypeError("Array index out of bounds: " + i + "."));
210    }
211  }
212
213  @Override
214  public void fill(LispObject obj) {
215    if (!(obj instanceof LispInteger)) {
216      type_error(obj, Symbol.INTEGER);
217      // Not reached.
218      return;
219    }
220    if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) {
221      type_error(obj, UNSIGNED_BYTE_32);
222    }
223    for (int i = capacity; i-- > 0;) {
224      elements.put(i, (int)(obj.longValue() & 0xffffffffL));
225    }
226  }
227
228  @Override
229  public void shrink(int n) {
230    if (n < length()) {
231      // One cannot shrink the underlying ByteBuffer physically, and
232      // the elements field may refer to malloc()d memory that we
233      // shouldn't touch, so use the java.nio.Buffer limit pointer.
234      // Not totally sure that this strategy will work out

235      ((java.nio.Buffer)elements).limit(n);
236      capacity = n;
237      return;
238    }
239    if (n == capacity) {
240      return;
241    }
242    error(new LispError());
243  }
244
245  @Override
246  public LispObject reverse() {
247    BasicVector_IntBuffer result = new BasicVector_IntBuffer(capacity);
248    int i, j;
249    for (i = 0, j = capacity - 1; i < capacity; i++, j--) {
250      result.elements.put(i, elements.get(j));
251    }
252    return result;
253  }
254
255  @Override
256  public LispObject nreverse() {
257    int i = 0;
258    int j = capacity - 1;
259    while (i < j) {
260      int temp = elements.get(i);
261      elements.put(i, elements.get(j));
262      elements.put(j, temp);
263      ++i;
264      --j;
265    }
266    return this;
267  }
268
269  @Override
270  public AbstractVector adjustArray(int newCapacity,
271                                    LispObject initialElement,
272                                    LispObject initialContents) {
273    if (initialContents != null) {
274      LispObject[] newElements = new LispObject[newCapacity];
275      if (initialContents.listp()) {
276        LispObject list = initialContents;
277        for (int i = 0; i < newCapacity; i++) {
278          newElements[i] = list.car();
279          list = list.cdr();
280        }
281      } else if (initialContents.vectorp()) {
282        for (int i = 0; i < newCapacity; i++) {
283          newElements[i] = initialContents.elt(i);
284        }
285      } else {
286        type_error(initialContents, Symbol.SEQUENCE);
287      }
288      return new BasicVector_IntBuffer(newElements, directAllocation);
289    }
290    if (capacity != newCapacity) {
291      LispObject[] newElements = new LispObject[newCapacity];
292      System.arraycopy(elements.array(), 0, newElements, 0,
293                       Math.min(capacity, newCapacity));
294      if (initialElement != null) {
295        for (int i = capacity; i < newCapacity; i++) {
296          newElements[i] = initialElement;
297        }
298      }
299      return new BasicVector_IntBuffer(newElements, directAllocation);
300    }
301    // No change.
302    return this;
303  }
304
305  @Override
306  public AbstractVector adjustArray(int newCapacity,
307                                     AbstractArray displacedTo,
308                                     int displacement) {
309    return new ComplexVector(newCapacity, displacedTo, displacement);
310  }
311
312  @Override
313  public AbstractVector replace(AbstractVector source,
314                                int targetStart, int targetEnd,
315                                int sourceStart, int sourceEnd)
316  {
317    if (source instanceof BasicVector_IntBuffer) {
318      IntBuffer view = ((BasicVector_IntBuffer)source).elements.asReadOnlyBuffer();
319      view.position(sourceStart);
320      view.limit(sourceEnd);
321      elements.position(targetStart);
322      elements.put(view);
323      elements.position(0);
324      return this;
325    } else {
326      return super.replace(source, targetStart, targetEnd, sourceStart, sourceEnd);
327    }
328  }
329}
Note: See TracBrowser for help on using the repository browser.