BSD 4_3 development
[unix-history] / usr / lib / lisp / array.l
CommitLineData
5ffa1c4c
C
1;;
2;; array.l -[Tue Jul 5 23:51:48 1983 by layer]-
3;;
4;; maclisp compatible array package. This implements maclisp
5;; compatible arrays.
6;;
7;; features of the new package:
8;; Most array will be notype arrays. This is because they are the most
9;; efficient in Franz. What used to be fixnum and flonums arrays are
10;; now fixnum-block and flonum-block arrays.
11;; The array access functions are more specialized and much faster now.
12;; The array access functions have different semantics. Now they are
13;; responsible for both accessing and storing in an array.
14;; When an access function is asked to access a value, it will be given
15;; the subscripts already evaluated and the array object. These will
16;; be stacked, so the array access function should be a lexpr to read them.
17;; When an access function is asked to store a value that value will be
18;; the first argument, the subscripts will follow and finally there will
19;; be the array object.
20;; It is up to the access function to determine if it is being asked to
21;; store or retrieve a value, and this determination will probably
22;; be made by looking at the number of arguments.
23
24
25(setq rcs-array-
26 "$Header: array.l 1.5 83/07/05 23:51:58 layer Exp $")
27
28(declare (special gcdisable)
29 (macros t))
30
31(def array
32 (macro ($lis$)
33 `(*array ',(cadr $lis$) ',(caddr $lis$) ,@(cdddr $lis$))))
34
35(def *array
36 (lexpr (nargs)
37 (prog (name type rtype dims size tname numdims)
38
39 (cond ((lessp (setq numdims (- nargs 2)) 1)
40 (error "no bounds to array declaration ")))
41
42 (setq name (arg 1)
43 type (arg 2)
44 rtype (cond ((memq type '(t nil fixnum flonum))
45 'value)
46 ((eq type 'fixnum-block)
47 'fixnum)
48 ((eq type 'flonum-block)
49 'flonum)
50 (t (error "array: bad type: " type)))
51 dims (do ((i nargs (1- i))
52 (res nil (cons (arg i) res)))
53 ((eq i 2) res))
54
55 size (apply 'times dims))
56
57 (cond ((null type) (setq type 'unmarked_array)))
58
59 ; we disable gc during the next calculation since
60 ; the data returned from small-segment is unprotected
61 ; and a gc would cause its data to be put on the
62 ; free list.
63 (let ((gcdisable t))
64 (setq tname
65 (marray (small-segment rtype size)
66 (cond ((eq rtype 'value)
67 (cond ((eq numdims 1)
68 (getd 'arrac-oneD))
69 ((eq numdims 2)
70 (getd 'arrac-twoD))
71 (t (getd 'arrac-nD))))
72 (t (getd 'arrac-nD)))
73 (cons type dims)
74 size
75 (sizeof rtype))))
76 ; if type is fixnum or flonum
77 ; we must intialize to 0 or 0.0
78 (cond ((or (and (eq 'fixnum type)
79 (setq rtype 0))
80 (and (eq 'flonum type)
81 (setq rtype 0.0))
82 (and (or (status feature 68k)
83 (status feature for-68k))
84 (progn (setq rtype nil) t)))
85 (do ((i size))
86 ((zerop i))
87 (set (arrayref tname (setq i (1- i))) rtype))))
88
89 (cond (name (putd name tname)))
90 (return tname))))
91
92(defmacro arraycall (type array &rest indexes)
93 `(funcall ,array ,@indexes))
94
95;--- array-type :: return type of array
96;
97(defun array-type (arr)
98 (cond ((not (arrayp arr)) (error "array-type: non array passed " arr))
99 (t (car (getaux arr)))))
100
101; this is used by the old array scheme. Keep this around until
102; everything is recompiled
103
104(defun ev-arraycall (type array indexes)
105 (apply array indexes))
106
107
108;;;---- array access functions.
109
110; we first define a macro to evaluate a value cell. In compiled code cdr
111; is the fastest way to do this, in interpreted code the type checker
112; would not let us use cdr so we have to use eval.
113(eval-when (compile)
114 (defmacro value-eval (x) `(cdr ,x)) ; one level of indirection
115 (defmacro simple-arrayref (arr ind) `(offset-cxr ,ind (getdata ,arr))))
116
117(eval-when (eval)
118 (defun value-eval (x) (eval x))
119 (defun simple-arrayref (arr ind) (arrayref arr ind)))
120
121;- one dimensional
122(defun arrac-oneD n
123 (cond ((eq n 2) (value-eval (simple-arrayref (arg 2) (arg 1))))
124 ((eq n 3) (set (simple-arrayref (arg 3) (arg 2)) (arg 1)))
125 (t (error " wrong number of subscripts to array: " (arg n)))))
126
127(defun arrac-twoD n
128 (let ((aux (getaux (arg n))))
129 (cond ((eq n 3)
130 (value-eval (simple-arrayref
131 (arg n)
132 (+ (* (arg 1) (caddr aux)) (arg 2)))))
133 ((eq n 4)
134 (set (simple-arrayref (arg n)
135 (+ (* (arg 2) (caddr aux)) (arg 3)))
136 (arg 1)))
137 (t (error " wrong number of subscripts to array: " (arg n))))))
138
139;-- n dimensional array access function.
140(defun arrac-nD n
141 (let ((aux (getaux (arg n)))
142 firstsub subs
143 store
144 (index 0))
145
146 (setq subs (length (cdr aux)))
147 (cond ((eq n (1+ subs))
148 (setq firstsub 1))
149 ((eq n (+ 2 subs))
150 (setq firstsub 2 store t))
151 (t (error "wrong number of subscripts to array: " (arg n))))
152
153 (setq index (arg firstsub))
154 (do ((bounds (cddr aux) (cdr bounds))
155 (i firstsub))
156 ((null bounds))
157 (setq index (+ (* index (car bounds)) (arg (setq i (1+ i))))))
158
159 (setq subs (arrayref (arg n) index)) ; get cell requested
160 (cond ((memq (car aux) '(fixnum-block flonum-block))
161 (cond (store (replace subs (arg 1)))
162 (t (cpy1 subs))))
163 (t (cond (store (set subs (arg 1)))
164 (t (value-eval subs)))))))
165
166
167(defmacro store ( (arrname . indexes) value)
168 (do ((fnd))
169 (nil)
170 (cond ((eq 'funcall arrname)
171 (return `(funcall ,(car indexes) ,value . ,(cdr indexes))))
172 ((eq 'apply arrname)
173 (return `(apply ,(car indexes) (cons ,value ,@(cdr indexes)))))
174 ((eq 'arraycall arrname)
175 (return `(funcall ,(cadr indexes) ,value ,@(cddr indexes))))
176 ((arrayp arrname)
177 (return `(funcall ',arrname ,value ,@indexes))))
178 (setq fnd (getd arrname))
179 (cond ((or (and (dtpr fnd) (eq 'macro (car fnd)))
180 (and (bcdp fnd) (eq 'macro (getdisc fnd))))
181 (setq fnd (apply arrname (cons arrname indexes)))
182 (setq arrname (car fnd)
183 indexes (cdr fnd)))
184 (t (return `(,arrname ,value . ,indexes))))))
185
186;-- storeintern - there may be residual calls to storeintern from
187; old code, we handle it here. this routine can be eliminated when
188; code is recompiled
189
190(defun storeintern (arrnam value indexes)
191 (apply arrnam (cons value indexes)))
192
193;--- small segment storage allocators.
194
195; this function allocates segments of storage and attempt to use the whole
196; block instead of throwing away what isnt used
197;
198
199(declare (special gcdisable))
200
201(defun small-segment (type n)
202 (prog (lastseg retv elementsize itemsperpage-1 gcdisable tmp)
203 (setq gcdisable t) ; its not a good idea to gc while we are
204 ; handling pointers to things segment returns.
205 (desetq (elementsize . itemsperpage-1) (get 'segment-sizes type))
206 (cond ((null elementsize) (error "small-segment: bad type " type)))
207 (setq lastseg (get 'segment-types type))
208 (cond ((and lastseg (not (lessp (car lastseg) n))))
209 (t ; must allocate a block of storage, want to the least number of
210 ; pages which includes n elements
211 ; there are elementsize elements per page, and
212 ; itemsperpage-1 is the number of elements on a page minus 1
213 (setq retv (boole 4
214 (+ n itemsperpage-1)
215 itemsperpage-1)) ; 4 is x & ~y
216 (setq lastseg (cons retv (maknum (segment type retv))))))
217 (setq retv (cdr lastseg))
218 (rplaca lastseg (- (car lastseg) n))
219 (rplacd lastseg (+ (cdr lastseg) (* elementsize n)))
220 (cond ((greaterp (car lastseg) 0)
221 (putprop 'segment-types lastseg type)
222 (cond ((null (setq tmp (get 'segment-arrays type)))
223 (putprop 'segment-arrays
224 (setq tmp (marray nil nil nil nil nil))
225 type)))
226 (putdata tmp (fake (cdr lastseg)))
227 (putlength tmp (car lastseg))
228 (putdelta tmp elementsize))
229 (t ; remove all counters since we no longer have any space
230 ; left and we can't have a zero length array
231 (remprop 'segment-types type)
232 (remprop 'segment-arrays type)))
233 (return (fake retv))))
234
235; data base for small-segment
236(putprop 'segment-sizes '( 4 . 127) 'value)
237(putprop 'segment-sizes '( 4 . 127) 'fixnum)
238(putprop 'segment-sizes '( 8 . 63) 'flonum)
239
240
241(def arraydims (lambda (arg) (cond ((symbolp arg) (getaux (getd arg)))
242 ((arrayp arg) (getaux arg))
243 (t (break '"non array arg to arraydims")))))
244
245; fill array from list or array
246
247(def fillarray
248 (lambda (arr lis)
249 (prog (maxv typept)
250 (cond ((symbolp arr) (setq arr (getd arr))))
251
252 (cond ((symbolp lis)
253 (setq lis (getd lis))
254 (return (fillarrayarray arr lis)))
255
256 ((arrayp lis) (return (fillarrayarray arr lis))))
257
258 (setq maxv (1- (getlength arr))
259 typept (cond ((memq (car (getaux arr))
260 '(t fixnum flonum unmarked_array))
261 t)
262 (t nil)))
263 (do ((ls lis)
264 (i 0 (1+ i)))
265 ((>& i maxv))
266
267 (cond (typept (set (arrayref arr i) (car ls)))
268 (t (replace (arrayref arr i) (car ls))))
269
270 (cond ((cdr ls) (setq ls (cdr ls))))))))
271
272(def fillarrayarray
273 (lambda (arrto arrfrom)
274 (prog (maxv)
275 (setq maxv (1- (min (getlength arrto)
276 (getlength arrfrom))))
277 (do ((i 0 (1+ i)))
278 ((>& i maxv))
279 (replace (arrayref arrto i) (arrayref arrfrom i))))))
280
281(def listarray
282 (lexpr (n)
283 (prog (arr size typ ret newv)
284 (setq arr (arg 1))
285 (cond ((arrayp arr))
286 ((and (symbolp arr) (arrayp (setq arr (getd arr)))))
287 (t (error "Non array to listarray " arr)))
288 (setq size (cond ((eq n 2) (arg 2))
289 (t (apply '* (cdr (arraydims arr))))))
290 (setq typ (car (getaux arr)))
291 (cond ((memq typ '(t fixnum flonum unmarked_array))
292 (setq typ t))
293 (t (setq typ nil)))
294 (do ((i (1- size) (1- i)))
295 ((lessp i 0))
296 (setq newv (arrayref arr i))
297 (setq ret (cons (cond (typ (eval newv))
298 (t (cpy1 newv)))
299 ret)))
300 (return ret))))