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