(scm_is_vector, scm_c_vector_length, scm_c_vector_ref,
[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;
7c183c95 83static SCM exactly_one_third;
0f2d19dd 84
85368844 85#if 0
bc86da5d
MD
86/* Silly function used not to modify the semantics of the silly
87 * prototype system in order to be backward compatible.
88 */
89static int
90singp (SCM obj)
0f2d19dd 91{
a08b0d00 92 if (!SCM_REALP (obj))
bc86da5d
MD
93 return 0;
94 else
95 {
96 double x = SCM_REAL_VALUE (obj);
97 float fx = x;
98 return (- SCM_FLTMAX < x) && (x < SCM_FLTMAX) && (fx == x);
99 }
0f2d19dd 100}
85368844 101#endif
1cc91f1b 102
bfad4005
MV
103static SCM scm_i_proc_make_vector;
104static SCM scm_i_proc_make_string;
105static SCM scm_i_proc_make_u1vector;
106
107#if SCM_ENABLE_DEPRECATED
108
109SCM_SYMBOL (scm_sym_s, "s");
110SCM_SYMBOL (scm_sym_l, "l");
111
112SCM scm_make_u1vector (SCM len, SCM fill);
113
114SCM_DEFINE (scm_make_u1vector, "make-u1vector", 1, 1, 0,
115 (SCM len, SCM fill),
116 "...")
117#define FUNC_NAME s_scm_make_u1vector
118{
119 long k = scm_to_long (len);
120 if (k > 0)
121 {
122 long i;
123 SCM_ASSERT_RANGE (1, scm_from_long (k),
124 k <= SCM_BITVECTOR_MAX_LENGTH);
125 i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
126 return scm_cell (SCM_MAKE_BITVECTOR_TAG (k),
127 (scm_t_bits) scm_gc_malloc (i, "vector"));
128 }
129 else
130 return scm_cell (SCM_MAKE_BITVECTOR_TAG (0), 0);
131}
132#undef FUNC_NAME
133
711a9fd7 134static SCM
bfad4005 135scm_i_convert_old_prototype (SCM proto)
711a9fd7 136{
bfad4005
MV
137 SCM new_proto;
138
139 /* All new 'prototypes' are creator procedures.
140 */
141 if (scm_is_true (scm_procedure_p (proto)))
142 return proto;
143
144 if (scm_is_eq (proto, SCM_BOOL_T))
145 new_proto = scm_i_proc_make_u1vector;
146 else if (scm_is_eq (proto, SCM_MAKE_CHAR ('a')))
147 new_proto = scm_i_proc_make_string;
148 else if (scm_is_eq (proto, SCM_MAKE_CHAR (0)))
149 new_proto = scm_i_proc_make_s8vector;
150 else if (scm_is_eq (proto, scm_sym_s))
151 new_proto = scm_i_proc_make_s16vector;
152 else if (scm_is_true (scm_eqv_p (proto, scm_from_int (1))))
153 new_proto = scm_i_proc_make_u32vector;
154 else if (scm_is_true (scm_eqv_p (proto, scm_from_int (-1))))
155 new_proto = scm_i_proc_make_s32vector;
156 else if (scm_is_eq (proto, scm_sym_l))
157 new_proto = scm_i_proc_make_s64vector;
158 else if (scm_is_true (scm_eqv_p (proto, scm_from_double (1.0))))
159 new_proto = scm_i_proc_make_f32vector;
160 else if (scm_is_true (scm_eqv_p (proto, scm_divide (scm_from_int (1),
161 scm_from_int (3)))))
162 new_proto = scm_i_proc_make_f64vector;
163 else if (scm_is_true (scm_eqv_p (proto, scm_c_make_rectangular (0, 1))))
164 new_proto = scm_i_proc_make_c64vector;
165 else if (scm_is_null (proto))
166 new_proto = scm_i_proc_make_vector;
167 else
168 new_proto = proto;
711a9fd7 169
bfad4005
MV
170 scm_c_issue_deprecation_warning
171 ("Using prototypes with arrays is deprecated. "
172 "Use creator functions instead.");
173
174 return new_proto;
711a9fd7 175}
bfad4005 176
ab1be174
MV
177static SCM
178scm_i_get_old_prototype (SCM uvec)
179{
180 if (SCM_BITVECTOR_P (uvec))
181 return SCM_BOOL_T;
182 else if (scm_is_string (uvec))
183 return SCM_MAKE_CHAR ('a');
184 else if (scm_is_true (scm_s8vector_p (uvec)))
185 return SCM_MAKE_CHAR ('\0');
186 else if (scm_is_true (scm_s16vector_p (uvec)))
187 return scm_sym_s;
188 else if (scm_is_true (scm_u32vector_p (uvec)))
189 return scm_from_int (1);
190 else if (scm_is_true (scm_s32vector_p (uvec)))
191 return scm_from_int (-1);
192 else if (scm_is_true (scm_s64vector_p (uvec)))
193 return scm_sym_l;
194 else if (scm_is_true (scm_f32vector_p (uvec)))
195 return scm_from_double (1.0);
196 else if (scm_is_true (scm_f64vector_p (uvec)))
197 return scm_divide (scm_from_int (1), scm_from_int (3));
198 else if (scm_is_true (scm_c64vector_p (uvec)))
199 return scm_c_make_rectangular (0, 1);
200 else if (scm_is_true (scm_vector_p (uvec)))
201 return SCM_EOL;
202 else
203 return SCM_UNSPECIFIED;
204}
205
bfad4005 206#endif
711a9fd7 207
0f2d19dd 208SCM
c014a02e 209scm_make_uve (long k, SCM prot)
a3a32939 210#define FUNC_NAME "scm_make_uve"
0f2d19dd 211{
bfad4005
MV
212#if SCM_ENABLE_DEPRECATED
213 prot = scm_i_convert_old_prototype (prot);
0f2d19dd 214#endif
ab1be174 215 return scm_call_1 (prot, scm_from_long (k));
0f2d19dd 216}
a3a32939
DH
217#undef FUNC_NAME
218
3b3b36dd 219SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
1bbd0b84 220 (SCM v, SCM prot),
1e6808ea
MG
221 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
222 "not. The @var{prototype} argument is used with uniform arrays\n"
223 "and is described elsewhere.")
1bbd0b84 224#define FUNC_NAME s_scm_array_p
0f2d19dd
JB
225{
226 int nprot;
227 int enclosed;
228 nprot = SCM_UNBNDP (prot);
229 enclosed = 0;
230 if (SCM_IMP (v))
231 return SCM_BOOL_F;
c209c88e 232
e0e49670 233 while (SCM_ARRAYP (v))
0f2d19dd 234 {
0f2d19dd
JB
235 if (nprot)
236 return SCM_BOOL_T;
237 if (enclosed++)
238 return SCM_BOOL_F;
239 v = SCM_ARRAY_V (v);
e0e49670
MV
240 }
241
bfad4005
MV
242 /* XXX - clean up
243 */
e0e49670
MV
244 if (scm_is_uniform_vector (v))
245 {
246 if (nprot)
247 return SCM_BOOL_T;
248 else
bfad4005
MV
249 {
250#if SCM_ENABLE_DEPRECATED
251 prot = scm_i_convert_old_prototype (prot);
252#endif
253 return scm_eq_p (prot, scm_i_uniform_vector_creator (v));
254 }
255 }
256 else if (scm_is_true (scm_vector_p (v)))
257 {
258 if (nprot)
259 return SCM_BOOL_T;
260 else
261 {
262#if SCM_ENABLE_DEPRECATED
263 prot = scm_i_convert_old_prototype (prot);
264#endif
265 return scm_eq_p (prot, scm_i_proc_make_vector);
266 }
e0e49670 267 }
9b0018a1 268
c209c88e 269 if (nprot)
9b0018a1
MV
270 {
271 switch (SCM_TYP7 (v))
272 {
273 case scm_tc7_bvect:
274 case scm_tc7_string:
9b0018a1
MV
275 case scm_tc7_vector:
276 case scm_tc7_wvect:
277 return SCM_BOOL_T;
278 default:
279 return SCM_BOOL_F;
280 }
281 }
c209c88e
GB
282 else
283 {
284 int protp = 0;
e0e49670 285
c209c88e
GB
286 switch (SCM_TYP7 (v))
287 {
288 case scm_tc7_bvect:
bc36d050 289 protp = (scm_is_eq (prot, SCM_BOOL_T));
7c183c95 290 break;
c209c88e 291 case scm_tc7_string:
4260a7fc 292 protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
7c183c95 293 break;
c209c88e
GB
294 case scm_tc7_vector:
295 case scm_tc7_wvect:
d2e53ed6 296 protp = scm_is_null(prot);
7c183c95 297 break;
c209c88e
GB
298 default:
299 /* no default */
300 ;
301 }
7888309b 302 return scm_from_bool(protp);
0f2d19dd 303 }
0f2d19dd 304}
1bbd0b84 305#undef FUNC_NAME
0f2d19dd
JB
306
307
3b3b36dd 308SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
1bbd0b84 309 (SCM ra),
1e6808ea
MG
310 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
311 "not an array, @code{0} is returned.")
1bbd0b84 312#define FUNC_NAME s_scm_array_rank
0f2d19dd 313{
e0e49670
MV
314 if (scm_is_uniform_vector (ra))
315 return scm_from_int (1);
316
0f2d19dd 317 if (SCM_IMP (ra))
1bbd0b84 318 return SCM_INUM0;
0f2d19dd
JB
319 switch (SCM_TYP7 (ra))
320 {
321 default:
322 return SCM_INUM0;
323 case scm_tc7_string:
324 case scm_tc7_vector:
95f5b0f5 325 case scm_tc7_wvect:
e11e83f3 326 return scm_from_int (1);
0f2d19dd
JB
327 case scm_tc7_smob:
328 if (SCM_ARRAYP (ra))
e11e83f3 329 return scm_from_size_t (SCM_ARRAY_NDIM (ra));
0f2d19dd
JB
330 return SCM_INUM0;
331 }
332}
1bbd0b84 333#undef FUNC_NAME
0f2d19dd
JB
334
335
3b3b36dd 336SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 337 (SCM ra),
b380b885
MD
338 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
339 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
1e6808ea 340 "@lisp\n"
b380b885 341 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
1e6808ea 342 "@end lisp")
1bbd0b84 343#define FUNC_NAME s_scm_array_dimensions
0f2d19dd
JB
344{
345 SCM res = SCM_EOL;
1be6b49c 346 size_t k;
92c2555f 347 scm_t_array_dim *s;
0f2d19dd 348 if (SCM_IMP (ra))
1bbd0b84 349 return SCM_BOOL_F;
e0e49670
MV
350
351 if (scm_is_uniform_vector (ra))
352 return scm_cons (scm_uniform_vector_length (ra), SCM_EOL);
353
0f2d19dd
JB
354 switch (SCM_TYP7 (ra))
355 {
356 default:
357 return SCM_BOOL_F;
358 case scm_tc7_string:
359 case scm_tc7_vector:
95f5b0f5 360 case scm_tc7_wvect:
0f2d19dd 361 case scm_tc7_bvect:
74014c46 362 return scm_cons (scm_uniform_vector_length (ra), SCM_EOL);
0f2d19dd
JB
363 case scm_tc7_smob:
364 if (!SCM_ARRAYP (ra))
365 return SCM_BOOL_F;
366 k = SCM_ARRAY_NDIM (ra);
367 s = SCM_ARRAY_DIMS (ra);
368 while (k--)
e2d37336 369 res = scm_cons (s[k].lbnd
e11e83f3
MV
370 ? scm_cons2 (scm_from_long (s[k].lbnd),
371 scm_from_long (s[k].ubnd),
e2d37336 372 SCM_EOL)
e11e83f3 373 : scm_from_long (1 + s[k].ubnd),
e2d37336 374 res);
0f2d19dd
JB
375 return res;
376 }
377}
1bbd0b84 378#undef FUNC_NAME
0f2d19dd
JB
379
380
e2d37336
MD
381SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
382 (SCM ra),
383 "Return the root vector of a shared array.")
384#define FUNC_NAME s_scm_shared_array_root
385{
386 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
387 return SCM_ARRAY_V (ra);
388}
389#undef FUNC_NAME
390
391
392SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
393 (SCM ra),
394 "Return the root vector index of the first element in the array.")
395#define FUNC_NAME s_scm_shared_array_offset
396{
397 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
e11e83f3 398 return scm_from_int (SCM_ARRAY_BASE (ra));
e2d37336
MD
399}
400#undef FUNC_NAME
401
402
403SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
404 (SCM ra),
405 "For each dimension, return the distance between elements in the root vector.")
406#define FUNC_NAME s_scm_shared_array_increments
407{
408 SCM res = SCM_EOL;
1be6b49c 409 size_t k;
92c2555f 410 scm_t_array_dim *s;
e2d37336
MD
411 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
412 k = SCM_ARRAY_NDIM (ra);
413 s = SCM_ARRAY_DIMS (ra);
414 while (k--)
e11e83f3 415 res = scm_cons (scm_from_long (s[k].inc), res);
e2d37336
MD
416 return res;
417}
418#undef FUNC_NAME
419
420
0f2d19dd
JB
421static char s_bad_ind[] = "Bad scm_array index";
422
1cc91f1b 423
c014a02e 424long
1bbd0b84 425scm_aind (SCM ra, SCM args, const char *what)
b3fcac34 426#define FUNC_NAME what
0f2d19dd
JB
427{
428 SCM ind;
c014a02e
ML
429 register long j;
430 register unsigned long pos = SCM_ARRAY_BASE (ra);
431 register unsigned long k = SCM_ARRAY_NDIM (ra);
92c2555f 432 scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
e11e83f3 433 if (scm_is_integer (args))
0f2d19dd 434 {
b3fcac34
DH
435 if (k != 1)
436 scm_error_num_args_subr (what);
e11e83f3 437 return pos + (scm_to_long (args) - s->lbnd) * (s->inc);
0f2d19dd 438 }
d2e53ed6 439 while (k && scm_is_pair (args))
0f2d19dd
JB
440 {
441 ind = SCM_CAR (args);
442 args = SCM_CDR (args);
e11e83f3 443 if (!scm_is_integer (ind))
b3fcac34 444 scm_misc_error (what, s_bad_ind, SCM_EOL);
e11e83f3 445 j = scm_to_long (ind);
685c0d71
DH
446 if (j < s->lbnd || j > s->ubnd)
447 scm_out_of_range (what, ind);
0f2d19dd
JB
448 pos += (j - s->lbnd) * (s->inc);
449 k--;
450 s++;
451 }
d2e53ed6 452 if (k != 0 || !scm_is_null (args))
b3fcac34
DH
453 scm_error_num_args_subr (what);
454
0f2d19dd
JB
455 return pos;
456}
b3fcac34 457#undef FUNC_NAME
0f2d19dd 458
1cc91f1b 459
0f2d19dd 460SCM
1bbd0b84 461scm_make_ra (int ndim)
0f2d19dd
JB
462{
463 SCM ra;
0f2d19dd 464 SCM_DEFER_INTS;
92c2555f 465 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + scm_tc16_array,
4c9419ac
MV
466 scm_gc_malloc ((sizeof (scm_t_array) +
467 ndim * sizeof (scm_t_array_dim)),
468 "array"));
0f2d19dd
JB
469 SCM_ARRAY_V (ra) = scm_nullvect;
470 SCM_ALLOW_INTS;
471 return ra;
472}
473
474static char s_bad_spec[] = "Bad scm_array dimension";
475/* Increments will still need to be set. */
476
1cc91f1b 477
0f2d19dd 478SCM
1bbd0b84 479scm_shap2ra (SCM args, const char *what)
0f2d19dd 480{
92c2555f 481 scm_t_array_dim *s;
0f2d19dd
JB
482 SCM ra, spec, sp;
483 int ndim = scm_ilength (args);
b3fcac34
DH
484 if (ndim < 0)
485 scm_misc_error (what, s_bad_spec, SCM_EOL);
486
0f2d19dd
JB
487 ra = scm_make_ra (ndim);
488 SCM_ARRAY_BASE (ra) = 0;
489 s = SCM_ARRAY_DIMS (ra);
d2e53ed6 490 for (; !scm_is_null (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
491 {
492 spec = SCM_CAR (args);
e11e83f3 493 if (scm_is_integer (spec))
0f2d19dd 494 {
e11e83f3 495 if (scm_to_long (spec) < 0)
b3fcac34 496 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd 497 s->lbnd = 0;
e11e83f3 498 s->ubnd = scm_to_long (spec) - 1;
0f2d19dd
JB
499 s->inc = 1;
500 }
501 else
502 {
d2e53ed6 503 if (!scm_is_pair (spec) || !scm_is_integer (SCM_CAR (spec)))
b3fcac34 504 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 505 s->lbnd = scm_to_long (SCM_CAR (spec));
0f2d19dd 506 sp = SCM_CDR (spec);
d2e53ed6 507 if (!scm_is_pair (sp)
e11e83f3 508 || !scm_is_integer (SCM_CAR (sp))
d2e53ed6 509 || !scm_is_null (SCM_CDR (sp)))
b3fcac34 510 scm_misc_error (what, s_bad_spec, SCM_EOL);
e11e83f3 511 s->ubnd = scm_to_long (SCM_CAR (sp));
0f2d19dd
JB
512 s->inc = 1;
513 }
514 }
515 return ra;
516}
517
3b3b36dd 518SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
1e6808ea 519 (SCM dims, SCM prot, SCM fill),
8f85c0c6 520 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
1e6808ea
MG
521 "Create and return a uniform array or vector of type\n"
522 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
523 "length @var{length}. If @var{fill} is supplied, it's used to\n"
524 "fill the array, otherwise @var{prototype} is used.")
1bbd0b84 525#define FUNC_NAME s_scm_dimensions_to_uniform_array
0f2d19dd 526{
1be6b49c 527 size_t k;
c014a02e 528 unsigned long rlen = 1;
92c2555f 529 scm_t_array_dim *s;
0f2d19dd 530 SCM ra;
1be6b49c 531
e11e83f3 532 if (scm_is_integer (dims))
cda139a7 533 {
e11e83f3 534 SCM answer = scm_make_uve (scm_to_long (dims), prot);
a3a32939
DH
535 if (!SCM_UNBNDP (fill))
536 scm_array_fill_x (answer, fill);
e0e49670 537 else if (scm_is_symbol (prot) || scm_is_eq (prot, SCM_MAKE_CHAR (0)))
e11e83f3 538 scm_array_fill_x (answer, scm_from_int (0));
bfad4005 539 else if (scm_is_false (scm_procedure_p (prot)))
a3a32939
DH
540 scm_array_fill_x (answer, prot);
541 return answer;
cda139a7 542 }
1be6b49c 543
d2e53ed6 544 SCM_ASSERT (scm_is_null (dims) || scm_is_pair (dims),
0c95b57d 545 dims, SCM_ARG1, FUNC_NAME);
1bbd0b84 546 ra = scm_shap2ra (dims, FUNC_NAME);
e038c042 547 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
548 s = SCM_ARRAY_DIMS (ra);
549 k = SCM_ARRAY_NDIM (ra);
1be6b49c 550
0f2d19dd
JB
551 while (k--)
552 {
a3a32939
DH
553 s[k].inc = rlen;
554 SCM_ASSERT_RANGE (1, dims, s[k].lbnd <= s[k].ubnd);
0f2d19dd 555 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 556 }
a3a32939 557
a3a32939
DH
558 SCM_ARRAY_V (ra) = scm_make_uve (rlen, prot);
559
5c11cc9d 560 if (!SCM_UNBNDP (fill))
a3a32939 561 scm_array_fill_x (ra, fill);
e0e49670 562 else if (scm_is_symbol (prot) || scm_is_eq (prot, SCM_MAKE_CHAR (0)))
e11e83f3 563 scm_array_fill_x (ra, scm_from_int (0));
bfad4005 564 else if (scm_is_false (scm_procedure_p (prot)))
0f2d19dd 565 scm_array_fill_x (ra, prot);
a3a32939 566
0f2d19dd 567 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
c014a02e 568 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
0f2d19dd
JB
569 return SCM_ARRAY_V (ra);
570 return ra;
571}
1bbd0b84 572#undef FUNC_NAME
0f2d19dd 573
1cc91f1b 574
0f2d19dd 575void
1bbd0b84 576scm_ra_set_contp (SCM ra)
0f2d19dd 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;
e11e83f3 645 old_max = scm_to_long (scm_uniform_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))
655 ra = scm_make_uve (0L, scm_array_prototype (ra));
656 else
657 SCM_ARRAY_V (ra) = scm_make_uve (0L, scm_array_prototype (ra));
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
JB
714 if (s->ubnd < s->lbnd)
715 return scm_make_uve (0L, scm_array_prototype (ra));
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
MV
754
755 if (scm_is_uniform_vector (ra))
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
f5bf2977 767 switch (SCM_TYP7 (ra))
0f2d19dd
JB
768 {
769 default:
276dd677 770 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
771 case scm_tc7_bvect:
772 case scm_tc7_string:
d2e53ed6 773 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
b3fcac34 774 SCM_WRONG_NUM_ARGS ();
a55c2b68
MV
775 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
776 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
0f2d19dd
JB
777 return ra;
778 case scm_tc7_smob:
779 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
780 vargs = scm_vector (args);
b3fcac34
DH
781 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
782 SCM_WRONG_NUM_ARGS ();
783 ve = SCM_VELTS (vargs);
0f2d19dd
JB
784 ndim = 0;
785 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
786 {
e11e83f3 787 i = scm_to_signed_integer (ve[k], 0, SCM_ARRAY_NDIM(ra));
0f2d19dd
JB
788 if (ndim < i)
789 ndim = i;
790 }
791 ndim++;
792 res = scm_make_ra (ndim);
793 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
794 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
795 for (k = ndim; k--;)
796 {
797 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
798 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
799 }
800 for (k = SCM_ARRAY_NDIM (ra); k--;)
801 {
e11e83f3 802 i = scm_to_int (ve[k]);
0f2d19dd
JB
803 s = &(SCM_ARRAY_DIMS (ra)[k]);
804 r = &(SCM_ARRAY_DIMS (res)[i]);
805 if (r->ubnd < r->lbnd)
806 {
807 r->lbnd = s->lbnd;
808 r->ubnd = s->ubnd;
809 r->inc = s->inc;
810 ndim--;
811 }
812 else
813 {
814 if (r->ubnd > s->ubnd)
815 r->ubnd = s->ubnd;
816 if (r->lbnd < s->lbnd)
817 {
818 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
819 r->lbnd = s->lbnd;
820 }
821 r->inc += s->inc;
822 }
823 }
b3fcac34
DH
824 if (ndim > 0)
825 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
826 scm_ra_set_contp (res);
827 return res;
828 }
829}
1bbd0b84 830#undef FUNC_NAME
0f2d19dd
JB
831
832/* args are RA . AXES */
af45e3b0
DH
833SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
834 (SCM ra, SCM axes),
b380b885
MD
835 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
836 "the rank of @var{array}. @var{enclose-array} returns an array\n"
837 "resembling an array of shared arrays. The dimensions of each shared\n"
838 "array are the same as the @var{dim}th dimensions of the original array,\n"
839 "the dimensions of the outer array are the same as those of the original\n"
840 "array that did not match a @var{dim}.\n\n"
841 "An enclosed array is not a general Scheme array. Its elements may not\n"
842 "be set using @code{array-set!}. Two references to the same element of\n"
843 "an enclosed array will be @code{equal?} but will not in general be\n"
844 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
845 "enclosed array is unspecified.\n\n"
846 "examples:\n"
1e6808ea 847 "@lisp\n"
b380b885
MD
848 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
849 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
850 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
851 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 852 "@end lisp")
1bbd0b84 853#define FUNC_NAME s_scm_enclose_array
0f2d19dd 854{
af45e3b0 855 SCM axv, res, ra_inr;
cc95e00a 856 const char *c_axv;
92c2555f 857 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 858 int ndim, j, k, ninr, noutr;
af45e3b0 859
b3fcac34 860 SCM_VALIDATE_REST_ARGUMENT (axes);
d2e53ed6 861 if (scm_is_null (axes))
e11e83f3 862 axes = scm_cons ((SCM_ARRAYP (ra) ? scm_from_size_t (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
0f2d19dd 863 ninr = scm_ilength (axes);
b3fcac34
DH
864 if (ninr < 0)
865 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
866 ra_inr = scm_make_ra (ninr);
867 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
e0e49670
MV
868
869 if (scm_is_uniform_vector (ra))
870 goto uniform_vector;
871
74014c46 872 switch SCM_TYP7 (ra)
0f2d19dd
JB
873 {
874 default:
276dd677 875 badarg1:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
876 case scm_tc7_string:
877 case scm_tc7_bvect:
0f2d19dd 878 case scm_tc7_vector:
95f5b0f5 879 case scm_tc7_wvect:
e0e49670 880 uniform_vector:
0f2d19dd 881 s->lbnd = 0;
e11e83f3 882 s->ubnd = scm_to_long (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
883 s->inc = 1;
884 SCM_ARRAY_V (ra_inr) = ra;
885 SCM_ARRAY_BASE (ra_inr) = 0;
886 ndim = 1;
887 break;
888 case scm_tc7_smob:
889 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
890 s = SCM_ARRAY_DIMS (ra);
891 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
892 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
893 ndim = SCM_ARRAY_NDIM (ra);
894 break;
895 }
896 noutr = ndim - ninr;
b3fcac34
DH
897 if (noutr < 0)
898 SCM_WRONG_NUM_ARGS ();
e11e83f3 899 axv = scm_make_string (scm_from_int (ndim), SCM_MAKE_CHAR (0));
0f2d19dd
JB
900 res = scm_make_ra (noutr);
901 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
902 SCM_ARRAY_V (res) = ra_inr;
903 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
904 {
e11e83f3 905 if (!scm_is_integer (SCM_CAR (axes)))
b3fcac34 906 SCM_MISC_ERROR ("bad axis", SCM_EOL);
e11e83f3 907 j = scm_to_int (SCM_CAR (axes));
0f2d19dd
JB
908 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
909 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
910 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
cc95e00a 911 scm_c_string_set_x (axv, j, SCM_MAKE_CHAR (1));
0f2d19dd 912 }
cc95e00a 913 c_axv = scm_i_string_chars (axv);
0f2d19dd
JB
914 for (j = 0, k = 0; k < noutr; k++, j++)
915 {
cc95e00a 916 while (c_axv[j])
0f2d19dd
JB
917 j++;
918 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
919 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
920 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
921 }
cc95e00a 922 scm_remember_upto_here_1 (axv);
0f2d19dd
JB
923 scm_ra_set_contp (ra_inr);
924 scm_ra_set_contp (res);
925 return res;
926}
1bbd0b84 927#undef FUNC_NAME
0f2d19dd
JB
928
929
930
af45e3b0
DH
931SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
932 (SCM v, SCM args),
1e6808ea
MG
933 "Return @code{#t} if its arguments would be acceptable to\n"
934 "@code{array-ref}.")
1bbd0b84 935#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 936{
af45e3b0 937 SCM ind = SCM_EOL;
c014a02e 938 long pos = 0;
1be6b49c 939 register size_t k;
c014a02e 940 register long j;
92c2555f 941 scm_t_array_dim *s;
af45e3b0 942
b3fcac34 943 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
944 SCM_ASRTGO (SCM_NIMP (v), badarg1);
945 if (SCM_NIMP (args))
946
947 {
948 ind = SCM_CAR (args);
949 args = SCM_CDR (args);
e11e83f3 950 pos = scm_to_long (ind);
0f2d19dd
JB
951 }
952tail:
e0e49670
MV
953
954 if (scm_is_uniform_vector (v))
955 goto uniform_vector;
956
74014c46 957 switch SCM_TYP7 (v)
0f2d19dd
JB
958 {
959 default:
276dd677 960 badarg1:SCM_WRONG_TYPE_ARG (1, v);
b3fcac34 961 wna: SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
962 case scm_tc7_smob:
963 k = SCM_ARRAY_NDIM (v);
964 s = SCM_ARRAY_DIMS (v);
965 pos = SCM_ARRAY_BASE (v);
966 if (!k)
967 {
d2e53ed6 968 SCM_ASRTGO (scm_is_null (ind), wna);
0f2d19dd
JB
969 ind = SCM_INUM0;
970 }
971 else
972 while (!0)
973 {
e11e83f3 974 j = scm_to_long (ind);
0f2d19dd
JB
975 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
976 {
977 SCM_ASRTGO (--k == scm_ilength (args), wna);
978 return SCM_BOOL_F;
979 }
980 pos += (j - s->lbnd) * (s->inc);
981 if (!(--k && SCM_NIMP (args)))
982 break;
983 ind = SCM_CAR (args);
984 args = SCM_CDR (args);
985 s++;
e11e83f3 986 if (!scm_is_integer (ind))
b3fcac34 987 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
988 }
989 SCM_ASRTGO (0 == k, wna);
990 v = SCM_ARRAY_V (v);
991 goto tail;
992 case scm_tc7_bvect:
993 case scm_tc7_string:
0f2d19dd 994 case scm_tc7_vector:
95f5b0f5 995 case scm_tc7_wvect:
e0e49670 996 uniform_vector:
74014c46 997 {
e11e83f3 998 unsigned long length = scm_to_ulong (scm_uniform_vector_length (v));
d2e53ed6 999 SCM_ASRTGO (scm_is_null (args) && scm_is_integer (ind), wna);
7888309b 1000 return scm_from_bool(pos >= 0 && pos < length);
74014c46 1001 }
0f2d19dd
JB
1002 }
1003}
1bbd0b84 1004#undef FUNC_NAME
0f2d19dd
JB
1005
1006
e0e49670 1007SCM_DEFINE (scm_array_ref, "array-ref", 1, 0, 1,
1bbd0b84 1008 (SCM v, SCM args),
1e6808ea
MG
1009 "Return the element at the @code{(index1, index2)} element in\n"
1010 "@var{array}.")
e0e49670 1011#define FUNC_NAME s_scm_array_ref
0f2d19dd 1012{
c014a02e 1013 long pos;
0f2d19dd 1014
35de7ebe 1015 if (SCM_IMP (v))
0f2d19dd 1016 {
d2e53ed6 1017 SCM_ASRTGO (scm_is_null (args), badarg);
0f2d19dd
JB
1018 return v;
1019 }
1020 else if (SCM_ARRAYP (v))
0f2d19dd 1021 {
1bbd0b84 1022 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1023 v = SCM_ARRAY_V (v);
1024 }
1025 else
1026 {
c014a02e 1027 unsigned long int length;
0f2d19dd 1028 if (SCM_NIMP (args))
0f2d19dd 1029 {
d2e53ed6 1030 SCM_ASSERT (scm_is_pair (args), args, SCM_ARG2, FUNC_NAME);
e11e83f3 1031 pos = scm_to_long (SCM_CAR (args));
d2e53ed6 1032 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
0f2d19dd
JB
1033 }
1034 else
1035 {
a55c2b68 1036 pos = scm_to_long (args);
0f2d19dd 1037 }
e11e83f3 1038 length = scm_to_ulong (scm_uniform_vector_length (v));
74014c46 1039 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1040 }
e0e49670
MV
1041
1042 if (scm_is_uniform_vector (v))
1043 return scm_uniform_vector_ref (v, scm_from_long (pos));
1044
74014c46 1045 switch SCM_TYP7 (v)
0f2d19dd
JB
1046 {
1047 default:
d2e53ed6 1048 if (scm_is_null (args))
0f2d19dd 1049 return v;
35de7ebe 1050 badarg:
276dd677
DH
1051 SCM_WRONG_TYPE_ARG (1, v);
1052 /* not reached */
c209c88e
GB
1053
1054 outrng:
e11e83f3 1055 scm_out_of_range (FUNC_NAME, scm_from_long (pos));
c209c88e 1056 wna:
b3fcac34 1057 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1058 case scm_tc7_smob:
1059 { /* enclosed */
1060 int k = SCM_ARRAY_NDIM (v);
1061 SCM res = scm_make_ra (k);
1062 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1063 SCM_ARRAY_BASE (res) = pos;
1064 while (k--)
1065 {
1066 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1067 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1068 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1069 }
1070 return res;
1071 }
1072 case scm_tc7_bvect:
c209c88e 1073 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1074 return SCM_BOOL_T;
1075 else
1076 return SCM_BOOL_F;
1077 case scm_tc7_string:
cc95e00a 1078 return scm_c_string_ref (v, pos);
0f2d19dd 1079 case scm_tc7_vector:
95f5b0f5 1080 case scm_tc7_wvect:
0f2d19dd
JB
1081 return SCM_VELTS (v)[pos];
1082 }
1083}
1bbd0b84 1084#undef FUNC_NAME
0f2d19dd
JB
1085
1086/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1087 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1088
0f2d19dd 1089SCM
c014a02e 1090scm_cvref (SCM v, unsigned long pos, SCM last)
db4b4ca6 1091#define FUNC_NAME "scm_cvref"
0f2d19dd 1092{
e0e49670
MV
1093 if (scm_is_uniform_vector (v))
1094 return scm_uniform_vector_ref (v, scm_from_ulong (pos));
1095
5c11cc9d 1096 switch SCM_TYP7 (v)
0f2d19dd
JB
1097 {
1098 default:
db4b4ca6 1099 SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd 1100 case scm_tc7_bvect:
34d19ef6 1101 if (SCM_BITVEC_REF(v, pos))
0f2d19dd
JB
1102 return SCM_BOOL_T;
1103 else
1104 return SCM_BOOL_F;
1105 case scm_tc7_string:
cc95e00a 1106 return scm_c_string_ref (v, pos);
0f2d19dd 1107 case scm_tc7_vector:
95f5b0f5 1108 case scm_tc7_wvect:
0f2d19dd
JB
1109 return SCM_VELTS (v)[pos];
1110 case scm_tc7_smob:
1111 { /* enclosed scm_array */
1112 int k = SCM_ARRAY_NDIM (v);
1113 SCM res = scm_make_ra (k);
1114 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1115 SCM_ARRAY_BASE (res) = pos;
1116 while (k--)
1117 {
1118 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1119 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1120 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1121 }
1122 return res;
1123 }
1124 }
1125}
db4b4ca6
DH
1126#undef FUNC_NAME
1127
0f2d19dd 1128
1bbd0b84
GB
1129SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1130
1cc91f1b 1131
0aa0871f
GH
1132/* Note that args may be a list or an immediate object, depending which
1133 PROC is used (and it's called from C too). */
3b3b36dd 1134SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1135 (SCM v, SCM obj, SCM args),
8f85c0c6
NJ
1136 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1137 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1138 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1139#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1140{
c014a02e 1141 long pos = 0;
b3fcac34 1142
0f2d19dd
JB
1143 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1144 if (SCM_ARRAYP (v))
0f2d19dd 1145 {
1bbd0b84 1146 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1147 v = SCM_ARRAY_V (v);
1148 }
1149 else
1150 {
c014a02e 1151 unsigned long int length;
d2e53ed6 1152 if (scm_is_pair (args))
0f2d19dd 1153 {
d2e53ed6 1154 SCM_ASRTGO (scm_is_null (SCM_CDR (args)), wna);
e11e83f3 1155 pos = scm_to_long (SCM_CAR (args));
0f2d19dd
JB
1156 }
1157 else
1158 {
a55c2b68 1159 pos = scm_to_long (args);
0f2d19dd 1160 }
e11e83f3 1161 length = scm_to_ulong (scm_uniform_vector_length (v));
74014c46 1162 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1163 }
e0e49670
MV
1164
1165 if (scm_is_uniform_vector (v))
1166 return scm_uniform_vector_set_x (v, scm_from_long (pos), obj);
1167
0f2d19dd
JB
1168 switch (SCM_TYP7 (v))
1169 {
35de7ebe 1170 default: badarg1:
276dd677
DH
1171 SCM_WRONG_TYPE_ARG (1, v);
1172 /* not reached */
c209c88e 1173 outrng:
e11e83f3 1174 scm_out_of_range (FUNC_NAME, scm_from_long (pos));
c209c88e 1175 wna:
b3fcac34 1176 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1177 case scm_tc7_smob: /* enclosed */
1178 goto badarg1;
1179 case scm_tc7_bvect:
7888309b 1180 if (scm_is_false (obj))
34d19ef6 1181 SCM_BITVEC_CLR(v, pos);
bc36d050 1182 else if (scm_is_eq (obj, SCM_BOOL_T))
34d19ef6 1183 SCM_BITVEC_SET(v, pos);
0f2d19dd 1184 else
276dd677 1185 badobj:SCM_WRONG_TYPE_ARG (2, obj);
0f2d19dd
JB
1186 break;
1187 case scm_tc7_string:
7866a09b 1188 SCM_ASRTGO (SCM_CHARP (obj), badobj);
cc95e00a 1189 scm_c_string_set_x (v, pos, obj);
0f2d19dd 1190 break;
0f2d19dd 1191 case scm_tc7_vector:
95f5b0f5 1192 case scm_tc7_wvect:
34d19ef6 1193 SCM_VECTOR_SET (v, pos, obj);
0f2d19dd
JB
1194 break;
1195 }
1196 return SCM_UNSPECIFIED;
1197}
1bbd0b84 1198#undef FUNC_NAME
0f2d19dd 1199
1d7bdb25
GH
1200/* attempts to unroll an array into a one-dimensional array.
1201 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1202 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1203 wouldn't have contiguous elements. */
3b3b36dd 1204SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1205 (SCM ra, SCM strict),
b380b885
MD
1206 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1207 "without changing their order (last subscript changing fastest), then\n"
1208 "@code{array-contents} returns that shared array, otherwise it returns\n"
1209 "@code{#f}. All arrays made by @var{make-array} and\n"
1210 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1211 "@var{make-shared-array} may not be.\n\n"
1212 "If the optional argument @var{strict} is provided, a shared array will\n"
1213 "be returned only if its elements are stored internally contiguous in\n"
1214 "memory.")
1bbd0b84 1215#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1216{
1217 SCM sra;
e0e49670
MV
1218
1219 if (scm_is_uniform_vector (ra))
1220 return ra;
1221
0f2d19dd 1222 if (SCM_IMP (ra))
f3667f52 1223 return SCM_BOOL_F;
e0e49670 1224
5c11cc9d 1225 switch SCM_TYP7 (ra)
0f2d19dd
JB
1226 {
1227 default:
1228 return SCM_BOOL_F;
1229 case scm_tc7_vector:
95f5b0f5 1230 case scm_tc7_wvect:
0f2d19dd
JB
1231 case scm_tc7_string:
1232 case scm_tc7_bvect:
0f2d19dd
JB
1233 return ra;
1234 case scm_tc7_smob:
1235 {
c014a02e 1236 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
0f2d19dd
JB
1237 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1238 return SCM_BOOL_F;
1239 for (k = 0; k < ndim; k++)
1240 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1241 if (!SCM_UNBNDP (strict))
1242 {
0f2d19dd
JB
1243 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1244 return SCM_BOOL_F;
1245 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1246 {
74014c46 1247 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
c014a02e
ML
1248 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1249 len % SCM_LONG_BIT)
0f2d19dd
JB
1250 return SCM_BOOL_F;
1251 }
1252 }
74014c46
DH
1253
1254 {
1255 SCM v = SCM_ARRAY_V (ra);
e11e83f3 1256 unsigned long length = scm_to_ulong (scm_uniform_vector_length (v));
74014c46
DH
1257 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1258 return v;
1259 }
1260
0f2d19dd
JB
1261 sra = scm_make_ra (1);
1262 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1263 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1264 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1265 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1266 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1267 return sra;
1268 }
1269 }
1270}
1bbd0b84 1271#undef FUNC_NAME
0f2d19dd 1272
1cc91f1b 1273
0f2d19dd 1274SCM
6e8d25a6 1275scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1276{
1277 SCM ret;
c014a02e
ML
1278 long inc = 1;
1279 size_t k, len = 1;
0f2d19dd
JB
1280 for (k = SCM_ARRAY_NDIM (ra); k--;)
1281 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1282 k = SCM_ARRAY_NDIM (ra);
1283 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1284 {
74014c46 1285 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1286 return ra;
74014c46 1287 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1288 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1289 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1290 return ra;
1291 }
1292 ret = scm_make_ra (k);
1293 SCM_ARRAY_BASE (ret) = 0;
1294 while (k--)
1295 {
1296 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1297 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1298 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1299 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1300 }
08112c95 1301 SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
0f2d19dd
JB
1302 if (copy)
1303 scm_array_copy_x (ra, ret);
1304 return ret;
1305}
1306
1307
1308
3b3b36dd 1309SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1310 (SCM ra, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1311 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1312 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1313 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1314 "If an end of file is encountered,\n"
1315 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1316 "(starting at the beginning) and the remainder of the array is\n"
1317 "unchanged.\n\n"
1318 "The optional arguments @var{start} and @var{end} allow\n"
1319 "a specified region of a vector (or linearized array) to be read,\n"
1320 "leaving the remainder of the vector unchanged.\n\n"
1321 "@code{uniform-array-read!} returns the number of objects read.\n"
1322 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1323 "returned by @code{(current-input-port)}.")
1bbd0b84 1324#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1325{
35de7ebe 1326 SCM cra = SCM_UNDEFINED, v = ra;
c014a02e
ML
1327 long sz, vlen, ans;
1328 long cstart = 0;
1329 long cend;
1330 long offset = 0;
405aaef9 1331 char *base;
35de7ebe 1332
0f2d19dd 1333 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1334 if (SCM_UNBNDP (port_or_fd))
1335 port_or_fd = scm_cur_inp;
1336 else
e11e83f3 1337 SCM_ASSERT (scm_is_integer (port_or_fd)
0c95b57d 1338 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1339 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1340 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1341 ? 0
e11e83f3 1342 : scm_to_long (scm_uniform_vector_length (v)));
35de7ebe 1343
0f2d19dd 1344loop:
e0e49670 1345 if (scm_is_uniform_vector (v))
0f2d19dd 1346 {
e0e49670
MV
1347 base = scm_uniform_vector_elements (v);
1348 sz = scm_uniform_vector_element_size (v);
1349 }
1350 else
1351 switch SCM_TYP7 (v)
1352 {
1353 default:
1354 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
1355 case scm_tc7_smob:
1356 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1357 cra = scm_ra2contig (ra, 0);
1358 cstart += SCM_ARRAY_BASE (cra);
1359 vlen = SCM_ARRAY_DIMS (cra)->inc *
1360 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1361 v = SCM_ARRAY_V (cra);
1362 goto loop;
1363 case scm_tc7_string:
1364 base = NULL; /* writing to strings is special, see below. */
1365 sz = sizeof (char);
1366 break;
1367 case scm_tc7_bvect:
1368 base = (char *) SCM_BITVECTOR_BASE (v);
1369 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1370 cstart /= SCM_LONG_BIT;
1371 sz = sizeof (long);
1372 break;
e0e49670
MV
1373 }
1374
1146b6cd
GH
1375 cend = vlen;
1376 if (!SCM_UNBNDP (start))
3d8d56df 1377 {
1146b6cd 1378 offset =
c014a02e 1379 SCM_NUM2LONG (3, start);
35de7ebe 1380
1146b6cd 1381 if (offset < 0 || offset >= cend)
1bbd0b84 1382 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1383
1384 if (!SCM_UNBNDP (end))
1385 {
c014a02e
ML
1386 long tend =
1387 SCM_NUM2LONG (4, end);
3d8d56df 1388
1146b6cd 1389 if (tend <= offset || tend > cend)
1bbd0b84 1390 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1391 cend = tend;
1392 }
0f2d19dd 1393 }
35de7ebe 1394
3d8d56df
GH
1395 if (SCM_NIMP (port_or_fd))
1396 {
92c2555f 1397 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1398 int remaining = (cend - offset) * sz;
cc95e00a 1399 size_t off = (cstart + offset) * sz;
6c951427
GH
1400
1401 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1402 scm_flush (port_or_fd);
6c951427
GH
1403
1404 ans = cend - offset;
1405 while (remaining > 0)
3d8d56df 1406 {
6c951427
GH
1407 if (pt->read_pos < pt->read_end)
1408 {
1409 int to_copy = min (pt->read_end - pt->read_pos,
1410 remaining);
1411
cc95e00a
MV
1412 if (base == NULL)
1413 {
1414 /* strings */
1415 char *b = scm_i_string_writable_chars (v);
1416 memcpy (b + off, pt->read_pos, to_copy);
1417 scm_i_string_stop_writing ();
1418 }
1419 else
1420 memcpy (base + off, pt->read_pos, to_copy);
6c951427
GH
1421 pt->read_pos += to_copy;
1422 remaining -= to_copy;
cc95e00a 1423 off += to_copy;
6c951427
GH
1424 }
1425 else
1426 {
affc96b5 1427 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1428 {
1429 if (remaining % sz != 0)
1430 {
5d2d2ffc 1431 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1432 }
1433 ans -= remaining / sz;
1434 break;
1435 }
6c951427 1436 }
3d8d56df 1437 }
6c951427
GH
1438
1439 if (pt->rw_random)
1440 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1441 }
1442 else /* file descriptor. */
1443 {
cc95e00a
MV
1444 if (base == NULL)
1445 {
1446 /* strings */
1447 char *b = scm_i_string_writable_chars (v);
1448 SCM_SYSCALL (ans = read (scm_to_int (port_or_fd),
1449 b + (cstart + offset) * sz,
1450 (sz * (cend - offset))));
1451 scm_i_string_stop_writing ();
1452 }
1453 else
1454 SCM_SYSCALL (ans = read (scm_to_int (port_or_fd),
1455 base + (cstart + offset) * sz,
1456 (sz * (cend - offset))));
3d8d56df 1457 if (ans == -1)
1bbd0b84 1458 SCM_SYSERROR;
3d8d56df 1459 }
0f2d19dd 1460 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1461 ans *= SCM_LONG_BIT;
35de7ebe 1462
bc36d050 1463 if (!scm_is_eq (v, ra) && !scm_is_eq (cra, ra))
0f2d19dd 1464 scm_array_copy_x (cra, ra);
35de7ebe 1465
e11e83f3 1466 return scm_from_long (ans);
0f2d19dd 1467}
1bbd0b84 1468#undef FUNC_NAME
0f2d19dd 1469
3b3b36dd 1470SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1471 (SCM v, SCM port_or_fd, SCM start, SCM end),
8f85c0c6 1472 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
b380b885
MD
1473 "Writes all elements of @var{ura} as binary objects to\n"
1474 "@var{port-or-fdes}.\n\n"
1475 "The optional arguments @var{start}\n"
1476 "and @var{end} allow\n"
1477 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1478 "The number of objects actually written is returned.\n"
b380b885
MD
1479 "@var{port-or-fdes} may be\n"
1480 "omitted, in which case it defaults to the value returned by\n"
1481 "@code{(current-output-port)}.")
1bbd0b84 1482#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1483{
c014a02e
ML
1484 long sz, vlen, ans;
1485 long offset = 0;
1486 long cstart = 0;
1487 long cend;
cc95e00a 1488 const char *base;
3d8d56df 1489
78446828
MV
1490 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1491
0f2d19dd 1492 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1493 if (SCM_UNBNDP (port_or_fd))
1494 port_or_fd = scm_cur_outp;
1495 else
e11e83f3 1496 SCM_ASSERT (scm_is_integer (port_or_fd)
0c95b57d 1497 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1498 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1499 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1500 ? 0
e11e83f3 1501 : scm_to_long (scm_uniform_vector_length (v)));
d245ce23 1502
0f2d19dd 1503loop:
e0e49670 1504 if (scm_is_uniform_vector (v))
0f2d19dd 1505 {
e0e49670
MV
1506 base = scm_uniform_vector_elements (v);
1507 sz = scm_uniform_vector_element_size (v);
1508 }
1509 else
1510 switch SCM_TYP7 (v)
1511 {
1512 default:
1513 badarg1:SCM_WRONG_TYPE_ARG (1, v);
1514 case scm_tc7_smob:
1515 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1516 v = scm_ra2contig (v, 1);
1517 cstart = SCM_ARRAY_BASE (v);
1518 vlen = (SCM_ARRAY_DIMS (v)->inc
1519 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
1520 v = SCM_ARRAY_V (v);
1521 goto loop;
1522 case scm_tc7_string:
1523 base = scm_i_string_chars (v);
1524 sz = sizeof (char);
1525 break;
1526 case scm_tc7_bvect:
1527 base = (char *) SCM_BITVECTOR_BASE (v);
1528 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1529 cstart /= SCM_LONG_BIT;
1530 sz = sizeof (long);
1531 break;
e0e49670
MV
1532 }
1533
1146b6cd
GH
1534 cend = vlen;
1535 if (!SCM_UNBNDP (start))
3d8d56df 1536 {
1146b6cd 1537 offset =
c014a02e 1538 SCM_NUM2LONG (3, start);
3d8d56df 1539
1146b6cd 1540 if (offset < 0 || offset >= cend)
1bbd0b84 1541 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1542
1543 if (!SCM_UNBNDP (end))
1544 {
c014a02e
ML
1545 long tend =
1546 SCM_NUM2LONG (4, end);
3d8d56df 1547
1146b6cd 1548 if (tend <= offset || tend > cend)
1bbd0b84 1549 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1550 cend = tend;
1551 }
3d8d56df
GH
1552 }
1553
1554 if (SCM_NIMP (port_or_fd))
1555 {
cc95e00a 1556 const char *source = base + (cstart + offset) * sz;
6c951427
GH
1557
1558 ans = cend - offset;
265e6a4d 1559 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1560 }
1561 else /* file descriptor. */
1562 {
e11e83f3 1563 SCM_SYSCALL (ans = write (scm_to_int (port_or_fd),
405aaef9 1564 base + (cstart + offset) * sz,
1be6b49c 1565 (sz * (cend - offset))));
3d8d56df 1566 if (ans == -1)
1bbd0b84 1567 SCM_SYSERROR;
3d8d56df 1568 }
0f2d19dd 1569 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1570 ans *= SCM_LONG_BIT;
3d8d56df 1571
e11e83f3 1572 return scm_from_long (ans);
0f2d19dd 1573}
1bbd0b84 1574#undef FUNC_NAME
0f2d19dd
JB
1575
1576
1577static char cnt_tab[16] =
1578{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1579
3b3b36dd 1580SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1581 (SCM b, SCM bitvector),
1e6808ea 1582 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1583 "@var{bitvector}.")
1bbd0b84 1584#define FUNC_NAME s_scm_bit_count
0f2d19dd 1585{
44e47754 1586 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1587 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1588 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1589 return SCM_INUM0;
1590 } else {
c014a02e
ML
1591 unsigned long int count = 0;
1592 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1593 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
7888309b 1594 if (scm_is_false (b)) {
44e47754
DH
1595 w = ~w;
1596 };
c014a02e 1597 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1598 while (1) {
1599 while (w) {
1600 count += cnt_tab[w & 0x0f];
1601 w >>= 4;
1602 }
1603 if (i == 0) {
e11e83f3 1604 return scm_from_ulong (count);
44e47754
DH
1605 } else {
1606 --i;
1607 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
7888309b 1608 if (scm_is_false (b)) {
44e47754 1609 w = ~w;
0f2d19dd 1610 }
44e47754 1611 }
0f2d19dd 1612 }
44e47754 1613 }
0f2d19dd 1614}
1bbd0b84 1615#undef FUNC_NAME
0f2d19dd
JB
1616
1617
3b3b36dd 1618SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1619 (SCM item, SCM v, SCM k),
88ecf5cb
KR
1620 "Return the index of the first occurrance of @var{item} in bit\n"
1621 "vector @var{v}, starting from @var{k}. If there is no\n"
1622 "@var{item} entry between @var{k} and the end of\n"
1623 "@var{bitvector}, then return @code{#f}. For example,\n"
1624 "\n"
1625 "@example\n"
1626 "(bit-position #t #*000101 0) @result{} 3\n"
1627 "(bit-position #f #*0001111 3) @result{} #f\n"
1628 "@end example")
1bbd0b84 1629#define FUNC_NAME s_scm_bit_position
0f2d19dd 1630{
c014a02e
ML
1631 long i, lenw, xbits, pos;
1632 register unsigned long w;
74014c46
DH
1633
1634 SCM_VALIDATE_BOOL (1, item);
1635 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
a55c2b68 1636 pos = scm_to_long (k);
74014c46
DH
1637 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1638
1639 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1640 return SCM_BOOL_F;
74014c46 1641
c014a02e
ML
1642 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1643 i = pos / SCM_LONG_BIT;
74014c46 1644 w = SCM_UNPACK (SCM_VELTS (v)[i]);
7888309b 1645 if (scm_is_false (item))
74014c46 1646 w = ~w;
c014a02e 1647 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1648 pos -= xbits;
1649 w = ((w >> xbits) << xbits);
c014a02e 1650 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1651 while (!0)
1652 {
1653 if (w && (i == lenw))
1654 w = ((w << xbits) >> xbits);
1655 if (w)
1656 while (w)
1657 switch (w & 0x0f)
1658 {
1659 default:
e11e83f3 1660 return scm_from_long (pos);
74014c46
DH
1661 case 2:
1662 case 6:
1663 case 10:
1664 case 14:
e11e83f3 1665 return scm_from_long (pos + 1);
74014c46
DH
1666 case 4:
1667 case 12:
e11e83f3 1668 return scm_from_long (pos + 2);
74014c46 1669 case 8:
e11e83f3 1670 return scm_from_long (pos + 3);
74014c46
DH
1671 case 0:
1672 pos += 4;
1673 w >>= 4;
1674 }
1675 if (++i > lenw)
1676 break;
c014a02e 1677 pos += SCM_LONG_BIT;
f1267706 1678 w = SCM_UNPACK (SCM_VELTS (v)[i]);
7888309b 1679 if (scm_is_false (item))
0f2d19dd 1680 w = ~w;
0f2d19dd 1681 }
74014c46 1682 return SCM_BOOL_F;
0f2d19dd 1683}
1bbd0b84 1684#undef FUNC_NAME
0f2d19dd
JB
1685
1686
3b3b36dd 1687SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761 1688 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1689 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1690 "selecting the entries to change. The return value is\n"
1691 "unspecified.\n"
1692 "\n"
1693 "If @var{kv} is a bit vector, then those entries where it has\n"
1694 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1695 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1696 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1697 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1698 "\n"
1699 "@example\n"
1700 "(define bv #*01000010)\n"
1701 "(bit-set*! bv #*10010001 #t)\n"
1702 "bv\n"
1703 "@result{} #*11010011\n"
1704 "@end example\n"
1705 "\n"
85368844
MV
1706 "If @var{kv} is a u32vector, then its elements are\n"
1707 "indices into @var{v} which are set to @var{obj}.\n"
88ecf5cb
KR
1708 "\n"
1709 "@example\n"
1710 "(define bv #*01000010)\n"
85368844 1711 "(bit-set*! bv #u32(5 2 7) #t)\n"
88ecf5cb
KR
1712 "bv\n"
1713 "@result{} #*01100111\n"
1714 "@end example")
1bbd0b84 1715#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1716{
74014c46 1717 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
85368844
MV
1718
1719 if (SCM_BITVECTOR_P (kv))
0f2d19dd 1720 {
85368844
MV
1721 long k;
1722
1723 if (SCM_BITVECTOR_LENGTH (v) != SCM_BITVECTOR_LENGTH (kv))
1724 scm_misc_error (NULL,
1725 "bit vectors must have equal length",
1726 SCM_EOL);
1727
7888309b 1728 if (scm_is_false (obj))
85368844
MV
1729 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1730 k--;)
1731 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
1732 else if (scm_is_eq (obj, SCM_BOOL_T))
1733 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1734 k--;)
1735 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
1736 else
1737 scm_wrong_type_arg_msg (NULL, 0, obj, "boolean");
1738 }
1739 else if (scm_is_true (scm_u32vector_p (kv)))
1740 {
1741 size_t vlen = SCM_BITVECTOR_LENGTH (v);
d44ff083
MV
1742 size_t ulen, i;
1743 scm_t_uint32 k, *indices;
1744
1745 scm_frame_begin (0);
1746
1747 ulen = scm_c_uniform_vector_length (kv);
1748 indices = scm_u32vector_elements (kv);
1749 scm_frame_uniform_vector_release (kv);
85368844
MV
1750
1751 if (scm_to_bool (obj) == 0)
1752 for (i = 0; i < ulen; i++)
74014c46 1753 {
d44ff083 1754 k = indices[i];
74014c46 1755 if (k >= vlen)
85368844 1756 scm_out_of_range (FUNC_NAME, scm_from_uint32 (k));
34d19ef6 1757 SCM_BITVEC_CLR(v, k);
74014c46 1758 }
85368844
MV
1759 else
1760 for (i = 0; i < ulen; i++)
74014c46 1761 {
d44ff083 1762 k = indices[i];
74014c46 1763 if (k >= vlen)
85368844 1764 scm_out_of_range (FUNC_NAME, scm_from_uint32 (k));
34d19ef6 1765 SCM_BITVEC_SET(v, k);
74014c46 1766 }
d44ff083
MV
1767
1768 scm_frame_end ();
0f2d19dd 1769 }
85368844
MV
1770 else
1771 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
1772
0f2d19dd
JB
1773 return SCM_UNSPECIFIED;
1774}
1bbd0b84 1775#undef FUNC_NAME
0f2d19dd
JB
1776
1777
3b3b36dd 1778SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1779 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1780 "Return a count of how many entries in bit vector @var{v} are\n"
1781 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
1782 "consider.\n"
1783 "\n"
1784 "If @var{kv} is a bit vector, then those entries where it has\n"
1785 "@code{#t} are the ones in @var{v} which are considered.\n"
1786 "@var{kv} and @var{v} must be the same length.\n"
1787 "\n"
85368844
MV
1788 "If @var{kv} is a u32vector, then it contains\n"
1789 "the indexes in @var{v} to consider.\n"
88ecf5cb
KR
1790 "\n"
1791 "For example,\n"
1792 "\n"
1793 "@example\n"
1794 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
85368844 1795 "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
88ecf5cb 1796 "@end example")
1bbd0b84 1797#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1798{
85368844 1799 size_t count = 0;
c209c88e 1800
74014c46 1801 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
85368844
MV
1802
1803 if (SCM_BITVECTOR_P (kv))
0f2d19dd 1804 {
85368844
MV
1805 unsigned long k, i;
1806 int fObj = 0;
1807
1808 if (SCM_BITVECTOR_LENGTH (v) != SCM_BITVECTOR_LENGTH (kv))
1809 scm_misc_error (NULL,
1810 "bit vectors must have equal length",
1811 SCM_EOL);
1812
74014c46 1813 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1814 return SCM_INUM0;
85368844
MV
1815
1816 fObj = scm_to_bool (obj);
1817
c014a02e
ML
1818 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1819 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1820 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1821 while (1)
0f2d19dd
JB
1822 {
1823 for (; k; k >>= 4)
1824 count += cnt_tab[k & 0x0f];
1825 if (0 == i--)
e11e83f3 1826 return scm_from_long (count);
c209c88e
GB
1827
1828 /* urg. repetitive (see above.) */
c014a02e 1829 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1830 }
1831 }
85368844
MV
1832 else if (scm_is_true (scm_u32vector_p (kv)))
1833 {
1834 size_t vlen = SCM_BITVECTOR_LENGTH (v);
d44ff083
MV
1835 size_t ulen, i;
1836 scm_t_uint32 k, *indices;
1837
1838 scm_frame_begin (0);
1839
1840 ulen = scm_c_uniform_vector_length (kv);
1841 indices = scm_u32vector_elements (kv);
1842 scm_frame_uniform_vector_release (kv);
85368844
MV
1843
1844 if (scm_to_bool (obj) == 0)
1845 for (i = 0; i < ulen; i++)
1846 {
d44ff083 1847 k = indices[i];
85368844 1848 if (k >= vlen)
d44ff083 1849 scm_out_of_range (FUNC_NAME, scm_from_uint32 (k));
85368844
MV
1850 if (!SCM_BITVEC_REF(v, k))
1851 count++;
1852 }
1853 else
1854 for (i = 0; i < ulen; i++)
1855 {
d44ff083 1856 k = indices[i];
85368844 1857 if (k >= vlen)
d44ff083 1858 scm_out_of_range (FUNC_NAME, scm_from_uint32 (k));
85368844
MV
1859 if (SCM_BITVEC_REF (v, k))
1860 count++;
1861 }
d44ff083
MV
1862
1863 scm_frame_end ();
85368844
MV
1864 }
1865 else
1866 scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
1867
e11e83f3 1868 return scm_from_long (count);
0f2d19dd 1869}
1bbd0b84 1870#undef FUNC_NAME
0f2d19dd
JB
1871
1872
3b3b36dd 1873SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1874 (SCM v),
88ecf5cb
KR
1875 "Modify the bit vector @var{v} by replacing each element with\n"
1876 "its negation.")
1bbd0b84 1877#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 1878{
c014a02e 1879 long int k;
74014c46
DH
1880
1881 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
1882
1883 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 1884 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1885 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 1886
0f2d19dd
JB
1887 return SCM_UNSPECIFIED;
1888}
1bbd0b84 1889#undef FUNC_NAME
0f2d19dd
JB
1890
1891
0f2d19dd 1892SCM
cc95e00a 1893scm_istr2bve (SCM str)
0f2d19dd 1894{
cc95e00a 1895 size_t len = scm_i_string_length (str);
85368844 1896 SCM v = scm_make_u1vector (scm_from_size_t (len), SCM_UNDEFINED);
c014a02e
ML
1897 long *data = (long *) SCM_VELTS (v);
1898 register unsigned long mask;
1899 register long k;
1900 register long j;
cc95e00a
MV
1901 const char *c_str = scm_i_string_chars (str);
1902
c014a02e 1903 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
1904 {
1905 data[k] = 0L;
c014a02e
ML
1906 j = len - k * SCM_LONG_BIT;
1907 if (j > SCM_LONG_BIT)
1908 j = SCM_LONG_BIT;
0f2d19dd 1909 for (mask = 1L; j--; mask <<= 1)
cc95e00a 1910 switch (*c_str++)
0f2d19dd
JB
1911 {
1912 case '0':
1913 break;
1914 case '1':
1915 data[k] |= mask;
1916 break;
1917 default:
1918 return SCM_BOOL_F;
1919 }
1920 }
1921 return v;
1922}
1923
1924
1cc91f1b 1925
0f2d19dd 1926static SCM
34d19ef6 1927ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd
JB
1928{
1929 register SCM res = SCM_EOL;
c014a02e
ML
1930 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
1931 register size_t i;
0f2d19dd
JB
1932 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
1933 return SCM_EOL;
1934 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
1935 if (k < SCM_ARRAY_NDIM (ra) - 1)
1936 {
1937 do
1938 {
1939 i -= inc;
1940 res = scm_cons (ra2l (ra, i, k + 1), res);
1941 }
1942 while (i != base);
1943 }
1944 else
1945 do
1946 {
1947 i -= inc;
e11e83f3 1948 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), scm_from_size_t (i)), res);
0f2d19dd
JB
1949 }
1950 while (i != base);
1951 return res;
1952}
1953
1954
cd328b4f 1955SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 1956 (SCM v),
1e6808ea
MG
1957 "Return a list consisting of all the elements, in order, of\n"
1958 "@var{array}.")
cd328b4f 1959#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
1960{
1961 SCM res = SCM_EOL;
c014a02e 1962 register long k;
e0e49670
MV
1963
1964 if (scm_is_uniform_vector (v))
1965 return scm_uniform_vector_to_list (v);
1966
0f2d19dd 1967 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 1968 switch SCM_TYP7 (v)
0f2d19dd
JB
1969 {
1970 default:
276dd677 1971 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
1972 case scm_tc7_smob:
1973 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1974 return ra2l (v, SCM_ARRAY_BASE (v), 0);
1975 case scm_tc7_vector:
95f5b0f5 1976 case scm_tc7_wvect:
0f2d19dd
JB
1977 return scm_vector_to_list (v);
1978 case scm_tc7_string:
1979 return scm_string_to_list (v);
1980 case scm_tc7_bvect:
1981 {
c014a02e
ML
1982 long *data = (long *) SCM_VELTS (v);
1983 register unsigned long mask;
1984 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
1985 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
7888309b 1986 res = scm_cons (scm_from_bool(((long *) data)[k] & mask), res);
c014a02e 1987 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
7888309b 1988 res = scm_cons (scm_from_bool(((long *) data)[k] & mask), res);
0f2d19dd
JB
1989 return res;
1990 }
0f2d19dd
JB
1991 }
1992}
1bbd0b84 1993#undef FUNC_NAME
0f2d19dd
JB
1994
1995
c014a02e 1996static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 1997
3b3b36dd 1998SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 1999 (SCM ndim, SCM prot, SCM lst),
8f85c0c6 2000 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1e6808ea
MG
2001 "Return a uniform array of the type indicated by prototype\n"
2002 "@var{prot} with elements the same as those of @var{lst}.\n"
2003 "Elements must be of the appropriate type, no coercions are\n"
bfad4005
MV
2004 "done.\n"
2005 "\n"
2006 "The argument @var{ndim} determines the number of dimensions\n"
2007 "of the array. It is either an exact integer, giving the\n"
2008 " number directly, or a list of exact integers, whose length\n"
2009 "specifies the number of dimensions and each element is the\n"
2010 "lower index bound of its dimension.")
1bbd0b84 2011#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd 2012{
bfad4005 2013 SCM shape, row;
0f2d19dd 2014 SCM ra;
c014a02e 2015 unsigned long k;
bfad4005
MV
2016
2017 shape = SCM_EOL;
2018 row = lst;
2019 if (scm_is_integer (ndim))
0f2d19dd 2020 {
bfad4005
MV
2021 size_t k = scm_to_size_t (ndim);
2022 while (k-- > 0)
2023 {
2024 shape = scm_cons (scm_length (row), shape);
2025 if (k > 0)
2026 row = scm_car (row);
2027 }
2028 }
2029 else
2030 {
2031 while (1)
2032 {
2033 shape = scm_cons (scm_list_2 (scm_car (ndim),
2034 scm_sum (scm_sum (scm_car (ndim),
2035 scm_length (row)),
2036 scm_from_int (-1))),
2037 shape);
2038 ndim = scm_cdr (ndim);
2039 if (scm_is_pair (ndim))
2040 row = scm_car (row);
2041 else
2042 break;
2043 }
0f2d19dd 2044 }
bfad4005
MV
2045
2046 ra = scm_dimensions_to_uniform_array (scm_reverse_x (shape, SCM_EOL), prot,
d12feca3 2047 SCM_UNDEFINED);
bfad4005 2048 if (scm_is_null (shape))
0f2d19dd
JB
2049 {
2050 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2051 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2052 return ra;
2053 }
2054 if (!SCM_ARRAYP (ra))
2055 {
e11e83f3 2056 unsigned long length = scm_to_ulong (scm_uniform_vector_length (ra));
74014c46 2057 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
e11e83f3 2058 scm_array_set_x (ra, SCM_CAR (lst), scm_from_ulong (k));
0f2d19dd
JB
2059 return ra;
2060 }
2061 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2062 return ra;
2063 else
1afff620
KN
2064 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2065 scm_list_1 (lst));
0f2d19dd 2066}
1bbd0b84 2067#undef FUNC_NAME
0f2d19dd 2068
0f2d19dd 2069static int
c014a02e 2070l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2071{
c014a02e
ML
2072 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2073 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2074 int ok = 1;
2075 if (n <= 0)
d2e53ed6 2076 return (scm_is_null (lst));
0f2d19dd
JB
2077 if (k < SCM_ARRAY_NDIM (ra) - 1)
2078 {
2079 while (n--)
2080 {
d2e53ed6 2081 if (!scm_is_pair (lst))
0f2d19dd
JB
2082 return 0;
2083 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2084 base += inc;
2085 lst = SCM_CDR (lst);
2086 }
d2e53ed6 2087 if (!scm_is_null (lst))
0f2d19dd
JB
2088 return 0;
2089 }
2090 else
2091 {
2092 while (n--)
2093 {
d2e53ed6 2094 if (!scm_is_pair (lst))
0f2d19dd 2095 return 0;
e11e83f3 2096 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), scm_from_ulong (base));
0f2d19dd
JB
2097 base += inc;
2098 lst = SCM_CDR (lst);
2099 }
d2e53ed6 2100 if (!scm_is_null (lst))
fee7ef83 2101 return 0;
0f2d19dd
JB
2102 }
2103 return ok;
2104}
2105
1cc91f1b 2106
0f2d19dd 2107static void
34d19ef6 2108rapr1 (SCM ra, unsigned long j, unsigned long k, SCM port, scm_print_state *pstate)
0f2d19dd 2109{
c014a02e
ML
2110 long inc = 1;
2111 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8 2112 ? 0
e11e83f3 2113 : scm_to_long (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2114 int enclosed = 0;
2115tail:
5c11cc9d 2116 switch SCM_TYP7 (ra)
0f2d19dd
JB
2117 {
2118 case scm_tc7_smob:
2119 if (enclosed++)
2120 {
2121 SCM_ARRAY_BASE (ra) = j;
2122 if (n-- > 0)
9882ea19 2123 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2124 for (j += inc; n-- > 0; j += inc)
2125 {
b7f3516f 2126 scm_putc (' ', port);
0f2d19dd 2127 SCM_ARRAY_BASE (ra) = j;
9882ea19 2128 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2129 }
2130 break;
2131 }
2132 if (k + 1 < SCM_ARRAY_NDIM (ra))
2133 {
c014a02e 2134 long i;
0f2d19dd
JB
2135 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2136 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2137 {
b7f3516f 2138 scm_putc ('(', port);
9882ea19 2139 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2140 scm_puts (") ", port);
0f2d19dd
JB
2141 j += inc;
2142 }
2143 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2144 { /* could be zero size. */
b7f3516f 2145 scm_putc ('(', port);
9882ea19 2146 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2147 scm_putc (')', port);
0f2d19dd
JB
2148 }
2149 break;
2150 }
1be6b49c 2151 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2152 { /* Could be zero-dimensional */
2153 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2154 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2155 }
2156 else
2157 n = 1;
2158 ra = SCM_ARRAY_V (ra);
2159 goto tail;
2160 default:
5c11cc9d 2161 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2162 if (n-- > 0)
e0e49670 2163 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2164 for (j += inc; n-- > 0; j += inc)
2165 {
b7f3516f 2166 scm_putc (' ', port);
9882ea19 2167 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2168 }
2169 break;
2170 case scm_tc7_string:
cc95e00a
MV
2171 {
2172 const char *src;
2173 src = scm_i_string_chars (ra);
2174 if (n-- > 0)
2175 scm_iprin1 (SCM_MAKE_CHAR (src[j]), port, pstate);
2176 if (SCM_WRITINGP (pstate))
2177 for (j += inc; n-- > 0; j += inc)
2178 {
2179 scm_putc (' ', port);
2180 scm_iprin1 (SCM_MAKE_CHAR (src[j]), port, pstate);
2181 }
2182 else
2183 for (j += inc; n-- > 0; j += inc)
2184 scm_putc (src[j], port);
2185 scm_remember_upto_here_1 (ra);
2186 }
0f2d19dd 2187 break;
e0e49670 2188
0f2d19dd
JB
2189 }
2190}
2191
e0e49670
MV
2192/* Print dimension DIM of ARRAY.
2193 */
0f2d19dd 2194
e0e49670
MV
2195static int
2196scm_i_print_array_dimension (SCM array, int dim, int base,
2197 SCM port, scm_print_state *pstate)
2198{
2199 scm_t_array_dim *dim_spec = SCM_ARRAY_DIMS (array) + dim;
2200 long idx;
2201
2202 scm_putc ('(', port);
2203
2204#if 0
2205 scm_putc ('{', port);
2206 scm_intprint (dim_spec->lbnd, 10, port);
2207 scm_putc (':', port);
2208 scm_intprint (dim_spec->ubnd, 10, port);
2209 scm_putc (':', port);
2210 scm_intprint (dim_spec->inc, 10, port);
2211 scm_putc ('}', port);
2212#endif
2213
2214 for (idx = dim_spec->lbnd; idx <= dim_spec->ubnd; idx++)
2215 {
2216 if (dim < SCM_ARRAY_NDIM(array)-1)
2217 scm_i_print_array_dimension (array, dim+1, base, port, pstate);
2218 else
2219 scm_iprin1 (scm_cvref (SCM_ARRAY_V (array), base, SCM_UNDEFINED),
2220 port, pstate);
2221 if (idx < dim_spec->ubnd)
2222 scm_putc (' ', port);
2223 base += dim_spec->inc;
2224 }
2225
2226 scm_putc (')', port);
2227 return 1;
2228}
2229
2230static const char *
2231scm_i_legacy_tag (SCM v)
2232{
2233 switch (SCM_TYP7 (v))
2234 {
2235 case scm_tc7_bvect:
2236 return "b";
2237 case scm_tc7_string:
2238 return "a";
e0e49670
MV
2239 case scm_tc7_vector:
2240 case scm_tc7_wvect:
2241 return "";
2242 default:
2243 return "?";
2244 }
2245}
2246
2247/* Print a array. (Only for strict arrays, not for strings, uniform
2248 vectors, vectors and other stuff that can masquerade as an array.)
2249*/
2250
2251/* The array tag is generally of the form
2252 *
2253 * #<rank><unif><@lower><@lower>...
2254 *
2255 * <rank> is a positive integer in decimal giving the rank of the
bfad4005
MV
2256 * array. It is omitted when the rank is 1 and the array is
2257 * non-shared and has zero-origin. For shared arrays and for a
2258 * non-zero origin, the rank is always printed even when it is 1 to
2259 * dinstinguish them from ordinary vectors.
e0e49670
MV
2260 *
2261 * <unif> is the tag for a uniform (or homogenous) numeric vector,
2262 * like u8, s16, etc, as defined by SRFI-4. It is omitted when the
2263 * array is not uniform.
2264 *
2265 * <@lower> is a 'at' sign followed by a integer in decimal giving the
2266 * lower bound of a dimension. There is one <@lower> for each
2267 * dimension. When all lower bounds are zero, all <@lower> are
2268 * omitted.
2269 *
2270 * Thus,
2271 *
2272 * #(1 2 3) is non-uniform array of rank 1 with lower bound 0 in
2273 * dimension 0. (I.e., a regular vector.)
2274 *
2275 * #@2(1 2 3) is non-uniform array of rank 1 with lower bound 2 in
2276 * dimension 0.
2277 *
2278 * #2((1 2 3) (4 5 6)) is a non-uniform array of rank 2; a 3x3
2279 * matrix with index ranges 0..2 and 0..2.
2280 *
2281 * #u32(0 1 2) is a uniform u8 array of rank 1.
2282 *
2283 * #2u32@2@3((1 2) (2 3)) is a uniform u8 array of rank 2 with index
2284 * ranges 2..3 and 3..4.
2285 */
2286
2287static int
2288scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
2289{
2290 long ndim = SCM_ARRAY_NDIM (array);
2291 scm_t_array_dim *dim_specs = SCM_ARRAY_DIMS (array);
2292 unsigned long base = SCM_ARRAY_BASE (array);
2293 long i;
2294
2295 scm_putc ('#', port);
c0fc64c8 2296 if (ndim != 1 || dim_specs[0].lbnd != 0)
e0e49670
MV
2297 scm_intprint (ndim, 10, port);
2298 if (scm_is_uniform_vector (SCM_ARRAY_V (array)))
2299 scm_puts (scm_i_uniform_vector_tag (SCM_ARRAY_V (array)), port);
2300 else
2301 scm_puts (scm_i_legacy_tag (SCM_ARRAY_V (array)), port);
2302 for (i = 0; i < ndim; i++)
2303 if (dim_specs[i].lbnd != 0)
2304 {
2305 for (i = 0; i < ndim; i++)
2306 {
2307 scm_putc ('@', port);
2308 scm_uintprint (dim_specs[i].lbnd, 10, port);
2309 }
2310 break;
2311 }
2312
2313#if 0
2314 scm_putc ('{', port);
2315 scm_uintprint (base, 10, port);
2316 scm_putc ('}', port);
2317#endif
2318
2319 return scm_i_print_array_dimension (array, 0, base, port, pstate);
2320}
1cc91f1b 2321
bfad4005
MV
2322/* Read an array. This function can also read vectors and uniform
2323 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2324 handled here.
2325
2326 C is the first character read after the '#'.
2327*/
2328
2329typedef struct {
2330 const char *tag;
2331 SCM *proto_var;
2332} tag_proto;
2333
2334static SCM scm_i_proc_make_vector;
2335
2336static tag_proto tag_proto_table[] = {
2337 { "", &scm_i_proc_make_vector },
2338 { "u8", &scm_i_proc_make_u8vector },
2339 { "s8", &scm_i_proc_make_s8vector },
2340 { "u16", &scm_i_proc_make_u16vector },
2341 { "s16", &scm_i_proc_make_s16vector },
2342 { "u32", &scm_i_proc_make_u32vector },
2343 { "s32", &scm_i_proc_make_s32vector },
2344 { "u64", &scm_i_proc_make_u64vector },
2345 { "s64", &scm_i_proc_make_s64vector },
2346 { "f32", &scm_i_proc_make_f32vector },
2347 { "f64", &scm_i_proc_make_f64vector },
2348 { NULL, NULL }
2349};
2350
2351static SCM
2352scm_i_tag_to_prototype (const char *tag, SCM port)
2353{
2354 tag_proto *tp;
2355
2356 for (tp = tag_proto_table; tp->tag; tp++)
2357 if (!strcmp (tp->tag, tag))
2358 return *(tp->proto_var);
2359
2360#if SCM_ENABLE_DEPRECATED
2361 {
2362 /* Recognize the old syntax, producing the old prototypes.
2363 */
2364 SCM proto = SCM_EOL;
2365 const char *instead;
2366 switch (tag[0])
2367 {
2368 case 'a':
2369 proto = SCM_MAKE_CHAR ('a');
2370 instead = "???";
2371 break;
2372 case 'u':
2373 proto = scm_from_int (1);
2374 instead = "u32";
2375 break;
2376 case 'e':
2377 proto = scm_from_int (-1);
2378 instead = "s32";
2379 break;
2380 case 's':
2381 proto = scm_from_double (1.0);
2382 instead = "f32";
2383 break;
2384 case 'i':
2385 proto = scm_divide (scm_from_int (1), scm_from_int (3));
2386 instead = "f64";
2387 break;
2388 case 'y':
2389 proto = SCM_MAKE_CHAR (0);
2390 instead = "s8";
2391 break;
2392 case 'h':
2393 proto = scm_from_locale_symbol ("s");
2394 instead = "s16";
2395 break;
2396 case 'l':
2397 proto = scm_from_locale_symbol ("l");
2398 instead = "s64";
2399 break;
2400 case 'c':
2401 proto = scm_c_make_rectangular (0.0, 1.0);
72d05aa4
MV
2402 instead = "c64";
2403 break;
2404 default:
bfad4005
MV
2405 instead = "???";
2406 break;
2407 }
2408 if (!scm_is_eq (proto, SCM_EOL) && tag[1] == '\0')
2409 {
2410 scm_c_issue_deprecation_warning_fmt
2411 ("The tag '%c' is deprecated for uniform vectors. "
2412 "Use '%s' instead.", tag[0], instead);
2413 return proto;
2414 }
2415 }
2416#endif
2417
2418 scm_i_input_error (NULL, port,
2419 "unrecognized uniform array tag: ~a",
2420 scm_list_1 (scm_from_locale_string (tag)));
2421 return SCM_BOOL_F;
2422}
2423
2424SCM
2425scm_i_read_array (SCM port, int c)
2426{
2427 size_t rank;
2428 int got_rank;
2429 char tag[80];
2430 int tag_len;
2431
2432 SCM lower_bounds, elements;
2433
2434 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2435 the array code can not deal with zero-length dimensions yet, and
2436 we want to allow zero-length vectors, of course.
2437 */
2438 if (c == '(')
2439 {
2440 scm_ungetc (c, port);
2441 return scm_vector (scm_read (port));
2442 }
2443
2444 /* Disambiguate between '#f' and uniform floating point vectors.
2445 */
2446 if (c == 'f')
2447 {
2448 c = scm_getc (port);
2449 if (c != '3' && c != '6')
2450 {
2451 if (c != EOF)
2452 scm_ungetc (c, port);
2453 return SCM_BOOL_F;
2454 }
2455 rank = 1;
2456 got_rank = 1;
2457 tag[0] = 'f';
2458 tag_len = 1;
2459 goto continue_reading_tag;
2460 }
2461
2462 /* Read rank. We disallow arrays of rank zero since they do not
2463 seem to work reliably yet. */
2464 rank = 0;
2465 got_rank = 0;
2466 while ('0' <= c && c <= '9')
2467 {
2468 rank = 10*rank + c-'0';
2469 got_rank = 1;
2470 c = scm_getc (port);
2471 }
2472 if (!got_rank)
2473 rank = 1;
2474 else if (rank == 0)
2475 scm_i_input_error (NULL, port,
2476 "array rank must be positive", SCM_EOL);
2477
2478 /* Read tag. */
2479 tag_len = 0;
2480 continue_reading_tag:
2481 while (c != EOF && c != '(' && c != '@' && tag_len < 80)
2482 {
2483 tag[tag_len++] = c;
2484 c = scm_getc (port);
2485 }
2486 tag[tag_len] = '\0';
2487
2488 /* Read lower bounds. */
2489 lower_bounds = SCM_EOL;
2490 while (c == '@')
2491 {
2492 /* Yeah, right, we should use some ready-made integer parsing
2493 routine for this...
2494 */
2495
2496 long lbnd = 0;
2497 long sign = 1;
2498
2499 c = scm_getc (port);
2500 if (c == '-')
2501 {
2502 sign = -1;
2503 c = scm_getc (port);
2504 }
2505 while ('0' <= c && c <= '9')
2506 {
2507 lbnd = 10*lbnd + c-'0';
2508 c = scm_getc (port);
2509 }
2510 lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
2511 }
2512
2513 /* Read nested lists of elements.
2514 */
2515 if (c != '(')
2516 scm_i_input_error (NULL, port,
2517 "missing '(' in vector or array literal",
2518 SCM_EOL);
2519 scm_ungetc (c, port);
2520 elements = scm_read (port);
2521
2522 if (scm_is_null (lower_bounds))
2523 lower_bounds = scm_from_size_t (rank);
2524 else if (scm_ilength (lower_bounds) != rank)
2525 scm_i_input_error (NULL, port,
2526 "the number of lower bounds must match the array rank",
2527 SCM_EOL);
2528
2529 /* Construct array. */
2530 return scm_list_to_uniform_array (lower_bounds,
2531 scm_i_tag_to_prototype (tag, port),
2532 elements);
2533}
2534
0f2d19dd 2535int
1bbd0b84 2536scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2537{
2538 SCM v = exp;
c014a02e 2539 unsigned long base = 0;
e0e49670 2540
bfad4005 2541 if (SCM_ARRAYP (exp) && !SCM_ARRAYP (SCM_ARRAY_V (exp)))
e0e49670
MV
2542 return scm_i_print_array (exp, port, pstate);
2543
b7f3516f 2544 scm_putc ('#', port);
0f2d19dd 2545tail:
5c11cc9d 2546 switch SCM_TYP7 (v)
0f2d19dd
JB
2547 {
2548 case scm_tc7_smob:
2549 {
2550 long ndim = SCM_ARRAY_NDIM (v);
2551 base = SCM_ARRAY_BASE (v);
2552 v = SCM_ARRAY_V (v);
2553 if (SCM_ARRAYP (v))
2554
2555 {
b7f3516f 2556 scm_puts ("<enclosed-array ", port);
9882ea19 2557 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2558 scm_putc ('>', port);
0f2d19dd
JB
2559 return 1;
2560 }
2561 else
2562 {
2563 scm_intprint (ndim, 10, port);
2564 goto tail;
2565 }
2566 }
2567 case scm_tc7_bvect:
bc36d050 2568 if (scm_is_eq (exp, v))
0f2d19dd 2569 { /* a uve, not an scm_array */
c014a02e 2570 register long i, j, w;
b7f3516f 2571 scm_putc ('*', port);
c014a02e 2572 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2573 {
92c2555f 2574 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2575 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2576 {
b7f3516f 2577 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2578 w >>= 1;
2579 }
2580 }
c014a02e 2581 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2582 if (j)
2583 {
c014a02e 2584 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2585 for (; j; j--)
2586 {
b7f3516f 2587 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2588 w >>= 1;
2589 }
2590 }
2591 return 1;
2592 }
2593 else
b7f3516f 2594 scm_putc ('b', port);
0f2d19dd
JB
2595 break;
2596 case scm_tc7_string:
b7f3516f 2597 scm_putc ('a', port);
0f2d19dd 2598 break;
0f2d19dd 2599 }
b7f3516f 2600 scm_putc ('(', port);
9882ea19 2601 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2602 scm_putc (')', port);
0f2d19dd
JB
2603 return 1;
2604}
2605
ab1be174
MV
2606SCM_DEFINE (scm_array_creator, "array-creator", 1, 0, 0,
2607 (SCM ra),
2608 "Return a procedure that would produce an array of the same type\n"
2609 "as @var{array}, if used as the @var{creator} with\n"
2610 "@code{make-uniform-array}.")
2611#define FUNC_NAME s_scm_array_creator
2612{
2613 int outer = 1;
2614 SCM orig_ra = ra;
2615
2616 if (SCM_ARRAYP (ra))
2617 {
2618 ra = SCM_ARRAY_V (ra);
2619 outer = 0;
2620 }
2621
2622 if (scm_is_uniform_vector (ra))
2623 return scm_i_uniform_vector_creator (ra);
2624 else if (scm_is_true (scm_vector_p (ra)))
2625 return scm_i_proc_make_vector;
2626 else if (scm_is_string (ra))
2627 return scm_i_proc_make_string;
2628 else if (SCM_BITVECTOR_P (ra))
2629 return scm_i_proc_make_u1vector;
2630 else if (SCM_ARRAYP (ra))
2631 scm_misc_error (NULL, "creator not known for enclosed array: ~a",
2632 scm_list_1 (orig_ra));
2633 else if (outer)
2634 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
2635 else
2636 scm_misc_error (NULL, "creator not known for array content: ~a",
2637 scm_list_1 (ra));
2638}
2639#undef FUNC_NAME
2640
72d05aa4
MV
2641#if SCM_ENABLE_DEPRECATED
2642
3b3b36dd 2643SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2644 (SCM ra),
1e6808ea
MG
2645 "Return an object that would produce an array of the same type\n"
2646 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2647 "@code{make-uniform-array}.")
1bbd0b84 2648#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2649{
2650 int enclosed = 0;
2651 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2652loop:
74014c46 2653 switch SCM_TYP7 (ra)
0f2d19dd
JB
2654 {
2655 default:
276dd677 2656 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd 2657 case scm_tc7_smob:
ab1be174
MV
2658 if (SCM_ARRAYP (ra))
2659 {
2660 if (enclosed++)
2661 return SCM_UNSPECIFIED;
2662 ra = SCM_ARRAY_V (ra);
2663 goto loop;
2664 }
2665 else
2666 {
2667 SCM proto = scm_i_get_old_prototype (ra);
2668 if (scm_is_eq (SCM_UNSPECIFIED, proto))
2669 goto badarg;
2670 return proto;
2671 }
0f2d19dd 2672 case scm_tc7_vector:
95f5b0f5 2673 case scm_tc7_wvect:
0f2d19dd
JB
2674 return SCM_EOL;
2675 case scm_tc7_bvect:
2676 return SCM_BOOL_T;
2677 case scm_tc7_string:
7866a09b 2678 return SCM_MAKE_CHAR ('a');
0f2d19dd
JB
2679 }
2680}
1bbd0b84 2681#undef FUNC_NAME
0f2d19dd 2682
72d05aa4 2683#endif
1cc91f1b 2684
0f2d19dd 2685static SCM
e841c3e0 2686array_mark (SCM ptr)
0f2d19dd 2687{
0f2d19dd
JB
2688 return SCM_ARRAY_V (ptr);
2689}
2690
1cc91f1b 2691
1be6b49c 2692static size_t
e841c3e0 2693array_free (SCM ptr)
0f2d19dd 2694{
4c9419ac
MV
2695 scm_gc_free (SCM_ARRAY_MEM (ptr),
2696 (sizeof (scm_t_array)
2697 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2698 "array");
2699 return 0;
0f2d19dd
JB
2700}
2701
0f2d19dd
JB
2702void
2703scm_init_unif ()
0f2d19dd 2704{
e841c3e0
KN
2705 scm_tc16_array = scm_make_smob_type ("array", 0);
2706 scm_set_smob_mark (scm_tc16_array, array_mark);
2707 scm_set_smob_free (scm_tc16_array, array_free);
2708 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2709 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
cba42c93
MV
2710 exactly_one_third = scm_permanent_object (scm_divide (scm_from_int (1),
2711 scm_from_int (3)));
0f2d19dd 2712 scm_add_feature ("array");
a0599745 2713#include "libguile/unif.x"
bfad4005
MV
2714
2715 scm_i_proc_make_vector = scm_variable_ref (scm_c_lookup ("make-vector"));
2716 scm_i_proc_make_string = scm_variable_ref (scm_c_lookup ("make-string"));
2717 scm_i_proc_make_u1vector = scm_variable_ref (scm_c_lookup ("make-u1vector"));
0f2d19dd 2718}
89e00824
ML
2719
2720/*
2721 Local Variables:
2722 c-file-style: "gnu"
2723 End:
2724*/