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