(scm_array_handle_set): Correctly execute only one
[bpt/guile.git] / libguile / unif.c
CommitLineData
18e2aba3 1/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004 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
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
c209c88e
GB
19/*
20 This file has code for arrays in lots of variants (double, integer,
21 unsigned etc. ). It suffers from hugely repetitive code because
22 there is similar (but different) code for every variant included. (urg.)
23
24 --hwn
25*/
0f2d19dd
JB
26\f
27
2a5cd898
RB
28#if HAVE_CONFIG_H
29# include <config.h>
30#endif
31
0f2d19dd 32#include <stdio.h>
e6e2e95a 33#include <errno.h>
783e7774 34#include <string.h>
e6e2e95a 35
a0599745 36#include "libguile/_scm.h"
e0e49670
MV
37#include "libguile/__scm.h"
38#include "libguile/eq.h"
a0599745
MD
39#include "libguile/chars.h"
40#include "libguile/eval.h"
41#include "libguile/fports.h"
42#include "libguile/smob.h"
a0599745
MD
43#include "libguile/feature.h"
44#include "libguile/root.h"
45#include "libguile/strings.h"
c44ca4fe 46#include "libguile/srfi-13.h"
e0e49670 47#include "libguile/srfi-4.h"
a0599745 48#include "libguile/vectors.h"
bfad4005
MV
49#include "libguile/list.h"
50#include "libguile/deprecation.h"
d44ff083 51#include "libguile/dynwind.h"
a0599745
MD
52
53#include "libguile/validate.h"
54#include "libguile/unif.h"
55#include "libguile/ramap.h"
f27d2057 56#include "libguile/print.h"
bfad4005 57#include "libguile/read.h"
0f2d19dd 58
3d8d56df
GH
59#ifdef HAVE_UNISTD_H
60#include <unistd.h>
61#endif
62
7beabedb
MG
63#ifdef HAVE_IO_H
64#include <io.h>
65#endif
66
0f2d19dd
JB
67\f
68/* The set of uniform scm_vector types is:
e0e49670 69 * Vector of: Called: Replaced by:
bfad4005 70 * unsigned char string
85368844 71 * char byvect s8 or u8, depending on signedness of 'char'
e0e49670
MV
72 * boolean bvect
73 * signed long ivect s32
74 * unsigned long uvect u32
75 * float fvect f32
76 * double dvect d32
85368844 77 * complex double cvect c64
e0e49670
MV
78 * short svect s16
79 * long long llvect s64
0f2d19dd
JB
80 */
81
92c2555f 82scm_t_bits scm_tc16_array;
02339e5b 83scm_t_bits scm_tc16_enclosed_array;
1cc91f1b 84
f301dbf3
MV
85typedef SCM creator_proc (SCM len, SCM fill);
86
87struct {
88 char *type_name;
89 SCM type;
90 creator_proc *creator;
91} type_creator_table[] = {
92 { "a", SCM_UNSPECIFIED, scm_make_string },
93 { "b", SCM_UNSPECIFIED, scm_make_bitvector },
94 { "u8", SCM_UNSPECIFIED, scm_make_u8vector },
95 { "s8", SCM_UNSPECIFIED, scm_make_s8vector },
96 { "u16", SCM_UNSPECIFIED, scm_make_u16vector },
97 { "s16", SCM_UNSPECIFIED, scm_make_s16vector },
98 { "u32", SCM_UNSPECIFIED, scm_make_u32vector },
99 { "s32", SCM_UNSPECIFIED, scm_make_s32vector },
100 { "u64", SCM_UNSPECIFIED, scm_make_u64vector },
101 { "s64", SCM_UNSPECIFIED, scm_make_s64vector },
102 { "f32", SCM_UNSPECIFIED, scm_make_f32vector },
103 { "f64", SCM_UNSPECIFIED, scm_make_f64vector },
104 { "c32", SCM_UNSPECIFIED, scm_make_c32vector },
105 { "c64", SCM_UNSPECIFIED, scm_make_c64vector },
106 { NULL }
107};
108
109static void
110init_type_creator_table ()
111{
112 int i;
113 for (i = 0; type_creator_table[i].type_name; i++)
114 {
115 SCM sym = scm_from_locale_symbol (type_creator_table[i].type_name);
116 type_creator_table[i].type = scm_permanent_object (sym);
117 }
118}
119
120static creator_proc *
121type_to_creator (SCM type)
122{
123 int i;
124
125 if (scm_is_eq (type, SCM_BOOL_T))
126 return scm_make_vector;
127 for (i = 0; type_creator_table[i].type_name; i++)
128 if (scm_is_eq (type, type_creator_table[i].type))
129 return type_creator_table[i].creator;
130
131 scm_misc_error (NULL, "unknown array type: ~a", scm_list_1 (type));
132}
133
134static SCM
135make_typed_vector (SCM type, size_t len)
136{
137 creator_proc *creator = type_to_creator (type);
138 return creator (scm_from_size_t (len), SCM_UNDEFINED);
139}
bfad4005
MV
140
141#if SCM_ENABLE_DEPRECATED
142
143SCM_SYMBOL (scm_sym_s, "s");
144SCM_SYMBOL (scm_sym_l, "l");
145
711a9fd7 146static SCM
f301dbf3 147prototype_to_type (SCM proto)
711a9fd7 148{
f301dbf3 149 const char *type_name;
bfad4005
MV
150
151 if (scm_is_eq (proto, SCM_BOOL_T))
f301dbf3 152 type_name = "b";
bfad4005 153 else if (scm_is_eq (proto, SCM_MAKE_CHAR ('a')))
f301dbf3 154 type_name = "a";
bfad4005 155 else if (scm_is_eq (proto, SCM_MAKE_CHAR (0)))
f301dbf3 156 type_name = "s8";
bfad4005 157 else if (scm_is_eq (proto, scm_sym_s))
f301dbf3 158 type_name = "s16";
bfad4005 159 else if (scm_is_true (scm_eqv_p (proto, scm_from_int (1))))
f301dbf3 160 type_name = "u32";
bfad4005 161 else if (scm_is_true (scm_eqv_p (proto, scm_from_int (-1))))
f301dbf3 162 type_name = "s32";
bfad4005 163 else if (scm_is_eq (proto, scm_sym_l))
f301dbf3 164 type_name = "s64";
bfad4005 165 else if (scm_is_true (scm_eqv_p (proto, scm_from_double (1.0))))
f301dbf3 166 type_name = "f32";
bfad4005 167 else if (scm_is_true (scm_eqv_p (proto, scm_divide (scm_from_int (1),
f301dbf3
MV
168 scm_from_int (3)))))
169 type_name = "f64";
bfad4005 170 else if (scm_is_true (scm_eqv_p (proto, scm_c_make_rectangular (0, 1))))
f301dbf3 171 type_name = "c64";
bfad4005 172 else if (scm_is_null (proto))
f301dbf3 173 type_name = NULL;
bfad4005 174 else
f301dbf3 175 type_name = NULL;
711a9fd7 176
f301dbf3
MV
177 if (type_name)
178 return scm_from_locale_symbol (type_name);
179 else
180 return SCM_BOOL_T;
711a9fd7 181}
bfad4005 182
ab1be174
MV
183static SCM
184scm_i_get_old_prototype (SCM uvec)
185{
20930f28 186 if (scm_is_bitvector (uvec))
ab1be174
MV
187 return SCM_BOOL_T;
188 else if (scm_is_string (uvec))
189 return SCM_MAKE_CHAR ('a');
190 else if (scm_is_true (scm_s8vector_p (uvec)))
191 return SCM_MAKE_CHAR ('\0');
192 else if (scm_is_true (scm_s16vector_p (uvec)))
193 return scm_sym_s;
194 else if (scm_is_true (scm_u32vector_p (uvec)))
195 return scm_from_int (1);
196 else if (scm_is_true (scm_s32vector_p (uvec)))
197 return scm_from_int (-1);
198 else if (scm_is_true (scm_s64vector_p (uvec)))
199 return scm_sym_l;
200 else if (scm_is_true (scm_f32vector_p (uvec)))
201 return scm_from_double (1.0);
202 else if (scm_is_true (scm_f64vector_p (uvec)))
203 return scm_divide (scm_from_int (1), scm_from_int (3));
204 else if (scm_is_true (scm_c64vector_p (uvec)))
205 return scm_c_make_rectangular (0, 1);
20930f28 206 else if (scm_is_vector (uvec))
ab1be174
MV
207 return SCM_EOL;
208 else
03a5397a 209 scm_misc_error (NULL, "~a has no prototype", scm_list_1 (uvec));
ab1be174
MV
210}
211
0f2d19dd 212SCM
c014a02e 213scm_make_uve (long k, SCM prot)
a3a32939 214#define FUNC_NAME "scm_make_uve"
0f2d19dd 215{
f301dbf3
MV
216 scm_c_issue_deprecation_warning
217 ("`scm_make_uve' is deprecated, see the manual for alternatives.");
218
219 return make_typed_vector (prototype_to_type (prot), k);
0f2d19dd 220}
a3a32939
DH
221#undef FUNC_NAME
222
f301dbf3
MV
223#endif
224
225int
226scm_is_array (SCM obj)
0f2d19dd 227{
f301dbf3
MV
228 return (SCM_ENCLOSED_ARRAYP (obj)
229 || SCM_ARRAYP (obj)
230 || scm_is_generalized_vector (obj));
231}
232
233int
234scm_is_typed_array (SCM obj, SCM type)
235{
236 if (SCM_ENCLOSED_ARRAYP (obj))
0f2d19dd 237 {
f301dbf3 238 /* Enclosed arrays are arrays but are not of any type.
02339e5b 239 */
f301dbf3 240 return 0;
e0e49670
MV
241 }
242
02339e5b
MV
243 /* Get storage vector.
244 */
f301dbf3
MV
245 if (SCM_ARRAYP (obj))
246 obj = SCM_ARRAY_V (obj);
02339e5b 247
20930f28 248 /* It must be a generalized vector (which includes vectors, strings, etc).
bfad4005 249 */
f301dbf3
MV
250 if (!scm_is_generalized_vector (obj))
251 return 0;
9b0018a1 252
f301dbf3
MV
253 return scm_is_eq (type, scm_i_generalized_vector_type (obj));
254}
20930f28 255
6e708ef2
MV
256void
257scm_array_get_handle (SCM array, scm_t_array_handle *h)
258{
259 h->array = array;
260 if (SCM_ARRAYP (array) || SCM_ENCLOSED_ARRAYP (array))
261 {
262 h->dims = SCM_ARRAY_DIMS (array);
263 h->base = SCM_ARRAY_BASE (array);
264 }
265 else if (scm_is_generalized_vector (array))
266 {
267 h->dim0.lbnd = 0;
268 h->dim0.ubnd = scm_c_generalized_vector_length (array) - 1;
269 h->dim0.inc = 1;
270 h->dims = &h->dim0;
271 h->base = 0;
272 }
273 else
274 scm_wrong_type_arg_msg (NULL, 0, array, "array");
275}
276
cdd6e0a8
MV
277void
278scm_array_handle_release (scm_t_array_handle *h)
279{
280 /* Nothing to do here until arrays need to be reserved for real.
281 */
282}
283
6e708ef2
MV
284size_t
285scm_array_handle_rank (scm_t_array_handle *h)
286{
287 if (SCM_ARRAYP (h->array) || SCM_ENCLOSED_ARRAYP (h->array))
288 return SCM_ARRAY_NDIM (h->array);
289 else
290 return 1;
291}
292
293scm_t_array_dim *
294scm_array_handle_dims (scm_t_array_handle *h)
295{
296 return h->dims;
297}
298
299SCM
cdd6e0a8 300scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos)
6e708ef2
MV
301{
302 pos += h->base;
303 if (SCM_ARRAYP (h->array))
304 return scm_i_cvref (SCM_ARRAY_V (h->array), pos, 0);
305 if (SCM_ENCLOSED_ARRAYP (h->array))
306 return scm_i_cvref (SCM_ARRAY_V (h->array), pos, 1);
307 return scm_c_generalized_vector_ref (h->array, pos);
308}
309
310void
cdd6e0a8 311scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM val)
6e708ef2
MV
312{
313 pos += h->base;
314 if (SCM_ARRAYP (h->array))
315 scm_c_generalized_vector_set_x (SCM_ARRAY_V (h->array), pos, val);
bcbbea0e 316 else if (SCM_ENCLOSED_ARRAYP (h->array))
6e708ef2 317 scm_wrong_type_arg_msg (NULL, 0, h->array, "non-enclosed array");
bcbbea0e
MV
318 else
319 scm_c_generalized_vector_set_x (h->array, pos, val);
6e708ef2
MV
320}
321
322const SCM *
323scm_array_handle_elements (scm_t_array_handle *h)
324{
325 SCM vec = h->array;
326 if (SCM_ARRAYP (vec))
327 vec = SCM_ARRAY_V (vec);
328 if (SCM_I_IS_VECTOR (vec))
329 return SCM_I_VECTOR_ELTS (vec) + h->base;
330 scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
331}
332
333SCM *
334scm_array_handle_writable_elements (scm_t_array_handle *h)
335{
336 SCM vec = h->array;
337 if (SCM_ARRAYP (vec))
338 vec = SCM_ARRAY_V (vec);
339 if (SCM_I_IS_VECTOR (vec))
340 return SCM_I_VECTOR_WELTS (vec) + h->base;
341 scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
342}
343
20930f28 344#if SCM_ENABLE_DEPRECATED
f301dbf3
MV
345
346SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
347 (SCM obj, SCM prot),
348 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
349 "not.")
350#define FUNC_NAME s_scm_array_p
351{
352 if (!SCM_UNBNDP (prot))
353 {
354 scm_c_issue_deprecation_warning
355 ("Using prototypes with `array?' is deprecated."
356 " Use `typed-array?' instead.");
357
358 return scm_typed_array_p (obj, prototype_to_type (prot));
359 }
360 else
361 return scm_from_bool (scm_is_array (obj));
362}
363#undef FUNC_NAME
364
365#else /* !SCM_ENABLE_DEPRECATED */
366
367/* We keep the old 2-argument C prototype for a while although the old
368 PROT argument is always ignored now. C code should probably use
369 scm_is_array or scm_is_typed_array anyway.
370*/
371
6e708ef2
MV
372static SCM scm_i_array_p (SCM obj);
373
374SCM_DEFINE (scm_i_array_p, "array?", 1, 0, 0,
375 (SCM obj),
f301dbf3
MV
376 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
377 "not.")
6e708ef2 378#define FUNC_NAME s_scm_i_array_p
f301dbf3
MV
379{
380 return scm_from_bool (scm_is_array (obj));
381}
382#undef FUNC_NAME
383
6e708ef2
MV
384SCM
385scm_array_p (SCM obj, SCM prot)
386{
387 return scm_from_bool (scm_is_array (obj));
388}
389
f301dbf3
MV
390#endif /* !SCM_ENABLE_DEPRECATED */
391
392
393SCM_DEFINE (scm_typed_array_p, "typed-array?", 2, 0, 0,
394 (SCM obj, SCM type),
395 "Return @code{#t} if the @var{obj} is an array of type\n"
396 "@var{type}, and @code{#f} if not.")
397#define FUNC_NAME s_scm_typed_array_p
398{
399 return scm_from_bool (scm_is_typed_array (obj, type));
0f2d19dd 400}
1bbd0b84 401#undef FUNC_NAME
0f2d19dd
JB
402
403
3b3b36dd 404SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
02339e5b
MV
405 (SCM array),
406 "Return the number of dimensions of the array @var{array.}\n")
1bbd0b84 407#define FUNC_NAME s_scm_array_rank
0f2d19dd 408{
02339e5b 409 if (scm_is_generalized_vector (array))
e0e49670
MV
410 return scm_from_int (1);
411
02339e5b
MV
412 if (SCM_ARRAYP (array) || SCM_ENCLOSED_ARRAYP (array))
413 return scm_from_size_t (SCM_ARRAY_NDIM (array));
20930f28 414
02339e5b 415 scm_wrong_type_arg_msg (NULL, 0, array, "array");
0f2d19dd 416}
1bbd0b84 417#undef FUNC_NAME
0f2d19dd
JB
418
419
3b3b36dd 420SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 421 (SCM ra),
02339e5b 422 "@code{array-dimensions} is similar to @code{array-shape} but replaces\n"
b380b885 423 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
1e6808ea 424 "@lisp\n"
b380b885 425 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
1e6808ea 426 "@end lisp")
1bbd0b84 427#define FUNC_NAME s_scm_array_dimensions
0f2d19dd 428{
20930f28 429 if (scm_is_generalized_vector (ra))
f301dbf3 430 return scm_list_1 (scm_generalized_vector_length (ra));
e0e49670 431
02339e5b 432 if (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra))
0f2d19dd 433 {
20930f28
MV
434 SCM res = SCM_EOL;
435 size_t k;
436 scm_t_array_dim *s;
437
0f2d19dd
JB
438 k = SCM_ARRAY_NDIM (ra);
439 s = SCM_ARRAY_DIMS (ra);
440 while (k--)
e2d37336 441 res = scm_cons (s[k].lbnd
e11e83f3
MV
442 ? scm_cons2 (scm_from_long (s[k].lbnd),
443 scm_from_long (s[k].ubnd),
e2d37336 444 SCM_EOL)
e11e83f3 445 : scm_from_long (1 + s[k].ubnd),
e2d37336 446 res);
0f2d19dd
JB
447 return res;
448 }
20930f28
MV
449
450 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 451}
1bbd0b84 452#undef FUNC_NAME
0f2d19dd
JB
453
454
e2d37336
MD
455SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
456 (SCM ra),
457 "Return the root vector of a shared array.")
458#define FUNC_NAME s_scm_shared_array_root
459{
02339e5b
MV
460 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
461 SCM_ARG1, FUNC_NAME);
e2d37336
MD
462 return SCM_ARRAY_V (ra);
463}
464#undef FUNC_NAME
465
466
467SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
468 (SCM ra),
469 "Return the root vector index of the first element in the array.")
470#define FUNC_NAME s_scm_shared_array_offset
471{
02339e5b
MV
472 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
473 SCM_ARG1, FUNC_NAME);
e11e83f3 474 return scm_from_int (SCM_ARRAY_BASE (ra));
e2d37336
MD
475}
476#undef FUNC_NAME
477
478
479SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
480 (SCM ra),
481 "For each dimension, return the distance between elements in the root vector.")
482#define FUNC_NAME s_scm_shared_array_increments
483{
484 SCM res = SCM_EOL;
1be6b49c 485 size_t k;
92c2555f 486 scm_t_array_dim *s;
02339e5b
MV
487
488 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
489 SCM_ARG1, FUNC_NAME);
e2d37336
MD
490 k = SCM_ARRAY_NDIM (ra);
491 s = SCM_ARRAY_DIMS (ra);
492 while (k--)
e11e83f3 493 res = scm_cons (scm_from_long (s[k].inc), res);
e2d37336
MD
494 return res;
495}
496#undef FUNC_NAME
497
498
0f2d19dd
JB
499static char s_bad_ind[] = "Bad scm_array index";
500
1cc91f1b 501
c014a02e 502long
1bbd0b84 503scm_aind (SCM ra, SCM args, const char *what)
0f2d19dd
JB
504{
505 SCM ind;
c014a02e
ML
506 register long j;
507 register unsigned long pos = SCM_ARRAY_BASE (ra);
508 register unsigned long k = SCM_ARRAY_NDIM (ra);
92c2555f 509 scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
02339e5b 510
e11e83f3 511 if (scm_is_integer (args))
0f2d19dd 512 {
b3fcac34
DH
513 if (k != 1)
514 scm_error_num_args_subr (what);
e11e83f3 515 return pos + (scm_to_long (args) - s->lbnd) * (s->inc);
0f2d19dd 516 }
d2e53ed6 517 while (k && scm_is_pair (args))
0f2d19dd
JB
518 {
519 ind = SCM_CAR (args);
520 args = SCM_CDR (args);
e11e83f3 521 if (!scm_is_integer (ind))
b3fcac34 522 scm_misc_error (what, s_bad_ind, SCM_EOL);
e11e83f3 523 j = scm_to_long (ind);
685c0d71
DH
524 if (j < s->lbnd || j > s->ubnd)
525 scm_out_of_range (what, ind);
0f2d19dd
JB
526 pos += (j - s->lbnd) * (s->inc);
527 k--;
528 s++;
529 }
d2e53ed6 530 if (k != 0 || !scm_is_null (args))
b3fcac34
DH
531 scm_error_num_args_subr (what);
532
0f2d19dd
JB
533 return pos;
534}
0f2d19dd 535
1cc91f1b 536
02339e5b
MV
537static SCM
538scm_i_make_ra (int ndim, scm_t_bits tag)
0f2d19dd
JB
539{
540 SCM ra;
02339e5b 541 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + tag,
4c9419ac
MV
542 scm_gc_malloc ((sizeof (scm_t_array) +
543 ndim * sizeof (scm_t_array_dim)),
544 "array"));
02339e5b 545 SCM_ARRAY_V (ra) = SCM_BOOL_F;
0f2d19dd
JB
546 return ra;
547}
548
02339e5b
MV
549SCM
550scm_make_ra (int ndim)
551{
552 return scm_i_make_ra (ndim, scm_tc16_array);
553}
554
555
0f2d19dd 556static char s_bad_spec[] = "Bad scm_array dimension";
0f2d19dd 557
1cc91f1b 558
02339e5b
MV
559/* Increments will still need to be set. */
560
0f2d19dd 561SCM
1bbd0b84 562scm_shap2ra (SCM args, const char *what)
0f2d19dd 563{
92c2555f 564 scm_t_array_dim *s;
0f2d19dd
JB
565 SCM ra, spec, sp;
566 int ndim = scm_ilength (args);
b3fcac34
DH
567 if (ndim < 0)
568 scm_misc_error (what, s_bad_spec, SCM_EOL);
569
0f2d19dd
JB
570 ra = scm_make_ra (ndim);
571 SCM_ARRAY_BASE (ra) = 0;
572 s = SCM_ARRAY_DIMS (ra);
d2e53ed6 573 for (; !scm_is_null (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
574 {
575 spec = SCM_CAR (args);
e11e83f3 576 if (scm_is_integer (spec))
0f2d19dd 577 {
e11e83f3 578 if (scm_to_long (spec) < 0)
b3fcac34 579 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd 580 s->lbnd = 0;
e11e83f3 581 s->ubnd = scm_to_long (spec) - 1;
0f2d19dd
JB
582 s->inc = 1;
583 }
584 else
585 {
d2e53ed6 586 if (!scm_is_pair (spec) || !scm_is_integer (SCM_CAR (spec)))
b3fcac34 587 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 588 s->lbnd = scm_to_long (SCM_CAR (spec));
0f2d19dd 589 sp = SCM_CDR (spec);
d2e53ed6 590 if (!scm_is_pair (sp)
e11e83f3 591 || !scm_is_integer (SCM_CAR (sp))
d2e53ed6 592 || !scm_is_null (SCM_CDR (sp)))
b3fcac34 593 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 594 s->ubnd = scm_to_long (SCM_CAR (sp));
0f2d19dd
JB
595 s->inc = 1;
596 }
597 }
598 return ra;
599}
600
f301dbf3
MV
601SCM_DEFINE (scm_make_typed_array, "make-typed-array", 2, 0, 1,
602 (SCM type, SCM fill, SCM bounds),
603 "Create and return an array of type @var{type}.")
604#define FUNC_NAME s_scm_make_typed_array
0f2d19dd 605{
f301dbf3 606 size_t k, rlen = 1;
92c2555f 607 scm_t_array_dim *s;
f301dbf3 608 creator_proc *creator;
0f2d19dd 609 SCM ra;
1be6b49c 610
f301dbf3
MV
611 creator = type_to_creator (type);
612 ra = scm_shap2ra (bounds, FUNC_NAME);
e038c042 613 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
614 s = SCM_ARRAY_DIMS (ra);
615 k = SCM_ARRAY_NDIM (ra);
1be6b49c 616
0f2d19dd
JB
617 while (k--)
618 {
a3a32939 619 s[k].inc = rlen;
f301dbf3 620 SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd);
0f2d19dd 621 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 622 }
a3a32939 623
f0b91039 624 if (scm_is_eq (fill, SCM_UNSPECIFIED))
f301dbf3 625 fill = SCM_UNDEFINED;
a3a32939 626
f301dbf3 627 SCM_ARRAY_V (ra) = creator (scm_from_size_t (rlen), fill);
a3a32939 628
0f2d19dd 629 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
c014a02e 630 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
0f2d19dd
JB
631 return SCM_ARRAY_V (ra);
632 return ra;
633}
1bbd0b84 634#undef FUNC_NAME
0f2d19dd 635
f301dbf3
MV
636SCM_DEFINE (scm_make_array, "make-array", 1, 0, 1,
637 (SCM fill, SCM bounds),
638 "Create and return an array.")
639#define FUNC_NAME s_scm_make_array
640{
641 return scm_make_typed_array (SCM_BOOL_T, fill, bounds);
642}
643#undef FUNC_NAME
644
645#if SCM_ENABLE_DEPRECATED
646
647SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
648 (SCM dims, SCM prot, SCM fill),
649 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
650 "Create and return a uniform array or vector of type\n"
651 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
652 "length @var{length}. If @var{fill} is supplied, it's used to\n"
653 "fill the array, otherwise @var{prototype} is used.")
654#define FUNC_NAME s_scm_dimensions_to_uniform_array
655{
656 scm_c_issue_deprecation_warning
657 ("`dimensions->uniform-array' is deprecated. "
658 "Use `make-typed-array' instead.");
659
660 if (scm_is_integer (dims))
661 dims = scm_list_1 (dims);
662 return scm_make_typed_array (prototype_to_type (prot), fill, dims);
663}
664#undef FUNC_NAME
665
666#endif
1cc91f1b 667
0f2d19dd 668void
1bbd0b84 669scm_ra_set_contp (SCM ra)
0f2d19dd 670{
02339e5b
MV
671 /* XXX - correct? one-dimensional arrays are always 'contiguous',
672 is that right?
673 */
1be6b49c 674 size_t k = SCM_ARRAY_NDIM (ra);
0f2d19dd 675 if (k)
0f2d19dd 676 {
c014a02e 677 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 678 while (k--)
0f2d19dd 679 {
fe0c6dae
JB
680 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
681 {
e038c042 682 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
683 return;
684 }
685 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
686 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 687 }
0f2d19dd 688 }
e038c042 689 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
690}
691
692
3b3b36dd 693SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 694 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
695 "@code{make-shared-array} can be used to create shared subarrays of other\n"
696 "arrays. The @var{mapper} is a function that translates coordinates in\n"
697 "the new array into coordinates in the old array. A @var{mapper} must be\n"
698 "linear, and its range must stay within the bounds of the old array, but\n"
699 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 700 "@lisp\n"
b380b885
MD
701 "(define fred (make-array #f 8 8))\n"
702 "(define freds-diagonal\n"
703 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
704 "(array-set! freds-diagonal 'foo 3)\n"
705 "(array-ref fred 3 3) @result{} foo\n"
706 "(define freds-center\n"
707 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
708 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 709 "@end lisp")
1bbd0b84 710#define FUNC_NAME s_scm_make_shared_array
0f2d19dd
JB
711{
712 SCM ra;
713 SCM inds, indptr;
714 SCM imap;
c014a02e
ML
715 size_t k, i;
716 long old_min, new_min, old_max, new_max;
92c2555f 717 scm_t_array_dim *s;
b3fcac34
DH
718
719 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6
HWN
720 SCM_VALIDATE_ARRAY (1, oldra);
721 SCM_VALIDATE_PROC (2, mapfunc);
1bbd0b84 722 ra = scm_shap2ra (dims, FUNC_NAME);
0f2d19dd
JB
723 if (SCM_ARRAYP (oldra))
724 {
725 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
726 old_min = old_max = SCM_ARRAY_BASE (oldra);
727 s = SCM_ARRAY_DIMS (oldra);
728 k = SCM_ARRAY_NDIM (oldra);
729 while (k--)
730 {
731 if (s[k].inc > 0)
732 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
733 else
734 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
735 }
736 }
737 else
738 {
739 SCM_ARRAY_V (ra) = oldra;
740 old_min = 0;
02339e5b 741 old_max = scm_c_generalized_vector_length (oldra) - 1;
0f2d19dd
JB
742 }
743 inds = SCM_EOL;
744 s = SCM_ARRAY_DIMS (ra);
745 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
746 {
e11e83f3 747 inds = scm_cons (scm_from_long (s[k].lbnd), inds);
0f2d19dd
JB
748 if (s[k].ubnd < s[k].lbnd)
749 {
750 if (1 == SCM_ARRAY_NDIM (ra))
f301dbf3 751 ra = make_typed_vector (scm_array_type (ra), 0);
0f2d19dd 752 else
f301dbf3 753 SCM_ARRAY_V (ra) = make_typed_vector (scm_array_type (ra), 0);
0f2d19dd
JB
754 return ra;
755 }
756 }
fdc28395 757 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd 758 if (SCM_ARRAYP (oldra))
c014a02e 759 i = (size_t) scm_aind (oldra, imap, FUNC_NAME);
0f2d19dd
JB
760 else
761 {
e11e83f3 762 if (!scm_is_integer (imap))
0f2d19dd 763 {
e11e83f3 764 if (scm_ilength (imap) != 1 || !scm_is_integer (SCM_CAR (imap)))
b3fcac34 765 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
766 imap = SCM_CAR (imap);
767 }
e11e83f3 768 i = scm_to_size_t (imap);
0f2d19dd
JB
769 }
770 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
771 indptr = inds;
772 k = SCM_ARRAY_NDIM (ra);
773 while (k--)
774 {
775 if (s[k].ubnd > s[k].lbnd)
776 {
e11e83f3 777 SCM_SETCAR (indptr, scm_sum (SCM_CAR (indptr), scm_from_int (1)));
fdc28395 778 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd
JB
779 if (SCM_ARRAYP (oldra))
780
1bbd0b84 781 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
782 else
783 {
e11e83f3 784 if (!scm_is_integer (imap))
0f2d19dd 785 {
e11e83f3 786 if (scm_ilength (imap) != 1 || !scm_is_integer (SCM_CAR (imap)))
b3fcac34 787 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
788 imap = SCM_CAR (imap);
789 }
e11e83f3 790 s[k].inc = scm_to_long (imap) - i;
0f2d19dd
JB
791 }
792 i += s[k].inc;
793 if (s[k].inc > 0)
794 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
795 else
796 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
797 }
798 else
799 s[k].inc = new_max - new_min + 1; /* contiguous by default */
800 indptr = SCM_CDR (indptr);
801 }
b3fcac34
DH
802 if (old_min > new_min || old_max < new_max)
803 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
804 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
805 {
74014c46 806 SCM v = SCM_ARRAY_V (ra);
6e708ef2 807 size_t length = scm_c_generalized_vector_length (v);
74014c46
DH
808 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
809 return v;
0f2d19dd 810 if (s->ubnd < s->lbnd)
f301dbf3 811 return make_typed_vector (scm_array_type (ra), 0);
0f2d19dd
JB
812 }
813 scm_ra_set_contp (ra);
814 return ra;
815}
1bbd0b84 816#undef FUNC_NAME
0f2d19dd
JB
817
818
819/* args are RA . DIMS */
af45e3b0
DH
820SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
821 (SCM ra, SCM args),
1e6808ea
MG
822 "Return an array sharing contents with @var{array}, but with\n"
823 "dimensions arranged in a different order. There must be one\n"
824 "@var{dim} argument for each dimension of @var{array}.\n"
825 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
826 "and the rank of the array to be returned. Each integer in that\n"
827 "range must appear at least once in the argument list.\n"
828 "\n"
829 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
830 "dimensions in the array to be returned, their positions in the\n"
831 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
832 "may have the same value, in which case the returned array will\n"
833 "have smaller rank than @var{array}.\n"
834 "\n"
835 "@lisp\n"
b380b885
MD
836 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
837 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
838 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
839 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 840 "@end lisp")
1bbd0b84 841#define FUNC_NAME s_scm_transpose_array
0f2d19dd 842{
34d19ef6 843 SCM res, vargs;
92c2555f 844 scm_t_array_dim *s, *r;
0f2d19dd 845 int ndim, i, k;
af45e3b0 846
b3fcac34 847 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 848 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
e0e49670 849
20930f28 850 if (scm_is_generalized_vector (ra))
e0e49670
MV
851 {
852 /* Make sure that we are called with a single zero as
853 arguments.
854 */
855 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
856 SCM_WRONG_NUM_ARGS ();
857 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
858 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
859 return ra;
860 }
861
02339e5b 862 if (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra))
0f2d19dd 863 {
0f2d19dd 864 vargs = scm_vector (args);
6e708ef2 865 if (SCM_SIMPLE_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
b3fcac34 866 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
867 ndim = 0;
868 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
869 {
6e708ef2
MV
870 i = scm_to_signed_integer (SCM_SIMPLE_VECTOR_REF (vargs, k),
871 0, SCM_ARRAY_NDIM(ra));
0f2d19dd
JB
872 if (ndim < i)
873 ndim = i;
874 }
875 ndim++;
876 res = scm_make_ra (ndim);
877 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
878 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
879 for (k = ndim; k--;)
880 {
881 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
882 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
883 }
884 for (k = SCM_ARRAY_NDIM (ra); k--;)
885 {
6e708ef2 886 i = scm_to_int (SCM_SIMPLE_VECTOR_REF (vargs, k));
0f2d19dd
JB
887 s = &(SCM_ARRAY_DIMS (ra)[k]);
888 r = &(SCM_ARRAY_DIMS (res)[i]);
889 if (r->ubnd < r->lbnd)
890 {
891 r->lbnd = s->lbnd;
892 r->ubnd = s->ubnd;
893 r->inc = s->inc;
894 ndim--;
895 }
896 else
897 {
898 if (r->ubnd > s->ubnd)
899 r->ubnd = s->ubnd;
900 if (r->lbnd < s->lbnd)
901 {
902 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
903 r->lbnd = s->lbnd;
904 }
905 r->inc += s->inc;
906 }
907 }
b3fcac34
DH
908 if (ndim > 0)
909 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
910 scm_ra_set_contp (res);
911 return res;
912 }
20930f28
MV
913
914 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 915}
1bbd0b84 916#undef FUNC_NAME
0f2d19dd
JB
917
918/* args are RA . AXES */
af45e3b0
DH
919SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
920 (SCM ra, SCM axes),
b380b885
MD
921 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
922 "the rank of @var{array}. @var{enclose-array} returns an array\n"
923 "resembling an array of shared arrays. The dimensions of each shared\n"
924 "array are the same as the @var{dim}th dimensions of the original array,\n"
925 "the dimensions of the outer array are the same as those of the original\n"
926 "array that did not match a @var{dim}.\n\n"
927 "An enclosed array is not a general Scheme array. Its elements may not\n"
928 "be set using @code{array-set!}. Two references to the same element of\n"
929 "an enclosed array will be @code{equal?} but will not in general be\n"
930 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
931 "enclosed array is unspecified.\n\n"
932 "examples:\n"
1e6808ea 933 "@lisp\n"
b380b885
MD
934 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
935 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
936 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
937 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 938 "@end lisp")
1bbd0b84 939#define FUNC_NAME s_scm_enclose_array
0f2d19dd 940{
af45e3b0 941 SCM axv, res, ra_inr;
cc95e00a 942 const char *c_axv;
92c2555f 943 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 944 int ndim, j, k, ninr, noutr;
af45e3b0 945
b3fcac34 946 SCM_VALIDATE_REST_ARGUMENT (axes);
d2e53ed6 947 if (scm_is_null (axes))
02339e5b 948 axes = scm_cons ((SCM_ARRAYP (ra) ? scm_from_size_t (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
0f2d19dd 949 ninr = scm_ilength (axes);
b3fcac34
DH
950 if (ninr < 0)
951 SCM_WRONG_NUM_ARGS ();
0f2d19dd 952 ra_inr = scm_make_ra (ninr);
e0e49670 953
20930f28 954 if (scm_is_generalized_vector (ra))
0f2d19dd 955 {
0f2d19dd 956 s->lbnd = 0;
6e708ef2 957 s->ubnd = scm_c_generalized_vector_length (ra) - 1;
0f2d19dd
JB
958 s->inc = 1;
959 SCM_ARRAY_V (ra_inr) = ra;
960 SCM_ARRAY_BASE (ra_inr) = 0;
961 ndim = 1;
20930f28
MV
962 }
963 else if (SCM_ARRAYP (ra))
964 {
0f2d19dd
JB
965 s = SCM_ARRAY_DIMS (ra);
966 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
967 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
968 ndim = SCM_ARRAY_NDIM (ra);
0f2d19dd 969 }
20930f28
MV
970 else
971 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
972
0f2d19dd 973 noutr = ndim - ninr;
b3fcac34
DH
974 if (noutr < 0)
975 SCM_WRONG_NUM_ARGS ();
e11e83f3 976 axv = scm_make_string (scm_from_int (ndim), SCM_MAKE_CHAR (0));
02339e5b 977 res = scm_i_make_ra (noutr, scm_tc16_enclosed_array);
0f2d19dd
JB
978 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
979 SCM_ARRAY_V (res) = ra_inr;
980 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
981 {
e11e83f3 982 if (!scm_is_integer (SCM_CAR (axes)))
b3fcac34 983 SCM_MISC_ERROR ("bad axis", SCM_EOL);
e11e83f3 984 j = scm_to_int (SCM_CAR (axes));
0f2d19dd
JB
985 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
986 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
987 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
cc95e00a 988 scm_c_string_set_x (axv, j, SCM_MAKE_CHAR (1));
0f2d19dd 989 }
cc95e00a 990 c_axv = scm_i_string_chars (axv);
0f2d19dd
JB
991 for (j = 0, k = 0; k < noutr; k++, j++)
992 {
cc95e00a 993 while (c_axv[j])
0f2d19dd
JB
994 j++;
995 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
996 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
997 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
998 }
cc95e00a 999 scm_remember_upto_here_1 (axv);
0f2d19dd
JB
1000 scm_ra_set_contp (ra_inr);
1001 scm_ra_set_contp (res);
1002 return res;
1003}
1bbd0b84 1004#undef FUNC_NAME
0f2d19dd
JB
1005
1006
1007
af45e3b0
DH
1008SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
1009 (SCM v, SCM args),
1e6808ea
MG
1010 "Return @code{#t} if its arguments would be acceptable to\n"
1011 "@code{array-ref}.")
1bbd0b84 1012#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 1013{
02339e5b 1014 SCM res = SCM_BOOL_T;
af45e3b0 1015
b3fcac34 1016 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd 1017
20930f28
MV
1018 if (scm_is_generalized_vector (v))
1019 {
02339e5b
MV
1020 long ind;
1021
1022 if (!scm_is_pair (args))
1023 SCM_WRONG_NUM_ARGS ();
1024 ind = scm_to_long (SCM_CAR (args));
1025 args = SCM_CDR (args);
1026 res = scm_from_bool (ind >= 0
1027 && ind < scm_c_generalized_vector_length (v));
20930f28 1028 }
02339e5b 1029 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
0f2d19dd 1030 {
02339e5b
MV
1031 size_t k = SCM_ARRAY_NDIM (v);
1032 scm_t_array_dim *s = SCM_ARRAY_DIMS (v);
1033
1034 while (k > 0)
0f2d19dd 1035 {
02339e5b 1036 long ind;
20930f28 1037
02339e5b
MV
1038 if (!scm_is_pair (args))
1039 SCM_WRONG_NUM_ARGS ();
1040 ind = scm_to_long (SCM_CAR (args));
1041 args = SCM_CDR (args);
1042 k -= 1;
1043
1044 if (ind < s->lbnd || ind > s->ubnd)
1045 {
1046 res = SCM_BOOL_F;
1047 /* We do not stop the checking after finding a violation
1048 since we want to validate the type-correctness and
1049 number of arguments in any case.
1050 */
1051 }
1052 }
0f2d19dd 1053 }
02339e5b
MV
1054 else
1055 scm_wrong_type_arg_msg (NULL, 0, v, "array");
20930f28 1056
02339e5b
MV
1057 if (!scm_is_null (args))
1058 SCM_WRONG_NUM_ARGS ();
1059
1060 return res;
0f2d19dd 1061}
1bbd0b84 1062#undef FUNC_NAME
0f2d19dd 1063
2d4d7f27 1064SCM
02339e5b
MV
1065scm_i_cvref (SCM v, size_t pos, int enclosed)
1066{
1067 if (enclosed)
1068 {
1069 int k = SCM_ARRAY_NDIM (v);
1070 SCM res = scm_make_ra (k);
1071 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1072 SCM_ARRAY_BASE (res) = pos;
1073 while (k--)
1074 {
1075 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1076 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1077 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1078 }
1079 return res;
1080 }
1081 else
1082 return scm_c_generalized_vector_ref (v, pos);
1083}
1084
1085SCM
1086scm_cvref (SCM v, unsigned long pos, SCM last)
1087{
1088 return scm_i_cvref (v, pos, 0);
1089}
0f2d19dd 1090
e0e49670 1091SCM_DEFINE (scm_array_ref, "array-ref", 1, 0, 1,
1bbd0b84 1092 (SCM v, SCM args),
1e6808ea
MG
1093 "Return the element at the @code{(index1, index2)} element in\n"
1094 "@var{array}.")
e0e49670 1095#define FUNC_NAME s_scm_array_ref
0f2d19dd 1096{
c014a02e 1097 long pos;
02339e5b 1098 int enclosed = 0;
0f2d19dd 1099
02339e5b 1100 if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
0f2d19dd 1101 {
02339e5b 1102 enclosed = SCM_ENCLOSED_ARRAYP (v);
1bbd0b84 1103 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1104 v = SCM_ARRAY_V (v);
1105 }
1106 else
1107 {
20930f28 1108 size_t length;
0f2d19dd 1109 if (SCM_NIMP (args))
0f2d19dd 1110 {
d2e53ed6 1111 SCM_ASSERT (scm_is_pair (args), args, SCM_ARG2, FUNC_NAME);
e11e83f3 1112 pos = scm_to_long (SCM_CAR (args));
d2e53ed6 1113 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
0f2d19dd
JB
1114 }
1115 else
20930f28
MV
1116 pos = scm_to_long (args);
1117 length = scm_c_generalized_vector_length (v);
74014c46 1118 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1119 }
e0e49670 1120
02339e5b 1121 return scm_i_cvref (v, pos, enclosed);
20930f28 1122
20930f28
MV
1123 wna:
1124 scm_wrong_num_args (NULL);
1125 outrng:
1126 scm_out_of_range (NULL, scm_from_long (pos));
0f2d19dd 1127}
1bbd0b84 1128#undef FUNC_NAME
0f2d19dd 1129
0f2d19dd 1130
3b3b36dd 1131SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1132 (SCM v, SCM obj, SCM args),
8f85c0c6 1133 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1134 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1135#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1136{
c014a02e 1137 long pos = 0;
b3fcac34 1138
0f2d19dd 1139 if (SCM_ARRAYP (v))
0f2d19dd 1140 {
1bbd0b84 1141 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1142 v = SCM_ARRAY_V (v);
1143 }
02339e5b
MV
1144 else if (SCM_ENCLOSED_ARRAYP (v))
1145 scm_wrong_type_arg_msg (NULL, 0, v, "non-enclosed array");
1146 else if (scm_is_generalized_vector (v))
0f2d19dd 1147 {
20930f28 1148 size_t length;
d2e53ed6 1149 if (scm_is_pair (args))
0f2d19dd 1150 {
d2e53ed6 1151 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
e11e83f3 1152 pos = scm_to_long (SCM_CAR (args));
0f2d19dd
JB
1153 }
1154 else
20930f28
MV
1155 pos = scm_to_long (args);
1156 length = scm_c_generalized_vector_length (v);
74014c46 1157 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1158 }
02339e5b
MV
1159 else
1160 scm_wrong_type_arg_msg (NULL, 0, v, "array");
1161
1162 scm_c_generalized_vector_set_x (v, pos, obj);
1163 return SCM_UNSPECIFIED;
20930f28
MV
1164
1165 outrng:
1166 scm_out_of_range (NULL, scm_from_long (pos));
1167 wna:
1168 scm_wrong_num_args (NULL);
0f2d19dd 1169}
1bbd0b84 1170#undef FUNC_NAME
0f2d19dd 1171
1d7bdb25
GH
1172/* attempts to unroll an array into a one-dimensional array.
1173 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1174 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1175 wouldn't have contiguous elements. */
3b3b36dd 1176SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1177 (SCM ra, SCM strict),
b380b885
MD
1178 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1179 "without changing their order (last subscript changing fastest), then\n"
1180 "@code{array-contents} returns that shared array, otherwise it returns\n"
1181 "@code{#f}. All arrays made by @var{make-array} and\n"
1182 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1183 "@var{make-shared-array} may not be.\n\n"
1184 "If the optional argument @var{strict} is provided, a shared array will\n"
1185 "be returned only if its elements are stored internally contiguous in\n"
1186 "memory.")
1bbd0b84 1187#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1188{
1189 SCM sra;
e0e49670 1190
20930f28 1191 if (scm_is_generalized_vector (ra))
e0e49670
MV
1192 return ra;
1193
20930f28 1194 if (SCM_ARRAYP (ra))
0f2d19dd 1195 {
20930f28
MV
1196 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1197 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1198 return SCM_BOOL_F;
1199 for (k = 0; k < ndim; k++)
1200 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1201 if (!SCM_UNBNDP (strict))
74014c46 1202 {
20930f28
MV
1203 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1204 return SCM_BOOL_F;
1205 if (scm_is_bitvector (SCM_ARRAY_V (ra)))
1206 {
1207 if (len != scm_c_bitvector_length (SCM_ARRAY_V (ra)) ||
1208 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1209 len % SCM_LONG_BIT)
1210 return SCM_BOOL_F;
1211 }
74014c46 1212 }
20930f28
MV
1213
1214 {
1215 SCM v = SCM_ARRAY_V (ra);
1216 size_t length = scm_c_generalized_vector_length (v);
1217 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1218 return v;
0f2d19dd 1219 }
20930f28
MV
1220
1221 sra = scm_make_ra (1);
1222 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1223 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1224 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1225 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1226 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1227 return sra;
0f2d19dd 1228 }
02339e5b
MV
1229 else if (SCM_ENCLOSED_ARRAYP (ra))
1230 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
1231 else
1232 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1233}
1bbd0b84 1234#undef FUNC_NAME
0f2d19dd 1235
1cc91f1b 1236
0f2d19dd 1237SCM
6e8d25a6 1238scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1239{
1240 SCM ret;
c014a02e
ML
1241 long inc = 1;
1242 size_t k, len = 1;
0f2d19dd
JB
1243 for (k = SCM_ARRAY_NDIM (ra); k--;)
1244 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1245 k = SCM_ARRAY_NDIM (ra);
1246 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1247 {
20930f28 1248 if (!scm_is_bitvector (SCM_ARRAY_V (ra)))
0f2d19dd 1249 return ra;
20930f28 1250 if ((len == scm_c_bitvector_length (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1251 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1252 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1253 return ra;
1254 }
1255 ret = scm_make_ra (k);
1256 SCM_ARRAY_BASE (ret) = 0;
1257 while (k--)
1258 {
1259 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1260 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1261 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1262 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1263 }
f301dbf3 1264 SCM_ARRAY_V (ret) = make_typed_vector (scm_array_type (ra), inc);
0f2d19dd
JB
1265 if (copy)
1266 scm_array_copy_x (ra, ret);
1267 return ret;
1268}
1269
1270
1271
3b3b36dd 1272SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
03a5397a 1273 (SCM ura, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1274 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1275 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1276 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1277 "If an end of file is encountered,\n"
1278 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1279 "(starting at the beginning) and the remainder of the array is\n"
1280 "unchanged.\n\n"
1281 "The optional arguments @var{start} and @var{end} allow\n"
1282 "a specified region of a vector (or linearized array) to be read,\n"
1283 "leaving the remainder of the vector unchanged.\n\n"
1284 "@code{uniform-array-read!} returns the number of objects read.\n"
1285 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1286 "returned by @code{(current-input-port)}.")
1bbd0b84 1287#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1288{
3d8d56df
GH
1289 if (SCM_UNBNDP (port_or_fd))
1290 port_or_fd = scm_cur_inp;
35de7ebe 1291
03a5397a 1292 if (scm_is_uniform_vector (ura))
20930f28 1293 {
03a5397a 1294 return scm_uniform_vector_read_x (ura, port_or_fd, start, end);
20930f28 1295 }
03a5397a 1296 else if (SCM_ARRAYP (ura))
20930f28 1297 {
03a5397a
MV
1298 size_t base, vlen, cstart, cend;
1299 SCM cra, ans;
1300
1301 cra = scm_ra2contig (ura, 0);
1302 base = SCM_ARRAY_BASE (cra);
20930f28
MV
1303 vlen = SCM_ARRAY_DIMS (cra)->inc *
1304 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
35de7ebe 1305
03a5397a
MV
1306 cstart = 0;
1307 cend = vlen;
1308 if (!SCM_UNBNDP (start))
1146b6cd 1309 {
03a5397a
MV
1310 cstart = scm_to_unsigned_integer (start, 0, vlen);
1311 if (!SCM_UNBNDP (end))
1312 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1313 }
35de7ebe 1314
03a5397a
MV
1315 ans = scm_uniform_vector_read_x (SCM_ARRAY_V (cra), port_or_fd,
1316 scm_from_size_t (base + cstart),
1317 scm_from_size_t (base + cend));
6c951427 1318
03a5397a
MV
1319 if (!scm_is_eq (cra, ura))
1320 scm_array_copy_x (cra, ura);
1321 return ans;
3d8d56df 1322 }
02339e5b
MV
1323 else if (SCM_ENCLOSED_ARRAYP (ura))
1324 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1325 else
1326 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1327}
1bbd0b84 1328#undef FUNC_NAME
0f2d19dd 1329
3b3b36dd 1330SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
03a5397a 1331 (SCM ura, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1332 "Writes all elements of @var{ura} as binary objects to\n"
1333 "@var{port-or-fdes}.\n\n"
1334 "The optional arguments @var{start}\n"
1335 "and @var{end} allow\n"
1336 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1337 "The number of objects actually written is returned.\n"
b380b885
MD
1338 "@var{port-or-fdes} may be\n"
1339 "omitted, in which case it defaults to the value returned by\n"
1340 "@code{(current-output-port)}.")
1bbd0b84 1341#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1342{
3d8d56df
GH
1343 if (SCM_UNBNDP (port_or_fd))
1344 port_or_fd = scm_cur_outp;
20930f28 1345
03a5397a 1346 if (scm_is_uniform_vector (ura))
20930f28 1347 {
03a5397a 1348 return scm_uniform_vector_write (ura, port_or_fd, start, end);
20930f28 1349 }
03a5397a 1350 else if (SCM_ARRAYP (ura))
20930f28 1351 {
03a5397a
MV
1352 size_t base, vlen, cstart, cend;
1353 SCM cra, ans;
1354
1355 cra = scm_ra2contig (ura, 1);
1356 base = SCM_ARRAY_BASE (cra);
1357 vlen = SCM_ARRAY_DIMS (cra)->inc *
1358 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1146b6cd 1359
03a5397a
MV
1360 cstart = 0;
1361 cend = vlen;
1362 if (!SCM_UNBNDP (start))
1146b6cd 1363 {
03a5397a
MV
1364 cstart = scm_to_unsigned_integer (start, 0, vlen);
1365 if (!SCM_UNBNDP (end))
1366 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1367 }
3d8d56df 1368
03a5397a
MV
1369 ans = scm_uniform_vector_write (SCM_ARRAY_V (cra), port_or_fd,
1370 scm_from_size_t (base + cstart),
1371 scm_from_size_t (base + cend));
6c951427 1372
03a5397a 1373 return ans;
3d8d56df 1374 }
02339e5b
MV
1375 else if (SCM_ENCLOSED_ARRAYP (ura))
1376 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1377 else
1378 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1379}
1bbd0b84 1380#undef FUNC_NAME
0f2d19dd
JB
1381
1382
20930f28
MV
1383/** Bit vectors */
1384
1385static scm_t_bits scm_tc16_bitvector;
1386
1387#define IS_BITVECTOR(obj) SCM_SMOB_PREDICATE(scm_tc16_bitvector,(obj))
1388#define BITVECTOR_BITS(obj) ((scm_t_uint32 *)SCM_SMOB_DATA(obj))
1389#define BITVECTOR_LENGTH(obj) ((size_t)SCM_SMOB_DATA_2(obj))
1390
1391static size_t
1392bitvector_free (SCM vec)
1393{
1394 scm_gc_free (BITVECTOR_BITS (vec),
1395 sizeof (scm_t_uint32) * ((BITVECTOR_LENGTH (vec)+31)/32),
1396 "bitvector");
1397 return 0;
1398}
1399
1400static int
1401bitvector_print (SCM vec, SCM port, scm_print_state *pstate)
1402{
1403 size_t bit_len = BITVECTOR_LENGTH (vec);
1404 size_t word_len = (bit_len+31)/32;
1405 scm_t_uint32 *bits = BITVECTOR_BITS (vec);
1406 size_t i, j;
1407
1408 scm_puts ("#*", port);
1409 for (i = 0; i < word_len; i++, bit_len -= 32)
1410 {
1411 scm_t_uint32 mask = 1;
1412 for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
1413 scm_putc ((bits[i] & mask)? '1' : '0', port);
1414 }
1415
1416 return 1;
1417}
1418
1419static SCM
1420bitvector_equalp (SCM vec1, SCM vec2)
1421{
1422 size_t bit_len = BITVECTOR_LENGTH (vec1);
1423 size_t word_len = (bit_len + 31) / 32;
1424 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
1425 scm_t_uint32 *bits1 = BITVECTOR_BITS (vec1);
1426 scm_t_uint32 *bits2 = BITVECTOR_BITS (vec2);
1427
1428 /* compare lengths */
1429 if (BITVECTOR_LENGTH (vec2) != bit_len)
1430 return SCM_BOOL_F;
1431 /* avoid underflow in word_len-1 below. */
1432 if (bit_len == 0)
1433 return SCM_BOOL_T;
1434 /* compare full words */
1435 if (memcmp (bits1, bits2, sizeof (scm_t_uint32) * (word_len-1)))
1436 return SCM_BOOL_F;
1437 /* compare partial last words */
1438 if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
1439 return SCM_BOOL_F;
1440 return SCM_BOOL_T;
1441}
1442
1443int
1444scm_is_bitvector (SCM vec)
1445{
1446 return IS_BITVECTOR (vec);
1447}
1448
1449SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
1450 (SCM obj),
1451 "Return @code{#t} when @var{obj} is a bitvector, else\n"
1452 "return @code{#f}.")
1453#define FUNC_NAME s_scm_bitvector_p
1454{
1455 return scm_from_bool (scm_is_bitvector (obj));
1456}
1457#undef FUNC_NAME
1458
1459SCM
1460scm_c_make_bitvector (size_t len, SCM fill)
1461{
1462 size_t word_len = (len + 31) / 32;
1463 scm_t_uint32 *bits;
1464 SCM res;
1465
1466 bits = scm_gc_malloc (sizeof (scm_t_uint32) * word_len,
1467 "bitvector");
1468 SCM_NEWSMOB2 (res, scm_tc16_bitvector, bits, len);
1469
1470 if (!SCM_UNBNDP (fill))
1471 scm_bitvector_fill_x (res, fill);
1472
1473 return res;
1474}
1475
1476SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
1477 (SCM len, SCM fill),
1478 "Create a new bitvector of length @var{len} and\n"
1479 "optionally initialize all elements to @var{fill}.")
1480#define FUNC_NAME s_scm_make_bitvector
1481{
1482 return scm_c_make_bitvector (scm_to_size_t (len), fill);
1483}
1484#undef FUNC_NAME
1485
1486SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
1487 (SCM bits),
1488 "Create a new bitvector with the arguments as elements.")
1489#define FUNC_NAME s_scm_bitvector
1490{
1491 return scm_list_to_bitvector (bits);
1492}
1493#undef FUNC_NAME
1494
1495size_t
1496scm_c_bitvector_length (SCM vec)
1497{
1498 scm_assert_smob_type (scm_tc16_bitvector, vec);
1499 return BITVECTOR_LENGTH (vec);
1500}
1501
1502SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
1503 (SCM vec),
1504 "Return the length of the bitvector @var{vec}.")
1505#define FUNC_NAME s_scm_bitvector_length
1506{
1507 return scm_from_size_t (scm_c_bitvector_length (vec));
1508}
1509#undef FUNC_NAME
1510
21c487f1 1511const scm_t_uint32 *
f0b91039 1512scm_array_handle_bit_elements (scm_t_array_handle *h)
20930f28 1513{
f0b91039 1514 return scm_array_handle_bit_writable_elements (h);
20930f28
MV
1515}
1516
f0b91039
MV
1517scm_t_uint32 *
1518scm_array_handle_bit_writable_elements (scm_t_array_handle *h)
20930f28 1519{
f0b91039
MV
1520 SCM vec = h->array;
1521 if (SCM_ARRAYP (vec))
1522 vec = SCM_ARRAY_V (vec);
1523 if (IS_BITVECTOR (vec))
1524 return BITVECTOR_BITS (vec) + h->base/32;
1525 scm_wrong_type_arg_msg (NULL, 0, h->array, "bit array");
20930f28
MV
1526}
1527
f0b91039
MV
1528size_t
1529scm_array_handle_bit_elements_offset (scm_t_array_handle *h)
21c487f1 1530{
f0b91039 1531 return h->base % 32;
21c487f1
MV
1532}
1533
f0b91039
MV
1534const scm_t_uint32 *
1535scm_bitvector_elements (SCM vec,
1536 scm_t_array_handle *h,
1537 size_t *offp,
1538 size_t *lenp,
1539 ssize_t *incp)
21c487f1 1540{
f0b91039 1541 return scm_bitvector_writable_elements (vec, h, offp, lenp, incp);
21c487f1
MV
1542}
1543
f0b91039
MV
1544
1545scm_t_uint32 *
1546scm_bitvector_writable_elements (SCM vec,
1547 scm_t_array_handle *h,
1548 size_t *offp,
1549 size_t *lenp,
1550 ssize_t *incp)
21c487f1 1551{
cdd6e0a8 1552 scm_generalized_vector_get_handle (vec, h);
f0b91039
MV
1553 if (offp)
1554 {
1555 scm_t_array_dim *dim = scm_array_handle_dims (h);
1556 *offp = scm_array_handle_bit_elements_offset (h);
1557 *lenp = dim->ubnd - dim->lbnd + 1;
1558 *incp = dim->inc;
1559 }
1560 return scm_array_handle_bit_writable_elements (h);
21c487f1
MV
1561}
1562
20930f28
MV
1563SCM
1564scm_c_bitvector_ref (SCM vec, size_t idx)
1565{
f0b91039
MV
1566 scm_t_array_handle handle;
1567 const scm_t_uint32 *bits;
1568
1569 if (IS_BITVECTOR (vec))
20930f28 1570 {
f0b91039
MV
1571 if (idx >= BITVECTOR_LENGTH (vec))
1572 scm_out_of_range (NULL, scm_from_size_t (idx));
1573 bits = BITVECTOR_BITS(vec);
cdd6e0a8 1574 return scm_from_bool (bits[idx/32] & (1L << (idx%32)));
20930f28
MV
1575 }
1576 else
f0b91039 1577 {
cdd6e0a8 1578 SCM res;
f0b91039
MV
1579 size_t len, off;
1580 ssize_t inc;
1581
1582 bits = scm_bitvector_elements (vec, &handle, &off, &len, &inc);
1583 if (idx >= len)
1584 scm_out_of_range (NULL, scm_from_size_t (idx));
1585 idx = idx*inc + off;
cdd6e0a8
MV
1586 res = scm_from_bool (bits[idx/32] & (1L << (idx%32)));
1587 scm_array_handle_release (&handle);
1588 return res;
f0b91039 1589 }
20930f28
MV
1590}
1591
1592SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
1593 (SCM vec, SCM idx),
1594 "Return the element at index @var{idx} of the bitvector\n"
1595 "@var{vec}.")
1596#define FUNC_NAME s_scm_bitvector_ref
1597{
1598 return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
1599}
1600#undef FUNC_NAME
1601
1602void
1603scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
1604{
f0b91039
MV
1605 scm_t_array_handle handle;
1606 scm_t_uint32 *bits, mask;
1607
1608 if (IS_BITVECTOR (vec))
20930f28 1609 {
f0b91039
MV
1610 if (idx >= BITVECTOR_LENGTH (vec))
1611 scm_out_of_range (NULL, scm_from_size_t (idx));
1612 bits = BITVECTOR_BITS(vec);
20930f28
MV
1613 }
1614 else
f0b91039
MV
1615 {
1616 size_t len, off;
1617 ssize_t inc;
1618
1619 bits = scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
1620 if (idx >= len)
1621 scm_out_of_range (NULL, scm_from_size_t (idx));
1622 idx = idx*inc + off;
1623 }
1624
1625 mask = 1L << (idx%32);
1626 if (scm_is_true (val))
1627 bits[idx/32] |= mask;
1628 else
1629 bits[idx/32] &= ~mask;
cdd6e0a8
MV
1630
1631 if (!IS_BITVECTOR (vec))
1632 scm_array_handle_release (&handle);
20930f28
MV
1633}
1634
1635SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
1636 (SCM vec, SCM idx, SCM val),
1637 "Set the element at index @var{idx} of the bitvector\n"
1638 "@var{vec} when @var{val} is true, else clear it.")
1639#define FUNC_NAME s_scm_bitvector_set_x
1640{
1641 scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
1642 return SCM_UNSPECIFIED;
1643}
1644#undef FUNC_NAME
1645
1646SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
1647 (SCM vec, SCM val),
1648 "Set all elements of the bitvector\n"
1649 "@var{vec} when @var{val} is true, else clear them.")
1650#define FUNC_NAME s_scm_bitvector_fill_x
1651{
f0b91039
MV
1652 scm_t_array_handle handle;
1653 size_t off, len;
1654 ssize_t inc;
1655 scm_t_uint32 *bits;
1656
1657 bits = scm_bitvector_writable_elements (vec, &handle,
1658 &off, &len, &inc);
1659
1660 if (off == 0 && inc == 1 && len > 0)
1661 {
1662 /* the usual case
1663 */
1664 size_t word_len = (len + 31) / 32;
1665 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1666
1667 if (scm_is_true (val))
1668 {
1669 memset (bits, 0xFF, sizeof(scm_t_uint32)*(word_len-1));
1670 bits[word_len-1] |= last_mask;
1671 }
1672 else
1673 {
1674 memset (bits, 0x00, sizeof(scm_t_uint32)*(word_len-1));
1675 bits[word_len-1] &= ~last_mask;
1676 }
1677 }
1678 else
1679 {
1680 size_t i;
1681 for (i = 0; i < len; i++)
1682 scm_array_handle_set (&handle, i, val);
1683 }
1684
cdd6e0a8
MV
1685 scm_array_handle_release (&handle);
1686
20930f28
MV
1687 return SCM_UNSPECIFIED;
1688}
1689#undef FUNC_NAME
1690
1691SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
1692 (SCM list),
1693 "Return a new bitvector initialized with the elements\n"
1694 "of @var{list}.")
1695#define FUNC_NAME s_scm_list_to_bitvector
1696{
1697 size_t bit_len = scm_to_size_t (scm_length (list));
1698 SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
1699 size_t word_len = (bit_len+31)/32;
f0b91039
MV
1700 scm_t_array_handle handle;
1701 scm_t_uint32 *bits = scm_bitvector_writable_elements (vec, &handle,
1702 NULL, NULL, NULL);
20930f28
MV
1703 size_t i, j;
1704
1705 for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
1706 {
1707 scm_t_uint32 mask = 1;
1708 bits[i] = 0;
1709 for (j = 0; j < 32 && j < bit_len;
1710 j++, mask <<= 1, list = SCM_CDR (list))
1711 if (scm_is_true (SCM_CAR (list)))
1712 bits[i] |= mask;
1713 }
f0b91039 1714
cdd6e0a8
MV
1715 scm_array_handle_release (&handle);
1716
20930f28
MV
1717 return vec;
1718}
1719#undef FUNC_NAME
1720
1721SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
1722 (SCM vec),
1723 "Return a new list initialized with the elements\n"
1724 "of the bitvector @var{vec}.")
1725#define FUNC_NAME s_scm_bitvector_to_list
1726{
f0b91039
MV
1727 scm_t_array_handle handle;
1728 size_t off, len;
1729 ssize_t inc;
1730 scm_t_uint32 *bits;
20930f28 1731 SCM res = SCM_EOL;
20930f28 1732
f0b91039
MV
1733 bits = scm_bitvector_writable_elements (vec, &handle,
1734 &off, &len, &inc);
1735
1736 if (off == 0 && inc == 1)
20930f28 1737 {
f0b91039
MV
1738 /* the usual case
1739 */
1740 size_t word_len = (len + 31) / 32;
1741 size_t i, j;
1742
1743 for (i = 0; i < word_len; i++, len -= 32)
1744 {
1745 scm_t_uint32 mask = 1;
1746 for (j = 0; j < 32 && j < len; j++, mask <<= 1)
1747 res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
1748 }
1749 }
1750 else
1751 {
1752 size_t i;
1753 for (i = 0; i < len; i++)
1754 res = scm_cons (scm_array_handle_ref (&handle, i), res);
20930f28 1755 }
cdd6e0a8
MV
1756
1757 scm_array_handle_release (&handle);
20930f28 1758
20930f28
MV
1759 return scm_reverse_x (res, SCM_EOL);
1760}
1761#undef FUNC_NAME
1762
1763/* From mmix-arith.w by Knuth.
1764
1765 Here's a fun way to count the number of bits in a tetrabyte.
1766
1767 [This classical trick is called the ``Gillies--Miller method for
1768 sideways addition'' in {\sl The Preparation of Programs for an
1769 Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
1770 edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
1771 the tricks used here were suggested by Balbir Singh, Peter
1772 Rossmanith, and Stefan Schwoon.]
1773*/
1774
1775static size_t
1776count_ones (scm_t_uint32 x)
1777{
1778 x=x-((x>>1)&0x55555555);
1779 x=(x&0x33333333)+((x>>2)&0x33333333);
1780 x=(x+(x>>4))&0x0f0f0f0f;
1781 x=x+(x>>8);
1782 return (x+(x>>16)) & 0xff;
1783}
0f2d19dd 1784
3b3b36dd 1785SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1786 (SCM b, SCM bitvector),
1e6808ea 1787 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1788 "@var{bitvector}.")
1bbd0b84 1789#define FUNC_NAME s_scm_bit_count
0f2d19dd 1790{
f0b91039
MV
1791 scm_t_array_handle handle;
1792 size_t off, len;
1793 ssize_t inc;
1794 scm_t_uint32 *bits;
20930f28 1795 int bit = scm_to_bool (b);
f0b91039 1796 size_t count = 0;
20930f28 1797
f0b91039
MV
1798 bits = scm_bitvector_writable_elements (bitvector, &handle,
1799 &off, &len, &inc);
20930f28 1800
f0b91039
MV
1801 if (off == 0 && inc == 1 && len > 0)
1802 {
1803 /* the usual case
1804 */
1805 size_t word_len = (len + 31) / 32;
1806 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1807 size_t i;
20930f28 1808
f0b91039
MV
1809 for (i = 0; i < word_len-1; i++)
1810 count += count_ones (bits[i]);
1811 count += count_ones (bits[i] & last_mask);
1812 }
1813 else
1814 {
1815 size_t i;
1816 for (i = 0; i < len; i++)
1817 if (scm_is_true (scm_array_handle_ref (&handle, i)))
1818 count++;
1819 }
1820
cdd6e0a8
MV
1821 scm_array_handle_release (&handle);
1822
f0b91039 1823 return scm_from_size_t (bit? count : len-count);
0f2d19dd 1824}
1bbd0b84 1825#undef FUNC_NAME
0f2d19dd 1826
20930f28
MV
1827/* returns 32 for x == 0.
1828*/
1829static size_t
1830find_first_one (scm_t_uint32 x)
1831{
1832 size_t pos = 0;
1833 /* do a binary search in x. */
1834 if ((x & 0xFFFF) == 0)
1835 x >>= 16, pos += 16;
1836 if ((x & 0xFF) == 0)
1837 x >>= 8, pos += 8;
1838 if ((x & 0xF) == 0)
1839 x >>= 4, pos += 4;
1840 if ((x & 0x3) == 0)
1841 x >>= 2, pos += 2;
1842 if ((x & 0x1) == 0)
1843 pos += 1;
1844 return pos;
1845}
0f2d19dd 1846
3b3b36dd 1847SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1848 (SCM item, SCM v, SCM k),
88ecf5cb
KR
1849 "Return the index of the first occurrance of @var{item} in bit\n"
1850 "vector @var{v}, starting from @var{k}. If there is no\n"
1851 "@var{item} entry between @var{k} and the end of\n"
1852 "@var{bitvector}, then return @code{#f}. For example,\n"
1853 "\n"
1854 "@example\n"
1855 "(bit-position #t #*000101 0) @result{} 3\n"
1856 "(bit-position #f #*0001111 3) @result{} #f\n"
1857 "@end example")
1bbd0b84 1858#define FUNC_NAME s_scm_bit_position
0f2d19dd 1859{
f0b91039
MV
1860 scm_t_array_handle handle;
1861 size_t off, len, first_bit;
1862 ssize_t inc;
1863 const scm_t_uint32 *bits;
20930f28 1864 int bit = scm_to_bool (item);
20930f28 1865 SCM res = SCM_BOOL_F;
f0b91039
MV
1866
1867 bits = scm_bitvector_elements (v, &handle, &off, &len, &inc);
1868 first_bit = scm_to_unsigned_integer (k, 0, len);
20930f28 1869
f0b91039
MV
1870 if (off == 0 && inc == 1 && len > 0)
1871 {
1872 size_t i, word_len = (len + 31) / 32;
1873 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1874 size_t first_word = first_bit / 32;
1875 scm_t_uint32 first_mask =
1876 ((scm_t_uint32)-1) << (first_bit - 32*first_word);
1877 scm_t_uint32 w;
1878
1879 for (i = first_word; i < word_len; i++)
1880 {
1881 w = (bit? bits[i] : ~bits[i]);
1882 if (i == first_word)
1883 w &= first_mask;
1884 if (i == word_len-1)
1885 w &= last_mask;
1886 if (w)
1887 {
1888 res = scm_from_size_t (32*i + find_first_one (w));
1889 break;
1890 }
1891 }
1892 }
1893 else
20930f28 1894 {
f0b91039
MV
1895 size_t i;
1896 for (i = first_bit; i < len; i++)
20930f28 1897 {
f0b91039
MV
1898 SCM elt = scm_array_handle_ref (&handle, i);
1899 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
1900 {
1901 res = scm_from_size_t (i);
1902 break;
1903 }
20930f28 1904 }
0f2d19dd 1905 }
20930f28 1906
cdd6e0a8
MV
1907 scm_array_handle_release (&handle);
1908
20930f28 1909 return res;
0f2d19dd 1910}
1bbd0b84 1911#undef FUNC_NAME
0f2d19dd 1912
3b3b36dd 1913SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761 1914 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1915 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1916 "selecting the entries to change. The return value is\n"
1917 "unspecified.\n"
1918 "\n"
1919 "If @var{kv} is a bit vector, then those entries where it has\n"
1920 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1921 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1922 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1923 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1924 "\n"
1925 "@example\n"
1926 "(define bv #*01000010)\n"
1927 "(bit-set*! bv #*10010001 #t)\n"
1928 "bv\n"
1929 "@result{} #*11010011\n"
1930 "@end example\n"
1931 "\n"
85368844
MV
1932 "If @var{kv} is a u32vector, then its elements are\n"
1933 "indices into @var{v} which are set to @var{obj}.\n"
88ecf5cb
KR
1934 "\n"
1935 "@example\n"
1936 "(define bv #*01000010)\n"
85368844 1937 "(bit-set*! bv #u32(5 2 7) #t)\n"
88ecf5cb
KR
1938 "bv\n"
1939 "@result{} #*01100111\n"
1940 "@end example")
1bbd0b84 1941#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1942{
f0b91039
MV
1943 scm_t_array_handle v_handle;
1944 size_t v_off, v_len;
1945 ssize_t v_inc;
1946 scm_t_uint32 *v_bits;
1947 int bit;
1948
1949 /* Validate that OBJ is a boolean so this is done even if we don't
1950 need BIT.
1951 */
1952 bit = scm_to_bool (obj);
1953
1954 v_bits = scm_bitvector_writable_elements (v, &v_handle,
1955 &v_off, &v_len, &v_inc);
1956
20930f28
MV
1957 if (scm_is_bitvector (kv))
1958 {
f0b91039
MV
1959 scm_t_array_handle kv_handle;
1960 size_t kv_off, kv_len;
1961 ssize_t kv_inc;
1962 const scm_t_uint32 *kv_bits;
1963
1964 kv_bits = scm_bitvector_elements (v, &kv_handle,
1965 &kv_off, &kv_len, &kv_inc);
1966
1967 if (v_len != kv_len)
85368844
MV
1968 scm_misc_error (NULL,
1969 "bit vectors must have equal length",
1970 SCM_EOL);
1971
f0b91039
MV
1972 if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
1973 {
1974 size_t word_len = (kv_len + 31) / 32;
1975 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
1976 size_t i;
1977
1978 if (bit == 0)
1979 {
1980 for (i = 0; i < word_len-1; i++)
1981 v_bits[i] &= ~kv_bits[i];
1982 v_bits[i] &= ~(kv_bits[i] & last_mask);
1983 }
1984 else
1985 {
1986 for (i = 0; i < word_len-1; i++)
1987 v_bits[i] |= kv_bits[i];
1988 v_bits[i] |= kv_bits[i] & last_mask;
1989 }
1990 }
85368844 1991 else
f0b91039
MV
1992 {
1993 size_t i;
1994 for (i = 0; i < kv_len; i++)
1995 if (scm_is_true (scm_array_handle_ref (&kv_handle, i)))
1996 scm_array_handle_set (&v_handle, i, obj);
1997 }
cdd6e0a8
MV
1998
1999 scm_array_handle_release (&kv_handle);
2000
85368844
MV
2001 }
2002 else if (scm_is_true (scm_u32vector_p (kv)))
2003 {
f0b91039
MV
2004 scm_t_array_handle kv_handle;
2005 size_t i, kv_len;
2006 ssize_t kv_inc;
2007 const scm_t_uint32 *kv_elts;
2008
2009 kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
2010 for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
2011 scm_array_handle_set (&v_handle, (size_t) *kv_elts, obj);
cdd6e0a8
MV
2012
2013 scm_array_handle_release (&kv_handle);
0f2d19dd 2014 }
20930f28 2015 else
85368844
MV
2016 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
2017
cdd6e0a8
MV
2018 scm_array_handle_release (&v_handle);
2019
0f2d19dd
JB
2020 return SCM_UNSPECIFIED;
2021}
1bbd0b84 2022#undef FUNC_NAME
0f2d19dd
JB
2023
2024
3b3b36dd 2025SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 2026 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
2027 "Return a count of how many entries in bit vector @var{v} are\n"
2028 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
2029 "consider.\n"
2030 "\n"
2031 "If @var{kv} is a bit vector, then those entries where it has\n"
2032 "@code{#t} are the ones in @var{v} which are considered.\n"
2033 "@var{kv} and @var{v} must be the same length.\n"
2034 "\n"
85368844
MV
2035 "If @var{kv} is a u32vector, then it contains\n"
2036 "the indexes in @var{v} to consider.\n"
88ecf5cb
KR
2037 "\n"
2038 "For example,\n"
2039 "\n"
2040 "@example\n"
2041 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
85368844 2042 "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
88ecf5cb 2043 "@end example")
1bbd0b84 2044#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 2045{
f0b91039
MV
2046 scm_t_array_handle v_handle;
2047 size_t v_off, v_len;
2048 ssize_t v_inc;
2049 const scm_t_uint32 *v_bits;
2050 size_t count = 0;
2051 int bit;
2052
2053 /* Validate that OBJ is a boolean so this is done even if we don't
2054 need BIT.
2055 */
2056 bit = scm_to_bool (obj);
2057
2058 v_bits = scm_bitvector_elements (v, &v_handle,
2059 &v_off, &v_len, &v_inc);
2060
20930f28 2061 if (scm_is_bitvector (kv))
0f2d19dd 2062 {
f0b91039
MV
2063 scm_t_array_handle kv_handle;
2064 size_t kv_off, kv_len;
2065 ssize_t kv_inc;
2066 const scm_t_uint32 *kv_bits;
2067
2068 kv_bits = scm_bitvector_elements (v, &kv_handle,
2069 &kv_off, &kv_len, &kv_inc);
85368844 2070
f0b91039 2071 if (v_len != kv_len)
85368844
MV
2072 scm_misc_error (NULL,
2073 "bit vectors must have equal length",
2074 SCM_EOL);
2075
f0b91039
MV
2076 if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
2077 {
2078 size_t i, word_len = (kv_len + 31) / 32;
2079 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
2080 scm_t_uint32 xor_mask = bit? 0 : ((scm_t_uint32)-1);
2081
2082 for (i = 0; i < word_len-1; i++)
2083 count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i]);
2084 count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i] & last_mask);
2085 }
2086 else
2087 {
2088 size_t i;
2089 for (i = 0; i < kv_len; i++)
2090 if (scm_is_true (scm_array_handle_ref (&kv_handle, i)))
2091 {
2092 SCM elt = scm_array_handle_ref (&v_handle, i);
2093 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
2094 count++;
2095 }
2096 }
cdd6e0a8
MV
2097
2098 scm_array_handle_release (&kv_handle);
2099
0f2d19dd 2100 }
85368844
MV
2101 else if (scm_is_true (scm_u32vector_p (kv)))
2102 {
f0b91039
MV
2103 scm_t_array_handle kv_handle;
2104 size_t i, kv_len;
2105 ssize_t kv_inc;
2106 const scm_t_uint32 *kv_elts;
d44ff083 2107
f0b91039
MV
2108 kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
2109 for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
2110 {
2111 SCM elt = scm_array_handle_ref (&v_handle, *kv_elts);
2112 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
2113 count++;
2114 }
cdd6e0a8
MV
2115
2116 scm_array_handle_release (&kv_handle);
85368844 2117 }
20930f28 2118 else
85368844 2119 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
f0b91039 2120
cdd6e0a8
MV
2121 scm_array_handle_release (&v_handle);
2122
f0b91039 2123 return scm_from_size_t (count);
0f2d19dd 2124}
1bbd0b84 2125#undef FUNC_NAME
0f2d19dd 2126
3b3b36dd 2127SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2128 (SCM v),
88ecf5cb
KR
2129 "Modify the bit vector @var{v} by replacing each element with\n"
2130 "its negation.")
1bbd0b84 2131#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2132{
f0b91039
MV
2133 scm_t_array_handle handle;
2134 size_t off, len;
2135 ssize_t inc;
2136 scm_t_uint32 *bits;
74014c46 2137
f0b91039
MV
2138 bits = scm_bitvector_writable_elements (v, &handle, &off, &len, &inc);
2139
2140 if (off == 0 && inc == 1 && len > 0)
2141 {
2142 size_t word_len = (len + 31) / 32;
2143 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
2144 size_t i;
2145
2146 for (i = 0; i < word_len-1; i++)
2147 bits[i] = ~bits[i];
2148 bits[i] = bits[i] ^ last_mask;
2149 }
2150 else
2151 {
2152 size_t i;
2153 for (i = 0; i < len; i++)
2154 scm_array_handle_set (&handle, i,
2155 scm_not (scm_array_handle_ref (&handle, i)));
2156 }
74014c46 2157
cdd6e0a8
MV
2158 scm_array_handle_release (&handle);
2159
0f2d19dd
JB
2160 return SCM_UNSPECIFIED;
2161}
1bbd0b84 2162#undef FUNC_NAME
0f2d19dd
JB
2163
2164
0f2d19dd 2165SCM
cc95e00a 2166scm_istr2bve (SCM str)
0f2d19dd 2167{
f0b91039 2168 scm_t_array_handle handle;
cc95e00a 2169 size_t len = scm_i_string_length (str);
20930f28
MV
2170 SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
2171 SCM res = vec;
2172
2173 scm_t_uint32 mask;
2174 size_t k, j;
f0b91039
MV
2175 const char *c_str;
2176 scm_t_uint32 *data;
2177
2178 data = scm_bitvector_writable_elements (vec, &handle, NULL, NULL, NULL);
2179 c_str = scm_i_string_chars (str);
cc95e00a 2180
20930f28 2181 for (k = 0; k < (len + 31) / 32; k++)
0f2d19dd
JB
2182 {
2183 data[k] = 0L;
20930f28
MV
2184 j = len - k * 32;
2185 if (j > 32)
2186 j = 32;
0f2d19dd 2187 for (mask = 1L; j--; mask <<= 1)
cc95e00a 2188 switch (*c_str++)
0f2d19dd
JB
2189 {
2190 case '0':
2191 break;
2192 case '1':
2193 data[k] |= mask;
2194 break;
2195 default:
20930f28
MV
2196 res = SCM_BOOL_F;
2197 goto exit;
0f2d19dd
JB
2198 }
2199 }
20930f28
MV
2200
2201 exit:
cdd6e0a8 2202 scm_array_handle_release (&handle);
20930f28 2203 scm_remember_upto_here_1 (str);
20930f28 2204 return res;
0f2d19dd
JB
2205}
2206
2207
1cc91f1b 2208
0f2d19dd 2209static SCM
34d19ef6 2210ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2211{
02339e5b 2212 SCM res = SCM_EOL;
5f37cb63 2213 long inc;
02339e5b
MV
2214 size_t i;
2215 int enclosed = SCM_ENCLOSED_ARRAYP (ra);
2216
5f37cb63
MV
2217 if (k == SCM_ARRAY_NDIM (ra))
2218 return scm_i_cvref (SCM_ARRAY_V (ra), base, enclosed);
2219
2220 inc = SCM_ARRAY_DIMS (ra)[k].inc;
0f2d19dd
JB
2221 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2222 return SCM_EOL;
2223 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
5f37cb63 2224 do
0f2d19dd 2225 {
5f37cb63
MV
2226 i -= inc;
2227 res = scm_cons (ra2l (ra, i, k + 1), res);
0f2d19dd 2228 }
5f37cb63 2229 while (i != base);
0f2d19dd
JB
2230 return res;
2231}
2232
2233
cd328b4f 2234SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2235 (SCM v),
1e6808ea
MG
2236 "Return a list consisting of all the elements, in order, of\n"
2237 "@var{array}.")
cd328b4f 2238#define FUNC_NAME s_scm_array_to_list
0f2d19dd 2239{
20930f28
MV
2240 if (scm_is_generalized_vector (v))
2241 return scm_generalized_vector_to_list (v);
02339e5b 2242 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
20930f28 2243 return ra2l (v, SCM_ARRAY_BASE (v), 0);
e0e49670 2244
20930f28 2245 scm_wrong_type_arg_msg (NULL, 0, v, "array");
0f2d19dd 2246}
1bbd0b84 2247#undef FUNC_NAME
0f2d19dd
JB
2248
2249
bcbbea0e 2250static void l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k);
1cc91f1b 2251
f301dbf3
MV
2252SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
2253 (SCM type, SCM ndim, SCM lst),
2254 "Return an array of the type @var{type}\n"
2255 "with elements the same as those of @var{lst}.\n"
bfad4005
MV
2256 "\n"
2257 "The argument @var{ndim} determines the number of dimensions\n"
2258 "of the array. It is either an exact integer, giving the\n"
20930f28 2259 "number directly, or a list of exact integers, whose length\n"
bfad4005
MV
2260 "specifies the number of dimensions and each element is the\n"
2261 "lower index bound of its dimension.")
f301dbf3 2262#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 2263{
bfad4005 2264 SCM shape, row;
0f2d19dd 2265 SCM ra;
bcbbea0e 2266 scm_t_array_handle handle;
bfad4005
MV
2267
2268 shape = SCM_EOL;
2269 row = lst;
2270 if (scm_is_integer (ndim))
0f2d19dd 2271 {
bfad4005
MV
2272 size_t k = scm_to_size_t (ndim);
2273 while (k-- > 0)
2274 {
2275 shape = scm_cons (scm_length (row), shape);
2276 if (k > 0)
2277 row = scm_car (row);
2278 }
2279 }
2280 else
2281 {
2282 while (1)
2283 {
2284 shape = scm_cons (scm_list_2 (scm_car (ndim),
2285 scm_sum (scm_sum (scm_car (ndim),
2286 scm_length (row)),
2287 scm_from_int (-1))),
2288 shape);
2289 ndim = scm_cdr (ndim);
2290 if (scm_is_pair (ndim))
2291 row = scm_car (row);
2292 else
2293 break;
2294 }
0f2d19dd 2295 }
bfad4005 2296
f0b91039
MV
2297 ra = scm_make_typed_array (type, SCM_UNSPECIFIED,
2298 scm_reverse_x (shape, SCM_EOL));
20930f28 2299
bcbbea0e
MV
2300 scm_array_get_handle (ra, &handle);
2301 l2ra (lst, &handle, 0, 0);
2302 scm_array_handle_release (&handle);
2303
2304 return ra;
0f2d19dd 2305}
1bbd0b84 2306#undef FUNC_NAME
0f2d19dd 2307
f301dbf3
MV
2308SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
2309 (SCM ndim, SCM lst),
2310 "Return an array with elements the same as those of @var{lst}.")
2311#define FUNC_NAME s_scm_list_to_array
2312{
2313 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
2314}
2315#undef FUNC_NAME
2316
bcbbea0e
MV
2317static void
2318l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
0f2d19dd 2319{
bcbbea0e
MV
2320 if (k == scm_array_handle_rank (handle))
2321 scm_array_handle_set (handle, pos, lst);
0f2d19dd
JB
2322 else
2323 {
bcbbea0e
MV
2324 scm_t_array_dim *dim = scm_array_handle_dims (handle) + k;
2325 ssize_t inc = dim->inc;
2326 size_t n = 1 + dim->ubnd - dim->lbnd;
2327
2328 while (n > 0 && scm_is_pair (lst))
0f2d19dd 2329 {
bcbbea0e
MV
2330 l2ra (SCM_CAR (lst), handle, pos, k + 1);
2331 pos += inc;
0f2d19dd 2332 lst = SCM_CDR (lst);
bcbbea0e 2333 n -= 1;
0f2d19dd 2334 }
bcbbea0e
MV
2335 if (n != 0)
2336 scm_misc_error (NULL, "too few elements for array dimension ~a",
2337 scm_list_1 (scm_from_ulong (k)));
d2e53ed6 2338 if (!scm_is_null (lst))
bcbbea0e
MV
2339 scm_misc_error (NULL, "too many elements for array dimension ~a",
2340 scm_list_1 (scm_from_ulong (k)));
0f2d19dd 2341 }
0f2d19dd
JB
2342}
2343
f301dbf3
MV
2344#if SCM_ENABLE_DEPRECATED
2345
2346SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
2347 (SCM ndim, SCM prot, SCM lst),
2348 "Return a uniform array of the type indicated by prototype\n"
2349 "@var{prot} with elements the same as those of @var{lst}.\n"
2350 "Elements must be of the appropriate type, no coercions are\n"
2351 "done.\n"
2352 "\n"
2353 "The argument @var{ndim} determines the number of dimensions\n"
2354 "of the array. It is either an exact integer, giving the\n"
2355 "number directly, or a list of exact integers, whose length\n"
2356 "specifies the number of dimensions and each element is the\n"
2357 "lower index bound of its dimension.")
2358#define FUNC_NAME s_scm_list_to_uniform_array
2359{
2360 return scm_list_to_typed_array (prototype_to_type (prot), ndim, lst);
2361}
2362#undef FUNC_NAME
2363
2364#endif
1cc91f1b 2365
e0e49670
MV
2366/* Print dimension DIM of ARRAY.
2367 */
0f2d19dd 2368
e0e49670 2369static int
02339e5b 2370scm_i_print_array_dimension (SCM array, int dim, int base, int enclosed,
e0e49670
MV
2371 SCM port, scm_print_state *pstate)
2372{
2373 scm_t_array_dim *dim_spec = SCM_ARRAY_DIMS (array) + dim;
2374 long idx;
2375
2376 scm_putc ('(', port);
2377
e0e49670
MV
2378 for (idx = dim_spec->lbnd; idx <= dim_spec->ubnd; idx++)
2379 {
2380 if (dim < SCM_ARRAY_NDIM(array)-1)
02339e5b
MV
2381 scm_i_print_array_dimension (array, dim+1, base, enclosed,
2382 port, pstate);
e0e49670 2383 else
02339e5b 2384 scm_iprin1 (scm_i_cvref (SCM_ARRAY_V (array), base, enclosed),
e0e49670
MV
2385 port, pstate);
2386 if (idx < dim_spec->ubnd)
2387 scm_putc (' ', port);
2388 base += dim_spec->inc;
2389 }
2390
2391 scm_putc (')', port);
2392 return 1;
2393}
2394
f301dbf3 2395/* Print an array. (Only for strict arrays, not for generalized vectors.)
e0e49670
MV
2396*/
2397
e0e49670
MV
2398static int
2399scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
2400{
2401 long ndim = SCM_ARRAY_NDIM (array);
2402 scm_t_array_dim *dim_specs = SCM_ARRAY_DIMS (array);
20930f28 2403 SCM v = SCM_ARRAY_V (array);
e0e49670
MV
2404 unsigned long base = SCM_ARRAY_BASE (array);
2405 long i;
2406
2407 scm_putc ('#', port);
c0fc64c8 2408 if (ndim != 1 || dim_specs[0].lbnd != 0)
e0e49670 2409 scm_intprint (ndim, 10, port);
20930f28
MV
2410 if (scm_is_uniform_vector (v))
2411 scm_puts (scm_i_uniform_vector_tag (v), port);
2412 else if (scm_is_bitvector (v))
2413 scm_puts ("b", port);
2414 else if (scm_is_string (v))
2415 scm_puts ("a", port);
2416 else if (!scm_is_vector (v))
2417 scm_puts ("?", port);
2418
e0e49670
MV
2419 for (i = 0; i < ndim; i++)
2420 if (dim_specs[i].lbnd != 0)
2421 {
2422 for (i = 0; i < ndim; i++)
2423 {
2424 scm_putc ('@', port);
2425 scm_uintprint (dim_specs[i].lbnd, 10, port);
2426 }
2427 break;
2428 }
2429
5f37cb63
MV
2430 if (ndim == 0)
2431 {
2432 /* Rank zero arrays, which are really just scalars, are printed
2433 specially. The consequent way would be to print them as
2434
2435 #0 OBJ
2436
2437 where OBJ is the printed representation of the scalar, but we
2438 print them instead as
2439
2440 #0(OBJ)
2441
2442 to make them look less strange.
2443
2444 Just printing them as
2445
2446 OBJ
2447
2448 would be correct in a way as well, but zero rank arrays are
2449 not really the same as Scheme values since they are boxed and
2450 can be modified with array-set!, say.
2451 */
2452 scm_putc ('(', port);
2453 scm_iprin1 (scm_i_cvref (v, base, 0), port, pstate);
2454 scm_putc (')', port);
2455 return 1;
2456 }
2457 else
2458 return scm_i_print_array_dimension (array, 0, base, 0, port, pstate);
02339e5b
MV
2459}
2460
2461static int
2462scm_i_print_enclosed_array (SCM array, SCM port, scm_print_state *pstate)
2463{
2464 size_t base;
2465
2466 scm_putc ('#', port);
2467 base = SCM_ARRAY_BASE (array);
2468 scm_puts ("<enclosed-array ", port);
2469 scm_i_print_array_dimension (array, 0, base, 1, port, pstate);
2470 scm_putc ('>', port);
2471 return 1;
e0e49670 2472}
1cc91f1b 2473
bfad4005
MV
2474/* Read an array. This function can also read vectors and uniform
2475 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2476 handled here.
2477
2478 C is the first character read after the '#'.
2479*/
2480
bfad4005 2481static SCM
f301dbf3 2482tag_to_type (const char *tag, SCM port)
bfad4005 2483{
bfad4005
MV
2484#if SCM_ENABLE_DEPRECATED
2485 {
f301dbf3 2486 /* Recognize the old syntax.
bfad4005 2487 */
bfad4005
MV
2488 const char *instead;
2489 switch (tag[0])
2490 {
bfad4005 2491 case 'u':
bfad4005
MV
2492 instead = "u32";
2493 break;
2494 case 'e':
bfad4005
MV
2495 instead = "s32";
2496 break;
2497 case 's':
bfad4005
MV
2498 instead = "f32";
2499 break;
2500 case 'i':
bfad4005
MV
2501 instead = "f64";
2502 break;
2503 case 'y':
bfad4005
MV
2504 instead = "s8";
2505 break;
2506 case 'h':
bfad4005
MV
2507 instead = "s16";
2508 break;
2509 case 'l':
bfad4005
MV
2510 instead = "s64";
2511 break;
2512 case 'c':
72d05aa4
MV
2513 instead = "c64";
2514 break;
2515 default:
f301dbf3 2516 instead = NULL;
bfad4005
MV
2517 break;
2518 }
f301dbf3
MV
2519
2520 if (instead && tag[1] == '\0')
bfad4005
MV
2521 {
2522 scm_c_issue_deprecation_warning_fmt
2523 ("The tag '%c' is deprecated for uniform vectors. "
2524 "Use '%s' instead.", tag[0], instead);
f301dbf3 2525 return scm_from_locale_symbol (instead);
bfad4005
MV
2526 }
2527 }
2528#endif
5f37cb63
MV
2529
2530 if (*tag == '\0')
2531 return SCM_BOOL_T;
2532 else
2533 return scm_from_locale_symbol (tag);
bfad4005
MV
2534}
2535
2536SCM
2537scm_i_read_array (SCM port, int c)
2538{
2539 size_t rank;
2540 int got_rank;
2541 char tag[80];
2542 int tag_len;
2543
5f37cb63 2544 SCM lower_bounds = SCM_BOOL_F, elements;
bfad4005
MV
2545
2546 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2547 the array code can not deal with zero-length dimensions yet, and
2548 we want to allow zero-length vectors, of course.
2549 */
2550 if (c == '(')
2551 {
2552 scm_ungetc (c, port);
2553 return scm_vector (scm_read (port));
2554 }
2555
2556 /* Disambiguate between '#f' and uniform floating point vectors.
2557 */
2558 if (c == 'f')
2559 {
2560 c = scm_getc (port);
2561 if (c != '3' && c != '6')
2562 {
2563 if (c != EOF)
2564 scm_ungetc (c, port);
2565 return SCM_BOOL_F;
2566 }
2567 rank = 1;
2568 got_rank = 1;
2569 tag[0] = 'f';
2570 tag_len = 1;
2571 goto continue_reading_tag;
2572 }
2573
5f37cb63 2574 /* Read rank. */
bfad4005
MV
2575 rank = 0;
2576 got_rank = 0;
2577 while ('0' <= c && c <= '9')
2578 {
2579 rank = 10*rank + c-'0';
2580 got_rank = 1;
2581 c = scm_getc (port);
2582 }
2583 if (!got_rank)
2584 rank = 1;
bfad4005
MV
2585
2586 /* Read tag. */
2587 tag_len = 0;
2588 continue_reading_tag:
2589 while (c != EOF && c != '(' && c != '@' && tag_len < 80)
2590 {
2591 tag[tag_len++] = c;
2592 c = scm_getc (port);
2593 }
2594 tag[tag_len] = '\0';
2595
2596 /* Read lower bounds. */
5f37cb63 2597 if (c == '@')
bfad4005 2598 {
5f37cb63
MV
2599 lower_bounds = SCM_EOL;
2600
2601 do
bfad4005 2602 {
5f37cb63
MV
2603 /* Yeah, right, we should use some ready-made integer parsing
2604 routine for this...
2605 */
2606
2607 long lbnd = 0;
2608 long sign = 1;
2609
bfad4005 2610 c = scm_getc (port);
5f37cb63
MV
2611 if (c == '-')
2612 {
2613 sign = -1;
2614 c = scm_getc (port);
2615 }
2616 while ('0' <= c && c <= '9')
2617 {
2618 lbnd = 10*lbnd + c-'0';
2619 c = scm_getc (port);
2620 }
2621 lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
2622 } while (c == '@');
bfad4005
MV
2623 }
2624
2625 /* Read nested lists of elements.
2626 */
2627 if (c != '(')
2628 scm_i_input_error (NULL, port,
2629 "missing '(' in vector or array literal",
2630 SCM_EOL);
2631 scm_ungetc (c, port);
2632 elements = scm_read (port);
2633
5f37cb63 2634 if (scm_is_false (lower_bounds))
bfad4005
MV
2635 lower_bounds = scm_from_size_t (rank);
2636 else if (scm_ilength (lower_bounds) != rank)
2637 scm_i_input_error (NULL, port,
2638 "the number of lower bounds must match the array rank",
2639 SCM_EOL);
2640
5f37cb63
MV
2641 /* Handle special print syntax of rank zero arrays; see
2642 scm_i_print_array for a rationale.
2643 */
2644 if (rank == 0)
2645 elements = scm_car (elements);
2646
2647 /* Construct array.
2648 */
f301dbf3
MV
2649 return scm_list_to_typed_array (tag_to_type (tag, port),
2650 lower_bounds,
2651 elements);
bfad4005
MV
2652}
2653
0f2d19dd 2654int
1bbd0b84 2655scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 2656{
02339e5b 2657 scm_iprin1 (exp, port, pstate);
0f2d19dd
JB
2658 return 1;
2659}
2660
f301dbf3 2661SCM_DEFINE (scm_array_type, "array-type", 1, 0, 0,
ab1be174 2662 (SCM ra),
f301dbf3
MV
2663 "")
2664#define FUNC_NAME s_scm_array_type
ab1be174 2665{
ab1be174 2666 if (SCM_ARRAYP (ra))
f301dbf3 2667 return scm_i_generalized_vector_type (SCM_ARRAY_V (ra));
02339e5b 2668 else if (scm_is_generalized_vector (ra))
f301dbf3 2669 return scm_i_generalized_vector_type (ra);
02339e5b
MV
2670 else if (SCM_ENCLOSED_ARRAYP (ra))
2671 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
ab1be174 2672 else
02339e5b 2673 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
ab1be174
MV
2674}
2675#undef FUNC_NAME
2676
72d05aa4
MV
2677#if SCM_ENABLE_DEPRECATED
2678
3b3b36dd 2679SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2680 (SCM ra),
1e6808ea
MG
2681 "Return an object that would produce an array of the same type\n"
2682 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2683 "@code{make-uniform-array}.")
1bbd0b84 2684#define FUNC_NAME s_scm_array_prototype
0f2d19dd 2685{
20930f28 2686 if (SCM_ARRAYP (ra))
02339e5b 2687 return scm_i_get_old_prototype (SCM_ARRAY_V (ra));
20930f28
MV
2688 else if (scm_is_generalized_vector (ra))
2689 return scm_i_get_old_prototype (ra);
02339e5b
MV
2690 else if (SCM_ENCLOSED_ARRAYP (ra))
2691 return SCM_UNSPECIFIED;
20930f28
MV
2692 else
2693 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 2694}
1bbd0b84 2695#undef FUNC_NAME
0f2d19dd 2696
72d05aa4 2697#endif
1cc91f1b 2698
0f2d19dd 2699static SCM
e841c3e0 2700array_mark (SCM ptr)
0f2d19dd 2701{
0f2d19dd
JB
2702 return SCM_ARRAY_V (ptr);
2703}
2704
1be6b49c 2705static size_t
e841c3e0 2706array_free (SCM ptr)
0f2d19dd 2707{
4c9419ac
MV
2708 scm_gc_free (SCM_ARRAY_MEM (ptr),
2709 (sizeof (scm_t_array)
2710 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2711 "array");
2712 return 0;
0f2d19dd
JB
2713}
2714
0f2d19dd
JB
2715void
2716scm_init_unif ()
0f2d19dd 2717{
e841c3e0
KN
2718 scm_tc16_array = scm_make_smob_type ("array", 0);
2719 scm_set_smob_mark (scm_tc16_array, array_mark);
2720 scm_set_smob_free (scm_tc16_array, array_free);
02339e5b 2721 scm_set_smob_print (scm_tc16_array, scm_i_print_array);
e841c3e0 2722 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
02339e5b
MV
2723
2724 scm_tc16_enclosed_array = scm_make_smob_type ("enclosed-array", 0);
2725 scm_set_smob_mark (scm_tc16_enclosed_array, array_mark);
2726 scm_set_smob_free (scm_tc16_enclosed_array, array_free);
2727 scm_set_smob_print (scm_tc16_enclosed_array, scm_i_print_enclosed_array);
2728 scm_set_smob_equalp (scm_tc16_enclosed_array, scm_array_equal_p);
2729
0f2d19dd 2730 scm_add_feature ("array");
20930f28
MV
2731
2732 scm_tc16_bitvector = scm_make_smob_type ("bitvector", 0);
2733 scm_set_smob_free (scm_tc16_bitvector, bitvector_free);
2734 scm_set_smob_print (scm_tc16_bitvector, bitvector_print);
2735 scm_set_smob_equalp (scm_tc16_bitvector, bitvector_equalp);
2736
f301dbf3
MV
2737 init_type_creator_table ();
2738
a0599745 2739#include "libguile/unif.x"
bfad4005 2740
0f2d19dd 2741}
89e00824
ML
2742
2743/*
2744 Local Variables:
2745 c-file-style: "gnu"
2746 End:
2747*/