* threads.h: replace usage of struct timespect with
[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{
a08b0d00 149 if (!SCM_REALP (obj))
bc86da5d
MD
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);
34d19ef6
HWN
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{
34d19ef6
HWN
805 SCM res, vargs;
806 SCM const *ve = &vargs;
92c2555f 807 scm_t_array_dim *s, *r;
0f2d19dd 808 int ndim, i, k;
af45e3b0 809
b3fcac34 810 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 811 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
f5bf2977 812 switch (SCM_TYP7 (ra))
0f2d19dd
JB
813 {
814 default:
276dd677 815 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
816 case scm_tc7_bvect:
817 case scm_tc7_string:
818 case scm_tc7_byvect:
819 case scm_tc7_uvect:
820 case scm_tc7_ivect:
821 case scm_tc7_fvect:
822 case scm_tc7_dvect:
823 case scm_tc7_cvect:
824 case scm_tc7_svect:
5c11cc9d 825#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
826 case scm_tc7_llvect:
827#endif
b3fcac34
DH
828 if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
829 SCM_WRONG_NUM_ARGS ();
830 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CAR (args));
685c0d71
DH
831 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args),
832 SCM_EQ_P (SCM_INUM0, SCM_CAR (args)));
0f2d19dd
JB
833 return ra;
834 case scm_tc7_smob:
835 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
836 vargs = scm_vector (args);
b3fcac34
DH
837 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
838 SCM_WRONG_NUM_ARGS ();
839 ve = SCM_VELTS (vargs);
0f2d19dd
JB
840 ndim = 0;
841 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
842 {
20a54673 843 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 844 FUNC_NAME);
0f2d19dd 845 i = SCM_INUM (ve[k]);
685c0d71
DH
846 if (i < 0 || i >= SCM_ARRAY_NDIM (ra))
847 scm_out_of_range (FUNC_NAME, ve[k]);
0f2d19dd
JB
848 if (ndim < i)
849 ndim = i;
850 }
851 ndim++;
852 res = scm_make_ra (ndim);
853 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
854 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
855 for (k = ndim; k--;)
856 {
857 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
858 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
859 }
860 for (k = SCM_ARRAY_NDIM (ra); k--;)
861 {
862 i = SCM_INUM (ve[k]);
863 s = &(SCM_ARRAY_DIMS (ra)[k]);
864 r = &(SCM_ARRAY_DIMS (res)[i]);
865 if (r->ubnd < r->lbnd)
866 {
867 r->lbnd = s->lbnd;
868 r->ubnd = s->ubnd;
869 r->inc = s->inc;
870 ndim--;
871 }
872 else
873 {
874 if (r->ubnd > s->ubnd)
875 r->ubnd = s->ubnd;
876 if (r->lbnd < s->lbnd)
877 {
878 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
879 r->lbnd = s->lbnd;
880 }
881 r->inc += s->inc;
882 }
883 }
b3fcac34
DH
884 if (ndim > 0)
885 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
886 scm_ra_set_contp (res);
887 return res;
888 }
889}
1bbd0b84 890#undef FUNC_NAME
0f2d19dd
JB
891
892/* args are RA . AXES */
af45e3b0
DH
893SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
894 (SCM ra, SCM axes),
b380b885
MD
895 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
896 "the rank of @var{array}. @var{enclose-array} returns an array\n"
897 "resembling an array of shared arrays. The dimensions of each shared\n"
898 "array are the same as the @var{dim}th dimensions of the original array,\n"
899 "the dimensions of the outer array are the same as those of the original\n"
900 "array that did not match a @var{dim}.\n\n"
901 "An enclosed array is not a general Scheme array. Its elements may not\n"
902 "be set using @code{array-set!}. Two references to the same element of\n"
903 "an enclosed array will be @code{equal?} but will not in general be\n"
904 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
905 "enclosed array is unspecified.\n\n"
906 "examples:\n"
1e6808ea 907 "@lisp\n"
b380b885
MD
908 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
909 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
910 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
911 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 912 "@end lisp")
1bbd0b84 913#define FUNC_NAME s_scm_enclose_array
0f2d19dd 914{
af45e3b0 915 SCM axv, res, ra_inr;
92c2555f 916 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 917 int ndim, j, k, ninr, noutr;
af45e3b0 918
b3fcac34 919 SCM_VALIDATE_REST_ARGUMENT (axes);
0f2d19dd 920 if (SCM_NULLP (axes))
0f2d19dd
JB
921 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
922 ninr = scm_ilength (axes);
b3fcac34
DH
923 if (ninr < 0)
924 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
925 ra_inr = scm_make_ra (ninr);
926 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
74014c46 927 switch SCM_TYP7 (ra)
0f2d19dd
JB
928 {
929 default:
276dd677 930 badarg1:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
931 case scm_tc7_string:
932 case scm_tc7_bvect:
933 case scm_tc7_byvect:
934 case scm_tc7_uvect:
935 case scm_tc7_ivect:
936 case scm_tc7_fvect:
937 case scm_tc7_dvect:
938 case scm_tc7_cvect:
939 case scm_tc7_vector:
95f5b0f5 940 case scm_tc7_wvect:
0f2d19dd 941 case scm_tc7_svect:
5c11cc9d 942#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
943 case scm_tc7_llvect:
944#endif
945 s->lbnd = 0;
74014c46 946 s->ubnd = SCM_INUM (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
947 s->inc = 1;
948 SCM_ARRAY_V (ra_inr) = ra;
949 SCM_ARRAY_BASE (ra_inr) = 0;
950 ndim = 1;
951 break;
952 case scm_tc7_smob:
953 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
954 s = SCM_ARRAY_DIMS (ra);
955 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
956 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
957 ndim = SCM_ARRAY_NDIM (ra);
958 break;
959 }
960 noutr = ndim - ninr;
b3fcac34
DH
961 if (noutr < 0)
962 SCM_WRONG_NUM_ARGS ();
7866a09b 963 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
0f2d19dd
JB
964 res = scm_make_ra (noutr);
965 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
966 SCM_ARRAY_V (res) = ra_inr;
967 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
968 {
b3fcac34
DH
969 if (!SCM_INUMP (SCM_CAR (axes)))
970 SCM_MISC_ERROR ("bad axis", SCM_EOL);
0f2d19dd
JB
971 j = SCM_INUM (SCM_CAR (axes));
972 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
973 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
974 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
405aaef9 975 SCM_STRING_CHARS (axv)[j] = 1;
0f2d19dd
JB
976 }
977 for (j = 0, k = 0; k < noutr; k++, j++)
978 {
405aaef9 979 while (SCM_STRING_CHARS (axv)[j])
0f2d19dd
JB
980 j++;
981 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
982 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
983 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
984 }
985 scm_ra_set_contp (ra_inr);
986 scm_ra_set_contp (res);
987 return res;
988}
1bbd0b84 989#undef FUNC_NAME
0f2d19dd
JB
990
991
992
af45e3b0
DH
993SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
994 (SCM v, SCM args),
1e6808ea
MG
995 "Return @code{#t} if its arguments would be acceptable to\n"
996 "@code{array-ref}.")
1bbd0b84 997#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 998{
af45e3b0 999 SCM ind = SCM_EOL;
c014a02e 1000 long pos = 0;
1be6b49c 1001 register size_t k;
c014a02e 1002 register long j;
92c2555f 1003 scm_t_array_dim *s;
af45e3b0 1004
b3fcac34 1005 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
1006 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1007 if (SCM_NIMP (args))
1008
1009 {
1010 ind = SCM_CAR (args);
1011 args = SCM_CDR (args);
1bbd0b84 1012 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1013 pos = SCM_INUM (ind);
1014 }
1015tail:
74014c46 1016 switch SCM_TYP7 (v)
0f2d19dd
JB
1017 {
1018 default:
276dd677 1019 badarg1:SCM_WRONG_TYPE_ARG (1, v);
b3fcac34 1020 wna: SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1021 case scm_tc7_smob:
1022 k = SCM_ARRAY_NDIM (v);
1023 s = SCM_ARRAY_DIMS (v);
1024 pos = SCM_ARRAY_BASE (v);
1025 if (!k)
1026 {
1027 SCM_ASRTGO (SCM_NULLP (ind), wna);
1028 ind = SCM_INUM0;
1029 }
1030 else
1031 while (!0)
1032 {
1033 j = SCM_INUM (ind);
1034 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1035 {
1036 SCM_ASRTGO (--k == scm_ilength (args), wna);
1037 return SCM_BOOL_F;
1038 }
1039 pos += (j - s->lbnd) * (s->inc);
1040 if (!(--k && SCM_NIMP (args)))
1041 break;
1042 ind = SCM_CAR (args);
1043 args = SCM_CDR (args);
1044 s++;
b3fcac34
DH
1045 if (!SCM_INUMP (ind))
1046 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
1047 }
1048 SCM_ASRTGO (0 == k, wna);
1049 v = SCM_ARRAY_V (v);
1050 goto tail;
1051 case scm_tc7_bvect:
1052 case scm_tc7_string:
1053 case scm_tc7_byvect:
1054 case scm_tc7_uvect:
1055 case scm_tc7_ivect:
1056 case scm_tc7_fvect:
1057 case scm_tc7_dvect:
1058 case scm_tc7_cvect:
1059 case scm_tc7_svect:
5c11cc9d 1060#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1061 case scm_tc7_llvect:
1062#endif
1063 case scm_tc7_vector:
95f5b0f5 1064 case scm_tc7_wvect:
74014c46 1065 {
c014a02e 1066 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1067 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1068 return SCM_BOOL(pos >= 0 && pos < length);
1069 }
0f2d19dd
JB
1070 }
1071}
1bbd0b84 1072#undef FUNC_NAME
0f2d19dd
JB
1073
1074
1bbd0b84 1075SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1076
1bbd0b84 1077
3b3b36dd 1078SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1079 (SCM v, SCM args),
8f85c0c6 1080 "@deffnx {Scheme Procedure} array-ref v . args\n"
1e6808ea
MG
1081 "Return the element at the @code{(index1, index2)} element in\n"
1082 "@var{array}.")
1bbd0b84 1083#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd 1084{
c014a02e 1085 long pos;
0f2d19dd 1086
35de7ebe 1087 if (SCM_IMP (v))
0f2d19dd
JB
1088 {
1089 SCM_ASRTGO (SCM_NULLP (args), badarg);
1090 return v;
1091 }
1092 else if (SCM_ARRAYP (v))
0f2d19dd 1093 {
1bbd0b84 1094 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1095 v = SCM_ARRAY_V (v);
1096 }
1097 else
1098 {
c014a02e 1099 unsigned long int length;
0f2d19dd 1100 if (SCM_NIMP (args))
0f2d19dd 1101 {
1bbd0b84 1102 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1103 pos = SCM_INUM (SCM_CAR (args));
1104 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1105 }
1106 else
1107 {
34d19ef6 1108 SCM_VALIDATE_INUM (2, args);
0f2d19dd
JB
1109 pos = SCM_INUM (args);
1110 }
74014c46
DH
1111 length = SCM_INUM (scm_uniform_vector_length (v));
1112 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1113 }
74014c46 1114 switch SCM_TYP7 (v)
0f2d19dd
JB
1115 {
1116 default:
1117 if (SCM_NULLP (args))
1118 return v;
35de7ebe 1119 badarg:
276dd677
DH
1120 SCM_WRONG_TYPE_ARG (1, v);
1121 /* not reached */
c209c88e
GB
1122
1123 outrng:
1124 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1125 wna:
b3fcac34 1126 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1127 case scm_tc7_smob:
1128 { /* enclosed */
1129 int k = SCM_ARRAY_NDIM (v);
1130 SCM res = scm_make_ra (k);
1131 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1132 SCM_ARRAY_BASE (res) = pos;
1133 while (k--)
1134 {
1135 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1136 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1137 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1138 }
1139 return res;
1140 }
1141 case scm_tc7_bvect:
c209c88e 1142 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1143 return SCM_BOOL_T;
1144 else
1145 return SCM_BOOL_F;
1146 case scm_tc7_string:
322ac0c5 1147 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1148 case scm_tc7_byvect:
405aaef9 1149 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1150 case scm_tc7_uvect:
fee7ef83 1151 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1152 case scm_tc7_ivect:
1be6b49c 1153 return scm_long2num (((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1154
1155 case scm_tc7_svect:
4260a7fc 1156 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1157#ifdef HAVE_LONG_LONGS
0f2d19dd 1158 case scm_tc7_llvect:
1be6b49c 1159 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1160#endif
1161
0f2d19dd 1162 case scm_tc7_fvect:
4260a7fc 1163 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1164 case scm_tc7_dvect:
4260a7fc 1165 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1166 case scm_tc7_cvect:
4260a7fc
DH
1167 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1168 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1169 case scm_tc7_vector:
95f5b0f5 1170 case scm_tc7_wvect:
0f2d19dd
JB
1171 return SCM_VELTS (v)[pos];
1172 }
1173}
1bbd0b84 1174#undef FUNC_NAME
0f2d19dd
JB
1175
1176/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1177 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1178
0f2d19dd 1179SCM
c014a02e 1180scm_cvref (SCM v, unsigned long pos, SCM last)
db4b4ca6 1181#define FUNC_NAME "scm_cvref"
0f2d19dd 1182{
5c11cc9d 1183 switch SCM_TYP7 (v)
0f2d19dd
JB
1184 {
1185 default:
db4b4ca6 1186 SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd 1187 case scm_tc7_bvect:
34d19ef6 1188 if (SCM_BITVEC_REF(v, pos))
0f2d19dd
JB
1189 return SCM_BOOL_T;
1190 else
1191 return SCM_BOOL_F;
1192 case scm_tc7_string:
322ac0c5 1193 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1194 case scm_tc7_byvect:
405aaef9 1195 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1196 case scm_tc7_uvect:
fee7ef83 1197 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1198 case scm_tc7_ivect:
fee7ef83 1199 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1200 case scm_tc7_svect:
4260a7fc 1201 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1202#ifdef HAVE_LONG_LONGS
0f2d19dd 1203 case scm_tc7_llvect:
1be6b49c 1204 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1205#endif
0f2d19dd 1206 case scm_tc7_fvect:
fee7ef83 1207 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1208 {
4260a7fc 1209 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1210 return last;
1211 }
4260a7fc 1212 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1213 case scm_tc7_dvect:
fee7ef83 1214 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1215 {
4260a7fc 1216 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1217 return last;
1218 }
4260a7fc 1219 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1220 case scm_tc7_cvect:
bc86da5d 1221 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1222 {
4260a7fc
DH
1223 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1224 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1225 return last;
1226 }
4260a7fc
DH
1227 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1228 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1229 case scm_tc7_vector:
95f5b0f5 1230 case scm_tc7_wvect:
0f2d19dd
JB
1231 return SCM_VELTS (v)[pos];
1232 case scm_tc7_smob:
1233 { /* enclosed scm_array */
1234 int k = SCM_ARRAY_NDIM (v);
1235 SCM res = scm_make_ra (k);
1236 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1237 SCM_ARRAY_BASE (res) = pos;
1238 while (k--)
1239 {
1240 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1241 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1242 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1243 }
1244 return res;
1245 }
1246 }
1247}
db4b4ca6
DH
1248#undef FUNC_NAME
1249
0f2d19dd 1250
1bbd0b84
GB
1251SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1252
1cc91f1b 1253
0aa0871f
GH
1254/* Note that args may be a list or an immediate object, depending which
1255 PROC is used (and it's called from C too). */
3b3b36dd 1256SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1257 (SCM v, SCM obj, SCM args),
8f85c0c6
NJ
1258 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1259 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1260 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1261#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1262{
c014a02e 1263 long pos = 0;
b3fcac34 1264
0f2d19dd
JB
1265 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1266 if (SCM_ARRAYP (v))
0f2d19dd 1267 {
1bbd0b84 1268 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1269 v = SCM_ARRAY_V (v);
1270 }
1271 else
1272 {
c014a02e 1273 unsigned long int length;
9a97e362 1274 if (SCM_CONSP (args))
0f2d19dd 1275 {
9a97e362 1276 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), args, SCM_ARG3, FUNC_NAME);
0f2d19dd 1277 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1278 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1279 }
1280 else
1281 {
34d19ef6 1282 SCM_VALIDATE_INUM_COPY (3, args, pos);
0f2d19dd 1283 }
74014c46
DH
1284 length = SCM_INUM (scm_uniform_vector_length (v));
1285 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd
JB
1286 }
1287 switch (SCM_TYP7 (v))
1288 {
35de7ebe 1289 default: badarg1:
276dd677
DH
1290 SCM_WRONG_TYPE_ARG (1, v);
1291 /* not reached */
c209c88e
GB
1292 outrng:
1293 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1294 wna:
b3fcac34 1295 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1296 case scm_tc7_smob: /* enclosed */
1297 goto badarg1;
1298 case scm_tc7_bvect:
4260a7fc 1299 if (SCM_FALSEP (obj))
34d19ef6 1300 SCM_BITVEC_CLR(v, pos);
9a09deb1 1301 else if (SCM_EQ_P (obj, SCM_BOOL_T))
34d19ef6 1302 SCM_BITVEC_SET(v, pos);
0f2d19dd 1303 else
276dd677 1304 badobj:SCM_WRONG_TYPE_ARG (2, obj);
0f2d19dd
JB
1305 break;
1306 case scm_tc7_string:
7866a09b 1307 SCM_ASRTGO (SCM_CHARP (obj), badobj);
322ac0c5 1308 SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1309 break;
1310 case scm_tc7_byvect:
7866a09b
GB
1311 if (SCM_CHARP (obj))
1312 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1313 SCM_ASRTGO (SCM_INUMP (obj), badobj);
405aaef9 1314 ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1315 break;
1bbd0b84 1316 case scm_tc7_uvect:
729dbac3
DH
1317 ((unsigned long *) SCM_UVECTOR_BASE (v))[pos]
1318 = scm_num2ulong (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1319 break;
1bbd0b84 1320 case scm_tc7_ivect:
729dbac3
DH
1321 ((long *) SCM_UVECTOR_BASE (v))[pos]
1322 = scm_num2long (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1323 break;
0f2d19dd 1324 case scm_tc7_svect:
0aa0871f 1325 SCM_ASRTGO (SCM_INUMP (obj), badobj);
729dbac3 1326 ((short *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1327 break;
5c11cc9d 1328#ifdef HAVE_LONG_LONGS
0f2d19dd 1329 case scm_tc7_llvect:
729dbac3
DH
1330 ((long long *) SCM_UVECTOR_BASE (v))[pos]
1331 = scm_num2long_long (obj, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1332 break;
1333#endif
0f2d19dd 1334 case scm_tc7_fvect:
729dbac3
DH
1335 ((float *) SCM_UVECTOR_BASE (v))[pos]
1336 = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1337 break;
0f2d19dd 1338 case scm_tc7_dvect:
729dbac3
DH
1339 ((double *) SCM_UVECTOR_BASE (v))[pos]
1340 = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1341 break;
1342 case scm_tc7_cvect:
eb42e2f0
DH
1343 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1344 if (SCM_REALP (obj)) {
729dbac3
DH
1345 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_REAL_VALUE (obj);
1346 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = 0.0;
eb42e2f0 1347 } else {
729dbac3
DH
1348 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1349 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
eb42e2f0 1350 }
0f2d19dd 1351 break;
0f2d19dd 1352 case scm_tc7_vector:
95f5b0f5 1353 case scm_tc7_wvect:
34d19ef6 1354 SCM_VECTOR_SET (v, pos, obj);
0f2d19dd
JB
1355 break;
1356 }
1357 return SCM_UNSPECIFIED;
1358}
1bbd0b84 1359#undef FUNC_NAME
0f2d19dd 1360
1d7bdb25
GH
1361/* attempts to unroll an array into a one-dimensional array.
1362 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1363 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1364 wouldn't have contiguous elements. */
3b3b36dd 1365SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1366 (SCM ra, SCM strict),
b380b885
MD
1367 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1368 "without changing their order (last subscript changing fastest), then\n"
1369 "@code{array-contents} returns that shared array, otherwise it returns\n"
1370 "@code{#f}. All arrays made by @var{make-array} and\n"
1371 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1372 "@var{make-shared-array} may not be.\n\n"
1373 "If the optional argument @var{strict} is provided, a shared array will\n"
1374 "be returned only if its elements are stored internally contiguous in\n"
1375 "memory.")
1bbd0b84 1376#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1377{
1378 SCM sra;
1379 if (SCM_IMP (ra))
f3667f52 1380 return SCM_BOOL_F;
5c11cc9d 1381 switch SCM_TYP7 (ra)
0f2d19dd
JB
1382 {
1383 default:
1384 return SCM_BOOL_F;
1385 case scm_tc7_vector:
95f5b0f5 1386 case scm_tc7_wvect:
0f2d19dd
JB
1387 case scm_tc7_string:
1388 case scm_tc7_bvect:
1389 case scm_tc7_byvect:
1390 case scm_tc7_uvect:
1391 case scm_tc7_ivect:
1392 case scm_tc7_fvect:
1393 case scm_tc7_dvect:
1394 case scm_tc7_cvect:
1395 case scm_tc7_svect:
5c11cc9d 1396#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1397 case scm_tc7_llvect:
1398#endif
1399 return ra;
1400 case scm_tc7_smob:
1401 {
c014a02e 1402 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
0f2d19dd
JB
1403 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1404 return SCM_BOOL_F;
1405 for (k = 0; k < ndim; k++)
1406 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1407 if (!SCM_UNBNDP (strict))
1408 {
0f2d19dd
JB
1409 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1410 return SCM_BOOL_F;
1411 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1412 {
74014c46 1413 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
c014a02e
ML
1414 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1415 len % SCM_LONG_BIT)
0f2d19dd
JB
1416 return SCM_BOOL_F;
1417 }
1418 }
74014c46
DH
1419
1420 {
1421 SCM v = SCM_ARRAY_V (ra);
c014a02e 1422 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1423 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1424 return v;
1425 }
1426
0f2d19dd
JB
1427 sra = scm_make_ra (1);
1428 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1429 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1430 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1431 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1432 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1433 return sra;
1434 }
1435 }
1436}
1bbd0b84 1437#undef FUNC_NAME
0f2d19dd 1438
1cc91f1b 1439
0f2d19dd 1440SCM
6e8d25a6 1441scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1442{
1443 SCM ret;
c014a02e
ML
1444 long inc = 1;
1445 size_t k, len = 1;
0f2d19dd
JB
1446 for (k = SCM_ARRAY_NDIM (ra); k--;)
1447 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1448 k = SCM_ARRAY_NDIM (ra);
1449 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1450 {
74014c46 1451 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1452 return ra;
74014c46 1453 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1454 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1455 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1456 return ra;
1457 }
1458 ret = scm_make_ra (k);
1459 SCM_ARRAY_BASE (ret) = 0;
1460 while (k--)
1461 {
1462 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1463 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1464 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1465 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1466 }
08112c95 1467 SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
0f2d19dd
JB
1468 if (copy)
1469 scm_array_copy_x (ra, ret);
1470 return ret;
1471}
1472
1473
1474
3b3b36dd 1475SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1476 (SCM ra, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1477 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1478 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1479 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1480 "If an end of file is encountered,\n"
1481 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1482 "(starting at the beginning) and the remainder of the array is\n"
1483 "unchanged.\n\n"
1484 "The optional arguments @var{start} and @var{end} allow\n"
1485 "a specified region of a vector (or linearized array) to be read,\n"
1486 "leaving the remainder of the vector unchanged.\n\n"
1487 "@code{uniform-array-read!} returns the number of objects read.\n"
1488 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1489 "returned by @code{(current-input-port)}.")
1bbd0b84 1490#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1491{
35de7ebe 1492 SCM cra = SCM_UNDEFINED, v = ra;
c014a02e
ML
1493 long sz, vlen, ans;
1494 long cstart = 0;
1495 long cend;
1496 long offset = 0;
405aaef9 1497 char *base;
35de7ebe 1498
0f2d19dd 1499 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1500 if (SCM_UNBNDP (port_or_fd))
1501 port_or_fd = scm_cur_inp;
1502 else
1503 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1504 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1505 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1506 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1507 ? 0
1508 : SCM_INUM (scm_uniform_vector_length (v)));
35de7ebe 1509
0f2d19dd 1510loop:
35de7ebe 1511 switch SCM_TYP7 (v)
0f2d19dd
JB
1512 {
1513 default:
276dd677 1514 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd
JB
1515 case scm_tc7_smob:
1516 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1517 cra = scm_ra2contig (ra, 0);
1146b6cd 1518 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1519 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1520 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1521 v = SCM_ARRAY_V (cra);
1522 goto loop;
1523 case scm_tc7_string:
74014c46 1524 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1525 sz = sizeof (char);
1526 break;
1527 case scm_tc7_bvect:
74014c46 1528 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1529 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1530 cstart /= SCM_LONG_BIT;
1531 sz = sizeof (long);
74014c46
DH
1532 break;
1533 case scm_tc7_byvect:
1534 base = (char *) SCM_UVECTOR_BASE (v);
1535 sz = sizeof (char);
1536 break;
0f2d19dd
JB
1537 case scm_tc7_uvect:
1538 case scm_tc7_ivect:
74014c46 1539 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1540 sz = sizeof (long);
1541 break;
1542 case scm_tc7_svect:
74014c46 1543 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1544 sz = sizeof (short);
1545 break;
5c11cc9d 1546#ifdef HAVE_LONG_LONGS
0f2d19dd 1547 case scm_tc7_llvect:
74014c46 1548 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1549 sz = sizeof (long long);
0f2d19dd
JB
1550 break;
1551#endif
0f2d19dd 1552 case scm_tc7_fvect:
74014c46 1553 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1554 sz = sizeof (float);
1555 break;
0f2d19dd 1556 case scm_tc7_dvect:
74014c46 1557 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1558 sz = sizeof (double);
1559 break;
1560 case scm_tc7_cvect:
74014c46 1561 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1562 sz = 2 * sizeof (double);
1563 break;
0f2d19dd 1564 }
405aaef9 1565
1146b6cd
GH
1566 cend = vlen;
1567 if (!SCM_UNBNDP (start))
3d8d56df 1568 {
1146b6cd 1569 offset =
c014a02e 1570 SCM_NUM2LONG (3, start);
35de7ebe 1571
1146b6cd 1572 if (offset < 0 || offset >= cend)
1bbd0b84 1573 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1574
1575 if (!SCM_UNBNDP (end))
1576 {
c014a02e
ML
1577 long tend =
1578 SCM_NUM2LONG (4, end);
3d8d56df 1579
1146b6cd 1580 if (tend <= offset || tend > cend)
1bbd0b84 1581 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1582 cend = tend;
1583 }
0f2d19dd 1584 }
35de7ebe 1585
3d8d56df
GH
1586 if (SCM_NIMP (port_or_fd))
1587 {
92c2555f 1588 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1589 int remaining = (cend - offset) * sz;
405aaef9 1590 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1591
1592 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1593 scm_flush (port_or_fd);
6c951427
GH
1594
1595 ans = cend - offset;
1596 while (remaining > 0)
3d8d56df 1597 {
6c951427
GH
1598 if (pt->read_pos < pt->read_end)
1599 {
1600 int to_copy = min (pt->read_end - pt->read_pos,
1601 remaining);
1602
1603 memcpy (dest, pt->read_pos, to_copy);
1604 pt->read_pos += to_copy;
1605 remaining -= to_copy;
1606 dest += to_copy;
1607 }
1608 else
1609 {
affc96b5 1610 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1611 {
1612 if (remaining % sz != 0)
1613 {
5d2d2ffc 1614 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1615 }
1616 ans -= remaining / sz;
1617 break;
1618 }
6c951427 1619 }
3d8d56df 1620 }
6c951427
GH
1621
1622 if (pt->rw_random)
1623 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1624 }
1625 else /* file descriptor. */
1626 {
1627 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1628 base + (cstart + offset) * sz,
1be6b49c 1629 (sz * (cend - offset))));
3d8d56df 1630 if (ans == -1)
1bbd0b84 1631 SCM_SYSERROR;
3d8d56df 1632 }
0f2d19dd 1633 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1634 ans *= SCM_LONG_BIT;
35de7ebe 1635
fee7ef83 1636 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1637 scm_array_copy_x (cra, ra);
35de7ebe 1638
0f2d19dd
JB
1639 return SCM_MAKINUM (ans);
1640}
1bbd0b84 1641#undef FUNC_NAME
0f2d19dd 1642
3b3b36dd 1643SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1644 (SCM v, SCM port_or_fd, SCM start, SCM end),
8f85c0c6 1645 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
b380b885
MD
1646 "Writes all elements of @var{ura} as binary objects to\n"
1647 "@var{port-or-fdes}.\n\n"
1648 "The optional arguments @var{start}\n"
1649 "and @var{end} allow\n"
1650 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1651 "The number of objects actually written is returned.\n"
b380b885
MD
1652 "@var{port-or-fdes} may be\n"
1653 "omitted, in which case it defaults to the value returned by\n"
1654 "@code{(current-output-port)}.")
1bbd0b84 1655#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1656{
c014a02e
ML
1657 long sz, vlen, ans;
1658 long offset = 0;
1659 long cstart = 0;
1660 long cend;
405aaef9 1661 char *base;
3d8d56df 1662
78446828
MV
1663 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1664
0f2d19dd 1665 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1666 if (SCM_UNBNDP (port_or_fd))
1667 port_or_fd = scm_cur_outp;
1668 else
1669 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1670 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1671 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1672 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1673 ? 0
1674 : SCM_INUM (scm_uniform_vector_length (v)));
1675
0f2d19dd 1676loop:
3d8d56df 1677 switch SCM_TYP7 (v)
0f2d19dd
JB
1678 {
1679 default:
276dd677 1680 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
1681 case scm_tc7_smob:
1682 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1683 v = scm_ra2contig (v, 1);
1146b6cd 1684 cstart = SCM_ARRAY_BASE (v);
d245ce23
MD
1685 vlen = (SCM_ARRAY_DIMS (v)->inc
1686 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
0f2d19dd
JB
1687 v = SCM_ARRAY_V (v);
1688 goto loop;
0f2d19dd 1689 case scm_tc7_string:
74014c46 1690 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1691 sz = sizeof (char);
1692 break;
1693 case scm_tc7_bvect:
74014c46 1694 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1695 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1696 cstart /= SCM_LONG_BIT;
1697 sz = sizeof (long);
74014c46
DH
1698 break;
1699 case scm_tc7_byvect:
1700 base = (char *) SCM_UVECTOR_BASE (v);
1701 sz = sizeof (char);
1702 break;
0f2d19dd
JB
1703 case scm_tc7_uvect:
1704 case scm_tc7_ivect:
74014c46 1705 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1706 sz = sizeof (long);
1707 break;
1708 case scm_tc7_svect:
74014c46 1709 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1710 sz = sizeof (short);
1711 break;
5c11cc9d 1712#ifdef HAVE_LONG_LONGS
0f2d19dd 1713 case scm_tc7_llvect:
74014c46 1714 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1715 sz = sizeof (long long);
0f2d19dd
JB
1716 break;
1717#endif
0f2d19dd 1718 case scm_tc7_fvect:
74014c46 1719 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1720 sz = sizeof (float);
1721 break;
0f2d19dd 1722 case scm_tc7_dvect:
74014c46 1723 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1724 sz = sizeof (double);
1725 break;
1726 case scm_tc7_cvect:
74014c46 1727 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1728 sz = 2 * sizeof (double);
1729 break;
0f2d19dd 1730 }
3d8d56df 1731
1146b6cd
GH
1732 cend = vlen;
1733 if (!SCM_UNBNDP (start))
3d8d56df 1734 {
1146b6cd 1735 offset =
c014a02e 1736 SCM_NUM2LONG (3, start);
3d8d56df 1737
1146b6cd 1738 if (offset < 0 || offset >= cend)
1bbd0b84 1739 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1740
1741 if (!SCM_UNBNDP (end))
1742 {
c014a02e
ML
1743 long tend =
1744 SCM_NUM2LONG (4, end);
3d8d56df 1745
1146b6cd 1746 if (tend <= offset || tend > cend)
1bbd0b84 1747 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1748 cend = tend;
1749 }
3d8d56df
GH
1750 }
1751
1752 if (SCM_NIMP (port_or_fd))
1753 {
405aaef9 1754 char *source = base + (cstart + offset) * sz;
6c951427
GH
1755
1756 ans = cend - offset;
265e6a4d 1757 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1758 }
1759 else /* file descriptor. */
1760 {
1761 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
405aaef9 1762 base + (cstart + offset) * sz,
1be6b49c 1763 (sz * (cend - offset))));
3d8d56df 1764 if (ans == -1)
1bbd0b84 1765 SCM_SYSERROR;
3d8d56df 1766 }
0f2d19dd 1767 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1768 ans *= SCM_LONG_BIT;
3d8d56df 1769
0f2d19dd
JB
1770 return SCM_MAKINUM (ans);
1771}
1bbd0b84 1772#undef FUNC_NAME
0f2d19dd
JB
1773
1774
1775static char cnt_tab[16] =
1776{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1777
3b3b36dd 1778SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1779 (SCM b, SCM bitvector),
1e6808ea 1780 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1781 "@var{bitvector}.")
1bbd0b84 1782#define FUNC_NAME s_scm_bit_count
0f2d19dd 1783{
44e47754 1784 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1785 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1786 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1787 return SCM_INUM0;
1788 } else {
c014a02e
ML
1789 unsigned long int count = 0;
1790 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1791 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
44e47754
DH
1792 if (SCM_FALSEP (b)) {
1793 w = ~w;
1794 };
c014a02e 1795 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1796 while (1) {
1797 while (w) {
1798 count += cnt_tab[w & 0x0f];
1799 w >>= 4;
1800 }
1801 if (i == 0) {
1802 return SCM_MAKINUM (count);
1803 } else {
1804 --i;
1805 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1806 if (SCM_FALSEP (b)) {
1807 w = ~w;
0f2d19dd 1808 }
44e47754 1809 }
0f2d19dd 1810 }
44e47754 1811 }
0f2d19dd 1812}
1bbd0b84 1813#undef FUNC_NAME
0f2d19dd
JB
1814
1815
3b3b36dd 1816SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1817 (SCM item, SCM v, SCM k),
1e6808ea
MG
1818 "Return the minimum index of an occurrence of @var{bool} in\n"
1819 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1820 "within the specified range @code{#f} is returned.")
1bbd0b84 1821#define FUNC_NAME s_scm_bit_position
0f2d19dd 1822{
c014a02e
ML
1823 long i, lenw, xbits, pos;
1824 register unsigned long w;
74014c46
DH
1825
1826 SCM_VALIDATE_BOOL (1, item);
1827 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
34d19ef6 1828 SCM_VALIDATE_INUM_COPY (3, k, pos);
74014c46
DH
1829 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1830
1831 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1832 return SCM_BOOL_F;
74014c46 1833
c014a02e
ML
1834 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1835 i = pos / SCM_LONG_BIT;
74014c46
DH
1836 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1837 if (SCM_FALSEP (item))
1838 w = ~w;
c014a02e 1839 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1840 pos -= xbits;
1841 w = ((w >> xbits) << xbits);
c014a02e 1842 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1843 while (!0)
1844 {
1845 if (w && (i == lenw))
1846 w = ((w << xbits) >> xbits);
1847 if (w)
1848 while (w)
1849 switch (w & 0x0f)
1850 {
1851 default:
1852 return SCM_MAKINUM (pos);
1853 case 2:
1854 case 6:
1855 case 10:
1856 case 14:
1857 return SCM_MAKINUM (pos + 1);
1858 case 4:
1859 case 12:
1860 return SCM_MAKINUM (pos + 2);
1861 case 8:
1862 return SCM_MAKINUM (pos + 3);
1863 case 0:
1864 pos += 4;
1865 w >>= 4;
1866 }
1867 if (++i > lenw)
1868 break;
c014a02e 1869 pos += SCM_LONG_BIT;
f1267706 1870 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1871 if (SCM_FALSEP (item))
1872 w = ~w;
0f2d19dd 1873 }
74014c46 1874 return SCM_BOOL_F;
0f2d19dd 1875}
1bbd0b84 1876#undef FUNC_NAME
0f2d19dd
JB
1877
1878
3b3b36dd 1879SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761
MG
1880 (SCM v, SCM kv, SCM obj),
1881 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1882 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1883 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1884 "AND'ed into @var{bv}.\n\n"
8f85c0c6 1885 "If uve is a unsigned long integer vector all the elements of uve\n"
c7eb8761
MG
1886 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1887 "of @var{bv} corresponding to the indexes in uve are set to\n"
1888 "@var{bool}. The return value is unspecified.")
1bbd0b84 1889#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1890{
c014a02e 1891 register long i, k, vlen;
74014c46 1892 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1893 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1894 switch SCM_TYP7 (kv)
0f2d19dd
JB
1895 {
1896 default:
276dd677 1897 badarg2:SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1898 case scm_tc7_uvect:
74014c46
DH
1899 vlen = SCM_BITVECTOR_LENGTH (v);
1900 if (SCM_FALSEP (obj))
1901 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1902 {
c014a02e 1903 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1904 if (k >= vlen)
1905 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1906 SCM_BITVEC_CLR(v, k);
74014c46
DH
1907 }
1908 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1909 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1910 {
c014a02e 1911 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1912 if (k >= vlen)
1913 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1914 SCM_BITVEC_SET(v, k);
74014c46
DH
1915 }
1916 else
276dd677 1917 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1918 break;
1919 case scm_tc7_bvect:
74014c46 1920 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1921 if (SCM_FALSEP (obj))
c014a02e 1922 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1923 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
9a09deb1 1924 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c014a02e 1925 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1926 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
0f2d19dd
JB
1927 else
1928 goto badarg3;
1929 break;
1930 }
1931 return SCM_UNSPECIFIED;
1932}
1bbd0b84 1933#undef FUNC_NAME
0f2d19dd
JB
1934
1935
3b3b36dd 1936SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1937 (SCM v, SCM kv, SCM obj),
1e6808ea
MG
1938 "Return\n"
1939 "@lisp\n"
b380b885 1940 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1e6808ea 1941 "@end lisp\n"
b380b885 1942 "@var{bv} is not modified.")
1bbd0b84 1943#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1944{
c014a02e
ML
1945 register long i, vlen, count = 0;
1946 register unsigned long k;
41b0806d 1947 int fObj = 0;
c209c88e 1948
74014c46 1949 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1950 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1951 switch SCM_TYP7 (kv)
0f2d19dd
JB
1952 {
1953 default:
c209c88e 1954 badarg2:
276dd677 1955 SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1956 case scm_tc7_uvect:
74014c46
DH
1957 vlen = SCM_BITVECTOR_LENGTH (v);
1958 if (SCM_FALSEP (obj))
1959 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1960 {
c014a02e 1961 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1962 if (k >= vlen)
1963 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1964 if (!SCM_BITVEC_REF(v, k))
74014c46
DH
1965 count++;
1966 }
1967 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1968 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1969 {
c014a02e 1970 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1971 if (k >= vlen)
1972 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1973 if (SCM_BITVEC_REF (v, k))
74014c46
DH
1974 count++;
1975 }
1976 else
276dd677 1977 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1978 break;
1979 case scm_tc7_bvect:
74014c46
DH
1980 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1981 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1982 return SCM_INUM0;
4260a7fc 1983 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1984 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
c014a02e
ML
1985 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1986 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1987 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1988 while (1)
0f2d19dd
JB
1989 {
1990 for (; k; k >>= 4)
1991 count += cnt_tab[k & 0x0f];
1992 if (0 == i--)
1993 return SCM_MAKINUM (count);
c209c88e
GB
1994
1995 /* urg. repetitive (see above.) */
c014a02e 1996 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1997 }
1998 }
1999 return SCM_MAKINUM (count);
2000}
1bbd0b84 2001#undef FUNC_NAME
0f2d19dd
JB
2002
2003
3b3b36dd 2004SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2005 (SCM v),
8f85c0c6 2006 "Modify @var{bv} by replacing each element with its negation.")
1bbd0b84 2007#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2008{
c014a02e 2009 long int k;
74014c46
DH
2010
2011 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
2012
2013 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 2014 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 2015 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 2016
0f2d19dd
JB
2017 return SCM_UNSPECIFIED;
2018}
1bbd0b84 2019#undef FUNC_NAME
0f2d19dd
JB
2020
2021
0f2d19dd 2022SCM
c014a02e 2023scm_istr2bve (char *str, long len)
0f2d19dd
JB
2024{
2025 SCM v = scm_make_uve (len, SCM_BOOL_T);
c014a02e
ML
2026 long *data = (long *) SCM_VELTS (v);
2027 register unsigned long mask;
2028 register long k;
2029 register long j;
2030 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
2031 {
2032 data[k] = 0L;
c014a02e
ML
2033 j = len - k * SCM_LONG_BIT;
2034 if (j > SCM_LONG_BIT)
2035 j = SCM_LONG_BIT;
0f2d19dd
JB
2036 for (mask = 1L; j--; mask <<= 1)
2037 switch (*str++)
2038 {
2039 case '0':
2040 break;
2041 case '1':
2042 data[k] |= mask;
2043 break;
2044 default:
2045 return SCM_BOOL_F;
2046 }
2047 }
2048 return v;
2049}
2050
2051
1cc91f1b 2052
0f2d19dd 2053static SCM
34d19ef6 2054ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd
JB
2055{
2056 register SCM res = SCM_EOL;
c014a02e
ML
2057 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2058 register size_t i;
0f2d19dd
JB
2059 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2060 return SCM_EOL;
2061 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2062 if (k < SCM_ARRAY_NDIM (ra) - 1)
2063 {
2064 do
2065 {
2066 i -= inc;
2067 res = scm_cons (ra2l (ra, i, k + 1), res);
2068 }
2069 while (i != base);
2070 }
2071 else
2072 do
2073 {
2074 i -= inc;
2075 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2076 }
2077 while (i != base);
2078 return res;
2079}
2080
2081
cd328b4f 2082SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2083 (SCM v),
1e6808ea
MG
2084 "Return a list consisting of all the elements, in order, of\n"
2085 "@var{array}.")
cd328b4f 2086#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2087{
2088 SCM res = SCM_EOL;
c014a02e 2089 register long k;
0f2d19dd 2090 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2091 switch SCM_TYP7 (v)
0f2d19dd
JB
2092 {
2093 default:
276dd677 2094 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
2095 case scm_tc7_smob:
2096 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2097 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2098 case scm_tc7_vector:
95f5b0f5 2099 case scm_tc7_wvect:
0f2d19dd
JB
2100 return scm_vector_to_list (v);
2101 case scm_tc7_string:
2102 return scm_string_to_list (v);
2103 case scm_tc7_bvect:
2104 {
c014a02e
ML
2105 long *data = (long *) SCM_VELTS (v);
2106 register unsigned long mask;
2107 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2108 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2109 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2110 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2111 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2112 return res;
2113 }
af7546eb
DH
2114 case scm_tc7_byvect:
2115 {
2116 signed char *data = (signed char *) SCM_VELTS (v);
c014a02e 2117 unsigned long k = SCM_UVECTOR_LENGTH (v);
af7546eb
DH
2118 while (k != 0)
2119 res = scm_cons (SCM_MAKINUM (data[--k]), res);
2120 return res;
2121 }
2122 case scm_tc7_uvect:
2123 {
c014a02e 2124 long *data = (long *)SCM_VELTS(v);
af7546eb 2125 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2126 res = scm_cons(scm_ulong2num(data[k]), res);
af7546eb
DH
2127 return res;
2128 }
2129 case scm_tc7_ivect:
2130 {
c014a02e 2131 long *data = (long *)SCM_VELTS(v);
af7546eb 2132 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2133 res = scm_cons(scm_long2num(data[k]), res);
af7546eb
DH
2134 return res;
2135 }
2136 case scm_tc7_svect:
2137 {
2138 short *data = (short *)SCM_VELTS(v);
2139 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
1be6b49c 2140 res = scm_cons(scm_short2num (data[k]), res);
af7546eb
DH
2141 return res;
2142 }
5c11cc9d 2143#ifdef HAVE_LONG_LONGS
af7546eb
DH
2144 case scm_tc7_llvect:
2145 {
1be6b49c 2146 long long *data = (long long *)SCM_VELTS(v);
af7546eb
DH
2147 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
2148 res = scm_cons(scm_long_long2num(data[k]), res);
2149 return res;
2150 }
0f2d19dd 2151#endif
0f2d19dd
JB
2152 case scm_tc7_fvect:
2153 {
2154 float *data = (float *) SCM_VELTS (v);
74014c46 2155 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2156 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2157 return res;
2158 }
0f2d19dd
JB
2159 case scm_tc7_dvect:
2160 {
2161 double *data = (double *) SCM_VELTS (v);
74014c46 2162 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2163 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2164 return res;
2165 }
2166 case scm_tc7_cvect:
2167 {
2168 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2169 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2170 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2171 return res;
2172 }
0f2d19dd
JB
2173 }
2174}
1bbd0b84 2175#undef FUNC_NAME
0f2d19dd
JB
2176
2177
c014a02e 2178static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2179
3b3b36dd 2180SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2181 (SCM ndim, SCM prot, SCM lst),
8f85c0c6 2182 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1e6808ea
MG
2183 "Return a uniform array of the type indicated by prototype\n"
2184 "@var{prot} with elements the same as those of @var{lst}.\n"
2185 "Elements must be of the appropriate type, no coercions are\n"
2186 "done.")
1bbd0b84 2187#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2188{
2189 SCM shp = SCM_EOL;
2190 SCM row = lst;
2191 SCM ra;
c014a02e 2192 unsigned long k;
0f2d19dd 2193 long n;
34d19ef6 2194 SCM_VALIDATE_INUM_COPY (1, ndim, k);
0f2d19dd
JB
2195 while (k--)
2196 {
2197 n = scm_ilength (row);
1bbd0b84 2198 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2199 shp = scm_cons (SCM_MAKINUM (n), shp);
2200 if (SCM_NIMP (row))
2201 row = SCM_CAR (row);
2202 }
d12feca3
GH
2203 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2204 SCM_UNDEFINED);
0f2d19dd 2205 if (SCM_NULLP (shp))
0f2d19dd
JB
2206 {
2207 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2208 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2209 return ra;
2210 }
2211 if (!SCM_ARRAYP (ra))
2212 {
c014a02e 2213 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
74014c46 2214 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2215 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2216 return ra;
2217 }
2218 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2219 return ra;
2220 else
1afff620
KN
2221 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2222 scm_list_1 (lst));
0f2d19dd 2223}
1bbd0b84 2224#undef FUNC_NAME
0f2d19dd 2225
0f2d19dd 2226static int
c014a02e 2227l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2228{
c014a02e
ML
2229 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2230 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2231 int ok = 1;
2232 if (n <= 0)
4260a7fc 2233 return (SCM_NULLP (lst));
0f2d19dd
JB
2234 if (k < SCM_ARRAY_NDIM (ra) - 1)
2235 {
2236 while (n--)
2237 {
2238 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2239 return 0;
2240 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2241 base += inc;
2242 lst = SCM_CDR (lst);
2243 }
2244 if (SCM_NNULLP (lst))
2245 return 0;
2246 }
2247 else
2248 {
2249 while (n--)
2250 {
2251 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2252 return 0;
baa702c8 2253 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2254 base += inc;
2255 lst = SCM_CDR (lst);
2256 }
2257 if (SCM_NNULLP (lst))
fee7ef83 2258 return 0;
0f2d19dd
JB
2259 }
2260 return ok;
2261}
2262
1cc91f1b 2263
0f2d19dd 2264static void
34d19ef6 2265rapr1 (SCM ra, unsigned long j, unsigned long k, SCM port, scm_print_state *pstate)
0f2d19dd 2266{
c014a02e
ML
2267 long inc = 1;
2268 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8
MD
2269 ? 0
2270 : SCM_INUM (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2271 int enclosed = 0;
2272tail:
5c11cc9d 2273 switch SCM_TYP7 (ra)
0f2d19dd
JB
2274 {
2275 case scm_tc7_smob:
2276 if (enclosed++)
2277 {
2278 SCM_ARRAY_BASE (ra) = j;
2279 if (n-- > 0)
9882ea19 2280 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2281 for (j += inc; n-- > 0; j += inc)
2282 {
b7f3516f 2283 scm_putc (' ', port);
0f2d19dd 2284 SCM_ARRAY_BASE (ra) = j;
9882ea19 2285 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2286 }
2287 break;
2288 }
2289 if (k + 1 < SCM_ARRAY_NDIM (ra))
2290 {
c014a02e 2291 long i;
0f2d19dd
JB
2292 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2293 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2294 {
b7f3516f 2295 scm_putc ('(', port);
9882ea19 2296 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2297 scm_puts (") ", port);
0f2d19dd
JB
2298 j += inc;
2299 }
2300 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2301 { /* could be zero size. */
b7f3516f 2302 scm_putc ('(', port);
9882ea19 2303 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2304 scm_putc (')', port);
0f2d19dd
JB
2305 }
2306 break;
2307 }
1be6b49c 2308 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2309 { /* Could be zero-dimensional */
2310 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2311 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2312 }
2313 else
2314 n = 1;
2315 ra = SCM_ARRAY_V (ra);
2316 goto tail;
2317 default:
5c11cc9d 2318 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2319 if (n-- > 0)
9882ea19 2320 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2321 for (j += inc; n-- > 0; j += inc)
2322 {
b7f3516f 2323 scm_putc (' ', port);
9882ea19 2324 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2325 }
2326 break;
2327 case scm_tc7_string:
2328 if (n-- > 0)
322ac0c5 2329 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2330 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2331 for (j += inc; n-- > 0; j += inc)
2332 {
b7f3516f 2333 scm_putc (' ', port);
322ac0c5 2334 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2335 }
2336 else
2337 for (j += inc; n-- > 0; j += inc)
405aaef9 2338 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2339 break;
2340 case scm_tc7_byvect:
2341 if (n-- > 0)
4260a7fc 2342 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2343 for (j += inc; n-- > 0; j += inc)
2344 {
b7f3516f 2345 scm_putc (' ', port);
4260a7fc 2346 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2347 }
2348 break;
2349
2350 case scm_tc7_uvect:
5c11cc9d
GH
2351 {
2352 char str[11];
2353
2354 if (n-- > 0)
2355 {
2356 /* intprint can't handle >= 2^31. */
fee7ef83 2357 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2358 scm_puts (str, port);
2359 }
2360 for (j += inc; n-- > 0; j += inc)
2361 {
2362 scm_putc (' ', port);
fee7ef83 2363 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2364 scm_puts (str, port);
2365 }
2366 }
0f2d19dd
JB
2367 case scm_tc7_ivect:
2368 if (n-- > 0)
fee7ef83 2369 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2370 for (j += inc; n-- > 0; j += inc)
2371 {
b7f3516f 2372 scm_putc (' ', port);
fee7ef83 2373 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2374 }
2375 break;
2376
2377 case scm_tc7_svect:
2378 if (n-- > 0)
4260a7fc 2379 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2380 for (j += inc; n-- > 0; j += inc)
2381 {
b7f3516f 2382 scm_putc (' ', port);
4260a7fc 2383 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2384 }
2385 break;
2386
0f2d19dd
JB
2387 case scm_tc7_fvect:
2388 if (n-- > 0)
2389 {
bc86da5d
MD
2390 SCM z = scm_make_real (1.0);
2391 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2392 scm_print_real (z, port, pstate);
0f2d19dd
JB
2393 for (j += inc; n-- > 0; j += inc)
2394 {
b7f3516f 2395 scm_putc (' ', port);
bc86da5d
MD
2396 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2397 scm_print_real (z, port, pstate);
0f2d19dd
JB
2398 }
2399 }
2400 break;
0f2d19dd
JB
2401 case scm_tc7_dvect:
2402 if (n-- > 0)
2403 {
bc86da5d
MD
2404 SCM z = scm_make_real (1.0 / 3.0);
2405 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2406 scm_print_real (z, port, pstate);
0f2d19dd
JB
2407 for (j += inc; n-- > 0; j += inc)
2408 {
b7f3516f 2409 scm_putc (' ', port);
bc86da5d
MD
2410 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2411 scm_print_real (z, port, pstate);
0f2d19dd
JB
2412 }
2413 }
2414 break;
2415 case scm_tc7_cvect:
2416 if (n-- > 0)
2417 {
bc86da5d
MD
2418 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2419 SCM_REAL_VALUE (z) =
2420 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2421 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2422 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2423 port, pstate);
0f2d19dd
JB
2424 for (j += inc; n-- > 0; j += inc)
2425 {
b7f3516f 2426 scm_putc (' ', port);
bc86da5d
MD
2427 SCM_REAL_VALUE (z)
2428 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2429 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2430 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2431 port, pstate);
0f2d19dd
JB
2432 }
2433 }
2434 break;
0f2d19dd
JB
2435 }
2436}
2437
2438
1cc91f1b 2439
0f2d19dd 2440int
1bbd0b84 2441scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2442{
2443 SCM v = exp;
c014a02e 2444 unsigned long base = 0;
b7f3516f 2445 scm_putc ('#', port);
0f2d19dd 2446tail:
5c11cc9d 2447 switch SCM_TYP7 (v)
0f2d19dd
JB
2448 {
2449 case scm_tc7_smob:
2450 {
2451 long ndim = SCM_ARRAY_NDIM (v);
2452 base = SCM_ARRAY_BASE (v);
2453 v = SCM_ARRAY_V (v);
2454 if (SCM_ARRAYP (v))
2455
2456 {
b7f3516f 2457 scm_puts ("<enclosed-array ", port);
9882ea19 2458 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2459 scm_putc ('>', port);
0f2d19dd
JB
2460 return 1;
2461 }
2462 else
2463 {
2464 scm_intprint (ndim, 10, port);
2465 goto tail;
2466 }
2467 }
2468 case scm_tc7_bvect:
fee7ef83 2469 if (SCM_EQ_P (exp, v))
0f2d19dd 2470 { /* a uve, not an scm_array */
c014a02e 2471 register long i, j, w;
b7f3516f 2472 scm_putc ('*', port);
c014a02e 2473 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2474 {
92c2555f 2475 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2476 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2477 {
b7f3516f 2478 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2479 w >>= 1;
2480 }
2481 }
c014a02e 2482 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2483 if (j)
2484 {
c014a02e 2485 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2486 for (; j; j--)
2487 {
b7f3516f 2488 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2489 w >>= 1;
2490 }
2491 }
2492 return 1;
2493 }
2494 else
b7f3516f 2495 scm_putc ('b', port);
0f2d19dd
JB
2496 break;
2497 case scm_tc7_string:
b7f3516f 2498 scm_putc ('a', port);
0f2d19dd
JB
2499 break;
2500 case scm_tc7_byvect:
05c33d09 2501 scm_putc ('y', port);
0f2d19dd
JB
2502 break;
2503 case scm_tc7_uvect:
b7f3516f 2504 scm_putc ('u', port);
0f2d19dd
JB
2505 break;
2506 case scm_tc7_ivect:
b7f3516f 2507 scm_putc ('e', port);
0f2d19dd
JB
2508 break;
2509 case scm_tc7_svect:
05c33d09 2510 scm_putc ('h', port);
0f2d19dd 2511 break;
5c11cc9d 2512#ifdef HAVE_LONG_LONGS
0f2d19dd 2513 case scm_tc7_llvect:
5c11cc9d 2514 scm_putc ('l', port);
0f2d19dd
JB
2515 break;
2516#endif
0f2d19dd 2517 case scm_tc7_fvect:
b7f3516f 2518 scm_putc ('s', port);
0f2d19dd 2519 break;
0f2d19dd 2520 case scm_tc7_dvect:
b7f3516f 2521 scm_putc ('i', port);
0f2d19dd
JB
2522 break;
2523 case scm_tc7_cvect:
b7f3516f 2524 scm_putc ('c', port);
0f2d19dd 2525 break;
0f2d19dd 2526 }
b7f3516f 2527 scm_putc ('(', port);
9882ea19 2528 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2529 scm_putc (')', port);
0f2d19dd
JB
2530 return 1;
2531}
2532
3b3b36dd 2533SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2534 (SCM ra),
1e6808ea
MG
2535 "Return an object that would produce an array of the same type\n"
2536 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2537 "@code{make-uniform-array}.")
1bbd0b84 2538#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2539{
2540 int enclosed = 0;
2541 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2542loop:
74014c46 2543 switch SCM_TYP7 (ra)
0f2d19dd
JB
2544 {
2545 default:
276dd677 2546 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
2547 case scm_tc7_smob:
2548 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2549 if (enclosed++)
2550 return SCM_UNSPECIFIED;
2551 ra = SCM_ARRAY_V (ra);
2552 goto loop;
2553 case scm_tc7_vector:
95f5b0f5 2554 case scm_tc7_wvect:
0f2d19dd
JB
2555 return SCM_EOL;
2556 case scm_tc7_bvect:
2557 return SCM_BOOL_T;
2558 case scm_tc7_string:
7866a09b 2559 return SCM_MAKE_CHAR ('a');
0f2d19dd 2560 case scm_tc7_byvect:
7866a09b 2561 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2562 case scm_tc7_uvect:
2563 return SCM_MAKINUM (1L);
2564 case scm_tc7_ivect:
2565 return SCM_MAKINUM (-1L);
2566 case scm_tc7_svect:
38ae064c 2567 return scm_str2symbol ("s");
5c11cc9d 2568#ifdef HAVE_LONG_LONGS
0f2d19dd 2569 case scm_tc7_llvect:
38ae064c 2570 return scm_str2symbol ("l");
0f2d19dd 2571#endif
0f2d19dd 2572 case scm_tc7_fvect:
bc86da5d 2573 return scm_make_real (1.0);
0f2d19dd 2574 case scm_tc7_dvect:
bc86da5d 2575 return scm_make_real (1.0 / 3.0);
0f2d19dd 2576 case scm_tc7_cvect:
bc86da5d 2577 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2578 }
2579}
1bbd0b84 2580#undef FUNC_NAME
0f2d19dd 2581
1cc91f1b 2582
0f2d19dd 2583static SCM
e841c3e0 2584array_mark (SCM ptr)
0f2d19dd 2585{
0f2d19dd
JB
2586 return SCM_ARRAY_V (ptr);
2587}
2588
1cc91f1b 2589
1be6b49c 2590static size_t
e841c3e0 2591array_free (SCM ptr)
0f2d19dd 2592{
4c9419ac
MV
2593 scm_gc_free (SCM_ARRAY_MEM (ptr),
2594 (sizeof (scm_t_array)
2595 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2596 "array");
2597 return 0;
0f2d19dd
JB
2598}
2599
0f2d19dd
JB
2600void
2601scm_init_unif ()
0f2d19dd 2602{
e841c3e0
KN
2603 scm_tc16_array = scm_make_smob_type ("array", 0);
2604 scm_set_smob_mark (scm_tc16_array, array_mark);
2605 scm_set_smob_free (scm_tc16_array, array_free);
2606 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2607 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
0f2d19dd 2608 scm_add_feature ("array");
a0599745 2609#include "libguile/unif.x"
0f2d19dd 2610}
89e00824
ML
2611
2612/*
2613 Local Variables:
2614 c-file-style: "gnu"
2615 End:
2616*/