Merge commit 'f30e1bdf97ae8b2b2918da585f887a4d3a23a347' into boehm-demers-weiser-gc
[bpt/guile.git] / libguile / vectors.c
1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library 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 GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18
19 \f
20
21 #include "libguile/_scm.h"
22 #include "libguile/eq.h"
23 #include "libguile/root.h"
24 #include "libguile/strings.h"
25 #include "libguile/lang.h"
26
27 #include "libguile/validate.h"
28 #include "libguile/vectors.h"
29 #include "libguile/unif.h"
30 #include "libguile/ramap.h"
31 #include "libguile/srfi-4.h"
32 #include "libguile/strings.h"
33 #include "libguile/srfi-13.h"
34 #include "libguile/dynwind.h"
35 #include "libguile/deprecation.h"
36
37 #include "libguile/boehm-gc.h"
38
39
40 \f
41
42 #define VECTOR_MAX_LENGTH (SCM_T_BITS_MAX >> 8)
43
44 int
45 scm_is_vector (SCM obj)
46 {
47 if (SCM_I_IS_VECTOR (obj))
48 return 1;
49 if (SCM_I_ARRAYP (obj) && SCM_I_ARRAY_NDIM (obj) == 1)
50 {
51 SCM v = SCM_I_ARRAY_V (obj);
52 return SCM_I_IS_VECTOR (v);
53 }
54 return 0;
55 }
56
57 int
58 scm_is_simple_vector (SCM obj)
59 {
60 return SCM_I_IS_VECTOR (obj);
61 }
62
63 const SCM *
64 scm_vector_elements (SCM vec, scm_t_array_handle *h,
65 size_t *lenp, ssize_t *incp)
66 {
67 if (SCM_I_WVECTP (vec))
68 /* FIXME: We should check each (weak) element of the vector for NULL and
69 convert it to SCM_BOOL_F. */
70 abort ();
71
72 scm_generalized_vector_get_handle (vec, h);
73 if (lenp)
74 {
75 scm_t_array_dim *dim = scm_array_handle_dims (h);
76 *lenp = dim->ubnd - dim->lbnd + 1;
77 *incp = dim->inc;
78 }
79 return scm_array_handle_elements (h);
80 }
81
82 SCM *
83 scm_vector_writable_elements (SCM vec, scm_t_array_handle *h,
84 size_t *lenp, ssize_t *incp)
85 {
86 if (SCM_I_WVECTP (vec))
87 /* FIXME: We should check each (weak) element of the vector for NULL and
88 convert it to SCM_BOOL_F. */
89 abort ();
90
91 scm_generalized_vector_get_handle (vec, h);
92 if (lenp)
93 {
94 scm_t_array_dim *dim = scm_array_handle_dims (h);
95 *lenp = dim->ubnd - dim->lbnd + 1;
96 *incp = dim->inc;
97 }
98 return scm_array_handle_writable_elements (h);
99 }
100
101 SCM_DEFINE (scm_vector_p, "vector?", 1, 0, 0,
102 (SCM obj),
103 "Return @code{#t} if @var{obj} is a vector, otherwise return\n"
104 "@code{#f}.")
105 #define FUNC_NAME s_scm_vector_p
106 {
107 return scm_from_bool (scm_is_vector (obj));
108 }
109 #undef FUNC_NAME
110
111 SCM_GPROC (s_vector_length, "vector-length", 1, 0, 0, scm_vector_length, g_vector_length);
112 /* Returns the number of elements in @var{vector} as an exact integer. */
113 SCM
114 scm_vector_length (SCM v)
115 {
116 if (SCM_I_IS_VECTOR (v))
117 return scm_from_size_t (SCM_I_VECTOR_LENGTH (v));
118 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
119 {
120 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
121 return scm_from_size_t (dim->ubnd - dim->lbnd + 1);
122 }
123 else
124 SCM_WTA_DISPATCH_1 (g_vector_length, v, 1, NULL);
125 }
126
127 size_t
128 scm_c_vector_length (SCM v)
129 {
130 if (SCM_I_IS_VECTOR (v))
131 return SCM_I_VECTOR_LENGTH (v);
132 else
133 return scm_to_size_t (scm_vector_length (v));
134 }
135
136 SCM_REGISTER_PROC (s_list_to_vector, "list->vector", 1, 0, 0, scm_vector);
137 /*
138 "Return a newly created vector initialized to the elements of"
139 "the list @var{list}.\n\n"
140 "@lisp\n"
141 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
142 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
143 "@end lisp")
144 */
145 SCM_DEFINE (scm_vector, "vector", 0, 0, 1,
146 (SCM l),
147 "@deffnx {Scheme Procedure} list->vector l\n"
148 "Return a newly allocated vector composed of the\n"
149 "given arguments. Analogous to @code{list}.\n"
150 "\n"
151 "@lisp\n"
152 "(vector 'a 'b 'c) @result{} #(a b c)\n"
153 "@end lisp")
154 #define FUNC_NAME s_scm_vector
155 {
156 SCM res;
157 SCM *data;
158 long i, len;
159 scm_t_array_handle handle;
160
161 SCM_VALIDATE_LIST_COPYLEN (1, l, len);
162
163 res = scm_c_make_vector (len, SCM_UNSPECIFIED);
164 data = scm_vector_writable_elements (res, &handle, NULL, NULL);
165 i = 0;
166 while (scm_is_pair (l) && i < len)
167 {
168 data[i] = SCM_CAR (l);
169 l = SCM_CDR (l);
170 i += 1;
171 }
172
173 scm_array_handle_release (&handle);
174
175 return res;
176 }
177 #undef FUNC_NAME
178
179 SCM_GPROC (s_vector_ref, "vector-ref", 2, 0, 0, scm_vector_ref, g_vector_ref);
180
181 /*
182 "@var{k} must be a valid index of @var{vector}.\n"
183 "@samp{Vector-ref} returns the contents of element @var{k} of\n"
184 "@var{vector}.\n\n"
185 "@lisp\n"
186 "(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8\n"
187 "(vector-ref '#(1 1 2 3 5 8 13 21)\n"
188 " (let ((i (round (* 2 (acos -1)))))\n"
189 " (if (inexact? i)\n"
190 " (inexact->exact i)\n"
191 " i))) @result{} 13\n"
192 "@end lisp"
193 */
194
195 SCM
196 scm_vector_ref (SCM v, SCM k)
197 #define FUNC_NAME s_vector_ref
198 {
199 return scm_c_vector_ref (v, scm_to_size_t (k));
200 }
201 #undef FUNC_NAME
202
203 SCM
204 scm_c_vector_ref (SCM v, size_t k)
205 {
206 if (SCM_I_IS_VECTOR (v))
207 {
208 register SCM elt;
209
210 if (k >= SCM_I_VECTOR_LENGTH (v))
211 scm_out_of_range (NULL, scm_from_size_t (k));
212 elt = (SCM_I_VECTOR_ELTS(v))[k];
213
214 if ((elt == SCM_PACK (NULL)) && SCM_I_WVECTP (v))
215 /* ELT was a weak pointer and got nullified by the GC. */
216 return SCM_BOOL_F;
217
218 return elt;
219 }
220 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
221 {
222 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
223 SCM vv = SCM_I_ARRAY_V (v);
224 if (SCM_I_IS_VECTOR (vv))
225 {
226 register SCM elt;
227
228 if (k >= dim->ubnd - dim->lbnd + 1)
229 scm_out_of_range (NULL, scm_from_size_t (k));
230 k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
231 elt = (SCM_I_VECTOR_ELTS (vv))[k];
232
233 if ((elt == SCM_PACK (NULL)) && (SCM_I_WVECTP (vv)))
234 /* ELT was a weak pointer and got nullified by the GC. */
235 return SCM_BOOL_F;
236
237 return elt;
238 }
239 scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
240 }
241 else
242 SCM_WTA_DISPATCH_2 (g_vector_ref, v, scm_from_size_t (k), 2, NULL);
243 }
244
245 SCM_GPROC (s_vector_set_x, "vector-set!", 3, 0, 0, scm_vector_set_x, g_vector_set_x);
246
247 /* "@var{k} must be a valid index of @var{vector}.\n"
248 "@code{Vector-set!} stores @var{obj} in element @var{k} of @var{vector}.\n"
249 "The value returned by @samp{vector-set!} is unspecified.\n"
250 "@lisp\n"
251 "(let ((vec (vector 0 '(2 2 2 2) "Anna")))\n"
252 " (vector-set! vec 1 '("Sue" "Sue"))\n"
253 " vec) @result{} #(0 ("Sue" "Sue") "Anna")\n"
254 "(vector-set! '#(0 1 2) 1 "doe") @result{} @emph{error} ; constant vector\n"
255 "@end lisp"
256 */
257
258 SCM
259 scm_vector_set_x (SCM v, SCM k, SCM obj)
260 #define FUNC_NAME s_vector_set_x
261 {
262 scm_c_vector_set_x (v, scm_to_size_t (k), obj);
263 return SCM_UNSPECIFIED;
264 }
265 #undef FUNC_NAME
266
267 void
268 scm_c_vector_set_x (SCM v, size_t k, SCM obj)
269 {
270 if (SCM_I_IS_VECTOR (v))
271 {
272 if (k >= SCM_I_VECTOR_LENGTH (v))
273 scm_out_of_range (NULL, scm_from_size_t (k));
274 (SCM_I_VECTOR_WELTS(v))[k] = obj;
275 if (SCM_I_WVECTP (v))
276 {
277 /* Make it a weak pointer. */
278 GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (v))[k]);
279 GC_GENERAL_REGISTER_DISAPPEARING_LINK (link, obj);
280 }
281 }
282 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
283 {
284 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
285 SCM vv = SCM_I_ARRAY_V (v);
286 if (SCM_I_IS_VECTOR (vv))
287 {
288 if (k >= dim->ubnd - dim->lbnd + 1)
289 scm_out_of_range (NULL, scm_from_size_t (k));
290 k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
291 (SCM_I_VECTOR_WELTS (vv))[k] = obj;
292
293 if (SCM_I_WVECTP (vv))
294 {
295 /* Make it a weak pointer. */
296 GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (vv))[k]);
297 GC_GENERAL_REGISTER_DISAPPEARING_LINK (link, obj);
298 }
299 }
300 else
301 scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
302 }
303 else
304 {
305 if (SCM_UNPACK (g_vector_set_x))
306 scm_apply_generic (g_vector_set_x,
307 scm_list_3 (v, scm_from_size_t (k), obj));
308 else
309 scm_wrong_type_arg_msg (NULL, 0, v, "vector");
310 }
311 }
312
313 SCM_DEFINE (scm_make_vector, "make-vector", 1, 1, 0,
314 (SCM k, SCM fill),
315 "Return a newly allocated vector of @var{k} elements. If a\n"
316 "second argument is given, then each position is initialized to\n"
317 "@var{fill}. Otherwise the initial contents of each position is\n"
318 "unspecified.")
319 #define FUNC_NAME s_scm_make_vector
320 {
321 size_t l = scm_to_unsigned_integer (k, 0, VECTOR_MAX_LENGTH);
322
323 if (SCM_UNBNDP (fill))
324 fill = SCM_UNSPECIFIED;
325
326 return scm_c_make_vector (l, fill);
327 }
328 #undef FUNC_NAME
329
330
331 SCM
332 scm_c_make_vector (size_t k, SCM fill)
333 #define FUNC_NAME s_scm_make_vector
334 {
335 SCM v;
336 SCM *base;
337
338 if (k > 0)
339 {
340 unsigned long int j;
341
342 SCM_ASSERT_RANGE (1, scm_from_ulong (k), k <= VECTOR_MAX_LENGTH);
343
344 base = scm_gc_malloc (k * sizeof (SCM), "vector");
345 for (j = 0; j != k; ++j)
346 base[j] = fill;
347 }
348 else
349 base = NULL;
350
351 v = scm_cell ((k << 8) | scm_tc7_vector, (scm_t_bits) base);
352 scm_remember_upto_here_1 (fill);
353
354 return v;
355 }
356 #undef FUNC_NAME
357
358 SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
359 (SCM vec),
360 "Return a copy of @var{vec}.")
361 #define FUNC_NAME s_scm_vector_copy
362 {
363 scm_t_array_handle handle;
364 size_t i, len;
365 ssize_t inc;
366 const SCM *src;
367 SCM *dst;
368
369 src = scm_vector_elements (vec, &handle, &len, &inc);
370 dst = scm_gc_malloc (len * sizeof (SCM), "vector");
371 for (i = 0; i < len; i++, src += inc)
372 dst[i] = *src;
373 scm_array_handle_release (&handle);
374
375 return scm_cell ((len << 8) | scm_tc7_vector, (scm_t_bits) dst);
376 }
377 #undef FUNC_NAME
378
379 void
380 scm_i_vector_free (SCM vec)
381 {
382 scm_gc_free (SCM_I_VECTOR_WELTS (vec),
383 SCM_I_VECTOR_LENGTH (vec) * sizeof(SCM),
384 "vector");
385 }
386
387 \f
388 /* Weak vectors. */
389
390
391 /* Initialize RET as a weak vector of type TYPE of SIZE elements pointed to
392 by BASE. */
393 #define MAKE_WEAK_VECTOR(_ret, _type, _size, _base) \
394 (_ret) = scm_double_cell ((_size << 8) | scm_tc7_wvect, \
395 (scm_t_bits) (_base), \
396 (_type), \
397 SCM_UNPACK (SCM_EOL));
398
399
400 /* Allocate memory for the elements of a weak vector on behalf of the
401 caller. */
402 static SCM *
403 allocate_weak_vector (scm_t_bits type, size_t c_size)
404 {
405 SCM *base;
406
407 if (c_size > 0)
408 /* The base itself should not be scanned for pointers otherwise those
409 pointers will always be reachable. */
410 base = scm_gc_malloc_pointerless (c_size * sizeof (SCM), "weak vector");
411 else
412 base = NULL;
413
414 return base;
415 }
416
417 /* Return a new weak vector. The allocated vector will be of the given weak
418 vector subtype. It will contain SIZE elements which are initialized with
419 the FILL object, or, if FILL is undefined, with an unspecified object. */
420 SCM
421 scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill)
422 {
423 SCM wv, *base;
424 size_t c_size, j;
425
426 if (SCM_UNBNDP (fill))
427 fill = SCM_UNSPECIFIED;
428
429 c_size = scm_to_unsigned_integer (size, 0, VECTOR_MAX_LENGTH);
430 base = allocate_weak_vector (type, c_size);
431
432 for (j = 0; j != c_size; ++j)
433 base[j] = fill;
434
435 MAKE_WEAK_VECTOR (wv, type, c_size, base);
436
437 return wv;
438 }
439
440 /* Return a new weak vector with type TYPE and whose content are taken from
441 list LST. */
442 SCM
443 scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst)
444 {
445 SCM wv, *base, *elt;
446 long c_size;
447
448 c_size = scm_ilength (lst);
449 SCM_ASSERT (c_size >= 0, lst, SCM_ARG2, "scm_i_make_weak_vector_from_list");
450
451 base = allocate_weak_vector (type, (size_t)c_size);
452 for (elt = base;
453 scm_is_pair (lst);
454 lst = SCM_CDR (lst), elt++)
455 {
456 *elt = SCM_CAR (lst);
457 }
458
459 MAKE_WEAK_VECTOR (wv, type, (size_t)c_size, base);
460
461 return wv;
462 }
463
464
465 \f
466 SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
467 (SCM v),
468 "Return a newly allocated list composed of the elements of @var{v}.\n"
469 "\n"
470 "@lisp\n"
471 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
472 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
473 "@end lisp")
474 #define FUNC_NAME s_scm_vector_to_list
475 {
476 SCM res = SCM_EOL;
477 const SCM *data;
478 scm_t_array_handle handle;
479 size_t i, count, len;
480 ssize_t inc;
481
482 data = scm_vector_elements (v, &handle, &len, &inc);
483 for (i = (len - 1) * inc, count = 0;
484 count < len;
485 i -= inc, count++)
486 res = scm_cons (data[i], res);
487
488 scm_array_handle_release (&handle);
489 return res;
490 }
491 #undef FUNC_NAME
492
493
494 SCM_DEFINE (scm_vector_fill_x, "vector-fill!", 2, 0, 0,
495 (SCM v, SCM fill),
496 "Store @var{fill} in every position of @var{vector}. The value\n"
497 "returned by @code{vector-fill!} is unspecified.")
498 #define FUNC_NAME s_scm_vector_fill_x
499 {
500 scm_t_array_handle handle;
501 SCM *data;
502 size_t i, len;
503 ssize_t inc;
504
505 data = scm_vector_writable_elements (v, &handle, &len, &inc);
506 for (i = 0; i < len; i += inc)
507 data[i] = fill;
508 scm_array_handle_release (&handle);
509 return SCM_UNSPECIFIED;
510 }
511 #undef FUNC_NAME
512
513
514 SCM
515 scm_i_vector_equal_p (SCM x, SCM y)
516 {
517 long i;
518 for (i = SCM_I_VECTOR_LENGTH (x) - 1; i >= 0; i--)
519 if (scm_is_false (scm_equal_p (SCM_I_VECTOR_ELTS (x)[i],
520 SCM_I_VECTOR_ELTS (y)[i])))
521 return SCM_BOOL_F;
522 return SCM_BOOL_T;
523 }
524
525
526 SCM_DEFINE (scm_vector_move_left_x, "vector-move-left!", 5, 0, 0,
527 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
528 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
529 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
530 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
531 "@code{vector-move-left!} copies elements in leftmost order.\n"
532 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
533 "same vector, @code{vector-move-left!} is usually appropriate when\n"
534 "@var{start1} is greater than @var{start2}.")
535 #define FUNC_NAME s_scm_vector_move_left_x
536 {
537 scm_t_array_handle handle1, handle2;
538 const SCM *elts1;
539 SCM *elts2;
540 size_t len1, len2;
541 ssize_t inc1, inc2;
542 size_t i, j, e;
543
544 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
545 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
546
547 i = scm_to_unsigned_integer (start1, 0, len1);
548 e = scm_to_unsigned_integer (end1, i, len1);
549 j = scm_to_unsigned_integer (start2, 0, len2 - (i-e));
550
551 i *= inc1;
552 e *= inc1;
553 j *= inc2;
554 for (; i < e; i += inc1, j += inc2)
555 elts2[j] = elts1[i];
556
557 scm_array_handle_release (&handle2);
558 scm_array_handle_release (&handle1);
559
560 return SCM_UNSPECIFIED;
561 }
562 #undef FUNC_NAME
563
564 SCM_DEFINE (scm_vector_move_right_x, "vector-move-right!", 5, 0, 0,
565 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
566 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
567 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
568 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
569 "@code{vector-move-right!} copies elements in rightmost order.\n"
570 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
571 "same vector, @code{vector-move-right!} is usually appropriate when\n"
572 "@var{start1} is less than @var{start2}.")
573 #define FUNC_NAME s_scm_vector_move_right_x
574 {
575 scm_t_array_handle handle1, handle2;
576 const SCM *elts1;
577 SCM *elts2;
578 size_t len1, len2;
579 ssize_t inc1, inc2;
580 size_t i, j, e;
581
582 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
583 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
584
585 i = scm_to_unsigned_integer (start1, 0, len1);
586 e = scm_to_unsigned_integer (end1, i, len1);
587 j = scm_to_unsigned_integer (start2, 0, len2 - (i-e));
588
589 i *= inc1;
590 e *= inc1;
591 j *= inc2;
592 while (i < e)
593 {
594 e -= inc1;
595 j -= inc2;
596 elts2[j] = elts1[e];
597 }
598
599 scm_array_handle_release (&handle2);
600 scm_array_handle_release (&handle1);
601
602 return SCM_UNSPECIFIED;
603 }
604 #undef FUNC_NAME
605
606
607 /* Generalized vectors. */
608
609 int
610 scm_is_generalized_vector (SCM obj)
611 {
612 return (scm_is_vector (obj)
613 || scm_is_string (obj)
614 || scm_is_bitvector (obj)
615 || scm_is_uniform_vector (obj));
616 }
617
618 SCM_DEFINE (scm_generalized_vector_p, "generalized-vector?", 1, 0, 0,
619 (SCM obj),
620 "Return @code{#t} if @var{obj} is a vector, string,\n"
621 "bitvector, or uniform numeric vector.")
622 #define FUNC_NAME s_scm_generalized_vector_p
623 {
624 return scm_from_bool (scm_is_generalized_vector (obj));
625 }
626 #undef FUNC_NAME
627
628 void
629 scm_generalized_vector_get_handle (SCM vec, scm_t_array_handle *h)
630 {
631 scm_array_get_handle (vec, h);
632 if (scm_array_handle_rank (h) != 1)
633 scm_wrong_type_arg_msg (NULL, 0, vec, "vector");
634 }
635
636 size_t
637 scm_c_generalized_vector_length (SCM v)
638 {
639 if (scm_is_vector (v))
640 return scm_c_vector_length (v);
641 else if (scm_is_string (v))
642 return scm_c_string_length (v);
643 else if (scm_is_bitvector (v))
644 return scm_c_bitvector_length (v);
645 else if (scm_is_uniform_vector (v))
646 return scm_c_uniform_vector_length (v);
647 else
648 scm_wrong_type_arg_msg (NULL, 0, v, "generalized vector");
649 }
650
651 SCM_DEFINE (scm_generalized_vector_length, "generalized-vector-length", 1, 0, 0,
652 (SCM v),
653 "Return the length of the generalized vector @var{v}.")
654 #define FUNC_NAME s_scm_generalized_vector_length
655 {
656 return scm_from_size_t (scm_c_generalized_vector_length (v));
657 }
658 #undef FUNC_NAME
659
660 SCM
661 scm_c_generalized_vector_ref (SCM v, size_t idx)
662 {
663 if (scm_is_vector (v))
664 return scm_c_vector_ref (v, idx);
665 else if (scm_is_string (v))
666 return scm_c_string_ref (v, idx);
667 else if (scm_is_bitvector (v))
668 return scm_c_bitvector_ref (v, idx);
669 else if (scm_is_uniform_vector (v))
670 return scm_c_uniform_vector_ref (v, idx);
671 else
672 scm_wrong_type_arg_msg (NULL, 0, v, "generalized vector");
673 }
674
675 SCM_DEFINE (scm_generalized_vector_ref, "generalized-vector-ref", 2, 0, 0,
676 (SCM v, SCM idx),
677 "Return the element at index @var{idx} of the\n"
678 "generalized vector @var{v}.")
679 #define FUNC_NAME s_scm_generalized_vector_ref
680 {
681 return scm_c_generalized_vector_ref (v, scm_to_size_t (idx));
682 }
683 #undef FUNC_NAME
684
685 void
686 scm_c_generalized_vector_set_x (SCM v, size_t idx, SCM val)
687 {
688 if (scm_is_vector (v))
689 scm_c_vector_set_x (v, idx, val);
690 else if (scm_is_string (v))
691 scm_c_string_set_x (v, idx, val);
692 else if (scm_is_bitvector (v))
693 scm_c_bitvector_set_x (v, idx, val);
694 else if (scm_is_uniform_vector (v))
695 scm_c_uniform_vector_set_x (v, idx, val);
696 else
697 scm_wrong_type_arg_msg (NULL, 0, v, "generalized vector");
698 }
699
700 SCM_DEFINE (scm_generalized_vector_set_x, "generalized-vector-set!", 3, 0, 0,
701 (SCM v, SCM idx, SCM val),
702 "Set the element at index @var{idx} of the\n"
703 "generalized vector @var{v} to @var{val}.")
704 #define FUNC_NAME s_scm_generalized_vector_set_x
705 {
706 scm_c_generalized_vector_set_x (v, scm_to_size_t (idx), val);
707 return SCM_UNSPECIFIED;
708 }
709 #undef FUNC_NAME
710
711 SCM_DEFINE (scm_generalized_vector_to_list, "generalized-vector->list", 1, 0, 0,
712 (SCM v),
713 "Return a new list whose elements are the elements of the\n"
714 "generalized vector @var{v}.")
715 #define FUNC_NAME s_scm_generalized_vector_to_list
716 {
717 if (scm_is_vector (v))
718 return scm_vector_to_list (v);
719 else if (scm_is_string (v))
720 return scm_string_to_list (v);
721 else if (scm_is_bitvector (v))
722 return scm_bitvector_to_list (v);
723 else if (scm_is_uniform_vector (v))
724 return scm_uniform_vector_to_list (v);
725 else
726 scm_wrong_type_arg_msg (NULL, 0, v, "generalized vector");
727 }
728 #undef FUNC_NAME
729
730
731 void
732 scm_init_vectors ()
733 {
734 scm_nullvect = scm_c_make_vector (0, SCM_UNDEFINED);
735
736 #include "libguile/vectors.x"
737 }
738
739
740 /*
741 Local Variables:
742 c-file-style: "gnu"
743 End:
744 */