fix fencepost error in vector-move-left! and -right!
[bpt/guile.git] / libguile / vectors.c
CommitLineData
cd038da5 1/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006, 2008, 2009, 2010 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
216 if ((elt == SCM_PACK (NULL)) && SCM_I_WVECTP (v))
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
235 if ((elt == SCM_PACK (NULL)) && (SCM_I_WVECTP (vv)))
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]);
dbe4d258 281 SCM_I_REGISTER_DISAPPEARING_LINK (link, obj);
3a2de079 282 }
de5c0f58 283 }
04b87de5 284 else if (SCM_I_ARRAYP (v) && SCM_I_ARRAY_NDIM (v) == 1)
de5c0f58 285 {
04b87de5
MV
286 scm_t_array_dim *dim = SCM_I_ARRAY_DIMS (v);
287 SCM vv = SCM_I_ARRAY_V (v);
6e708ef2
MV
288 if (SCM_I_IS_VECTOR (vv))
289 {
290 if (k >= dim->ubnd - dim->lbnd + 1)
291 scm_out_of_range (NULL, scm_from_size_t (k));
04b87de5 292 k = SCM_I_ARRAY_BASE (v) + k*dim->inc;
6e708ef2 293 (SCM_I_VECTOR_WELTS (vv))[k] = obj;
3a2de079
LC
294
295 if (SCM_I_WVECTP (vv))
296 {
297 /* Make it a weak pointer. */
298 GC_PTR link = (GC_PTR) & ((SCM_I_VECTOR_WELTS (vv))[k]);
dbe4d258 299 SCM_I_REGISTER_DISAPPEARING_LINK (link, obj);
3a2de079 300 }
6e708ef2
MV
301 }
302 else
303 scm_wrong_type_arg_msg (NULL, 0, v, "non-uniform vector");
88797580
MV
304 }
305 else
306 {
de5c0f58
MV
307 if (SCM_UNPACK (g_vector_set_x))
308 scm_apply_generic (g_vector_set_x,
309 scm_list_3 (v, scm_from_size_t (k), obj));
310 else
311 scm_wrong_type_arg_msg (NULL, 0, v, "vector");
88797580
MV
312 }
313}
0f2d19dd 314
a1ec6916 315SCM_DEFINE (scm_make_vector, "make-vector", 1, 1, 0,
1bbd0b84 316 (SCM k, SCM fill),
1e6808ea 317 "Return a newly allocated vector of @var{k} elements. If a\n"
8f85c0c6
NJ
318 "second argument is given, then each position is initialized to\n"
319 "@var{fill}. Otherwise the initial contents of each position is\n"
1e6808ea 320 "unspecified.")
1bbd0b84 321#define FUNC_NAME s_scm_make_vector
0f2d19dd 322{
6e708ef2 323 size_t l = scm_to_unsigned_integer (k, 0, VECTOR_MAX_LENGTH);
e11e83f3 324
1b9be268 325 if (SCM_UNBNDP (fill))
d60cebe2 326 fill = SCM_UNSPECIFIED;
e11e83f3
MV
327
328 return scm_c_make_vector (l, fill);
00ffa0e7
KN
329}
330#undef FUNC_NAME
331
e382fdbe 332
00ffa0e7 333SCM
88797580 334scm_c_make_vector (size_t k, SCM fill)
00ffa0e7
KN
335#define FUNC_NAME s_scm_make_vector
336{
ed7e0765 337 SCM *vector;
1b9be268 338
ed7e0765
LC
339 vector = (SCM *)
340 scm_gc_malloc ((k + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM),
341 "vector");
342
343 if (k > 0)
e382fdbe 344 {
ed7e0765 345 SCM *base;
c014a02e 346 unsigned long int j;
1b9be268 347
6e708ef2 348 SCM_ASSERT_RANGE (1, scm_from_ulong (k), k <= VECTOR_MAX_LENGTH);
1b9be268 349
ed7e0765 350 base = vector + SCM_I_VECTOR_HEADER_SIZE;
e382fdbe 351 for (j = 0; j != k; ++j)
6e708ef2 352 base[j] = fill;
e382fdbe 353 }
1b9be268 354
ed7e0765
LC
355 ((scm_t_bits *) vector)[0] = (k << 8) | scm_tc7_vector;
356 ((scm_t_bits *) vector)[1] = 0;
1b9be268 357
ed7e0765 358 return PTR2SCM (vector);
0f2d19dd 359}
1bbd0b84 360#undef FUNC_NAME
0f2d19dd 361
6e708ef2
MV
362SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
363 (SCM vec),
364 "Return a copy of @var{vec}.")
365#define FUNC_NAME s_scm_vector_copy
366{
367 scm_t_array_handle handle;
368 size_t i, len;
369 ssize_t inc;
370 const SCM *src;
ed7e0765 371 SCM result, *dst;
6e708ef2
MV
372
373 src = scm_vector_elements (vec, &handle, &len, &inc);
ed7e0765
LC
374
375 result = scm_c_make_vector (len, SCM_UNDEFINED);
376 dst = SCM_I_VECTOR_WELTS (result);
6e708ef2
MV
377 for (i = 0; i < len; i++, src += inc)
378 dst[i] = *src;
ed7e0765 379
c8857a4d 380 scm_array_handle_release (&handle);
6e708ef2 381
ed7e0765 382 return result;
6e708ef2
MV
383}
384#undef FUNC_NAME
385
d525e4f9
LC
386\f
387/* Weak vectors. */
388
d525e4f9
LC
389/* Allocate memory for the elements of a weak vector on behalf of the
390 caller. */
ed7e0765
LC
391static SCM
392make_weak_vector (scm_t_bits type, size_t c_size)
6e708ef2 393{
ed7e0765
LC
394 SCM *vector;
395 size_t total_size;
d525e4f9 396
ed7e0765
LC
397 total_size = (c_size + SCM_I_VECTOR_HEADER_SIZE) * sizeof (SCM);
398 vector = (SCM *) scm_gc_malloc_pointerless (total_size, "weak vector");
d525e4f9 399
ed7e0765
LC
400 ((scm_t_bits *) vector)[0] = (c_size << 8) | scm_tc7_wvect;
401 ((scm_t_bits *) vector)[1] = type;
402
403 return PTR2SCM (vector);
d525e4f9
LC
404}
405
406/* Return a new weak vector. The allocated vector will be of the given weak
407 vector subtype. It will contain SIZE elements which are initialized with
408 the FILL object, or, if FILL is undefined, with an unspecified object. */
409SCM
410scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill)
411{
412 SCM wv, *base;
413 size_t c_size, j;
414
415 if (SCM_UNBNDP (fill))
416 fill = SCM_UNSPECIFIED;
6e708ef2
MV
417
418 c_size = scm_to_unsigned_integer (size, 0, VECTOR_MAX_LENGTH);
ed7e0765
LC
419 wv = make_weak_vector (type, c_size);
420 base = SCM_I_WVECT_GC_WVELTS (wv);
6e708ef2 421
d525e4f9
LC
422 for (j = 0; j != c_size; ++j)
423 base[j] = fill;
3a2de079 424
d525e4f9
LC
425 return wv;
426}
427
428/* Return a new weak vector with type TYPE and whose content are taken from
429 list LST. */
430SCM
431scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst)
432{
ed7e0765 433 SCM wv, *elt;
d525e4f9
LC
434 long c_size;
435
436 c_size = scm_ilength (lst);
437 SCM_ASSERT (c_size >= 0, lst, SCM_ARG2, "scm_i_make_weak_vector_from_list");
438
ed7e0765
LC
439 wv = make_weak_vector(type, (size_t) c_size);
440
441 for (elt = SCM_I_WVECT_GC_WVELTS (wv);
d525e4f9
LC
442 scm_is_pair (lst);
443 lst = SCM_CDR (lst), elt++)
444 {
445 *elt = SCM_CAR (lst);
6e708ef2 446 }
6e708ef2 447
d525e4f9 448 return wv;
6e708ef2 449}
e382fdbe 450
d525e4f9
LC
451
452\f
3b3b36dd 453SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
1e6808ea 454 (SCM v),
8f85c0c6 455 "Return a newly allocated list composed of the elements of @var{v}.\n"
1e6808ea 456 "\n"
942e5b91
MG
457 "@lisp\n"
458 "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
459 "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
460 "@end lisp")
1bbd0b84 461#define FUNC_NAME s_scm_vector_to_list
0f2d19dd 462{
6e708ef2
MV
463 SCM res = SCM_EOL;
464 const SCM *data;
465 scm_t_array_handle handle;
22be72d3 466 size_t i, count, len;
6e708ef2
MV
467 ssize_t inc;
468
469 data = scm_vector_elements (v, &handle, &len, &inc);
22be72d3
LC
470 for (i = (len - 1) * inc, count = 0;
471 count < len;
472 i -= inc, count++)
473 res = scm_cons (data[i], res);
474
c8857a4d 475 scm_array_handle_release (&handle);
6e708ef2 476 return res;
0f2d19dd 477}
1bbd0b84 478#undef FUNC_NAME
0f2d19dd
JB
479
480
a1ec6916 481SCM_DEFINE (scm_vector_fill_x, "vector-fill!", 2, 0, 0,
1e6808ea 482 (SCM v, SCM fill),
8f85c0c6 483 "Store @var{fill} in every position of @var{vector}. The value\n"
1e6808ea 484 "returned by @code{vector-fill!} is unspecified.")
1bbd0b84 485#define FUNC_NAME s_scm_vector_fill_x
0f2d19dd 486{
6e708ef2
MV
487 scm_t_array_handle handle;
488 SCM *data;
489 size_t i, len;
490 ssize_t inc;
491
492 data = scm_vector_writable_elements (v, &handle, &len, &inc);
493 for (i = 0; i < len; i += inc)
494 data[i] = fill;
c8857a4d 495 scm_array_handle_release (&handle);
6e708ef2 496 return SCM_UNSPECIFIED;
0f2d19dd 497}
1bbd0b84 498#undef FUNC_NAME
0f2d19dd
JB
499
500
0f2d19dd 501SCM
354116f7 502scm_i_vector_equal_p (SCM x, SCM y)
0f2d19dd 503{
c014a02e 504 long i;
6e708ef2
MV
505 for (i = SCM_I_VECTOR_LENGTH (x) - 1; i >= 0; i--)
506 if (scm_is_false (scm_equal_p (SCM_I_VECTOR_ELTS (x)[i],
507 SCM_I_VECTOR_ELTS (y)[i])))
0f2d19dd
JB
508 return SCM_BOOL_F;
509 return SCM_BOOL_T;
510}
511
512
a1ec6916 513SCM_DEFINE (scm_vector_move_left_x, "vector-move-left!", 5, 0, 0,
1bbd0b84 514 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
694a9bb3
NJ
515 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
516 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
517 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
518 "@code{vector-move-left!} copies elements in leftmost order.\n"
519 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
520 "same vector, @code{vector-move-left!} is usually appropriate when\n"
521 "@var{start1} is greater than @var{start2}.")
1bbd0b84 522#define FUNC_NAME s_scm_vector_move_left_x
0f2d19dd 523{
6e708ef2
MV
524 scm_t_array_handle handle1, handle2;
525 const SCM *elts1;
526 SCM *elts2;
de5c0f58 527 size_t len1, len2;
6e708ef2 528 ssize_t inc1, inc2;
a55c2b68 529 size_t i, j, e;
6e708ef2
MV
530
531 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
532 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
34d19ef6 533
de5c0f58
MV
534 i = scm_to_unsigned_integer (start1, 0, len1);
535 e = scm_to_unsigned_integer (end1, i, len1);
ca659673 536 SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
551b96d2
AW
537 j = scm_to_unsigned_integer (start2, 0, len2);
538 SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
de5c0f58 539
6e708ef2
MV
540 i *= inc1;
541 e *= inc1;
542 j *= inc2;
543 for (; i < e; i += inc1, j += inc2)
544 elts2[j] = elts1[i];
545
c8857a4d
MV
546 scm_array_handle_release (&handle2);
547 scm_array_handle_release (&handle1);
548
0f2d19dd
JB
549 return SCM_UNSPECIFIED;
550}
1bbd0b84 551#undef FUNC_NAME
0f2d19dd 552
a1ec6916 553SCM_DEFINE (scm_vector_move_right_x, "vector-move-right!", 5, 0, 0,
1bbd0b84 554 (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
694a9bb3
NJ
555 "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
556 "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
557 "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
558 "@code{vector-move-right!} copies elements in rightmost order.\n"
559 "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
560 "same vector, @code{vector-move-right!} is usually appropriate when\n"
561 "@var{start1} is less than @var{start2}.")
1bbd0b84 562#define FUNC_NAME s_scm_vector_move_right_x
0f2d19dd 563{
6e708ef2
MV
564 scm_t_array_handle handle1, handle2;
565 const SCM *elts1;
566 SCM *elts2;
de5c0f58 567 size_t len1, len2;
6e708ef2 568 ssize_t inc1, inc2;
a55c2b68 569 size_t i, j, e;
6e708ef2
MV
570
571 elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
572 elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
0f2d19dd 573
de5c0f58
MV
574 i = scm_to_unsigned_integer (start1, 0, len1);
575 e = scm_to_unsigned_integer (end1, i, len1);
ca659673 576 SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
551b96d2
AW
577 j = scm_to_unsigned_integer (start2, 0, len2);
578 SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
579
580 j += (e - i);
de5c0f58 581
6e708ef2
MV
582 i *= inc1;
583 e *= inc1;
584 j *= inc2;
585 while (i < e)
de5c0f58 586 {
6e708ef2
MV
587 e -= inc1;
588 j -= inc2;
589 elts2[j] = elts1[e];
de5c0f58 590 }
6e708ef2 591
c8857a4d
MV
592 scm_array_handle_release (&handle2);
593 scm_array_handle_release (&handle1);
594
0f2d19dd
JB
595 return SCM_UNSPECIFIED;
596}
1bbd0b84 597#undef FUNC_NAME
0f2d19dd 598
438974d0 599\f
2a610be5
AW
600static SCM
601vector_handle_ref (scm_t_array_handle *h, size_t idx)
88797580 602{
2a610be5
AW
603 if (idx > h->dims[0].ubnd)
604 scm_out_of_range ("vector-handle-ref", scm_from_size_t (idx));
605 return ((SCM*)h->elements)[idx];
88797580
MV
606}
607
2a610be5
AW
608static void
609vector_handle_set (scm_t_array_handle *h, size_t idx, SCM val)
88797580 610{
2a610be5
AW
611 if (idx > h->dims[0].ubnd)
612 scm_out_of_range ("vector-handle-set!", scm_from_size_t (idx));
613 ((SCM*)h->writable_elements)[idx] = val;
88797580 614}
88797580 615
2a610be5
AW
616static void
617vector_get_handle (SCM v, scm_t_array_handle *h)
88797580 618{
2a610be5
AW
619 h->array = v;
620 h->ndims = 1;
621 h->dims = &h->dim0;
622 h->dim0.lbnd = 0;
623 h->dim0.ubnd = SCM_I_VECTOR_LENGTH (v) - 1;
624 h->dim0.inc = 1;
625 h->element_type = SCM_ARRAY_ELEMENT_TYPE_SCM;
626 h->elements = h->writable_elements = SCM_I_VECTOR_WELTS (v);
88797580
MV
627}
628
c5f17102
AW
629/* the & ~2 allows catching scm_tc7_wvect as well. needs changing if you change
630 tags.h. */
2a610be5
AW
631SCM_ARRAY_IMPLEMENTATION (scm_tc7_vector, 0x7f & ~2,
632 vector_handle_ref, vector_handle_set,
f65e0168 633 vector_get_handle)
f65e0168 634SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_SCM, scm_make_vector)
88797580 635
1cc91f1b 636
0f2d19dd
JB
637void
638scm_init_vectors ()
0f2d19dd 639{
a0599745 640#include "libguile/vectors.x"
0f2d19dd
JB
641}
642
89e00824
ML
643
644/*
645 Local Variables:
646 c-file-style: "gnu"
647 End:
648*/