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