Changes in doc/ref:
[bpt/guile.git] / libguile / unif.c
CommitLineData
b3fcac34 1/* Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84 41
1bbd0b84 42
c209c88e
GB
43/*
44 This file has code for arrays in lots of variants (double, integer,
45 unsigned etc. ). It suffers from hugely repetitive code because
46 there is similar (but different) code for every variant included. (urg.)
47
48 --hwn
49*/
0f2d19dd
JB
50\f
51
52#include <stdio.h>
e6e2e95a 53#include <errno.h>
783e7774 54#include <string.h>
e6e2e95a 55
a0599745
MD
56#include "libguile/_scm.h"
57#include "libguile/chars.h"
58#include "libguile/eval.h"
59#include "libguile/fports.h"
60#include "libguile/smob.h"
61#include "libguile/strop.h"
62#include "libguile/feature.h"
63#include "libguile/root.h"
64#include "libguile/strings.h"
65#include "libguile/vectors.h"
66
67#include "libguile/validate.h"
68#include "libguile/unif.h"
69#include "libguile/ramap.h"
0f2d19dd 70
3d8d56df
GH
71#ifdef HAVE_UNISTD_H
72#include <unistd.h>
73#endif
74
7beabedb
MG
75#ifdef HAVE_IO_H
76#include <io.h>
77#endif
78
0f2d19dd
JB
79\f
80/* The set of uniform scm_vector types is:
81 * Vector of: Called:
82 * unsigned char string
83 * char byvect
84 * boolean bvect
a515d287
MD
85 * signed long ivect
86 * unsigned long uvect
0f2d19dd
JB
87 * float fvect
88 * double dvect
89 * complex double cvect
90 * short svect
5c11cc9d 91 * long long llvect
0f2d19dd
JB
92 */
93
92c2555f 94scm_t_bits scm_tc16_array;
0f2d19dd 95
afe5177e
GH
96/* return the size of an element in a uniform array or 0 if type not
97 found. */
1be6b49c 98size_t
afe5177e 99scm_uniform_element_size (SCM obj)
0f2d19dd 100{
1be6b49c 101 size_t result;
0f2d19dd 102
afe5177e 103 switch (SCM_TYP7 (obj))
0f2d19dd 104 {
0f2d19dd 105 case scm_tc7_bvect:
0f2d19dd
JB
106 case scm_tc7_uvect:
107 case scm_tc7_ivect:
afe5177e 108 result = sizeof (long);
0f2d19dd 109 break;
afe5177e 110
0f2d19dd 111 case scm_tc7_byvect:
afe5177e 112 result = sizeof (char);
0f2d19dd
JB
113 break;
114
115 case scm_tc7_svect:
afe5177e 116 result = sizeof (short);
0f2d19dd 117 break;
afe5177e 118
5c11cc9d 119#ifdef HAVE_LONG_LONGS
0f2d19dd 120 case scm_tc7_llvect:
1be6b49c 121 result = sizeof (long long);
0f2d19dd
JB
122 break;
123#endif
124
0f2d19dd 125 case scm_tc7_fvect:
afe5177e 126 result = sizeof (float);
0f2d19dd 127 break;
afe5177e 128
0f2d19dd 129 case scm_tc7_dvect:
afe5177e 130 result = sizeof (double);
0f2d19dd 131 break;
afe5177e 132
0f2d19dd 133 case scm_tc7_cvect:
afe5177e 134 result = 2 * sizeof (double);
0f2d19dd 135 break;
afe5177e
GH
136
137 default:
138 result = 0;
0f2d19dd 139 }
afe5177e 140 return result;
0f2d19dd
JB
141}
142
bc86da5d
MD
143/* Silly function used not to modify the semantics of the silly
144 * prototype system in order to be backward compatible.
145 */
146static int
147singp (SCM obj)
0f2d19dd 148{
bc86da5d
MD
149 if (!SCM_SLOPPY_REALP (obj))
150 return 0;
151 else
152 {
153 double x = SCM_REAL_VALUE (obj);
154 float fx = x;
155 return (- SCM_FLTMAX < x) && (x < SCM_FLTMAX) && (fx == x);
156 }
0f2d19dd 157}
1cc91f1b 158
0f2d19dd 159SCM
c014a02e 160scm_make_uve (long k, SCM prot)
a3a32939 161#define FUNC_NAME "scm_make_uve"
0f2d19dd
JB
162{
163 SCM v;
c014a02e 164 long i, type;
a3a32939 165
9a09deb1 166 if (SCM_EQ_P (prot, SCM_BOOL_T))
0f2d19dd 167 {
93778877
DH
168 if (k > 0)
169 {
16d4699b
MV
170 SCM_ASSERT_RANGE (1,
171 scm_long2num (k), k <= SCM_BITVECTOR_MAX_LENGTH);
c014a02e 172 i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
228a24ef
DH
173 v = scm_cell (SCM_MAKE_BITVECTOR_TAG (k),
174 (scm_t_bits) scm_gc_malloc (i, "vector"));
93778877
DH
175 }
176 else
228a24ef 177 v = scm_cell (SCM_MAKE_BITVECTOR_TAG (0), 0);
93778877 178 return v;
0f2d19dd 179 }
4260a7fc 180 else if (SCM_CHARP (prot) && (SCM_CHAR (prot) == '\0'))
0f2d19dd 181 {
c014a02e 182 i = sizeof (char) * k;
0f2d19dd 183 type = scm_tc7_byvect;
5b9eb8ae 184 }
7866a09b 185 else if (SCM_CHARP (prot))
0f2d19dd 186 {
c014a02e 187 i = sizeof (char) * k;
be54b15d 188 return scm_allocate_string (i);
0f2d19dd
JB
189 }
190 else if (SCM_INUMP (prot))
191 {
c014a02e 192 i = sizeof (long) * k;
0f2d19dd
JB
193 if (SCM_INUM (prot) > 0)
194 type = scm_tc7_uvect;
195 else
196 type = scm_tc7_ivect;
197 }
74014c46 198 else if (SCM_SYMBOLP (prot) && (1 == SCM_SYMBOL_LENGTH (prot)))
0f2d19dd
JB
199 {
200 char s;
201
86c991c2 202 s = SCM_SYMBOL_CHARS (prot)[0];
0f2d19dd
JB
203 if (s == 's')
204 {
c014a02e 205 i = sizeof (short) * k;
0f2d19dd
JB
206 type = scm_tc7_svect;
207 }
5c11cc9d 208#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
209 else if (s == 'l')
210 {
c014a02e 211 i = sizeof (long long) * k;
0f2d19dd
JB
212 type = scm_tc7_llvect;
213 }
214#endif
215 else
216 {
00ffa0e7 217 return scm_c_make_vector (k, SCM_UNDEFINED);
0f2d19dd
JB
218 }
219 }
5b9eb8ae 220 else if (!SCM_INEXACTP (prot))
0f2d19dd 221 /* Huge non-unif vectors are NOT supported. */
5c11cc9d 222 /* no special scm_vector */
00ffa0e7 223 return scm_c_make_vector (k, SCM_UNDEFINED);
bc86da5d 224 else if (singp (prot))
0f2d19dd 225 {
c014a02e 226 i = sizeof (float) * k;
0f2d19dd
JB
227 type = scm_tc7_fvect;
228 }
eb42e2f0 229 else if (SCM_COMPLEXP (prot))
0f2d19dd 230 {
c014a02e 231 i = 2 * sizeof (double) * k;
0f2d19dd
JB
232 type = scm_tc7_cvect;
233 }
234 else
235 {
c014a02e 236 i = sizeof (double) * k;
0f2d19dd
JB
237 type = scm_tc7_dvect;
238 }
0f2d19dd 239
c014a02e 240 SCM_ASSERT_RANGE (1, scm_long2num (k), k <= SCM_UVECTOR_MAX_LENGTH);
5b9eb8ae 241
228a24ef
DH
242 return scm_cell (SCM_MAKE_UVECTOR_TAG (k, type),
243 (scm_t_bits) scm_gc_malloc (i, "vector"));
0f2d19dd 244}
a3a32939
DH
245#undef FUNC_NAME
246
0f2d19dd 247
3b3b36dd 248SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
1e6808ea
MG
249 (SCM v),
250 "Return the number of elements in @var{uve}.")
1bbd0b84 251#define FUNC_NAME s_scm_uniform_vector_length
0f2d19dd
JB
252{
253 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 254 switch SCM_TYP7 (v)
0f2d19dd
JB
255 {
256 default:
276dd677 257 badarg1:SCM_WRONG_TYPE_ARG (1, v);
74014c46
DH
258 case scm_tc7_vector:
259 case scm_tc7_wvect:
260 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v));
0f2d19dd 261 case scm_tc7_string:
74014c46
DH
262 return SCM_MAKINUM (SCM_STRING_LENGTH (v));
263 case scm_tc7_bvect:
264 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v));
0f2d19dd
JB
265 case scm_tc7_byvect:
266 case scm_tc7_uvect:
267 case scm_tc7_ivect:
268 case scm_tc7_fvect:
269 case scm_tc7_dvect:
270 case scm_tc7_cvect:
0f2d19dd 271 case scm_tc7_svect:
5c11cc9d 272#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
273 case scm_tc7_llvect:
274#endif
74014c46 275 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v));
0f2d19dd
JB
276 }
277}
1bbd0b84 278#undef FUNC_NAME
0f2d19dd 279
3b3b36dd 280SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
1bbd0b84 281 (SCM v, SCM prot),
1e6808ea
MG
282 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
283 "not. The @var{prototype} argument is used with uniform arrays\n"
284 "and is described elsewhere.")
1bbd0b84 285#define FUNC_NAME s_scm_array_p
0f2d19dd
JB
286{
287 int nprot;
288 int enclosed;
289 nprot = SCM_UNBNDP (prot);
290 enclosed = 0;
291 if (SCM_IMP (v))
292 return SCM_BOOL_F;
c209c88e
GB
293
294 while (SCM_TYP7 (v) == scm_tc7_smob)
0f2d19dd 295 {
0f2d19dd
JB
296 if (!SCM_ARRAYP (v))
297 return SCM_BOOL_F;
298 if (nprot)
299 return SCM_BOOL_T;
300 if (enclosed++)
301 return SCM_BOOL_F;
302 v = SCM_ARRAY_V (v);
c209c88e
GB
303 }
304 if (nprot)
305 return SCM_BOOL(nprot);
306 else
307 {
308 int protp = 0;
309
310 switch (SCM_TYP7 (v))
311 {
312 case scm_tc7_bvect:
9a09deb1 313 protp = (SCM_EQ_P (prot, SCM_BOOL_T));
c209c88e 314 case scm_tc7_string:
4260a7fc 315 protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
c209c88e 316 case scm_tc7_byvect:
4260a7fc 317 protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
c209c88e
GB
318 case scm_tc7_uvect:
319 protp = SCM_INUMP(prot) && SCM_INUM(prot)>0;
320 case scm_tc7_ivect:
321 protp = SCM_INUMP(prot) && SCM_INUM(prot)<=0;
322
323 case scm_tc7_svect:
324 protp = SCM_SYMBOLP (prot)
74014c46 325 && (1 == SCM_SYMBOL_LENGTH (prot))
86c991c2 326 && ('s' == SCM_SYMBOL_CHARS (prot)[0]);
5c11cc9d 327#ifdef HAVE_LONG_LONGS
c209c88e
GB
328 case scm_tc7_llvect:
329 protp = SCM_SYMBOLP (prot)
74014c46 330 && (1 == SCM_SYMBOL_LENGTH (prot))
86c991c2 331 && ('s' == SCM_SYMBOL_CHARS (prot)[0]);
0f2d19dd 332#endif
c209c88e 333 case scm_tc7_fvect:
bc86da5d 334 protp = singp (prot);
c209c88e
GB
335 case scm_tc7_dvect:
336 protp = SCM_REALP(prot);
337 case scm_tc7_cvect:
eb42e2f0 338 protp = SCM_COMPLEXP(prot);
c209c88e
GB
339 case scm_tc7_vector:
340 case scm_tc7_wvect:
341 protp = SCM_NULLP(prot);
342 default:
343 /* no default */
344 ;
345 }
346 return SCM_BOOL(protp);
0f2d19dd 347 }
0f2d19dd 348}
1bbd0b84 349#undef FUNC_NAME
0f2d19dd
JB
350
351
3b3b36dd 352SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
1bbd0b84 353 (SCM ra),
1e6808ea
MG
354 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
355 "not an array, @code{0} is returned.")
1bbd0b84 356#define FUNC_NAME s_scm_array_rank
0f2d19dd
JB
357{
358 if (SCM_IMP (ra))
1bbd0b84 359 return SCM_INUM0;
0f2d19dd
JB
360 switch (SCM_TYP7 (ra))
361 {
362 default:
363 return SCM_INUM0;
364 case scm_tc7_string:
365 case scm_tc7_vector:
95f5b0f5 366 case scm_tc7_wvect:
0f2d19dd
JB
367 case scm_tc7_byvect:
368 case scm_tc7_uvect:
369 case scm_tc7_ivect:
370 case scm_tc7_fvect:
371 case scm_tc7_cvect:
372 case scm_tc7_dvect:
5c11cc9d 373#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
374 case scm_tc7_llvect:
375#endif
376 case scm_tc7_svect:
377 return SCM_MAKINUM (1L);
378 case scm_tc7_smob:
379 if (SCM_ARRAYP (ra))
380 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra));
381 return SCM_INUM0;
382 }
383}
1bbd0b84 384#undef FUNC_NAME
0f2d19dd
JB
385
386
3b3b36dd 387SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 388 (SCM ra),
b380b885
MD
389 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
390 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
1e6808ea 391 "@lisp\n"
b380b885 392 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
1e6808ea 393 "@end lisp")
1bbd0b84 394#define FUNC_NAME s_scm_array_dimensions
0f2d19dd
JB
395{
396 SCM res = SCM_EOL;
1be6b49c 397 size_t k;
92c2555f 398 scm_t_array_dim *s;
0f2d19dd 399 if (SCM_IMP (ra))
1bbd0b84 400 return SCM_BOOL_F;
0f2d19dd
JB
401 switch (SCM_TYP7 (ra))
402 {
403 default:
404 return SCM_BOOL_F;
405 case scm_tc7_string:
406 case scm_tc7_vector:
95f5b0f5 407 case scm_tc7_wvect:
0f2d19dd
JB
408 case scm_tc7_bvect:
409 case scm_tc7_byvect:
410 case scm_tc7_uvect:
411 case scm_tc7_ivect:
412 case scm_tc7_fvect:
413 case scm_tc7_cvect:
414 case scm_tc7_dvect:
415 case scm_tc7_svect:
5c11cc9d 416#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
417 case scm_tc7_llvect:
418#endif
74014c46 419 return scm_cons (scm_uniform_vector_length (ra), SCM_EOL);
0f2d19dd
JB
420 case scm_tc7_smob:
421 if (!SCM_ARRAYP (ra))
422 return SCM_BOOL_F;
423 k = SCM_ARRAY_NDIM (ra);
424 s = SCM_ARRAY_DIMS (ra);
425 while (k--)
e2d37336
MD
426 res = scm_cons (s[k].lbnd
427 ? scm_cons2 (SCM_MAKINUM (s[k].lbnd),
428 SCM_MAKINUM (s[k].ubnd),
429 SCM_EOL)
430 : SCM_MAKINUM (1 + s[k].ubnd),
431 res);
0f2d19dd
JB
432 return res;
433 }
434}
1bbd0b84 435#undef FUNC_NAME
0f2d19dd
JB
436
437
e2d37336
MD
438SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
439 (SCM ra),
440 "Return the root vector of a shared array.")
441#define FUNC_NAME s_scm_shared_array_root
442{
443 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
444 return SCM_ARRAY_V (ra);
445}
446#undef FUNC_NAME
447
448
449SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
450 (SCM ra),
451 "Return the root vector index of the first element in the array.")
452#define FUNC_NAME s_scm_shared_array_offset
453{
454 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
455 return SCM_MAKINUM (SCM_ARRAY_BASE (ra));
456}
457#undef FUNC_NAME
458
459
460SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
461 (SCM ra),
462 "For each dimension, return the distance between elements in the root vector.")
463#define FUNC_NAME s_scm_shared_array_increments
464{
465 SCM res = SCM_EOL;
1be6b49c 466 size_t k;
92c2555f 467 scm_t_array_dim *s;
e2d37336
MD
468 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
469 k = SCM_ARRAY_NDIM (ra);
470 s = SCM_ARRAY_DIMS (ra);
471 while (k--)
472 res = scm_cons (SCM_MAKINUM (s[k].inc), res);
473 return res;
474}
475#undef FUNC_NAME
476
477
0f2d19dd
JB
478static char s_bad_ind[] = "Bad scm_array index";
479
1cc91f1b 480
c014a02e 481long
1bbd0b84 482scm_aind (SCM ra, SCM args, const char *what)
b3fcac34 483#define FUNC_NAME what
0f2d19dd
JB
484{
485 SCM ind;
c014a02e
ML
486 register long j;
487 register unsigned long pos = SCM_ARRAY_BASE (ra);
488 register unsigned long k = SCM_ARRAY_NDIM (ra);
92c2555f 489 scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
0f2d19dd 490 if (SCM_INUMP (args))
0f2d19dd 491 {
b3fcac34
DH
492 if (k != 1)
493 scm_error_num_args_subr (what);
0f2d19dd
JB
494 return pos + (SCM_INUM (args) - s->lbnd) * (s->inc);
495 }
1be6b49c 496 while (k && !SCM_NULLP (args))
0f2d19dd
JB
497 {
498 ind = SCM_CAR (args);
499 args = SCM_CDR (args);
b3fcac34
DH
500 if (!SCM_INUMP (ind))
501 scm_misc_error (what, s_bad_ind, SCM_EOL);
0f2d19dd 502 j = SCM_INUM (ind);
685c0d71
DH
503 if (j < s->lbnd || j > s->ubnd)
504 scm_out_of_range (what, ind);
0f2d19dd
JB
505 pos += (j - s->lbnd) * (s->inc);
506 k--;
507 s++;
508 }
b3fcac34
DH
509 if (k != 0 || !SCM_NULLP (args))
510 scm_error_num_args_subr (what);
511
0f2d19dd
JB
512 return pos;
513}
b3fcac34 514#undef FUNC_NAME
0f2d19dd 515
1cc91f1b 516
0f2d19dd 517SCM
1bbd0b84 518scm_make_ra (int ndim)
0f2d19dd
JB
519{
520 SCM ra;
0f2d19dd 521 SCM_DEFER_INTS;
92c2555f 522 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + scm_tc16_array,
4c9419ac
MV
523 scm_gc_malloc ((sizeof (scm_t_array) +
524 ndim * sizeof (scm_t_array_dim)),
525 "array"));
0f2d19dd
JB
526 SCM_ARRAY_V (ra) = scm_nullvect;
527 SCM_ALLOW_INTS;
528 return ra;
529}
530
531static char s_bad_spec[] = "Bad scm_array dimension";
532/* Increments will still need to be set. */
533
1cc91f1b 534
0f2d19dd 535SCM
1bbd0b84 536scm_shap2ra (SCM args, const char *what)
0f2d19dd 537{
92c2555f 538 scm_t_array_dim *s;
0f2d19dd
JB
539 SCM ra, spec, sp;
540 int ndim = scm_ilength (args);
b3fcac34
DH
541 if (ndim < 0)
542 scm_misc_error (what, s_bad_spec, SCM_EOL);
543
0f2d19dd
JB
544 ra = scm_make_ra (ndim);
545 SCM_ARRAY_BASE (ra) = 0;
546 s = SCM_ARRAY_DIMS (ra);
a3a32939 547 for (; !SCM_NULLP (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
548 {
549 spec = SCM_CAR (args);
a3a32939 550 if (SCM_INUMP (spec))
0f2d19dd 551 {
b3fcac34
DH
552 if (SCM_INUM (spec) < 0)
553 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
554 s->lbnd = 0;
555 s->ubnd = SCM_INUM (spec) - 1;
556 s->inc = 1;
557 }
558 else
559 {
b3fcac34
DH
560 if (!SCM_CONSP (spec) || !SCM_INUMP (SCM_CAR (spec)))
561 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
562 s->lbnd = SCM_INUM (SCM_CAR (spec));
563 sp = SCM_CDR (spec);
b3fcac34
DH
564 if (!SCM_CONSP (sp)
565 || !SCM_INUMP (SCM_CAR (sp))
566 || !SCM_NULLP (SCM_CDR (sp)))
567 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
568 s->ubnd = SCM_INUM (SCM_CAR (sp));
569 s->inc = 1;
570 }
571 }
572 return ra;
573}
574
3b3b36dd 575SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
1e6808ea 576 (SCM dims, SCM prot, SCM fill),
8f85c0c6 577 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
1e6808ea
MG
578 "Create and return a uniform array or vector of type\n"
579 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
580 "length @var{length}. If @var{fill} is supplied, it's used to\n"
581 "fill the array, otherwise @var{prototype} is used.")
1bbd0b84 582#define FUNC_NAME s_scm_dimensions_to_uniform_array
0f2d19dd 583{
1be6b49c 584 size_t k;
c014a02e 585 unsigned long rlen = 1;
92c2555f 586 scm_t_array_dim *s;
0f2d19dd 587 SCM ra;
1be6b49c 588
0f2d19dd 589 if (SCM_INUMP (dims))
cda139a7 590 {
5b9eb8ae 591 SCM answer = scm_make_uve (SCM_INUM (dims), prot);
a3a32939
DH
592 if (!SCM_UNBNDP (fill))
593 scm_array_fill_x (answer, fill);
594 else if (SCM_SYMBOLP (prot))
595 scm_array_fill_x (answer, SCM_MAKINUM (0));
596 else
597 scm_array_fill_x (answer, prot);
598 return answer;
cda139a7 599 }
1be6b49c 600
0c95b57d
GB
601 SCM_ASSERT (SCM_NULLP (dims) || SCM_CONSP (dims),
602 dims, SCM_ARG1, FUNC_NAME);
1bbd0b84 603 ra = scm_shap2ra (dims, FUNC_NAME);
e038c042 604 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
605 s = SCM_ARRAY_DIMS (ra);
606 k = SCM_ARRAY_NDIM (ra);
1be6b49c 607
0f2d19dd
JB
608 while (k--)
609 {
a3a32939
DH
610 s[k].inc = rlen;
611 SCM_ASSERT_RANGE (1, dims, s[k].lbnd <= s[k].ubnd);
0f2d19dd 612 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 613 }
a3a32939 614
a3a32939
DH
615 SCM_ARRAY_V (ra) = scm_make_uve (rlen, prot);
616
5c11cc9d 617 if (!SCM_UNBNDP (fill))
a3a32939 618 scm_array_fill_x (ra, fill);
0c95b57d 619 else if (SCM_SYMBOLP (prot))
0f2d19dd
JB
620 scm_array_fill_x (ra, SCM_MAKINUM (0));
621 else
622 scm_array_fill_x (ra, prot);
a3a32939 623
0f2d19dd 624 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
c014a02e 625 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
0f2d19dd
JB
626 return SCM_ARRAY_V (ra);
627 return ra;
628}
1bbd0b84 629#undef FUNC_NAME
0f2d19dd 630
1cc91f1b 631
0f2d19dd 632void
1bbd0b84 633scm_ra_set_contp (SCM ra)
0f2d19dd 634{
1be6b49c 635 size_t k = SCM_ARRAY_NDIM (ra);
0f2d19dd 636 if (k)
0f2d19dd 637 {
c014a02e 638 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 639 while (k--)
0f2d19dd 640 {
fe0c6dae
JB
641 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
642 {
e038c042 643 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
644 return;
645 }
646 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
647 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 648 }
0f2d19dd 649 }
e038c042 650 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
651}
652
653
3b3b36dd 654SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 655 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
656 "@code{make-shared-array} can be used to create shared subarrays of other\n"
657 "arrays. The @var{mapper} is a function that translates coordinates in\n"
658 "the new array into coordinates in the old array. A @var{mapper} must be\n"
659 "linear, and its range must stay within the bounds of the old array, but\n"
660 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 661 "@lisp\n"
b380b885
MD
662 "(define fred (make-array #f 8 8))\n"
663 "(define freds-diagonal\n"
664 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
665 "(array-set! freds-diagonal 'foo 3)\n"
666 "(array-ref fred 3 3) @result{} foo\n"
667 "(define freds-center\n"
668 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
669 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 670 "@end lisp")
1bbd0b84 671#define FUNC_NAME s_scm_make_shared_array
0f2d19dd
JB
672{
673 SCM ra;
674 SCM inds, indptr;
675 SCM imap;
c014a02e
ML
676 size_t k, i;
677 long old_min, new_min, old_max, new_max;
92c2555f 678 scm_t_array_dim *s;
b3fcac34
DH
679
680 SCM_VALIDATE_REST_ARGUMENT (dims);
3b3b36dd
GB
681 SCM_VALIDATE_ARRAY (1,oldra);
682 SCM_VALIDATE_PROC (2,mapfunc);
1bbd0b84 683 ra = scm_shap2ra (dims, FUNC_NAME);
0f2d19dd
JB
684 if (SCM_ARRAYP (oldra))
685 {
686 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
687 old_min = old_max = SCM_ARRAY_BASE (oldra);
688 s = SCM_ARRAY_DIMS (oldra);
689 k = SCM_ARRAY_NDIM (oldra);
690 while (k--)
691 {
692 if (s[k].inc > 0)
693 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
694 else
695 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
696 }
697 }
698 else
699 {
700 SCM_ARRAY_V (ra) = oldra;
701 old_min = 0;
74014c46 702 old_max = SCM_INUM (scm_uniform_vector_length (oldra)) - 1;
0f2d19dd
JB
703 }
704 inds = SCM_EOL;
705 s = SCM_ARRAY_DIMS (ra);
706 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
707 {
708 inds = scm_cons (SCM_MAKINUM (s[k].lbnd), inds);
709 if (s[k].ubnd < s[k].lbnd)
710 {
711 if (1 == SCM_ARRAY_NDIM (ra))
712 ra = scm_make_uve (0L, scm_array_prototype (ra));
713 else
714 SCM_ARRAY_V (ra) = scm_make_uve (0L, scm_array_prototype (ra));
715 return ra;
716 }
717 }
fdc28395 718 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd 719 if (SCM_ARRAYP (oldra))
c014a02e 720 i = (size_t) scm_aind (oldra, imap, FUNC_NAME);
0f2d19dd
JB
721 else
722 {
723 if (SCM_NINUMP (imap))
724
725 {
b3fcac34
DH
726 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
727 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
728 imap = SCM_CAR (imap);
729 }
730 i = SCM_INUM (imap);
731 }
732 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
733 indptr = inds;
734 k = SCM_ARRAY_NDIM (ra);
735 while (k--)
736 {
737 if (s[k].ubnd > s[k].lbnd)
738 {
898a256f 739 SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
fdc28395 740 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd
JB
741 if (SCM_ARRAYP (oldra))
742
1bbd0b84 743 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
744 else
745 {
746 if (SCM_NINUMP (imap))
0f2d19dd 747 {
b3fcac34
DH
748 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
749 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
750 imap = SCM_CAR (imap);
751 }
752 s[k].inc = (long) SCM_INUM (imap) - i;
753 }
754 i += s[k].inc;
755 if (s[k].inc > 0)
756 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
757 else
758 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
759 }
760 else
761 s[k].inc = new_max - new_min + 1; /* contiguous by default */
762 indptr = SCM_CDR (indptr);
763 }
b3fcac34
DH
764 if (old_min > new_min || old_max < new_max)
765 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
766 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
767 {
74014c46 768 SCM v = SCM_ARRAY_V (ra);
c014a02e 769 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
770 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
771 return v;
0f2d19dd
JB
772 if (s->ubnd < s->lbnd)
773 return scm_make_uve (0L, scm_array_prototype (ra));
774 }
775 scm_ra_set_contp (ra);
776 return ra;
777}
1bbd0b84 778#undef FUNC_NAME
0f2d19dd
JB
779
780
781/* args are RA . DIMS */
af45e3b0
DH
782SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
783 (SCM ra, SCM args),
1e6808ea
MG
784 "Return an array sharing contents with @var{array}, but with\n"
785 "dimensions arranged in a different order. There must be one\n"
786 "@var{dim} argument for each dimension of @var{array}.\n"
787 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
788 "and the rank of the array to be returned. Each integer in that\n"
789 "range must appear at least once in the argument list.\n"
790 "\n"
791 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
792 "dimensions in the array to be returned, their positions in the\n"
793 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
794 "may have the same value, in which case the returned array will\n"
795 "have smaller rank than @var{array}.\n"
796 "\n"
797 "@lisp\n"
b380b885
MD
798 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
799 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
800 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
801 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 802 "@end lisp")
1bbd0b84 803#define FUNC_NAME s_scm_transpose_array
0f2d19dd 804{
af45e3b0 805 SCM res, vargs, *ve = &vargs;
92c2555f 806 scm_t_array_dim *s, *r;
0f2d19dd 807 int ndim, i, k;
af45e3b0 808
b3fcac34 809 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 810 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
f5bf2977 811 switch (SCM_TYP7 (ra))
0f2d19dd
JB
812 {
813 default:
276dd677 814 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
815 case scm_tc7_bvect:
816 case scm_tc7_string:
817 case scm_tc7_byvect:
818 case scm_tc7_uvect:
819 case scm_tc7_ivect:
820 case scm_tc7_fvect:
821 case scm_tc7_dvect:
822 case scm_tc7_cvect:
823 case scm_tc7_svect:
5c11cc9d 824#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
825 case scm_tc7_llvect:
826#endif
b3fcac34
DH
827 if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
828 SCM_WRONG_NUM_ARGS ();
829 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CAR (args));
685c0d71
DH
830 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args),
831 SCM_EQ_P (SCM_INUM0, SCM_CAR (args)));
0f2d19dd
JB
832 return ra;
833 case scm_tc7_smob:
834 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
835 vargs = scm_vector (args);
b3fcac34
DH
836 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
837 SCM_WRONG_NUM_ARGS ();
838 ve = SCM_VELTS (vargs);
0f2d19dd
JB
839 ndim = 0;
840 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
841 {
20a54673 842 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 843 FUNC_NAME);
0f2d19dd 844 i = SCM_INUM (ve[k]);
685c0d71
DH
845 if (i < 0 || i >= SCM_ARRAY_NDIM (ra))
846 scm_out_of_range (FUNC_NAME, ve[k]);
0f2d19dd
JB
847 if (ndim < i)
848 ndim = i;
849 }
850 ndim++;
851 res = scm_make_ra (ndim);
852 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
853 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
854 for (k = ndim; k--;)
855 {
856 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
857 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
858 }
859 for (k = SCM_ARRAY_NDIM (ra); k--;)
860 {
861 i = SCM_INUM (ve[k]);
862 s = &(SCM_ARRAY_DIMS (ra)[k]);
863 r = &(SCM_ARRAY_DIMS (res)[i]);
864 if (r->ubnd < r->lbnd)
865 {
866 r->lbnd = s->lbnd;
867 r->ubnd = s->ubnd;
868 r->inc = s->inc;
869 ndim--;
870 }
871 else
872 {
873 if (r->ubnd > s->ubnd)
874 r->ubnd = s->ubnd;
875 if (r->lbnd < s->lbnd)
876 {
877 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
878 r->lbnd = s->lbnd;
879 }
880 r->inc += s->inc;
881 }
882 }
b3fcac34
DH
883 if (ndim > 0)
884 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
885 scm_ra_set_contp (res);
886 return res;
887 }
888}
1bbd0b84 889#undef FUNC_NAME
0f2d19dd
JB
890
891/* args are RA . AXES */
af45e3b0
DH
892SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
893 (SCM ra, SCM axes),
b380b885
MD
894 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
895 "the rank of @var{array}. @var{enclose-array} returns an array\n"
896 "resembling an array of shared arrays. The dimensions of each shared\n"
897 "array are the same as the @var{dim}th dimensions of the original array,\n"
898 "the dimensions of the outer array are the same as those of the original\n"
899 "array that did not match a @var{dim}.\n\n"
900 "An enclosed array is not a general Scheme array. Its elements may not\n"
901 "be set using @code{array-set!}. Two references to the same element of\n"
902 "an enclosed array will be @code{equal?} but will not in general be\n"
903 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
904 "enclosed array is unspecified.\n\n"
905 "examples:\n"
1e6808ea 906 "@lisp\n"
b380b885
MD
907 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
908 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
909 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
910 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 911 "@end lisp")
1bbd0b84 912#define FUNC_NAME s_scm_enclose_array
0f2d19dd 913{
af45e3b0 914 SCM axv, res, ra_inr;
92c2555f 915 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 916 int ndim, j, k, ninr, noutr;
af45e3b0 917
b3fcac34 918 SCM_VALIDATE_REST_ARGUMENT (axes);
0f2d19dd 919 if (SCM_NULLP (axes))
0f2d19dd
JB
920 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
921 ninr = scm_ilength (axes);
b3fcac34
DH
922 if (ninr < 0)
923 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
924 ra_inr = scm_make_ra (ninr);
925 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
74014c46 926 switch SCM_TYP7 (ra)
0f2d19dd
JB
927 {
928 default:
276dd677 929 badarg1:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
930 case scm_tc7_string:
931 case scm_tc7_bvect:
932 case scm_tc7_byvect:
933 case scm_tc7_uvect:
934 case scm_tc7_ivect:
935 case scm_tc7_fvect:
936 case scm_tc7_dvect:
937 case scm_tc7_cvect:
938 case scm_tc7_vector:
95f5b0f5 939 case scm_tc7_wvect:
0f2d19dd 940 case scm_tc7_svect:
5c11cc9d 941#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
942 case scm_tc7_llvect:
943#endif
944 s->lbnd = 0;
74014c46 945 s->ubnd = SCM_INUM (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
946 s->inc = 1;
947 SCM_ARRAY_V (ra_inr) = ra;
948 SCM_ARRAY_BASE (ra_inr) = 0;
949 ndim = 1;
950 break;
951 case scm_tc7_smob:
952 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
953 s = SCM_ARRAY_DIMS (ra);
954 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
955 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
956 ndim = SCM_ARRAY_NDIM (ra);
957 break;
958 }
959 noutr = ndim - ninr;
b3fcac34
DH
960 if (noutr < 0)
961 SCM_WRONG_NUM_ARGS ();
7866a09b 962 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
0f2d19dd
JB
963 res = scm_make_ra (noutr);
964 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
965 SCM_ARRAY_V (res) = ra_inr;
966 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
967 {
b3fcac34
DH
968 if (!SCM_INUMP (SCM_CAR (axes)))
969 SCM_MISC_ERROR ("bad axis", SCM_EOL);
0f2d19dd
JB
970 j = SCM_INUM (SCM_CAR (axes));
971 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
972 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
973 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
405aaef9 974 SCM_STRING_CHARS (axv)[j] = 1;
0f2d19dd
JB
975 }
976 for (j = 0, k = 0; k < noutr; k++, j++)
977 {
405aaef9 978 while (SCM_STRING_CHARS (axv)[j])
0f2d19dd
JB
979 j++;
980 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
981 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
982 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
983 }
984 scm_ra_set_contp (ra_inr);
985 scm_ra_set_contp (res);
986 return res;
987}
1bbd0b84 988#undef FUNC_NAME
0f2d19dd
JB
989
990
991
af45e3b0
DH
992SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
993 (SCM v, SCM args),
1e6808ea
MG
994 "Return @code{#t} if its arguments would be acceptable to\n"
995 "@code{array-ref}.")
1bbd0b84 996#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 997{
af45e3b0 998 SCM ind = SCM_EOL;
c014a02e 999 long pos = 0;
1be6b49c 1000 register size_t k;
c014a02e 1001 register long j;
92c2555f 1002 scm_t_array_dim *s;
af45e3b0 1003
b3fcac34 1004 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
1005 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1006 if (SCM_NIMP (args))
1007
1008 {
1009 ind = SCM_CAR (args);
1010 args = SCM_CDR (args);
1bbd0b84 1011 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1012 pos = SCM_INUM (ind);
1013 }
1014tail:
74014c46 1015 switch SCM_TYP7 (v)
0f2d19dd
JB
1016 {
1017 default:
276dd677 1018 badarg1:SCM_WRONG_TYPE_ARG (1, v);
b3fcac34 1019 wna: SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1020 case scm_tc7_smob:
1021 k = SCM_ARRAY_NDIM (v);
1022 s = SCM_ARRAY_DIMS (v);
1023 pos = SCM_ARRAY_BASE (v);
1024 if (!k)
1025 {
1026 SCM_ASRTGO (SCM_NULLP (ind), wna);
1027 ind = SCM_INUM0;
1028 }
1029 else
1030 while (!0)
1031 {
1032 j = SCM_INUM (ind);
1033 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1034 {
1035 SCM_ASRTGO (--k == scm_ilength (args), wna);
1036 return SCM_BOOL_F;
1037 }
1038 pos += (j - s->lbnd) * (s->inc);
1039 if (!(--k && SCM_NIMP (args)))
1040 break;
1041 ind = SCM_CAR (args);
1042 args = SCM_CDR (args);
1043 s++;
b3fcac34
DH
1044 if (!SCM_INUMP (ind))
1045 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
1046 }
1047 SCM_ASRTGO (0 == k, wna);
1048 v = SCM_ARRAY_V (v);
1049 goto tail;
1050 case scm_tc7_bvect:
1051 case scm_tc7_string:
1052 case scm_tc7_byvect:
1053 case scm_tc7_uvect:
1054 case scm_tc7_ivect:
1055 case scm_tc7_fvect:
1056 case scm_tc7_dvect:
1057 case scm_tc7_cvect:
1058 case scm_tc7_svect:
5c11cc9d 1059#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1060 case scm_tc7_llvect:
1061#endif
1062 case scm_tc7_vector:
95f5b0f5 1063 case scm_tc7_wvect:
74014c46 1064 {
c014a02e 1065 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1066 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1067 return SCM_BOOL(pos >= 0 && pos < length);
1068 }
0f2d19dd
JB
1069 }
1070}
1bbd0b84 1071#undef FUNC_NAME
0f2d19dd
JB
1072
1073
1bbd0b84 1074SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1075
1bbd0b84 1076
3b3b36dd 1077SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1078 (SCM v, SCM args),
8f85c0c6 1079 "@deffnx {Scheme Procedure} array-ref v . args\n"
1e6808ea
MG
1080 "Return the element at the @code{(index1, index2)} element in\n"
1081 "@var{array}.")
1bbd0b84 1082#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd 1083{
c014a02e 1084 long pos;
0f2d19dd 1085
35de7ebe 1086 if (SCM_IMP (v))
0f2d19dd
JB
1087 {
1088 SCM_ASRTGO (SCM_NULLP (args), badarg);
1089 return v;
1090 }
1091 else if (SCM_ARRAYP (v))
0f2d19dd 1092 {
1bbd0b84 1093 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1094 v = SCM_ARRAY_V (v);
1095 }
1096 else
1097 {
c014a02e 1098 unsigned long int length;
0f2d19dd 1099 if (SCM_NIMP (args))
0f2d19dd 1100 {
1bbd0b84 1101 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1102 pos = SCM_INUM (SCM_CAR (args));
1103 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1104 }
1105 else
1106 {
3b3b36dd 1107 SCM_VALIDATE_INUM (2,args);
0f2d19dd
JB
1108 pos = SCM_INUM (args);
1109 }
74014c46
DH
1110 length = SCM_INUM (scm_uniform_vector_length (v));
1111 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1112 }
74014c46 1113 switch SCM_TYP7 (v)
0f2d19dd
JB
1114 {
1115 default:
1116 if (SCM_NULLP (args))
1117 return v;
35de7ebe 1118 badarg:
276dd677
DH
1119 SCM_WRONG_TYPE_ARG (1, v);
1120 /* not reached */
c209c88e
GB
1121
1122 outrng:
1123 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1124 wna:
b3fcac34 1125 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1126 case scm_tc7_smob:
1127 { /* enclosed */
1128 int k = SCM_ARRAY_NDIM (v);
1129 SCM res = scm_make_ra (k);
1130 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1131 SCM_ARRAY_BASE (res) = pos;
1132 while (k--)
1133 {
1134 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1135 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1136 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1137 }
1138 return res;
1139 }
1140 case scm_tc7_bvect:
c209c88e 1141 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1142 return SCM_BOOL_T;
1143 else
1144 return SCM_BOOL_F;
1145 case scm_tc7_string:
322ac0c5 1146 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1147 case scm_tc7_byvect:
405aaef9 1148 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1149 case scm_tc7_uvect:
fee7ef83 1150 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1151 case scm_tc7_ivect:
1be6b49c 1152 return scm_long2num (((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1153
1154 case scm_tc7_svect:
4260a7fc 1155 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1156#ifdef HAVE_LONG_LONGS
0f2d19dd 1157 case scm_tc7_llvect:
1be6b49c 1158 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1159#endif
1160
0f2d19dd 1161 case scm_tc7_fvect:
4260a7fc 1162 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1163 case scm_tc7_dvect:
4260a7fc 1164 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1165 case scm_tc7_cvect:
4260a7fc
DH
1166 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1167 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1168 case scm_tc7_vector:
95f5b0f5 1169 case scm_tc7_wvect:
0f2d19dd
JB
1170 return SCM_VELTS (v)[pos];
1171 }
1172}
1bbd0b84 1173#undef FUNC_NAME
0f2d19dd
JB
1174
1175/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1176 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1177
0f2d19dd 1178SCM
c014a02e 1179scm_cvref (SCM v, unsigned long pos, SCM last)
db4b4ca6 1180#define FUNC_NAME "scm_cvref"
0f2d19dd 1181{
5c11cc9d 1182 switch SCM_TYP7 (v)
0f2d19dd
JB
1183 {
1184 default:
db4b4ca6 1185 SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd 1186 case scm_tc7_bvect:
c209c88e 1187 if (SCM_BITVEC_REF(v,pos))
0f2d19dd
JB
1188 return SCM_BOOL_T;
1189 else
1190 return SCM_BOOL_F;
1191 case scm_tc7_string:
322ac0c5 1192 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1193 case scm_tc7_byvect:
405aaef9 1194 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1195 case scm_tc7_uvect:
fee7ef83 1196 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1197 case scm_tc7_ivect:
fee7ef83 1198 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1199 case scm_tc7_svect:
4260a7fc 1200 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1201#ifdef HAVE_LONG_LONGS
0f2d19dd 1202 case scm_tc7_llvect:
1be6b49c 1203 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1204#endif
0f2d19dd 1205 case scm_tc7_fvect:
fee7ef83 1206 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1207 {
4260a7fc 1208 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1209 return last;
1210 }
4260a7fc 1211 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1212 case scm_tc7_dvect:
fee7ef83 1213 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1214 {
4260a7fc 1215 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1216 return last;
1217 }
4260a7fc 1218 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1219 case scm_tc7_cvect:
bc86da5d 1220 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1221 {
4260a7fc
DH
1222 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1223 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1224 return last;
1225 }
4260a7fc
DH
1226 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1227 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1228 case scm_tc7_vector:
95f5b0f5 1229 case scm_tc7_wvect:
0f2d19dd
JB
1230 return SCM_VELTS (v)[pos];
1231 case scm_tc7_smob:
1232 { /* enclosed scm_array */
1233 int k = SCM_ARRAY_NDIM (v);
1234 SCM res = scm_make_ra (k);
1235 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1236 SCM_ARRAY_BASE (res) = pos;
1237 while (k--)
1238 {
1239 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1240 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1241 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1242 }
1243 return res;
1244 }
1245 }
1246}
db4b4ca6
DH
1247#undef FUNC_NAME
1248
0f2d19dd 1249
1bbd0b84
GB
1250SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1251
1cc91f1b 1252
0aa0871f
GH
1253/* Note that args may be a list or an immediate object, depending which
1254 PROC is used (and it's called from C too). */
3b3b36dd 1255SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1256 (SCM v, SCM obj, SCM args),
8f85c0c6
NJ
1257 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1258 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1259 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1260#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1261{
c014a02e 1262 long pos = 0;
b3fcac34 1263
0f2d19dd
JB
1264 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1265 if (SCM_ARRAYP (v))
0f2d19dd 1266 {
1bbd0b84 1267 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1268 v = SCM_ARRAY_V (v);
1269 }
1270 else
1271 {
c014a02e 1272 unsigned long int length;
9a97e362 1273 if (SCM_CONSP (args))
0f2d19dd 1274 {
9a97e362 1275 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), args, SCM_ARG3, FUNC_NAME);
0f2d19dd 1276 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1277 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1278 }
1279 else
1280 {
3b3b36dd 1281 SCM_VALIDATE_INUM_COPY (3,args,pos);
0f2d19dd 1282 }
74014c46
DH
1283 length = SCM_INUM (scm_uniform_vector_length (v));
1284 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd
JB
1285 }
1286 switch (SCM_TYP7 (v))
1287 {
35de7ebe 1288 default: badarg1:
276dd677
DH
1289 SCM_WRONG_TYPE_ARG (1, v);
1290 /* not reached */
c209c88e
GB
1291 outrng:
1292 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1293 wna:
b3fcac34 1294 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1295 case scm_tc7_smob: /* enclosed */
1296 goto badarg1;
1297 case scm_tc7_bvect:
4260a7fc 1298 if (SCM_FALSEP (obj))
c209c88e 1299 SCM_BITVEC_CLR(v,pos);
9a09deb1 1300 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c209c88e 1301 SCM_BITVEC_SET(v,pos);
0f2d19dd 1302 else
276dd677 1303 badobj:SCM_WRONG_TYPE_ARG (2, obj);
0f2d19dd
JB
1304 break;
1305 case scm_tc7_string:
7866a09b 1306 SCM_ASRTGO (SCM_CHARP (obj), badobj);
322ac0c5 1307 SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1308 break;
1309 case scm_tc7_byvect:
7866a09b
GB
1310 if (SCM_CHARP (obj))
1311 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1312 SCM_ASRTGO (SCM_INUMP (obj), badobj);
405aaef9 1313 ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1314 break;
1bbd0b84 1315 case scm_tc7_uvect:
729dbac3
DH
1316 ((unsigned long *) SCM_UVECTOR_BASE (v))[pos]
1317 = scm_num2ulong (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1318 break;
1bbd0b84 1319 case scm_tc7_ivect:
729dbac3
DH
1320 ((long *) SCM_UVECTOR_BASE (v))[pos]
1321 = scm_num2long (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1322 break;
0f2d19dd 1323 case scm_tc7_svect:
0aa0871f 1324 SCM_ASRTGO (SCM_INUMP (obj), badobj);
729dbac3 1325 ((short *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1326 break;
5c11cc9d 1327#ifdef HAVE_LONG_LONGS
0f2d19dd 1328 case scm_tc7_llvect:
729dbac3
DH
1329 ((long long *) SCM_UVECTOR_BASE (v))[pos]
1330 = scm_num2long_long (obj, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1331 break;
1332#endif
0f2d19dd 1333 case scm_tc7_fvect:
729dbac3
DH
1334 ((float *) SCM_UVECTOR_BASE (v))[pos]
1335 = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1336 break;
0f2d19dd 1337 case scm_tc7_dvect:
729dbac3
DH
1338 ((double *) SCM_UVECTOR_BASE (v))[pos]
1339 = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1340 break;
1341 case scm_tc7_cvect:
eb42e2f0
DH
1342 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1343 if (SCM_REALP (obj)) {
729dbac3
DH
1344 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_REAL_VALUE (obj);
1345 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = 0.0;
eb42e2f0 1346 } else {
729dbac3
DH
1347 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1348 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
eb42e2f0 1349 }
0f2d19dd 1350 break;
0f2d19dd 1351 case scm_tc7_vector:
95f5b0f5 1352 case scm_tc7_wvect:
0f2d19dd
JB
1353 SCM_VELTS (v)[pos] = obj;
1354 break;
1355 }
1356 return SCM_UNSPECIFIED;
1357}
1bbd0b84 1358#undef FUNC_NAME
0f2d19dd 1359
1d7bdb25
GH
1360/* attempts to unroll an array into a one-dimensional array.
1361 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1362 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1363 wouldn't have contiguous elements. */
3b3b36dd 1364SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1365 (SCM ra, SCM strict),
b380b885
MD
1366 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1367 "without changing their order (last subscript changing fastest), then\n"
1368 "@code{array-contents} returns that shared array, otherwise it returns\n"
1369 "@code{#f}. All arrays made by @var{make-array} and\n"
1370 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1371 "@var{make-shared-array} may not be.\n\n"
1372 "If the optional argument @var{strict} is provided, a shared array will\n"
1373 "be returned only if its elements are stored internally contiguous in\n"
1374 "memory.")
1bbd0b84 1375#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1376{
1377 SCM sra;
1378 if (SCM_IMP (ra))
f3667f52 1379 return SCM_BOOL_F;
5c11cc9d 1380 switch SCM_TYP7 (ra)
0f2d19dd
JB
1381 {
1382 default:
1383 return SCM_BOOL_F;
1384 case scm_tc7_vector:
95f5b0f5 1385 case scm_tc7_wvect:
0f2d19dd
JB
1386 case scm_tc7_string:
1387 case scm_tc7_bvect:
1388 case scm_tc7_byvect:
1389 case scm_tc7_uvect:
1390 case scm_tc7_ivect:
1391 case scm_tc7_fvect:
1392 case scm_tc7_dvect:
1393 case scm_tc7_cvect:
1394 case scm_tc7_svect:
5c11cc9d 1395#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1396 case scm_tc7_llvect:
1397#endif
1398 return ra;
1399 case scm_tc7_smob:
1400 {
c014a02e 1401 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
0f2d19dd
JB
1402 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1403 return SCM_BOOL_F;
1404 for (k = 0; k < ndim; k++)
1405 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1406 if (!SCM_UNBNDP (strict))
1407 {
0f2d19dd
JB
1408 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1409 return SCM_BOOL_F;
1410 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1411 {
74014c46 1412 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
c014a02e
ML
1413 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1414 len % SCM_LONG_BIT)
0f2d19dd
JB
1415 return SCM_BOOL_F;
1416 }
1417 }
74014c46
DH
1418
1419 {
1420 SCM v = SCM_ARRAY_V (ra);
c014a02e 1421 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1422 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1423 return v;
1424 }
1425
0f2d19dd
JB
1426 sra = scm_make_ra (1);
1427 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1428 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1429 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1430 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1431 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1432 return sra;
1433 }
1434 }
1435}
1bbd0b84 1436#undef FUNC_NAME
0f2d19dd 1437
1cc91f1b 1438
0f2d19dd 1439SCM
6e8d25a6 1440scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1441{
1442 SCM ret;
c014a02e
ML
1443 long inc = 1;
1444 size_t k, len = 1;
0f2d19dd
JB
1445 for (k = SCM_ARRAY_NDIM (ra); k--;)
1446 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1447 k = SCM_ARRAY_NDIM (ra);
1448 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1449 {
74014c46 1450 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1451 return ra;
74014c46 1452 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1453 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1454 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1455 return ra;
1456 }
1457 ret = scm_make_ra (k);
1458 SCM_ARRAY_BASE (ret) = 0;
1459 while (k--)
1460 {
1461 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1462 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1463 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1464 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1465 }
08112c95 1466 SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
0f2d19dd
JB
1467 if (copy)
1468 scm_array_copy_x (ra, ret);
1469 return ret;
1470}
1471
1472
1473
3b3b36dd 1474SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1475 (SCM ra, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1476 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1477 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1478 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1479 "If an end of file is encountered,\n"
1480 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1481 "(starting at the beginning) and the remainder of the array is\n"
1482 "unchanged.\n\n"
1483 "The optional arguments @var{start} and @var{end} allow\n"
1484 "a specified region of a vector (or linearized array) to be read,\n"
1485 "leaving the remainder of the vector unchanged.\n\n"
1486 "@code{uniform-array-read!} returns the number of objects read.\n"
1487 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1488 "returned by @code{(current-input-port)}.")
1bbd0b84 1489#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1490{
35de7ebe 1491 SCM cra = SCM_UNDEFINED, v = ra;
c014a02e
ML
1492 long sz, vlen, ans;
1493 long cstart = 0;
1494 long cend;
1495 long offset = 0;
405aaef9 1496 char *base;
35de7ebe 1497
0f2d19dd 1498 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1499 if (SCM_UNBNDP (port_or_fd))
1500 port_or_fd = scm_cur_inp;
1501 else
1502 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1503 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1504 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1505 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1506 ? 0
1507 : SCM_INUM (scm_uniform_vector_length (v)));
35de7ebe 1508
0f2d19dd 1509loop:
35de7ebe 1510 switch SCM_TYP7 (v)
0f2d19dd
JB
1511 {
1512 default:
276dd677 1513 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd
JB
1514 case scm_tc7_smob:
1515 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1516 cra = scm_ra2contig (ra, 0);
1146b6cd 1517 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1518 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1519 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1520 v = SCM_ARRAY_V (cra);
1521 goto loop;
1522 case scm_tc7_string:
74014c46 1523 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1524 sz = sizeof (char);
1525 break;
1526 case scm_tc7_bvect:
74014c46 1527 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1528 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1529 cstart /= SCM_LONG_BIT;
1530 sz = sizeof (long);
74014c46
DH
1531 break;
1532 case scm_tc7_byvect:
1533 base = (char *) SCM_UVECTOR_BASE (v);
1534 sz = sizeof (char);
1535 break;
0f2d19dd
JB
1536 case scm_tc7_uvect:
1537 case scm_tc7_ivect:
74014c46 1538 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1539 sz = sizeof (long);
1540 break;
1541 case scm_tc7_svect:
74014c46 1542 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1543 sz = sizeof (short);
1544 break;
5c11cc9d 1545#ifdef HAVE_LONG_LONGS
0f2d19dd 1546 case scm_tc7_llvect:
74014c46 1547 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1548 sz = sizeof (long long);
0f2d19dd
JB
1549 break;
1550#endif
0f2d19dd 1551 case scm_tc7_fvect:
74014c46 1552 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1553 sz = sizeof (float);
1554 break;
0f2d19dd 1555 case scm_tc7_dvect:
74014c46 1556 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1557 sz = sizeof (double);
1558 break;
1559 case scm_tc7_cvect:
74014c46 1560 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1561 sz = 2 * sizeof (double);
1562 break;
0f2d19dd 1563 }
405aaef9 1564
1146b6cd
GH
1565 cend = vlen;
1566 if (!SCM_UNBNDP (start))
3d8d56df 1567 {
1146b6cd 1568 offset =
c014a02e 1569 SCM_NUM2LONG (3, start);
35de7ebe 1570
1146b6cd 1571 if (offset < 0 || offset >= cend)
1bbd0b84 1572 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1573
1574 if (!SCM_UNBNDP (end))
1575 {
c014a02e
ML
1576 long tend =
1577 SCM_NUM2LONG (4, end);
3d8d56df 1578
1146b6cd 1579 if (tend <= offset || tend > cend)
1bbd0b84 1580 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1581 cend = tend;
1582 }
0f2d19dd 1583 }
35de7ebe 1584
3d8d56df
GH
1585 if (SCM_NIMP (port_or_fd))
1586 {
92c2555f 1587 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1588 int remaining = (cend - offset) * sz;
405aaef9 1589 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1590
1591 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1592 scm_flush (port_or_fd);
6c951427
GH
1593
1594 ans = cend - offset;
1595 while (remaining > 0)
3d8d56df 1596 {
6c951427
GH
1597 if (pt->read_pos < pt->read_end)
1598 {
1599 int to_copy = min (pt->read_end - pt->read_pos,
1600 remaining);
1601
1602 memcpy (dest, pt->read_pos, to_copy);
1603 pt->read_pos += to_copy;
1604 remaining -= to_copy;
1605 dest += to_copy;
1606 }
1607 else
1608 {
affc96b5 1609 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1610 {
1611 if (remaining % sz != 0)
1612 {
5d2d2ffc 1613 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1614 }
1615 ans -= remaining / sz;
1616 break;
1617 }
6c951427 1618 }
3d8d56df 1619 }
6c951427
GH
1620
1621 if (pt->rw_random)
1622 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1623 }
1624 else /* file descriptor. */
1625 {
1626 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1627 base + (cstart + offset) * sz,
1be6b49c 1628 (sz * (cend - offset))));
3d8d56df 1629 if (ans == -1)
1bbd0b84 1630 SCM_SYSERROR;
3d8d56df 1631 }
0f2d19dd 1632 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1633 ans *= SCM_LONG_BIT;
35de7ebe 1634
fee7ef83 1635 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1636 scm_array_copy_x (cra, ra);
35de7ebe 1637
0f2d19dd
JB
1638 return SCM_MAKINUM (ans);
1639}
1bbd0b84 1640#undef FUNC_NAME
0f2d19dd 1641
3b3b36dd 1642SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1643 (SCM v, SCM port_or_fd, SCM start, SCM end),
8f85c0c6 1644 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
b380b885
MD
1645 "Writes all elements of @var{ura} as binary objects to\n"
1646 "@var{port-or-fdes}.\n\n"
1647 "The optional arguments @var{start}\n"
1648 "and @var{end} allow\n"
1649 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1650 "The number of objects actually written is returned.\n"
b380b885
MD
1651 "@var{port-or-fdes} may be\n"
1652 "omitted, in which case it defaults to the value returned by\n"
1653 "@code{(current-output-port)}.")
1bbd0b84 1654#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1655{
c014a02e
ML
1656 long sz, vlen, ans;
1657 long offset = 0;
1658 long cstart = 0;
1659 long cend;
405aaef9 1660 char *base;
3d8d56df 1661
78446828
MV
1662 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1663
0f2d19dd 1664 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1665 if (SCM_UNBNDP (port_or_fd))
1666 port_or_fd = scm_cur_outp;
1667 else
1668 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1669 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1670 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1671 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1672 ? 0
1673 : SCM_INUM (scm_uniform_vector_length (v)));
1674
0f2d19dd 1675loop:
3d8d56df 1676 switch SCM_TYP7 (v)
0f2d19dd
JB
1677 {
1678 default:
276dd677 1679 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
1680 case scm_tc7_smob:
1681 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1682 v = scm_ra2contig (v, 1);
1146b6cd 1683 cstart = SCM_ARRAY_BASE (v);
d245ce23
MD
1684 vlen = (SCM_ARRAY_DIMS (v)->inc
1685 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
0f2d19dd
JB
1686 v = SCM_ARRAY_V (v);
1687 goto loop;
0f2d19dd 1688 case scm_tc7_string:
74014c46 1689 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1690 sz = sizeof (char);
1691 break;
1692 case scm_tc7_bvect:
74014c46 1693 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1694 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1695 cstart /= SCM_LONG_BIT;
1696 sz = sizeof (long);
74014c46
DH
1697 break;
1698 case scm_tc7_byvect:
1699 base = (char *) SCM_UVECTOR_BASE (v);
1700 sz = sizeof (char);
1701 break;
0f2d19dd
JB
1702 case scm_tc7_uvect:
1703 case scm_tc7_ivect:
74014c46 1704 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1705 sz = sizeof (long);
1706 break;
1707 case scm_tc7_svect:
74014c46 1708 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1709 sz = sizeof (short);
1710 break;
5c11cc9d 1711#ifdef HAVE_LONG_LONGS
0f2d19dd 1712 case scm_tc7_llvect:
74014c46 1713 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1714 sz = sizeof (long long);
0f2d19dd
JB
1715 break;
1716#endif
0f2d19dd 1717 case scm_tc7_fvect:
74014c46 1718 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1719 sz = sizeof (float);
1720 break;
0f2d19dd 1721 case scm_tc7_dvect:
74014c46 1722 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1723 sz = sizeof (double);
1724 break;
1725 case scm_tc7_cvect:
74014c46 1726 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1727 sz = 2 * sizeof (double);
1728 break;
0f2d19dd 1729 }
3d8d56df 1730
1146b6cd
GH
1731 cend = vlen;
1732 if (!SCM_UNBNDP (start))
3d8d56df 1733 {
1146b6cd 1734 offset =
c014a02e 1735 SCM_NUM2LONG (3, start);
3d8d56df 1736
1146b6cd 1737 if (offset < 0 || offset >= cend)
1bbd0b84 1738 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1739
1740 if (!SCM_UNBNDP (end))
1741 {
c014a02e
ML
1742 long tend =
1743 SCM_NUM2LONG (4, end);
3d8d56df 1744
1146b6cd 1745 if (tend <= offset || tend > cend)
1bbd0b84 1746 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1747 cend = tend;
1748 }
3d8d56df
GH
1749 }
1750
1751 if (SCM_NIMP (port_or_fd))
1752 {
405aaef9 1753 char *source = base + (cstart + offset) * sz;
6c951427
GH
1754
1755 ans = cend - offset;
265e6a4d 1756 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1757 }
1758 else /* file descriptor. */
1759 {
1760 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
405aaef9 1761 base + (cstart + offset) * sz,
1be6b49c 1762 (sz * (cend - offset))));
3d8d56df 1763 if (ans == -1)
1bbd0b84 1764 SCM_SYSERROR;
3d8d56df 1765 }
0f2d19dd 1766 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1767 ans *= SCM_LONG_BIT;
3d8d56df 1768
0f2d19dd
JB
1769 return SCM_MAKINUM (ans);
1770}
1bbd0b84 1771#undef FUNC_NAME
0f2d19dd
JB
1772
1773
1774static char cnt_tab[16] =
1775{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1776
3b3b36dd 1777SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1778 (SCM b, SCM bitvector),
1e6808ea 1779 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1780 "@var{bitvector}.")
1bbd0b84 1781#define FUNC_NAME s_scm_bit_count
0f2d19dd 1782{
44e47754 1783 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1784 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1785 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1786 return SCM_INUM0;
1787 } else {
c014a02e
ML
1788 unsigned long int count = 0;
1789 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1790 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
44e47754
DH
1791 if (SCM_FALSEP (b)) {
1792 w = ~w;
1793 };
c014a02e 1794 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1795 while (1) {
1796 while (w) {
1797 count += cnt_tab[w & 0x0f];
1798 w >>= 4;
1799 }
1800 if (i == 0) {
1801 return SCM_MAKINUM (count);
1802 } else {
1803 --i;
1804 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1805 if (SCM_FALSEP (b)) {
1806 w = ~w;
0f2d19dd 1807 }
44e47754 1808 }
0f2d19dd 1809 }
44e47754 1810 }
0f2d19dd 1811}
1bbd0b84 1812#undef FUNC_NAME
0f2d19dd
JB
1813
1814
3b3b36dd 1815SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1816 (SCM item, SCM v, SCM k),
1e6808ea
MG
1817 "Return the minimum index of an occurrence of @var{bool} in\n"
1818 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1819 "within the specified range @code{#f} is returned.")
1bbd0b84 1820#define FUNC_NAME s_scm_bit_position
0f2d19dd 1821{
c014a02e
ML
1822 long i, lenw, xbits, pos;
1823 register unsigned long w;
74014c46
DH
1824
1825 SCM_VALIDATE_BOOL (1, item);
1826 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
3b3b36dd 1827 SCM_VALIDATE_INUM_COPY (3,k,pos);
74014c46
DH
1828 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1829
1830 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1831 return SCM_BOOL_F;
74014c46 1832
c014a02e
ML
1833 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1834 i = pos / SCM_LONG_BIT;
74014c46
DH
1835 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1836 if (SCM_FALSEP (item))
1837 w = ~w;
c014a02e 1838 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1839 pos -= xbits;
1840 w = ((w >> xbits) << xbits);
c014a02e 1841 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1842 while (!0)
1843 {
1844 if (w && (i == lenw))
1845 w = ((w << xbits) >> xbits);
1846 if (w)
1847 while (w)
1848 switch (w & 0x0f)
1849 {
1850 default:
1851 return SCM_MAKINUM (pos);
1852 case 2:
1853 case 6:
1854 case 10:
1855 case 14:
1856 return SCM_MAKINUM (pos + 1);
1857 case 4:
1858 case 12:
1859 return SCM_MAKINUM (pos + 2);
1860 case 8:
1861 return SCM_MAKINUM (pos + 3);
1862 case 0:
1863 pos += 4;
1864 w >>= 4;
1865 }
1866 if (++i > lenw)
1867 break;
c014a02e 1868 pos += SCM_LONG_BIT;
f1267706 1869 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1870 if (SCM_FALSEP (item))
1871 w = ~w;
0f2d19dd 1872 }
74014c46 1873 return SCM_BOOL_F;
0f2d19dd 1874}
1bbd0b84 1875#undef FUNC_NAME
0f2d19dd
JB
1876
1877
3b3b36dd 1878SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761
MG
1879 (SCM v, SCM kv, SCM obj),
1880 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1881 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1882 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1883 "AND'ed into @var{bv}.\n\n"
8f85c0c6 1884 "If uve is a unsigned long integer vector all the elements of uve\n"
c7eb8761
MG
1885 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1886 "of @var{bv} corresponding to the indexes in uve are set to\n"
1887 "@var{bool}. The return value is unspecified.")
1bbd0b84 1888#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1889{
c014a02e 1890 register long i, k, vlen;
74014c46 1891 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1892 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1893 switch SCM_TYP7 (kv)
0f2d19dd
JB
1894 {
1895 default:
276dd677 1896 badarg2:SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1897 case scm_tc7_uvect:
74014c46
DH
1898 vlen = SCM_BITVECTOR_LENGTH (v);
1899 if (SCM_FALSEP (obj))
1900 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1901 {
c014a02e 1902 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1903 if (k >= vlen)
1904 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1905 SCM_BITVEC_CLR(v,k);
1906 }
1907 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1908 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1909 {
c014a02e 1910 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1911 if (k >= vlen)
1912 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1913 SCM_BITVEC_SET(v,k);
1914 }
1915 else
276dd677 1916 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1917 break;
1918 case scm_tc7_bvect:
74014c46 1919 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1920 if (SCM_FALSEP (obj))
c014a02e 1921 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1922 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
9a09deb1 1923 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c014a02e 1924 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1925 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
0f2d19dd
JB
1926 else
1927 goto badarg3;
1928 break;
1929 }
1930 return SCM_UNSPECIFIED;
1931}
1bbd0b84 1932#undef FUNC_NAME
0f2d19dd
JB
1933
1934
3b3b36dd 1935SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1936 (SCM v, SCM kv, SCM obj),
1e6808ea
MG
1937 "Return\n"
1938 "@lisp\n"
b380b885 1939 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1e6808ea 1940 "@end lisp\n"
b380b885 1941 "@var{bv} is not modified.")
1bbd0b84 1942#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1943{
c014a02e
ML
1944 register long i, vlen, count = 0;
1945 register unsigned long k;
41b0806d 1946 int fObj = 0;
c209c88e 1947
74014c46 1948 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1949 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1950 switch SCM_TYP7 (kv)
0f2d19dd
JB
1951 {
1952 default:
c209c88e 1953 badarg2:
276dd677 1954 SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1955 case scm_tc7_uvect:
74014c46
DH
1956 vlen = SCM_BITVECTOR_LENGTH (v);
1957 if (SCM_FALSEP (obj))
1958 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1959 {
c014a02e 1960 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1961 if (k >= vlen)
1962 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1963 if (!SCM_BITVEC_REF(v,k))
1964 count++;
1965 }
1966 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1967 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1968 {
c014a02e 1969 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1970 if (k >= vlen)
1971 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1972 if (SCM_BITVEC_REF (v,k))
1973 count++;
1974 }
1975 else
276dd677 1976 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1977 break;
1978 case scm_tc7_bvect:
74014c46
DH
1979 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1980 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1981 return SCM_INUM0;
4260a7fc 1982 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1983 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
c014a02e
ML
1984 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1985 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1986 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1987 while (1)
0f2d19dd
JB
1988 {
1989 for (; k; k >>= 4)
1990 count += cnt_tab[k & 0x0f];
1991 if (0 == i--)
1992 return SCM_MAKINUM (count);
c209c88e
GB
1993
1994 /* urg. repetitive (see above.) */
c014a02e 1995 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1996 }
1997 }
1998 return SCM_MAKINUM (count);
1999}
1bbd0b84 2000#undef FUNC_NAME
0f2d19dd
JB
2001
2002
3b3b36dd 2003SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2004 (SCM v),
8f85c0c6 2005 "Modify @var{bv} by replacing each element with its negation.")
1bbd0b84 2006#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2007{
c014a02e 2008 long int k;
74014c46
DH
2009
2010 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
2011
2012 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 2013 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 2014 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 2015
0f2d19dd
JB
2016 return SCM_UNSPECIFIED;
2017}
1bbd0b84 2018#undef FUNC_NAME
0f2d19dd
JB
2019
2020
0f2d19dd 2021SCM
c014a02e 2022scm_istr2bve (char *str, long len)
0f2d19dd
JB
2023{
2024 SCM v = scm_make_uve (len, SCM_BOOL_T);
c014a02e
ML
2025 long *data = (long *) SCM_VELTS (v);
2026 register unsigned long mask;
2027 register long k;
2028 register long j;
2029 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
2030 {
2031 data[k] = 0L;
c014a02e
ML
2032 j = len - k * SCM_LONG_BIT;
2033 if (j > SCM_LONG_BIT)
2034 j = SCM_LONG_BIT;
0f2d19dd
JB
2035 for (mask = 1L; j--; mask <<= 1)
2036 switch (*str++)
2037 {
2038 case '0':
2039 break;
2040 case '1':
2041 data[k] |= mask;
2042 break;
2043 default:
2044 return SCM_BOOL_F;
2045 }
2046 }
2047 return v;
2048}
2049
2050
1cc91f1b 2051
0f2d19dd 2052static SCM
c014a02e 2053ra2l (SCM ra,unsigned long base,unsigned long k)
0f2d19dd
JB
2054{
2055 register SCM res = SCM_EOL;
c014a02e
ML
2056 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2057 register size_t i;
0f2d19dd
JB
2058 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2059 return SCM_EOL;
2060 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2061 if (k < SCM_ARRAY_NDIM (ra) - 1)
2062 {
2063 do
2064 {
2065 i -= inc;
2066 res = scm_cons (ra2l (ra, i, k + 1), res);
2067 }
2068 while (i != base);
2069 }
2070 else
2071 do
2072 {
2073 i -= inc;
2074 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2075 }
2076 while (i != base);
2077 return res;
2078}
2079
2080
cd328b4f 2081SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2082 (SCM v),
1e6808ea
MG
2083 "Return a list consisting of all the elements, in order, of\n"
2084 "@var{array}.")
cd328b4f 2085#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2086{
2087 SCM res = SCM_EOL;
c014a02e 2088 register long k;
0f2d19dd 2089 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2090 switch SCM_TYP7 (v)
0f2d19dd
JB
2091 {
2092 default:
276dd677 2093 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
2094 case scm_tc7_smob:
2095 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2096 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2097 case scm_tc7_vector:
95f5b0f5 2098 case scm_tc7_wvect:
0f2d19dd
JB
2099 return scm_vector_to_list (v);
2100 case scm_tc7_string:
2101 return scm_string_to_list (v);
2102 case scm_tc7_bvect:
2103 {
c014a02e
ML
2104 long *data = (long *) SCM_VELTS (v);
2105 register unsigned long mask;
2106 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2107 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2108 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2109 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2110 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2111 return res;
2112 }
af7546eb
DH
2113 case scm_tc7_byvect:
2114 {
2115 signed char *data = (signed char *) SCM_VELTS (v);
c014a02e 2116 unsigned long k = SCM_UVECTOR_LENGTH (v);
af7546eb
DH
2117 while (k != 0)
2118 res = scm_cons (SCM_MAKINUM (data[--k]), res);
2119 return res;
2120 }
2121 case scm_tc7_uvect:
2122 {
c014a02e 2123 long *data = (long *)SCM_VELTS(v);
af7546eb 2124 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2125 res = scm_cons(scm_ulong2num(data[k]), res);
af7546eb
DH
2126 return res;
2127 }
2128 case scm_tc7_ivect:
2129 {
c014a02e 2130 long *data = (long *)SCM_VELTS(v);
af7546eb 2131 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2132 res = scm_cons(scm_long2num(data[k]), res);
af7546eb
DH
2133 return res;
2134 }
2135 case scm_tc7_svect:
2136 {
2137 short *data = (short *)SCM_VELTS(v);
2138 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
1be6b49c 2139 res = scm_cons(scm_short2num (data[k]), res);
af7546eb
DH
2140 return res;
2141 }
5c11cc9d 2142#ifdef HAVE_LONG_LONGS
af7546eb
DH
2143 case scm_tc7_llvect:
2144 {
1be6b49c 2145 long long *data = (long long *)SCM_VELTS(v);
af7546eb
DH
2146 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
2147 res = scm_cons(scm_long_long2num(data[k]), res);
2148 return res;
2149 }
0f2d19dd 2150#endif
0f2d19dd
JB
2151 case scm_tc7_fvect:
2152 {
2153 float *data = (float *) SCM_VELTS (v);
74014c46 2154 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2155 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2156 return res;
2157 }
0f2d19dd
JB
2158 case scm_tc7_dvect:
2159 {
2160 double *data = (double *) SCM_VELTS (v);
74014c46 2161 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2162 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2163 return res;
2164 }
2165 case scm_tc7_cvect:
2166 {
2167 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2168 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2169 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2170 return res;
2171 }
0f2d19dd
JB
2172 }
2173}
1bbd0b84 2174#undef FUNC_NAME
0f2d19dd
JB
2175
2176
c014a02e 2177static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2178
3b3b36dd 2179SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2180 (SCM ndim, SCM prot, SCM lst),
8f85c0c6 2181 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1e6808ea
MG
2182 "Return a uniform array of the type indicated by prototype\n"
2183 "@var{prot} with elements the same as those of @var{lst}.\n"
2184 "Elements must be of the appropriate type, no coercions are\n"
2185 "done.")
1bbd0b84 2186#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2187{
2188 SCM shp = SCM_EOL;
2189 SCM row = lst;
2190 SCM ra;
c014a02e 2191 unsigned long k;
0f2d19dd 2192 long n;
3b3b36dd 2193 SCM_VALIDATE_INUM_COPY (1,ndim,k);
0f2d19dd
JB
2194 while (k--)
2195 {
2196 n = scm_ilength (row);
1bbd0b84 2197 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2198 shp = scm_cons (SCM_MAKINUM (n), shp);
2199 if (SCM_NIMP (row))
2200 row = SCM_CAR (row);
2201 }
d12feca3
GH
2202 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2203 SCM_UNDEFINED);
0f2d19dd 2204 if (SCM_NULLP (shp))
0f2d19dd
JB
2205 {
2206 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2207 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2208 return ra;
2209 }
2210 if (!SCM_ARRAYP (ra))
2211 {
c014a02e 2212 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
74014c46 2213 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2214 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2215 return ra;
2216 }
2217 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2218 return ra;
2219 else
1afff620
KN
2220 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2221 scm_list_1 (lst));
0f2d19dd 2222}
1bbd0b84 2223#undef FUNC_NAME
0f2d19dd 2224
0f2d19dd 2225static int
c014a02e 2226l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2227{
c014a02e
ML
2228 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2229 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2230 int ok = 1;
2231 if (n <= 0)
4260a7fc 2232 return (SCM_NULLP (lst));
0f2d19dd
JB
2233 if (k < SCM_ARRAY_NDIM (ra) - 1)
2234 {
2235 while (n--)
2236 {
2237 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2238 return 0;
2239 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2240 base += inc;
2241 lst = SCM_CDR (lst);
2242 }
2243 if (SCM_NNULLP (lst))
2244 return 0;
2245 }
2246 else
2247 {
2248 while (n--)
2249 {
2250 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2251 return 0;
baa702c8 2252 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2253 base += inc;
2254 lst = SCM_CDR (lst);
2255 }
2256 if (SCM_NNULLP (lst))
fee7ef83 2257 return 0;
0f2d19dd
JB
2258 }
2259 return ok;
2260}
2261
1cc91f1b 2262
0f2d19dd 2263static void
c014a02e 2264rapr1 (SCM ra,unsigned long j,unsigned long k,SCM port,scm_print_state *pstate)
0f2d19dd 2265{
c014a02e
ML
2266 long inc = 1;
2267 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8
MD
2268 ? 0
2269 : SCM_INUM (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2270 int enclosed = 0;
2271tail:
5c11cc9d 2272 switch SCM_TYP7 (ra)
0f2d19dd
JB
2273 {
2274 case scm_tc7_smob:
2275 if (enclosed++)
2276 {
2277 SCM_ARRAY_BASE (ra) = j;
2278 if (n-- > 0)
9882ea19 2279 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2280 for (j += inc; n-- > 0; j += inc)
2281 {
b7f3516f 2282 scm_putc (' ', port);
0f2d19dd 2283 SCM_ARRAY_BASE (ra) = j;
9882ea19 2284 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2285 }
2286 break;
2287 }
2288 if (k + 1 < SCM_ARRAY_NDIM (ra))
2289 {
c014a02e 2290 long i;
0f2d19dd
JB
2291 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2292 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2293 {
b7f3516f 2294 scm_putc ('(', port);
9882ea19 2295 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2296 scm_puts (") ", port);
0f2d19dd
JB
2297 j += inc;
2298 }
2299 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2300 { /* could be zero size. */
b7f3516f 2301 scm_putc ('(', port);
9882ea19 2302 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2303 scm_putc (')', port);
0f2d19dd
JB
2304 }
2305 break;
2306 }
1be6b49c 2307 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2308 { /* Could be zero-dimensional */
2309 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2310 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2311 }
2312 else
2313 n = 1;
2314 ra = SCM_ARRAY_V (ra);
2315 goto tail;
2316 default:
5c11cc9d 2317 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2318 if (n-- > 0)
9882ea19 2319 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2320 for (j += inc; n-- > 0; j += inc)
2321 {
b7f3516f 2322 scm_putc (' ', port);
9882ea19 2323 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2324 }
2325 break;
2326 case scm_tc7_string:
2327 if (n-- > 0)
322ac0c5 2328 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2329 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2330 for (j += inc; n-- > 0; j += inc)
2331 {
b7f3516f 2332 scm_putc (' ', port);
322ac0c5 2333 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2334 }
2335 else
2336 for (j += inc; n-- > 0; j += inc)
405aaef9 2337 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2338 break;
2339 case scm_tc7_byvect:
2340 if (n-- > 0)
4260a7fc 2341 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2342 for (j += inc; n-- > 0; j += inc)
2343 {
b7f3516f 2344 scm_putc (' ', port);
4260a7fc 2345 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2346 }
2347 break;
2348
2349 case scm_tc7_uvect:
5c11cc9d
GH
2350 {
2351 char str[11];
2352
2353 if (n-- > 0)
2354 {
2355 /* intprint can't handle >= 2^31. */
fee7ef83 2356 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2357 scm_puts (str, port);
2358 }
2359 for (j += inc; n-- > 0; j += inc)
2360 {
2361 scm_putc (' ', port);
fee7ef83 2362 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2363 scm_puts (str, port);
2364 }
2365 }
0f2d19dd
JB
2366 case scm_tc7_ivect:
2367 if (n-- > 0)
fee7ef83 2368 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2369 for (j += inc; n-- > 0; j += inc)
2370 {
b7f3516f 2371 scm_putc (' ', port);
fee7ef83 2372 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2373 }
2374 break;
2375
2376 case scm_tc7_svect:
2377 if (n-- > 0)
4260a7fc 2378 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2379 for (j += inc; n-- > 0; j += inc)
2380 {
b7f3516f 2381 scm_putc (' ', port);
4260a7fc 2382 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2383 }
2384 break;
2385
0f2d19dd
JB
2386 case scm_tc7_fvect:
2387 if (n-- > 0)
2388 {
bc86da5d
MD
2389 SCM z = scm_make_real (1.0);
2390 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2391 scm_print_real (z, port, pstate);
0f2d19dd
JB
2392 for (j += inc; n-- > 0; j += inc)
2393 {
b7f3516f 2394 scm_putc (' ', port);
bc86da5d
MD
2395 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2396 scm_print_real (z, port, pstate);
0f2d19dd
JB
2397 }
2398 }
2399 break;
0f2d19dd
JB
2400 case scm_tc7_dvect:
2401 if (n-- > 0)
2402 {
bc86da5d
MD
2403 SCM z = scm_make_real (1.0 / 3.0);
2404 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2405 scm_print_real (z, port, pstate);
0f2d19dd
JB
2406 for (j += inc; n-- > 0; j += inc)
2407 {
b7f3516f 2408 scm_putc (' ', port);
bc86da5d
MD
2409 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2410 scm_print_real (z, port, pstate);
0f2d19dd
JB
2411 }
2412 }
2413 break;
2414 case scm_tc7_cvect:
2415 if (n-- > 0)
2416 {
bc86da5d
MD
2417 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2418 SCM_REAL_VALUE (z) =
2419 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2420 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2421 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2422 port, pstate);
0f2d19dd
JB
2423 for (j += inc; n-- > 0; j += inc)
2424 {
b7f3516f 2425 scm_putc (' ', port);
bc86da5d
MD
2426 SCM_REAL_VALUE (z)
2427 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2428 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2429 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2430 port, pstate);
0f2d19dd
JB
2431 }
2432 }
2433 break;
0f2d19dd
JB
2434 }
2435}
2436
2437
1cc91f1b 2438
0f2d19dd 2439int
1bbd0b84 2440scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2441{
2442 SCM v = exp;
c014a02e 2443 unsigned long base = 0;
b7f3516f 2444 scm_putc ('#', port);
0f2d19dd 2445tail:
5c11cc9d 2446 switch SCM_TYP7 (v)
0f2d19dd
JB
2447 {
2448 case scm_tc7_smob:
2449 {
2450 long ndim = SCM_ARRAY_NDIM (v);
2451 base = SCM_ARRAY_BASE (v);
2452 v = SCM_ARRAY_V (v);
2453 if (SCM_ARRAYP (v))
2454
2455 {
b7f3516f 2456 scm_puts ("<enclosed-array ", port);
9882ea19 2457 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2458 scm_putc ('>', port);
0f2d19dd
JB
2459 return 1;
2460 }
2461 else
2462 {
2463 scm_intprint (ndim, 10, port);
2464 goto tail;
2465 }
2466 }
2467 case scm_tc7_bvect:
fee7ef83 2468 if (SCM_EQ_P (exp, v))
0f2d19dd 2469 { /* a uve, not an scm_array */
c014a02e 2470 register long i, j, w;
b7f3516f 2471 scm_putc ('*', port);
c014a02e 2472 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2473 {
92c2555f 2474 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2475 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2476 {
b7f3516f 2477 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2478 w >>= 1;
2479 }
2480 }
c014a02e 2481 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2482 if (j)
2483 {
c014a02e 2484 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2485 for (; j; j--)
2486 {
b7f3516f 2487 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2488 w >>= 1;
2489 }
2490 }
2491 return 1;
2492 }
2493 else
b7f3516f 2494 scm_putc ('b', port);
0f2d19dd
JB
2495 break;
2496 case scm_tc7_string:
b7f3516f 2497 scm_putc ('a', port);
0f2d19dd
JB
2498 break;
2499 case scm_tc7_byvect:
05c33d09 2500 scm_putc ('y', port);
0f2d19dd
JB
2501 break;
2502 case scm_tc7_uvect:
b7f3516f 2503 scm_putc ('u', port);
0f2d19dd
JB
2504 break;
2505 case scm_tc7_ivect:
b7f3516f 2506 scm_putc ('e', port);
0f2d19dd
JB
2507 break;
2508 case scm_tc7_svect:
05c33d09 2509 scm_putc ('h', port);
0f2d19dd 2510 break;
5c11cc9d 2511#ifdef HAVE_LONG_LONGS
0f2d19dd 2512 case scm_tc7_llvect:
5c11cc9d 2513 scm_putc ('l', port);
0f2d19dd
JB
2514 break;
2515#endif
0f2d19dd 2516 case scm_tc7_fvect:
b7f3516f 2517 scm_putc ('s', port);
0f2d19dd 2518 break;
0f2d19dd 2519 case scm_tc7_dvect:
b7f3516f 2520 scm_putc ('i', port);
0f2d19dd
JB
2521 break;
2522 case scm_tc7_cvect:
b7f3516f 2523 scm_putc ('c', port);
0f2d19dd 2524 break;
0f2d19dd 2525 }
b7f3516f 2526 scm_putc ('(', port);
9882ea19 2527 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2528 scm_putc (')', port);
0f2d19dd
JB
2529 return 1;
2530}
2531
3b3b36dd 2532SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2533 (SCM ra),
1e6808ea
MG
2534 "Return an object that would produce an array of the same type\n"
2535 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2536 "@code{make-uniform-array}.")
1bbd0b84 2537#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2538{
2539 int enclosed = 0;
2540 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2541loop:
74014c46 2542 switch SCM_TYP7 (ra)
0f2d19dd
JB
2543 {
2544 default:
276dd677 2545 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
2546 case scm_tc7_smob:
2547 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2548 if (enclosed++)
2549 return SCM_UNSPECIFIED;
2550 ra = SCM_ARRAY_V (ra);
2551 goto loop;
2552 case scm_tc7_vector:
95f5b0f5 2553 case scm_tc7_wvect:
0f2d19dd
JB
2554 return SCM_EOL;
2555 case scm_tc7_bvect:
2556 return SCM_BOOL_T;
2557 case scm_tc7_string:
7866a09b 2558 return SCM_MAKE_CHAR ('a');
0f2d19dd 2559 case scm_tc7_byvect:
7866a09b 2560 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2561 case scm_tc7_uvect:
2562 return SCM_MAKINUM (1L);
2563 case scm_tc7_ivect:
2564 return SCM_MAKINUM (-1L);
2565 case scm_tc7_svect:
38ae064c 2566 return scm_str2symbol ("s");
5c11cc9d 2567#ifdef HAVE_LONG_LONGS
0f2d19dd 2568 case scm_tc7_llvect:
38ae064c 2569 return scm_str2symbol ("l");
0f2d19dd 2570#endif
0f2d19dd 2571 case scm_tc7_fvect:
bc86da5d 2572 return scm_make_real (1.0);
0f2d19dd 2573 case scm_tc7_dvect:
bc86da5d 2574 return scm_make_real (1.0 / 3.0);
0f2d19dd 2575 case scm_tc7_cvect:
bc86da5d 2576 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2577 }
2578}
1bbd0b84 2579#undef FUNC_NAME
0f2d19dd 2580
1cc91f1b 2581
0f2d19dd 2582static SCM
e841c3e0 2583array_mark (SCM ptr)
0f2d19dd 2584{
0f2d19dd
JB
2585 return SCM_ARRAY_V (ptr);
2586}
2587
1cc91f1b 2588
1be6b49c 2589static size_t
e841c3e0 2590array_free (SCM ptr)
0f2d19dd 2591{
4c9419ac
MV
2592 scm_gc_free (SCM_ARRAY_MEM (ptr),
2593 (sizeof (scm_t_array)
2594 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2595 "array");
2596 return 0;
0f2d19dd
JB
2597}
2598
0f2d19dd
JB
2599void
2600scm_init_unif ()
0f2d19dd 2601{
e841c3e0
KN
2602 scm_tc16_array = scm_make_smob_type ("array", 0);
2603 scm_set_smob_mark (scm_tc16_array, array_mark);
2604 scm_set_smob_free (scm_tc16_array, array_free);
2605 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2606 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
0f2d19dd 2607 scm_add_feature ("array");
8dc9439f 2608#ifndef SCM_MAGIC_SNARFER
a0599745 2609#include "libguile/unif.x"
8dc9439f 2610#endif
0f2d19dd 2611}
89e00824
ML
2612
2613/*
2614 Local Variables:
2615 c-file-style: "gnu"
2616 End:
2617*/