* Deprecated SCM_LENGTH_MAX.
[bpt/guile.git] / libguile / unif.c
CommitLineData
bc86da5d 1/* Copyright (C) 1995,1996,1997,1998, 2000 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
89long scm_tc16_array;
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 {
a8741caa 215 return scm_make_vector (SCM_MAKINUM (k), SCM_UNDEFINED);
0f2d19dd
JB
216 }
217 }
5b9eb8ae 218 else if (!SCM_INEXACTP (prot))
0f2d19dd 219 /* Huge non-unif vectors are NOT supported. */
5c11cc9d
GH
220 /* no special scm_vector */
221 return scm_make_vector (SCM_MAKINUM (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)
0f2d19dd 1159{
5c11cc9d 1160 switch SCM_TYP7 (v)
0f2d19dd
JB
1161 {
1162 default:
1163 scm_wta (v, (char *) SCM_ARG1, "PROGRAMMING ERROR: scm_cvref");
1164 case scm_tc7_bvect:
c209c88e 1165 if (SCM_BITVEC_REF(v,pos))
0f2d19dd
JB
1166 return SCM_BOOL_T;
1167 else
1168 return SCM_BOOL_F;
1169 case scm_tc7_string:
322ac0c5 1170 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1171 case scm_tc7_byvect:
405aaef9 1172 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1173 case scm_tc7_uvect:
fee7ef83 1174 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1175 case scm_tc7_ivect:
fee7ef83 1176 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1177 case scm_tc7_svect:
4260a7fc 1178 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1179#ifdef HAVE_LONG_LONGS
0f2d19dd 1180 case scm_tc7_llvect:
4260a7fc 1181 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1182#endif
0f2d19dd 1183 case scm_tc7_fvect:
fee7ef83 1184 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1185 {
4260a7fc 1186 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1187 return last;
1188 }
4260a7fc 1189 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1190 case scm_tc7_dvect:
fee7ef83 1191 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1192 {
4260a7fc 1193 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1194 return last;
1195 }
4260a7fc 1196 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1197 case scm_tc7_cvect:
bc86da5d 1198 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1199 {
4260a7fc
DH
1200 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1201 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1202 return last;
1203 }
4260a7fc
DH
1204 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1205 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1206 case scm_tc7_vector:
95f5b0f5 1207 case scm_tc7_wvect:
0f2d19dd
JB
1208 return SCM_VELTS (v)[pos];
1209 case scm_tc7_smob:
1210 { /* enclosed scm_array */
1211 int k = SCM_ARRAY_NDIM (v);
1212 SCM res = scm_make_ra (k);
1213 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1214 SCM_ARRAY_BASE (res) = pos;
1215 while (k--)
1216 {
1217 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1218 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1219 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1220 }
1221 return res;
1222 }
1223 }
1224}
1225
1bbd0b84
GB
1226SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1227
1cc91f1b 1228
0aa0871f
GH
1229/* Note that args may be a list or an immediate object, depending which
1230 PROC is used (and it's called from C too). */
3b3b36dd 1231SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1232 (SCM v, SCM obj, SCM args),
ec57ce2e 1233 "@deffnx primitive uniform-array-set1! v obj args\n"
b380b885
MD
1234 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1235 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1236#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1237{
f3667f52 1238 long pos = 0;
0f2d19dd
JB
1239 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1240 if (SCM_ARRAYP (v))
0f2d19dd 1241 {
1bbd0b84 1242 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1243 v = SCM_ARRAY_V (v);
1244 }
1245 else
1246 {
74014c46 1247 unsigned long int length;
0f2d19dd 1248 if (SCM_NIMP (args))
0f2d19dd 1249 {
0aa0871f 1250 SCM_ASSERT (SCM_CONSP(args) && SCM_INUMP (SCM_CAR (args)), args,
1bbd0b84 1251 SCM_ARG3, FUNC_NAME);
0f2d19dd 1252 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1253 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1254 }
1255 else
1256 {
3b3b36dd 1257 SCM_VALIDATE_INUM_COPY (3,args,pos);
0f2d19dd 1258 }
74014c46
DH
1259 length = SCM_INUM (scm_uniform_vector_length (v));
1260 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd
JB
1261 }
1262 switch (SCM_TYP7 (v))
1263 {
35de7ebe 1264 default: badarg1:
1bbd0b84 1265 SCM_WTA (1,v);
35de7ebe 1266 abort ();
c209c88e
GB
1267 outrng:
1268 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1269 wna:
1270 scm_wrong_num_args (SCM_FUNC_NAME);
0f2d19dd
JB
1271 case scm_tc7_smob: /* enclosed */
1272 goto badarg1;
1273 case scm_tc7_bvect:
4260a7fc 1274 if (SCM_FALSEP (obj))
c209c88e 1275 SCM_BITVEC_CLR(v,pos);
9a09deb1 1276 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c209c88e 1277 SCM_BITVEC_SET(v,pos);
0f2d19dd 1278 else
1bbd0b84 1279 badobj:SCM_WTA (2,obj);
0f2d19dd
JB
1280 break;
1281 case scm_tc7_string:
7866a09b 1282 SCM_ASRTGO (SCM_CHARP (obj), badobj);
322ac0c5 1283 SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1284 break;
1285 case scm_tc7_byvect:
7866a09b
GB
1286 if (SCM_CHARP (obj))
1287 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1288 SCM_ASRTGO (SCM_INUMP (obj), badobj);
405aaef9 1289 ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1290 break;
1bbd0b84 1291 case scm_tc7_uvect:
f1267706 1292 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2ulong(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1293 break;
1bbd0b84 1294 case scm_tc7_ivect:
f1267706 1295 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2long(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1296 break;
0f2d19dd 1297 case scm_tc7_svect:
0aa0871f 1298 SCM_ASRTGO (SCM_INUMP (obj), badobj);
4260a7fc 1299 ((short *) SCM_CELL_WORD_1 (v))[pos] = SCM_INUM (obj);
0f2d19dd 1300 break;
5c11cc9d 1301#ifdef HAVE_LONG_LONGS
0f2d19dd 1302 case scm_tc7_llvect:
4260a7fc 1303 ((long_long *) SCM_CELL_WORD_1 (v))[pos] = scm_num2long_long (obj, (char *)SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1304 break;
1305#endif
1306
1307
0f2d19dd 1308 case scm_tc7_fvect:
4260a7fc 1309 ((float *) SCM_CELL_WORD_1 (v))[pos] = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1310 break;
0f2d19dd 1311 case scm_tc7_dvect:
4260a7fc 1312 ((double *) SCM_CELL_WORD_1 (v))[pos] = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1313 break;
1314 case scm_tc7_cvect:
eb42e2f0
DH
1315 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1316 if (SCM_REALP (obj)) {
1317 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_REAL_VALUE (obj);
1318 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = 0.0;
1319 } else {
1320 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1321 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
1322 }
0f2d19dd 1323 break;
0f2d19dd 1324 case scm_tc7_vector:
95f5b0f5 1325 case scm_tc7_wvect:
0f2d19dd
JB
1326 SCM_VELTS (v)[pos] = obj;
1327 break;
1328 }
1329 return SCM_UNSPECIFIED;
1330}
1bbd0b84 1331#undef FUNC_NAME
0f2d19dd 1332
1d7bdb25
GH
1333/* attempts to unroll an array into a one-dimensional array.
1334 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1335 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1336 wouldn't have contiguous elements. */
3b3b36dd 1337SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1338 (SCM ra, SCM strict),
b380b885
MD
1339 "@deffnx primitive array-contents array strict\n"
1340 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1341 "without changing their order (last subscript changing fastest), then\n"
1342 "@code{array-contents} returns that shared array, otherwise it returns\n"
1343 "@code{#f}. All arrays made by @var{make-array} and\n"
1344 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1345 "@var{make-shared-array} may not be.\n\n"
1346 "If the optional argument @var{strict} is provided, a shared array will\n"
1347 "be returned only if its elements are stored internally contiguous in\n"
1348 "memory.")
1bbd0b84 1349#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1350{
1351 SCM sra;
1352 if (SCM_IMP (ra))
f3667f52 1353 return SCM_BOOL_F;
5c11cc9d 1354 switch SCM_TYP7 (ra)
0f2d19dd
JB
1355 {
1356 default:
1357 return SCM_BOOL_F;
1358 case scm_tc7_vector:
95f5b0f5 1359 case scm_tc7_wvect:
0f2d19dd
JB
1360 case scm_tc7_string:
1361 case scm_tc7_bvect:
1362 case scm_tc7_byvect:
1363 case scm_tc7_uvect:
1364 case scm_tc7_ivect:
1365 case scm_tc7_fvect:
1366 case scm_tc7_dvect:
1367 case scm_tc7_cvect:
1368 case scm_tc7_svect:
5c11cc9d 1369#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1370 case scm_tc7_llvect:
1371#endif
1372 return ra;
1373 case scm_tc7_smob:
1374 {
1375 scm_sizet k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1376 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1377 return SCM_BOOL_F;
1378 for (k = 0; k < ndim; k++)
1379 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1380 if (!SCM_UNBNDP (strict))
1381 {
0f2d19dd
JB
1382 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1383 return SCM_BOOL_F;
1384 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1385 {
74014c46 1386 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
0f2d19dd
JB
1387 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1388 len % SCM_LONG_BIT)
1389 return SCM_BOOL_F;
1390 }
1391 }
74014c46
DH
1392
1393 {
1394 SCM v = SCM_ARRAY_V (ra);
1395 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
1396 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1397 return v;
1398 }
1399
0f2d19dd
JB
1400 sra = scm_make_ra (1);
1401 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1402 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1403 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1404 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1405 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1406 return sra;
1407 }
1408 }
1409}
1bbd0b84 1410#undef FUNC_NAME
0f2d19dd 1411
1cc91f1b 1412
0f2d19dd 1413SCM
6e8d25a6 1414scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1415{
1416 SCM ret;
1417 long inc = 1;
1418 scm_sizet k, len = 1;
1419 for (k = SCM_ARRAY_NDIM (ra); k--;)
1420 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1421 k = SCM_ARRAY_NDIM (ra);
1422 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1423 {
74014c46 1424 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1425 return ra;
74014c46 1426 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
0f2d19dd
JB
1427 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1428 0 == len % SCM_LONG_BIT))
1429 return ra;
1430 }
1431 ret = scm_make_ra (k);
1432 SCM_ARRAY_BASE (ret) = 0;
1433 while (k--)
1434 {
1435 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1436 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1437 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1438 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1439 }
1440 SCM_ARRAY_V (ret) = scm_make_uve ((inc - 1), scm_array_prototype (ra));
1441 if (copy)
1442 scm_array_copy_x (ra, ret);
1443 return ret;
1444}
1445
1446
1447
3b3b36dd 1448SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1449 (SCM ra, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1450 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1451 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1452 "binary objects from @var{port-or-fdes}.\n"
1453 "If an end of file is encountered during\n"
1454 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1455 "(starting at the beginning) and the remainder of the array is\n"
1456 "unchanged.\n\n"
1457 "The optional arguments @var{start} and @var{end} allow\n"
1458 "a specified region of a vector (or linearized array) to be read,\n"
1459 "leaving the remainder of the vector unchanged.\n\n"
1460 "@code{uniform-array-read!} returns the number of objects read.\n"
1461 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1462 "returned by @code{(current-input-port)}.")
1bbd0b84 1463#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1464{
35de7ebe 1465 SCM cra = SCM_UNDEFINED, v = ra;
3d8d56df 1466 long sz, vlen, ans;
1146b6cd
GH
1467 long cstart = 0;
1468 long cend;
1469 long offset = 0;
405aaef9 1470 char *base;
35de7ebe 1471
0f2d19dd 1472 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1473 if (SCM_UNBNDP (port_or_fd))
1474 port_or_fd = scm_cur_inp;
1475 else
1476 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1477 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1478 port_or_fd, SCM_ARG2, FUNC_NAME);
74014c46 1479 vlen = SCM_INUM (scm_uniform_vector_length (v));
35de7ebe 1480
0f2d19dd 1481loop:
35de7ebe 1482 switch SCM_TYP7 (v)
0f2d19dd
JB
1483 {
1484 default:
5d2d2ffc 1485 badarg1:SCM_WTA (SCM_ARG1,v);
0f2d19dd
JB
1486 case scm_tc7_smob:
1487 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1488 cra = scm_ra2contig (ra, 0);
1146b6cd 1489 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1490 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1491 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1492 v = SCM_ARRAY_V (cra);
1493 goto loop;
1494 case scm_tc7_string:
74014c46 1495 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1496 sz = sizeof (char);
1497 break;
1498 case scm_tc7_bvect:
74014c46 1499 base = (char *) SCM_BITVECTOR_BASE (v);
3d8d56df 1500 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1501 cstart /= SCM_LONG_BIT;
74014c46
DH
1502 sz = sizeof (long);
1503 break;
1504 case scm_tc7_byvect:
1505 base = (char *) SCM_UVECTOR_BASE (v);
1506 sz = sizeof (char);
1507 break;
0f2d19dd
JB
1508 case scm_tc7_uvect:
1509 case scm_tc7_ivect:
74014c46 1510 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1511 sz = sizeof (long);
1512 break;
1513 case scm_tc7_svect:
74014c46 1514 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1515 sz = sizeof (short);
1516 break;
5c11cc9d 1517#ifdef HAVE_LONG_LONGS
0f2d19dd 1518 case scm_tc7_llvect:
74014c46 1519 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1520 sz = sizeof (long_long);
1521 break;
1522#endif
0f2d19dd 1523 case scm_tc7_fvect:
74014c46 1524 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1525 sz = sizeof (float);
1526 break;
0f2d19dd 1527 case scm_tc7_dvect:
74014c46 1528 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1529 sz = sizeof (double);
1530 break;
1531 case scm_tc7_cvect:
74014c46 1532 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1533 sz = 2 * sizeof (double);
1534 break;
0f2d19dd 1535 }
405aaef9 1536
1146b6cd
GH
1537 cend = vlen;
1538 if (!SCM_UNBNDP (start))
3d8d56df 1539 {
1146b6cd 1540 offset =
4638e087 1541 SCM_NUM2LONG (3, start);
35de7ebe 1542
1146b6cd 1543 if (offset < 0 || offset >= cend)
1bbd0b84 1544 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1545
1546 if (!SCM_UNBNDP (end))
1547 {
1548 long tend =
4638e087 1549 SCM_NUM2LONG (4, end);
3d8d56df 1550
1146b6cd 1551 if (tend <= offset || tend > cend)
1bbd0b84 1552 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1553 cend = tend;
1554 }
0f2d19dd 1555 }
35de7ebe 1556
3d8d56df
GH
1557 if (SCM_NIMP (port_or_fd))
1558 {
6c951427
GH
1559 scm_port *pt = SCM_PTAB_ENTRY (port_or_fd);
1560 int remaining = (cend - offset) * sz;
405aaef9 1561 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1562
1563 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1564 scm_flush (port_or_fd);
6c951427
GH
1565
1566 ans = cend - offset;
1567 while (remaining > 0)
3d8d56df 1568 {
6c951427
GH
1569 if (pt->read_pos < pt->read_end)
1570 {
1571 int to_copy = min (pt->read_end - pt->read_pos,
1572 remaining);
1573
1574 memcpy (dest, pt->read_pos, to_copy);
1575 pt->read_pos += to_copy;
1576 remaining -= to_copy;
1577 dest += to_copy;
1578 }
1579 else
1580 {
affc96b5 1581 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1582 {
1583 if (remaining % sz != 0)
1584 {
5d2d2ffc 1585 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1586 }
1587 ans -= remaining / sz;
1588 break;
1589 }
6c951427 1590 }
3d8d56df 1591 }
6c951427
GH
1592
1593 if (pt->rw_random)
1594 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1595 }
1596 else /* file descriptor. */
1597 {
1598 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1599 base + (cstart + offset) * sz,
1146b6cd 1600 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1601 if (ans == -1)
1bbd0b84 1602 SCM_SYSERROR;
3d8d56df 1603 }
0f2d19dd
JB
1604 if (SCM_TYP7 (v) == scm_tc7_bvect)
1605 ans *= SCM_LONG_BIT;
35de7ebe 1606
fee7ef83 1607 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1608 scm_array_copy_x (cra, ra);
35de7ebe 1609
0f2d19dd
JB
1610 return SCM_MAKINUM (ans);
1611}
1bbd0b84 1612#undef FUNC_NAME
0f2d19dd 1613
3b3b36dd 1614SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1615 (SCM v, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1616 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1617 "Writes all elements of @var{ura} as binary objects to\n"
1618 "@var{port-or-fdes}.\n\n"
1619 "The optional arguments @var{start}\n"
1620 "and @var{end} allow\n"
1621 "a specified region of a vector (or linearized array) to be written.\n\n"
1622 "The number of objects actually written is returned. \n"
1623 "@var{port-or-fdes} may be\n"
1624 "omitted, in which case it defaults to the value returned by\n"
1625 "@code{(current-output-port)}.")
1bbd0b84 1626#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1627{
3d8d56df 1628 long sz, vlen, ans;
1146b6cd
GH
1629 long offset = 0;
1630 long cstart = 0;
1631 long cend;
405aaef9 1632 char *base;
3d8d56df 1633
78446828
MV
1634 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1635
0f2d19dd 1636 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1637 if (SCM_UNBNDP (port_or_fd))
1638 port_or_fd = scm_cur_outp;
1639 else
1640 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1641 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1642 port_or_fd, SCM_ARG2, FUNC_NAME);
74014c46 1643 vlen = SCM_INUM (scm_uniform_vector_length (v));
3d8d56df 1644
0f2d19dd 1645loop:
3d8d56df 1646 switch SCM_TYP7 (v)
0f2d19dd
JB
1647 {
1648 default:
4638e087 1649 badarg1:SCM_WTA (1, v);
0f2d19dd
JB
1650 case scm_tc7_smob:
1651 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1652 v = scm_ra2contig (v, 1);
1146b6cd 1653 cstart = SCM_ARRAY_BASE (v);
3d8d56df
GH
1654 vlen = SCM_ARRAY_DIMS (v)->inc
1655 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1);
0f2d19dd
JB
1656 v = SCM_ARRAY_V (v);
1657 goto loop;
0f2d19dd 1658 case scm_tc7_string:
74014c46 1659 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1660 sz = sizeof (char);
1661 break;
1662 case scm_tc7_bvect:
74014c46 1663 base = (char *) SCM_BITVECTOR_BASE (v);
3d8d56df 1664 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1665 cstart /= SCM_LONG_BIT;
74014c46
DH
1666 sz = sizeof (long);
1667 break;
1668 case scm_tc7_byvect:
1669 base = (char *) SCM_UVECTOR_BASE (v);
1670 sz = sizeof (char);
1671 break;
0f2d19dd
JB
1672 case scm_tc7_uvect:
1673 case scm_tc7_ivect:
74014c46 1674 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1675 sz = sizeof (long);
1676 break;
1677 case scm_tc7_svect:
74014c46 1678 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1679 sz = sizeof (short);
1680 break;
5c11cc9d 1681#ifdef HAVE_LONG_LONGS
0f2d19dd 1682 case scm_tc7_llvect:
74014c46 1683 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1684 sz = sizeof (long_long);
1685 break;
1686#endif
0f2d19dd 1687 case scm_tc7_fvect:
74014c46 1688 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1689 sz = sizeof (float);
1690 break;
0f2d19dd 1691 case scm_tc7_dvect:
74014c46 1692 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1693 sz = sizeof (double);
1694 break;
1695 case scm_tc7_cvect:
74014c46 1696 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1697 sz = 2 * sizeof (double);
1698 break;
0f2d19dd 1699 }
3d8d56df 1700
1146b6cd
GH
1701 cend = vlen;
1702 if (!SCM_UNBNDP (start))
3d8d56df 1703 {
1146b6cd 1704 offset =
4638e087 1705 SCM_NUM2LONG (3, start);
3d8d56df 1706
1146b6cd 1707 if (offset < 0 || offset >= cend)
1bbd0b84 1708 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1709
1710 if (!SCM_UNBNDP (end))
1711 {
1712 long tend =
4638e087 1713 SCM_NUM2LONG (4, end);
3d8d56df 1714
1146b6cd 1715 if (tend <= offset || tend > cend)
1bbd0b84 1716 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1717 cend = tend;
1718 }
3d8d56df
GH
1719 }
1720
1721 if (SCM_NIMP (port_or_fd))
1722 {
405aaef9 1723 char *source = base + (cstart + offset) * sz;
6c951427
GH
1724
1725 ans = cend - offset;
265e6a4d 1726 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1727 }
1728 else /* file descriptor. */
1729 {
1730 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
405aaef9 1731 base + (cstart + offset) * sz,
1146b6cd 1732 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1733 if (ans == -1)
1bbd0b84 1734 SCM_SYSERROR;
3d8d56df 1735 }
0f2d19dd
JB
1736 if (SCM_TYP7 (v) == scm_tc7_bvect)
1737 ans *= SCM_LONG_BIT;
3d8d56df 1738
0f2d19dd
JB
1739 return SCM_MAKINUM (ans);
1740}
1bbd0b84 1741#undef FUNC_NAME
0f2d19dd
JB
1742
1743
1744static char cnt_tab[16] =
1745{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1746
3b3b36dd 1747SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
44e47754
DH
1748 (SCM b, SCM bitvector),
1749 "Returns the number of occurrences of the boolean B in BITVECTOR.")
1bbd0b84 1750#define FUNC_NAME s_scm_bit_count
0f2d19dd 1751{
44e47754 1752 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1753 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1754 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1755 return SCM_INUM0;
1756 } else {
1757 unsigned long int count = 0;
74014c46 1758 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
44e47754
DH
1759 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1760 if (SCM_FALSEP (b)) {
1761 w = ~w;
1762 };
74014c46 1763 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1764 while (1) {
1765 while (w) {
1766 count += cnt_tab[w & 0x0f];
1767 w >>= 4;
1768 }
1769 if (i == 0) {
1770 return SCM_MAKINUM (count);
1771 } else {
1772 --i;
1773 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1774 if (SCM_FALSEP (b)) {
1775 w = ~w;
0f2d19dd 1776 }
44e47754 1777 }
0f2d19dd 1778 }
44e47754 1779 }
0f2d19dd 1780}
1bbd0b84 1781#undef FUNC_NAME
0f2d19dd
JB
1782
1783
3b3b36dd 1784SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1785 (SCM item, SCM v, SCM k),
b380b885
MD
1786 "Returns the minimum index of an occurrence of @var{bool} in @var{bv}\n"
1787 "which is at least @var{k}. If no @var{bool} occurs within the specified\n"
1788 "range @code{#f} is returned.")
1bbd0b84 1789#define FUNC_NAME s_scm_bit_position
0f2d19dd 1790{
1bbd0b84 1791 long i, lenw, xbits, pos;
0f2d19dd 1792 register unsigned long w;
74014c46
DH
1793
1794 SCM_VALIDATE_BOOL (1, item);
1795 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
3b3b36dd 1796 SCM_VALIDATE_INUM_COPY (3,k,pos);
74014c46
DH
1797 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1798
1799 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1800 return SCM_BOOL_F;
74014c46
DH
1801
1802 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1803 i = pos / SCM_LONG_BIT;
1804 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1805 if (SCM_FALSEP (item))
1806 w = ~w;
1807 xbits = (pos % SCM_LONG_BIT);
1808 pos -= xbits;
1809 w = ((w >> xbits) << xbits);
1810 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
1811 while (!0)
1812 {
1813 if (w && (i == lenw))
1814 w = ((w << xbits) >> xbits);
1815 if (w)
1816 while (w)
1817 switch (w & 0x0f)
1818 {
1819 default:
1820 return SCM_MAKINUM (pos);
1821 case 2:
1822 case 6:
1823 case 10:
1824 case 14:
1825 return SCM_MAKINUM (pos + 1);
1826 case 4:
1827 case 12:
1828 return SCM_MAKINUM (pos + 2);
1829 case 8:
1830 return SCM_MAKINUM (pos + 3);
1831 case 0:
1832 pos += 4;
1833 w >>= 4;
1834 }
1835 if (++i > lenw)
1836 break;
1837 pos += SCM_LONG_BIT;
f1267706 1838 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1839 if (SCM_FALSEP (item))
1840 w = ~w;
0f2d19dd 1841 }
74014c46 1842 return SCM_BOOL_F;
0f2d19dd 1843}
1bbd0b84 1844#undef FUNC_NAME
0f2d19dd
JB
1845
1846
3b3b36dd 1847SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
1bbd0b84 1848 (SCM v, SCM kv, SCM obj),
b380b885
MD
1849 "If uve is a bit-vector @var{bv} and uve must be of the same length. If\n"
1850 "@var{bool} is @code{#t}, uve is OR'ed into @var{bv}; If @var{bool} is @code{#f}, the\n"
1851 "inversion of uve is AND'ed into @var{bv}.\n\n"
1852 "If uve is a unsigned integer vector all the elements of uve must be\n"
1853 "between 0 and the @code{LENGTH} of @var{bv}. The bits of @var{bv}\n"
1854 "corresponding to the indexes in uve are set to @var{bool}.\n\n"
1855 "The return value is unspecified.")
1bbd0b84 1856#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd
JB
1857{
1858 register long i, k, vlen;
74014c46 1859 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1860 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1861 switch SCM_TYP7 (kv)
0f2d19dd
JB
1862 {
1863 default:
1bbd0b84 1864 badarg2:SCM_WTA (2,kv);
0f2d19dd 1865 case scm_tc7_uvect:
74014c46
DH
1866 vlen = SCM_BITVECTOR_LENGTH (v);
1867 if (SCM_FALSEP (obj))
1868 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1869 {
1870 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1871 if (k >= vlen)
1872 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1873 SCM_BITVEC_CLR(v,k);
1874 }
1875 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1876 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1877 {
1878 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1879 if (k >= vlen)
1880 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1881 SCM_BITVEC_SET(v,k);
1882 }
1883 else
1884 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1885 break;
1886 case scm_tc7_bvect:
74014c46 1887 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1888 if (SCM_FALSEP (obj))
74014c46 1889 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1890 SCM_UNPACK (SCM_VELTS (v)[k]) &= ~ SCM_UNPACK(SCM_VELTS (kv)[k]);
9a09deb1 1891 else if (SCM_EQ_P (obj, SCM_BOOL_T))
74014c46 1892 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1893 SCM_UNPACK (SCM_VELTS (v)[k]) |= SCM_UNPACK (SCM_VELTS (kv)[k]);
0f2d19dd
JB
1894 else
1895 goto badarg3;
1896 break;
1897 }
1898 return SCM_UNSPECIFIED;
1899}
1bbd0b84 1900#undef FUNC_NAME
0f2d19dd
JB
1901
1902
3b3b36dd 1903SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1904 (SCM v, SCM kv, SCM obj),
b380b885
MD
1905 "Returns\n"
1906 "@example\n"
1907 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1908 "@end example\n"
1909 "@var{bv} is not modified.")
1bbd0b84 1910#define FUNC_NAME s_scm_bit_count_star
0f2d19dd
JB
1911{
1912 register long i, vlen, count = 0;
1913 register unsigned long k;
41b0806d 1914 int fObj = 0;
c209c88e 1915
74014c46 1916 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1917 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1918 switch SCM_TYP7 (kv)
0f2d19dd
JB
1919 {
1920 default:
c209c88e
GB
1921 badarg2:
1922 SCM_WTA (2,kv);
0f2d19dd 1923 case scm_tc7_uvect:
74014c46
DH
1924 vlen = SCM_BITVECTOR_LENGTH (v);
1925 if (SCM_FALSEP (obj))
1926 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1927 {
1928 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1929 if (k >= vlen)
1930 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1931 if (!SCM_BITVEC_REF(v,k))
1932 count++;
1933 }
1934 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1935 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1936 {
1937 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1938 if (k >= vlen)
1939 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1940 if (SCM_BITVEC_REF (v,k))
1941 count++;
1942 }
1943 else
1944 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1945 break;
1946 case scm_tc7_bvect:
74014c46
DH
1947 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1948 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1949 return SCM_INUM0;
4260a7fc 1950 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1951 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
74014c46 1952 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
f1267706 1953 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
74014c46 1954 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1955 while (1)
0f2d19dd
JB
1956 {
1957 for (; k; k >>= 4)
1958 count += cnt_tab[k & 0x0f];
1959 if (0 == i--)
1960 return SCM_MAKINUM (count);
c209c88e
GB
1961
1962 /* urg. repetitive (see above.) */
f1267706 1963 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1964 }
1965 }
1966 return SCM_MAKINUM (count);
1967}
1bbd0b84 1968#undef FUNC_NAME
0f2d19dd
JB
1969
1970
3b3b36dd 1971SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1972 (SCM v),
b380b885 1973 "Modifies @var{bv} by replacing each element with its negation.")
1bbd0b84 1974#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 1975{
74014c46
DH
1976 long int k;
1977
1978 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
1979
1980 k = SCM_BITVECTOR_LENGTH (v);
1981 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
1982 SCM_UNPACK (SCM_VELTS (v)[k]) = ~SCM_UNPACK (SCM_VELTS (v)[k]);
1983
0f2d19dd
JB
1984 return SCM_UNSPECIFIED;
1985}
1bbd0b84 1986#undef FUNC_NAME
0f2d19dd
JB
1987
1988
0f2d19dd 1989SCM
1bbd0b84 1990scm_istr2bve (char *str, long len)
0f2d19dd
JB
1991{
1992 SCM v = scm_make_uve (len, SCM_BOOL_T);
1993 long *data = (long *) SCM_VELTS (v);
1994 register unsigned long mask;
1995 register long k;
1996 register long j;
1997 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
1998 {
1999 data[k] = 0L;
2000 j = len - k * SCM_LONG_BIT;
2001 if (j > SCM_LONG_BIT)
2002 j = SCM_LONG_BIT;
2003 for (mask = 1L; j--; mask <<= 1)
2004 switch (*str++)
2005 {
2006 case '0':
2007 break;
2008 case '1':
2009 data[k] |= mask;
2010 break;
2011 default:
2012 return SCM_BOOL_F;
2013 }
2014 }
2015 return v;
2016}
2017
2018
1cc91f1b 2019
0f2d19dd 2020static SCM
1bbd0b84 2021ra2l (SCM ra,scm_sizet base,scm_sizet k)
0f2d19dd
JB
2022{
2023 register SCM res = SCM_EOL;
2024 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2025 register scm_sizet i;
2026 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2027 return SCM_EOL;
2028 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2029 if (k < SCM_ARRAY_NDIM (ra) - 1)
2030 {
2031 do
2032 {
2033 i -= inc;
2034 res = scm_cons (ra2l (ra, i, k + 1), res);
2035 }
2036 while (i != base);
2037 }
2038 else
2039 do
2040 {
2041 i -= inc;
2042 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2043 }
2044 while (i != base);
2045 return res;
2046}
2047
2048
3b3b36dd 2049SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2050 (SCM v),
b380b885 2051 "Returns a list consisting of all the elements, in order, of @var{array}.")
1bbd0b84 2052#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2053{
2054 SCM res = SCM_EOL;
2055 register long k;
2056 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2057 switch SCM_TYP7 (v)
0f2d19dd
JB
2058 {
2059 default:
1bbd0b84 2060 badarg1:SCM_WTA (1,v);
0f2d19dd
JB
2061 case scm_tc7_smob:
2062 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2063 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2064 case scm_tc7_vector:
95f5b0f5 2065 case scm_tc7_wvect:
0f2d19dd
JB
2066 return scm_vector_to_list (v);
2067 case scm_tc7_string:
2068 return scm_string_to_list (v);
2069 case scm_tc7_bvect:
2070 {
2071 long *data = (long *) SCM_VELTS (v);
2072 register unsigned long mask;
74014c46 2073 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
cdbadcac 2074 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
156dcb09 2075 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
74014c46 2076 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
156dcb09 2077 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2078 return res;
2079 }
0f2d19dd
JB
2080 case scm_tc7_uvect: {
2081 long *data = (long *)SCM_VELTS(v);
74014c46 2082 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
0f2d19dd
JB
2083 res = scm_cons(scm_ulong2num(data[k]), res);
2084 return res;
2085 }
2086 case scm_tc7_ivect: {
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_long2num(data[k]), res);
2090 return res;
2091 }
0f2d19dd
JB
2092 case scm_tc7_svect: {
2093 short *data;
2094 data = (short *)SCM_VELTS(v);
74014c46 2095 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
0f2d19dd
JB
2096 res = scm_cons(SCM_MAKINUM (data[k]), res);
2097 return res;
2098 }
5c11cc9d 2099#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2100 case scm_tc7_llvect: {
2101 long_long *data;
2102 data = (long_long *)SCM_VELTS(v);
74014c46 2103 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
0f2d19dd
JB
2104 res = scm_cons(scm_long_long2num(data[k]), res);
2105 return res;
2106 }
2107#endif
2108
2109
0f2d19dd
JB
2110 case scm_tc7_fvect:
2111 {
2112 float *data = (float *) SCM_VELTS (v);
74014c46 2113 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2114 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2115 return res;
2116 }
0f2d19dd
JB
2117 case scm_tc7_dvect:
2118 {
2119 double *data = (double *) SCM_VELTS (v);
74014c46 2120 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2121 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2122 return res;
2123 }
2124 case scm_tc7_cvect:
2125 {
2126 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2127 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2128 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2129 return res;
2130 }
0f2d19dd
JB
2131 }
2132}
1bbd0b84 2133#undef FUNC_NAME
0f2d19dd
JB
2134
2135
20a54673 2136static char s_bad_ralst[] = "Bad scm_array contents list";
1cc91f1b 2137
1bbd0b84 2138static int l2ra(SCM lst, SCM ra, scm_sizet base, scm_sizet k);
1cc91f1b 2139
3b3b36dd 2140SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2141 (SCM ndim, SCM prot, SCM lst),
b380b885
MD
2142 "@deffnx procedure list->uniform-vector prot lst\n"
2143 "Returns a uniform array of the type indicated by prototype @var{prot}\n"
2144 "with elements the same as those of @var{lst}. Elements must be of the\n"
2145 "appropriate type, no coercions are done.")
1bbd0b84 2146#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2147{
2148 SCM shp = SCM_EOL;
2149 SCM row = lst;
2150 SCM ra;
2151 scm_sizet k;
2152 long n;
3b3b36dd 2153 SCM_VALIDATE_INUM_COPY (1,ndim,k);
0f2d19dd
JB
2154 while (k--)
2155 {
2156 n = scm_ilength (row);
1bbd0b84 2157 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2158 shp = scm_cons (SCM_MAKINUM (n), shp);
2159 if (SCM_NIMP (row))
2160 row = SCM_CAR (row);
2161 }
d12feca3
GH
2162 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2163 SCM_UNDEFINED);
0f2d19dd
JB
2164 if (SCM_NULLP (shp))
2165
2166 {
2167 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2168 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2169 return ra;
2170 }
2171 if (!SCM_ARRAYP (ra))
2172 {
74014c46
DH
2173 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
2174 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2175 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2176 return ra;
2177 }
2178 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2179 return ra;
2180 else
1bbd0b84 2181 badlst:scm_wta (lst, s_bad_ralst, FUNC_NAME);
0f2d19dd
JB
2182 return SCM_BOOL_F;
2183}
1bbd0b84 2184#undef FUNC_NAME
0f2d19dd 2185
0f2d19dd 2186static int
1bbd0b84 2187l2ra (SCM lst, SCM ra, scm_sizet base, scm_sizet k)
0f2d19dd
JB
2188{
2189 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2190 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
2191 int ok = 1;
2192 if (n <= 0)
4260a7fc 2193 return (SCM_NULLP (lst));
0f2d19dd
JB
2194 if (k < SCM_ARRAY_NDIM (ra) - 1)
2195 {
2196 while (n--)
2197 {
2198 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2199 return 0;
2200 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2201 base += inc;
2202 lst = SCM_CDR (lst);
2203 }
2204 if (SCM_NNULLP (lst))
2205 return 0;
2206 }
2207 else
2208 {
2209 while (n--)
2210 {
2211 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2212 return 0;
baa702c8 2213 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2214 base += inc;
2215 lst = SCM_CDR (lst);
2216 }
2217 if (SCM_NNULLP (lst))
fee7ef83 2218 return 0;
0f2d19dd
JB
2219 }
2220 return ok;
2221}
2222
1cc91f1b 2223
0f2d19dd 2224static void
1bbd0b84 2225rapr1 (SCM ra,scm_sizet j,scm_sizet k,SCM port,scm_print_state *pstate)
0f2d19dd
JB
2226{
2227 long inc = 1;
74014c46 2228 long n = SCM_INUM (scm_uniform_vector_length (ra));
0f2d19dd
JB
2229 int enclosed = 0;
2230tail:
5c11cc9d 2231 switch SCM_TYP7 (ra)
0f2d19dd
JB
2232 {
2233 case scm_tc7_smob:
2234 if (enclosed++)
2235 {
2236 SCM_ARRAY_BASE (ra) = j;
2237 if (n-- > 0)
9882ea19 2238 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2239 for (j += inc; n-- > 0; j += inc)
2240 {
b7f3516f 2241 scm_putc (' ', port);
0f2d19dd 2242 SCM_ARRAY_BASE (ra) = j;
9882ea19 2243 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2244 }
2245 break;
2246 }
2247 if (k + 1 < SCM_ARRAY_NDIM (ra))
2248 {
2249 long i;
2250 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2251 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2252 {
b7f3516f 2253 scm_putc ('(', port);
9882ea19 2254 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2255 scm_puts (") ", port);
0f2d19dd
JB
2256 j += inc;
2257 }
2258 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2259 { /* could be zero size. */
b7f3516f 2260 scm_putc ('(', port);
9882ea19 2261 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2262 scm_putc (')', port);
0f2d19dd
JB
2263 }
2264 break;
2265 }
2266 if SCM_ARRAY_NDIM
2267 (ra)
2268 { /* Could be zero-dimensional */
2269 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2270 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2271 }
2272 else
2273 n = 1;
2274 ra = SCM_ARRAY_V (ra);
2275 goto tail;
2276 default:
5c11cc9d 2277 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2278 if (n-- > 0)
9882ea19 2279 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2280 for (j += inc; n-- > 0; j += inc)
2281 {
b7f3516f 2282 scm_putc (' ', port);
9882ea19 2283 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2284 }
2285 break;
2286 case scm_tc7_string:
2287 if (n-- > 0)
322ac0c5 2288 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2289 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2290 for (j += inc; n-- > 0; j += inc)
2291 {
b7f3516f 2292 scm_putc (' ', port);
322ac0c5 2293 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2294 }
2295 else
2296 for (j += inc; n-- > 0; j += inc)
405aaef9 2297 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2298 break;
2299 case scm_tc7_byvect:
2300 if (n-- > 0)
4260a7fc 2301 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2302 for (j += inc; n-- > 0; j += inc)
2303 {
b7f3516f 2304 scm_putc (' ', port);
4260a7fc 2305 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2306 }
2307 break;
2308
2309 case scm_tc7_uvect:
5c11cc9d
GH
2310 {
2311 char str[11];
2312
2313 if (n-- > 0)
2314 {
2315 /* intprint can't handle >= 2^31. */
fee7ef83 2316 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2317 scm_puts (str, port);
2318 }
2319 for (j += inc; n-- > 0; j += inc)
2320 {
2321 scm_putc (' ', port);
fee7ef83 2322 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2323 scm_puts (str, port);
2324 }
2325 }
0f2d19dd
JB
2326 case scm_tc7_ivect:
2327 if (n-- > 0)
fee7ef83 2328 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2329 for (j += inc; n-- > 0; j += inc)
2330 {
b7f3516f 2331 scm_putc (' ', port);
fee7ef83 2332 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2333 }
2334 break;
2335
2336 case scm_tc7_svect:
2337 if (n-- > 0)
4260a7fc 2338 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2339 for (j += inc; n-- > 0; j += inc)
2340 {
b7f3516f 2341 scm_putc (' ', port);
4260a7fc 2342 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2343 }
2344 break;
2345
0f2d19dd
JB
2346 case scm_tc7_fvect:
2347 if (n-- > 0)
2348 {
bc86da5d
MD
2349 SCM z = scm_make_real (1.0);
2350 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2351 scm_print_real (z, port, pstate);
0f2d19dd
JB
2352 for (j += inc; n-- > 0; j += inc)
2353 {
b7f3516f 2354 scm_putc (' ', port);
bc86da5d
MD
2355 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2356 scm_print_real (z, port, pstate);
0f2d19dd
JB
2357 }
2358 }
2359 break;
0f2d19dd
JB
2360 case scm_tc7_dvect:
2361 if (n-- > 0)
2362 {
bc86da5d
MD
2363 SCM z = scm_make_real (1.0 / 3.0);
2364 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2365 scm_print_real (z, port, pstate);
0f2d19dd
JB
2366 for (j += inc; n-- > 0; j += inc)
2367 {
b7f3516f 2368 scm_putc (' ', port);
bc86da5d
MD
2369 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2370 scm_print_real (z, port, pstate);
0f2d19dd
JB
2371 }
2372 }
2373 break;
2374 case scm_tc7_cvect:
2375 if (n-- > 0)
2376 {
bc86da5d
MD
2377 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2378 SCM_REAL_VALUE (z) =
2379 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2380 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2381 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2382 port, pstate);
0f2d19dd
JB
2383 for (j += inc; n-- > 0; j += inc)
2384 {
b7f3516f 2385 scm_putc (' ', port);
bc86da5d
MD
2386 SCM_REAL_VALUE (z)
2387 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2388 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2389 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2390 port, pstate);
0f2d19dd
JB
2391 }
2392 }
2393 break;
0f2d19dd
JB
2394 }
2395}
2396
2397
1cc91f1b 2398
0f2d19dd 2399int
1bbd0b84 2400scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2401{
2402 SCM v = exp;
2403 scm_sizet base = 0;
b7f3516f 2404 scm_putc ('#', port);
0f2d19dd 2405tail:
5c11cc9d 2406 switch SCM_TYP7 (v)
0f2d19dd
JB
2407 {
2408 case scm_tc7_smob:
2409 {
2410 long ndim = SCM_ARRAY_NDIM (v);
2411 base = SCM_ARRAY_BASE (v);
2412 v = SCM_ARRAY_V (v);
2413 if (SCM_ARRAYP (v))
2414
2415 {
b7f3516f 2416 scm_puts ("<enclosed-array ", port);
9882ea19 2417 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2418 scm_putc ('>', port);
0f2d19dd
JB
2419 return 1;
2420 }
2421 else
2422 {
2423 scm_intprint (ndim, 10, port);
2424 goto tail;
2425 }
2426 }
2427 case scm_tc7_bvect:
fee7ef83 2428 if (SCM_EQ_P (exp, v))
0f2d19dd
JB
2429 { /* a uve, not an scm_array */
2430 register long i, j, w;
b7f3516f 2431 scm_putc ('*', port);
74014c46 2432 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2433 {
f1267706 2434 scm_bits_t w = SCM_UNPACK (SCM_VELTS (exp)[i]);
0f2d19dd
JB
2435 for (j = SCM_LONG_BIT; j; j--)
2436 {
b7f3516f 2437 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2438 w >>= 1;
2439 }
2440 }
74014c46 2441 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2442 if (j)
2443 {
74014c46 2444 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2445 for (; j; j--)
2446 {
b7f3516f 2447 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2448 w >>= 1;
2449 }
2450 }
2451 return 1;
2452 }
2453 else
b7f3516f 2454 scm_putc ('b', port);
0f2d19dd
JB
2455 break;
2456 case scm_tc7_string:
b7f3516f 2457 scm_putc ('a', port);
0f2d19dd
JB
2458 break;
2459 case scm_tc7_byvect:
05c33d09 2460 scm_putc ('y', port);
0f2d19dd
JB
2461 break;
2462 case scm_tc7_uvect:
b7f3516f 2463 scm_putc ('u', port);
0f2d19dd
JB
2464 break;
2465 case scm_tc7_ivect:
b7f3516f 2466 scm_putc ('e', port);
0f2d19dd
JB
2467 break;
2468 case scm_tc7_svect:
05c33d09 2469 scm_putc ('h', port);
0f2d19dd 2470 break;
5c11cc9d 2471#ifdef HAVE_LONG_LONGS
0f2d19dd 2472 case scm_tc7_llvect:
5c11cc9d 2473 scm_putc ('l', port);
0f2d19dd
JB
2474 break;
2475#endif
0f2d19dd 2476 case scm_tc7_fvect:
b7f3516f 2477 scm_putc ('s', port);
0f2d19dd 2478 break;
0f2d19dd 2479 case scm_tc7_dvect:
b7f3516f 2480 scm_putc ('i', port);
0f2d19dd
JB
2481 break;
2482 case scm_tc7_cvect:
b7f3516f 2483 scm_putc ('c', port);
0f2d19dd 2484 break;
0f2d19dd 2485 }
b7f3516f 2486 scm_putc ('(', port);
9882ea19 2487 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2488 scm_putc (')', port);
0f2d19dd
JB
2489 return 1;
2490}
2491
3b3b36dd 2492SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2493 (SCM ra),
b380b885
MD
2494 "Returns an object that would produce an array of the same type as\n"
2495 "@var{array}, if used as the @var{prototype} for\n"
2496 "@code{make-uniform-array}.")
1bbd0b84 2497#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2498{
2499 int enclosed = 0;
2500 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2501loop:
74014c46 2502 switch SCM_TYP7 (ra)
0f2d19dd
JB
2503 {
2504 default:
1bbd0b84 2505 badarg:SCM_WTA (1,ra);
0f2d19dd
JB
2506 case scm_tc7_smob:
2507 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2508 if (enclosed++)
2509 return SCM_UNSPECIFIED;
2510 ra = SCM_ARRAY_V (ra);
2511 goto loop;
2512 case scm_tc7_vector:
95f5b0f5 2513 case scm_tc7_wvect:
0f2d19dd
JB
2514 return SCM_EOL;
2515 case scm_tc7_bvect:
2516 return SCM_BOOL_T;
2517 case scm_tc7_string:
7866a09b 2518 return SCM_MAKE_CHAR ('a');
0f2d19dd 2519 case scm_tc7_byvect:
7866a09b 2520 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2521 case scm_tc7_uvect:
2522 return SCM_MAKINUM (1L);
2523 case scm_tc7_ivect:
2524 return SCM_MAKINUM (-1L);
2525 case scm_tc7_svect:
2526 return SCM_CDR (scm_intern ("s", 1));
5c11cc9d 2527#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2528 case scm_tc7_llvect:
2529 return SCM_CDR (scm_intern ("l", 1));
2530#endif
0f2d19dd 2531 case scm_tc7_fvect:
bc86da5d 2532 return scm_make_real (1.0);
0f2d19dd 2533 case scm_tc7_dvect:
bc86da5d 2534 return scm_make_real (1.0 / 3.0);
0f2d19dd 2535 case scm_tc7_cvect:
bc86da5d 2536 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2537 }
2538}
1bbd0b84 2539#undef FUNC_NAME
0f2d19dd 2540
1cc91f1b 2541
0f2d19dd 2542static SCM
1bbd0b84 2543markra (SCM ptr)
0f2d19dd 2544{
0f2d19dd
JB
2545 return SCM_ARRAY_V (ptr);
2546}
2547
1cc91f1b 2548
0f2d19dd 2549static scm_sizet
1bbd0b84 2550freera (SCM ptr)
0f2d19dd 2551{
405aaef9 2552 scm_must_free (SCM_ARRAY_MEM (ptr));
0f2d19dd
JB
2553 return sizeof (scm_array) + SCM_ARRAY_NDIM (ptr) * sizeof (scm_array_dim);
2554}
2555
0f2d19dd
JB
2556void
2557scm_init_unif ()
0f2d19dd 2558{
23a62151
MD
2559 scm_tc16_array = scm_make_smob_type_mfpe ("array", 0,
2560 markra,
2561 freera,
2562 scm_raprin1,
2563 scm_array_equal_p);
0f2d19dd 2564 scm_add_feature ("array");
8dc9439f 2565#ifndef SCM_MAGIC_SNARFER
a0599745 2566#include "libguile/unif.x"
8dc9439f 2567#endif
0f2d19dd 2568}
89e00824
ML
2569
2570/*
2571 Local Variables:
2572 c-file-style: "gnu"
2573 End:
2574*/