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