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