*** 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 855{
112ba0ac 856 scm_t_array_handle old_handle;
0f2d19dd
JB
857 SCM ra;
858 SCM inds, indptr;
859 SCM imap;
112ba0ac
MV
860 size_t k;
861 ssize_t i;
c014a02e 862 long old_min, new_min, old_max, new_max;
92c2555f 863 scm_t_array_dim *s;
b3fcac34
DH
864
865 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6 866 SCM_VALIDATE_PROC (2, mapfunc);
1bbd0b84 867 ra = scm_shap2ra (dims, FUNC_NAME);
112ba0ac
MV
868
869 scm_array_get_handle (oldra, &old_handle);
870
0f2d19dd
JB
871 if (SCM_ARRAYP (oldra))
872 {
873 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
874 old_min = old_max = SCM_ARRAY_BASE (oldra);
112ba0ac
MV
875 s = scm_array_handle_dims (&old_handle);
876 k = scm_array_handle_rank (&old_handle);
0f2d19dd
JB
877 while (k--)
878 {
879 if (s[k].inc > 0)
880 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
881 else
882 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
883 }
884 }
885 else
886 {
887 SCM_ARRAY_V (ra) = oldra;
888 old_min = 0;
02339e5b 889 old_max = scm_c_generalized_vector_length (oldra) - 1;
0f2d19dd 890 }
112ba0ac 891
0f2d19dd
JB
892 inds = SCM_EOL;
893 s = SCM_ARRAY_DIMS (ra);
894 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
895 {
e11e83f3 896 inds = scm_cons (scm_from_long (s[k].lbnd), inds);
0f2d19dd
JB
897 if (s[k].ubnd < s[k].lbnd)
898 {
899 if (1 == SCM_ARRAY_NDIM (ra))
f301dbf3 900 ra = make_typed_vector (scm_array_type (ra), 0);
0f2d19dd 901 else
f301dbf3 902 SCM_ARRAY_V (ra) = make_typed_vector (scm_array_type (ra), 0);
112ba0ac 903 scm_array_handle_release (&old_handle);
0f2d19dd
JB
904 return ra;
905 }
906 }
112ba0ac 907
fdc28395 908 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
112ba0ac 909 i = indices_to_pos (&old_handle, imap);
0f2d19dd
JB
910 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
911 indptr = inds;
912 k = SCM_ARRAY_NDIM (ra);
913 while (k--)
914 {
915 if (s[k].ubnd > s[k].lbnd)
916 {
e11e83f3 917 SCM_SETCAR (indptr, scm_sum (SCM_CAR (indptr), scm_from_int (1)));
fdc28395 918 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
112ba0ac 919 s[k].inc = indices_to_pos (&old_handle, imap) - i;
0f2d19dd
JB
920 i += s[k].inc;
921 if (s[k].inc > 0)
922 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
923 else
924 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
925 }
926 else
927 s[k].inc = new_max - new_min + 1; /* contiguous by default */
928 indptr = SCM_CDR (indptr);
929 }
112ba0ac
MV
930
931 scm_array_handle_release (&old_handle);
932
b3fcac34
DH
933 if (old_min > new_min || old_max < new_max)
934 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
935 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
936 {
74014c46 937 SCM v = SCM_ARRAY_V (ra);
6e708ef2 938 size_t length = scm_c_generalized_vector_length (v);
74014c46
DH
939 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
940 return v;
0f2d19dd 941 if (s->ubnd < s->lbnd)
f301dbf3 942 return make_typed_vector (scm_array_type (ra), 0);
0f2d19dd
JB
943 }
944 scm_ra_set_contp (ra);
945 return ra;
946}
1bbd0b84 947#undef FUNC_NAME
0f2d19dd
JB
948
949
950/* args are RA . DIMS */
af45e3b0
DH
951SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
952 (SCM ra, SCM args),
1e6808ea
MG
953 "Return an array sharing contents with @var{array}, but with\n"
954 "dimensions arranged in a different order. There must be one\n"
955 "@var{dim} argument for each dimension of @var{array}.\n"
956 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
957 "and the rank of the array to be returned. Each integer in that\n"
958 "range must appear at least once in the argument list.\n"
959 "\n"
960 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
961 "dimensions in the array to be returned, their positions in the\n"
962 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
963 "may have the same value, in which case the returned array will\n"
964 "have smaller rank than @var{array}.\n"
965 "\n"
966 "@lisp\n"
b380b885
MD
967 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
968 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
969 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
970 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 971 "@end lisp")
1bbd0b84 972#define FUNC_NAME s_scm_transpose_array
0f2d19dd 973{
34d19ef6 974 SCM res, vargs;
92c2555f 975 scm_t_array_dim *s, *r;
0f2d19dd 976 int ndim, i, k;
af45e3b0 977
b3fcac34 978 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 979 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
e0e49670 980
20930f28 981 if (scm_is_generalized_vector (ra))
e0e49670
MV
982 {
983 /* Make sure that we are called with a single zero as
984 arguments.
985 */
986 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
987 SCM_WRONG_NUM_ARGS ();
988 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
989 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
990 return ra;
991 }
992
02339e5b 993 if (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra))
0f2d19dd 994 {
0f2d19dd 995 vargs = scm_vector (args);
6e708ef2 996 if (SCM_SIMPLE_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
b3fcac34 997 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
998 ndim = 0;
999 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
1000 {
6e708ef2
MV
1001 i = scm_to_signed_integer (SCM_SIMPLE_VECTOR_REF (vargs, k),
1002 0, SCM_ARRAY_NDIM(ra));
0f2d19dd
JB
1003 if (ndim < i)
1004 ndim = i;
1005 }
1006 ndim++;
1007 res = scm_make_ra (ndim);
1008 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
1009 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
1010 for (k = ndim; k--;)
1011 {
1012 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
1013 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
1014 }
1015 for (k = SCM_ARRAY_NDIM (ra); k--;)
1016 {
6e708ef2 1017 i = scm_to_int (SCM_SIMPLE_VECTOR_REF (vargs, k));
0f2d19dd
JB
1018 s = &(SCM_ARRAY_DIMS (ra)[k]);
1019 r = &(SCM_ARRAY_DIMS (res)[i]);
1020 if (r->ubnd < r->lbnd)
1021 {
1022 r->lbnd = s->lbnd;
1023 r->ubnd = s->ubnd;
1024 r->inc = s->inc;
1025 ndim--;
1026 }
1027 else
1028 {
1029 if (r->ubnd > s->ubnd)
1030 r->ubnd = s->ubnd;
1031 if (r->lbnd < s->lbnd)
1032 {
1033 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
1034 r->lbnd = s->lbnd;
1035 }
1036 r->inc += s->inc;
1037 }
1038 }
b3fcac34
DH
1039 if (ndim > 0)
1040 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
1041 scm_ra_set_contp (res);
1042 return res;
1043 }
20930f28
MV
1044
1045 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1046}
1bbd0b84 1047#undef FUNC_NAME
0f2d19dd
JB
1048
1049/* args are RA . AXES */
af45e3b0
DH
1050SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
1051 (SCM ra, SCM axes),
b380b885
MD
1052 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
1053 "the rank of @var{array}. @var{enclose-array} returns an array\n"
1054 "resembling an array of shared arrays. The dimensions of each shared\n"
1055 "array are the same as the @var{dim}th dimensions of the original array,\n"
1056 "the dimensions of the outer array are the same as those of the original\n"
1057 "array that did not match a @var{dim}.\n\n"
1058 "An enclosed array is not a general Scheme array. Its elements may not\n"
1059 "be set using @code{array-set!}. Two references to the same element of\n"
1060 "an enclosed array will be @code{equal?} but will not in general be\n"
1061 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
1062 "enclosed array is unspecified.\n\n"
1063 "examples:\n"
1e6808ea 1064 "@lisp\n"
b380b885
MD
1065 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
1066 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
1067 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
1068 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 1069 "@end lisp")
1bbd0b84 1070#define FUNC_NAME s_scm_enclose_array
0f2d19dd 1071{
af45e3b0 1072 SCM axv, res, ra_inr;
cc95e00a 1073 const char *c_axv;
92c2555f 1074 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 1075 int ndim, j, k, ninr, noutr;
af45e3b0 1076
b3fcac34 1077 SCM_VALIDATE_REST_ARGUMENT (axes);
d2e53ed6 1078 if (scm_is_null (axes))
02339e5b 1079 axes = scm_cons ((SCM_ARRAYP (ra) ? scm_from_size_t (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
0f2d19dd 1080 ninr = scm_ilength (axes);
b3fcac34
DH
1081 if (ninr < 0)
1082 SCM_WRONG_NUM_ARGS ();
0f2d19dd 1083 ra_inr = scm_make_ra (ninr);
e0e49670 1084
20930f28 1085 if (scm_is_generalized_vector (ra))
0f2d19dd 1086 {
0f2d19dd 1087 s->lbnd = 0;
6e708ef2 1088 s->ubnd = scm_c_generalized_vector_length (ra) - 1;
0f2d19dd
JB
1089 s->inc = 1;
1090 SCM_ARRAY_V (ra_inr) = ra;
1091 SCM_ARRAY_BASE (ra_inr) = 0;
1092 ndim = 1;
20930f28
MV
1093 }
1094 else if (SCM_ARRAYP (ra))
1095 {
0f2d19dd
JB
1096 s = SCM_ARRAY_DIMS (ra);
1097 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
1098 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
1099 ndim = SCM_ARRAY_NDIM (ra);
0f2d19dd 1100 }
20930f28
MV
1101 else
1102 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
1103
0f2d19dd 1104 noutr = ndim - ninr;
b3fcac34
DH
1105 if (noutr < 0)
1106 SCM_WRONG_NUM_ARGS ();
e11e83f3 1107 axv = scm_make_string (scm_from_int (ndim), SCM_MAKE_CHAR (0));
02339e5b 1108 res = scm_i_make_ra (noutr, scm_tc16_enclosed_array);
0f2d19dd
JB
1109 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
1110 SCM_ARRAY_V (res) = ra_inr;
1111 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
1112 {
e11e83f3 1113 if (!scm_is_integer (SCM_CAR (axes)))
b3fcac34 1114 SCM_MISC_ERROR ("bad axis", SCM_EOL);
e11e83f3 1115 j = scm_to_int (SCM_CAR (axes));
0f2d19dd
JB
1116 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
1117 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
1118 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
cc95e00a 1119 scm_c_string_set_x (axv, j, SCM_MAKE_CHAR (1));
0f2d19dd 1120 }
cc95e00a 1121 c_axv = scm_i_string_chars (axv);
0f2d19dd
JB
1122 for (j = 0, k = 0; k < noutr; k++, j++)
1123 {
cc95e00a 1124 while (c_axv[j])
0f2d19dd
JB
1125 j++;
1126 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
1127 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
1128 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
1129 }
cc95e00a 1130 scm_remember_upto_here_1 (axv);
0f2d19dd
JB
1131 scm_ra_set_contp (ra_inr);
1132 scm_ra_set_contp (res);
1133 return res;
1134}
1bbd0b84 1135#undef FUNC_NAME
0f2d19dd
JB
1136
1137
1138
af45e3b0
DH
1139SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
1140 (SCM v, SCM args),
1e6808ea
MG
1141 "Return @code{#t} if its arguments would be acceptable to\n"
1142 "@code{array-ref}.")
1bbd0b84 1143#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 1144{
02339e5b 1145 SCM res = SCM_BOOL_T;
af45e3b0 1146
b3fcac34 1147 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd 1148
20930f28
MV
1149 if (scm_is_generalized_vector (v))
1150 {
02339e5b
MV
1151 long ind;
1152
1153 if (!scm_is_pair (args))
1154 SCM_WRONG_NUM_ARGS ();
1155 ind = scm_to_long (SCM_CAR (args));
1156 args = SCM_CDR (args);
1157 res = scm_from_bool (ind >= 0
1158 && ind < scm_c_generalized_vector_length (v));
20930f28 1159 }
02339e5b 1160 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
0f2d19dd 1161 {
02339e5b
MV
1162 size_t k = SCM_ARRAY_NDIM (v);
1163 scm_t_array_dim *s = SCM_ARRAY_DIMS (v);
1164
1165 while (k > 0)
0f2d19dd 1166 {
02339e5b 1167 long ind;
20930f28 1168
02339e5b
MV
1169 if (!scm_is_pair (args))
1170 SCM_WRONG_NUM_ARGS ();
1171 ind = scm_to_long (SCM_CAR (args));
1172 args = SCM_CDR (args);
1173 k -= 1;
1174
1175 if (ind < s->lbnd || ind > s->ubnd)
1176 {
1177 res = SCM_BOOL_F;
1178 /* We do not stop the checking after finding a violation
1179 since we want to validate the type-correctness and
1180 number of arguments in any case.
1181 */
1182 }
1183 }
0f2d19dd 1184 }
02339e5b
MV
1185 else
1186 scm_wrong_type_arg_msg (NULL, 0, v, "array");
20930f28 1187
02339e5b
MV
1188 if (!scm_is_null (args))
1189 SCM_WRONG_NUM_ARGS ();
1190
1191 return res;
0f2d19dd 1192}
1bbd0b84 1193#undef FUNC_NAME
0f2d19dd 1194
2d4d7f27 1195SCM
02339e5b
MV
1196scm_i_cvref (SCM v, size_t pos, int enclosed)
1197{
1198 if (enclosed)
1199 {
1200 int k = SCM_ARRAY_NDIM (v);
1201 SCM res = scm_make_ra (k);
1202 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1203 SCM_ARRAY_BASE (res) = pos;
1204 while (k--)
1205 {
1206 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1207 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1208 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1209 }
1210 return res;
1211 }
1212 else
1213 return scm_c_generalized_vector_ref (v, pos);
1214}
1215
1216SCM
1217scm_cvref (SCM v, unsigned long pos, SCM last)
1218{
1219 return scm_i_cvref (v, pos, 0);
1220}
0f2d19dd 1221
e0e49670 1222SCM_DEFINE (scm_array_ref, "array-ref", 1, 0, 1,
1bbd0b84 1223 (SCM v, SCM args),
1e6808ea
MG
1224 "Return the element at the @code{(index1, index2)} element in\n"
1225 "@var{array}.")
e0e49670 1226#define FUNC_NAME s_scm_array_ref
0f2d19dd 1227{
52372719
MV
1228 scm_t_array_handle handle;
1229 SCM res;
e0e49670 1230
52372719
MV
1231 scm_array_get_handle (v, &handle);
1232 res = scm_array_handle_ref (&handle, indices_to_pos (&handle, args));
1233 scm_array_handle_release (&handle);
1234 return res;
0f2d19dd 1235}
1bbd0b84 1236#undef FUNC_NAME
0f2d19dd 1237
0f2d19dd 1238
3b3b36dd 1239SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1240 (SCM v, SCM obj, SCM args),
8f85c0c6 1241 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1242 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1243#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1244{
52372719 1245 scm_t_array_handle handle;
b3fcac34 1246
52372719
MV
1247 scm_array_get_handle (v, &handle);
1248 scm_array_handle_set (&handle, indices_to_pos (&handle, args), obj);
1249 scm_array_handle_release (&handle);
02339e5b 1250 return SCM_UNSPECIFIED;
0f2d19dd 1251}
1bbd0b84 1252#undef FUNC_NAME
0f2d19dd 1253
1d7bdb25
GH
1254/* attempts to unroll an array into a one-dimensional array.
1255 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1256 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1257 wouldn't have contiguous elements. */
3b3b36dd 1258SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1259 (SCM ra, SCM strict),
b380b885
MD
1260 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1261 "without changing their order (last subscript changing fastest), then\n"
1262 "@code{array-contents} returns that shared array, otherwise it returns\n"
1263 "@code{#f}. All arrays made by @var{make-array} and\n"
1264 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1265 "@var{make-shared-array} may not be.\n\n"
1266 "If the optional argument @var{strict} is provided, a shared array will\n"
1267 "be returned only if its elements are stored internally contiguous in\n"
1268 "memory.")
1bbd0b84 1269#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1270{
1271 SCM sra;
e0e49670 1272
20930f28 1273 if (scm_is_generalized_vector (ra))
e0e49670
MV
1274 return ra;
1275
20930f28 1276 if (SCM_ARRAYP (ra))
0f2d19dd 1277 {
20930f28
MV
1278 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1279 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1280 return SCM_BOOL_F;
1281 for (k = 0; k < ndim; k++)
1282 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1283 if (!SCM_UNBNDP (strict))
74014c46 1284 {
20930f28
MV
1285 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1286 return SCM_BOOL_F;
1287 if (scm_is_bitvector (SCM_ARRAY_V (ra)))
1288 {
1289 if (len != scm_c_bitvector_length (SCM_ARRAY_V (ra)) ||
1290 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1291 len % SCM_LONG_BIT)
1292 return SCM_BOOL_F;
1293 }
74014c46 1294 }
20930f28
MV
1295
1296 {
1297 SCM v = SCM_ARRAY_V (ra);
1298 size_t length = scm_c_generalized_vector_length (v);
1299 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1300 return v;
0f2d19dd 1301 }
20930f28
MV
1302
1303 sra = scm_make_ra (1);
1304 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1305 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1306 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1307 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1308 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1309 return sra;
0f2d19dd 1310 }
02339e5b
MV
1311 else if (SCM_ENCLOSED_ARRAYP (ra))
1312 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
1313 else
1314 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1315}
1bbd0b84 1316#undef FUNC_NAME
0f2d19dd 1317
1cc91f1b 1318
0f2d19dd 1319SCM
6e8d25a6 1320scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1321{
1322 SCM ret;
c014a02e
ML
1323 long inc = 1;
1324 size_t k, len = 1;
0f2d19dd
JB
1325 for (k = SCM_ARRAY_NDIM (ra); k--;)
1326 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1327 k = SCM_ARRAY_NDIM (ra);
1328 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1329 {
20930f28 1330 if (!scm_is_bitvector (SCM_ARRAY_V (ra)))
0f2d19dd 1331 return ra;
20930f28 1332 if ((len == scm_c_bitvector_length (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1333 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1334 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1335 return ra;
1336 }
1337 ret = scm_make_ra (k);
1338 SCM_ARRAY_BASE (ret) = 0;
1339 while (k--)
1340 {
1341 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1342 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1343 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1344 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1345 }
f301dbf3 1346 SCM_ARRAY_V (ret) = make_typed_vector (scm_array_type (ra), inc);
0f2d19dd
JB
1347 if (copy)
1348 scm_array_copy_x (ra, ret);
1349 return ret;
1350}
1351
1352
1353
3b3b36dd 1354SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
03a5397a 1355 (SCM ura, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1356 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1357 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1358 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1359 "If an end of file is encountered,\n"
1360 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1361 "(starting at the beginning) and the remainder of the array is\n"
1362 "unchanged.\n\n"
1363 "The optional arguments @var{start} and @var{end} allow\n"
1364 "a specified region of a vector (or linearized array) to be read,\n"
1365 "leaving the remainder of the vector unchanged.\n\n"
1366 "@code{uniform-array-read!} returns the number of objects read.\n"
1367 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1368 "returned by @code{(current-input-port)}.")
1bbd0b84 1369#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1370{
3d8d56df
GH
1371 if (SCM_UNBNDP (port_or_fd))
1372 port_or_fd = scm_cur_inp;
35de7ebe 1373
03a5397a 1374 if (scm_is_uniform_vector (ura))
20930f28 1375 {
03a5397a 1376 return scm_uniform_vector_read_x (ura, port_or_fd, start, end);
20930f28 1377 }
03a5397a 1378 else if (SCM_ARRAYP (ura))
20930f28 1379 {
03a5397a
MV
1380 size_t base, vlen, cstart, cend;
1381 SCM cra, ans;
1382
1383 cra = scm_ra2contig (ura, 0);
1384 base = SCM_ARRAY_BASE (cra);
20930f28
MV
1385 vlen = SCM_ARRAY_DIMS (cra)->inc *
1386 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
35de7ebe 1387
03a5397a
MV
1388 cstart = 0;
1389 cend = vlen;
1390 if (!SCM_UNBNDP (start))
1146b6cd 1391 {
03a5397a
MV
1392 cstart = scm_to_unsigned_integer (start, 0, vlen);
1393 if (!SCM_UNBNDP (end))
1394 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1395 }
35de7ebe 1396
03a5397a
MV
1397 ans = scm_uniform_vector_read_x (SCM_ARRAY_V (cra), port_or_fd,
1398 scm_from_size_t (base + cstart),
1399 scm_from_size_t (base + cend));
6c951427 1400
03a5397a
MV
1401 if (!scm_is_eq (cra, ura))
1402 scm_array_copy_x (cra, ura);
1403 return ans;
3d8d56df 1404 }
02339e5b
MV
1405 else if (SCM_ENCLOSED_ARRAYP (ura))
1406 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1407 else
1408 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1409}
1bbd0b84 1410#undef FUNC_NAME
0f2d19dd 1411
3b3b36dd 1412SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
03a5397a 1413 (SCM ura, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1414 "Writes all elements of @var{ura} as binary objects to\n"
1415 "@var{port-or-fdes}.\n\n"
1416 "The optional arguments @var{start}\n"
1417 "and @var{end} allow\n"
1418 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1419 "The number of objects actually written is returned.\n"
b380b885
MD
1420 "@var{port-or-fdes} may be\n"
1421 "omitted, in which case it defaults to the value returned by\n"
1422 "@code{(current-output-port)}.")
1bbd0b84 1423#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1424{
3d8d56df
GH
1425 if (SCM_UNBNDP (port_or_fd))
1426 port_or_fd = scm_cur_outp;
20930f28 1427
03a5397a 1428 if (scm_is_uniform_vector (ura))
20930f28 1429 {
03a5397a 1430 return scm_uniform_vector_write (ura, port_or_fd, start, end);
20930f28 1431 }
03a5397a 1432 else if (SCM_ARRAYP (ura))
20930f28 1433 {
03a5397a
MV
1434 size_t base, vlen, cstart, cend;
1435 SCM cra, ans;
1436
1437 cra = scm_ra2contig (ura, 1);
1438 base = SCM_ARRAY_BASE (cra);
1439 vlen = SCM_ARRAY_DIMS (cra)->inc *
1440 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1146b6cd 1441
03a5397a
MV
1442 cstart = 0;
1443 cend = vlen;
1444 if (!SCM_UNBNDP (start))
1146b6cd 1445 {
03a5397a
MV
1446 cstart = scm_to_unsigned_integer (start, 0, vlen);
1447 if (!SCM_UNBNDP (end))
1448 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1449 }
3d8d56df 1450
03a5397a
MV
1451 ans = scm_uniform_vector_write (SCM_ARRAY_V (cra), port_or_fd,
1452 scm_from_size_t (base + cstart),
1453 scm_from_size_t (base + cend));
6c951427 1454
03a5397a 1455 return ans;
3d8d56df 1456 }
02339e5b
MV
1457 else if (SCM_ENCLOSED_ARRAYP (ura))
1458 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1459 else
1460 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1461}
1bbd0b84 1462#undef FUNC_NAME
0f2d19dd
JB
1463
1464
20930f28
MV
1465/** Bit vectors */
1466
1467static scm_t_bits scm_tc16_bitvector;
1468
1469#define IS_BITVECTOR(obj) SCM_SMOB_PREDICATE(scm_tc16_bitvector,(obj))
1470#define BITVECTOR_BITS(obj) ((scm_t_uint32 *)SCM_SMOB_DATA(obj))
1471#define BITVECTOR_LENGTH(obj) ((size_t)SCM_SMOB_DATA_2(obj))
1472
1473static size_t
1474bitvector_free (SCM vec)
1475{
1476 scm_gc_free (BITVECTOR_BITS (vec),
1477 sizeof (scm_t_uint32) * ((BITVECTOR_LENGTH (vec)+31)/32),
1478 "bitvector");
1479 return 0;
1480}
1481
1482static int
1483bitvector_print (SCM vec, SCM port, scm_print_state *pstate)
1484{
1485 size_t bit_len = BITVECTOR_LENGTH (vec);
1486 size_t word_len = (bit_len+31)/32;
1487 scm_t_uint32 *bits = BITVECTOR_BITS (vec);
1488 size_t i, j;
1489
1490 scm_puts ("#*", port);
1491 for (i = 0; i < word_len; i++, bit_len -= 32)
1492 {
1493 scm_t_uint32 mask = 1;
1494 for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
1495 scm_putc ((bits[i] & mask)? '1' : '0', port);
1496 }
1497
1498 return 1;
1499}
1500
1501static SCM
1502bitvector_equalp (SCM vec1, SCM vec2)
1503{
1504 size_t bit_len = BITVECTOR_LENGTH (vec1);
1505 size_t word_len = (bit_len + 31) / 32;
1506 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
1507 scm_t_uint32 *bits1 = BITVECTOR_BITS (vec1);
1508 scm_t_uint32 *bits2 = BITVECTOR_BITS (vec2);
1509
1510 /* compare lengths */
1511 if (BITVECTOR_LENGTH (vec2) != bit_len)
1512 return SCM_BOOL_F;
1513 /* avoid underflow in word_len-1 below. */
1514 if (bit_len == 0)
1515 return SCM_BOOL_T;
1516 /* compare full words */
1517 if (memcmp (bits1, bits2, sizeof (scm_t_uint32) * (word_len-1)))
1518 return SCM_BOOL_F;
1519 /* compare partial last words */
1520 if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
1521 return SCM_BOOL_F;
1522 return SCM_BOOL_T;
1523}
1524
1525int
1526scm_is_bitvector (SCM vec)
1527{
1528 return IS_BITVECTOR (vec);
1529}
1530
1531SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
1532 (SCM obj),
1533 "Return @code{#t} when @var{obj} is a bitvector, else\n"
1534 "return @code{#f}.")
1535#define FUNC_NAME s_scm_bitvector_p
1536{
1537 return scm_from_bool (scm_is_bitvector (obj));
1538}
1539#undef FUNC_NAME
1540
1541SCM
1542scm_c_make_bitvector (size_t len, SCM fill)
1543{
1544 size_t word_len = (len + 31) / 32;
1545 scm_t_uint32 *bits;
1546 SCM res;
1547
1548 bits = scm_gc_malloc (sizeof (scm_t_uint32) * word_len,
1549 "bitvector");
1550 SCM_NEWSMOB2 (res, scm_tc16_bitvector, bits, len);
1551
1552 if (!SCM_UNBNDP (fill))
1553 scm_bitvector_fill_x (res, fill);
1554
1555 return res;
1556}
1557
1558SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
1559 (SCM len, SCM fill),
1560 "Create a new bitvector of length @var{len} and\n"
1561 "optionally initialize all elements to @var{fill}.")
1562#define FUNC_NAME s_scm_make_bitvector
1563{
1564 return scm_c_make_bitvector (scm_to_size_t (len), fill);
1565}
1566#undef FUNC_NAME
1567
1568SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
1569 (SCM bits),
1570 "Create a new bitvector with the arguments as elements.")
1571#define FUNC_NAME s_scm_bitvector
1572{
1573 return scm_list_to_bitvector (bits);
1574}
1575#undef FUNC_NAME
1576
1577size_t
1578scm_c_bitvector_length (SCM vec)
1579{
1580 scm_assert_smob_type (scm_tc16_bitvector, vec);
1581 return BITVECTOR_LENGTH (vec);
1582}
1583
1584SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
1585 (SCM vec),
1586 "Return the length of the bitvector @var{vec}.")
1587#define FUNC_NAME s_scm_bitvector_length
1588{
1589 return scm_from_size_t (scm_c_bitvector_length (vec));
1590}
1591#undef FUNC_NAME
1592
21c487f1 1593const scm_t_uint32 *
f0b91039 1594scm_array_handle_bit_elements (scm_t_array_handle *h)
20930f28 1595{
f0b91039 1596 return scm_array_handle_bit_writable_elements (h);
20930f28
MV
1597}
1598
f0b91039
MV
1599scm_t_uint32 *
1600scm_array_handle_bit_writable_elements (scm_t_array_handle *h)
20930f28 1601{
f0b91039
MV
1602 SCM vec = h->array;
1603 if (SCM_ARRAYP (vec))
1604 vec = SCM_ARRAY_V (vec);
1605 if (IS_BITVECTOR (vec))
1606 return BITVECTOR_BITS (vec) + h->base/32;
1607 scm_wrong_type_arg_msg (NULL, 0, h->array, "bit array");
20930f28
MV
1608}
1609
f0b91039
MV
1610size_t
1611scm_array_handle_bit_elements_offset (scm_t_array_handle *h)
21c487f1 1612{
f0b91039 1613 return h->base % 32;
21c487f1
MV
1614}
1615
f0b91039
MV
1616const scm_t_uint32 *
1617scm_bitvector_elements (SCM vec,
1618 scm_t_array_handle *h,
1619 size_t *offp,
1620 size_t *lenp,
1621 ssize_t *incp)
21c487f1 1622{
f0b91039 1623 return scm_bitvector_writable_elements (vec, h, offp, lenp, incp);
21c487f1
MV
1624}
1625
f0b91039
MV
1626
1627scm_t_uint32 *
1628scm_bitvector_writable_elements (SCM vec,
1629 scm_t_array_handle *h,
1630 size_t *offp,
1631 size_t *lenp,
1632 ssize_t *incp)
21c487f1 1633{
cdd6e0a8 1634 scm_generalized_vector_get_handle (vec, h);
f0b91039
MV
1635 if (offp)
1636 {
1637 scm_t_array_dim *dim = scm_array_handle_dims (h);
1638 *offp = scm_array_handle_bit_elements_offset (h);
1639 *lenp = dim->ubnd - dim->lbnd + 1;
1640 *incp = dim->inc;
1641 }
1642 return scm_array_handle_bit_writable_elements (h);
21c487f1
MV
1643}
1644
20930f28
MV
1645SCM
1646scm_c_bitvector_ref (SCM vec, size_t idx)
1647{
f0b91039
MV
1648 scm_t_array_handle handle;
1649 const scm_t_uint32 *bits;
1650
1651 if (IS_BITVECTOR (vec))
20930f28 1652 {
f0b91039
MV
1653 if (idx >= BITVECTOR_LENGTH (vec))
1654 scm_out_of_range (NULL, scm_from_size_t (idx));
1655 bits = BITVECTOR_BITS(vec);
cdd6e0a8 1656 return scm_from_bool (bits[idx/32] & (1L << (idx%32)));
20930f28
MV
1657 }
1658 else
f0b91039 1659 {
cdd6e0a8 1660 SCM res;
f0b91039
MV
1661 size_t len, off;
1662 ssize_t inc;
1663
1664 bits = scm_bitvector_elements (vec, &handle, &off, &len, &inc);
1665 if (idx >= len)
1666 scm_out_of_range (NULL, scm_from_size_t (idx));
1667 idx = idx*inc + off;
cdd6e0a8
MV
1668 res = scm_from_bool (bits[idx/32] & (1L << (idx%32)));
1669 scm_array_handle_release (&handle);
1670 return res;
f0b91039 1671 }
20930f28
MV
1672}
1673
1674SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
1675 (SCM vec, SCM idx),
1676 "Return the element at index @var{idx} of the bitvector\n"
1677 "@var{vec}.")
1678#define FUNC_NAME s_scm_bitvector_ref
1679{
1680 return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
1681}
1682#undef FUNC_NAME
1683
1684void
1685scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
1686{
f0b91039
MV
1687 scm_t_array_handle handle;
1688 scm_t_uint32 *bits, mask;
1689
1690 if (IS_BITVECTOR (vec))
20930f28 1691 {
f0b91039
MV
1692 if (idx >= BITVECTOR_LENGTH (vec))
1693 scm_out_of_range (NULL, scm_from_size_t (idx));
1694 bits = BITVECTOR_BITS(vec);
20930f28
MV
1695 }
1696 else
f0b91039
MV
1697 {
1698 size_t len, off;
1699 ssize_t inc;
1700
1701 bits = scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
1702 if (idx >= len)
1703 scm_out_of_range (NULL, scm_from_size_t (idx));
1704 idx = idx*inc + off;
1705 }
1706
1707 mask = 1L << (idx%32);
1708 if (scm_is_true (val))
1709 bits[idx/32] |= mask;
1710 else
1711 bits[idx/32] &= ~mask;
cdd6e0a8
MV
1712
1713 if (!IS_BITVECTOR (vec))
1714 scm_array_handle_release (&handle);
20930f28
MV
1715}
1716
1717SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
1718 (SCM vec, SCM idx, SCM val),
1719 "Set the element at index @var{idx} of the bitvector\n"
1720 "@var{vec} when @var{val} is true, else clear it.")
1721#define FUNC_NAME s_scm_bitvector_set_x
1722{
1723 scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
1724 return SCM_UNSPECIFIED;
1725}
1726#undef FUNC_NAME
1727
1728SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
1729 (SCM vec, SCM val),
1730 "Set all elements of the bitvector\n"
1731 "@var{vec} when @var{val} is true, else clear them.")
1732#define FUNC_NAME s_scm_bitvector_fill_x
1733{
f0b91039
MV
1734 scm_t_array_handle handle;
1735 size_t off, len;
1736 ssize_t inc;
1737 scm_t_uint32 *bits;
1738
1739 bits = scm_bitvector_writable_elements (vec, &handle,
1740 &off, &len, &inc);
1741
1742 if (off == 0 && inc == 1 && len > 0)
1743 {
1744 /* the usual case
1745 */
1746 size_t word_len = (len + 31) / 32;
1747 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1748
1749 if (scm_is_true (val))
1750 {
1751 memset (bits, 0xFF, sizeof(scm_t_uint32)*(word_len-1));
1752 bits[word_len-1] |= last_mask;
1753 }
1754 else
1755 {
1756 memset (bits, 0x00, sizeof(scm_t_uint32)*(word_len-1));
1757 bits[word_len-1] &= ~last_mask;
1758 }
1759 }
1760 else
1761 {
1762 size_t i;
1763 for (i = 0; i < len; i++)
9598a406 1764 scm_array_handle_set (&handle, i*inc, val);
f0b91039
MV
1765 }
1766
cdd6e0a8
MV
1767 scm_array_handle_release (&handle);
1768
20930f28
MV
1769 return SCM_UNSPECIFIED;
1770}
1771#undef FUNC_NAME
1772
1773SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
1774 (SCM list),
1775 "Return a new bitvector initialized with the elements\n"
1776 "of @var{list}.")
1777#define FUNC_NAME s_scm_list_to_bitvector
1778{
1779 size_t bit_len = scm_to_size_t (scm_length (list));
1780 SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
1781 size_t word_len = (bit_len+31)/32;
f0b91039
MV
1782 scm_t_array_handle handle;
1783 scm_t_uint32 *bits = scm_bitvector_writable_elements (vec, &handle,
1784 NULL, NULL, NULL);
20930f28
MV
1785 size_t i, j;
1786
1787 for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
1788 {
1789 scm_t_uint32 mask = 1;
1790 bits[i] = 0;
1791 for (j = 0; j < 32 && j < bit_len;
1792 j++, mask <<= 1, list = SCM_CDR (list))
1793 if (scm_is_true (SCM_CAR (list)))
1794 bits[i] |= mask;
1795 }
f0b91039 1796
cdd6e0a8
MV
1797 scm_array_handle_release (&handle);
1798
20930f28
MV
1799 return vec;
1800}
1801#undef FUNC_NAME
1802
1803SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
1804 (SCM vec),
1805 "Return a new list initialized with the elements\n"
1806 "of the bitvector @var{vec}.")
1807#define FUNC_NAME s_scm_bitvector_to_list
1808{
f0b91039
MV
1809 scm_t_array_handle handle;
1810 size_t off, len;
1811 ssize_t inc;
1812 scm_t_uint32 *bits;
20930f28 1813 SCM res = SCM_EOL;
20930f28 1814
f0b91039
MV
1815 bits = scm_bitvector_writable_elements (vec, &handle,
1816 &off, &len, &inc);
1817
1818 if (off == 0 && inc == 1)
20930f28 1819 {
f0b91039
MV
1820 /* the usual case
1821 */
1822 size_t word_len = (len + 31) / 32;
1823 size_t i, j;
1824
1825 for (i = 0; i < word_len; i++, len -= 32)
1826 {
1827 scm_t_uint32 mask = 1;
1828 for (j = 0; j < 32 && j < len; j++, mask <<= 1)
1829 res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
1830 }
1831 }
1832 else
1833 {
1834 size_t i;
1835 for (i = 0; i < len; i++)
9598a406 1836 res = scm_cons (scm_array_handle_ref (&handle, i*inc), res);
20930f28 1837 }
cdd6e0a8
MV
1838
1839 scm_array_handle_release (&handle);
20930f28 1840
20930f28
MV
1841 return scm_reverse_x (res, SCM_EOL);
1842}
1843#undef FUNC_NAME
1844
1845/* From mmix-arith.w by Knuth.
1846
1847 Here's a fun way to count the number of bits in a tetrabyte.
1848
1849 [This classical trick is called the ``Gillies--Miller method for
1850 sideways addition'' in {\sl The Preparation of Programs for an
1851 Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
1852 edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
1853 the tricks used here were suggested by Balbir Singh, Peter
1854 Rossmanith, and Stefan Schwoon.]
1855*/
1856
1857static size_t
1858count_ones (scm_t_uint32 x)
1859{
1860 x=x-((x>>1)&0x55555555);
1861 x=(x&0x33333333)+((x>>2)&0x33333333);
1862 x=(x+(x>>4))&0x0f0f0f0f;
1863 x=x+(x>>8);
1864 return (x+(x>>16)) & 0xff;
1865}
0f2d19dd 1866
3b3b36dd 1867SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1868 (SCM b, SCM bitvector),
1e6808ea 1869 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1870 "@var{bitvector}.")
1bbd0b84 1871#define FUNC_NAME s_scm_bit_count
0f2d19dd 1872{
f0b91039
MV
1873 scm_t_array_handle handle;
1874 size_t off, len;
1875 ssize_t inc;
1876 scm_t_uint32 *bits;
20930f28 1877 int bit = scm_to_bool (b);
f0b91039 1878 size_t count = 0;
20930f28 1879
f0b91039
MV
1880 bits = scm_bitvector_writable_elements (bitvector, &handle,
1881 &off, &len, &inc);
20930f28 1882
f0b91039
MV
1883 if (off == 0 && inc == 1 && len > 0)
1884 {
1885 /* the usual case
1886 */
1887 size_t word_len = (len + 31) / 32;
1888 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1889 size_t i;
20930f28 1890
f0b91039
MV
1891 for (i = 0; i < word_len-1; i++)
1892 count += count_ones (bits[i]);
1893 count += count_ones (bits[i] & last_mask);
1894 }
1895 else
1896 {
1897 size_t i;
1898 for (i = 0; i < len; i++)
9598a406 1899 if (scm_is_true (scm_array_handle_ref (&handle, i*inc)))
f0b91039
MV
1900 count++;
1901 }
1902
cdd6e0a8
MV
1903 scm_array_handle_release (&handle);
1904
f0b91039 1905 return scm_from_size_t (bit? count : len-count);
0f2d19dd 1906}
1bbd0b84 1907#undef FUNC_NAME
0f2d19dd 1908
20930f28
MV
1909/* returns 32 for x == 0.
1910*/
1911static size_t
1912find_first_one (scm_t_uint32 x)
1913{
1914 size_t pos = 0;
1915 /* do a binary search in x. */
1916 if ((x & 0xFFFF) == 0)
1917 x >>= 16, pos += 16;
1918 if ((x & 0xFF) == 0)
1919 x >>= 8, pos += 8;
1920 if ((x & 0xF) == 0)
1921 x >>= 4, pos += 4;
1922 if ((x & 0x3) == 0)
1923 x >>= 2, pos += 2;
1924 if ((x & 0x1) == 0)
1925 pos += 1;
1926 return pos;
1927}
0f2d19dd 1928
3b3b36dd 1929SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1930 (SCM item, SCM v, SCM k),
88ecf5cb
KR
1931 "Return the index of the first occurrance of @var{item} in bit\n"
1932 "vector @var{v}, starting from @var{k}. If there is no\n"
1933 "@var{item} entry between @var{k} and the end of\n"
1934 "@var{bitvector}, then return @code{#f}. For example,\n"
1935 "\n"
1936 "@example\n"
1937 "(bit-position #t #*000101 0) @result{} 3\n"
1938 "(bit-position #f #*0001111 3) @result{} #f\n"
1939 "@end example")
1bbd0b84 1940#define FUNC_NAME s_scm_bit_position
0f2d19dd 1941{
f0b91039
MV
1942 scm_t_array_handle handle;
1943 size_t off, len, first_bit;
1944 ssize_t inc;
1945 const scm_t_uint32 *bits;
20930f28 1946 int bit = scm_to_bool (item);
20930f28 1947 SCM res = SCM_BOOL_F;
f0b91039
MV
1948
1949 bits = scm_bitvector_elements (v, &handle, &off, &len, &inc);
1950 first_bit = scm_to_unsigned_integer (k, 0, len);
20930f28 1951
f0b91039
MV
1952 if (off == 0 && inc == 1 && len > 0)
1953 {
1954 size_t i, word_len = (len + 31) / 32;
1955 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
1956 size_t first_word = first_bit / 32;
1957 scm_t_uint32 first_mask =
1958 ((scm_t_uint32)-1) << (first_bit - 32*first_word);
1959 scm_t_uint32 w;
1960
1961 for (i = first_word; i < word_len; i++)
1962 {
1963 w = (bit? bits[i] : ~bits[i]);
1964 if (i == first_word)
1965 w &= first_mask;
1966 if (i == word_len-1)
1967 w &= last_mask;
1968 if (w)
1969 {
1970 res = scm_from_size_t (32*i + find_first_one (w));
1971 break;
1972 }
1973 }
1974 }
1975 else
20930f28 1976 {
f0b91039
MV
1977 size_t i;
1978 for (i = first_bit; i < len; i++)
20930f28 1979 {
9598a406 1980 SCM elt = scm_array_handle_ref (&handle, i*inc);
f0b91039
MV
1981 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
1982 {
1983 res = scm_from_size_t (i);
1984 break;
1985 }
20930f28 1986 }
0f2d19dd 1987 }
20930f28 1988
cdd6e0a8
MV
1989 scm_array_handle_release (&handle);
1990
20930f28 1991 return res;
0f2d19dd 1992}
1bbd0b84 1993#undef FUNC_NAME
0f2d19dd 1994
3b3b36dd 1995SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761 1996 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1997 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1998 "selecting the entries to change. The return value is\n"
1999 "unspecified.\n"
2000 "\n"
2001 "If @var{kv} is a bit vector, then those entries where it has\n"
2002 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
2003 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
2004 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
2005 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
2006 "\n"
2007 "@example\n"
2008 "(define bv #*01000010)\n"
2009 "(bit-set*! bv #*10010001 #t)\n"
2010 "bv\n"
2011 "@result{} #*11010011\n"
2012 "@end example\n"
2013 "\n"
85368844
MV
2014 "If @var{kv} is a u32vector, then its elements are\n"
2015 "indices into @var{v} which are set to @var{obj}.\n"
88ecf5cb
KR
2016 "\n"
2017 "@example\n"
2018 "(define bv #*01000010)\n"
85368844 2019 "(bit-set*! bv #u32(5 2 7) #t)\n"
88ecf5cb
KR
2020 "bv\n"
2021 "@result{} #*01100111\n"
2022 "@end example")
1bbd0b84 2023#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 2024{
f0b91039
MV
2025 scm_t_array_handle v_handle;
2026 size_t v_off, v_len;
2027 ssize_t v_inc;
2028 scm_t_uint32 *v_bits;
2029 int bit;
2030
2031 /* Validate that OBJ is a boolean so this is done even if we don't
2032 need BIT.
2033 */
2034 bit = scm_to_bool (obj);
2035
2036 v_bits = scm_bitvector_writable_elements (v, &v_handle,
2037 &v_off, &v_len, &v_inc);
2038
20930f28
MV
2039 if (scm_is_bitvector (kv))
2040 {
f0b91039
MV
2041 scm_t_array_handle kv_handle;
2042 size_t kv_off, kv_len;
2043 ssize_t kv_inc;
2044 const scm_t_uint32 *kv_bits;
2045
2046 kv_bits = scm_bitvector_elements (v, &kv_handle,
2047 &kv_off, &kv_len, &kv_inc);
2048
2049 if (v_len != kv_len)
85368844
MV
2050 scm_misc_error (NULL,
2051 "bit vectors must have equal length",
2052 SCM_EOL);
2053
f0b91039
MV
2054 if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
2055 {
2056 size_t word_len = (kv_len + 31) / 32;
2057 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
2058 size_t i;
2059
2060 if (bit == 0)
2061 {
2062 for (i = 0; i < word_len-1; i++)
2063 v_bits[i] &= ~kv_bits[i];
2064 v_bits[i] &= ~(kv_bits[i] & last_mask);
2065 }
2066 else
2067 {
2068 for (i = 0; i < word_len-1; i++)
2069 v_bits[i] |= kv_bits[i];
2070 v_bits[i] |= kv_bits[i] & last_mask;
2071 }
2072 }
85368844 2073 else
f0b91039
MV
2074 {
2075 size_t i;
2076 for (i = 0; i < kv_len; i++)
9598a406
MV
2077 if (scm_is_true (scm_array_handle_ref (&kv_handle, i*kv_inc)))
2078 scm_array_handle_set (&v_handle, i*v_inc, obj);
f0b91039 2079 }
cdd6e0a8
MV
2080
2081 scm_array_handle_release (&kv_handle);
2082
85368844
MV
2083 }
2084 else if (scm_is_true (scm_u32vector_p (kv)))
2085 {
f0b91039
MV
2086 scm_t_array_handle kv_handle;
2087 size_t i, kv_len;
2088 ssize_t kv_inc;
2089 const scm_t_uint32 *kv_elts;
2090
2091 kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
2092 for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
9598a406 2093 scm_array_handle_set (&v_handle, (*kv_elts)*v_inc, obj);
cdd6e0a8
MV
2094
2095 scm_array_handle_release (&kv_handle);
0f2d19dd 2096 }
20930f28 2097 else
85368844
MV
2098 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
2099
cdd6e0a8
MV
2100 scm_array_handle_release (&v_handle);
2101
0f2d19dd
JB
2102 return SCM_UNSPECIFIED;
2103}
1bbd0b84 2104#undef FUNC_NAME
0f2d19dd
JB
2105
2106
3b3b36dd 2107SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 2108 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
2109 "Return a count of how many entries in bit vector @var{v} are\n"
2110 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
2111 "consider.\n"
2112 "\n"
2113 "If @var{kv} is a bit vector, then those entries where it has\n"
2114 "@code{#t} are the ones in @var{v} which are considered.\n"
2115 "@var{kv} and @var{v} must be the same length.\n"
2116 "\n"
85368844
MV
2117 "If @var{kv} is a u32vector, then it contains\n"
2118 "the indexes in @var{v} to consider.\n"
88ecf5cb
KR
2119 "\n"
2120 "For example,\n"
2121 "\n"
2122 "@example\n"
2123 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
85368844 2124 "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
88ecf5cb 2125 "@end example")
1bbd0b84 2126#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 2127{
f0b91039
MV
2128 scm_t_array_handle v_handle;
2129 size_t v_off, v_len;
2130 ssize_t v_inc;
2131 const scm_t_uint32 *v_bits;
2132 size_t count = 0;
2133 int bit;
2134
2135 /* Validate that OBJ is a boolean so this is done even if we don't
2136 need BIT.
2137 */
2138 bit = scm_to_bool (obj);
2139
2140 v_bits = scm_bitvector_elements (v, &v_handle,
2141 &v_off, &v_len, &v_inc);
2142
20930f28 2143 if (scm_is_bitvector (kv))
0f2d19dd 2144 {
f0b91039
MV
2145 scm_t_array_handle kv_handle;
2146 size_t kv_off, kv_len;
2147 ssize_t kv_inc;
2148 const scm_t_uint32 *kv_bits;
2149
2150 kv_bits = scm_bitvector_elements (v, &kv_handle,
2151 &kv_off, &kv_len, &kv_inc);
85368844 2152
f0b91039 2153 if (v_len != kv_len)
85368844
MV
2154 scm_misc_error (NULL,
2155 "bit vectors must have equal length",
2156 SCM_EOL);
2157
f0b91039
MV
2158 if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
2159 {
2160 size_t i, word_len = (kv_len + 31) / 32;
2161 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
2162 scm_t_uint32 xor_mask = bit? 0 : ((scm_t_uint32)-1);
2163
2164 for (i = 0; i < word_len-1; i++)
2165 count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i]);
2166 count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i] & last_mask);
2167 }
2168 else
2169 {
2170 size_t i;
2171 for (i = 0; i < kv_len; i++)
2172 if (scm_is_true (scm_array_handle_ref (&kv_handle, i)))
2173 {
9598a406 2174 SCM elt = scm_array_handle_ref (&v_handle, i*v_inc);
f0b91039
MV
2175 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
2176 count++;
2177 }
2178 }
cdd6e0a8
MV
2179
2180 scm_array_handle_release (&kv_handle);
2181
0f2d19dd 2182 }
85368844
MV
2183 else if (scm_is_true (scm_u32vector_p (kv)))
2184 {
f0b91039
MV
2185 scm_t_array_handle kv_handle;
2186 size_t i, kv_len;
2187 ssize_t kv_inc;
2188 const scm_t_uint32 *kv_elts;
d44ff083 2189
f0b91039
MV
2190 kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
2191 for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
2192 {
9598a406 2193 SCM elt = scm_array_handle_ref (&v_handle, (*kv_elts)*v_inc);
f0b91039
MV
2194 if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
2195 count++;
2196 }
cdd6e0a8
MV
2197
2198 scm_array_handle_release (&kv_handle);
85368844 2199 }
20930f28 2200 else
85368844 2201 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
f0b91039 2202
cdd6e0a8
MV
2203 scm_array_handle_release (&v_handle);
2204
f0b91039 2205 return scm_from_size_t (count);
0f2d19dd 2206}
1bbd0b84 2207#undef FUNC_NAME
0f2d19dd 2208
3b3b36dd 2209SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2210 (SCM v),
88ecf5cb
KR
2211 "Modify the bit vector @var{v} by replacing each element with\n"
2212 "its negation.")
1bbd0b84 2213#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2214{
f0b91039
MV
2215 scm_t_array_handle handle;
2216 size_t off, len;
2217 ssize_t inc;
2218 scm_t_uint32 *bits;
74014c46 2219
f0b91039
MV
2220 bits = scm_bitvector_writable_elements (v, &handle, &off, &len, &inc);
2221
2222 if (off == 0 && inc == 1 && len > 0)
2223 {
2224 size_t word_len = (len + 31) / 32;
2225 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
2226 size_t i;
2227
2228 for (i = 0; i < word_len-1; i++)
2229 bits[i] = ~bits[i];
2230 bits[i] = bits[i] ^ last_mask;
2231 }
2232 else
2233 {
2234 size_t i;
2235 for (i = 0; i < len; i++)
9598a406
MV
2236 scm_array_handle_set (&handle, i*inc,
2237 scm_not (scm_array_handle_ref (&handle, i*inc)));
f0b91039 2238 }
74014c46 2239
cdd6e0a8
MV
2240 scm_array_handle_release (&handle);
2241
0f2d19dd
JB
2242 return SCM_UNSPECIFIED;
2243}
1bbd0b84 2244#undef FUNC_NAME
0f2d19dd
JB
2245
2246
0f2d19dd 2247SCM
cc95e00a 2248scm_istr2bve (SCM str)
0f2d19dd 2249{
f0b91039 2250 scm_t_array_handle handle;
cc95e00a 2251 size_t len = scm_i_string_length (str);
20930f28
MV
2252 SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
2253 SCM res = vec;
2254
2255 scm_t_uint32 mask;
2256 size_t k, j;
f0b91039
MV
2257 const char *c_str;
2258 scm_t_uint32 *data;
2259
2260 data = scm_bitvector_writable_elements (vec, &handle, NULL, NULL, NULL);
2261 c_str = scm_i_string_chars (str);
cc95e00a 2262
20930f28 2263 for (k = 0; k < (len + 31) / 32; k++)
0f2d19dd
JB
2264 {
2265 data[k] = 0L;
20930f28
MV
2266 j = len - k * 32;
2267 if (j > 32)
2268 j = 32;
0f2d19dd 2269 for (mask = 1L; j--; mask <<= 1)
cc95e00a 2270 switch (*c_str++)
0f2d19dd
JB
2271 {
2272 case '0':
2273 break;
2274 case '1':
2275 data[k] |= mask;
2276 break;
2277 default:
20930f28
MV
2278 res = SCM_BOOL_F;
2279 goto exit;
0f2d19dd
JB
2280 }
2281 }
20930f28
MV
2282
2283 exit:
cdd6e0a8 2284 scm_array_handle_release (&handle);
20930f28 2285 scm_remember_upto_here_1 (str);
20930f28 2286 return res;
0f2d19dd
JB
2287}
2288
2289
1cc91f1b 2290
0f2d19dd 2291static SCM
34d19ef6 2292ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2293{
02339e5b 2294 SCM res = SCM_EOL;
5f37cb63 2295 long inc;
02339e5b
MV
2296 size_t i;
2297 int enclosed = SCM_ENCLOSED_ARRAYP (ra);
2298
5f37cb63
MV
2299 if (k == SCM_ARRAY_NDIM (ra))
2300 return scm_i_cvref (SCM_ARRAY_V (ra), base, enclosed);
2301
2302 inc = SCM_ARRAY_DIMS (ra)[k].inc;
0f2d19dd
JB
2303 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2304 return SCM_EOL;
2305 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
5f37cb63 2306 do
0f2d19dd 2307 {
5f37cb63
MV
2308 i -= inc;
2309 res = scm_cons (ra2l (ra, i, k + 1), res);
0f2d19dd 2310 }
5f37cb63 2311 while (i != base);
0f2d19dd
JB
2312 return res;
2313}
2314
2315
cd328b4f 2316SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2317 (SCM v),
1e6808ea
MG
2318 "Return a list consisting of all the elements, in order, of\n"
2319 "@var{array}.")
cd328b4f 2320#define FUNC_NAME s_scm_array_to_list
0f2d19dd 2321{
20930f28
MV
2322 if (scm_is_generalized_vector (v))
2323 return scm_generalized_vector_to_list (v);
02339e5b 2324 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
20930f28 2325 return ra2l (v, SCM_ARRAY_BASE (v), 0);
e0e49670 2326
20930f28 2327 scm_wrong_type_arg_msg (NULL, 0, v, "array");
0f2d19dd 2328}
1bbd0b84 2329#undef FUNC_NAME
0f2d19dd
JB
2330
2331
bcbbea0e 2332static void l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k);
1cc91f1b 2333
f301dbf3
MV
2334SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
2335 (SCM type, SCM ndim, SCM lst),
2336 "Return an array of the type @var{type}\n"
2337 "with elements the same as those of @var{lst}.\n"
bfad4005
MV
2338 "\n"
2339 "The argument @var{ndim} determines the number of dimensions\n"
2340 "of the array. It is either an exact integer, giving the\n"
20930f28 2341 "number directly, or a list of exact integers, whose length\n"
bfad4005
MV
2342 "specifies the number of dimensions and each element is the\n"
2343 "lower index bound of its dimension.")
f301dbf3 2344#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 2345{
bfad4005 2346 SCM shape, row;
0f2d19dd 2347 SCM ra;
bcbbea0e 2348 scm_t_array_handle handle;
bfad4005
MV
2349
2350 shape = SCM_EOL;
2351 row = lst;
2352 if (scm_is_integer (ndim))
0f2d19dd 2353 {
bfad4005
MV
2354 size_t k = scm_to_size_t (ndim);
2355 while (k-- > 0)
2356 {
2357 shape = scm_cons (scm_length (row), shape);
2358 if (k > 0)
2359 row = scm_car (row);
2360 }
2361 }
2362 else
2363 {
2364 while (1)
2365 {
2366 shape = scm_cons (scm_list_2 (scm_car (ndim),
2367 scm_sum (scm_sum (scm_car (ndim),
2368 scm_length (row)),
2369 scm_from_int (-1))),
2370 shape);
2371 ndim = scm_cdr (ndim);
2372 if (scm_is_pair (ndim))
2373 row = scm_car (row);
2374 else
2375 break;
2376 }
0f2d19dd 2377 }
bfad4005 2378
f0b91039
MV
2379 ra = scm_make_typed_array (type, SCM_UNSPECIFIED,
2380 scm_reverse_x (shape, SCM_EOL));
20930f28 2381
bcbbea0e
MV
2382 scm_array_get_handle (ra, &handle);
2383 l2ra (lst, &handle, 0, 0);
2384 scm_array_handle_release (&handle);
2385
2386 return ra;
0f2d19dd 2387}
1bbd0b84 2388#undef FUNC_NAME
0f2d19dd 2389
f301dbf3
MV
2390SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
2391 (SCM ndim, SCM lst),
2392 "Return an array with elements the same as those of @var{lst}.")
2393#define FUNC_NAME s_scm_list_to_array
2394{
2395 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
2396}
2397#undef FUNC_NAME
2398
bcbbea0e
MV
2399static void
2400l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
0f2d19dd 2401{
bcbbea0e
MV
2402 if (k == scm_array_handle_rank (handle))
2403 scm_array_handle_set (handle, pos, lst);
0f2d19dd
JB
2404 else
2405 {
bcbbea0e
MV
2406 scm_t_array_dim *dim = scm_array_handle_dims (handle) + k;
2407 ssize_t inc = dim->inc;
2408 size_t n = 1 + dim->ubnd - dim->lbnd;
2409
2410 while (n > 0 && scm_is_pair (lst))
0f2d19dd 2411 {
bcbbea0e
MV
2412 l2ra (SCM_CAR (lst), handle, pos, k + 1);
2413 pos += inc;
0f2d19dd 2414 lst = SCM_CDR (lst);
bcbbea0e 2415 n -= 1;
0f2d19dd 2416 }
bcbbea0e
MV
2417 if (n != 0)
2418 scm_misc_error (NULL, "too few elements for array dimension ~a",
2419 scm_list_1 (scm_from_ulong (k)));
d2e53ed6 2420 if (!scm_is_null (lst))
bcbbea0e
MV
2421 scm_misc_error (NULL, "too many elements for array dimension ~a",
2422 scm_list_1 (scm_from_ulong (k)));
0f2d19dd 2423 }
0f2d19dd
JB
2424}
2425
f301dbf3
MV
2426#if SCM_ENABLE_DEPRECATED
2427
2428SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
2429 (SCM ndim, SCM prot, SCM lst),
2430 "Return a uniform array of the type indicated by prototype\n"
2431 "@var{prot} with elements the same as those of @var{lst}.\n"
2432 "Elements must be of the appropriate type, no coercions are\n"
2433 "done.\n"
2434 "\n"
2435 "The argument @var{ndim} determines the number of dimensions\n"
2436 "of the array. It is either an exact integer, giving the\n"
2437 "number directly, or a list of exact integers, whose length\n"
2438 "specifies the number of dimensions and each element is the\n"
2439 "lower index bound of its dimension.")
2440#define FUNC_NAME s_scm_list_to_uniform_array
2441{
2442 return scm_list_to_typed_array (prototype_to_type (prot), ndim, lst);
2443}
2444#undef FUNC_NAME
2445
2446#endif
1cc91f1b 2447
e0e49670
MV
2448/* Print dimension DIM of ARRAY.
2449 */
0f2d19dd 2450
e0e49670 2451static int
02339e5b 2452scm_i_print_array_dimension (SCM array, int dim, int base, int enclosed,
e0e49670
MV
2453 SCM port, scm_print_state *pstate)
2454{
2455 scm_t_array_dim *dim_spec = SCM_ARRAY_DIMS (array) + dim;
2456 long idx;
2457
2458 scm_putc ('(', port);
2459
e0e49670
MV
2460 for (idx = dim_spec->lbnd; idx <= dim_spec->ubnd; idx++)
2461 {
2462 if (dim < SCM_ARRAY_NDIM(array)-1)
02339e5b
MV
2463 scm_i_print_array_dimension (array, dim+1, base, enclosed,
2464 port, pstate);
e0e49670 2465 else
02339e5b 2466 scm_iprin1 (scm_i_cvref (SCM_ARRAY_V (array), base, enclosed),
e0e49670
MV
2467 port, pstate);
2468 if (idx < dim_spec->ubnd)
2469 scm_putc (' ', port);
2470 base += dim_spec->inc;
2471 }
2472
2473 scm_putc (')', port);
2474 return 1;
2475}
2476
f301dbf3 2477/* Print an array. (Only for strict arrays, not for generalized vectors.)
e0e49670
MV
2478*/
2479
e0e49670
MV
2480static int
2481scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
2482{
2483 long ndim = SCM_ARRAY_NDIM (array);
2484 scm_t_array_dim *dim_specs = SCM_ARRAY_DIMS (array);
20930f28 2485 SCM v = SCM_ARRAY_V (array);
e0e49670
MV
2486 unsigned long base = SCM_ARRAY_BASE (array);
2487 long i;
2488
2489 scm_putc ('#', port);
c0fc64c8 2490 if (ndim != 1 || dim_specs[0].lbnd != 0)
e0e49670 2491 scm_intprint (ndim, 10, port);
20930f28
MV
2492 if (scm_is_uniform_vector (v))
2493 scm_puts (scm_i_uniform_vector_tag (v), port);
2494 else if (scm_is_bitvector (v))
2495 scm_puts ("b", port);
2496 else if (scm_is_string (v))
2497 scm_puts ("a", port);
2498 else if (!scm_is_vector (v))
2499 scm_puts ("?", port);
2500
e0e49670
MV
2501 for (i = 0; i < ndim; i++)
2502 if (dim_specs[i].lbnd != 0)
2503 {
2504 for (i = 0; i < ndim; i++)
2505 {
2506 scm_putc ('@', port);
2507 scm_uintprint (dim_specs[i].lbnd, 10, port);
2508 }
2509 break;
2510 }
2511
5f37cb63
MV
2512 if (ndim == 0)
2513 {
2514 /* Rank zero arrays, which are really just scalars, are printed
2515 specially. The consequent way would be to print them as
2516
2517 #0 OBJ
2518
2519 where OBJ is the printed representation of the scalar, but we
2520 print them instead as
2521
2522 #0(OBJ)
2523
2524 to make them look less strange.
2525
2526 Just printing them as
2527
2528 OBJ
2529
2530 would be correct in a way as well, but zero rank arrays are
2531 not really the same as Scheme values since they are boxed and
2532 can be modified with array-set!, say.
2533 */
2534 scm_putc ('(', port);
2535 scm_iprin1 (scm_i_cvref (v, base, 0), port, pstate);
2536 scm_putc (')', port);
2537 return 1;
2538 }
2539 else
2540 return scm_i_print_array_dimension (array, 0, base, 0, port, pstate);
02339e5b
MV
2541}
2542
2543static int
2544scm_i_print_enclosed_array (SCM array, SCM port, scm_print_state *pstate)
2545{
2546 size_t base;
2547
2548 scm_putc ('#', port);
2549 base = SCM_ARRAY_BASE (array);
2550 scm_puts ("<enclosed-array ", port);
2551 scm_i_print_array_dimension (array, 0, base, 1, port, pstate);
2552 scm_putc ('>', port);
2553 return 1;
e0e49670 2554}
1cc91f1b 2555
bfad4005
MV
2556/* Read an array. This function can also read vectors and uniform
2557 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2558 handled here.
2559
2560 C is the first character read after the '#'.
2561*/
2562
bfad4005 2563static SCM
f301dbf3 2564tag_to_type (const char *tag, SCM port)
bfad4005 2565{
bfad4005
MV
2566#if SCM_ENABLE_DEPRECATED
2567 {
f301dbf3 2568 /* Recognize the old syntax.
bfad4005 2569 */
bfad4005
MV
2570 const char *instead;
2571 switch (tag[0])
2572 {
bfad4005 2573 case 'u':
bfad4005
MV
2574 instead = "u32";
2575 break;
2576 case 'e':
bfad4005
MV
2577 instead = "s32";
2578 break;
2579 case 's':
bfad4005
MV
2580 instead = "f32";
2581 break;
2582 case 'i':
bfad4005
MV
2583 instead = "f64";
2584 break;
2585 case 'y':
bfad4005
MV
2586 instead = "s8";
2587 break;
2588 case 'h':
bfad4005
MV
2589 instead = "s16";
2590 break;
2591 case 'l':
bfad4005
MV
2592 instead = "s64";
2593 break;
2594 case 'c':
72d05aa4
MV
2595 instead = "c64";
2596 break;
2597 default:
f301dbf3 2598 instead = NULL;
bfad4005
MV
2599 break;
2600 }
f301dbf3
MV
2601
2602 if (instead && tag[1] == '\0')
bfad4005
MV
2603 {
2604 scm_c_issue_deprecation_warning_fmt
2605 ("The tag '%c' is deprecated for uniform vectors. "
2606 "Use '%s' instead.", tag[0], instead);
f301dbf3 2607 return scm_from_locale_symbol (instead);
bfad4005
MV
2608 }
2609 }
2610#endif
5f37cb63
MV
2611
2612 if (*tag == '\0')
2613 return SCM_BOOL_T;
2614 else
2615 return scm_from_locale_symbol (tag);
bfad4005
MV
2616}
2617
2618SCM
2619scm_i_read_array (SCM port, int c)
2620{
2621 size_t rank;
2622 int got_rank;
2623 char tag[80];
2624 int tag_len;
2625
5f37cb63 2626 SCM lower_bounds = SCM_BOOL_F, elements;
bfad4005
MV
2627
2628 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2629 the array code can not deal with zero-length dimensions yet, and
2630 we want to allow zero-length vectors, of course.
2631 */
2632 if (c == '(')
2633 {
2634 scm_ungetc (c, port);
2635 return scm_vector (scm_read (port));
2636 }
2637
2638 /* Disambiguate between '#f' and uniform floating point vectors.
2639 */
2640 if (c == 'f')
2641 {
2642 c = scm_getc (port);
2643 if (c != '3' && c != '6')
2644 {
2645 if (c != EOF)
2646 scm_ungetc (c, port);
2647 return SCM_BOOL_F;
2648 }
2649 rank = 1;
2650 got_rank = 1;
2651 tag[0] = 'f';
2652 tag_len = 1;
2653 goto continue_reading_tag;
2654 }
2655
5f37cb63 2656 /* Read rank. */
bfad4005
MV
2657 rank = 0;
2658 got_rank = 0;
2659 while ('0' <= c && c <= '9')
2660 {
2661 rank = 10*rank + c-'0';
2662 got_rank = 1;
2663 c = scm_getc (port);
2664 }
2665 if (!got_rank)
2666 rank = 1;
bfad4005
MV
2667
2668 /* Read tag. */
2669 tag_len = 0;
2670 continue_reading_tag:
2671 while (c != EOF && c != '(' && c != '@' && tag_len < 80)
2672 {
2673 tag[tag_len++] = c;
2674 c = scm_getc (port);
2675 }
2676 tag[tag_len] = '\0';
2677
2678 /* Read lower bounds. */
5f37cb63 2679 if (c == '@')
bfad4005 2680 {
5f37cb63
MV
2681 lower_bounds = SCM_EOL;
2682
2683 do
bfad4005 2684 {
5f37cb63
MV
2685 /* Yeah, right, we should use some ready-made integer parsing
2686 routine for this...
2687 */
2688
2689 long lbnd = 0;
2690 long sign = 1;
2691
bfad4005 2692 c = scm_getc (port);
5f37cb63
MV
2693 if (c == '-')
2694 {
2695 sign = -1;
2696 c = scm_getc (port);
2697 }
2698 while ('0' <= c && c <= '9')
2699 {
2700 lbnd = 10*lbnd + c-'0';
2701 c = scm_getc (port);
2702 }
2703 lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
2704 } while (c == '@');
bfad4005
MV
2705 }
2706
2707 /* Read nested lists of elements.
2708 */
2709 if (c != '(')
2710 scm_i_input_error (NULL, port,
2711 "missing '(' in vector or array literal",
2712 SCM_EOL);
2713 scm_ungetc (c, port);
2714 elements = scm_read (port);
2715
5f37cb63 2716 if (scm_is_false (lower_bounds))
bfad4005
MV
2717 lower_bounds = scm_from_size_t (rank);
2718 else if (scm_ilength (lower_bounds) != rank)
2719 scm_i_input_error (NULL, port,
2720 "the number of lower bounds must match the array rank",
2721 SCM_EOL);
2722
5f37cb63
MV
2723 /* Handle special print syntax of rank zero arrays; see
2724 scm_i_print_array for a rationale.
2725 */
2726 if (rank == 0)
2727 elements = scm_car (elements);
2728
2729 /* Construct array.
2730 */
f301dbf3
MV
2731 return scm_list_to_typed_array (tag_to_type (tag, port),
2732 lower_bounds,
2733 elements);
bfad4005
MV
2734}
2735
0f2d19dd 2736int
1bbd0b84 2737scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 2738{
02339e5b 2739 scm_iprin1 (exp, port, pstate);
0f2d19dd
JB
2740 return 1;
2741}
2742
f301dbf3 2743SCM_DEFINE (scm_array_type, "array-type", 1, 0, 0,
ab1be174 2744 (SCM ra),
f301dbf3
MV
2745 "")
2746#define FUNC_NAME s_scm_array_type
ab1be174 2747{
ab1be174 2748 if (SCM_ARRAYP (ra))
f301dbf3 2749 return scm_i_generalized_vector_type (SCM_ARRAY_V (ra));
02339e5b 2750 else if (scm_is_generalized_vector (ra))
f301dbf3 2751 return scm_i_generalized_vector_type (ra);
02339e5b
MV
2752 else if (SCM_ENCLOSED_ARRAYP (ra))
2753 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
ab1be174 2754 else
02339e5b 2755 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
ab1be174
MV
2756}
2757#undef FUNC_NAME
2758
72d05aa4
MV
2759#if SCM_ENABLE_DEPRECATED
2760
3b3b36dd 2761SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2762 (SCM ra),
1e6808ea
MG
2763 "Return an object that would produce an array of the same type\n"
2764 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2765 "@code{make-uniform-array}.")
1bbd0b84 2766#define FUNC_NAME s_scm_array_prototype
0f2d19dd 2767{
20930f28 2768 if (SCM_ARRAYP (ra))
02339e5b 2769 return scm_i_get_old_prototype (SCM_ARRAY_V (ra));
20930f28
MV
2770 else if (scm_is_generalized_vector (ra))
2771 return scm_i_get_old_prototype (ra);
02339e5b
MV
2772 else if (SCM_ENCLOSED_ARRAYP (ra))
2773 return SCM_UNSPECIFIED;
20930f28
MV
2774 else
2775 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 2776}
1bbd0b84 2777#undef FUNC_NAME
0f2d19dd 2778
72d05aa4 2779#endif
1cc91f1b 2780
0f2d19dd 2781static SCM
e841c3e0 2782array_mark (SCM ptr)
0f2d19dd 2783{
0f2d19dd
JB
2784 return SCM_ARRAY_V (ptr);
2785}
2786
1be6b49c 2787static size_t
e841c3e0 2788array_free (SCM ptr)
0f2d19dd 2789{
4c9419ac
MV
2790 scm_gc_free (SCM_ARRAY_MEM (ptr),
2791 (sizeof (scm_t_array)
2792 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2793 "array");
2794 return 0;
0f2d19dd
JB
2795}
2796
0f2d19dd
JB
2797void
2798scm_init_unif ()
0f2d19dd 2799{
e841c3e0
KN
2800 scm_tc16_array = scm_make_smob_type ("array", 0);
2801 scm_set_smob_mark (scm_tc16_array, array_mark);
2802 scm_set_smob_free (scm_tc16_array, array_free);
02339e5b 2803 scm_set_smob_print (scm_tc16_array, scm_i_print_array);
e841c3e0 2804 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
02339e5b
MV
2805
2806 scm_tc16_enclosed_array = scm_make_smob_type ("enclosed-array", 0);
2807 scm_set_smob_mark (scm_tc16_enclosed_array, array_mark);
2808 scm_set_smob_free (scm_tc16_enclosed_array, array_free);
2809 scm_set_smob_print (scm_tc16_enclosed_array, scm_i_print_enclosed_array);
2810 scm_set_smob_equalp (scm_tc16_enclosed_array, scm_array_equal_p);
2811
0f2d19dd 2812 scm_add_feature ("array");
20930f28
MV
2813
2814 scm_tc16_bitvector = scm_make_smob_type ("bitvector", 0);
2815 scm_set_smob_free (scm_tc16_bitvector, bitvector_free);
2816 scm_set_smob_print (scm_tc16_bitvector, bitvector_print);
2817 scm_set_smob_equalp (scm_tc16_bitvector, bitvector_equalp);
2818
f301dbf3
MV
2819 init_type_creator_table ();
2820
a0599745 2821#include "libguile/unif.x"
bfad4005 2822
0f2d19dd 2823}
89e00824
ML
2824
2825/*
2826 Local Variables:
2827 c-file-style: "gnu"
2828 End:
2829*/