Remove "face-lift" comment.
[bpt/guile.git] / libguile / vectors.c
1 /* Copyright (C) 1995,1996,1998,1999,2000,2001 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42
43 \f
44
45 #include "libguile/_scm.h"
46 #include "libguile/eq.h"
47 #include "libguile/root.h"
48 #include "libguile/strings.h"
49
50 #include "libguile/validate.h"
51 #include "libguile/vectors.h"
52 #include "libguile/unif.h"
53 \f
54
55 #if (SCM_DEBUG_DEPRECATED == 0)
56
57 /* The function scm_vector_set_length_x will disappear in the next release of
58 * guile.
59 */
60
61 /*
62 * This complicates things too much if allowed on any array.
63 * C code can safely call it on arrays known to be used in a single
64 * threaded manner.
65 *
66 * SCM_REGISTER_PROC(s_vector_set_length_x, "vector-set-length!", 2, 0, 0, scm_vector_set_length_x);
67 */
68 static char s_vector_set_length_x[] = "vector-set-length!";
69
70
71 SCM
72 scm_vector_set_length_x (SCM vect, SCM len)
73 {
74 long l;
75 size_t siz;
76 size_t sz;
77 char *base;
78
79 l = SCM_INUM (len);
80 SCM_ASRTGO (SCM_NIMP (vect), badarg1);
81
82 #ifdef HAVE_ARRAYS
83 if (SCM_TYP7 (vect) == scm_tc7_bvect)
84 {
85 l = (l + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
86 }
87 sz = scm_uniform_element_size (vect);
88 if (sz != 0)
89 base = SCM_UVECTOR_BASE (vect);
90 else
91 #endif
92 switch (SCM_TYP7 (vect))
93 {
94 default:
95 badarg1: scm_wta (vect, (char *) SCM_ARG1, s_vector_set_length_x);
96 case scm_tc7_string:
97 SCM_ASRTGO (!SCM_EQ_P (vect, scm_nullstr), badarg1);
98 sz = sizeof (char);
99 base = SCM_STRING_CHARS (vect);
100 l++;
101 break;
102 case scm_tc7_vector:
103 case scm_tc7_wvect:
104 SCM_ASRTGO (!SCM_EQ_P (vect, scm_nullvect), badarg1);
105 sz = sizeof (SCM);
106 base = (char *) SCM_VECTOR_BASE (vect);
107 break;
108 }
109 SCM_ASSERT (SCM_INUMP (len), len, SCM_ARG2, s_vector_set_length_x);
110 if (!l)
111 l = 1L;
112 siz = l * sz;
113 if (siz != l * sz)
114 scm_memory_error (s_vector_set_length_x);
115 SCM_REDEFER_INTS;
116 SCM_SETCHARS (vect,
117 ((char *)
118 scm_must_realloc (base,
119 (size_t) SCM_LENGTH (vect) * sz,
120 (size_t) siz,
121 s_vector_set_length_x)));
122 if (SCM_VECTORP (vect))
123 {
124 sz = SCM_LENGTH (vect);
125 while (l > sz)
126 SCM_VELTS (vect)[--l] = SCM_UNSPECIFIED;
127 }
128 else if (SCM_STRINGP (vect))
129 SCM_STRING_CHARS (vect)[l - 1] = 0;
130 SCM_SETLENGTH (vect, SCM_INUM (len), SCM_TYP7 (vect));
131 SCM_REALLOW_INTS;
132 return vect;
133 }
134
135 #endif /* (SCM_DEBUG_DEPRECATED == 0) */
136
137 SCM_DEFINE (scm_vector_p, "vector?", 1, 0, 0,
138 (SCM obj),
139 "Return @code{#t} if @var{obj} is a vector, otherwise return\n"
140 "@code{#f}.")
141 #define FUNC_NAME s_scm_vector_p
142 {
143 if (SCM_IMP (obj))
144 return SCM_BOOL_F;
145 return SCM_BOOL (SCM_VECTORP (obj));
146 }
147 #undef FUNC_NAME
148
149 SCM_GPROC (s_vector_length, "vector-length", 1, 0, 0, scm_vector_length, g_vector_length);
150 /* Returns the number of elements in @var{vector} as an exact integer. */
151 SCM
152 scm_vector_length (SCM v)
153 {
154 SCM_GASSERT1 (SCM_VECTORP(v),
155 g_vector_length, v, SCM_ARG1, s_vector_length);
156 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v));
157 }
158
159 SCM_REGISTER_PROC (s_list_to_vector, "list->vector", 1, 0, 0, scm_vector);
160 /*
161 "Return a newly created vector initialized to the elements of"
162 "the list @var{list}.\n\n"
163 "@lisp\n"
164 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
165 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
166 "@end lisp")
167 */
168 SCM_DEFINE (scm_vector, "vector", 0, 0, 1,
169 (SCM l),
170 "@deffnx primitive list->vector l\n"
171 "Return a newly allocated vector whose elements contain the\n"
172 "given arguments. Analogous to @code{list}.\n"
173 "\n"
174 "@lisp\n"
175 "(vector 'a 'b 'c) @result{} #(a b c)\n"
176 "@end lisp")
177 #define FUNC_NAME s_scm_vector
178 {
179 SCM res;
180 SCM *data;
181 long i;
182
183 /* Dirk:FIXME:: In case of multiple threads, the list might get corrupted
184 while the vector is being created. */
185 SCM_VALIDATE_LIST_COPYLEN (1, l, i);
186 res = scm_c_make_vector (i, SCM_UNSPECIFIED);
187 data = SCM_VELTS (res);
188 while (!SCM_NULLP (l))
189 {
190 *data++ = SCM_CAR (l);
191 l = SCM_CDR (l);
192 }
193
194 return res;
195 }
196 #undef FUNC_NAME
197
198 SCM_GPROC (s_vector_ref, "vector-ref", 2, 0, 0, scm_vector_ref, g_vector_ref);
199
200 /*
201 "@var{k} must be a valid index of @var{vector}.\n"
202 "@samp{Vector-ref} returns the contents of element @var{k} of\n"
203 "@var{vector}.\n\n"
204 "@lisp\n"
205 "(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8\n"
206 "(vector-ref '#(1 1 2 3 5 8 13 21)\n"
207 " (let ((i (round (* 2 (acos -1)))))\n"
208 " (if (inexact? i)\n"
209 " (inexact->exact i)\n"
210 " i))) @result{} 13\n"
211 "@end lisp"
212 */
213
214 SCM
215 scm_vector_ref (SCM v, SCM k)
216 #define FUNC_NAME s_vector_ref
217 {
218 SCM_GASSERT2 (SCM_VECTORP (v),
219 g_vector_ref, v, k, SCM_ARG1, s_vector_ref);
220 SCM_GASSERT2 (SCM_INUMP (k),
221 g_vector_ref, v, k, SCM_ARG2, s_vector_ref);
222 SCM_ASSERT_RANGE (2, k, SCM_INUM (k) < SCM_VECTOR_LENGTH (v) && SCM_INUM (k) >= 0);
223 return SCM_VELTS (v)[(long) SCM_INUM (k)];
224 }
225 #undef FUNC_NAME
226
227 SCM_GPROC (s_vector_set_x, "vector-set!", 3, 0, 0, scm_vector_set_x, g_vector_set_x);
228
229 /* "@var{k} must be a valid index of @var{vector}.\n"
230 "@code{Vector-set!} stores @var{obj} in element @var{k} of @var{vector}.\n"
231 "The value returned by @samp{vector-set!} is unspecified.\n"
232 "@lisp\n"
233 "(let ((vec (vector 0 '(2 2 2 2) "Anna")))\n"
234 " (vector-set! vec 1 '("Sue" "Sue"))\n"
235 " vec) @result{} #(0 ("Sue" "Sue") "Anna")\n"
236 "(vector-set! '#(0 1 2) 1 "doe") @result{} @emph{error} ; constant vector\n"
237 "@end lisp"
238 */
239
240 SCM
241 scm_vector_set_x (SCM v, SCM k, SCM obj)
242 #define FUNC_NAME s_vector_set_x
243 {
244 SCM_GASSERTn (SCM_VECTORP (v),
245 g_vector_set_x, scm_list_3 (v, k, obj),
246 SCM_ARG1, s_vector_set_x);
247 SCM_GASSERTn (SCM_INUMP (k),
248 g_vector_set_x, scm_list_3 (v, k, obj),
249 SCM_ARG2, s_vector_set_x);
250 SCM_ASSERT_RANGE (2, k, SCM_INUM (k) < SCM_VECTOR_LENGTH (v) && SCM_INUM (k) >= 0);
251 SCM_VELTS(v)[(long) SCM_INUM(k)] = obj;
252 return SCM_UNSPECIFIED;
253 }
254 #undef FUNC_NAME
255
256
257 SCM_DEFINE (scm_make_vector, "make-vector", 1, 1, 0,
258 (SCM k, SCM fill),
259 "Return a newly allocated vector of @var{k} elements. If a\n"
260 "second argument is given, then each element is initialized to\n"
261 "@var{fill}. Otherwise the initial contents of each element is\n"
262 "unspecified.")
263 #define FUNC_NAME s_scm_make_vector
264 {
265 if (SCM_UNBNDP (fill))
266 fill = SCM_UNSPECIFIED;
267
268 if (SCM_INUMP (k))
269 {
270 SCM_ASSERT_RANGE (1, k, SCM_INUM (k) >= 0);
271 return scm_c_make_vector (SCM_INUM (k), fill);
272 }
273 else if (SCM_BIGP (k))
274 SCM_OUT_OF_RANGE (1, k);
275 else
276 SCM_WRONG_TYPE_ARG (1, k);
277 }
278 #undef FUNC_NAME
279
280
281 SCM
282 scm_c_make_vector (unsigned long int k, SCM fill)
283 #define FUNC_NAME s_scm_make_vector
284 {
285 SCM v;
286 scm_t_bits *base;
287
288 if (k > 0)
289 {
290 unsigned long int j;
291
292 SCM_ASSERT_RANGE (1, scm_ulong2num (k), k <= SCM_VECTOR_MAX_LENGTH);
293
294 base = scm_must_malloc (k * sizeof (scm_t_bits), FUNC_NAME);
295 for (j = 0; j != k; ++j)
296 base[j] = SCM_UNPACK (fill);
297 }
298 else
299 base = NULL;
300
301 SCM_NEWCELL (v);
302 SCM_SET_VECTOR_BASE (v, base);
303 SCM_SET_VECTOR_LENGTH (v, k, scm_tc7_vector);
304 scm_remember_upto_here_1 (fill);
305
306 return v;
307 }
308 #undef FUNC_NAME
309
310
311 SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
312 (SCM v),
313 "Return a newly allocated list of the objects contained in the\n"
314 "elements of @var{vector}.\n"
315 "\n"
316 "@lisp\n"
317 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
318 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
319 "@end lisp")
320 #define FUNC_NAME s_scm_vector_to_list
321 {
322 SCM res = SCM_EOL;
323 long i;
324 SCM *data;
325 SCM_VALIDATE_VECTOR (1,v);
326 data = SCM_VELTS(v);
327 for(i = SCM_VECTOR_LENGTH(v)-1;i >= 0;i--) res = scm_cons(data[i], res);
328 return res;
329 }
330 #undef FUNC_NAME
331
332
333 SCM_DEFINE (scm_vector_fill_x, "vector-fill!", 2, 0, 0,
334 (SCM v, SCM fill),
335 "Store @var{fill} in every element of @var{vector}. The value\n"
336 "returned by @code{vector-fill!} is unspecified.")
337 #define FUNC_NAME s_scm_vector_fill_x
338 {
339 register long i;
340 register SCM *data;
341 SCM_VALIDATE_VECTOR (1, v);
342 data = SCM_VELTS (v);
343 for(i = SCM_VECTOR_LENGTH (v) - 1; i >= 0; i--)
344 data[i] = fill;
345 return SCM_UNSPECIFIED;
346 }
347 #undef FUNC_NAME
348
349
350 SCM
351 scm_vector_equal_p(SCM x, SCM y)
352 {
353 long i;
354 for(i = SCM_VECTOR_LENGTH (x) - 1; i >= 0; i--)
355 if (SCM_FALSEP (scm_equal_p (SCM_VELTS (x)[i], SCM_VELTS (y)[i])))
356 return SCM_BOOL_F;
357 return SCM_BOOL_T;
358 }
359
360
361 SCM_DEFINE (scm_vector_move_left_x, "vector-move-left!", 5, 0, 0,
362 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
363 "Vector version of @code{substring-move-left!}.")
364 #define FUNC_NAME s_scm_vector_move_left_x
365 {
366 long i;
367 long j;
368 long e;
369
370 SCM_VALIDATE_VECTOR (1,vec1);
371 SCM_VALIDATE_INUM_COPY (2,start1,i);
372 SCM_VALIDATE_INUM_COPY (3,end1,e);
373 SCM_VALIDATE_VECTOR (4,vec2);
374 SCM_VALIDATE_INUM_COPY (5,start2,j);
375 SCM_ASSERT_RANGE (2, start1, i <= SCM_VECTOR_LENGTH (vec1) && i >= 0);
376 SCM_ASSERT_RANGE (5, start2, j <= SCM_VECTOR_LENGTH (vec2) && j >= 0);
377 SCM_ASSERT_RANGE (3, end1, e <= SCM_VECTOR_LENGTH (vec1) && e >= 0);
378 SCM_ASSERT_RANGE (5, start2, e-i+j <= SCM_VECTOR_LENGTH (vec2));
379 while (i<e) SCM_VELTS (vec2)[j++] = SCM_VELTS (vec1)[i++];
380 return SCM_UNSPECIFIED;
381 }
382 #undef FUNC_NAME
383
384 SCM_DEFINE (scm_vector_move_right_x, "vector-move-right!", 5, 0, 0,
385 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
386 "Vector version of @code{substring-move-right!}.")
387 #define FUNC_NAME s_scm_vector_move_right_x
388 {
389 long i;
390 long j;
391 long e;
392
393 SCM_VALIDATE_VECTOR (1,vec1);
394 SCM_VALIDATE_INUM_COPY (2,start1,i);
395 SCM_VALIDATE_INUM_COPY (3,end1,e);
396 SCM_VALIDATE_VECTOR (4,vec2);
397 SCM_VALIDATE_INUM_COPY (5,start2,j);
398 SCM_ASSERT_RANGE (2, start1, i <= SCM_VECTOR_LENGTH (vec1) && i >= 0);
399 SCM_ASSERT_RANGE (5, start2, j <= SCM_VECTOR_LENGTH (vec2) && j >= 0);
400 SCM_ASSERT_RANGE (3, end1, e <= SCM_VECTOR_LENGTH (vec1) && e >= 0);
401 j = e - i + j;
402 SCM_ASSERT_RANGE (5, start2, j <= SCM_VECTOR_LENGTH (vec2));
403 while (i < e)
404 SCM_VELTS (vec2)[--j] = SCM_VELTS (vec1)[--e];
405 return SCM_UNSPECIFIED;
406 }
407 #undef FUNC_NAME
408
409
410
411 void
412 scm_init_vectors ()
413 {
414 scm_nullvect = scm_c_make_vector (0, SCM_UNDEFINED);
415
416 #ifndef SCM_MAGIC_SNARFER
417 #include "libguile/vectors.x"
418 #endif
419 }
420
421
422 /*
423 Local Variables:
424 c-file-style: "gnu"
425 End:
426 */