Remove extraneous functions from `AC_REPLACE_FUNCS'.
[bpt/guile.git] / libguile / arrays.c
CommitLineData
438974d0 1/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005, 2006, 2009 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd
JB
20\f
21
dbb605f5 22#ifdef HAVE_CONFIG_H
2a5cd898
RB
23# include <config.h>
24#endif
25
0f2d19dd 26#include <stdio.h>
e6e2e95a 27#include <errno.h>
783e7774 28#include <string.h>
e6e2e95a 29
a0599745 30#include "libguile/_scm.h"
e0e49670
MV
31#include "libguile/__scm.h"
32#include "libguile/eq.h"
a0599745
MD
33#include "libguile/chars.h"
34#include "libguile/eval.h"
35#include "libguile/fports.h"
36#include "libguile/smob.h"
a0599745
MD
37#include "libguile/feature.h"
38#include "libguile/root.h"
39#include "libguile/strings.h"
c44ca4fe 40#include "libguile/srfi-13.h"
e0e49670 41#include "libguile/srfi-4.h"
a0599745 42#include "libguile/vectors.h"
cf396142 43#include "libguile/bitvectors.h"
438974d0 44#include "libguile/bytevectors.h"
bfad4005 45#include "libguile/list.h"
d44ff083 46#include "libguile/dynwind.h"
943a0a87 47#include "libguile/read.h"
a0599745
MD
48
49#include "libguile/validate.h"
2fa901a5 50#include "libguile/arrays.h"
943a0a87 51#include "libguile/array-map.h"
f332e957 52#include "libguile/generalized-vectors.h"
943a0a87 53#include "libguile/generalized-arrays.h"
476b894c 54#include "libguile/uniform.h"
0f2d19dd 55
0f2d19dd 56
04b87de5 57scm_t_bits scm_i_tc16_array;
04b87de5 58#define SCM_SET_ARRAY_CONTIGUOUS_FLAG(x) \
c395cb78 59 (SCM_SET_SMOB_FLAGS ((x), SCM_SMOB_FLAGS (x) | SCM_I_ARRAY_FLAG_CONTIGUOUS))
04b87de5 60#define SCM_CLR_ARRAY_CONTIGUOUS_FLAG(x) \
c395cb78 61 (SCM_SET_SMOB_FLAGS ((x), SCM_SMOB_FLAGS (x) & ~SCM_I_ARRAY_FLAG_CONTIGUOUS))
1cc91f1b 62
0f2d19dd 63
e2d37336
MD
64SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
65 (SCM ra),
66 "Return the root vector of a shared array.")
67#define FUNC_NAME s_scm_shared_array_root
68{
66b9d7d3 69 if (SCM_I_ARRAYP (ra))
04b87de5 70 return SCM_I_ARRAY_V (ra);
52372719
MV
71 else if (scm_is_generalized_vector (ra))
72 return ra;
943a0a87 73 scm_wrong_type_arg_msg (FUNC_NAME, SCM_ARG1, ra, "array");
e2d37336
MD
74}
75#undef FUNC_NAME
76
77
78SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
79 (SCM ra),
80 "Return the root vector index of the first element in the array.")
81#define FUNC_NAME s_scm_shared_array_offset
82{
52372719
MV
83 scm_t_array_handle handle;
84 SCM res;
85
86 scm_array_get_handle (ra, &handle);
87 res = scm_from_size_t (handle.base);
88 scm_array_handle_release (&handle);
89 return res;
e2d37336
MD
90}
91#undef FUNC_NAME
92
93
94SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
95 (SCM ra),
96 "For each dimension, return the distance between elements in the root vector.")
97#define FUNC_NAME s_scm_shared_array_increments
98{
52372719 99 scm_t_array_handle handle;
e2d37336 100 SCM res = SCM_EOL;
1be6b49c 101 size_t k;
92c2555f 102 scm_t_array_dim *s;
02339e5b 103
52372719
MV
104 scm_array_get_handle (ra, &handle);
105 k = scm_array_handle_rank (&handle);
106 s = scm_array_handle_dims (&handle);
e2d37336 107 while (k--)
52372719
MV
108 res = scm_cons (scm_from_ssize_t (s[k].inc), res);
109 scm_array_handle_release (&handle);
e2d37336
MD
110 return res;
111}
112#undef FUNC_NAME
113
0cd6cb2f 114SCM
66b9d7d3 115scm_i_make_array (int ndim)
0f2d19dd
JB
116{
117 SCM ra;
66b9d7d3 118 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + scm_i_tc16_array,
04b87de5 119 scm_gc_malloc ((sizeof (scm_i_t_array) +
4c9419ac
MV
120 ndim * sizeof (scm_t_array_dim)),
121 "array"));
04b87de5 122 SCM_I_ARRAY_V (ra) = SCM_BOOL_F;
0f2d19dd
JB
123 return ra;
124}
125
126static char s_bad_spec[] = "Bad scm_array dimension";
0f2d19dd 127
1cc91f1b 128
02339e5b
MV
129/* Increments will still need to be set. */
130
0cd6cb2f
MV
131static SCM
132scm_i_shap2ra (SCM args)
0f2d19dd 133{
92c2555f 134 scm_t_array_dim *s;
0f2d19dd
JB
135 SCM ra, spec, sp;
136 int ndim = scm_ilength (args);
b3fcac34 137 if (ndim < 0)
0cd6cb2f 138 scm_misc_error (NULL, s_bad_spec, SCM_EOL);
b3fcac34 139
66b9d7d3 140 ra = scm_i_make_array (ndim);
04b87de5
MV
141 SCM_I_ARRAY_BASE (ra) = 0;
142 s = SCM_I_ARRAY_DIMS (ra);
d2e53ed6 143 for (; !scm_is_null (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
144 {
145 spec = SCM_CAR (args);
e11e83f3 146 if (scm_is_integer (spec))
0f2d19dd 147 {
e11e83f3 148 if (scm_to_long (spec) < 0)
0cd6cb2f 149 scm_misc_error (NULL, s_bad_spec, SCM_EOL);
0f2d19dd 150 s->lbnd = 0;
e11e83f3 151 s->ubnd = scm_to_long (spec) - 1;
0f2d19dd
JB
152 s->inc = 1;
153 }
154 else
155 {
d2e53ed6 156 if (!scm_is_pair (spec) || !scm_is_integer (SCM_CAR (spec)))
0cd6cb2f 157 scm_misc_error (NULL, s_bad_spec, SCM_EOL);
e11e83f3 158 s->lbnd = scm_to_long (SCM_CAR (spec));
0f2d19dd 159 sp = SCM_CDR (spec);
d2e53ed6 160 if (!scm_is_pair (sp)
e11e83f3 161 || !scm_is_integer (SCM_CAR (sp))
d2e53ed6 162 || !scm_is_null (SCM_CDR (sp)))
0cd6cb2f 163 scm_misc_error (NULL, s_bad_spec, SCM_EOL);
e11e83f3 164 s->ubnd = scm_to_long (SCM_CAR (sp));
0f2d19dd
JB
165 s->inc = 1;
166 }
167 }
168 return ra;
169}
170
f301dbf3
MV
171SCM_DEFINE (scm_make_typed_array, "make-typed-array", 2, 0, 1,
172 (SCM type, SCM fill, SCM bounds),
173 "Create and return an array of type @var{type}.")
174#define FUNC_NAME s_scm_make_typed_array
0f2d19dd 175{
f301dbf3 176 size_t k, rlen = 1;
92c2555f 177 scm_t_array_dim *s;
0f2d19dd 178 SCM ra;
1be6b49c 179
0cd6cb2f 180 ra = scm_i_shap2ra (bounds);
e038c042 181 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
04b87de5
MV
182 s = SCM_I_ARRAY_DIMS (ra);
183 k = SCM_I_ARRAY_NDIM (ra);
1be6b49c 184
0f2d19dd
JB
185 while (k--)
186 {
a3a32939 187 s[k].inc = rlen;
2caaadd1 188 SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd + 1);
0f2d19dd 189 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 190 }
a3a32939 191
f0b91039 192 if (scm_is_eq (fill, SCM_UNSPECIFIED))
f301dbf3 193 fill = SCM_UNDEFINED;
a3a32939 194
943a0a87
AW
195 SCM_I_ARRAY_V (ra) =
196 scm_make_generalized_vector (type, scm_from_size_t (rlen), fill);
a3a32939 197
04b87de5 198 if (1 == SCM_I_ARRAY_NDIM (ra) && 0 == SCM_I_ARRAY_BASE (ra))
c014a02e 199 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
04b87de5 200 return SCM_I_ARRAY_V (ra);
0f2d19dd
JB
201 return ra;
202}
1bbd0b84 203#undef FUNC_NAME
0f2d19dd 204
782a82ee
AW
205SCM
206scm_from_contiguous_typed_array (SCM type, SCM bounds, const void *bytes,
207 size_t byte_len)
208#define FUNC_NAME "scm_from_contiguous_typed_array"
209{
210 size_t k, rlen = 1;
211 scm_t_array_dim *s;
782a82ee
AW
212 SCM ra;
213 scm_t_array_handle h;
f5a51cae 214 void *elts;
782a82ee
AW
215 size_t sz;
216
782a82ee
AW
217 ra = scm_i_shap2ra (bounds);
218 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
219 s = SCM_I_ARRAY_DIMS (ra);
220 k = SCM_I_ARRAY_NDIM (ra);
221
222 while (k--)
223 {
224 s[k].inc = rlen;
225 SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd + 1);
226 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
227 }
943a0a87
AW
228 SCM_I_ARRAY_V (ra) =
229 scm_make_generalized_vector (type, scm_from_size_t (rlen), SCM_UNDEFINED);
782a82ee
AW
230
231
232 scm_array_get_handle (ra, &h);
f5a51cae
AW
233 elts = h.writable_elements;
234 sz = scm_array_handle_uniform_element_bit_size (&h);
782a82ee
AW
235 scm_array_handle_release (&h);
236
f5a51cae
AW
237 if (sz >= 8 && ((sz % 8) == 0))
238 {
239 if (byte_len % (sz / 8))
240 SCM_MISC_ERROR ("byte length not a multiple of the unit size", SCM_EOL);
241 if (byte_len / (sz / 8) != rlen)
242 SCM_MISC_ERROR ("byte length and dimensions do not match", SCM_EOL);
243 }
b0fae4ec 244 else if (sz < 8)
f5a51cae 245 {
cd48c32c
LC
246 /* byte_len ?= ceil (rlen * sz / 8) */
247 if (byte_len != (rlen * sz + 7) / 8)
f5a51cae
AW
248 SCM_MISC_ERROR ("byte length and dimensions do not match", SCM_EOL);
249 }
b0fae4ec
AW
250 else
251 /* an internal guile error, really */
252 SCM_MISC_ERROR ("uniform elements larger than 8 bits must fill whole bytes", SCM_EOL);
782a82ee 253
f5a51cae 254 memcpy (elts, bytes, byte_len);
782a82ee
AW
255
256 if (1 == SCM_I_ARRAY_NDIM (ra) && 0 == SCM_I_ARRAY_BASE (ra))
257 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
258 return SCM_I_ARRAY_V (ra);
259 return ra;
260}
261#undef FUNC_NAME
262
f301dbf3
MV
263SCM_DEFINE (scm_make_array, "make-array", 1, 0, 1,
264 (SCM fill, SCM bounds),
265 "Create and return an array.")
266#define FUNC_NAME s_scm_make_array
267{
268 return scm_make_typed_array (SCM_BOOL_T, fill, bounds);
269}
270#undef FUNC_NAME
271
0cd6cb2f
MV
272static void
273scm_i_ra_set_contp (SCM ra)
0f2d19dd 274{
04b87de5 275 size_t k = SCM_I_ARRAY_NDIM (ra);
0f2d19dd 276 if (k)
0f2d19dd 277 {
04b87de5 278 long inc = SCM_I_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 279 while (k--)
0f2d19dd 280 {
04b87de5 281 if (inc != SCM_I_ARRAY_DIMS (ra)[k].inc)
fe0c6dae 282 {
e038c042 283 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
284 return;
285 }
04b87de5
MV
286 inc *= (SCM_I_ARRAY_DIMS (ra)[k].ubnd
287 - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 288 }
0f2d19dd 289 }
e038c042 290 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
291}
292
293
3b3b36dd 294SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 295 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
296 "@code{make-shared-array} can be used to create shared subarrays of other\n"
297 "arrays. The @var{mapper} is a function that translates coordinates in\n"
298 "the new array into coordinates in the old array. A @var{mapper} must be\n"
299 "linear, and its range must stay within the bounds of the old array, but\n"
300 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 301 "@lisp\n"
b380b885
MD
302 "(define fred (make-array #f 8 8))\n"
303 "(define freds-diagonal\n"
304 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
305 "(array-set! freds-diagonal 'foo 3)\n"
306 "(array-ref fred 3 3) @result{} foo\n"
307 "(define freds-center\n"
308 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
309 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 310 "@end lisp")
1bbd0b84 311#define FUNC_NAME s_scm_make_shared_array
0f2d19dd 312{
112ba0ac 313 scm_t_array_handle old_handle;
0f2d19dd
JB
314 SCM ra;
315 SCM inds, indptr;
316 SCM imap;
112ba0ac
MV
317 size_t k;
318 ssize_t i;
2b829bbb 319 long old_base, old_min, new_min, old_max, new_max;
92c2555f 320 scm_t_array_dim *s;
b3fcac34
DH
321
322 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6 323 SCM_VALIDATE_PROC (2, mapfunc);
0cd6cb2f 324 ra = scm_i_shap2ra (dims);
112ba0ac
MV
325
326 scm_array_get_handle (oldra, &old_handle);
327
04b87de5 328 if (SCM_I_ARRAYP (oldra))
0f2d19dd 329 {
04b87de5 330 SCM_I_ARRAY_V (ra) = SCM_I_ARRAY_V (oldra);
2b829bbb 331 old_base = old_min = old_max = SCM_I_ARRAY_BASE (oldra);
112ba0ac
MV
332 s = scm_array_handle_dims (&old_handle);
333 k = scm_array_handle_rank (&old_handle);
0f2d19dd
JB
334 while (k--)
335 {
336 if (s[k].inc > 0)
337 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
338 else
339 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
340 }
341 }
342 else
343 {
04b87de5 344 SCM_I_ARRAY_V (ra) = oldra;
2b829bbb 345 old_base = old_min = 0;
02339e5b 346 old_max = scm_c_generalized_vector_length (oldra) - 1;
0f2d19dd 347 }
112ba0ac 348
0f2d19dd 349 inds = SCM_EOL;
04b87de5
MV
350 s = SCM_I_ARRAY_DIMS (ra);
351 for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
0f2d19dd 352 {
e11e83f3 353 inds = scm_cons (scm_from_long (s[k].lbnd), inds);
0f2d19dd
JB
354 if (s[k].ubnd < s[k].lbnd)
355 {
04b87de5 356 if (1 == SCM_I_ARRAY_NDIM (ra))
943a0a87
AW
357 ra = scm_make_generalized_vector (scm_array_type (ra),
358 SCM_INUM0, SCM_UNDEFINED);
0f2d19dd 359 else
943a0a87
AW
360 SCM_I_ARRAY_V (ra) =
361 scm_make_generalized_vector (scm_array_type (ra),
362 SCM_INUM0, SCM_UNDEFINED);
112ba0ac 363 scm_array_handle_release (&old_handle);
0f2d19dd
JB
364 return ra;
365 }
366 }
112ba0ac 367
fdc28395 368 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0cd6cb2f 369 i = scm_array_handle_pos (&old_handle, imap);
2b829bbb 370 SCM_I_ARRAY_BASE (ra) = new_min = new_max = i + old_base;
0f2d19dd 371 indptr = inds;
04b87de5 372 k = SCM_I_ARRAY_NDIM (ra);
0f2d19dd
JB
373 while (k--)
374 {
375 if (s[k].ubnd > s[k].lbnd)
376 {
e11e83f3 377 SCM_SETCAR (indptr, scm_sum (SCM_CAR (indptr), scm_from_int (1)));
fdc28395 378 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0cd6cb2f 379 s[k].inc = scm_array_handle_pos (&old_handle, imap) - i;
0f2d19dd
JB
380 i += s[k].inc;
381 if (s[k].inc > 0)
382 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
383 else
384 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
385 }
386 else
387 s[k].inc = new_max - new_min + 1; /* contiguous by default */
388 indptr = SCM_CDR (indptr);
389 }
112ba0ac
MV
390
391 scm_array_handle_release (&old_handle);
392
b3fcac34
DH
393 if (old_min > new_min || old_max < new_max)
394 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
04b87de5 395 if (1 == SCM_I_ARRAY_NDIM (ra) && 0 == SCM_I_ARRAY_BASE (ra))
0f2d19dd 396 {
04b87de5 397 SCM v = SCM_I_ARRAY_V (ra);
6e708ef2 398 size_t length = scm_c_generalized_vector_length (v);
74014c46
DH
399 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
400 return v;
0f2d19dd 401 if (s->ubnd < s->lbnd)
943a0a87
AW
402 return scm_make_generalized_vector (scm_array_type (ra), SCM_INUM0,
403 SCM_UNDEFINED);
0f2d19dd 404 }
0cd6cb2f 405 scm_i_ra_set_contp (ra);
0f2d19dd
JB
406 return ra;
407}
1bbd0b84 408#undef FUNC_NAME
0f2d19dd
JB
409
410
411/* args are RA . DIMS */
af45e3b0
DH
412SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
413 (SCM ra, SCM args),
1e6808ea
MG
414 "Return an array sharing contents with @var{array}, but with\n"
415 "dimensions arranged in a different order. There must be one\n"
416 "@var{dim} argument for each dimension of @var{array}.\n"
417 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
418 "and the rank of the array to be returned. Each integer in that\n"
419 "range must appear at least once in the argument list.\n"
420 "\n"
421 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
422 "dimensions in the array to be returned, their positions in the\n"
423 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
424 "may have the same value, in which case the returned array will\n"
425 "have smaller rank than @var{array}.\n"
426 "\n"
427 "@lisp\n"
b380b885
MD
428 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
429 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
430 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
431 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 432 "@end lisp")
1bbd0b84 433#define FUNC_NAME s_scm_transpose_array
0f2d19dd 434{
34d19ef6 435 SCM res, vargs;
92c2555f 436 scm_t_array_dim *s, *r;
0f2d19dd 437 int ndim, i, k;
af45e3b0 438
b3fcac34 439 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 440 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
e0e49670 441
20930f28 442 if (scm_is_generalized_vector (ra))
e0e49670
MV
443 {
444 /* Make sure that we are called with a single zero as
445 arguments.
446 */
447 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
448 SCM_WRONG_NUM_ARGS ();
449 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
450 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
451 return ra;
452 }
453
66b9d7d3 454 if (SCM_I_ARRAYP (ra))
0f2d19dd 455 {
0f2d19dd 456 vargs = scm_vector (args);
04b87de5 457 if (SCM_SIMPLE_VECTOR_LENGTH (vargs) != SCM_I_ARRAY_NDIM (ra))
b3fcac34 458 SCM_WRONG_NUM_ARGS ();
0f2d19dd 459 ndim = 0;
04b87de5 460 for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
0f2d19dd 461 {
6e708ef2 462 i = scm_to_signed_integer (SCM_SIMPLE_VECTOR_REF (vargs, k),
04b87de5 463 0, SCM_I_ARRAY_NDIM(ra));
0f2d19dd
JB
464 if (ndim < i)
465 ndim = i;
466 }
467 ndim++;
66b9d7d3 468 res = scm_i_make_array (ndim);
04b87de5
MV
469 SCM_I_ARRAY_V (res) = SCM_I_ARRAY_V (ra);
470 SCM_I_ARRAY_BASE (res) = SCM_I_ARRAY_BASE (ra);
0f2d19dd
JB
471 for (k = ndim; k--;)
472 {
04b87de5
MV
473 SCM_I_ARRAY_DIMS (res)[k].lbnd = 0;
474 SCM_I_ARRAY_DIMS (res)[k].ubnd = -1;
0f2d19dd 475 }
04b87de5 476 for (k = SCM_I_ARRAY_NDIM (ra); k--;)
0f2d19dd 477 {
6e708ef2 478 i = scm_to_int (SCM_SIMPLE_VECTOR_REF (vargs, k));
04b87de5
MV
479 s = &(SCM_I_ARRAY_DIMS (ra)[k]);
480 r = &(SCM_I_ARRAY_DIMS (res)[i]);
0f2d19dd
JB
481 if (r->ubnd < r->lbnd)
482 {
483 r->lbnd = s->lbnd;
484 r->ubnd = s->ubnd;
485 r->inc = s->inc;
486 ndim--;
487 }
488 else
489 {
490 if (r->ubnd > s->ubnd)
491 r->ubnd = s->ubnd;
492 if (r->lbnd < s->lbnd)
493 {
04b87de5 494 SCM_I_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
0f2d19dd
JB
495 r->lbnd = s->lbnd;
496 }
497 r->inc += s->inc;
498 }
499 }
b3fcac34
DH
500 if (ndim > 0)
501 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0cd6cb2f 502 scm_i_ra_set_contp (res);
0f2d19dd
JB
503 return res;
504 }
20930f28
MV
505
506 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 507}
1bbd0b84 508#undef FUNC_NAME
0f2d19dd 509
1d7bdb25
GH
510/* attempts to unroll an array into a one-dimensional array.
511 returns the unrolled array or #f if it can't be done. */
1bbd0b84 512 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 513 wouldn't have contiguous elements. */
3b3b36dd 514SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 515 (SCM ra, SCM strict),
b380b885
MD
516 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
517 "without changing their order (last subscript changing fastest), then\n"
518 "@code{array-contents} returns that shared array, otherwise it returns\n"
519 "@code{#f}. All arrays made by @var{make-array} and\n"
520 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
521 "@var{make-shared-array} may not be.\n\n"
522 "If the optional argument @var{strict} is provided, a shared array will\n"
523 "be returned only if its elements are stored internally contiguous in\n"
524 "memory.")
1bbd0b84 525#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
526{
527 SCM sra;
e0e49670 528
20930f28 529 if (scm_is_generalized_vector (ra))
e0e49670
MV
530 return ra;
531
04b87de5 532 if (SCM_I_ARRAYP (ra))
0f2d19dd 533 {
04b87de5
MV
534 size_t k, ndim = SCM_I_ARRAY_NDIM (ra), len = 1;
535 if (!SCM_I_ARRAYP (ra) || !SCM_I_ARRAY_CONTP (ra))
20930f28
MV
536 return SCM_BOOL_F;
537 for (k = 0; k < ndim; k++)
04b87de5 538 len *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
943a0a87 539 if (!SCM_UNBNDP (strict) && scm_is_true (strict))
74014c46 540 {
04b87de5 541 if (ndim && (1 != SCM_I_ARRAY_DIMS (ra)[ndim - 1].inc))
20930f28 542 return SCM_BOOL_F;
04b87de5 543 if (scm_is_bitvector (SCM_I_ARRAY_V (ra)))
20930f28 544 {
04b87de5
MV
545 if (len != scm_c_bitvector_length (SCM_I_ARRAY_V (ra)) ||
546 SCM_I_ARRAY_BASE (ra) % SCM_LONG_BIT ||
20930f28
MV
547 len % SCM_LONG_BIT)
548 return SCM_BOOL_F;
549 }
74014c46 550 }
20930f28
MV
551
552 {
04b87de5 553 SCM v = SCM_I_ARRAY_V (ra);
20930f28 554 size_t length = scm_c_generalized_vector_length (v);
04b87de5 555 if ((len == length) && 0 == SCM_I_ARRAY_BASE (ra) && SCM_I_ARRAY_DIMS (ra)->inc)
20930f28 556 return v;
0f2d19dd 557 }
20930f28 558
66b9d7d3 559 sra = scm_i_make_array (1);
04b87de5
MV
560 SCM_I_ARRAY_DIMS (sra)->lbnd = 0;
561 SCM_I_ARRAY_DIMS (sra)->ubnd = len - 1;
562 SCM_I_ARRAY_V (sra) = SCM_I_ARRAY_V (ra);
563 SCM_I_ARRAY_BASE (sra) = SCM_I_ARRAY_BASE (ra);
564 SCM_I_ARRAY_DIMS (sra)->inc = (ndim ? SCM_I_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
20930f28 565 return sra;
0f2d19dd 566 }
02339e5b
MV
567 else
568 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 569}
1bbd0b84 570#undef FUNC_NAME
0f2d19dd 571
1cc91f1b 572
0f2d19dd 573SCM
6e8d25a6 574scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
575{
576 SCM ret;
c014a02e
ML
577 long inc = 1;
578 size_t k, len = 1;
04b87de5
MV
579 for (k = SCM_I_ARRAY_NDIM (ra); k--;)
580 len *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
581 k = SCM_I_ARRAY_NDIM (ra);
582 if (SCM_I_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_I_ARRAY_DIMS (ra)[k - 1].inc)))
0f2d19dd 583 {
04b87de5 584 if (!scm_is_bitvector (SCM_I_ARRAY_V (ra)))
0f2d19dd 585 return ra;
04b87de5
MV
586 if ((len == scm_c_bitvector_length (SCM_I_ARRAY_V (ra)) &&
587 0 == SCM_I_ARRAY_BASE (ra) % SCM_LONG_BIT &&
c014a02e 588 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
589 return ra;
590 }
66b9d7d3 591 ret = scm_i_make_array (k);
04b87de5 592 SCM_I_ARRAY_BASE (ret) = 0;
0f2d19dd
JB
593 while (k--)
594 {
04b87de5
MV
595 SCM_I_ARRAY_DIMS (ret)[k].lbnd = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
596 SCM_I_ARRAY_DIMS (ret)[k].ubnd = SCM_I_ARRAY_DIMS (ra)[k].ubnd;
597 SCM_I_ARRAY_DIMS (ret)[k].inc = inc;
598 inc *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
0f2d19dd 599 }
943a0a87
AW
600 SCM_I_ARRAY_V (ret) = scm_make_generalized_vector (scm_array_type (ra),
601 scm_from_long (inc),
602 SCM_UNDEFINED);
0f2d19dd
JB
603 if (copy)
604 scm_array_copy_x (ra, ret);
605 return ret;
606}
607
608
609
3b3b36dd 610SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
03a5397a 611 (SCM ura, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
612 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
613 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 614 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
615 "If an end of file is encountered,\n"
616 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
617 "(starting at the beginning) and the remainder of the array is\n"
618 "unchanged.\n\n"
619 "The optional arguments @var{start} and @var{end} allow\n"
620 "a specified region of a vector (or linearized array) to be read,\n"
621 "leaving the remainder of the vector unchanged.\n\n"
622 "@code{uniform-array-read!} returns the number of objects read.\n"
623 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
624 "returned by @code{(current-input-port)}.")
1bbd0b84 625#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 626{
3d8d56df 627 if (SCM_UNBNDP (port_or_fd))
9de87eea 628 port_or_fd = scm_current_input_port ();
35de7ebe 629
03a5397a 630 if (scm_is_uniform_vector (ura))
20930f28 631 {
03a5397a 632 return scm_uniform_vector_read_x (ura, port_or_fd, start, end);
20930f28 633 }
04b87de5 634 else if (SCM_I_ARRAYP (ura))
20930f28 635 {
03a5397a
MV
636 size_t base, vlen, cstart, cend;
637 SCM cra, ans;
638
639 cra = scm_ra2contig (ura, 0);
04b87de5
MV
640 base = SCM_I_ARRAY_BASE (cra);
641 vlen = SCM_I_ARRAY_DIMS (cra)->inc *
642 (SCM_I_ARRAY_DIMS (cra)->ubnd - SCM_I_ARRAY_DIMS (cra)->lbnd + 1);
35de7ebe 643
03a5397a
MV
644 cstart = 0;
645 cend = vlen;
646 if (!SCM_UNBNDP (start))
1146b6cd 647 {
03a5397a
MV
648 cstart = scm_to_unsigned_integer (start, 0, vlen);
649 if (!SCM_UNBNDP (end))
650 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 651 }
35de7ebe 652
04b87de5 653 ans = scm_uniform_vector_read_x (SCM_I_ARRAY_V (cra), port_or_fd,
03a5397a
MV
654 scm_from_size_t (base + cstart),
655 scm_from_size_t (base + cend));
6c951427 656
03a5397a
MV
657 if (!scm_is_eq (cra, ura))
658 scm_array_copy_x (cra, ura);
659 return ans;
3d8d56df 660 }
03a5397a
MV
661 else
662 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 663}
1bbd0b84 664#undef FUNC_NAME
0f2d19dd 665
3b3b36dd 666SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
03a5397a 667 (SCM ura, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
668 "Writes all elements of @var{ura} as binary objects to\n"
669 "@var{port-or-fdes}.\n\n"
670 "The optional arguments @var{start}\n"
671 "and @var{end} allow\n"
672 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 673 "The number of objects actually written is returned.\n"
b380b885
MD
674 "@var{port-or-fdes} may be\n"
675 "omitted, in which case it defaults to the value returned by\n"
676 "@code{(current-output-port)}.")
1bbd0b84 677#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 678{
3d8d56df 679 if (SCM_UNBNDP (port_or_fd))
9de87eea 680 port_or_fd = scm_current_output_port ();
20930f28 681
03a5397a 682 if (scm_is_uniform_vector (ura))
20930f28 683 {
03a5397a 684 return scm_uniform_vector_write (ura, port_or_fd, start, end);
20930f28 685 }
04b87de5 686 else if (SCM_I_ARRAYP (ura))
20930f28 687 {
03a5397a
MV
688 size_t base, vlen, cstart, cend;
689 SCM cra, ans;
690
691 cra = scm_ra2contig (ura, 1);
04b87de5
MV
692 base = SCM_I_ARRAY_BASE (cra);
693 vlen = SCM_I_ARRAY_DIMS (cra)->inc *
694 (SCM_I_ARRAY_DIMS (cra)->ubnd - SCM_I_ARRAY_DIMS (cra)->lbnd + 1);
1146b6cd 695
03a5397a
MV
696 cstart = 0;
697 cend = vlen;
698 if (!SCM_UNBNDP (start))
1146b6cd 699 {
03a5397a
MV
700 cstart = scm_to_unsigned_integer (start, 0, vlen);
701 if (!SCM_UNBNDP (end))
702 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 703 }
3d8d56df 704
04b87de5 705 ans = scm_uniform_vector_write (SCM_I_ARRAY_V (cra), port_or_fd,
03a5397a
MV
706 scm_from_size_t (base + cstart),
707 scm_from_size_t (base + cend));
6c951427 708
03a5397a 709 return ans;
3d8d56df 710 }
03a5397a
MV
711 else
712 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 713}
1bbd0b84 714#undef FUNC_NAME
0f2d19dd
JB
715
716
943a0a87
AW
717static void
718list_to_array (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
719{
720 if (k == scm_array_handle_rank (handle))
721 scm_array_handle_set (handle, pos, lst);
722 else
723 {
724 scm_t_array_dim *dim = scm_array_handle_dims (handle) + k;
725 ssize_t inc = dim->inc;
726 size_t len = 1 + dim->ubnd - dim->lbnd, n;
727 char *errmsg = NULL;
728
729 n = len;
730 while (n > 0 && scm_is_pair (lst))
731 {
732 list_to_array (SCM_CAR (lst), handle, pos, k + 1);
733 pos += inc;
734 lst = SCM_CDR (lst);
735 n -= 1;
736 }
737 if (n != 0)
738 errmsg = "too few elements for array dimension ~a, need ~a";
739 if (!scm_is_null (lst))
740 errmsg = "too many elements for array dimension ~a, want ~a";
741 if (errmsg)
742 scm_misc_error (NULL, errmsg, scm_list_2 (scm_from_ulong (k),
743 scm_from_size_t (len)));
744 }
745}
746
1cc91f1b 747
f301dbf3 748SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
2caaadd1 749 (SCM type, SCM shape, SCM lst),
f301dbf3
MV
750 "Return an array of the type @var{type}\n"
751 "with elements the same as those of @var{lst}.\n"
bfad4005 752 "\n"
2caaadd1
MV
753 "The argument @var{shape} determines the number of dimensions\n"
754 "of the array and their shape. It is either an exact integer,\n"
755 "giving the\n"
756 "number of dimensions directly, or a list whose length\n"
757 "specifies the number of dimensions and each element specified\n"
758 "the lower and optionally the upper bound of the corresponding\n"
759 "dimension.\n"
760 "When the element is list of two elements, these elements\n"
761 "give the lower and upper bounds. When it is an exact\n"
762 "integer, it gives only the lower bound.")
f301dbf3 763#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 764{
2caaadd1 765 SCM row;
0f2d19dd 766 SCM ra;
bcbbea0e 767 scm_t_array_handle handle;
bfad4005 768
bfad4005 769 row = lst;
2caaadd1 770 if (scm_is_integer (shape))
0f2d19dd 771 {
2caaadd1
MV
772 size_t k = scm_to_size_t (shape);
773 shape = SCM_EOL;
bfad4005
MV
774 while (k-- > 0)
775 {
776 shape = scm_cons (scm_length (row), shape);
2caaadd1 777 if (k > 0 && !scm_is_null (row))
bfad4005
MV
778 row = scm_car (row);
779 }
780 }
781 else
782 {
2caaadd1
MV
783 SCM shape_spec = shape;
784 shape = SCM_EOL;
bfad4005
MV
785 while (1)
786 {
2caaadd1
MV
787 SCM spec = scm_car (shape_spec);
788 if (scm_is_pair (spec))
789 shape = scm_cons (spec, shape);
790 else
791 shape = scm_cons (scm_list_2 (spec,
792 scm_sum (scm_sum (spec,
793 scm_length (row)),
794 scm_from_int (-1))),
795 shape);
796 shape_spec = scm_cdr (shape_spec);
797 if (scm_is_pair (shape_spec))
798 {
799 if (!scm_is_null (row))
800 row = scm_car (row);
801 }
bfad4005
MV
802 else
803 break;
804 }
0f2d19dd 805 }
bfad4005 806
f0b91039
MV
807 ra = scm_make_typed_array (type, SCM_UNSPECIFIED,
808 scm_reverse_x (shape, SCM_EOL));
20930f28 809
bcbbea0e 810 scm_array_get_handle (ra, &handle);
943a0a87 811 list_to_array (lst, &handle, 0, 0);
bcbbea0e
MV
812 scm_array_handle_release (&handle);
813
814 return ra;
0f2d19dd 815}
1bbd0b84 816#undef FUNC_NAME
0f2d19dd 817
f301dbf3
MV
818SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
819 (SCM ndim, SCM lst),
820 "Return an array with elements the same as those of @var{lst}.")
821#define FUNC_NAME s_scm_list_to_array
822{
823 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
824}
825#undef FUNC_NAME
826
e0e49670
MV
827/* Print dimension DIM of ARRAY.
828 */
0f2d19dd 829
e0e49670 830static int
943a0a87 831scm_i_print_array_dimension (scm_t_array_handle *h, int dim, int pos,
e0e49670
MV
832 SCM port, scm_print_state *pstate)
833{
943a0a87
AW
834 if (dim == h->ndims)
835 scm_iprin1 (scm_array_handle_ref (h, pos), port, pstate);
836 else
e0e49670 837 {
943a0a87
AW
838 ssize_t i;
839 scm_putc ('(', port);
840 for (i = h->dims[dim].lbnd; i <= h->dims[dim].ubnd;
841 i++, pos += h->dims[dim].inc)
842 {
843 scm_i_print_array_dimension (h, dim+1, pos, port, pstate);
844 if (i < h->dims[dim].ubnd)
845 scm_putc (' ', port);
846 }
847 scm_putc (')', port);
e0e49670 848 }
e0e49670
MV
849 return 1;
850}
851
943a0a87 852/* Print an array.
e0e49670
MV
853*/
854
e0e49670
MV
855static int
856scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
857{
943a0a87 858 scm_t_array_handle h;
e0e49670 859 long i;
2caaadd1 860 int print_lbnds = 0, zero_size = 0, print_lens = 0;
e0e49670 861
943a0a87
AW
862 scm_array_get_handle (array, &h);
863
e0e49670 864 scm_putc ('#', port);
943a0a87
AW
865 if (h.ndims != 1 || h.dims[0].lbnd != 0)
866 scm_intprint (h.ndims, 10, port);
867 if (h.element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
868 scm_write (scm_array_handle_element_type (&h), port);
20930f28 869
943a0a87 870 for (i = 0; i < h.ndims; i++)
2caaadd1 871 {
943a0a87 872 if (h.dims[i].lbnd != 0)
2caaadd1 873 print_lbnds = 1;
943a0a87 874 if (h.dims[i].ubnd - h.dims[i].lbnd + 1 == 0)
2caaadd1
MV
875 zero_size = 1;
876 else if (zero_size)
877 print_lens = 1;
878 }
879
880 if (print_lbnds || print_lens)
943a0a87 881 for (i = 0; i < h.ndims; i++)
e0e49670 882 {
2caaadd1 883 if (print_lbnds)
e0e49670
MV
884 {
885 scm_putc ('@', port);
943a0a87 886 scm_intprint (h.dims[i].lbnd, 10, port);
2caaadd1
MV
887 }
888 if (print_lens)
889 {
890 scm_putc (':', port);
943a0a87 891 scm_intprint (h.dims[i].ubnd - h.dims[i].lbnd + 1,
2caaadd1 892 10, port);
e0e49670 893 }
e0e49670
MV
894 }
895
943a0a87 896 if (h.ndims == 0)
5f37cb63
MV
897 {
898 /* Rank zero arrays, which are really just scalars, are printed
899 specially. The consequent way would be to print them as
900
901 #0 OBJ
902
903 where OBJ is the printed representation of the scalar, but we
904 print them instead as
905
906 #0(OBJ)
907
908 to make them look less strange.
909
910 Just printing them as
911
912 OBJ
913
914 would be correct in a way as well, but zero rank arrays are
915 not really the same as Scheme values since they are boxed and
916 can be modified with array-set!, say.
917 */
918 scm_putc ('(', port);
943a0a87 919 scm_i_print_array_dimension (&h, 0, 0, port, pstate);
5f37cb63
MV
920 scm_putc (')', port);
921 return 1;
922 }
923 else
943a0a87 924 return scm_i_print_array_dimension (&h, 0, 0, port, pstate);
e0e49670 925}
1cc91f1b 926
bfad4005
MV
927/* Read an array. This function can also read vectors and uniform
928 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
929 handled here.
930
931 C is the first character read after the '#'.
932*/
933
bfad4005 934static SCM
f301dbf3 935tag_to_type (const char *tag, SCM port)
bfad4005 936{
5f37cb63
MV
937 if (*tag == '\0')
938 return SCM_BOOL_T;
939 else
940 return scm_from_locale_symbol (tag);
bfad4005
MV
941}
942
2caaadd1
MV
943static int
944read_decimal_integer (SCM port, int c, ssize_t *resp)
945{
946 ssize_t sign = 1;
947 ssize_t res = 0;
948 int got_it = 0;
949
950 if (c == '-')
951 {
952 sign = -1;
953 c = scm_getc (port);
954 }
955
956 while ('0' <= c && c <= '9')
957 {
958 res = 10*res + c-'0';
959 got_it = 1;
960 c = scm_getc (port);
961 }
962
963 if (got_it)
f30e1bdf 964 *resp = sign * res;
2caaadd1
MV
965 return c;
966}
967
bfad4005
MV
968SCM
969scm_i_read_array (SCM port, int c)
970{
5a6d139b 971 ssize_t rank;
bfad4005
MV
972 int got_rank;
973 char tag[80];
974 int tag_len;
975
2caaadd1 976 SCM shape = SCM_BOOL_F, elements;
bfad4005
MV
977
978 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
979 the array code can not deal with zero-length dimensions yet, and
980 we want to allow zero-length vectors, of course.
981 */
982 if (c == '(')
983 {
984 scm_ungetc (c, port);
985 return scm_vector (scm_read (port));
986 }
987
988 /* Disambiguate between '#f' and uniform floating point vectors.
989 */
990 if (c == 'f')
991 {
992 c = scm_getc (port);
993 if (c != '3' && c != '6')
994 {
995 if (c != EOF)
996 scm_ungetc (c, port);
997 return SCM_BOOL_F;
998 }
999 rank = 1;
1000 got_rank = 1;
1001 tag[0] = 'f';
1002 tag_len = 1;
1003 goto continue_reading_tag;
1004 }
1005
2caaadd1
MV
1006 /* Read rank.
1007 */
1008 rank = 1;
1009 c = read_decimal_integer (port, c, &rank);
1010 if (rank < 0)
1011 scm_i_input_error (NULL, port, "array rank must be non-negative",
1012 SCM_EOL);
bfad4005 1013
2caaadd1
MV
1014 /* Read tag.
1015 */
bfad4005
MV
1016 tag_len = 0;
1017 continue_reading_tag:
2caaadd1 1018 while (c != EOF && c != '(' && c != '@' && c != ':' && tag_len < 80)
bfad4005
MV
1019 {
1020 tag[tag_len++] = c;
1021 c = scm_getc (port);
1022 }
1023 tag[tag_len] = '\0';
1024
2caaadd1
MV
1025 /* Read shape.
1026 */
1027 if (c == '@' || c == ':')
bfad4005 1028 {
2caaadd1 1029 shape = SCM_EOL;
5f37cb63
MV
1030
1031 do
bfad4005 1032 {
2caaadd1
MV
1033 ssize_t lbnd = 0, len = 0;
1034 SCM s;
5f37cb63 1035
2caaadd1 1036 if (c == '@')
5f37cb63 1037 {
5f37cb63 1038 c = scm_getc (port);
2caaadd1 1039 c = read_decimal_integer (port, c, &lbnd);
5f37cb63 1040 }
2caaadd1
MV
1041
1042 s = scm_from_ssize_t (lbnd);
1043
1044 if (c == ':')
5f37cb63 1045 {
5f37cb63 1046 c = scm_getc (port);
2caaadd1 1047 c = read_decimal_integer (port, c, &len);
f30e1bdf
LC
1048 if (len < 0)
1049 scm_i_input_error (NULL, port,
1050 "array length must be non-negative",
1051 SCM_EOL);
1052
2caaadd1 1053 s = scm_list_2 (s, scm_from_ssize_t (lbnd+len-1));
5f37cb63 1054 }
2caaadd1
MV
1055
1056 shape = scm_cons (s, shape);
1057 } while (c == '@' || c == ':');
1058
1059 shape = scm_reverse_x (shape, SCM_EOL);
bfad4005
MV
1060 }
1061
1062 /* Read nested lists of elements.
1063 */
1064 if (c != '(')
1065 scm_i_input_error (NULL, port,
1066 "missing '(' in vector or array literal",
1067 SCM_EOL);
1068 scm_ungetc (c, port);
1069 elements = scm_read (port);
1070
2caaadd1 1071 if (scm_is_false (shape))
5a6d139b 1072 shape = scm_from_ssize_t (rank);
2caaadd1
MV
1073 else if (scm_ilength (shape) != rank)
1074 scm_i_input_error
1075 (NULL, port,
1076 "the number of shape specifications must match the array rank",
1077 SCM_EOL);
bfad4005 1078
5f37cb63
MV
1079 /* Handle special print syntax of rank zero arrays; see
1080 scm_i_print_array for a rationale.
1081 */
1082 if (rank == 0)
2caaadd1
MV
1083 {
1084 if (!scm_is_pair (elements))
1085 scm_i_input_error (NULL, port,
1086 "too few elements in array literal, need 1",
1087 SCM_EOL);
1088 if (!scm_is_null (SCM_CDR (elements)))
1089 scm_i_input_error (NULL, port,
1090 "too many elements in array literal, want 1",
1091 SCM_EOL);
1092 elements = SCM_CAR (elements);
1093 }
5f37cb63
MV
1094
1095 /* Construct array.
1096 */
2caaadd1 1097 return scm_list_to_typed_array (tag_to_type (tag, port), shape, elements);
bfad4005
MV
1098}
1099
ab1be174 1100
2a610be5
AW
1101static SCM
1102array_handle_ref (scm_t_array_handle *h, size_t pos)
1103{
1104 return scm_c_generalized_vector_ref (SCM_I_ARRAY_V (h->array), pos);
1105}
1106
1107static void
1108array_handle_set (scm_t_array_handle *h, size_t pos, SCM val)
1109{
1110 scm_c_generalized_vector_set_x (SCM_I_ARRAY_V (h->array), pos, val);
1111}
1112
1113/* FIXME: should be handle for vect? maybe not, because of dims */
1114static void
1115array_get_handle (SCM array, scm_t_array_handle *h)
1116{
1117 scm_t_array_handle vh;
1118 scm_array_get_handle (SCM_I_ARRAY_V (array), &vh);
1119 h->element_type = vh.element_type;
1120 h->elements = vh.elements;
1121 h->writable_elements = vh.writable_elements;
1122 scm_array_handle_release (&vh);
1123
1124 h->dims = SCM_I_ARRAY_DIMS (array);
1125 h->ndims = SCM_I_ARRAY_NDIM (array);
1126 h->base = SCM_I_ARRAY_BASE (array);
1127}
1128
735bcfe5
AW
1129SCM_ARRAY_IMPLEMENTATION (SCM_SMOB_TYPE_BITS (scm_i_tc16_array),
1130 SCM_SMOB_TYPE_MASK,
2a610be5
AW
1131 array_handle_ref, array_handle_set,
1132 array_get_handle);
1133
0f2d19dd 1134void
2fa901a5 1135scm_init_arrays ()
0f2d19dd 1136{
04b87de5 1137 scm_i_tc16_array = scm_make_smob_type ("array", 0);
04b87de5
MV
1138 scm_set_smob_print (scm_i_tc16_array, scm_i_print_array);
1139 scm_set_smob_equalp (scm_i_tc16_array, scm_array_equal_p);
1140
0f2d19dd 1141 scm_add_feature ("array");
20930f28 1142
2fa901a5 1143#include "libguile/arrays.x"
bfad4005 1144
0f2d19dd 1145}
89e00824
ML
1146
1147/*
1148 Local Variables:
1149 c-file-style: "gnu"
1150 End:
1151*/