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