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