(scm_uniform_element_size): Deprecated implementation
[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 2211 SCM res = SCM_EOL;
5f37cb63 2212 long inc;
02339e5b
MV
2213 size_t i;
2214 int enclosed = SCM_ENCLOSED_ARRAYP (ra);
2215
5f37cb63
MV
2216 if (k == SCM_ARRAY_NDIM (ra))
2217 return scm_i_cvref (SCM_ARRAY_V (ra), base, enclosed);
2218
2219 inc = SCM_ARRAY_DIMS (ra)[k].inc;
0f2d19dd
JB
2220 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2221 return SCM_EOL;
2222 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
5f37cb63 2223 do
0f2d19dd 2224 {
5f37cb63
MV
2225 i -= inc;
2226 res = scm_cons (ra2l (ra, i, k + 1), res);
0f2d19dd 2227 }
5f37cb63 2228 while (i != base);
0f2d19dd
JB
2229 return res;
2230}
2231
2232
cd328b4f 2233SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2234 (SCM v),
1e6808ea
MG
2235 "Return a list consisting of all the elements, in order, of\n"
2236 "@var{array}.")
cd328b4f 2237#define FUNC_NAME s_scm_array_to_list
0f2d19dd 2238{
20930f28
MV
2239 if (scm_is_generalized_vector (v))
2240 return scm_generalized_vector_to_list (v);
02339e5b 2241 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
20930f28 2242 return ra2l (v, SCM_ARRAY_BASE (v), 0);
e0e49670 2243
20930f28 2244 scm_wrong_type_arg_msg (NULL, 0, v, "array");
0f2d19dd 2245}
1bbd0b84 2246#undef FUNC_NAME
0f2d19dd
JB
2247
2248
c014a02e 2249static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2250
f301dbf3
MV
2251SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
2252 (SCM type, SCM ndim, SCM lst),
2253 "Return an array of the type @var{type}\n"
2254 "with elements the same as those of @var{lst}.\n"
bfad4005
MV
2255 "\n"
2256 "The argument @var{ndim} determines the number of dimensions\n"
2257 "of the array. It is either an exact integer, giving the\n"
20930f28 2258 "number directly, or a list of exact integers, whose length\n"
bfad4005
MV
2259 "specifies the number of dimensions and each element is the\n"
2260 "lower index bound of its dimension.")
f301dbf3 2261#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 2262{
bfad4005 2263 SCM shape, row;
0f2d19dd 2264 SCM ra;
c014a02e 2265 unsigned long k;
bfad4005
MV
2266
2267 shape = SCM_EOL;
2268 row = lst;
2269 if (scm_is_integer (ndim))
0f2d19dd 2270 {
bfad4005
MV
2271 size_t k = scm_to_size_t (ndim);
2272 while (k-- > 0)
2273 {
2274 shape = scm_cons (scm_length (row), shape);
2275 if (k > 0)
2276 row = scm_car (row);
2277 }
2278 }
2279 else
2280 {
2281 while (1)
2282 {
2283 shape = scm_cons (scm_list_2 (scm_car (ndim),
2284 scm_sum (scm_sum (scm_car (ndim),
2285 scm_length (row)),
2286 scm_from_int (-1))),
2287 shape);
2288 ndim = scm_cdr (ndim);
2289 if (scm_is_pair (ndim))
2290 row = scm_car (row);
2291 else
2292 break;
2293 }
0f2d19dd 2294 }
bfad4005 2295
f0b91039
MV
2296 ra = scm_make_typed_array (type, SCM_UNSPECIFIED,
2297 scm_reverse_x (shape, SCM_EOL));
20930f28 2298
bfad4005 2299 if (scm_is_null (shape))
0f2d19dd
JB
2300 {
2301 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2302 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2303 return ra;
2304 }
2305 if (!SCM_ARRAYP (ra))
2306 {
20930f28 2307 size_t length = scm_c_generalized_vector_length (ra);
74014c46 2308 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
20930f28 2309 scm_c_generalized_vector_set_x (ra, k, SCM_CAR (lst));
0f2d19dd
JB
2310 return ra;
2311 }
2312 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2313 return ra;
2314 else
1afff620
KN
2315 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2316 scm_list_1 (lst));
0f2d19dd 2317}
1bbd0b84 2318#undef FUNC_NAME
0f2d19dd 2319
f301dbf3
MV
2320SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
2321 (SCM ndim, SCM lst),
2322 "Return an array with elements the same as those of @var{lst}.")
2323#define FUNC_NAME s_scm_list_to_array
2324{
2325 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
2326}
2327#undef FUNC_NAME
2328
0f2d19dd 2329static int
c014a02e 2330l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2331{
c014a02e
ML
2332 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2333 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2334 int ok = 1;
2335 if (n <= 0)
d2e53ed6 2336 return (scm_is_null (lst));
0f2d19dd
JB
2337 if (k < SCM_ARRAY_NDIM (ra) - 1)
2338 {
2339 while (n--)
2340 {
d2e53ed6 2341 if (!scm_is_pair (lst))
0f2d19dd
JB
2342 return 0;
2343 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2344 base += inc;
2345 lst = SCM_CDR (lst);
2346 }
d2e53ed6 2347 if (!scm_is_null (lst))
0f2d19dd
JB
2348 return 0;
2349 }
2350 else
2351 {
2352 while (n--)
2353 {
d2e53ed6 2354 if (!scm_is_pair (lst))
0f2d19dd 2355 return 0;
e11e83f3 2356 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), scm_from_ulong (base));
0f2d19dd
JB
2357 base += inc;
2358 lst = SCM_CDR (lst);
2359 }
d2e53ed6 2360 if (!scm_is_null (lst))
fee7ef83 2361 return 0;
0f2d19dd
JB
2362 }
2363 return ok;
2364}
2365
f301dbf3
MV
2366#if SCM_ENABLE_DEPRECATED
2367
2368SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
2369 (SCM ndim, SCM prot, SCM lst),
2370 "Return a uniform array of the type indicated by prototype\n"
2371 "@var{prot} with elements the same as those of @var{lst}.\n"
2372 "Elements must be of the appropriate type, no coercions are\n"
2373 "done.\n"
2374 "\n"
2375 "The argument @var{ndim} determines the number of dimensions\n"
2376 "of the array. It is either an exact integer, giving the\n"
2377 "number directly, or a list of exact integers, whose length\n"
2378 "specifies the number of dimensions and each element is the\n"
2379 "lower index bound of its dimension.")
2380#define FUNC_NAME s_scm_list_to_uniform_array
2381{
2382 return scm_list_to_typed_array (prototype_to_type (prot), ndim, lst);
2383}
2384#undef FUNC_NAME
2385
2386#endif
1cc91f1b 2387
e0e49670
MV
2388/* Print dimension DIM of ARRAY.
2389 */
0f2d19dd 2390
e0e49670 2391static int
02339e5b 2392scm_i_print_array_dimension (SCM array, int dim, int base, int enclosed,
e0e49670
MV
2393 SCM port, scm_print_state *pstate)
2394{
2395 scm_t_array_dim *dim_spec = SCM_ARRAY_DIMS (array) + dim;
2396 long idx;
2397
2398 scm_putc ('(', port);
2399
e0e49670
MV
2400 for (idx = dim_spec->lbnd; idx <= dim_spec->ubnd; idx++)
2401 {
2402 if (dim < SCM_ARRAY_NDIM(array)-1)
02339e5b
MV
2403 scm_i_print_array_dimension (array, dim+1, base, enclosed,
2404 port, pstate);
e0e49670 2405 else
02339e5b 2406 scm_iprin1 (scm_i_cvref (SCM_ARRAY_V (array), base, enclosed),
e0e49670
MV
2407 port, pstate);
2408 if (idx < dim_spec->ubnd)
2409 scm_putc (' ', port);
2410 base += dim_spec->inc;
2411 }
2412
2413 scm_putc (')', port);
2414 return 1;
2415}
2416
f301dbf3 2417/* Print an array. (Only for strict arrays, not for generalized vectors.)
e0e49670
MV
2418*/
2419
e0e49670
MV
2420static int
2421scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
2422{
2423 long ndim = SCM_ARRAY_NDIM (array);
2424 scm_t_array_dim *dim_specs = SCM_ARRAY_DIMS (array);
20930f28 2425 SCM v = SCM_ARRAY_V (array);
e0e49670
MV
2426 unsigned long base = SCM_ARRAY_BASE (array);
2427 long i;
2428
2429 scm_putc ('#', port);
c0fc64c8 2430 if (ndim != 1 || dim_specs[0].lbnd != 0)
e0e49670 2431 scm_intprint (ndim, 10, port);
20930f28
MV
2432 if (scm_is_uniform_vector (v))
2433 scm_puts (scm_i_uniform_vector_tag (v), port);
2434 else if (scm_is_bitvector (v))
2435 scm_puts ("b", port);
2436 else if (scm_is_string (v))
2437 scm_puts ("a", port);
2438 else if (!scm_is_vector (v))
2439 scm_puts ("?", port);
2440
e0e49670
MV
2441 for (i = 0; i < ndim; i++)
2442 if (dim_specs[i].lbnd != 0)
2443 {
2444 for (i = 0; i < ndim; i++)
2445 {
2446 scm_putc ('@', port);
2447 scm_uintprint (dim_specs[i].lbnd, 10, port);
2448 }
2449 break;
2450 }
2451
5f37cb63
MV
2452 if (ndim == 0)
2453 {
2454 /* Rank zero arrays, which are really just scalars, are printed
2455 specially. The consequent way would be to print them as
2456
2457 #0 OBJ
2458
2459 where OBJ is the printed representation of the scalar, but we
2460 print them instead as
2461
2462 #0(OBJ)
2463
2464 to make them look less strange.
2465
2466 Just printing them as
2467
2468 OBJ
2469
2470 would be correct in a way as well, but zero rank arrays are
2471 not really the same as Scheme values since they are boxed and
2472 can be modified with array-set!, say.
2473 */
2474 scm_putc ('(', port);
2475 scm_iprin1 (scm_i_cvref (v, base, 0), port, pstate);
2476 scm_putc (')', port);
2477 return 1;
2478 }
2479 else
2480 return scm_i_print_array_dimension (array, 0, base, 0, port, pstate);
02339e5b
MV
2481}
2482
2483static int
2484scm_i_print_enclosed_array (SCM array, SCM port, scm_print_state *pstate)
2485{
2486 size_t base;
2487
2488 scm_putc ('#', port);
2489 base = SCM_ARRAY_BASE (array);
2490 scm_puts ("<enclosed-array ", port);
2491 scm_i_print_array_dimension (array, 0, base, 1, port, pstate);
2492 scm_putc ('>', port);
2493 return 1;
e0e49670 2494}
1cc91f1b 2495
bfad4005
MV
2496/* Read an array. This function can also read vectors and uniform
2497 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2498 handled here.
2499
2500 C is the first character read after the '#'.
2501*/
2502
bfad4005 2503static SCM
f301dbf3 2504tag_to_type (const char *tag, SCM port)
bfad4005 2505{
bfad4005
MV
2506#if SCM_ENABLE_DEPRECATED
2507 {
f301dbf3 2508 /* Recognize the old syntax.
bfad4005 2509 */
bfad4005
MV
2510 const char *instead;
2511 switch (tag[0])
2512 {
bfad4005 2513 case 'u':
bfad4005
MV
2514 instead = "u32";
2515 break;
2516 case 'e':
bfad4005
MV
2517 instead = "s32";
2518 break;
2519 case 's':
bfad4005
MV
2520 instead = "f32";
2521 break;
2522 case 'i':
bfad4005
MV
2523 instead = "f64";
2524 break;
2525 case 'y':
bfad4005
MV
2526 instead = "s8";
2527 break;
2528 case 'h':
bfad4005
MV
2529 instead = "s16";
2530 break;
2531 case 'l':
bfad4005
MV
2532 instead = "s64";
2533 break;
2534 case 'c':
72d05aa4
MV
2535 instead = "c64";
2536 break;
2537 default:
f301dbf3 2538 instead = NULL;
bfad4005
MV
2539 break;
2540 }
f301dbf3
MV
2541
2542 if (instead && tag[1] == '\0')
bfad4005
MV
2543 {
2544 scm_c_issue_deprecation_warning_fmt
2545 ("The tag '%c' is deprecated for uniform vectors. "
2546 "Use '%s' instead.", tag[0], instead);
f301dbf3 2547 return scm_from_locale_symbol (instead);
bfad4005
MV
2548 }
2549 }
2550#endif
5f37cb63
MV
2551
2552 if (*tag == '\0')
2553 return SCM_BOOL_T;
2554 else
2555 return scm_from_locale_symbol (tag);
bfad4005
MV
2556}
2557
2558SCM
2559scm_i_read_array (SCM port, int c)
2560{
2561 size_t rank;
2562 int got_rank;
2563 char tag[80];
2564 int tag_len;
2565
5f37cb63 2566 SCM lower_bounds = SCM_BOOL_F, elements;
bfad4005
MV
2567
2568 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2569 the array code can not deal with zero-length dimensions yet, and
2570 we want to allow zero-length vectors, of course.
2571 */
2572 if (c == '(')
2573 {
2574 scm_ungetc (c, port);
2575 return scm_vector (scm_read (port));
2576 }
2577
2578 /* Disambiguate between '#f' and uniform floating point vectors.
2579 */
2580 if (c == 'f')
2581 {
2582 c = scm_getc (port);
2583 if (c != '3' && c != '6')
2584 {
2585 if (c != EOF)
2586 scm_ungetc (c, port);
2587 return SCM_BOOL_F;
2588 }
2589 rank = 1;
2590 got_rank = 1;
2591 tag[0] = 'f';
2592 tag_len = 1;
2593 goto continue_reading_tag;
2594 }
2595
5f37cb63 2596 /* Read rank. */
bfad4005
MV
2597 rank = 0;
2598 got_rank = 0;
2599 while ('0' <= c && c <= '9')
2600 {
2601 rank = 10*rank + c-'0';
2602 got_rank = 1;
2603 c = scm_getc (port);
2604 }
2605 if (!got_rank)
2606 rank = 1;
bfad4005
MV
2607
2608 /* Read tag. */
2609 tag_len = 0;
2610 continue_reading_tag:
2611 while (c != EOF && c != '(' && c != '@' && tag_len < 80)
2612 {
2613 tag[tag_len++] = c;
2614 c = scm_getc (port);
2615 }
2616 tag[tag_len] = '\0';
2617
2618 /* Read lower bounds. */
5f37cb63 2619 if (c == '@')
bfad4005 2620 {
5f37cb63
MV
2621 lower_bounds = SCM_EOL;
2622
2623 do
bfad4005 2624 {
5f37cb63
MV
2625 /* Yeah, right, we should use some ready-made integer parsing
2626 routine for this...
2627 */
2628
2629 long lbnd = 0;
2630 long sign = 1;
2631
bfad4005 2632 c = scm_getc (port);
5f37cb63
MV
2633 if (c == '-')
2634 {
2635 sign = -1;
2636 c = scm_getc (port);
2637 }
2638 while ('0' <= c && c <= '9')
2639 {
2640 lbnd = 10*lbnd + c-'0';
2641 c = scm_getc (port);
2642 }
2643 lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
2644 } while (c == '@');
bfad4005
MV
2645 }
2646
2647 /* Read nested lists of elements.
2648 */
2649 if (c != '(')
2650 scm_i_input_error (NULL, port,
2651 "missing '(' in vector or array literal",
2652 SCM_EOL);
2653 scm_ungetc (c, port);
2654 elements = scm_read (port);
2655
5f37cb63 2656 if (scm_is_false (lower_bounds))
bfad4005
MV
2657 lower_bounds = scm_from_size_t (rank);
2658 else if (scm_ilength (lower_bounds) != rank)
2659 scm_i_input_error (NULL, port,
2660 "the number of lower bounds must match the array rank",
2661 SCM_EOL);
2662
5f37cb63
MV
2663 /* Handle special print syntax of rank zero arrays; see
2664 scm_i_print_array for a rationale.
2665 */
2666 if (rank == 0)
2667 elements = scm_car (elements);
2668
2669 /* Construct array.
2670 */
f301dbf3
MV
2671 return scm_list_to_typed_array (tag_to_type (tag, port),
2672 lower_bounds,
2673 elements);
bfad4005
MV
2674}
2675
0f2d19dd 2676int
1bbd0b84 2677scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 2678{
02339e5b 2679 scm_iprin1 (exp, port, pstate);
0f2d19dd
JB
2680 return 1;
2681}
2682
f301dbf3 2683SCM_DEFINE (scm_array_type, "array-type", 1, 0, 0,
ab1be174 2684 (SCM ra),
f301dbf3
MV
2685 "")
2686#define FUNC_NAME s_scm_array_type
ab1be174 2687{
ab1be174 2688 if (SCM_ARRAYP (ra))
f301dbf3 2689 return scm_i_generalized_vector_type (SCM_ARRAY_V (ra));
02339e5b 2690 else if (scm_is_generalized_vector (ra))
f301dbf3 2691 return scm_i_generalized_vector_type (ra);
02339e5b
MV
2692 else if (SCM_ENCLOSED_ARRAYP (ra))
2693 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
ab1be174 2694 else
02339e5b 2695 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
ab1be174
MV
2696}
2697#undef FUNC_NAME
2698
72d05aa4
MV
2699#if SCM_ENABLE_DEPRECATED
2700
3b3b36dd 2701SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2702 (SCM ra),
1e6808ea
MG
2703 "Return an object that would produce an array of the same type\n"
2704 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2705 "@code{make-uniform-array}.")
1bbd0b84 2706#define FUNC_NAME s_scm_array_prototype
0f2d19dd 2707{
20930f28 2708 if (SCM_ARRAYP (ra))
02339e5b 2709 return scm_i_get_old_prototype (SCM_ARRAY_V (ra));
20930f28
MV
2710 else if (scm_is_generalized_vector (ra))
2711 return scm_i_get_old_prototype (ra);
02339e5b
MV
2712 else if (SCM_ENCLOSED_ARRAYP (ra))
2713 return SCM_UNSPECIFIED;
20930f28
MV
2714 else
2715 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 2716}
1bbd0b84 2717#undef FUNC_NAME
0f2d19dd 2718
72d05aa4 2719#endif
1cc91f1b 2720
0f2d19dd 2721static SCM
e841c3e0 2722array_mark (SCM ptr)
0f2d19dd 2723{
0f2d19dd
JB
2724 return SCM_ARRAY_V (ptr);
2725}
2726
1be6b49c 2727static size_t
e841c3e0 2728array_free (SCM ptr)
0f2d19dd 2729{
4c9419ac
MV
2730 scm_gc_free (SCM_ARRAY_MEM (ptr),
2731 (sizeof (scm_t_array)
2732 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2733 "array");
2734 return 0;
0f2d19dd
JB
2735}
2736
0f2d19dd
JB
2737void
2738scm_init_unif ()
0f2d19dd 2739{
e841c3e0
KN
2740 scm_tc16_array = scm_make_smob_type ("array", 0);
2741 scm_set_smob_mark (scm_tc16_array, array_mark);
2742 scm_set_smob_free (scm_tc16_array, array_free);
02339e5b 2743 scm_set_smob_print (scm_tc16_array, scm_i_print_array);
e841c3e0 2744 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
02339e5b
MV
2745
2746 scm_tc16_enclosed_array = scm_make_smob_type ("enclosed-array", 0);
2747 scm_set_smob_mark (scm_tc16_enclosed_array, array_mark);
2748 scm_set_smob_free (scm_tc16_enclosed_array, array_free);
2749 scm_set_smob_print (scm_tc16_enclosed_array, scm_i_print_enclosed_array);
2750 scm_set_smob_equalp (scm_tc16_enclosed_array, scm_array_equal_p);
2751
0f2d19dd 2752 scm_add_feature ("array");
20930f28
MV
2753
2754 scm_tc16_bitvector = scm_make_smob_type ("bitvector", 0);
2755 scm_set_smob_free (scm_tc16_bitvector, bitvector_free);
2756 scm_set_smob_print (scm_tc16_bitvector, bitvector_print);
2757 scm_set_smob_equalp (scm_tc16_bitvector, bitvector_equalp);
2758
f301dbf3
MV
2759 init_type_creator_table ();
2760
a0599745 2761#include "libguile/unif.x"
bfad4005 2762
0f2d19dd 2763}
89e00824
ML
2764
2765/*
2766 Local Variables:
2767 c-file-style: "gnu"
2768 End:
2769*/