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