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