doc: Remove reference to `closure?', now deprecated.
[bpt/guile.git] / libguile / vectors.c
CommitLineData
b2b33168 1/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd 20\f
dbb605f5
LC
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
0f2d19dd 24
a0599745
MD
25#include "libguile/_scm.h"
26#include "libguile/eq.h"
27#include "libguile/root.h"
28#include "libguile/strings.h"
29
30#include "libguile/validate.h"
31#include "libguile/vectors.h"
5c39373f 32#include "libguile/arrays.h" /* Hit me with the ugly stick */
f332e957 33#include "libguile/generalized-vectors.h"
88797580
MV
34#include "libguile/strings.h"
35#include "libguile/srfi-13.h"
1d0df896 36#include "libguile/dynwind.h"
6e708ef2 37#include "libguile/deprecation.h"
88797580 38
1c44468d 39#include "libguile/bdw-gc.h"
3a2de079
LC
40
41
0f2d19dd
JB
42\f
43
6e708ef2
MV
44#define VECTOR_MAX_LENGTH (SCM_T_BITS_MAX >> 8)
45
6e708ef2
MV
46int
47scm_is_vector (SCM obj)
48{
49 if (SCM_I_IS_VECTOR (obj))
50 return 1;
04b87de5 51 if (SCM_I_ARRAYP (obj) && SCM_I_ARRAY_NDIM (obj) == 1)
6e708ef2 52 {
04b87de5 53 SCM v = SCM_I_ARRAY_V (obj);
6e708ef2
MV
54 return SCM_I_IS_VECTOR (v);
55 }
56 return 0;
57}
58
59int
60scm_is_simple_vector (SCM obj)
1d0df896 61{
6e708ef2 62 return SCM_I_IS_VECTOR (obj);
1d0df896
MV
63}
64
354116f7
MV
65const SCM *
66scm_vector_elements (SCM vec, scm_t_array_handle *h,
67 size_t *lenp, ssize_t *incp)
68{
3a2de079
LC
69 if (SCM_I_WVECTP (vec))
70 /* FIXME: We should check each (weak) element of the vector for NULL and
71 convert it to SCM_BOOL_F. */
72 abort ();
73
354116f7
MV
74 scm_generalized_vector_get_handle (vec, h);
75 if (lenp)
76 {
77 scm_t_array_dim *dim = scm_array_handle_dims (h);
78 *lenp = dim->ubnd - dim->lbnd + 1;
79 *incp = dim->inc;
80 }
81 return scm_array_handle_elements (h);
82}
83
84SCM *
85scm_vector_writable_elements (SCM vec, scm_t_array_handle *h,
86 size_t *lenp, ssize_t *incp)
87{
3a2de079
LC
88 if (SCM_I_WVECTP (vec))
89 /* FIXME: We should check each (weak) element of the vector for NULL and
90 convert it to SCM_BOOL_F. */
91 abort ();
92
354116f7
MV
93 scm_generalized_vector_get_handle (vec, h);
94 if (lenp)
95 {
96 scm_t_array_dim *dim = scm_array_handle_dims (h);
97 *lenp = dim->ubnd - dim->lbnd + 1;
98 *incp = dim->inc;
99 }
100 return scm_array_handle_writable_elements (h);
101}
102
a1ec6916 103SCM_DEFINE (scm_vector_p, "vector?", 1, 0, 0,
5ffe9968 104 (SCM obj),
1e6808ea
MG
105 "Return @code{#t} if @var{obj} is a vector, otherwise return\n"
106 "@code{#f}.")
1bbd0b84 107#define FUNC_NAME s_scm_vector_p
0f2d19dd 108{
de5c0f58 109 return scm_from_bool (scm_is_vector (obj));
0f2d19dd 110}
1bbd0b84 111#undef FUNC_NAME
0f2d19dd 112
f172c0b7 113SCM_GPROC (s_vector_length, "vector-length", 1, 0, 0, scm_vector_length, g_vector_length);
1e6808ea 114/* Returns the number of elements in @var{vector} as an exact integer. */
0f2d19dd 115SCM
f172c0b7 116scm_vector_length (SCM v)
0f2d19dd 117{
6e708ef2
MV
118 if (SCM_I_IS_VECTOR (v))
119 return scm_from_size_t (SCM_I_VECTOR_LENGTH (v));
04b87de5 120 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
de5c0f58 121 {
04b87de5 122 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
de5c0f58
MV
123 return scm_from_size_t (dim->ubnd - dim->lbnd + 1);
124 }
125 else
126 SCM_WTA_DISPATCH_1 (g_vector_length, v, 1, NULL);
0f2d19dd
JB
127}
128
88797580
MV
129size_t
130scm_c_vector_length (SCM v)
131{
6e708ef2
MV
132 if (SCM_I_IS_VECTOR (v))
133 return SCM_I_VECTOR_LENGTH (v);
88797580 134 else
de5c0f58 135 return scm_to_size_t (scm_vector_length (v));
88797580
MV
136}
137
f172c0b7 138SCM_REGISTER_PROC (s_list_to_vector, "list->vector", 1, 0, 0, scm_vector);
5ffe9968 139/*
942e5b91
MG
140 "Return a newly created vector initialized to the elements of"
141 "the list @var{list}.\n\n"
142 "@lisp\n"
143 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
144 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
145 "@end lisp")
5ffe9968 146*/
a1ec6916 147SCM_DEFINE (scm_vector, "vector", 0, 0, 1,
f172c0b7 148 (SCM l),
8f85c0c6
NJ
149 "@deffnx {Scheme Procedure} list->vector l\n"
150 "Return a newly allocated vector composed of the\n"
1e6808ea
MG
151 "given arguments. Analogous to @code{list}.\n"
152 "\n"
942e5b91 153 "@lisp\n"
1e6808ea 154 "(vector 'a 'b 'c) @result{} #(a b c)\n"
942e5b91 155 "@end lisp")
1bbd0b84 156#define FUNC_NAME s_scm_vector
0f2d19dd
JB
157{
158 SCM res;
22a52da1 159 SCM *data;
1d0df896 160 long i, len;
6e708ef2 161 scm_t_array_handle handle;
22a52da1 162
1d0df896 163 SCM_VALIDATE_LIST_COPYLEN (1, l, len);
34d19ef6 164
6e708ef2
MV
165 res = scm_c_make_vector (len, SCM_UNSPECIFIED);
166 data = scm_vector_writable_elements (res, &handle, NULL, NULL);
1d0df896 167 i = 0;
c8857a4d 168 while (scm_is_pair (l) && i < len)
22a52da1 169 {
1d0df896 170 data[i] = SCM_CAR (l);
22a52da1 171 l = SCM_CDR (l);
6e708ef2 172 i += 1;
22a52da1
DH
173 }
174
c8857a4d
MV
175 scm_array_handle_release (&handle);
176
0f2d19dd
JB
177 return res;
178}
1bbd0b84 179#undef FUNC_NAME
0f2d19dd 180
f172c0b7 181SCM_GPROC (s_vector_ref, "vector-ref", 2, 0, 0, scm_vector_ref, g_vector_ref);
1cc91f1b 182
5ffe9968
GB
183/*
184 "@var{k} must be a valid index of @var{vector}.\n"
185 "@samp{Vector-ref} returns the contents of element @var{k} of\n"
186 "@var{vector}.\n\n"
942e5b91
MG
187 "@lisp\n"
188 "(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8\n"
5ffe9968
GB
189 "(vector-ref '#(1 1 2 3 5 8 13 21)\n"
190 " (let ((i (round (* 2 (acos -1)))))\n"
191 " (if (inexact? i)\n"
192 " (inexact->exact i)\n"
942e5b91
MG
193 " i))) @result{} 13\n"
194 "@end lisp"
5ffe9968
GB
195*/
196
0f2d19dd 197SCM
ea633082 198scm_vector_ref (SCM v, SCM k)
685c0d71 199#define FUNC_NAME s_vector_ref
0f2d19dd 200{
de5c0f58 201 return scm_c_vector_ref (v, scm_to_size_t (k));
0f2d19dd 202}
685c0d71 203#undef FUNC_NAME
0f2d19dd 204
88797580
MV
205SCM
206scm_c_vector_ref (SCM v, size_t k)
207{
6e708ef2 208 if (SCM_I_IS_VECTOR (v))
de5c0f58 209 {
3a2de079
LC
210 register SCM elt;
211
6e708ef2 212 if (k >= SCM_I_VECTOR_LENGTH (v))
3a2de079
LC
213 scm_out_of_range (NULL, scm_from_size_t (k));
214 elt = (SCM_I_VECTOR_ELTS(v))[k];
215
b2b33168 216 if (SCM_UNPACK (elt) == 0 && SCM_I_WVECTP (v))
3a2de079
LC
217 /* ELT was a weak pointer and got nullified by the GC. */
218 return SCM_BOOL_F;
219
220 return elt;
de5c0f58 221 }
04b87de5 222 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
88797580 223 {
04b87de5
MV
224 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
225 SCM vv = SCM_I_ARRAY_V (v);
6e708ef2
MV
226 if (SCM_I_IS_VECTOR (vv))
227 {
3a2de079
LC
228 register SCM elt;
229
6e708ef2
MV
230 if (k >= dim->ubnd - dim->lbnd + 1)
231 scm_out_of_range (NULL, scm_from_size_t (k));
04b87de5 232 k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
3a2de079
LC
233 elt = (SCM_I_VECTOR_ELTS (vv))[k];
234
b2b33168 235 if (SCM_UNPACK (elt) == 0 && (SCM_I_WVECTP (vv)))
3a2de079
LC
236 /* ELT was a weak pointer and got nullified by the GC. */
237 return SCM_BOOL_F;
238
239 return elt;
6e708ef2
MV
240 }
241 scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
88797580 242 }
de5c0f58
MV
243 else
244 SCM_WTA_DISPATCH_2 (g_vector_ref, v, scm_from_size_t (k), 2, NULL);
88797580
MV
245}
246
f172c0b7 247SCM_GPROC (s_vector_set_x, "vector-set!", 3, 0, 0, scm_vector_set_x, g_vector_set_x);
1cc91f1b 248
942e5b91
MG
249/* "@var{k} must be a valid index of @var{vector}.\n"
250 "@code{Vector-set!} stores @var{obj} in element @var{k} of @var{vector}.\n"
251 "The value returned by @samp{vector-set!} is unspecified.\n"
252 "@lisp\n"
253 "(let ((vec (vector 0 '(2 2 2 2) "Anna")))\n"
254 " (vector-set! vec 1 '("Sue" "Sue"))\n"
255 " vec) @result{} #(0 ("Sue" "Sue") "Anna")\n"
256 "(vector-set! '#(0 1 2) 1 "doe") @result{} @emph{error} ; constant vector\n"
257 "@end lisp"
5ffe9968
GB
258*/
259
0f2d19dd 260SCM
f172c0b7 261scm_vector_set_x (SCM v, SCM k, SCM obj)
685c0d71 262#define FUNC_NAME s_vector_set_x
0f2d19dd 263{
de5c0f58 264 scm_c_vector_set_x (v, scm_to_size_t (k), obj);
60c497a3 265 return SCM_UNSPECIFIED;
0f2d19dd 266}
685c0d71 267#undef FUNC_NAME
0f2d19dd 268
de5c0f58 269void
88797580
MV
270scm_c_vector_set_x (SCM v, size_t k, SCM obj)
271{
6e708ef2 272 if (SCM_I_IS_VECTOR (v))
88797580 273 {
6e708ef2 274 if (k >= SCM_I_VECTOR_LENGTH (v))
de5c0f58 275 scm_out_of_range (NULL, scm_from_size_t (k));
6e708ef2 276 (SCM_I_VECTOR_WELTS(v))[k] = obj;
3a2de079
LC
277 if (SCM_I_WVECTP (v))
278 {
279 /* Make it a weak pointer. */
280 GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (v))[k]);
d3464bb6
AW
281 SCM_I_REGISTER_DISAPPEARING_LINK (link,
282 (GC_PTR) SCM2PTR (obj));
3a2de079 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]);
d3464bb6
AW
300 SCM_I_REGISTER_DISAPPEARING_LINK (link,
301 (GC_PTR) SCM2PTR (obj));
3a2de079 302 }
6e708ef2
MV
303 }
304 else
305 scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
88797580
MV
306 }
307 else
308 {
de5c0f58
MV
309 if (SCM_UNPACK (g_vector_set_x))
310 scm_apply_generic (g_vector_set_x,
311 scm_list_3 (v, scm_from_size_t (k), obj));
312 else
313 scm_wrong_type_arg_msg (NULL, 0, v, "vector");
88797580
MV
314 }
315}
0f2d19dd 316
a1ec6916 317SCM_DEFINE (scm_make_vector, "make-vector", 1, 1, 0,
1bbd0b84 318 (SCM k, SCM fill),
1e6808ea 319 "Return a newly allocated vector of @var{k} elements. If a\n"
8f85c0c6
NJ
320 "second argument is given, then each position is initialized to\n"
321 "@var{fill}. Otherwise the initial contents of each position is\n"
1e6808ea 322 "unspecified.")
1bbd0b84 323#define FUNC_NAME s_scm_make_vector
0f2d19dd 324{
6e708ef2 325 size_t l = scm_to_unsigned_integer (k, 0, VECTOR_MAX_LENGTH);
e11e83f3 326
1b9be268 327 if (SCM_UNBNDP (fill))
d60cebe2 328 fill = SCM_UNSPECIFIED;
e11e83f3
MV
329
330 return scm_c_make_vector (l, fill);
00ffa0e7
KN
331}
332#undef FUNC_NAME
333
e382fdbe 334
00ffa0e7 335SCM
88797580 336scm_c_make_vector (size_t k, SCM fill)
00ffa0e7
KN
337#define FUNC_NAME s_scm_make_vector
338{
ed7e0765 339 SCM *vector;
1b9be268 340
ed7e0765
LC
341 vector = (SCM *)
342 scm_gc_malloc ((k + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM),
343 "vector");
344
345 if (k > 0)
e382fdbe 346 {
ed7e0765 347 SCM *base;
c014a02e 348 unsigned long int j;
1b9be268 349
6e708ef2 350 SCM_ASSERT_RANGE (1, scm_from_ulong (k), k <= VECTOR_MAX_LENGTH);
1b9be268 351
ed7e0765 352 base = vector + SCM_I_VECTOR_HEADER_SIZE;
e382fdbe 353 for (j = 0; j != k; ++j)
6e708ef2 354 base[j] = fill;
e382fdbe 355 }
1b9be268 356
ed7e0765
LC
357 ((scm_t_bits *) vector)[0] = (k << 8) | scm_tc7_vector;
358 ((scm_t_bits *) vector)[1] = 0;
1b9be268 359
ed7e0765 360 return PTR2SCM (vector);
0f2d19dd 361}
1bbd0b84 362#undef FUNC_NAME
0f2d19dd 363
6e708ef2
MV
364SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
365 (SCM vec),
366 "Return a copy of @var{vec}.")
367#define FUNC_NAME s_scm_vector_copy
368{
369 scm_t_array_handle handle;
370 size_t i, len;
371 ssize_t inc;
372 const SCM *src;
ed7e0765 373 SCM result, *dst;
6e708ef2
MV
374
375 src = scm_vector_elements (vec, &handle, &len, &inc);
ed7e0765
LC
376
377 result = scm_c_make_vector (len, SCM_UNDEFINED);
378 dst = SCM_I_VECTOR_WELTS (result);
6e708ef2
MV
379 for (i = 0; i < len; i++, src += inc)
380 dst[i] = *src;
ed7e0765 381
c8857a4d 382 scm_array_handle_release (&handle);
6e708ef2 383
ed7e0765 384 return result;
6e708ef2
MV
385}
386#undef FUNC_NAME
387
d525e4f9
LC
388\f
389/* Weak vectors. */
390
d525e4f9
LC
391/* Allocate memory for the elements of a weak vector on behalf of the
392 caller. */
ed7e0765
LC
393static SCM
394make_weak_vector (scm_t_bits type, size_t c_size)
6e708ef2 395{
ed7e0765
LC
396 SCM *vector;
397 size_t total_size;
d525e4f9 398
ed7e0765
LC
399 total_size = (c_size + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM);
400 vector = (SCM *) scm_gc_malloc_pointerless (total_size, "weak vector");
d525e4f9 401
ed7e0765
LC
402 ((scm_t_bits *) vector)[0] = (c_size << 8) | scm_tc7_wvect;
403 ((scm_t_bits *) vector)[1] = type;
404
405 return PTR2SCM (vector);
d525e4f9
LC
406}
407
408/* Return a new weak vector. The allocated vector will be of the given weak
409 vector subtype. It will contain SIZE elements which are initialized with
410 the FILL object, or, if FILL is undefined, with an unspecified object. */
411SCM
412scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill)
413{
414 SCM wv, *base;
415 size_t c_size, j;
416
417 if (SCM_UNBNDP (fill))
418 fill = SCM_UNSPECIFIED;
6e708ef2
MV
419
420 c_size = scm_to_unsigned_integer (size, 0, VECTOR_MAX_LENGTH);
ed7e0765
LC
421 wv = make_weak_vector (type, c_size);
422 base = SCM_I_WVECT_GC_WVELTS (wv);
6e708ef2 423
d525e4f9
LC
424 for (j = 0; j != c_size; ++j)
425 base[j] = fill;
3a2de079 426
d525e4f9
LC
427 return wv;
428}
429
430/* Return a new weak vector with type TYPE and whose content are taken from
431 list LST. */
432SCM
433scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst)
434{
ed7e0765 435 SCM wv, *elt;
d525e4f9
LC
436 long c_size;
437
438 c_size = scm_ilength (lst);
439 SCM_ASSERT (c_size >= 0, lst, SCM_ARG2, "scm_i_make_weak_vector_from_list");
440
ed7e0765
LC
441 wv = make_weak_vector(type, (size_t) c_size);
442
443 for (elt = SCM_I_WVECT_GC_WVELTS (wv);
d525e4f9
LC
444 scm_is_pair (lst);
445 lst = SCM_CDR (lst), elt++)
446 {
447 *elt = SCM_CAR (lst);
6e708ef2 448 }
6e708ef2 449
d525e4f9 450 return wv;
6e708ef2 451}
e382fdbe 452
d525e4f9
LC
453
454\f
3b3b36dd 455SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
1e6808ea 456 (SCM v),
8f85c0c6 457 "Return a newly allocated list composed of the elements of @var{v}.\n"
1e6808ea 458 "\n"
942e5b91
MG
459 "@lisp\n"
460 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
461 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
462 "@end lisp")
1bbd0b84 463#define FUNC_NAME s_scm_vector_to_list
0f2d19dd 464{
6e708ef2
MV
465 SCM res = SCM_EOL;
466 const SCM *data;
467 scm_t_array_handle handle;
22be72d3 468 size_t i, count, len;
6e708ef2
MV
469 ssize_t inc;
470
471 data = scm_vector_elements (v, &handle, &len, &inc);
22be72d3
LC
472 for (i = (len - 1) * inc, count = 0;
473 count < len;
474 i -= inc, count++)
475 res = scm_cons (data[i], res);
476
c8857a4d 477 scm_array_handle_release (&handle);
6e708ef2 478 return res;
0f2d19dd 479}
1bbd0b84 480#undef FUNC_NAME
0f2d19dd
JB
481
482
a1ec6916 483SCM_DEFINE (scm_vector_fill_x, "vector-fill!", 2, 0, 0,
1e6808ea 484 (SCM v, SCM fill),
8f85c0c6 485 "Store @var{fill} in every position of @var{vector}. The value\n"
1e6808ea 486 "returned by @code{vector-fill!} is unspecified.")
1bbd0b84 487#define FUNC_NAME s_scm_vector_fill_x
0f2d19dd 488{
6e708ef2
MV
489 scm_t_array_handle handle;
490 SCM *data;
491 size_t i, len;
492 ssize_t inc;
493
494 data = scm_vector_writable_elements (v, &handle, &len, &inc);
495 for (i = 0; i < len; i += inc)
496 data[i] = fill;
c8857a4d 497 scm_array_handle_release (&handle);
6e708ef2 498 return SCM_UNSPECIFIED;
0f2d19dd 499}
1bbd0b84 500#undef FUNC_NAME
0f2d19dd
JB
501
502
0f2d19dd 503SCM
354116f7 504scm_i_vector_equal_p (SCM x, SCM y)
0f2d19dd 505{
c014a02e 506 long i;
6e708ef2
MV
507 for (i = SCM_I_VECTOR_LENGTH (x) - 1; i >= 0; i--)
508 if (scm_is_false (scm_equal_p (SCM_I_VECTOR_ELTS (x)[i],
509 SCM_I_VECTOR_ELTS (y)[i])))
0f2d19dd
JB
510 return SCM_BOOL_F;
511 return SCM_BOOL_T;
512}
513
514
a1ec6916 515SCM_DEFINE (scm_vector_move_left_x, "vector-move-left!", 5, 0, 0,
1bbd0b84 516 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
694a9bb3
NJ
517 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
518 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
519 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
520 "@code{vector-move-left!} copies elements in leftmost order.\n"
521 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
522 "same vector, @code{vector-move-left!} is usually appropriate when\n"
523 "@var{start1} is greater than @var{start2}.")
1bbd0b84 524#define FUNC_NAME s_scm_vector_move_left_x
0f2d19dd 525{
6e708ef2
MV
526 scm_t_array_handle handle1, handle2;
527 const SCM *elts1;
528 SCM *elts2;
de5c0f58 529 size_t len1, len2;
6e708ef2 530 ssize_t inc1, inc2;
a55c2b68 531 size_t i, j, e;
6e708ef2
MV
532
533 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
534 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
34d19ef6 535
de5c0f58
MV
536 i = scm_to_unsigned_integer (start1, 0, len1);
537 e = scm_to_unsigned_integer (end1, i, len1);
ca659673 538 SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
551b96d2
AW
539 j = scm_to_unsigned_integer (start2, 0, len2);
540 SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
de5c0f58 541
6e708ef2
MV
542 i *= inc1;
543 e *= inc1;
544 j *= inc2;
545 for (; i < e; i += inc1, j += inc2)
546 elts2[j] = elts1[i];
547
c8857a4d
MV
548 scm_array_handle_release (&handle2);
549 scm_array_handle_release (&handle1);
550
0f2d19dd
JB
551 return SCM_UNSPECIFIED;
552}
1bbd0b84 553#undef FUNC_NAME
0f2d19dd 554
a1ec6916 555SCM_DEFINE (scm_vector_move_right_x, "vector-move-right!", 5, 0, 0,
1bbd0b84 556 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
694a9bb3
NJ
557 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
558 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
559 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
560 "@code{vector-move-right!} copies elements in rightmost order.\n"
561 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
562 "same vector, @code{vector-move-right!} is usually appropriate when\n"
563 "@var{start1} is less than @var{start2}.")
1bbd0b84 564#define FUNC_NAME s_scm_vector_move_right_x
0f2d19dd 565{
6e708ef2
MV
566 scm_t_array_handle handle1, handle2;
567 const SCM *elts1;
568 SCM *elts2;
de5c0f58 569 size_t len1, len2;
6e708ef2 570 ssize_t inc1, inc2;
a55c2b68 571 size_t i, j, e;
6e708ef2
MV
572
573 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
574 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
0f2d19dd 575
de5c0f58
MV
576 i = scm_to_unsigned_integer (start1, 0, len1);
577 e = scm_to_unsigned_integer (end1, i, len1);
ca659673 578 SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
551b96d2
AW
579 j = scm_to_unsigned_integer (start2, 0, len2);
580 SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
581
582 j += (e - i);
de5c0f58 583
6e708ef2
MV
584 i *= inc1;
585 e *= inc1;
586 j *= inc2;
587 while (i < e)
de5c0f58 588 {
6e708ef2
MV
589 e -= inc1;
590 j -= inc2;
591 elts2[j] = elts1[e];
de5c0f58 592 }
6e708ef2 593
c8857a4d
MV
594 scm_array_handle_release (&handle2);
595 scm_array_handle_release (&handle1);
596
0f2d19dd
JB
597 return SCM_UNSPECIFIED;
598}
1bbd0b84 599#undef FUNC_NAME
0f2d19dd 600
438974d0 601\f
2a610be5
AW
602static SCM
603vector_handle_ref (scm_t_array_handle *h, size_t idx)
88797580 604{
2a610be5
AW
605 if (idx > h->dims[0].ubnd)
606 scm_out_of_range ("vector-handle-ref", scm_from_size_t (idx));
607 return ((SCM*)h->elements)[idx];
88797580
MV
608}
609
2a610be5
AW
610static void
611vector_handle_set (scm_t_array_handle *h, size_t idx, SCM val)
88797580 612{
2a610be5
AW
613 if (idx > h->dims[0].ubnd)
614 scm_out_of_range ("vector-handle-set!", scm_from_size_t (idx));
615 ((SCM*)h->writable_elements)[idx] = val;
88797580 616}
88797580 617
2a610be5
AW
618static void
619vector_get_handle (SCM v, scm_t_array_handle *h)
88797580 620{
2a610be5
AW
621 h->array = v;
622 h->ndims = 1;
623 h->dims = &h->dim0;
624 h->dim0.lbnd = 0;
625 h->dim0.ubnd = SCM_I_VECTOR_LENGTH (v) - 1;
626 h->dim0.inc = 1;
627 h->element_type = SCM_ARRAY_ELEMENT_TYPE_SCM;
628 h->elements = h->writable_elements = SCM_I_VECTOR_WELTS (v);
88797580
MV
629}
630
c5f17102
AW
631/* the & ~2 allows catching scm_tc7_wvect as well. needs changing if you change
632 tags.h. */
2a610be5
AW
633SCM_ARRAY_IMPLEMENTATION (scm_tc7_vector, 0x7f & ~2,
634 vector_handle_ref, vector_handle_set,
f65e0168 635 vector_get_handle)
f65e0168 636SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_SCM, scm_make_vector)
88797580 637
1cc91f1b 638
0f2d19dd
JB
639void
640scm_init_vectors ()
0f2d19dd 641{
a0599745 642#include "libguile/vectors.x"
0f2d19dd
JB
643}
644
89e00824
ML
645
646/*
647 Local Variables:
648 c-file-style: "gnu"
649 End:
650*/