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