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