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