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