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