fix thinko in api-memory.texi
[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
MV
58#define SCM_SET_ARRAY_CONTIGUOUS_FLAG(x) \
59 (SCM_SET_CELL_WORD_0 ((x), SCM_CELL_WORD_0 (x) | SCM_I_ARRAY_FLAG_CONTIGUOUS))
60#define SCM_CLR_ARRAY_CONTIGUOUS_FLAG(x) \
61 (SCM_SET_CELL_WORD_0 ((x), SCM_CELL_WORD_0 (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;
214 void *base;
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);
233 base = scm_array_handle_uniform_writable_elements (&h);
234 sz = scm_array_handle_uniform_element_size (&h);
235 scm_array_handle_release (&h);
236
237 if (byte_len % sz)
238 SCM_MISC_ERROR ("byte length not a multiple of the unit size", SCM_EOL);
239 if (byte_len / sz != rlen)
240 SCM_MISC_ERROR ("byte length and dimensions do not match", SCM_EOL);
241
242 memcpy (base, bytes, byte_len);
243
244 if (1 == SCM_I_ARRAY_NDIM (ra) && 0 == SCM_I_ARRAY_BASE (ra))
245 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
246 return SCM_I_ARRAY_V (ra);
247 return ra;
248}
249#undef FUNC_NAME
250
f301dbf3
MV
251SCM_DEFINE (scm_make_array, "make-array", 1, 0, 1,
252 (SCM fill, SCM bounds),
253 "Create and return an array.")
254#define FUNC_NAME s_scm_make_array
255{
256 return scm_make_typed_array (SCM_BOOL_T, fill, bounds);
257}
258#undef FUNC_NAME
259
0cd6cb2f
MV
260static void
261scm_i_ra_set_contp (SCM ra)
0f2d19dd 262{
04b87de5 263 size_t k = SCM_I_ARRAY_NDIM (ra);
0f2d19dd 264 if (k)
0f2d19dd 265 {
04b87de5 266 long inc = SCM_I_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 267 while (k--)
0f2d19dd 268 {
04b87de5 269 if (inc != SCM_I_ARRAY_DIMS (ra)[k].inc)
fe0c6dae 270 {
e038c042 271 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
272 return;
273 }
04b87de5
MV
274 inc *= (SCM_I_ARRAY_DIMS (ra)[k].ubnd
275 - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 276 }
0f2d19dd 277 }
e038c042 278 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
279}
280
281
3b3b36dd 282SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 283 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
284 "@code{make-shared-array} can be used to create shared subarrays of other\n"
285 "arrays. The @var{mapper} is a function that translates coordinates in\n"
286 "the new array into coordinates in the old array. A @var{mapper} must be\n"
287 "linear, and its range must stay within the bounds of the old array, but\n"
288 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 289 "@lisp\n"
b380b885
MD
290 "(define fred (make-array #f 8 8))\n"
291 "(define freds-diagonal\n"
292 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
293 "(array-set! freds-diagonal 'foo 3)\n"
294 "(array-ref fred 3 3) @result{} foo\n"
295 "(define freds-center\n"
296 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
297 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 298 "@end lisp")
1bbd0b84 299#define FUNC_NAME s_scm_make_shared_array
0f2d19dd 300{
112ba0ac 301 scm_t_array_handle old_handle;
0f2d19dd
JB
302 SCM ra;
303 SCM inds, indptr;
304 SCM imap;
112ba0ac
MV
305 size_t k;
306 ssize_t i;
2b829bbb 307 long old_base, old_min, new_min, old_max, new_max;
92c2555f 308 scm_t_array_dim *s;
b3fcac34
DH
309
310 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6 311 SCM_VALIDATE_PROC (2, mapfunc);
0cd6cb2f 312 ra = scm_i_shap2ra (dims);
112ba0ac
MV
313
314 scm_array_get_handle (oldra, &old_handle);
315
04b87de5 316 if (SCM_I_ARRAYP (oldra))
0f2d19dd 317 {
04b87de5 318 SCM_I_ARRAY_V (ra) = SCM_I_ARRAY_V (oldra);
2b829bbb 319 old_base = old_min = old_max = SCM_I_ARRAY_BASE (oldra);
112ba0ac
MV
320 s = scm_array_handle_dims (&old_handle);
321 k = scm_array_handle_rank (&old_handle);
0f2d19dd
JB
322 while (k--)
323 {
324 if (s[k].inc > 0)
325 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
326 else
327 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
328 }
329 }
330 else
331 {
04b87de5 332 SCM_I_ARRAY_V (ra) = oldra;
2b829bbb 333 old_base = old_min = 0;
02339e5b 334 old_max = scm_c_generalized_vector_length (oldra) - 1;
0f2d19dd 335 }
112ba0ac 336
0f2d19dd 337 inds = SCM_EOL;
04b87de5
MV
338 s = SCM_I_ARRAY_DIMS (ra);
339 for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
0f2d19dd 340 {
e11e83f3 341 inds = scm_cons (scm_from_long (s[k].lbnd), inds);
0f2d19dd
JB
342 if (s[k].ubnd < s[k].lbnd)
343 {
04b87de5 344 if (1 == SCM_I_ARRAY_NDIM (ra))
943a0a87
AW
345 ra = scm_make_generalized_vector (scm_array_type (ra),
346 SCM_INUM0, SCM_UNDEFINED);
0f2d19dd 347 else
943a0a87
AW
348 SCM_I_ARRAY_V (ra) =
349 scm_make_generalized_vector (scm_array_type (ra),
350 SCM_INUM0, SCM_UNDEFINED);
112ba0ac 351 scm_array_handle_release (&old_handle);
0f2d19dd
JB
352 return ra;
353 }
354 }
112ba0ac 355
fdc28395 356 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0cd6cb2f 357 i = scm_array_handle_pos (&old_handle, imap);
2b829bbb 358 SCM_I_ARRAY_BASE (ra) = new_min = new_max = i + old_base;
0f2d19dd 359 indptr = inds;
04b87de5 360 k = SCM_I_ARRAY_NDIM (ra);
0f2d19dd
JB
361 while (k--)
362 {
363 if (s[k].ubnd > s[k].lbnd)
364 {
e11e83f3 365 SCM_SETCAR (indptr, scm_sum (SCM_CAR (indptr), scm_from_int (1)));
fdc28395 366 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0cd6cb2f 367 s[k].inc = scm_array_handle_pos (&old_handle, imap) - i;
0f2d19dd
JB
368 i += s[k].inc;
369 if (s[k].inc > 0)
370 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
371 else
372 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
373 }
374 else
375 s[k].inc = new_max - new_min + 1; /* contiguous by default */
376 indptr = SCM_CDR (indptr);
377 }
112ba0ac
MV
378
379 scm_array_handle_release (&old_handle);
380
b3fcac34
DH
381 if (old_min > new_min || old_max < new_max)
382 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
04b87de5 383 if (1 == SCM_I_ARRAY_NDIM (ra) && 0 == SCM_I_ARRAY_BASE (ra))
0f2d19dd 384 {
04b87de5 385 SCM v = SCM_I_ARRAY_V (ra);
6e708ef2 386 size_t length = scm_c_generalized_vector_length (v);
74014c46
DH
387 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
388 return v;
0f2d19dd 389 if (s->ubnd < s->lbnd)
943a0a87
AW
390 return scm_make_generalized_vector (scm_array_type (ra), SCM_INUM0,
391 SCM_UNDEFINED);
0f2d19dd 392 }
0cd6cb2f 393 scm_i_ra_set_contp (ra);
0f2d19dd
JB
394 return ra;
395}
1bbd0b84 396#undef FUNC_NAME
0f2d19dd
JB
397
398
399/* args are RA . DIMS */
af45e3b0
DH
400SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
401 (SCM ra, SCM args),
1e6808ea
MG
402 "Return an array sharing contents with @var{array}, but with\n"
403 "dimensions arranged in a different order. There must be one\n"
404 "@var{dim} argument for each dimension of @var{array}.\n"
405 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
406 "and the rank of the array to be returned. Each integer in that\n"
407 "range must appear at least once in the argument list.\n"
408 "\n"
409 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
410 "dimensions in the array to be returned, their positions in the\n"
411 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
412 "may have the same value, in which case the returned array will\n"
413 "have smaller rank than @var{array}.\n"
414 "\n"
415 "@lisp\n"
b380b885
MD
416 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
417 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
418 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
419 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 420 "@end lisp")
1bbd0b84 421#define FUNC_NAME s_scm_transpose_array
0f2d19dd 422{
34d19ef6 423 SCM res, vargs;
92c2555f 424 scm_t_array_dim *s, *r;
0f2d19dd 425 int ndim, i, k;
af45e3b0 426
b3fcac34 427 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 428 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
e0e49670 429
20930f28 430 if (scm_is_generalized_vector (ra))
e0e49670
MV
431 {
432 /* Make sure that we are called with a single zero as
433 arguments.
434 */
435 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
436 SCM_WRONG_NUM_ARGS ();
437 SCM_VALIDATE_INT_COPY (SCM_ARG2, SCM_CAR (args), i);
438 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args), i == 0);
439 return ra;
440 }
441
66b9d7d3 442 if (SCM_I_ARRAYP (ra))
0f2d19dd 443 {
0f2d19dd 444 vargs = scm_vector (args);
04b87de5 445 if (SCM_SIMPLE_VECTOR_LENGTH (vargs) != SCM_I_ARRAY_NDIM (ra))
b3fcac34 446 SCM_WRONG_NUM_ARGS ();
0f2d19dd 447 ndim = 0;
04b87de5 448 for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
0f2d19dd 449 {
6e708ef2 450 i = scm_to_signed_integer (SCM_SIMPLE_VECTOR_REF (vargs, k),
04b87de5 451 0, SCM_I_ARRAY_NDIM(ra));
0f2d19dd
JB
452 if (ndim < i)
453 ndim = i;
454 }
455 ndim++;
66b9d7d3 456 res = scm_i_make_array (ndim);
04b87de5
MV
457 SCM_I_ARRAY_V (res) = SCM_I_ARRAY_V (ra);
458 SCM_I_ARRAY_BASE (res) = SCM_I_ARRAY_BASE (ra);
0f2d19dd
JB
459 for (k = ndim; k--;)
460 {
04b87de5
MV
461 SCM_I_ARRAY_DIMS (res)[k].lbnd = 0;
462 SCM_I_ARRAY_DIMS (res)[k].ubnd = -1;
0f2d19dd 463 }
04b87de5 464 for (k = SCM_I_ARRAY_NDIM (ra); k--;)
0f2d19dd 465 {
6e708ef2 466 i = scm_to_int (SCM_SIMPLE_VECTOR_REF (vargs, k));
04b87de5
MV
467 s = &(SCM_I_ARRAY_DIMS (ra)[k]);
468 r = &(SCM_I_ARRAY_DIMS (res)[i]);
0f2d19dd
JB
469 if (r->ubnd < r->lbnd)
470 {
471 r->lbnd = s->lbnd;
472 r->ubnd = s->ubnd;
473 r->inc = s->inc;
474 ndim--;
475 }
476 else
477 {
478 if (r->ubnd > s->ubnd)
479 r->ubnd = s->ubnd;
480 if (r->lbnd < s->lbnd)
481 {
04b87de5 482 SCM_I_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
0f2d19dd
JB
483 r->lbnd = s->lbnd;
484 }
485 r->inc += s->inc;
486 }
487 }
b3fcac34
DH
488 if (ndim > 0)
489 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0cd6cb2f 490 scm_i_ra_set_contp (res);
0f2d19dd
JB
491 return res;
492 }
20930f28
MV
493
494 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 495}
1bbd0b84 496#undef FUNC_NAME
0f2d19dd 497
1d7bdb25
GH
498/* attempts to unroll an array into a one-dimensional array.
499 returns the unrolled array or #f if it can't be done. */
1bbd0b84 500 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 501 wouldn't have contiguous elements. */
3b3b36dd 502SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 503 (SCM ra, SCM strict),
b380b885
MD
504 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
505 "without changing their order (last subscript changing fastest), then\n"
506 "@code{array-contents} returns that shared array, otherwise it returns\n"
507 "@code{#f}. All arrays made by @var{make-array} and\n"
508 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
509 "@var{make-shared-array} may not be.\n\n"
510 "If the optional argument @var{strict} is provided, a shared array will\n"
511 "be returned only if its elements are stored internally contiguous in\n"
512 "memory.")
1bbd0b84 513#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
514{
515 SCM sra;
e0e49670 516
20930f28 517 if (scm_is_generalized_vector (ra))
e0e49670
MV
518 return ra;
519
04b87de5 520 if (SCM_I_ARRAYP (ra))
0f2d19dd 521 {
04b87de5
MV
522 size_t k, ndim = SCM_I_ARRAY_NDIM (ra), len = 1;
523 if (!SCM_I_ARRAYP (ra) || !SCM_I_ARRAY_CONTP (ra))
20930f28
MV
524 return SCM_BOOL_F;
525 for (k = 0; k < ndim; k++)
04b87de5 526 len *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
943a0a87 527 if (!SCM_UNBNDP (strict) && scm_is_true (strict))
74014c46 528 {
04b87de5 529 if (ndim && (1 != SCM_I_ARRAY_DIMS (ra)[ndim - 1].inc))
20930f28 530 return SCM_BOOL_F;
04b87de5 531 if (scm_is_bitvector (SCM_I_ARRAY_V (ra)))
20930f28 532 {
04b87de5
MV
533 if (len != scm_c_bitvector_length (SCM_I_ARRAY_V (ra)) ||
534 SCM_I_ARRAY_BASE (ra) % SCM_LONG_BIT ||
20930f28
MV
535 len % SCM_LONG_BIT)
536 return SCM_BOOL_F;
537 }
74014c46 538 }
20930f28
MV
539
540 {
04b87de5 541 SCM v = SCM_I_ARRAY_V (ra);
20930f28 542 size_t length = scm_c_generalized_vector_length (v);
04b87de5 543 if ((len == length) && 0 == SCM_I_ARRAY_BASE (ra) && SCM_I_ARRAY_DIMS (ra)->inc)
20930f28 544 return v;
0f2d19dd 545 }
20930f28 546
66b9d7d3 547 sra = scm_i_make_array (1);
04b87de5
MV
548 SCM_I_ARRAY_DIMS (sra)->lbnd = 0;
549 SCM_I_ARRAY_DIMS (sra)->ubnd = len - 1;
550 SCM_I_ARRAY_V (sra) = SCM_I_ARRAY_V (ra);
551 SCM_I_ARRAY_BASE (sra) = SCM_I_ARRAY_BASE (ra);
552 SCM_I_ARRAY_DIMS (sra)->inc = (ndim ? SCM_I_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
20930f28 553 return sra;
0f2d19dd 554 }
02339e5b
MV
555 else
556 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 557}
1bbd0b84 558#undef FUNC_NAME
0f2d19dd 559
1cc91f1b 560
0f2d19dd 561SCM
6e8d25a6 562scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
563{
564 SCM ret;
c014a02e
ML
565 long inc = 1;
566 size_t k, len = 1;
04b87de5
MV
567 for (k = SCM_I_ARRAY_NDIM (ra); k--;)
568 len *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
569 k = SCM_I_ARRAY_NDIM (ra);
570 if (SCM_I_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_I_ARRAY_DIMS (ra)[k - 1].inc)))
0f2d19dd 571 {
04b87de5 572 if (!scm_is_bitvector (SCM_I_ARRAY_V (ra)))
0f2d19dd 573 return ra;
04b87de5
MV
574 if ((len == scm_c_bitvector_length (SCM_I_ARRAY_V (ra)) &&
575 0 == SCM_I_ARRAY_BASE (ra) % SCM_LONG_BIT &&
c014a02e 576 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
577 return ra;
578 }
66b9d7d3 579 ret = scm_i_make_array (k);
04b87de5 580 SCM_I_ARRAY_BASE (ret) = 0;
0f2d19dd
JB
581 while (k--)
582 {
04b87de5
MV
583 SCM_I_ARRAY_DIMS (ret)[k].lbnd = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
584 SCM_I_ARRAY_DIMS (ret)[k].ubnd = SCM_I_ARRAY_DIMS (ra)[k].ubnd;
585 SCM_I_ARRAY_DIMS (ret)[k].inc = inc;
586 inc *= SCM_I_ARRAY_DIMS (ra)[k].ubnd - SCM_I_ARRAY_DIMS (ra)[k].lbnd + 1;
0f2d19dd 587 }
943a0a87
AW
588 SCM_I_ARRAY_V (ret) = scm_make_generalized_vector (scm_array_type (ra),
589 scm_from_long (inc),
590 SCM_UNDEFINED);
0f2d19dd
JB
591 if (copy)
592 scm_array_copy_x (ra, ret);
593 return ret;
594}
595
596
597
3b3b36dd 598SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
03a5397a 599 (SCM ura, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
600 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
601 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 602 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
603 "If an end of file is encountered,\n"
604 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
605 "(starting at the beginning) and the remainder of the array is\n"
606 "unchanged.\n\n"
607 "The optional arguments @var{start} and @var{end} allow\n"
608 "a specified region of a vector (or linearized array) to be read,\n"
609 "leaving the remainder of the vector unchanged.\n\n"
610 "@code{uniform-array-read!} returns the number of objects read.\n"
611 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
612 "returned by @code{(current-input-port)}.")
1bbd0b84 613#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 614{
3d8d56df 615 if (SCM_UNBNDP (port_or_fd))
9de87eea 616 port_or_fd = scm_current_input_port ();
35de7ebe 617
03a5397a 618 if (scm_is_uniform_vector (ura))
20930f28 619 {
03a5397a 620 return scm_uniform_vector_read_x (ura, port_or_fd, start, end);
20930f28 621 }
04b87de5 622 else if (SCM_I_ARRAYP (ura))
20930f28 623 {
03a5397a
MV
624 size_t base, vlen, cstart, cend;
625 SCM cra, ans;
626
627 cra = scm_ra2contig (ura, 0);
04b87de5
MV
628 base = SCM_I_ARRAY_BASE (cra);
629 vlen = SCM_I_ARRAY_DIMS (cra)->inc *
630 (SCM_I_ARRAY_DIMS (cra)->ubnd - SCM_I_ARRAY_DIMS (cra)->lbnd + 1);
35de7ebe 631
03a5397a
MV
632 cstart = 0;
633 cend = vlen;
634 if (!SCM_UNBNDP (start))
1146b6cd 635 {
03a5397a
MV
636 cstart = scm_to_unsigned_integer (start, 0, vlen);
637 if (!SCM_UNBNDP (end))
638 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 639 }
35de7ebe 640
04b87de5 641 ans = scm_uniform_vector_read_x (SCM_I_ARRAY_V (cra), port_or_fd,
03a5397a
MV
642 scm_from_size_t (base + cstart),
643 scm_from_size_t (base + cend));
6c951427 644
03a5397a
MV
645 if (!scm_is_eq (cra, ura))
646 scm_array_copy_x (cra, ura);
647 return ans;
3d8d56df 648 }
03a5397a
MV
649 else
650 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 651}
1bbd0b84 652#undef FUNC_NAME
0f2d19dd 653
3b3b36dd 654SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
03a5397a 655 (SCM ura, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
656 "Writes all elements of @var{ura} as binary objects to\n"
657 "@var{port-or-fdes}.\n\n"
658 "The optional arguments @var{start}\n"
659 "and @var{end} allow\n"
660 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 661 "The number of objects actually written is returned.\n"
b380b885
MD
662 "@var{port-or-fdes} may be\n"
663 "omitted, in which case it defaults to the value returned by\n"
664 "@code{(current-output-port)}.")
1bbd0b84 665#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 666{
3d8d56df 667 if (SCM_UNBNDP (port_or_fd))
9de87eea 668 port_or_fd = scm_current_output_port ();
20930f28 669
03a5397a 670 if (scm_is_uniform_vector (ura))
20930f28 671 {
03a5397a 672 return scm_uniform_vector_write (ura, port_or_fd, start, end);
20930f28 673 }
04b87de5 674 else if (SCM_I_ARRAYP (ura))
20930f28 675 {
03a5397a
MV
676 size_t base, vlen, cstart, cend;
677 SCM cra, ans;
678
679 cra = scm_ra2contig (ura, 1);
04b87de5
MV
680 base = SCM_I_ARRAY_BASE (cra);
681 vlen = SCM_I_ARRAY_DIMS (cra)->inc *
682 (SCM_I_ARRAY_DIMS (cra)->ubnd - SCM_I_ARRAY_DIMS (cra)->lbnd + 1);
1146b6cd 683
03a5397a
MV
684 cstart = 0;
685 cend = vlen;
686 if (!SCM_UNBNDP (start))
1146b6cd 687 {
03a5397a
MV
688 cstart = scm_to_unsigned_integer (start, 0, vlen);
689 if (!SCM_UNBNDP (end))
690 cend = scm_to_unsigned_integer (end, cstart, vlen);
1146b6cd 691 }
3d8d56df 692
04b87de5 693 ans = scm_uniform_vector_write (SCM_I_ARRAY_V (cra), port_or_fd,
03a5397a
MV
694 scm_from_size_t (base + cstart),
695 scm_from_size_t (base + cend));
6c951427 696
03a5397a 697 return ans;
3d8d56df 698 }
03a5397a
MV
699 else
700 scm_wrong_type_arg_msg (NULL, 0, ura, "array");
0f2d19dd 701}
1bbd0b84 702#undef FUNC_NAME
0f2d19dd
JB
703
704
943a0a87
AW
705static void
706list_to_array (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
707{
708 if (k == scm_array_handle_rank (handle))
709 scm_array_handle_set (handle, pos, lst);
710 else
711 {
712 scm_t_array_dim *dim = scm_array_handle_dims (handle) + k;
713 ssize_t inc = dim->inc;
714 size_t len = 1 + dim->ubnd - dim->lbnd, n;
715 char *errmsg = NULL;
716
717 n = len;
718 while (n > 0 && scm_is_pair (lst))
719 {
720 list_to_array (SCM_CAR (lst), handle, pos, k + 1);
721 pos += inc;
722 lst = SCM_CDR (lst);
723 n -= 1;
724 }
725 if (n != 0)
726 errmsg = "too few elements for array dimension ~a, need ~a";
727 if (!scm_is_null (lst))
728 errmsg = "too many elements for array dimension ~a, want ~a";
729 if (errmsg)
730 scm_misc_error (NULL, errmsg, scm_list_2 (scm_from_ulong (k),
731 scm_from_size_t (len)));
732 }
733}
734
1cc91f1b 735
f301dbf3 736SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
2caaadd1 737 (SCM type, SCM shape, SCM lst),
f301dbf3
MV
738 "Return an array of the type @var{type}\n"
739 "with elements the same as those of @var{lst}.\n"
bfad4005 740 "\n"
2caaadd1
MV
741 "The argument @var{shape} determines the number of dimensions\n"
742 "of the array and their shape. It is either an exact integer,\n"
743 "giving the\n"
744 "number of dimensions directly, or a list whose length\n"
745 "specifies the number of dimensions and each element specified\n"
746 "the lower and optionally the upper bound of the corresponding\n"
747 "dimension.\n"
748 "When the element is list of two elements, these elements\n"
749 "give the lower and upper bounds. When it is an exact\n"
750 "integer, it gives only the lower bound.")
f301dbf3 751#define FUNC_NAME s_scm_list_to_typed_array
0f2d19dd 752{
2caaadd1 753 SCM row;
0f2d19dd 754 SCM ra;
bcbbea0e 755 scm_t_array_handle handle;
bfad4005 756
bfad4005 757 row = lst;
2caaadd1 758 if (scm_is_integer (shape))
0f2d19dd 759 {
2caaadd1
MV
760 size_t k = scm_to_size_t (shape);
761 shape = SCM_EOL;
bfad4005
MV
762 while (k-- > 0)
763 {
764 shape = scm_cons (scm_length (row), shape);
2caaadd1 765 if (k > 0 && !scm_is_null (row))
bfad4005
MV
766 row = scm_car (row);
767 }
768 }
769 else
770 {
2caaadd1
MV
771 SCM shape_spec = shape;
772 shape = SCM_EOL;
bfad4005
MV
773 while (1)
774 {
2caaadd1
MV
775 SCM spec = scm_car (shape_spec);
776 if (scm_is_pair (spec))
777 shape = scm_cons (spec, shape);
778 else
779 shape = scm_cons (scm_list_2 (spec,
780 scm_sum (scm_sum (spec,
781 scm_length (row)),
782 scm_from_int (-1))),
783 shape);
784 shape_spec = scm_cdr (shape_spec);
785 if (scm_is_pair (shape_spec))
786 {
787 if (!scm_is_null (row))
788 row = scm_car (row);
789 }
bfad4005
MV
790 else
791 break;
792 }
0f2d19dd 793 }
bfad4005 794
f0b91039
MV
795 ra = scm_make_typed_array (type, SCM_UNSPECIFIED,
796 scm_reverse_x (shape, SCM_EOL));
20930f28 797
bcbbea0e 798 scm_array_get_handle (ra, &handle);
943a0a87 799 list_to_array (lst, &handle, 0, 0);
bcbbea0e
MV
800 scm_array_handle_release (&handle);
801
802 return ra;
0f2d19dd 803}
1bbd0b84 804#undef FUNC_NAME
0f2d19dd 805
f301dbf3
MV
806SCM_DEFINE (scm_list_to_array, "list->array", 2, 0, 0,
807 (SCM ndim, SCM lst),
808 "Return an array with elements the same as those of @var{lst}.")
809#define FUNC_NAME s_scm_list_to_array
810{
811 return scm_list_to_typed_array (SCM_BOOL_T, ndim, lst);
812}
813#undef FUNC_NAME
814
e0e49670
MV
815/* Print dimension DIM of ARRAY.
816 */
0f2d19dd 817
e0e49670 818static int
943a0a87 819scm_i_print_array_dimension (scm_t_array_handle *h, int dim, int pos,
e0e49670
MV
820 SCM port, scm_print_state *pstate)
821{
943a0a87
AW
822 if (dim == h->ndims)
823 scm_iprin1 (scm_array_handle_ref (h, pos), port, pstate);
824 else
e0e49670 825 {
943a0a87
AW
826 ssize_t i;
827 scm_putc ('(', port);
828 for (i = h->dims[dim].lbnd; i <= h->dims[dim].ubnd;
829 i++, pos += h->dims[dim].inc)
830 {
831 scm_i_print_array_dimension (h, dim+1, pos, port, pstate);
832 if (i < h->dims[dim].ubnd)
833 scm_putc (' ', port);
834 }
835 scm_putc (')', port);
e0e49670 836 }
e0e49670
MV
837 return 1;
838}
839
943a0a87 840/* Print an array.
e0e49670
MV
841*/
842
e0e49670
MV
843static int
844scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
845{
943a0a87 846 scm_t_array_handle h;
e0e49670 847 long i;
2caaadd1 848 int print_lbnds = 0, zero_size = 0, print_lens = 0;
e0e49670 849
943a0a87
AW
850 scm_array_get_handle (array, &h);
851
e0e49670 852 scm_putc ('#', port);
943a0a87
AW
853 if (h.ndims != 1 || h.dims[0].lbnd != 0)
854 scm_intprint (h.ndims, 10, port);
855 if (h.element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
856 scm_write (scm_array_handle_element_type (&h), port);
20930f28 857
943a0a87 858 for (i = 0; i < h.ndims; i++)
2caaadd1 859 {
943a0a87 860 if (h.dims[i].lbnd != 0)
2caaadd1 861 print_lbnds = 1;
943a0a87 862 if (h.dims[i].ubnd - h.dims[i].lbnd + 1 == 0)
2caaadd1
MV
863 zero_size = 1;
864 else if (zero_size)
865 print_lens = 1;
866 }
867
868 if (print_lbnds || print_lens)
943a0a87 869 for (i = 0; i < h.ndims; i++)
e0e49670 870 {
2caaadd1 871 if (print_lbnds)
e0e49670
MV
872 {
873 scm_putc ('@', port);
943a0a87 874 scm_intprint (h.dims[i].lbnd, 10, port);
2caaadd1
MV
875 }
876 if (print_lens)
877 {
878 scm_putc (':', port);
943a0a87 879 scm_intprint (h.dims[i].ubnd - h.dims[i].lbnd + 1,
2caaadd1 880 10, port);
e0e49670 881 }
e0e49670
MV
882 }
883
943a0a87 884 if (h.ndims == 0)
5f37cb63
MV
885 {
886 /* Rank zero arrays, which are really just scalars, are printed
887 specially. The consequent way would be to print them as
888
889 #0 OBJ
890
891 where OBJ is the printed representation of the scalar, but we
892 print them instead as
893
894 #0(OBJ)
895
896 to make them look less strange.
897
898 Just printing them as
899
900 OBJ
901
902 would be correct in a way as well, but zero rank arrays are
903 not really the same as Scheme values since they are boxed and
904 can be modified with array-set!, say.
905 */
906 scm_putc ('(', port);
943a0a87 907 scm_i_print_array_dimension (&h, 0, 0, port, pstate);
5f37cb63
MV
908 scm_putc (')', port);
909 return 1;
910 }
911 else
943a0a87 912 return scm_i_print_array_dimension (&h, 0, 0, port, pstate);
e0e49670 913}
1cc91f1b 914
bfad4005
MV
915/* Read an array. This function can also read vectors and uniform
916 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
917 handled here.
918
919 C is the first character read after the '#'.
920*/
921
bfad4005 922static SCM
f301dbf3 923tag_to_type (const char *tag, SCM port)
bfad4005 924{
5f37cb63
MV
925 if (*tag == '\0')
926 return SCM_BOOL_T;
927 else
928 return scm_from_locale_symbol (tag);
bfad4005
MV
929}
930
2caaadd1
MV
931static int
932read_decimal_integer (SCM port, int c, ssize_t *resp)
933{
934 ssize_t sign = 1;
935 ssize_t res = 0;
936 int got_it = 0;
937
938 if (c == '-')
939 {
940 sign = -1;
941 c = scm_getc (port);
942 }
943
944 while ('0' <= c && c <= '9')
945 {
946 res = 10*res + c-'0';
947 got_it = 1;
948 c = scm_getc (port);
949 }
950
951 if (got_it)
f30e1bdf 952 *resp = sign * res;
2caaadd1
MV
953 return c;
954}
955
bfad4005
MV
956SCM
957scm_i_read_array (SCM port, int c)
958{
5a6d139b 959 ssize_t rank;
bfad4005
MV
960 int got_rank;
961 char tag[80];
962 int tag_len;
963
2caaadd1 964 SCM shape = SCM_BOOL_F, elements;
bfad4005
MV
965
966 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
967 the array code can not deal with zero-length dimensions yet, and
968 we want to allow zero-length vectors, of course.
969 */
970 if (c == '(')
971 {
972 scm_ungetc (c, port);
973 return scm_vector (scm_read (port));
974 }
975
976 /* Disambiguate between '#f' and uniform floating point vectors.
977 */
978 if (c == 'f')
979 {
980 c = scm_getc (port);
981 if (c != '3' && c != '6')
982 {
983 if (c != EOF)
984 scm_ungetc (c, port);
985 return SCM_BOOL_F;
986 }
987 rank = 1;
988 got_rank = 1;
989 tag[0] = 'f';
990 tag_len = 1;
991 goto continue_reading_tag;
992 }
993
2caaadd1
MV
994 /* Read rank.
995 */
996 rank = 1;
997 c = read_decimal_integer (port, c, &rank);
998 if (rank < 0)
999 scm_i_input_error (NULL, port, "array rank must be non-negative",
1000 SCM_EOL);
bfad4005 1001
2caaadd1
MV
1002 /* Read tag.
1003 */
bfad4005
MV
1004 tag_len = 0;
1005 continue_reading_tag:
2caaadd1 1006 while (c != EOF && c != '(' && c != '@' && c != ':' && tag_len < 80)
bfad4005
MV
1007 {
1008 tag[tag_len++] = c;
1009 c = scm_getc (port);
1010 }
1011 tag[tag_len] = '\0';
1012
2caaadd1
MV
1013 /* Read shape.
1014 */
1015 if (c == '@' || c == ':')
bfad4005 1016 {
2caaadd1 1017 shape = SCM_EOL;
5f37cb63
MV
1018
1019 do
bfad4005 1020 {
2caaadd1
MV
1021 ssize_t lbnd = 0, len = 0;
1022 SCM s;
5f37cb63 1023
2caaadd1 1024 if (c == '@')
5f37cb63 1025 {
5f37cb63 1026 c = scm_getc (port);
2caaadd1 1027 c = read_decimal_integer (port, c, &lbnd);
5f37cb63 1028 }
2caaadd1
MV
1029
1030 s = scm_from_ssize_t (lbnd);
1031
1032 if (c == ':')
5f37cb63 1033 {
5f37cb63 1034 c = scm_getc (port);
2caaadd1 1035 c = read_decimal_integer (port, c, &len);
f30e1bdf
LC
1036 if (len < 0)
1037 scm_i_input_error (NULL, port,
1038 "array length must be non-negative",
1039 SCM_EOL);
1040
2caaadd1 1041 s = scm_list_2 (s, scm_from_ssize_t (lbnd+len-1));
5f37cb63 1042 }
2caaadd1
MV
1043
1044 shape = scm_cons (s, shape);
1045 } while (c == '@' || c == ':');
1046
1047 shape = scm_reverse_x (shape, SCM_EOL);
bfad4005
MV
1048 }
1049
1050 /* Read nested lists of elements.
1051 */
1052 if (c != '(')
1053 scm_i_input_error (NULL, port,
1054 "missing '(' in vector or array literal",
1055 SCM_EOL);
1056 scm_ungetc (c, port);
1057 elements = scm_read (port);
1058
2caaadd1 1059 if (scm_is_false (shape))
5a6d139b 1060 shape = scm_from_ssize_t (rank);
2caaadd1
MV
1061 else if (scm_ilength (shape) != rank)
1062 scm_i_input_error
1063 (NULL, port,
1064 "the number of shape specifications must match the array rank",
1065 SCM_EOL);
bfad4005 1066
5f37cb63
MV
1067 /* Handle special print syntax of rank zero arrays; see
1068 scm_i_print_array for a rationale.
1069 */
1070 if (rank == 0)
2caaadd1
MV
1071 {
1072 if (!scm_is_pair (elements))
1073 scm_i_input_error (NULL, port,
1074 "too few elements in array literal, need 1",
1075 SCM_EOL);
1076 if (!scm_is_null (SCM_CDR (elements)))
1077 scm_i_input_error (NULL, port,
1078 "too many elements in array literal, want 1",
1079 SCM_EOL);
1080 elements = SCM_CAR (elements);
1081 }
5f37cb63
MV
1082
1083 /* Construct array.
1084 */
2caaadd1 1085 return scm_list_to_typed_array (tag_to_type (tag, port), shape, elements);
bfad4005
MV
1086}
1087
ab1be174 1088
0f2d19dd 1089static SCM
e841c3e0 1090array_mark (SCM ptr)
0f2d19dd 1091{
04b87de5 1092 return SCM_I_ARRAY_V (ptr);
0f2d19dd
JB
1093}
1094
1be6b49c 1095static size_t
e841c3e0 1096array_free (SCM ptr)
0f2d19dd 1097{
04b87de5
MV
1098 scm_gc_free (SCM_I_ARRAY_MEM (ptr),
1099 (sizeof (scm_i_t_array)
1100 + SCM_I_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
4c9419ac
MV
1101 "array");
1102 return 0;
0f2d19dd
JB
1103}
1104
2a610be5
AW
1105static SCM
1106array_handle_ref (scm_t_array_handle *h, size_t pos)
1107{
1108 return scm_c_generalized_vector_ref (SCM_I_ARRAY_V (h->array), pos);
1109}
1110
1111static void
1112array_handle_set (scm_t_array_handle *h, size_t pos, SCM val)
1113{
1114 scm_c_generalized_vector_set_x (SCM_I_ARRAY_V (h->array), pos, val);
1115}
1116
1117/* FIXME: should be handle for vect? maybe not, because of dims */
1118static void
1119array_get_handle (SCM array, scm_t_array_handle *h)
1120{
1121 scm_t_array_handle vh;
1122 scm_array_get_handle (SCM_I_ARRAY_V (array), &vh);
1123 h->element_type = vh.element_type;
1124 h->elements = vh.elements;
1125 h->writable_elements = vh.writable_elements;
1126 scm_array_handle_release (&vh);
1127
1128 h->dims = SCM_I_ARRAY_DIMS (array);
1129 h->ndims = SCM_I_ARRAY_NDIM (array);
1130 h->base = SCM_I_ARRAY_BASE (array);
1131}
1132
1133SCM_ARRAY_IMPLEMENTATION (scm_i_tc16_array, 0xffff,
1134 array_handle_ref, array_handle_set,
1135 array_get_handle);
1136
0f2d19dd 1137void
2fa901a5 1138scm_init_arrays ()
0f2d19dd 1139{
04b87de5
MV
1140 scm_i_tc16_array = scm_make_smob_type ("array", 0);
1141 scm_set_smob_mark (scm_i_tc16_array, array_mark);
1142 scm_set_smob_free (scm_i_tc16_array, array_free);
1143 scm_set_smob_print (scm_i_tc16_array, scm_i_print_array);
1144 scm_set_smob_equalp (scm_i_tc16_array, scm_array_equal_p);
1145
0f2d19dd 1146 scm_add_feature ("array");
20930f28 1147
2fa901a5 1148#include "libguile/arrays.x"
bfad4005 1149
0f2d19dd 1150}
89e00824
ML
1151
1152/*
1153 Local Variables:
1154 c-file-style: "gnu"
1155 End:
1156*/