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