* gen-scmconfig.h.in (SCM_I_GSC_HAVE_ARRAYS): Removed.
[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
0f2d19dd 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
MV
255
256#if SCM_ENABLE_DEPRECATED
f301dbf3
MV
257
258SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
259 (SCM obj, SCM prot),
260 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
261 "not.")
262#define FUNC_NAME s_scm_array_p
263{
264 if (!SCM_UNBNDP (prot))
265 {
266 scm_c_issue_deprecation_warning
267 ("Using prototypes with `array?' is deprecated."
268 " Use `typed-array?' instead.");
269
270 return scm_typed_array_p (obj, prototype_to_type (prot));
271 }
272 else
273 return scm_from_bool (scm_is_array (obj));
274}
275#undef FUNC_NAME
276
277#else /* !SCM_ENABLE_DEPRECATED */
278
279/* We keep the old 2-argument C prototype for a while although the old
280 PROT argument is always ignored now. C code should probably use
281 scm_is_array or scm_is_typed_array anyway.
282*/
283
284SCM_DEFINE (scm_array_p, "array?", 1, 0, 0,
285 (SCM obj, SCM unused),
286 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
287 "not.")
288#define FUNC_NAME s_scm_array_p
289{
290 return scm_from_bool (scm_is_array (obj));
291}
292#undef FUNC_NAME
293
294#endif /* !SCM_ENABLE_DEPRECATED */
295
296
297SCM_DEFINE (scm_typed_array_p, "typed-array?", 2, 0, 0,
298 (SCM obj, SCM type),
299 "Return @code{#t} if the @var{obj} is an array of type\n"
300 "@var{type}, and @code{#f} if not.")
301#define FUNC_NAME s_scm_typed_array_p
302{
303 return scm_from_bool (scm_is_typed_array (obj, type));
0f2d19dd 304}
1bbd0b84 305#undef FUNC_NAME
0f2d19dd
JB
306
307
3b3b36dd 308SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
02339e5b
MV
309 (SCM array),
310 "Return the number of dimensions of the array @var{array.}\n")
1bbd0b84 311#define FUNC_NAME s_scm_array_rank
0f2d19dd 312{
02339e5b 313 if (scm_is_generalized_vector (array))
e0e49670
MV
314 return scm_from_int (1);
315
02339e5b
MV
316 if (SCM_ARRAYP (array) || SCM_ENCLOSED_ARRAYP (array))
317 return scm_from_size_t (SCM_ARRAY_NDIM (array));
20930f28 318
02339e5b 319 scm_wrong_type_arg_msg (NULL, 0, array, "array");
0f2d19dd 320}
1bbd0b84 321#undef FUNC_NAME
0f2d19dd
JB
322
323
3b3b36dd 324SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 325 (SCM ra),
02339e5b 326 "@code{array-dimensions} is similar to @code{array-shape} but replaces\n"
b380b885 327 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
1e6808ea 328 "@lisp\n"
b380b885 329 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
1e6808ea 330 "@end lisp")
1bbd0b84 331#define FUNC_NAME s_scm_array_dimensions
0f2d19dd 332{
20930f28 333 if (scm_is_generalized_vector (ra))
f301dbf3 334 return scm_list_1 (scm_generalized_vector_length (ra));
e0e49670 335
02339e5b 336 if (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra))
0f2d19dd 337 {
20930f28
MV
338 SCM res = SCM_EOL;
339 size_t k;
340 scm_t_array_dim *s;
341
0f2d19dd
JB
342 k = SCM_ARRAY_NDIM (ra);
343 s = SCM_ARRAY_DIMS (ra);
344 while (k--)
e2d37336 345 res = scm_cons (s[k].lbnd
e11e83f3
MV
346 ? scm_cons2 (scm_from_long (s[k].lbnd),
347 scm_from_long (s[k].ubnd),
e2d37336 348 SCM_EOL)
e11e83f3 349 : scm_from_long (1 + s[k].ubnd),
e2d37336 350 res);
0f2d19dd
JB
351 return res;
352 }
20930f28
MV
353
354 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 355}
1bbd0b84 356#undef FUNC_NAME
0f2d19dd
JB
357
358
e2d37336
MD
359SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
360 (SCM ra),
361 "Return the root vector of a shared array.")
362#define FUNC_NAME s_scm_shared_array_root
363{
02339e5b
MV
364 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
365 SCM_ARG1, FUNC_NAME);
e2d37336
MD
366 return SCM_ARRAY_V (ra);
367}
368#undef FUNC_NAME
369
370
371SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
372 (SCM ra),
373 "Return the root vector index of the first element in the array.")
374#define FUNC_NAME s_scm_shared_array_offset
375{
02339e5b
MV
376 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
377 SCM_ARG1, FUNC_NAME);
e11e83f3 378 return scm_from_int (SCM_ARRAY_BASE (ra));
e2d37336
MD
379}
380#undef FUNC_NAME
381
382
383SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
384 (SCM ra),
385 "For each dimension, return the distance between elements in the root vector.")
386#define FUNC_NAME s_scm_shared_array_increments
387{
388 SCM res = SCM_EOL;
1be6b49c 389 size_t k;
92c2555f 390 scm_t_array_dim *s;
02339e5b
MV
391
392 SCM_ASSERT (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra), ra,
393 SCM_ARG1, FUNC_NAME);
e2d37336
MD
394 k = SCM_ARRAY_NDIM (ra);
395 s = SCM_ARRAY_DIMS (ra);
396 while (k--)
e11e83f3 397 res = scm_cons (scm_from_long (s[k].inc), res);
e2d37336
MD
398 return res;
399}
400#undef FUNC_NAME
401
402
0f2d19dd
JB
403static char s_bad_ind[] = "Bad scm_array index";
404
1cc91f1b 405
c014a02e 406long
1bbd0b84 407scm_aind (SCM ra, SCM args, const char *what)
0f2d19dd
JB
408{
409 SCM ind;
c014a02e
ML
410 register long j;
411 register unsigned long pos = SCM_ARRAY_BASE (ra);
412 register unsigned long k = SCM_ARRAY_NDIM (ra);
92c2555f 413 scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
02339e5b 414
e11e83f3 415 if (scm_is_integer (args))
0f2d19dd 416 {
b3fcac34
DH
417 if (k != 1)
418 scm_error_num_args_subr (what);
e11e83f3 419 return pos + (scm_to_long (args) - s->lbnd) * (s->inc);
0f2d19dd 420 }
d2e53ed6 421 while (k && scm_is_pair (args))
0f2d19dd
JB
422 {
423 ind = SCM_CAR (args);
424 args = SCM_CDR (args);
e11e83f3 425 if (!scm_is_integer (ind))
b3fcac34 426 scm_misc_error (what, s_bad_ind, SCM_EOL);
e11e83f3 427 j = scm_to_long (ind);
685c0d71
DH
428 if (j < s->lbnd || j > s->ubnd)
429 scm_out_of_range (what, ind);
0f2d19dd
JB
430 pos += (j - s->lbnd) * (s->inc);
431 k--;
432 s++;
433 }
d2e53ed6 434 if (k != 0 || !scm_is_null (args))
b3fcac34
DH
435 scm_error_num_args_subr (what);
436
0f2d19dd
JB
437 return pos;
438}
0f2d19dd 439
1cc91f1b 440
02339e5b
MV
441static SCM
442scm_i_make_ra (int ndim, scm_t_bits tag)
0f2d19dd
JB
443{
444 SCM ra;
02339e5b 445 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + tag,
4c9419ac
MV
446 scm_gc_malloc ((sizeof (scm_t_array) +
447 ndim * sizeof (scm_t_array_dim)),
448 "array"));
02339e5b 449 SCM_ARRAY_V (ra) = SCM_BOOL_F;
0f2d19dd
JB
450 return ra;
451}
452
02339e5b
MV
453SCM
454scm_make_ra (int ndim)
455{
456 return scm_i_make_ra (ndim, scm_tc16_array);
457}
458
459
0f2d19dd 460static char s_bad_spec[] = "Bad scm_array dimension";
0f2d19dd 461
1cc91f1b 462
02339e5b
MV
463/* Increments will still need to be set. */
464
0f2d19dd 465SCM
1bbd0b84 466scm_shap2ra (SCM args, const char *what)
0f2d19dd 467{
92c2555f 468 scm_t_array_dim *s;
0f2d19dd
JB
469 SCM ra, spec, sp;
470 int ndim = scm_ilength (args);
b3fcac34
DH
471 if (ndim < 0)
472 scm_misc_error (what, s_bad_spec, SCM_EOL);
473
0f2d19dd
JB
474 ra = scm_make_ra (ndim);
475 SCM_ARRAY_BASE (ra) = 0;
476 s = SCM_ARRAY_DIMS (ra);
d2e53ed6 477 for (; !scm_is_null (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
478 {
479 spec = SCM_CAR (args);
e11e83f3 480 if (scm_is_integer (spec))
0f2d19dd 481 {
e11e83f3 482 if (scm_to_long (spec) < 0)
b3fcac34 483 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd 484 s->lbnd = 0;
e11e83f3 485 s->ubnd = scm_to_long (spec) - 1;
0f2d19dd
JB
486 s->inc = 1;
487 }
488 else
489 {
d2e53ed6 490 if (!scm_is_pair (spec) || !scm_is_integer (SCM_CAR (spec)))
b3fcac34 491 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 492 s->lbnd = scm_to_long (SCM_CAR (spec));
0f2d19dd 493 sp = SCM_CDR (spec);
d2e53ed6 494 if (!scm_is_pair (sp)
e11e83f3 495 || !scm_is_integer (SCM_CAR (sp))
d2e53ed6 496 || !scm_is_null (SCM_CDR (sp)))
b3fcac34 497 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 498 s->ubnd = scm_to_long (SCM_CAR (sp));
0f2d19dd
JB
499 s->inc = 1;
500 }
501 }
502 return ra;
503}
504
f301dbf3
MV
505SCM_DEFINE (scm_make_typed_array, "make-typed-array", 2, 0, 1,
506 (SCM type, SCM fill, SCM bounds),
507 "Create and return an array of type @var{type}.")
508#define FUNC_NAME s_scm_make_typed_array
0f2d19dd 509{
f301dbf3 510 size_t k, rlen = 1;
92c2555f 511 scm_t_array_dim *s;
f301dbf3 512 creator_proc *creator;
0f2d19dd 513 SCM ra;
1be6b49c 514
f301dbf3
MV
515 creator = type_to_creator (type);
516 ra = scm_shap2ra (bounds, FUNC_NAME);
e038c042 517 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
518 s = SCM_ARRAY_DIMS (ra);
519 k = SCM_ARRAY_NDIM (ra);
1be6b49c 520
0f2d19dd
JB
521 while (k--)
522 {
a3a32939 523 s[k].inc = rlen;
f301dbf3 524 SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd);
0f2d19dd 525 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 526 }
a3a32939 527
f301dbf3
MV
528 if (scm_is_eq (fill, SCM_BOOL_F) && !scm_is_eq (type, SCM_BOOL_T))
529 fill = SCM_UNDEFINED;
a3a32939 530
f301dbf3 531 SCM_ARRAY_V (ra) = creator (scm_from_size_t (rlen), fill);
a3a32939 532
0f2d19dd 533 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
c014a02e 534 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
0f2d19dd
JB
535 return SCM_ARRAY_V (ra);
536 return ra;
537}
1bbd0b84 538#undef FUNC_NAME
0f2d19dd 539
f301dbf3
MV
540SCM_DEFINE (scm_make_array, "make-array", 1, 0, 1,
541 (SCM fill, SCM bounds),
542 "Create and return an array.")
543#define FUNC_NAME s_scm_make_array
544{
545 return scm_make_typed_array (SCM_BOOL_T, fill, bounds);
546}
547#undef FUNC_NAME
548
549#if SCM_ENABLE_DEPRECATED
550
551SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
552 (SCM dims, SCM prot, SCM fill),
553 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
554 "Create and return a uniform array or vector of type\n"
555 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
556 "length @var{length}. If @var{fill} is supplied, it's used to\n"
557 "fill the array, otherwise @var{prototype} is used.")
558#define FUNC_NAME s_scm_dimensions_to_uniform_array
559{
560 scm_c_issue_deprecation_warning
561 ("`dimensions->uniform-array' is deprecated. "
562 "Use `make-typed-array' instead.");
563
564 if (scm_is_integer (dims))
565 dims = scm_list_1 (dims);
566 return scm_make_typed_array (prototype_to_type (prot), fill, dims);
567}
568#undef FUNC_NAME
569
570#endif
1cc91f1b 571
0f2d19dd 572void
1bbd0b84 573scm_ra_set_contp (SCM ra)
0f2d19dd 574{
02339e5b
MV
575 /* XXX - correct? one-dimensional arrays are always 'contiguous',
576 is that right?
577 */
1be6b49c 578 size_t k = SCM_ARRAY_NDIM (ra);
0f2d19dd 579 if (k)
0f2d19dd 580 {
c014a02e 581 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 582 while (k--)
0f2d19dd 583 {
fe0c6dae
JB
584 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
585 {
e038c042 586 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
587 return;
588 }
589 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
590 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 591 }
0f2d19dd 592 }
e038c042 593 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
594}
595
596
3b3b36dd 597SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 598 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
599 "@code{make-shared-array} can be used to create shared subarrays of other\n"
600 "arrays. The @var{mapper} is a function that translates coordinates in\n"
601 "the new array into coordinates in the old array. A @var{mapper} must be\n"
602 "linear, and its range must stay within the bounds of the old array, but\n"
603 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 604 "@lisp\n"
b380b885
MD
605 "(define fred (make-array #f 8 8))\n"
606 "(define freds-diagonal\n"
607 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
608 "(array-set! freds-diagonal 'foo 3)\n"
609 "(array-ref fred 3 3) @result{} foo\n"
610 "(define freds-center\n"
611 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
612 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 613 "@end lisp")
1bbd0b84 614#define FUNC_NAME s_scm_make_shared_array
0f2d19dd
JB
615{
616 SCM ra;
617 SCM inds, indptr;
618 SCM imap;
c014a02e
ML
619 size_t k, i;
620 long old_min, new_min, old_max, new_max;
92c2555f 621 scm_t_array_dim *s;
b3fcac34
DH
622
623 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6
HWN
624 SCM_VALIDATE_ARRAY (1, oldra);
625 SCM_VALIDATE_PROC (2, mapfunc);
1bbd0b84 626 ra = scm_shap2ra (dims, FUNC_NAME);
0f2d19dd
JB
627 if (SCM_ARRAYP (oldra))
628 {
629 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
630 old_min = old_max = SCM_ARRAY_BASE (oldra);
631 s = SCM_ARRAY_DIMS (oldra);
632 k = SCM_ARRAY_NDIM (oldra);
633 while (k--)
634 {
635 if (s[k].inc > 0)
636 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
637 else
638 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
639 }
640 }
641 else
642 {
643 SCM_ARRAY_V (ra) = oldra;
644 old_min = 0;
02339e5b 645 old_max = scm_c_generalized_vector_length (oldra) - 1;
0f2d19dd
JB
646 }
647 inds = SCM_EOL;
648 s = SCM_ARRAY_DIMS (ra);
649 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
650 {
e11e83f3 651 inds = scm_cons (scm_from_long (s[k].lbnd), inds);
0f2d19dd
JB
652 if (s[k].ubnd < s[k].lbnd)
653 {
654 if (1 == SCM_ARRAY_NDIM (ra))
f301dbf3 655 ra = make_typed_vector (scm_array_type (ra), 0);
0f2d19dd 656 else
f301dbf3 657 SCM_ARRAY_V (ra) = make_typed_vector (scm_array_type (ra), 0);
0f2d19dd
JB
658 return ra;
659 }
660 }
fdc28395 661 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd 662 if (SCM_ARRAYP (oldra))
c014a02e 663 i = (size_t) scm_aind (oldra, imap, FUNC_NAME);
0f2d19dd
JB
664 else
665 {
e11e83f3 666 if (!scm_is_integer (imap))
0f2d19dd 667 {
e11e83f3 668 if (scm_ilength (imap) != 1 || !scm_is_integer (SCM_CAR (imap)))
b3fcac34 669 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
670 imap = SCM_CAR (imap);
671 }
e11e83f3 672 i = scm_to_size_t (imap);
0f2d19dd
JB
673 }
674 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
675 indptr = inds;
676 k = SCM_ARRAY_NDIM (ra);
677 while (k--)
678 {
679 if (s[k].ubnd > s[k].lbnd)
680 {
e11e83f3 681 SCM_SETCAR (indptr, scm_sum (SCM_CAR (indptr), scm_from_int (1)));
fdc28395 682 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd
JB
683 if (SCM_ARRAYP (oldra))
684
1bbd0b84 685 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
686 else
687 {
e11e83f3 688 if (!scm_is_integer (imap))
0f2d19dd 689 {
e11e83f3 690 if (scm_ilength (imap) != 1 || !scm_is_integer (SCM_CAR (imap)))
b3fcac34 691 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
692 imap = SCM_CAR (imap);
693 }
e11e83f3 694 s[k].inc = scm_to_long (imap) - i;
0f2d19dd
JB
695 }
696 i += s[k].inc;
697 if (s[k].inc > 0)
698 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
699 else
700 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
701 }
702 else
703 s[k].inc = new_max - new_min + 1; /* contiguous by default */
704 indptr = SCM_CDR (indptr);
705 }
b3fcac34
DH
706 if (old_min > new_min || old_max < new_max)
707 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
708 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
709 {
74014c46 710 SCM v = SCM_ARRAY_V (ra);
e11e83f3 711 unsigned long int length = scm_to_ulong (scm_uniform_vector_length (v));
74014c46
DH
712 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
713 return v;
0f2d19dd 714 if (s->ubnd < s->lbnd)
f301dbf3 715 return make_typed_vector (scm_array_type (ra), 0);
0f2d19dd
JB
716 }
717 scm_ra_set_contp (ra);
718 return ra;
719}
1bbd0b84 720#undef FUNC_NAME
0f2d19dd
JB
721
722
723/* args are RA . DIMS */
af45e3b0
DH
724SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
725 (SCM ra, SCM args),
1e6808ea
MG
726 "Return an array sharing contents with @var{array}, but with\n"
727 "dimensions arranged in a different order. There must be one\n"
728 "@var{dim} argument for each dimension of @var{array}.\n"
729 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
730 "and the rank of the array to be returned. Each integer in that\n"
731 "range must appear at least once in the argument list.\n"
732 "\n"
733 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
734 "dimensions in the array to be returned, their positions in the\n"
735 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
736 "may have the same value, in which case the returned array will\n"
737 "have smaller rank than @var{array}.\n"
738 "\n"
739 "@lisp\n"
b380b885
MD
740 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
741 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
742 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
743 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 744 "@end lisp")
1bbd0b84 745#define FUNC_NAME s_scm_transpose_array
0f2d19dd 746{
34d19ef6
HWN
747 SCM res, vargs;
748 SCM const *ve = &vargs;
92c2555f 749 scm_t_array_dim *s, *r;
0f2d19dd 750 int ndim, i, k;
af45e3b0 751
b3fcac34 752 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 753 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
e0e49670 754
20930f28 755 if (scm_is_generalized_vector (ra))
e0e49670
MV
756 {
757 /* Make sure that we are called with a single zero as
758 arguments.
759 */
760 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
761 SCM_WRONG_NUM_ARGS ();
762 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
763 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
764 return ra;
765 }
766
02339e5b 767 if (SCM_ARRAYP (ra) || SCM_ENCLOSED_ARRAYP (ra))
0f2d19dd 768 {
0f2d19dd 769 vargs = scm_vector (args);
b3fcac34
DH
770 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
771 SCM_WRONG_NUM_ARGS ();
772 ve = SCM_VELTS (vargs);
0f2d19dd
JB
773 ndim = 0;
774 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
775 {
e11e83f3 776 i = scm_to_signed_integer (ve[k], 0, SCM_ARRAY_NDIM(ra));
0f2d19dd
JB
777 if (ndim < i)
778 ndim = i;
779 }
780 ndim++;
781 res = scm_make_ra (ndim);
782 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
783 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
784 for (k = ndim; k--;)
785 {
786 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
787 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
788 }
789 for (k = SCM_ARRAY_NDIM (ra); k--;)
790 {
e11e83f3 791 i = scm_to_int (ve[k]);
0f2d19dd
JB
792 s = &(SCM_ARRAY_DIMS (ra)[k]);
793 r = &(SCM_ARRAY_DIMS (res)[i]);
794 if (r->ubnd < r->lbnd)
795 {
796 r->lbnd = s->lbnd;
797 r->ubnd = s->ubnd;
798 r->inc = s->inc;
799 ndim--;
800 }
801 else
802 {
803 if (r->ubnd > s->ubnd)
804 r->ubnd = s->ubnd;
805 if (r->lbnd < s->lbnd)
806 {
807 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
808 r->lbnd = s->lbnd;
809 }
810 r->inc += s->inc;
811 }
812 }
b3fcac34
DH
813 if (ndim > 0)
814 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
815 scm_ra_set_contp (res);
816 return res;
817 }
20930f28
MV
818
819 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 820}
1bbd0b84 821#undef FUNC_NAME
0f2d19dd
JB
822
823/* args are RA . AXES */
af45e3b0
DH
824SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
825 (SCM ra, SCM axes),
b380b885
MD
826 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
827 "the rank of @var{array}. @var{enclose-array} returns an array\n"
828 "resembling an array of shared arrays. The dimensions of each shared\n"
829 "array are the same as the @var{dim}th dimensions of the original array,\n"
830 "the dimensions of the outer array are the same as those of the original\n"
831 "array that did not match a @var{dim}.\n\n"
832 "An enclosed array is not a general Scheme array. Its elements may not\n"
833 "be set using @code{array-set!}. Two references to the same element of\n"
834 "an enclosed array will be @code{equal?} but will not in general be\n"
835 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
836 "enclosed array is unspecified.\n\n"
837 "examples:\n"
1e6808ea 838 "@lisp\n"
b380b885
MD
839 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
840 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
841 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
842 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 843 "@end lisp")
1bbd0b84 844#define FUNC_NAME s_scm_enclose_array
0f2d19dd 845{
af45e3b0 846 SCM axv, res, ra_inr;
cc95e00a 847 const char *c_axv;
92c2555f 848 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 849 int ndim, j, k, ninr, noutr;
af45e3b0 850
b3fcac34 851 SCM_VALIDATE_REST_ARGUMENT (axes);
d2e53ed6 852 if (scm_is_null (axes))
02339e5b 853 axes = scm_cons ((SCM_ARRAYP (ra) ? scm_from_size_t (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
0f2d19dd 854 ninr = scm_ilength (axes);
b3fcac34
DH
855 if (ninr < 0)
856 SCM_WRONG_NUM_ARGS ();
0f2d19dd 857 ra_inr = scm_make_ra (ninr);
e0e49670 858
20930f28 859 if (scm_is_generalized_vector (ra))
0f2d19dd 860 {
0f2d19dd 861 s->lbnd = 0;
e11e83f3 862 s->ubnd = scm_to_long (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
863 s->inc = 1;
864 SCM_ARRAY_V (ra_inr) = ra;
865 SCM_ARRAY_BASE (ra_inr) = 0;
866 ndim = 1;
20930f28
MV
867 }
868 else if (SCM_ARRAYP (ra))
869 {
0f2d19dd
JB
870 s = SCM_ARRAY_DIMS (ra);
871 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
872 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
873 ndim = SCM_ARRAY_NDIM (ra);
0f2d19dd 874 }
20930f28
MV
875 else
876 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
877
0f2d19dd 878 noutr = ndim - ninr;
b3fcac34
DH
879 if (noutr < 0)
880 SCM_WRONG_NUM_ARGS ();
e11e83f3 881 axv = scm_make_string (scm_from_int (ndim), SCM_MAKE_CHAR (0));
02339e5b 882 res = scm_i_make_ra (noutr, scm_tc16_enclosed_array);
0f2d19dd
JB
883 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
884 SCM_ARRAY_V (res) = ra_inr;
885 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
886 {
e11e83f3 887 if (!scm_is_integer (SCM_CAR (axes)))
b3fcac34 888 SCM_MISC_ERROR ("bad axis", SCM_EOL);
e11e83f3 889 j = scm_to_int (SCM_CAR (axes));
0f2d19dd
JB
890 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
891 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
892 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
cc95e00a 893 scm_c_string_set_x (axv, j, SCM_MAKE_CHAR (1));
0f2d19dd 894 }
cc95e00a 895 c_axv = scm_i_string_chars (axv);
0f2d19dd
JB
896 for (j = 0, k = 0; k < noutr; k++, j++)
897 {
cc95e00a 898 while (c_axv[j])
0f2d19dd
JB
899 j++;
900 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
901 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
902 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
903 }
cc95e00a 904 scm_remember_upto_here_1 (axv);
0f2d19dd
JB
905 scm_ra_set_contp (ra_inr);
906 scm_ra_set_contp (res);
907 return res;
908}
1bbd0b84 909#undef FUNC_NAME
0f2d19dd
JB
910
911
912
af45e3b0
DH
913SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
914 (SCM v, SCM args),
1e6808ea
MG
915 "Return @code{#t} if its arguments would be acceptable to\n"
916 "@code{array-ref}.")
1bbd0b84 917#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 918{
02339e5b 919 SCM res = SCM_BOOL_T;
af45e3b0 920
b3fcac34 921 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd 922
20930f28
MV
923 if (scm_is_generalized_vector (v))
924 {
02339e5b
MV
925 long ind;
926
927 if (!scm_is_pair (args))
928 SCM_WRONG_NUM_ARGS ();
929 ind = scm_to_long (SCM_CAR (args));
930 args = SCM_CDR (args);
931 res = scm_from_bool (ind >= 0
932 && ind < scm_c_generalized_vector_length (v));
20930f28 933 }
02339e5b 934 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
0f2d19dd 935 {
02339e5b
MV
936 size_t k = SCM_ARRAY_NDIM (v);
937 scm_t_array_dim *s = SCM_ARRAY_DIMS (v);
938
939 while (k > 0)
0f2d19dd 940 {
02339e5b 941 long ind;
20930f28 942
02339e5b
MV
943 if (!scm_is_pair (args))
944 SCM_WRONG_NUM_ARGS ();
945 ind = scm_to_long (SCM_CAR (args));
946 args = SCM_CDR (args);
947 k -= 1;
948
949 if (ind < s->lbnd || ind > s->ubnd)
950 {
951 res = SCM_BOOL_F;
952 /* We do not stop the checking after finding a violation
953 since we want to validate the type-correctness and
954 number of arguments in any case.
955 */
956 }
957 }
0f2d19dd 958 }
02339e5b
MV
959 else
960 scm_wrong_type_arg_msg (NULL, 0, v, "array");
20930f28 961
02339e5b
MV
962 if (!scm_is_null (args))
963 SCM_WRONG_NUM_ARGS ();
964
965 return res;
0f2d19dd 966}
1bbd0b84 967#undef FUNC_NAME
0f2d19dd 968
2d4d7f27 969SCM
02339e5b
MV
970scm_i_cvref (SCM v, size_t pos, int enclosed)
971{
972 if (enclosed)
973 {
974 int k = SCM_ARRAY_NDIM (v);
975 SCM res = scm_make_ra (k);
976 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
977 SCM_ARRAY_BASE (res) = pos;
978 while (k--)
979 {
980 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
981 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
982 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
983 }
984 return res;
985 }
986 else
987 return scm_c_generalized_vector_ref (v, pos);
988}
989
990SCM
991scm_cvref (SCM v, unsigned long pos, SCM last)
992{
993 return scm_i_cvref (v, pos, 0);
994}
0f2d19dd 995
e0e49670 996SCM_DEFINE (scm_array_ref, "array-ref", 1, 0, 1,
1bbd0b84 997 (SCM v, SCM args),
1e6808ea
MG
998 "Return the element at the @code{(index1, index2)} element in\n"
999 "@var{array}.")
e0e49670 1000#define FUNC_NAME s_scm_array_ref
0f2d19dd 1001{
c014a02e 1002 long pos;
02339e5b 1003 int enclosed = 0;
0f2d19dd 1004
02339e5b 1005 if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
0f2d19dd 1006 {
02339e5b 1007 enclosed = SCM_ENCLOSED_ARRAYP (v);
1bbd0b84 1008 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1009 v = SCM_ARRAY_V (v);
1010 }
1011 else
1012 {
20930f28 1013 size_t length;
0f2d19dd 1014 if (SCM_NIMP (args))
0f2d19dd 1015 {
d2e53ed6 1016 SCM_ASSERT (scm_is_pair (args), args, SCM_ARG2, FUNC_NAME);
e11e83f3 1017 pos = scm_to_long (SCM_CAR (args));
d2e53ed6 1018 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
0f2d19dd
JB
1019 }
1020 else
20930f28
MV
1021 pos = scm_to_long (args);
1022 length = scm_c_generalized_vector_length (v);
74014c46 1023 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1024 }
e0e49670 1025
02339e5b 1026 return scm_i_cvref (v, pos, enclosed);
20930f28 1027
20930f28
MV
1028 wna:
1029 scm_wrong_num_args (NULL);
1030 outrng:
1031 scm_out_of_range (NULL, scm_from_long (pos));
0f2d19dd 1032}
1bbd0b84 1033#undef FUNC_NAME
0f2d19dd 1034
0f2d19dd 1035
3b3b36dd 1036SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1037 (SCM v, SCM obj, SCM args),
8f85c0c6 1038 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1039 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1040#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1041{
c014a02e 1042 long pos = 0;
b3fcac34 1043
0f2d19dd 1044 if (SCM_ARRAYP (v))
0f2d19dd 1045 {
1bbd0b84 1046 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1047 v = SCM_ARRAY_V (v);
1048 }
02339e5b
MV
1049 else if (SCM_ENCLOSED_ARRAYP (v))
1050 scm_wrong_type_arg_msg (NULL, 0, v, "non-enclosed array");
1051 else if (scm_is_generalized_vector (v))
0f2d19dd 1052 {
20930f28 1053 size_t length;
d2e53ed6 1054 if (scm_is_pair (args))
0f2d19dd 1055 {
d2e53ed6 1056 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
e11e83f3 1057 pos = scm_to_long (SCM_CAR (args));
0f2d19dd
JB
1058 }
1059 else
20930f28
MV
1060 pos = scm_to_long (args);
1061 length = scm_c_generalized_vector_length (v);
74014c46 1062 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1063 }
02339e5b
MV
1064 else
1065 scm_wrong_type_arg_msg (NULL, 0, v, "array");
1066
1067 scm_c_generalized_vector_set_x (v, pos, obj);
1068 return SCM_UNSPECIFIED;
20930f28
MV
1069
1070 outrng:
1071 scm_out_of_range (NULL, scm_from_long (pos));
1072 wna:
1073 scm_wrong_num_args (NULL);
0f2d19dd 1074}
1bbd0b84 1075#undef FUNC_NAME
0f2d19dd 1076
1d7bdb25
GH
1077/* attempts to unroll an array into a one-dimensional array.
1078 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1079 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1080 wouldn't have contiguous elements. */
3b3b36dd 1081SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1082 (SCM ra, SCM strict),
b380b885
MD
1083 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1084 "without changing their order (last subscript changing fastest), then\n"
1085 "@code{array-contents} returns that shared array, otherwise it returns\n"
1086 "@code{#f}. All arrays made by @var{make-array} and\n"
1087 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1088 "@var{make-shared-array} may not be.\n\n"
1089 "If the optional argument @var{strict} is provided, a shared array will\n"
1090 "be returned only if its elements are stored internally contiguous in\n"
1091 "memory.")
1bbd0b84 1092#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1093{
1094 SCM sra;
e0e49670 1095
20930f28 1096 if (scm_is_generalized_vector (ra))
e0e49670
MV
1097 return ra;
1098
20930f28 1099 if (SCM_ARRAYP (ra))
0f2d19dd 1100 {
20930f28
MV
1101 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1102 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1103 return SCM_BOOL_F;
1104 for (k = 0; k < ndim; k++)
1105 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1106 if (!SCM_UNBNDP (strict))
74014c46 1107 {
20930f28
MV
1108 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1109 return SCM_BOOL_F;
1110 if (scm_is_bitvector (SCM_ARRAY_V (ra)))
1111 {
1112 if (len != scm_c_bitvector_length (SCM_ARRAY_V (ra)) ||
1113 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1114 len % SCM_LONG_BIT)
1115 return SCM_BOOL_F;
1116 }
74014c46 1117 }
20930f28
MV
1118
1119 {
1120 SCM v = SCM_ARRAY_V (ra);
1121 size_t length = scm_c_generalized_vector_length (v);
1122 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1123 return v;
0f2d19dd 1124 }
20930f28
MV
1125
1126 sra = scm_make_ra (1);
1127 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1128 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1129 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1130 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1131 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1132 return sra;
0f2d19dd 1133 }
02339e5b
MV
1134 else if (SCM_ENCLOSED_ARRAYP (ra))
1135 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
1136 else
1137 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1138}
1bbd0b84 1139#undef FUNC_NAME
0f2d19dd 1140
1cc91f1b 1141
0f2d19dd 1142SCM
6e8d25a6 1143scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1144{
1145 SCM ret;
c014a02e
ML
1146 long inc = 1;
1147 size_t k, len = 1;
0f2d19dd
JB
1148 for (k = SCM_ARRAY_NDIM (ra); k--;)
1149 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1150 k = SCM_ARRAY_NDIM (ra);
1151 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1152 {
20930f28 1153 if (!scm_is_bitvector (SCM_ARRAY_V (ra)))
0f2d19dd 1154 return ra;
20930f28 1155 if ((len == scm_c_bitvector_length (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1156 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1157 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1158 return ra;
1159 }
1160 ret = scm_make_ra (k);
1161 SCM_ARRAY_BASE (ret) = 0;
1162 while (k--)
1163 {
1164 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1165 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1166 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1167 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1168 }
f301dbf3 1169 SCM_ARRAY_V (ret) = make_typed_vector (scm_array_type (ra), inc);
0f2d19dd
JB
1170 if (copy)
1171 scm_array_copy_x (ra, ret);
1172 return ret;
1173}
1174
1175
1176
3b3b36dd 1177SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
03a5397a 1178 (SCM ura, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1179 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1180 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1181 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1182 "If an end of file is encountered,\n"
1183 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1184 "(starting at the beginning) and the remainder of the array is\n"
1185 "unchanged.\n\n"
1186 "The optional arguments @var{start} and @var{end} allow\n"
1187 "a specified region of a vector (or linearized array) to be read,\n"
1188 "leaving the remainder of the vector unchanged.\n\n"
1189 "@code{uniform-array-read!} returns the number of objects read.\n"
1190 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1191 "returned by @code{(current-input-port)}.")
1bbd0b84 1192#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1193{
3d8d56df
GH
1194 if (SCM_UNBNDP (port_or_fd))
1195 port_or_fd = scm_cur_inp;
35de7ebe 1196
03a5397a 1197 if (scm_is_uniform_vector (ura))
20930f28 1198 {
03a5397a 1199 return scm_uniform_vector_read_x (ura, port_or_fd, start, end);
20930f28 1200 }
03a5397a 1201 else if (SCM_ARRAYP (ura))
20930f28 1202 {
03a5397a
MV
1203 size_t base, vlen, cstart, cend;
1204 SCM cra, ans;
1205
1206 cra = scm_ra2contig (ura, 0);
1207 base = SCM_ARRAY_BASE (cra);
20930f28
MV
1208 vlen = SCM_ARRAY_DIMS (cra)->inc *
1209 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
35de7ebe 1210
03a5397a
MV
1211 cstart = 0;
1212 cend = vlen;
1213 if (!SCM_UNBNDP (start))
1146b6cd 1214 {
03a5397a
MV
1215 cstart = scm_to_unsigned_integer (start, 0, vlen);
1216 if (!SCM_UNBNDP (end))
1217 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1218 }
35de7ebe 1219
03a5397a
MV
1220 ans = scm_uniform_vector_read_x (SCM_ARRAY_V (cra), port_or_fd,
1221 scm_from_size_t (base + cstart),
1222 scm_from_size_t (base + cend));
6c951427 1223
03a5397a
MV
1224 if (!scm_is_eq (cra, ura))
1225 scm_array_copy_x (cra, ura);
1226 return ans;
3d8d56df 1227 }
02339e5b
MV
1228 else if (SCM_ENCLOSED_ARRAYP (ura))
1229 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1230 else
1231 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1232}
1bbd0b84 1233#undef FUNC_NAME
0f2d19dd 1234
3b3b36dd 1235SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
03a5397a 1236 (SCM ura, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1237 "Writes all elements of @var{ura} as binary objects to\n"
1238 "@var{port-or-fdes}.\n\n"
1239 "The optional arguments @var{start}\n"
1240 "and @var{end} allow\n"
1241 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1242 "The number of objects actually written is returned.\n"
b380b885
MD
1243 "@var{port-or-fdes} may be\n"
1244 "omitted, in which case it defaults to the value returned by\n"
1245 "@code{(current-output-port)}.")
1bbd0b84 1246#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1247{
3d8d56df
GH
1248 if (SCM_UNBNDP (port_or_fd))
1249 port_or_fd = scm_cur_outp;
20930f28 1250
03a5397a 1251 if (scm_is_uniform_vector (ura))
20930f28 1252 {
03a5397a 1253 return scm_uniform_vector_write (ura, port_or_fd, start, end);
20930f28 1254 }
03a5397a 1255 else if (SCM_ARRAYP (ura))
20930f28 1256 {
03a5397a
MV
1257 size_t base, vlen, cstart, cend;
1258 SCM cra, ans;
1259
1260 cra = scm_ra2contig (ura, 1);
1261 base = SCM_ARRAY_BASE (cra);
1262 vlen = SCM_ARRAY_DIMS (cra)->inc *
1263 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1146b6cd 1264
03a5397a
MV
1265 cstart = 0;
1266 cend = vlen;
1267 if (!SCM_UNBNDP (start))
1146b6cd 1268 {
03a5397a
MV
1269 cstart = scm_to_unsigned_integer (start, 0, vlen);
1270 if (!SCM_UNBNDP (end))
1271 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 1272 }
3d8d56df 1273
03a5397a
MV
1274 ans = scm_uniform_vector_write (SCM_ARRAY_V (cra), port_or_fd,
1275 scm_from_size_t (base + cstart),
1276 scm_from_size_t (base + cend));
6c951427 1277
03a5397a 1278 return ans;
3d8d56df 1279 }
02339e5b
MV
1280 else if (SCM_ENCLOSED_ARRAYP (ura))
1281 scm_wrong_type_arg_msg (NULL, 0, ura, "non-enclosed array");
03a5397a
MV
1282 else
1283 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 1284}
1bbd0b84 1285#undef FUNC_NAME
0f2d19dd
JB
1286
1287
20930f28
MV
1288/** Bit vectors */
1289
1290static scm_t_bits scm_tc16_bitvector;
1291
1292#define IS_BITVECTOR(obj) SCM_SMOB_PREDICATE(scm_tc16_bitvector,(obj))
1293#define BITVECTOR_BITS(obj) ((scm_t_uint32 *)SCM_SMOB_DATA(obj))
1294#define BITVECTOR_LENGTH(obj) ((size_t)SCM_SMOB_DATA_2(obj))
1295
1296static size_t
1297bitvector_free (SCM vec)
1298{
1299 scm_gc_free (BITVECTOR_BITS (vec),
1300 sizeof (scm_t_uint32) * ((BITVECTOR_LENGTH (vec)+31)/32),
1301 "bitvector");
1302 return 0;
1303}
1304
1305static int
1306bitvector_print (SCM vec, SCM port, scm_print_state *pstate)
1307{
1308 size_t bit_len = BITVECTOR_LENGTH (vec);
1309 size_t word_len = (bit_len+31)/32;
1310 scm_t_uint32 *bits = BITVECTOR_BITS (vec);
1311 size_t i, j;
1312
1313 scm_puts ("#*", port);
1314 for (i = 0; i < word_len; i++, bit_len -= 32)
1315 {
1316 scm_t_uint32 mask = 1;
1317 for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
1318 scm_putc ((bits[i] & mask)? '1' : '0', port);
1319 }
1320
1321 return 1;
1322}
1323
1324static SCM
1325bitvector_equalp (SCM vec1, SCM vec2)
1326{
1327 size_t bit_len = BITVECTOR_LENGTH (vec1);
1328 size_t word_len = (bit_len + 31) / 32;
1329 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
1330 scm_t_uint32 *bits1 = BITVECTOR_BITS (vec1);
1331 scm_t_uint32 *bits2 = BITVECTOR_BITS (vec2);
1332
1333 /* compare lengths */
1334 if (BITVECTOR_LENGTH (vec2) != bit_len)
1335 return SCM_BOOL_F;
1336 /* avoid underflow in word_len-1 below. */
1337 if (bit_len == 0)
1338 return SCM_BOOL_T;
1339 /* compare full words */
1340 if (memcmp (bits1, bits2, sizeof (scm_t_uint32) * (word_len-1)))
1341 return SCM_BOOL_F;
1342 /* compare partial last words */
1343 if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
1344 return SCM_BOOL_F;
1345 return SCM_BOOL_T;
1346}
1347
1348int
1349scm_is_bitvector (SCM vec)
1350{
1351 return IS_BITVECTOR (vec);
1352}
1353
1354SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
1355 (SCM obj),
1356 "Return @code{#t} when @var{obj} is a bitvector, else\n"
1357 "return @code{#f}.")
1358#define FUNC_NAME s_scm_bitvector_p
1359{
1360 return scm_from_bool (scm_is_bitvector (obj));
1361}
1362#undef FUNC_NAME
1363
1364SCM
1365scm_c_make_bitvector (size_t len, SCM fill)
1366{
1367 size_t word_len = (len + 31) / 32;
1368 scm_t_uint32 *bits;
1369 SCM res;
1370
1371 bits = scm_gc_malloc (sizeof (scm_t_uint32) * word_len,
1372 "bitvector");
1373 SCM_NEWSMOB2 (res, scm_tc16_bitvector, bits, len);
1374
1375 if (!SCM_UNBNDP (fill))
1376 scm_bitvector_fill_x (res, fill);
1377
1378 return res;
1379}
1380
1381SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
1382 (SCM len, SCM fill),
1383 "Create a new bitvector of length @var{len} and\n"
1384 "optionally initialize all elements to @var{fill}.")
1385#define FUNC_NAME s_scm_make_bitvector
1386{
1387 return scm_c_make_bitvector (scm_to_size_t (len), fill);
1388}
1389#undef FUNC_NAME
1390
1391SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
1392 (SCM bits),
1393 "Create a new bitvector with the arguments as elements.")
1394#define FUNC_NAME s_scm_bitvector
1395{
1396 return scm_list_to_bitvector (bits);
1397}
1398#undef FUNC_NAME
1399
1400size_t
1401scm_c_bitvector_length (SCM vec)
1402{
1403 scm_assert_smob_type (scm_tc16_bitvector, vec);
1404 return BITVECTOR_LENGTH (vec);
1405}
1406
1407SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
1408 (SCM vec),
1409 "Return the length of the bitvector @var{vec}.")
1410#define FUNC_NAME s_scm_bitvector_length
1411{
1412 return scm_from_size_t (scm_c_bitvector_length (vec));
1413}
1414#undef FUNC_NAME
1415
21c487f1 1416const scm_t_uint32 *
20930f28
MV
1417scm_bitvector_elements (SCM vec)
1418{
1419 scm_assert_smob_type (scm_tc16_bitvector, vec);
1420 return BITVECTOR_BITS (vec);
1421}
1422
1423void
21c487f1 1424scm_bitvector_release_elements (SCM vec)
20930f28
MV
1425{
1426 /* Nothing to do right now, but this function might come in handy
1427 when bitvectors need to be locked when giving away a pointer
1428 to their elements.
1429
21c487f1 1430 Also, a call to scm_bitvector_release_elements acts like
20930f28
MV
1431 scm_remember_upto_here, which is needed in any case.
1432 */
d817a70c
MV
1433
1434 scm_remember_upto_here_1 (vec);
20930f28
MV
1435}
1436
1437void
21c487f1 1438scm_frame_bitvector_release_elements (SCM vec)
20930f28 1439{
21c487f1 1440 scm_frame_unwind_handler_with_scm (scm_bitvector_release_elements, vec,
20930f28
MV
1441 SCM_F_WIND_EXPLICITLY);
1442}
1443
21c487f1
MV
1444scm_t_uint32 *
1445scm_bitvector_writable_elements (SCM vec)
1446{
1447 scm_assert_smob_type (scm_tc16_bitvector, vec);
1448 return BITVECTOR_BITS (vec);
1449}
1450
1451void
1452scm_bitvector_release_writable_elements (SCM vec)
1453{
1454 scm_remember_upto_here_1 (vec);
1455}
1456
1457void
1458scm_frame_bitvector_release_writable_elements (SCM vec)
1459{
1460 scm_frame_unwind_handler_with_scm
1461 (scm_bitvector_release_writable_elements, vec,
1462 SCM_F_WIND_EXPLICITLY);
1463}
1464
20930f28
MV
1465SCM
1466scm_c_bitvector_ref (SCM vec, size_t idx)
1467{
1468 if (idx < scm_c_bitvector_length (vec))
1469 {
21c487f1 1470 const scm_t_uint32 *bits = scm_bitvector_elements (vec);
20930f28 1471 SCM res = (bits[idx/32] & (1L << (idx%32)))? SCM_BOOL_T : SCM_BOOL_F;
21c487f1 1472 scm_bitvector_release_elements (vec);
20930f28
MV
1473 return res;
1474 }
1475 else
1476 scm_out_of_range (NULL, scm_from_size_t (idx));
1477}
1478
1479SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
1480 (SCM vec, SCM idx),
1481 "Return the element at index @var{idx} of the bitvector\n"
1482 "@var{vec}.")
1483#define FUNC_NAME s_scm_bitvector_ref
1484{
1485 return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
1486}
1487#undef FUNC_NAME
1488
1489void
1490scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
1491{
1492 if (idx < scm_c_bitvector_length (vec))
1493 {
21c487f1 1494 scm_t_uint32 *bits = scm_bitvector_writable_elements (vec);
20930f28
MV
1495 scm_t_uint32 mask = 1L << (idx%32);
1496 if (scm_is_true (val))
1497 bits[idx/32] |= mask;
1498 else
1499 bits[idx/32] &= ~mask;
21c487f1 1500 scm_bitvector_release_writable_elements (vec);
20930f28
MV
1501 }
1502 else
1503 scm_out_of_range (NULL, scm_from_size_t (idx));
1504}
1505
1506SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
1507 (SCM vec, SCM idx, SCM val),
1508 "Set the element at index @var{idx} of the bitvector\n"
1509 "@var{vec} when @var{val} is true, else clear it.")
1510#define FUNC_NAME s_scm_bitvector_set_x
1511{
1512 scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
1513 return SCM_UNSPECIFIED;
1514}
1515#undef FUNC_NAME
1516
1517SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
1518 (SCM vec, SCM val),
1519 "Set all elements of the bitvector\n"
1520 "@var{vec} when @var{val} is true, else clear them.")
1521#define FUNC_NAME s_scm_bitvector_fill_x
1522{
21c487f1 1523 scm_t_uint32 *bits = scm_bitvector_writable_elements (vec);
20930f28
MV
1524 size_t bit_len = BITVECTOR_LENGTH (vec);
1525 size_t word_len = (bit_len + 31) / 32;
1526 memset (bits, scm_is_true (val)? -1:0, sizeof (scm_t_uint32) * word_len);
21c487f1 1527 scm_bitvector_release_writable_elements (vec);
20930f28
MV
1528 return SCM_UNSPECIFIED;
1529}
1530#undef FUNC_NAME
1531
1532SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
1533 (SCM list),
1534 "Return a new bitvector initialized with the elements\n"
1535 "of @var{list}.")
1536#define FUNC_NAME s_scm_list_to_bitvector
1537{
1538 size_t bit_len = scm_to_size_t (scm_length (list));
1539 SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
1540 size_t word_len = (bit_len+31)/32;
21c487f1 1541 scm_t_uint32 *bits = scm_bitvector_writable_elements (vec);
20930f28
MV
1542 size_t i, j;
1543
1544 for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
1545 {
1546 scm_t_uint32 mask = 1;
1547 bits[i] = 0;
1548 for (j = 0; j < 32 && j < bit_len;
1549 j++, mask <<= 1, list = SCM_CDR (list))
1550 if (scm_is_true (SCM_CAR (list)))
1551 bits[i] |= mask;
1552 }
1553
21c487f1 1554 scm_bitvector_release_writable_elements (vec);
20930f28
MV
1555 return vec;
1556}
1557#undef FUNC_NAME
1558
1559SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
1560 (SCM vec),
1561 "Return a new list initialized with the elements\n"
1562 "of the bitvector @var{vec}.")
1563#define FUNC_NAME s_scm_bitvector_to_list
1564{
1565 size_t bit_len = scm_c_bitvector_length (vec);
1566 SCM res = SCM_EOL;
1567 size_t word_len = (bit_len+31)/32;
21c487f1 1568 const scm_t_uint32 *bits = scm_bitvector_elements (vec);
20930f28
MV
1569 size_t i, j;
1570
1571 for (i = 0; i < word_len; i++, bit_len -= 32)
1572 {
1573 scm_t_uint32 mask = 1;
1574 for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
1575 res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
1576 }
1577
21c487f1 1578 scm_bitvector_release_elements (vec);
20930f28
MV
1579 return scm_reverse_x (res, SCM_EOL);
1580}
1581#undef FUNC_NAME
1582
1583/* From mmix-arith.w by Knuth.
1584
1585 Here's a fun way to count the number of bits in a tetrabyte.
1586
1587 [This classical trick is called the ``Gillies--Miller method for
1588 sideways addition'' in {\sl The Preparation of Programs for an
1589 Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
1590 edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
1591 the tricks used here were suggested by Balbir Singh, Peter
1592 Rossmanith, and Stefan Schwoon.]
1593*/
1594
1595static size_t
1596count_ones (scm_t_uint32 x)
1597{
1598 x=x-((x>>1)&0x55555555);
1599 x=(x&0x33333333)+((x>>2)&0x33333333);
1600 x=(x+(x>>4))&0x0f0f0f0f;
1601 x=x+(x>>8);
1602 return (x+(x>>16)) & 0xff;
1603}
0f2d19dd 1604
3b3b36dd 1605SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1606 (SCM b, SCM bitvector),
1e6808ea 1607 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1608 "@var{bitvector}.")
1bbd0b84 1609#define FUNC_NAME s_scm_bit_count
0f2d19dd 1610{
20930f28
MV
1611 size_t bit_len = scm_c_bitvector_length (bitvector);
1612 size_t word_len = (bit_len + 31) / 32;
1613 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
21c487f1 1614 const scm_t_uint32 *bits = scm_bitvector_elements (bitvector);
20930f28
MV
1615
1616 int bit = scm_to_bool (b);
1617 size_t count = 0, i;
1618
1619 if (bit_len == 0)
1620 return 0;
1621
1622 for (i = 0; i < word_len-1; i++)
1623 count += count_ones (bits[i]);
1624 count += count_ones (bits[i] & last_mask);
1625
21c487f1 1626 scm_bitvector_release_elements (bitvector);
20930f28 1627 return scm_from_size_t (bit? count : bit_len-count);
0f2d19dd 1628}
1bbd0b84 1629#undef FUNC_NAME
0f2d19dd 1630
20930f28
MV
1631/* returns 32 for x == 0.
1632*/
1633static size_t
1634find_first_one (scm_t_uint32 x)
1635{
1636 size_t pos = 0;
1637 /* do a binary search in x. */
1638 if ((x & 0xFFFF) == 0)
1639 x >>= 16, pos += 16;
1640 if ((x & 0xFF) == 0)
1641 x >>= 8, pos += 8;
1642 if ((x & 0xF) == 0)
1643 x >>= 4, pos += 4;
1644 if ((x & 0x3) == 0)
1645 x >>= 2, pos += 2;
1646 if ((x & 0x1) == 0)
1647 pos += 1;
1648 return pos;
1649}
0f2d19dd 1650
3b3b36dd 1651SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1652 (SCM item, SCM v, SCM k),
88ecf5cb
KR
1653 "Return the index of the first occurrance of @var{item} in bit\n"
1654 "vector @var{v}, starting from @var{k}. If there is no\n"
1655 "@var{item} entry between @var{k} and the end of\n"
1656 "@var{bitvector}, then return @code{#f}. For example,\n"
1657 "\n"
1658 "@example\n"
1659 "(bit-position #t #*000101 0) @result{} 3\n"
1660 "(bit-position #f #*0001111 3) @result{} #f\n"
1661 "@end example")
1bbd0b84 1662#define FUNC_NAME s_scm_bit_position
0f2d19dd 1663{
20930f28
MV
1664 size_t bit_len = scm_c_bitvector_length (v);
1665 size_t word_len = (bit_len + 31) / 32;
1666 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
21c487f1 1667 const scm_t_uint32 *bits = scm_bitvector_elements (v);
20930f28
MV
1668 size_t first_bit = scm_to_unsigned_integer (k, 0, bit_len);
1669 size_t first_word = first_bit / 32;
1670 scm_t_uint32 first_mask = ((scm_t_uint32)-1) << (first_bit - 32*first_word);
1671 scm_t_uint32 w;
1672
1673 int bit = scm_to_bool (item);
1674 size_t i;
1675 SCM res = SCM_BOOL_F;
1676
1677 if (bit_len == 0)
1678 return 0;
74014c46 1679
20930f28
MV
1680 for (i = first_word; i < word_len; i++)
1681 {
1682 w = (bit? bits[i] : ~bits[i]);
1683 if (i == first_word)
1684 w &= first_mask;
1685 if (i == word_len-1)
1686 w &= last_mask;
74014c46 1687 if (w)
20930f28
MV
1688 {
1689 res = scm_from_size_t (32*i + find_first_one (w));
1690 break;
1691 }
0f2d19dd 1692 }
20930f28 1693
21c487f1 1694 scm_bitvector_release_elements (v);
20930f28 1695 return res;
0f2d19dd 1696}
1bbd0b84 1697#undef FUNC_NAME
0f2d19dd 1698
3b3b36dd 1699SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761 1700 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1701 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1702 "selecting the entries to change. The return value is\n"
1703 "unspecified.\n"
1704 "\n"
1705 "If @var{kv} is a bit vector, then those entries where it has\n"
1706 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1707 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1708 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1709 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1710 "\n"
1711 "@example\n"
1712 "(define bv #*01000010)\n"
1713 "(bit-set*! bv #*10010001 #t)\n"
1714 "bv\n"
1715 "@result{} #*11010011\n"
1716 "@end example\n"
1717 "\n"
85368844
MV
1718 "If @var{kv} is a u32vector, then its elements are\n"
1719 "indices into @var{v} which are set to @var{obj}.\n"
88ecf5cb
KR
1720 "\n"
1721 "@example\n"
1722 "(define bv #*01000010)\n"
85368844 1723 "(bit-set*! bv #u32(5 2 7) #t)\n"
88ecf5cb
KR
1724 "bv\n"
1725 "@result{} #*01100111\n"
1726 "@end example")
1bbd0b84 1727#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1728{
20930f28
MV
1729 if (scm_is_bitvector (kv))
1730 {
1731 size_t bit_len = scm_c_bitvector_length (kv);
1732 size_t word_len = (bit_len + 31) / 32;
21c487f1
MV
1733 scm_t_uint32 *bits1;
1734 const scm_t_uint32 *bits2;
20930f28
MV
1735 size_t i;
1736 int bit = scm_to_bool (obj);
1737
1738 if (scm_c_bitvector_length (v) != bit_len)
85368844
MV
1739 scm_misc_error (NULL,
1740 "bit vectors must have equal length",
1741 SCM_EOL);
1742
21c487f1 1743 bits1 = scm_bitvector_writable_elements (v);
20930f28
MV
1744 bits2 = scm_bitvector_elements (kv);
1745
1746 if (bit == 0)
1747 for (i = 0; i < word_len; i++)
1748 bits1[i] &= ~bits2[i];
85368844 1749 else
20930f28
MV
1750 for (i = 0; i < word_len; i++)
1751 bits1[i] |= bits2[i];
1752
21c487f1
MV
1753 scm_bitvector_release_elements (kv);
1754 scm_bitvector_release_writable_elements (v);
85368844
MV
1755 }
1756 else if (scm_is_true (scm_u32vector_p (kv)))
1757 {
d44ff083 1758 size_t ulen, i;
d817a70c 1759 const scm_t_uint32 *indices;
20930f28
MV
1760
1761 /* assert that obj is a boolean.
1762 */
1763 scm_to_bool (obj);
d44ff083
MV
1764
1765 scm_frame_begin (0);
1766
1767 ulen = scm_c_uniform_vector_length (kv);
1768 indices = scm_u32vector_elements (kv);
d817a70c 1769 scm_frame_uniform_vector_release_elements (kv);
85368844 1770
20930f28
MV
1771 for (i = 0; i < ulen; i++)
1772 scm_c_bitvector_set_x (v, (size_t)indices[i], obj);
d44ff083
MV
1773
1774 scm_frame_end ();
0f2d19dd 1775 }
20930f28 1776 else
85368844
MV
1777 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
1778
0f2d19dd
JB
1779 return SCM_UNSPECIFIED;
1780}
1bbd0b84 1781#undef FUNC_NAME
0f2d19dd
JB
1782
1783
3b3b36dd 1784SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1785 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1786 "Return a count of how many entries in bit vector @var{v} are\n"
1787 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
1788 "consider.\n"
1789 "\n"
1790 "If @var{kv} is a bit vector, then those entries where it has\n"
1791 "@code{#t} are the ones in @var{v} which are considered.\n"
1792 "@var{kv} and @var{v} must be the same length.\n"
1793 "\n"
85368844
MV
1794 "If @var{kv} is a u32vector, then it contains\n"
1795 "the indexes in @var{v} to consider.\n"
88ecf5cb
KR
1796 "\n"
1797 "For example,\n"
1798 "\n"
1799 "@example\n"
1800 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
85368844 1801 "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
88ecf5cb 1802 "@end example")
1bbd0b84 1803#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1804{
20930f28 1805 if (scm_is_bitvector (kv))
0f2d19dd 1806 {
20930f28
MV
1807 size_t bit_len = scm_c_bitvector_length (kv);
1808 size_t word_len = (bit_len + 31) / 32;
1809 scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
1810 scm_t_uint32 xor_mask = scm_to_bool (obj)? 0 : ((scm_t_uint32)-1);
21c487f1 1811 const scm_t_uint32 *bits1, *bits2;
20930f28 1812 size_t count = 0, i;
85368844 1813
20930f28 1814 if (scm_c_bitvector_length (v) != bit_len)
85368844
MV
1815 scm_misc_error (NULL,
1816 "bit vectors must have equal length",
1817 SCM_EOL);
1818
20930f28
MV
1819 if (bit_len == 0)
1820 return scm_from_size_t (0);
85368844 1821
20930f28
MV
1822 bits1 = scm_bitvector_elements (v);
1823 bits2 = scm_bitvector_elements (kv);
85368844 1824
20930f28
MV
1825 for (i = 0; i < word_len-1; i++)
1826 count += count_ones ((bits1[i]^xor_mask) & bits2[i]);
1827 count += count_ones ((bits1[i]^xor_mask) & bits2[i] & last_mask);
c209c88e 1828
21c487f1
MV
1829 scm_bitvector_release_elements (kv);
1830 scm_bitvector_release_elements (v);
20930f28
MV
1831
1832 return scm_from_size_t (count);
0f2d19dd 1833 }
85368844
MV
1834 else if (scm_is_true (scm_u32vector_p (kv)))
1835 {
20930f28 1836 size_t count = 0, ulen, i;
d817a70c 1837 const scm_t_uint32 *indices;
20930f28 1838 int bit = scm_to_bool (obj);
d44ff083
MV
1839
1840 scm_frame_begin (0);
1841
1842 ulen = scm_c_uniform_vector_length (kv);
1843 indices = scm_u32vector_elements (kv);
d817a70c 1844 scm_frame_uniform_vector_release_elements (kv);
85368844 1845
20930f28
MV
1846 for (i = 0; i < ulen; i++)
1847 if ((scm_is_true (scm_c_bitvector_ref (v, (size_t)indices[i])) != 0)
1848 == (bit != 0))
1849 count++;
d44ff083
MV
1850
1851 scm_frame_end ();
20930f28
MV
1852
1853 return scm_from_size_t (count);
85368844 1854 }
20930f28 1855 else
85368844 1856 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
0f2d19dd 1857}
1bbd0b84 1858#undef FUNC_NAME
0f2d19dd
JB
1859
1860
3b3b36dd 1861SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1862 (SCM v),
88ecf5cb
KR
1863 "Modify the bit vector @var{v} by replacing each element with\n"
1864 "its negation.")
1bbd0b84 1865#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 1866{
20930f28
MV
1867 size_t bit_len = scm_c_bitvector_length (v);
1868 size_t word_len = (bit_len + 31) / 32;
21c487f1 1869 scm_t_uint32 *bits = scm_bitvector_writable_elements (v);
20930f28 1870 size_t i;
74014c46 1871
20930f28
MV
1872 for (i = 0; i < word_len; i++)
1873 bits[i] = ~bits[i];
74014c46 1874
21c487f1 1875 scm_bitvector_release_writable_elements (v);
0f2d19dd
JB
1876 return SCM_UNSPECIFIED;
1877}
1bbd0b84 1878#undef FUNC_NAME
0f2d19dd
JB
1879
1880
0f2d19dd 1881SCM
cc95e00a 1882scm_istr2bve (SCM str)
0f2d19dd 1883{
cc95e00a 1884 size_t len = scm_i_string_length (str);
20930f28
MV
1885 SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
1886 SCM res = vec;
1887
1888 scm_t_uint32 mask;
1889 size_t k, j;
cc95e00a 1890 const char *c_str = scm_i_string_chars (str);
21c487f1 1891 scm_t_uint32 *data = scm_bitvector_writable_elements (vec);
cc95e00a 1892
20930f28 1893 for (k = 0; k < (len + 31) / 32; k++)
0f2d19dd
JB
1894 {
1895 data[k] = 0L;
20930f28
MV
1896 j = len - k * 32;
1897 if (j > 32)
1898 j = 32;
0f2d19dd 1899 for (mask = 1L; j--; mask <<= 1)
cc95e00a 1900 switch (*c_str++)
0f2d19dd
JB
1901 {
1902 case '0':
1903 break;
1904 case '1':
1905 data[k] |= mask;
1906 break;
1907 default:
20930f28
MV
1908 res = SCM_BOOL_F;
1909 goto exit;
0f2d19dd
JB
1910 }
1911 }
20930f28
MV
1912
1913 exit:
1914 scm_remember_upto_here_1 (str);
21c487f1 1915 scm_bitvector_release_writable_elements (vec);
20930f28 1916 return res;
0f2d19dd
JB
1917}
1918
1919
1cc91f1b 1920
0f2d19dd 1921static SCM
34d19ef6 1922ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd 1923{
02339e5b
MV
1924 SCM res = SCM_EOL;
1925 long inc = SCM_ARRAY_DIMS (ra)[k].inc;
1926 size_t i;
1927 int enclosed = SCM_ENCLOSED_ARRAYP (ra);
1928
0f2d19dd
JB
1929 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
1930 return SCM_EOL;
1931 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
1932 if (k < SCM_ARRAY_NDIM (ra) - 1)
1933 {
1934 do
1935 {
1936 i -= inc;
1937 res = scm_cons (ra2l (ra, i, k + 1), res);
1938 }
1939 while (i != base);
1940 }
1941 else
1942 do
1943 {
1944 i -= inc;
02339e5b
MV
1945 res = scm_cons (scm_i_cvref (SCM_ARRAY_V (ra), i, enclosed),
1946 res);
0f2d19dd
JB
1947 }
1948 while (i != base);
1949 return res;
1950}
1951
1952
cd328b4f 1953SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 1954 (SCM v),
1e6808ea
MG
1955 "Return a list consisting of all the elements, in order, of\n"
1956 "@var{array}.")
cd328b4f 1957#define FUNC_NAME s_scm_array_to_list
0f2d19dd 1958{
20930f28
MV
1959 if (scm_is_generalized_vector (v))
1960 return scm_generalized_vector_to_list (v);
02339e5b 1961 else if (SCM_ARRAYP (v) || SCM_ENCLOSED_ARRAYP (v))
20930f28 1962 return ra2l (v, SCM_ARRAY_BASE (v), 0);
e0e49670 1963
20930f28 1964 scm_wrong_type_arg_msg (NULL, 0, v, "array");
0f2d19dd 1965}
1bbd0b84 1966#undef FUNC_NAME
0f2d19dd
JB
1967
1968
c014a02e 1969static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 1970
f301dbf3
MV
1971SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
1972 (SCM type, SCM ndim, SCM lst),
1973 "Return an array of the type @var{type}\n"
1974 "with elements the same as those of @var{lst}.\n"
bfad4005
MV
1975 "\n"
1976 "The argument @var{ndim} determines the number of dimensions\n"
1977 "of the array. It is either an exact integer, giving the\n"
20930f28 1978 "number directly, or a list of exact integers, whose length\n"
bfad4005
MV
1979 "specifies the number of dimensions and each element is the\n"
1980 "lower index bound of its dimension.")
f301dbf3 1981#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 1982{
bfad4005 1983 SCM shape, row;
0f2d19dd 1984 SCM ra;
c014a02e 1985 unsigned long k;
bfad4005
MV
1986
1987 shape = SCM_EOL;
1988 row = lst;
1989 if (scm_is_integer (ndim))
0f2d19dd 1990 {
bfad4005
MV
1991 size_t k = scm_to_size_t (ndim);
1992 while (k-- > 0)
1993 {
1994 shape = scm_cons (scm_length (row), shape);
1995 if (k > 0)
1996 row = scm_car (row);
1997 }
1998 }
1999 else
2000 {
2001 while (1)
2002 {
2003 shape = scm_cons (scm_list_2 (scm_car (ndim),
2004 scm_sum (scm_sum (scm_car (ndim),
2005 scm_length (row)),
2006 scm_from_int (-1))),
2007 shape);
2008 ndim = scm_cdr (ndim);
2009 if (scm_is_pair (ndim))
2010 row = scm_car (row);
2011 else
2012 break;
2013 }
0f2d19dd 2014 }
bfad4005 2015
f301dbf3 2016 ra = scm_make_typed_array (type, SCM_BOOL_F, scm_reverse_x (shape, SCM_EOL));
20930f28 2017
bfad4005 2018 if (scm_is_null (shape))
0f2d19dd
JB
2019 {
2020 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2021 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2022 return ra;
2023 }
2024 if (!SCM_ARRAYP (ra))
2025 {
20930f28 2026 size_t length = scm_c_generalized_vector_length (ra);
74014c46 2027 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
20930f28 2028 scm_c_generalized_vector_set_x (ra, k, SCM_CAR (lst));
0f2d19dd
JB
2029 return ra;
2030 }
2031 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2032 return ra;
2033 else
1afff620
KN
2034 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2035 scm_list_1 (lst));
0f2d19dd 2036}
1bbd0b84 2037#undef FUNC_NAME
0f2d19dd 2038
f301dbf3
MV
2039SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
2040 (SCM ndim, SCM lst),
2041 "Return an array with elements the same as those of @var{lst}.")
2042#define FUNC_NAME s_scm_list_to_array
2043{
2044 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
2045}
2046#undef FUNC_NAME
2047
0f2d19dd 2048static int
c014a02e 2049l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2050{
c014a02e
ML
2051 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2052 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2053 int ok = 1;
2054 if (n <= 0)
d2e53ed6 2055 return (scm_is_null (lst));
0f2d19dd
JB
2056 if (k < SCM_ARRAY_NDIM (ra) - 1)
2057 {
2058 while (n--)
2059 {
d2e53ed6 2060 if (!scm_is_pair (lst))
0f2d19dd
JB
2061 return 0;
2062 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2063 base += inc;
2064 lst = SCM_CDR (lst);
2065 }
d2e53ed6 2066 if (!scm_is_null (lst))
0f2d19dd
JB
2067 return 0;
2068 }
2069 else
2070 {
2071 while (n--)
2072 {
d2e53ed6 2073 if (!scm_is_pair (lst))
0f2d19dd 2074 return 0;
e11e83f3 2075 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), scm_from_ulong (base));
0f2d19dd
JB
2076 base += inc;
2077 lst = SCM_CDR (lst);
2078 }
d2e53ed6 2079 if (!scm_is_null (lst))
fee7ef83 2080 return 0;
0f2d19dd
JB
2081 }
2082 return ok;
2083}
2084
f301dbf3
MV
2085#if SCM_ENABLE_DEPRECATED
2086
2087SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
2088 (SCM ndim, SCM prot, SCM lst),
2089 "Return a uniform array of the type indicated by prototype\n"
2090 "@var{prot} with elements the same as those of @var{lst}.\n"
2091 "Elements must be of the appropriate type, no coercions are\n"
2092 "done.\n"
2093 "\n"
2094 "The argument @var{ndim} determines the number of dimensions\n"
2095 "of the array. It is either an exact integer, giving the\n"
2096 "number directly, or a list of exact integers, whose length\n"
2097 "specifies the number of dimensions and each element is the\n"
2098 "lower index bound of its dimension.")
2099#define FUNC_NAME s_scm_list_to_uniform_array
2100{
2101 return scm_list_to_typed_array (prototype_to_type (prot), ndim, lst);
2102}
2103#undef FUNC_NAME
2104
2105#endif
1cc91f1b 2106
e0e49670
MV
2107/* Print dimension DIM of ARRAY.
2108 */
0f2d19dd 2109
e0e49670 2110static int
02339e5b 2111scm_i_print_array_dimension (SCM array, int dim, int base, int enclosed,
e0e49670
MV
2112 SCM port, scm_print_state *pstate)
2113{
2114 scm_t_array_dim *dim_spec = SCM_ARRAY_DIMS (array) + dim;
2115 long idx;
2116
2117 scm_putc ('(', port);
2118
e0e49670
MV
2119 for (idx = dim_spec->lbnd; idx <= dim_spec->ubnd; idx++)
2120 {
2121 if (dim < SCM_ARRAY_NDIM(array)-1)
02339e5b
MV
2122 scm_i_print_array_dimension (array, dim+1, base, enclosed,
2123 port, pstate);
e0e49670 2124 else
02339e5b 2125 scm_iprin1 (scm_i_cvref (SCM_ARRAY_V (array), base, enclosed),
e0e49670
MV
2126 port, pstate);
2127 if (idx < dim_spec->ubnd)
2128 scm_putc (' ', port);
2129 base += dim_spec->inc;
2130 }
2131
2132 scm_putc (')', port);
2133 return 1;
2134}
2135
f301dbf3 2136/* Print an array. (Only for strict arrays, not for generalized vectors.)
e0e49670
MV
2137*/
2138
e0e49670
MV
2139static int
2140scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
2141{
2142 long ndim = SCM_ARRAY_NDIM (array);
2143 scm_t_array_dim *dim_specs = SCM_ARRAY_DIMS (array);
20930f28 2144 SCM v = SCM_ARRAY_V (array);
e0e49670
MV
2145 unsigned long base = SCM_ARRAY_BASE (array);
2146 long i;
2147
2148 scm_putc ('#', port);
c0fc64c8 2149 if (ndim != 1 || dim_specs[0].lbnd != 0)
e0e49670 2150 scm_intprint (ndim, 10, port);
20930f28
MV
2151 if (scm_is_uniform_vector (v))
2152 scm_puts (scm_i_uniform_vector_tag (v), port);
2153 else if (scm_is_bitvector (v))
2154 scm_puts ("b", port);
2155 else if (scm_is_string (v))
2156 scm_puts ("a", port);
2157 else if (!scm_is_vector (v))
2158 scm_puts ("?", port);
2159
e0e49670
MV
2160 for (i = 0; i < ndim; i++)
2161 if (dim_specs[i].lbnd != 0)
2162 {
2163 for (i = 0; i < ndim; i++)
2164 {
2165 scm_putc ('@', port);
2166 scm_uintprint (dim_specs[i].lbnd, 10, port);
2167 }
2168 break;
2169 }
2170
02339e5b
MV
2171 return scm_i_print_array_dimension (array, 0, base, 0, port, pstate);
2172}
2173
2174static int
2175scm_i_print_enclosed_array (SCM array, SCM port, scm_print_state *pstate)
2176{
2177 size_t base;
2178
2179 scm_putc ('#', port);
2180 base = SCM_ARRAY_BASE (array);
2181 scm_puts ("<enclosed-array ", port);
2182 scm_i_print_array_dimension (array, 0, base, 1, port, pstate);
2183 scm_putc ('>', port);
2184 return 1;
e0e49670 2185}
1cc91f1b 2186
bfad4005
MV
2187/* Read an array. This function can also read vectors and uniform
2188 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2189 handled here.
2190
2191 C is the first character read after the '#'.
2192*/
2193
bfad4005 2194static SCM
f301dbf3 2195tag_to_type (const char *tag, SCM port)
bfad4005 2196{
bfad4005
MV
2197#if SCM_ENABLE_DEPRECATED
2198 {
f301dbf3 2199 /* Recognize the old syntax.
bfad4005 2200 */
bfad4005
MV
2201 const char *instead;
2202 switch (tag[0])
2203 {
bfad4005 2204 case 'u':
bfad4005
MV
2205 instead = "u32";
2206 break;
2207 case 'e':
bfad4005
MV
2208 instead = "s32";
2209 break;
2210 case 's':
bfad4005
MV
2211 instead = "f32";
2212 break;
2213 case 'i':
bfad4005
MV
2214 instead = "f64";
2215 break;
2216 case 'y':
bfad4005
MV
2217 instead = "s8";
2218 break;
2219 case 'h':
bfad4005
MV
2220 instead = "s16";
2221 break;
2222 case 'l':
bfad4005
MV
2223 instead = "s64";
2224 break;
2225 case 'c':
72d05aa4
MV
2226 instead = "c64";
2227 break;
2228 default:
f301dbf3 2229 instead = NULL;
bfad4005
MV
2230 break;
2231 }
f301dbf3
MV
2232
2233 if (instead && tag[1] == '\0')
bfad4005
MV
2234 {
2235 scm_c_issue_deprecation_warning_fmt
2236 ("The tag '%c' is deprecated for uniform vectors. "
2237 "Use '%s' instead.", tag[0], instead);
f301dbf3 2238 return scm_from_locale_symbol (instead);
bfad4005
MV
2239 }
2240 }
2241#endif
2242
f301dbf3 2243 return scm_from_locale_symbol (tag);
bfad4005
MV
2244}
2245
2246SCM
2247scm_i_read_array (SCM port, int c)
2248{
2249 size_t rank;
2250 int got_rank;
2251 char tag[80];
2252 int tag_len;
2253
2254 SCM lower_bounds, elements;
2255
2256 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2257 the array code can not deal with zero-length dimensions yet, and
2258 we want to allow zero-length vectors, of course.
2259 */
2260 if (c == '(')
2261 {
2262 scm_ungetc (c, port);
2263 return scm_vector (scm_read (port));
2264 }
2265
2266 /* Disambiguate between '#f' and uniform floating point vectors.
2267 */
2268 if (c == 'f')
2269 {
2270 c = scm_getc (port);
2271 if (c != '3' && c != '6')
2272 {
2273 if (c != EOF)
2274 scm_ungetc (c, port);
2275 return SCM_BOOL_F;
2276 }
2277 rank = 1;
2278 got_rank = 1;
2279 tag[0] = 'f';
2280 tag_len = 1;
2281 goto continue_reading_tag;
2282 }
2283
2284 /* Read rank. We disallow arrays of rank zero since they do not
2285 seem to work reliably yet. */
2286 rank = 0;
2287 got_rank = 0;
2288 while ('0' <= c && c <= '9')
2289 {
2290 rank = 10*rank + c-'0';
2291 got_rank = 1;
2292 c = scm_getc (port);
2293 }
2294 if (!got_rank)
2295 rank = 1;
2296 else if (rank == 0)
2297 scm_i_input_error (NULL, port,
2298 "array rank must be positive", SCM_EOL);
2299
2300 /* Read tag. */
2301 tag_len = 0;
2302 continue_reading_tag:
2303 while (c != EOF && c != '(' && c != '@' && tag_len < 80)
2304 {
2305 tag[tag_len++] = c;
2306 c = scm_getc (port);
2307 }
2308 tag[tag_len] = '\0';
2309
2310 /* Read lower bounds. */
2311 lower_bounds = SCM_EOL;
2312 while (c == '@')
2313 {
2314 /* Yeah, right, we should use some ready-made integer parsing
2315 routine for this...
2316 */
2317
2318 long lbnd = 0;
2319 long sign = 1;
2320
2321 c = scm_getc (port);
2322 if (c == '-')
2323 {
2324 sign = -1;
2325 c = scm_getc (port);
2326 }
2327 while ('0' <= c && c <= '9')
2328 {
2329 lbnd = 10*lbnd + c-'0';
2330 c = scm_getc (port);
2331 }
2332 lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
2333 }
2334
2335 /* Read nested lists of elements.
2336 */
2337 if (c != '(')
2338 scm_i_input_error (NULL, port,
2339 "missing '(' in vector or array literal",
2340 SCM_EOL);
2341 scm_ungetc (c, port);
2342 elements = scm_read (port);
2343
2344 if (scm_is_null (lower_bounds))
2345 lower_bounds = scm_from_size_t (rank);
2346 else if (scm_ilength (lower_bounds) != rank)
2347 scm_i_input_error (NULL, port,
2348 "the number of lower bounds must match the array rank",
2349 SCM_EOL);
2350
2351 /* Construct array. */
f301dbf3
MV
2352 return scm_list_to_typed_array (tag_to_type (tag, port),
2353 lower_bounds,
2354 elements);
bfad4005
MV
2355}
2356
0f2d19dd 2357int
1bbd0b84 2358scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 2359{
02339e5b 2360 scm_iprin1 (exp, port, pstate);
0f2d19dd
JB
2361 return 1;
2362}
2363
f301dbf3 2364SCM_DEFINE (scm_array_type, "array-type", 1, 0, 0,
ab1be174 2365 (SCM ra),
f301dbf3
MV
2366 "")
2367#define FUNC_NAME s_scm_array_type
ab1be174 2368{
ab1be174 2369 if (SCM_ARRAYP (ra))
f301dbf3 2370 return scm_i_generalized_vector_type (SCM_ARRAY_V (ra));
02339e5b 2371 else if (scm_is_generalized_vector (ra))
f301dbf3 2372 return scm_i_generalized_vector_type (ra);
02339e5b
MV
2373 else if (SCM_ENCLOSED_ARRAYP (ra))
2374 scm_wrong_type_arg_msg (NULL, 0, ra, "non-enclosed array");
ab1be174 2375 else
02339e5b 2376 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
ab1be174
MV
2377}
2378#undef FUNC_NAME
2379
72d05aa4
MV
2380#if SCM_ENABLE_DEPRECATED
2381
3b3b36dd 2382SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2383 (SCM ra),
1e6808ea
MG
2384 "Return an object that would produce an array of the same type\n"
2385 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2386 "@code{make-uniform-array}.")
1bbd0b84 2387#define FUNC_NAME s_scm_array_prototype
0f2d19dd 2388{
20930f28 2389 if (SCM_ARRAYP (ra))
02339e5b 2390 return scm_i_get_old_prototype (SCM_ARRAY_V (ra));
20930f28
MV
2391 else if (scm_is_generalized_vector (ra))
2392 return scm_i_get_old_prototype (ra);
02339e5b
MV
2393 else if (SCM_ENCLOSED_ARRAYP (ra))
2394 return SCM_UNSPECIFIED;
20930f28
MV
2395 else
2396 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 2397}
1bbd0b84 2398#undef FUNC_NAME
0f2d19dd 2399
72d05aa4 2400#endif
1cc91f1b 2401
0f2d19dd 2402static SCM
e841c3e0 2403array_mark (SCM ptr)
0f2d19dd 2404{
0f2d19dd
JB
2405 return SCM_ARRAY_V (ptr);
2406}
2407
1be6b49c 2408static size_t
e841c3e0 2409array_free (SCM ptr)
0f2d19dd 2410{
4c9419ac
MV
2411 scm_gc_free (SCM_ARRAY_MEM (ptr),
2412 (sizeof (scm_t_array)
2413 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2414 "array");
2415 return 0;
0f2d19dd
JB
2416}
2417
0f2d19dd
JB
2418void
2419scm_init_unif ()
0f2d19dd 2420{
e841c3e0
KN
2421 scm_tc16_array = scm_make_smob_type ("array", 0);
2422 scm_set_smob_mark (scm_tc16_array, array_mark);
2423 scm_set_smob_free (scm_tc16_array, array_free);
02339e5b 2424 scm_set_smob_print (scm_tc16_array, scm_i_print_array);
e841c3e0 2425 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
02339e5b
MV
2426
2427 scm_tc16_enclosed_array = scm_make_smob_type ("enclosed-array", 0);
2428 scm_set_smob_mark (scm_tc16_enclosed_array, array_mark);
2429 scm_set_smob_free (scm_tc16_enclosed_array, array_free);
2430 scm_set_smob_print (scm_tc16_enclosed_array, scm_i_print_enclosed_array);
2431 scm_set_smob_equalp (scm_tc16_enclosed_array, scm_array_equal_p);
2432
0f2d19dd 2433 scm_add_feature ("array");
20930f28
MV
2434
2435 scm_tc16_bitvector = scm_make_smob_type ("bitvector", 0);
2436 scm_set_smob_free (scm_tc16_bitvector, bitvector_free);
2437 scm_set_smob_print (scm_tc16_bitvector, bitvector_print);
2438 scm_set_smob_equalp (scm_tc16_bitvector, bitvector_equalp);
2439
f301dbf3
MV
2440 init_type_creator_table ();
2441
a0599745 2442#include "libguile/unif.x"
bfad4005 2443
0f2d19dd 2444}
89e00824
ML
2445
2446/*
2447 Local Variables:
2448 c-file-style: "gnu"
2449 End:
2450*/