1 /*
2  * ComplexArray_UnsignedByte8.java
3  *
4  * Copyright (C) 2003-2005 Peter Graves
5  * $Id$
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 
34 package org.armedbear.lisp;
35 
36 import static org.armedbear.lisp.Lisp.*;
37 
38 public final class ComplexArray_UnsignedByte8 extends AbstractArray
39 {
40     private final int[] dimv;
41     private int totalSize;
42 
43     // For non-displaced arrays.
44     private byte[] data;
45 
46     // For displaced arrays.
47     private AbstractArray array;
48     private int displacement;
49 
ComplexArray_UnsignedByte8(int[] dimv)50     public ComplexArray_UnsignedByte8(int[] dimv)
51     {
52         this.dimv = dimv;
53         totalSize = computeTotalSize(dimv);
54         data = new byte[totalSize];
55     }
56 
ComplexArray_UnsignedByte8(int[] dimv, LispObject initialContents)57     public ComplexArray_UnsignedByte8(int[] dimv, LispObject initialContents)
58 
59     {
60         this.dimv = dimv;
61         final int rank = dimv.length;
62         LispObject rest = initialContents;
63         for (int i = 0; i < rank; i++) {
64             dimv[i] = rest.length();
65             rest = rest.elt(0);
66         }
67         totalSize = computeTotalSize(dimv);
68         data = new byte[totalSize];
69         setInitialContents(0, dimv, initialContents, 0);
70     }
71 
ComplexArray_UnsignedByte8(int[] dimv, AbstractArray array, int displacement)72     public ComplexArray_UnsignedByte8(int[] dimv, AbstractArray array, int displacement)
73     {
74         this.dimv = dimv;
75         this.array = array;
76         this.displacement = displacement;
77         totalSize = computeTotalSize(dimv);
78     }
79 
setInitialContents(int axis, int[] dims, LispObject contents, int index)80     private int setInitialContents(int axis, int[] dims, LispObject contents,
81                                    int index)
82 
83     {
84         if (dims.length == 0) {
85             try {
86                 data[index] = coerceToJavaByte(contents);
87             }
88             catch (ArrayIndexOutOfBoundsException e) {
89                 error(new LispError("Bad initial contents for array."));
90                 return -1;
91             }
92             ++index;
93         } else {
94             int dim = dims[0];
95             if (dim != contents.length()) {
96                 error(new LispError("Bad initial contents for array."));
97                 return -1;
98             }
99             int[] newDims = new int[dims.length-1];
100             for (int i = 1; i < dims.length; i++)
101                 newDims[i-1] = dims[i];
102             if (contents.listp()) {
103                 for (int i = contents.length();i-- > 0;) {
104                     LispObject content = contents.car();
105                     index =
106                         setInitialContents(axis + 1, newDims, content, index);
107                     contents = contents.cdr();
108                 }
109             } else {
110                 AbstractVector v = checkVector(contents);
111                 final int length = v.length();
112                 for (int i = 0; i < length; i++) {
113                     LispObject content = v.AREF(i);
114                     index =
115                         setInitialContents(axis + 1, newDims, content, index);
116                 }
117             }
118         }
119         return index;
120     }
121 
122     @Override
typeOf()123     public LispObject typeOf()
124     {
125         return list(Symbol.ARRAY, UNSIGNED_BYTE_8, getDimensions());
126     }
127 
128     @Override
classOf()129     public LispObject classOf()
130     {
131         return BuiltInClass.ARRAY;
132     }
133 
134     @Override
getRank()135     public int getRank()
136     {
137         return dimv.length;
138     }
139 
140     @Override
getDimensions()141     public LispObject getDimensions()
142     {
143         LispObject result = NIL;
144         for (int i = dimv.length; i-- > 0;)
145             result = new Cons(Fixnum.getInstance(dimv[i]), result);
146         return result;
147     }
148 
149     @Override
getDimension(int n)150     public int getDimension(int n)
151     {
152         try {
153             return dimv[n];
154         }
155         catch (ArrayIndexOutOfBoundsException e) {
156             error(new TypeError("Bad array dimension " + n + "."));
157             return -1;
158         }
159     }
160 
161     @Override
getElementType()162     public LispObject getElementType()
163     {
164         return UNSIGNED_BYTE_8;
165     }
166 
167     @Override
getTotalSize()168     public int getTotalSize()
169     {
170         return totalSize;
171     }
172 
173     @Override
arrayDisplacement()174     public LispObject arrayDisplacement()
175     {
176         LispObject value1, value2;
177         if (array != null) {
178             value1 = array;
179             value2 = Fixnum.getInstance(displacement);
180         } else {
181             value1 = NIL;
182             value2 = Fixnum.ZERO;
183         }
184         return LispThread.currentThread().setValues(value1, value2);
185     }
186 
187     @Override
AREF(int index)188     public LispObject AREF(int index)
189     {
190         if (data != null) {
191             try {
192                 return coerceFromJavaByte(data[index]);
193             }
194             catch (ArrayIndexOutOfBoundsException e) {
195                 return error(new TypeError("Bad row major index " + index + "."));
196             }
197         } else
198             return array.AREF(index + displacement);
199     }
200 
201     @Override
aset(int index, LispObject newValue)202     public void aset(int index, LispObject newValue)
203     {
204         if (data != null) {
205             try {
206                 data[index] = coerceToJavaByte(newValue);
207             }
208             catch (ArrayIndexOutOfBoundsException e) {
209                 error(new TypeError("Bad row major index " + index + "."));
210             }
211         } else
212             array.aset(index + displacement, newValue);
213     }
214 
215     @Override
fill(LispObject obj)216     public void fill(LispObject obj)
217     {
218         if (!(obj instanceof Fixnum)) {
219             type_error(obj, Symbol.FIXNUM);
220             // Not reached.
221             return;
222         }
223         int n = ((Fixnum) obj).value;
224         if (n < 0 || n > 255) {
225             type_error(obj, UNSIGNED_BYTE_8);
226             // Not reached.
227             return;
228         }
229         if (data != null) {
230             for (int i = data.length; i-- > 0;)
231                 data[i] = (byte) n;
232         } else {
233             for (int i = totalSize; i-- > 0;)
234                 aset(i, obj);
235         }
236     }
237 
238     @Override
printObject()239     public String printObject()
240     {
241         if (Symbol.PRINT_READABLY.symbolValue() != NIL) {
242             error(new PrintNotReadable(list(Keyword.OBJECT, this)));
243             // Not reached.
244             return null;
245         }
246         return printObject(dimv);
247     }
248 
249 
250     @Override
adjustArray(int[] dims, LispObject initialElement, LispObject initialContents)251     public AbstractArray adjustArray(int[] dims,
252                                               LispObject initialElement,
253                                               LispObject initialContents)
254             {
255         if (isAdjustable()) {
256             if (initialContents != null)
257                 setInitialContents(0, dims, initialContents, 0);
258             else {
259                 //### FIXME Take the easy way out: we don't want to reorganize
260                 // all of the array code yet
261                 SimpleArray_UnsignedByte8 tempArray = new SimpleArray_UnsignedByte8(dims);
262                 if (initialElement != null)
263                     tempArray.fill(initialElement);
264                 SimpleArray_UnsignedByte8.copyArray(this, tempArray);
265                 this.data = tempArray.data;
266 
267                 for (int i = 0; i < dims.length; i++)
268                     dimv[i] = dims[i];
269             }
270             return this;
271         } else {
272             if (initialContents != null)
273                 return new ComplexArray_UnsignedByte8(dims, initialContents);
274             else {
275                 ComplexArray_UnsignedByte8 newArray = new ComplexArray_UnsignedByte8(dims);
276                 if (initialElement != null)
277                     newArray.fill(initialElement);
278                 return newArray;
279             }
280         }
281     }
282 
283     @Override
adjustArray(int[] dims, AbstractArray displacedTo, int displacement)284     public AbstractArray adjustArray(int[] dims,
285                                               AbstractArray displacedTo,
286                                               int displacement)
287             {
288         if (isAdjustable()) {
289             for (int i = 0; i < dims.length; i++)
290                 dimv[i] = dims[i];
291 
292             this.data = null;
293             this.array = displacedTo;
294             this.displacement = displacement;
295             this.totalSize = computeTotalSize(dims);
296 
297             return this;
298         } else {
299             ComplexArray_UnsignedByte8 a = new ComplexArray_UnsignedByte8(dims, displacedTo, displacement);
300 
301             return a;
302         }
303     }
304 }
305