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