Add SCM_API patch incorporation; associate mvo w/ it.
[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);
d245ce23
MD
1514 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1515 ? 0
1516 : SCM_INUM (scm_uniform_vector_length (v)));
35de7ebe 1517
0f2d19dd 1518loop:
35de7ebe 1519 switch SCM_TYP7 (v)
0f2d19dd
JB
1520 {
1521 default:
276dd677 1522 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd
JB
1523 case scm_tc7_smob:
1524 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1525 cra = scm_ra2contig (ra, 0);
1146b6cd 1526 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1527 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1528 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1529 v = SCM_ARRAY_V (cra);
1530 goto loop;
1531 case scm_tc7_string:
74014c46 1532 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1533 sz = sizeof (char);
1534 break;
1535 case scm_tc7_bvect:
74014c46 1536 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1537 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1538 cstart /= SCM_LONG_BIT;
1539 sz = sizeof (long);
74014c46
DH
1540 break;
1541 case scm_tc7_byvect:
1542 base = (char *) SCM_UVECTOR_BASE (v);
1543 sz = sizeof (char);
1544 break;
0f2d19dd
JB
1545 case scm_tc7_uvect:
1546 case scm_tc7_ivect:
74014c46 1547 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1548 sz = sizeof (long);
1549 break;
1550 case scm_tc7_svect:
74014c46 1551 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1552 sz = sizeof (short);
1553 break;
5c11cc9d 1554#ifdef HAVE_LONG_LONGS
0f2d19dd 1555 case scm_tc7_llvect:
74014c46 1556 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1557 sz = sizeof (long long);
0f2d19dd
JB
1558 break;
1559#endif
0f2d19dd 1560 case scm_tc7_fvect:
74014c46 1561 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1562 sz = sizeof (float);
1563 break;
0f2d19dd 1564 case scm_tc7_dvect:
74014c46 1565 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1566 sz = sizeof (double);
1567 break;
1568 case scm_tc7_cvect:
74014c46 1569 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1570 sz = 2 * sizeof (double);
1571 break;
0f2d19dd 1572 }
405aaef9 1573
1146b6cd
GH
1574 cend = vlen;
1575 if (!SCM_UNBNDP (start))
3d8d56df 1576 {
1146b6cd 1577 offset =
c014a02e 1578 SCM_NUM2LONG (3, start);
35de7ebe 1579
1146b6cd 1580 if (offset < 0 || offset >= cend)
1bbd0b84 1581 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1582
1583 if (!SCM_UNBNDP (end))
1584 {
c014a02e
ML
1585 long tend =
1586 SCM_NUM2LONG (4, end);
3d8d56df 1587
1146b6cd 1588 if (tend <= offset || tend > cend)
1bbd0b84 1589 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1590 cend = tend;
1591 }
0f2d19dd 1592 }
35de7ebe 1593
3d8d56df
GH
1594 if (SCM_NIMP (port_or_fd))
1595 {
92c2555f 1596 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1597 int remaining = (cend - offset) * sz;
405aaef9 1598 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1599
1600 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1601 scm_flush (port_or_fd);
6c951427
GH
1602
1603 ans = cend - offset;
1604 while (remaining > 0)
3d8d56df 1605 {
6c951427
GH
1606 if (pt->read_pos < pt->read_end)
1607 {
1608 int to_copy = min (pt->read_end - pt->read_pos,
1609 remaining);
1610
1611 memcpy (dest, pt->read_pos, to_copy);
1612 pt->read_pos += to_copy;
1613 remaining -= to_copy;
1614 dest += to_copy;
1615 }
1616 else
1617 {
affc96b5 1618 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1619 {
1620 if (remaining % sz != 0)
1621 {
5d2d2ffc 1622 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1623 }
1624 ans -= remaining / sz;
1625 break;
1626 }
6c951427 1627 }
3d8d56df 1628 }
6c951427
GH
1629
1630 if (pt->rw_random)
1631 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1632 }
1633 else /* file descriptor. */
1634 {
1635 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1636 base + (cstart + offset) * sz,
1be6b49c 1637 (sz * (cend - offset))));
3d8d56df 1638 if (ans == -1)
1bbd0b84 1639 SCM_SYSERROR;
3d8d56df 1640 }
0f2d19dd 1641 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1642 ans *= SCM_LONG_BIT;
35de7ebe 1643
fee7ef83 1644 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1645 scm_array_copy_x (cra, ra);
35de7ebe 1646
0f2d19dd
JB
1647 return SCM_MAKINUM (ans);
1648}
1bbd0b84 1649#undef FUNC_NAME
0f2d19dd 1650
3b3b36dd 1651SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1652 (SCM v, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1653 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1654 "Writes all elements of @var{ura} as binary objects to\n"
1655 "@var{port-or-fdes}.\n\n"
1656 "The optional arguments @var{start}\n"
1657 "and @var{end} allow\n"
1658 "a specified region of a vector (or linearized array) to be written.\n\n"
1659 "The number of objects actually written is returned. \n"
1660 "@var{port-or-fdes} may be\n"
1661 "omitted, in which case it defaults to the value returned by\n"
1662 "@code{(current-output-port)}.")
1bbd0b84 1663#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1664{
c014a02e
ML
1665 long sz, vlen, ans;
1666 long offset = 0;
1667 long cstart = 0;
1668 long cend;
405aaef9 1669 char *base;
3d8d56df 1670
78446828
MV
1671 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1672
0f2d19dd 1673 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1674 if (SCM_UNBNDP (port_or_fd))
1675 port_or_fd = scm_cur_outp;
1676 else
1677 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1678 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1679 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1680 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1681 ? 0
1682 : SCM_INUM (scm_uniform_vector_length (v)));
1683
0f2d19dd 1684loop:
3d8d56df 1685 switch SCM_TYP7 (v)
0f2d19dd
JB
1686 {
1687 default:
276dd677 1688 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
1689 case scm_tc7_smob:
1690 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1691 v = scm_ra2contig (v, 1);
1146b6cd 1692 cstart = SCM_ARRAY_BASE (v);
d245ce23
MD
1693 vlen = (SCM_ARRAY_DIMS (v)->inc
1694 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
0f2d19dd
JB
1695 v = SCM_ARRAY_V (v);
1696 goto loop;
0f2d19dd 1697 case scm_tc7_string:
74014c46 1698 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1699 sz = sizeof (char);
1700 break;
1701 case scm_tc7_bvect:
74014c46 1702 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1703 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1704 cstart /= SCM_LONG_BIT;
1705 sz = sizeof (long);
74014c46
DH
1706 break;
1707 case scm_tc7_byvect:
1708 base = (char *) SCM_UVECTOR_BASE (v);
1709 sz = sizeof (char);
1710 break;
0f2d19dd
JB
1711 case scm_tc7_uvect:
1712 case scm_tc7_ivect:
74014c46 1713 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1714 sz = sizeof (long);
1715 break;
1716 case scm_tc7_svect:
74014c46 1717 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1718 sz = sizeof (short);
1719 break;
5c11cc9d 1720#ifdef HAVE_LONG_LONGS
0f2d19dd 1721 case scm_tc7_llvect:
74014c46 1722 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1723 sz = sizeof (long long);
0f2d19dd
JB
1724 break;
1725#endif
0f2d19dd 1726 case scm_tc7_fvect:
74014c46 1727 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1728 sz = sizeof (float);
1729 break;
0f2d19dd 1730 case scm_tc7_dvect:
74014c46 1731 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1732 sz = sizeof (double);
1733 break;
1734 case scm_tc7_cvect:
74014c46 1735 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1736 sz = 2 * sizeof (double);
1737 break;
0f2d19dd 1738 }
3d8d56df 1739
1146b6cd
GH
1740 cend = vlen;
1741 if (!SCM_UNBNDP (start))
3d8d56df 1742 {
1146b6cd 1743 offset =
c014a02e 1744 SCM_NUM2LONG (3, start);
3d8d56df 1745
1146b6cd 1746 if (offset < 0 || offset >= cend)
1bbd0b84 1747 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1748
1749 if (!SCM_UNBNDP (end))
1750 {
c014a02e
ML
1751 long tend =
1752 SCM_NUM2LONG (4, end);
3d8d56df 1753
1146b6cd 1754 if (tend <= offset || tend > cend)
1bbd0b84 1755 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1756 cend = tend;
1757 }
3d8d56df
GH
1758 }
1759
1760 if (SCM_NIMP (port_or_fd))
1761 {
405aaef9 1762 char *source = base + (cstart + offset) * sz;
6c951427
GH
1763
1764 ans = cend - offset;
265e6a4d 1765 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1766 }
1767 else /* file descriptor. */
1768 {
1769 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
405aaef9 1770 base + (cstart + offset) * sz,
1be6b49c 1771 (sz * (cend - offset))));
3d8d56df 1772 if (ans == -1)
1bbd0b84 1773 SCM_SYSERROR;
3d8d56df 1774 }
0f2d19dd 1775 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1776 ans *= SCM_LONG_BIT;
3d8d56df 1777
0f2d19dd
JB
1778 return SCM_MAKINUM (ans);
1779}
1bbd0b84 1780#undef FUNC_NAME
0f2d19dd
JB
1781
1782
1783static char cnt_tab[16] =
1784{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1785
3b3b36dd 1786SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1787 (SCM b, SCM bitvector),
1e6808ea 1788 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1789 "@var{bitvector}.")
1bbd0b84 1790#define FUNC_NAME s_scm_bit_count
0f2d19dd 1791{
44e47754 1792 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1793 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1794 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1795 return SCM_INUM0;
1796 } else {
c014a02e
ML
1797 unsigned long int count = 0;
1798 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1799 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
44e47754
DH
1800 if (SCM_FALSEP (b)) {
1801 w = ~w;
1802 };
c014a02e 1803 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1804 while (1) {
1805 while (w) {
1806 count += cnt_tab[w & 0x0f];
1807 w >>= 4;
1808 }
1809 if (i == 0) {
1810 return SCM_MAKINUM (count);
1811 } else {
1812 --i;
1813 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1814 if (SCM_FALSEP (b)) {
1815 w = ~w;
0f2d19dd 1816 }
44e47754 1817 }
0f2d19dd 1818 }
44e47754 1819 }
0f2d19dd 1820}
1bbd0b84 1821#undef FUNC_NAME
0f2d19dd
JB
1822
1823
3b3b36dd 1824SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1825 (SCM item, SCM v, SCM k),
1e6808ea
MG
1826 "Return the minimum index of an occurrence of @var{bool} in\n"
1827 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1828 "within the specified range @code{#f} is returned.")
1bbd0b84 1829#define FUNC_NAME s_scm_bit_position
0f2d19dd 1830{
c014a02e
ML
1831 long i, lenw, xbits, pos;
1832 register unsigned long w;
74014c46
DH
1833
1834 SCM_VALIDATE_BOOL (1, item);
1835 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
3b3b36dd 1836 SCM_VALIDATE_INUM_COPY (3,k,pos);
74014c46
DH
1837 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1838
1839 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1840 return SCM_BOOL_F;
74014c46 1841
c014a02e
ML
1842 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1843 i = pos / SCM_LONG_BIT;
74014c46
DH
1844 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1845 if (SCM_FALSEP (item))
1846 w = ~w;
c014a02e 1847 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1848 pos -= xbits;
1849 w = ((w >> xbits) << xbits);
c014a02e 1850 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1851 while (!0)
1852 {
1853 if (w && (i == lenw))
1854 w = ((w << xbits) >> xbits);
1855 if (w)
1856 while (w)
1857 switch (w & 0x0f)
1858 {
1859 default:
1860 return SCM_MAKINUM (pos);
1861 case 2:
1862 case 6:
1863 case 10:
1864 case 14:
1865 return SCM_MAKINUM (pos + 1);
1866 case 4:
1867 case 12:
1868 return SCM_MAKINUM (pos + 2);
1869 case 8:
1870 return SCM_MAKINUM (pos + 3);
1871 case 0:
1872 pos += 4;
1873 w >>= 4;
1874 }
1875 if (++i > lenw)
1876 break;
c014a02e 1877 pos += SCM_LONG_BIT;
f1267706 1878 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1879 if (SCM_FALSEP (item))
1880 w = ~w;
0f2d19dd 1881 }
74014c46 1882 return SCM_BOOL_F;
0f2d19dd 1883}
1bbd0b84 1884#undef FUNC_NAME
0f2d19dd
JB
1885
1886
3b3b36dd 1887SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761
MG
1888 (SCM v, SCM kv, SCM obj),
1889 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1890 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1891 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1892 "AND'ed into @var{bv}.\n\n"
1893 "If uve is a unsigned integer vector all the elements of uve\n"
1894 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1895 "of @var{bv} corresponding to the indexes in uve are set to\n"
1896 "@var{bool}. The return value is unspecified.")
1bbd0b84 1897#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1898{
c014a02e 1899 register long i, k, vlen;
74014c46 1900 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1901 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1902 switch SCM_TYP7 (kv)
0f2d19dd
JB
1903 {
1904 default:
276dd677 1905 badarg2:SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1906 case scm_tc7_uvect:
74014c46
DH
1907 vlen = SCM_BITVECTOR_LENGTH (v);
1908 if (SCM_FALSEP (obj))
1909 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1910 {
c014a02e 1911 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1912 if (k >= vlen)
1913 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1914 SCM_BITVEC_CLR(v,k);
1915 }
1916 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1917 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1918 {
c014a02e 1919 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1920 if (k >= vlen)
1921 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1922 SCM_BITVEC_SET(v,k);
1923 }
1924 else
276dd677 1925 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1926 break;
1927 case scm_tc7_bvect:
74014c46 1928 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1929 if (SCM_FALSEP (obj))
c014a02e 1930 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1931 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
9a09deb1 1932 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c014a02e 1933 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1934 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
0f2d19dd
JB
1935 else
1936 goto badarg3;
1937 break;
1938 }
1939 return SCM_UNSPECIFIED;
1940}
1bbd0b84 1941#undef FUNC_NAME
0f2d19dd
JB
1942
1943
3b3b36dd 1944SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1945 (SCM v, SCM kv, SCM obj),
1e6808ea
MG
1946 "Return\n"
1947 "@lisp\n"
b380b885 1948 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1e6808ea 1949 "@end lisp\n"
b380b885 1950 "@var{bv} is not modified.")
1bbd0b84 1951#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1952{
c014a02e
ML
1953 register long i, vlen, count = 0;
1954 register unsigned long k;
41b0806d 1955 int fObj = 0;
c209c88e 1956
74014c46 1957 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1958 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1959 switch SCM_TYP7 (kv)
0f2d19dd
JB
1960 {
1961 default:
c209c88e 1962 badarg2:
276dd677 1963 SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1964 case scm_tc7_uvect:
74014c46
DH
1965 vlen = SCM_BITVECTOR_LENGTH (v);
1966 if (SCM_FALSEP (obj))
1967 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1968 {
c014a02e 1969 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1970 if (k >= vlen)
1971 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1972 if (!SCM_BITVEC_REF(v,k))
1973 count++;
1974 }
1975 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1976 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1977 {
c014a02e 1978 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1979 if (k >= vlen)
1980 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
1981 if (SCM_BITVEC_REF (v,k))
1982 count++;
1983 }
1984 else
276dd677 1985 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1986 break;
1987 case scm_tc7_bvect:
74014c46
DH
1988 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1989 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1990 return SCM_INUM0;
4260a7fc 1991 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1992 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
c014a02e
ML
1993 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1994 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1995 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1996 while (1)
0f2d19dd
JB
1997 {
1998 for (; k; k >>= 4)
1999 count += cnt_tab[k & 0x0f];
2000 if (0 == i--)
2001 return SCM_MAKINUM (count);
c209c88e
GB
2002
2003 /* urg. repetitive (see above.) */
c014a02e 2004 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
2005 }
2006 }
2007 return SCM_MAKINUM (count);
2008}
1bbd0b84 2009#undef FUNC_NAME
0f2d19dd
JB
2010
2011
3b3b36dd 2012SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2013 (SCM v),
b380b885 2014 "Modifies @var{bv} by replacing each element with its negation.")
1bbd0b84 2015#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2016{
c014a02e 2017 long int k;
74014c46
DH
2018
2019 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
2020
2021 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 2022 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 2023 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 2024
0f2d19dd
JB
2025 return SCM_UNSPECIFIED;
2026}
1bbd0b84 2027#undef FUNC_NAME
0f2d19dd
JB
2028
2029
0f2d19dd 2030SCM
c014a02e 2031scm_istr2bve (char *str, long len)
0f2d19dd
JB
2032{
2033 SCM v = scm_make_uve (len, SCM_BOOL_T);
c014a02e
ML
2034 long *data = (long *) SCM_VELTS (v);
2035 register unsigned long mask;
2036 register long k;
2037 register long j;
2038 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
2039 {
2040 data[k] = 0L;
c014a02e
ML
2041 j = len - k * SCM_LONG_BIT;
2042 if (j > SCM_LONG_BIT)
2043 j = SCM_LONG_BIT;
0f2d19dd
JB
2044 for (mask = 1L; j--; mask <<= 1)
2045 switch (*str++)
2046 {
2047 case '0':
2048 break;
2049 case '1':
2050 data[k] |= mask;
2051 break;
2052 default:
2053 return SCM_BOOL_F;
2054 }
2055 }
2056 return v;
2057}
2058
2059
1cc91f1b 2060
0f2d19dd 2061static SCM
c014a02e 2062ra2l (SCM ra,unsigned long base,unsigned long k)
0f2d19dd
JB
2063{
2064 register SCM res = SCM_EOL;
c014a02e
ML
2065 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2066 register size_t i;
0f2d19dd
JB
2067 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2068 return SCM_EOL;
2069 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2070 if (k < SCM_ARRAY_NDIM (ra) - 1)
2071 {
2072 do
2073 {
2074 i -= inc;
2075 res = scm_cons (ra2l (ra, i, k + 1), res);
2076 }
2077 while (i != base);
2078 }
2079 else
2080 do
2081 {
2082 i -= inc;
2083 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2084 }
2085 while (i != base);
2086 return res;
2087}
2088
2089
92c2555f 2090SCM_DEFINE (scm_t_arrayo_list, "array->list", 1, 0, 0,
1bbd0b84 2091 (SCM v),
1e6808ea
MG
2092 "Return a list consisting of all the elements, in order, of\n"
2093 "@var{array}.")
92c2555f 2094#define FUNC_NAME s_scm_t_arrayo_list
0f2d19dd
JB
2095{
2096 SCM res = SCM_EOL;
c014a02e 2097 register long k;
0f2d19dd 2098 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2099 switch SCM_TYP7 (v)
0f2d19dd
JB
2100 {
2101 default:
276dd677 2102 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
2103 case scm_tc7_smob:
2104 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2105 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2106 case scm_tc7_vector:
95f5b0f5 2107 case scm_tc7_wvect:
0f2d19dd
JB
2108 return scm_vector_to_list (v);
2109 case scm_tc7_string:
2110 return scm_string_to_list (v);
2111 case scm_tc7_bvect:
2112 {
c014a02e
ML
2113 long *data = (long *) SCM_VELTS (v);
2114 register unsigned long mask;
2115 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2116 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2117 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2118 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2119 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2120 return res;
2121 }
af7546eb
DH
2122 case scm_tc7_byvect:
2123 {
2124 signed char *data = (signed char *) SCM_VELTS (v);
c014a02e 2125 unsigned long k = SCM_UVECTOR_LENGTH (v);
af7546eb
DH
2126 while (k != 0)
2127 res = scm_cons (SCM_MAKINUM (data[--k]), res);
2128 return res;
2129 }
2130 case scm_tc7_uvect:
2131 {
c014a02e 2132 long *data = (long *)SCM_VELTS(v);
af7546eb 2133 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2134 res = scm_cons(scm_ulong2num(data[k]), res);
af7546eb
DH
2135 return res;
2136 }
2137 case scm_tc7_ivect:
2138 {
c014a02e 2139 long *data = (long *)SCM_VELTS(v);
af7546eb 2140 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2141 res = scm_cons(scm_long2num(data[k]), res);
af7546eb
DH
2142 return res;
2143 }
2144 case scm_tc7_svect:
2145 {
2146 short *data = (short *)SCM_VELTS(v);
2147 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
1be6b49c 2148 res = scm_cons(scm_short2num (data[k]), res);
af7546eb
DH
2149 return res;
2150 }
5c11cc9d 2151#ifdef HAVE_LONG_LONGS
af7546eb
DH
2152 case scm_tc7_llvect:
2153 {
1be6b49c 2154 long long *data = (long long *)SCM_VELTS(v);
af7546eb
DH
2155 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
2156 res = scm_cons(scm_long_long2num(data[k]), res);
2157 return res;
2158 }
0f2d19dd 2159#endif
0f2d19dd
JB
2160 case scm_tc7_fvect:
2161 {
2162 float *data = (float *) SCM_VELTS (v);
74014c46 2163 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2164 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2165 return res;
2166 }
0f2d19dd
JB
2167 case scm_tc7_dvect:
2168 {
2169 double *data = (double *) SCM_VELTS (v);
74014c46 2170 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2171 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2172 return res;
2173 }
2174 case scm_tc7_cvect:
2175 {
2176 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2177 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2178 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2179 return res;
2180 }
0f2d19dd
JB
2181 }
2182}
1bbd0b84 2183#undef FUNC_NAME
0f2d19dd
JB
2184
2185
c014a02e 2186static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2187
3b3b36dd 2188SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2189 (SCM ndim, SCM prot, SCM lst),
b380b885 2190 "@deffnx procedure list->uniform-vector prot lst\n"
1e6808ea
MG
2191 "Return a uniform array of the type indicated by prototype\n"
2192 "@var{prot} with elements the same as those of @var{lst}.\n"
2193 "Elements must be of the appropriate type, no coercions are\n"
2194 "done.")
1bbd0b84 2195#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2196{
2197 SCM shp = SCM_EOL;
2198 SCM row = lst;
2199 SCM ra;
c014a02e 2200 unsigned long k;
0f2d19dd 2201 long n;
3b3b36dd 2202 SCM_VALIDATE_INUM_COPY (1,ndim,k);
0f2d19dd
JB
2203 while (k--)
2204 {
2205 n = scm_ilength (row);
1bbd0b84 2206 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2207 shp = scm_cons (SCM_MAKINUM (n), shp);
2208 if (SCM_NIMP (row))
2209 row = SCM_CAR (row);
2210 }
d12feca3
GH
2211 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2212 SCM_UNDEFINED);
0f2d19dd 2213 if (SCM_NULLP (shp))
0f2d19dd
JB
2214 {
2215 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2216 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2217 return ra;
2218 }
2219 if (!SCM_ARRAYP (ra))
2220 {
c014a02e 2221 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
74014c46 2222 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2223 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2224 return ra;
2225 }
2226 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2227 return ra;
2228 else
1afff620
KN
2229 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2230 scm_list_1 (lst));
0f2d19dd 2231}
1bbd0b84 2232#undef FUNC_NAME
0f2d19dd 2233
0f2d19dd 2234static int
c014a02e 2235l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2236{
c014a02e
ML
2237 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2238 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2239 int ok = 1;
2240 if (n <= 0)
4260a7fc 2241 return (SCM_NULLP (lst));
0f2d19dd
JB
2242 if (k < SCM_ARRAY_NDIM (ra) - 1)
2243 {
2244 while (n--)
2245 {
2246 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2247 return 0;
2248 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2249 base += inc;
2250 lst = SCM_CDR (lst);
2251 }
2252 if (SCM_NNULLP (lst))
2253 return 0;
2254 }
2255 else
2256 {
2257 while (n--)
2258 {
2259 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2260 return 0;
baa702c8 2261 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2262 base += inc;
2263 lst = SCM_CDR (lst);
2264 }
2265 if (SCM_NNULLP (lst))
fee7ef83 2266 return 0;
0f2d19dd
JB
2267 }
2268 return ok;
2269}
2270
1cc91f1b 2271
0f2d19dd 2272static void
c014a02e 2273rapr1 (SCM ra,unsigned long j,unsigned long k,SCM port,scm_print_state *pstate)
0f2d19dd 2274{
c014a02e
ML
2275 long inc = 1;
2276 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8
MD
2277 ? 0
2278 : SCM_INUM (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2279 int enclosed = 0;
2280tail:
5c11cc9d 2281 switch SCM_TYP7 (ra)
0f2d19dd
JB
2282 {
2283 case scm_tc7_smob:
2284 if (enclosed++)
2285 {
2286 SCM_ARRAY_BASE (ra) = j;
2287 if (n-- > 0)
9882ea19 2288 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2289 for (j += inc; n-- > 0; j += inc)
2290 {
b7f3516f 2291 scm_putc (' ', port);
0f2d19dd 2292 SCM_ARRAY_BASE (ra) = j;
9882ea19 2293 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2294 }
2295 break;
2296 }
2297 if (k + 1 < SCM_ARRAY_NDIM (ra))
2298 {
c014a02e 2299 long i;
0f2d19dd
JB
2300 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2301 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2302 {
b7f3516f 2303 scm_putc ('(', port);
9882ea19 2304 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2305 scm_puts (") ", port);
0f2d19dd
JB
2306 j += inc;
2307 }
2308 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2309 { /* could be zero size. */
b7f3516f 2310 scm_putc ('(', port);
9882ea19 2311 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2312 scm_putc (')', port);
0f2d19dd
JB
2313 }
2314 break;
2315 }
1be6b49c 2316 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2317 { /* Could be zero-dimensional */
2318 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2319 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2320 }
2321 else
2322 n = 1;
2323 ra = SCM_ARRAY_V (ra);
2324 goto tail;
2325 default:
5c11cc9d 2326 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2327 if (n-- > 0)
9882ea19 2328 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2329 for (j += inc; n-- > 0; j += inc)
2330 {
b7f3516f 2331 scm_putc (' ', port);
9882ea19 2332 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2333 }
2334 break;
2335 case scm_tc7_string:
2336 if (n-- > 0)
322ac0c5 2337 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2338 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2339 for (j += inc; n-- > 0; j += inc)
2340 {
b7f3516f 2341 scm_putc (' ', port);
322ac0c5 2342 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2343 }
2344 else
2345 for (j += inc; n-- > 0; j += inc)
405aaef9 2346 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2347 break;
2348 case scm_tc7_byvect:
2349 if (n-- > 0)
4260a7fc 2350 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2351 for (j += inc; n-- > 0; j += inc)
2352 {
b7f3516f 2353 scm_putc (' ', port);
4260a7fc 2354 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2355 }
2356 break;
2357
2358 case scm_tc7_uvect:
5c11cc9d
GH
2359 {
2360 char str[11];
2361
2362 if (n-- > 0)
2363 {
2364 /* intprint can't handle >= 2^31. */
fee7ef83 2365 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2366 scm_puts (str, port);
2367 }
2368 for (j += inc; n-- > 0; j += inc)
2369 {
2370 scm_putc (' ', port);
fee7ef83 2371 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2372 scm_puts (str, port);
2373 }
2374 }
0f2d19dd
JB
2375 case scm_tc7_ivect:
2376 if (n-- > 0)
fee7ef83 2377 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2378 for (j += inc; n-- > 0; j += inc)
2379 {
b7f3516f 2380 scm_putc (' ', port);
fee7ef83 2381 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2382 }
2383 break;
2384
2385 case scm_tc7_svect:
2386 if (n-- > 0)
4260a7fc 2387 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2388 for (j += inc; n-- > 0; j += inc)
2389 {
b7f3516f 2390 scm_putc (' ', port);
4260a7fc 2391 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2392 }
2393 break;
2394
0f2d19dd
JB
2395 case scm_tc7_fvect:
2396 if (n-- > 0)
2397 {
bc86da5d
MD
2398 SCM z = scm_make_real (1.0);
2399 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2400 scm_print_real (z, port, pstate);
0f2d19dd
JB
2401 for (j += inc; n-- > 0; j += inc)
2402 {
b7f3516f 2403 scm_putc (' ', port);
bc86da5d
MD
2404 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2405 scm_print_real (z, port, pstate);
0f2d19dd
JB
2406 }
2407 }
2408 break;
0f2d19dd
JB
2409 case scm_tc7_dvect:
2410 if (n-- > 0)
2411 {
bc86da5d
MD
2412 SCM z = scm_make_real (1.0 / 3.0);
2413 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2414 scm_print_real (z, port, pstate);
0f2d19dd
JB
2415 for (j += inc; n-- > 0; j += inc)
2416 {
b7f3516f 2417 scm_putc (' ', port);
bc86da5d
MD
2418 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2419 scm_print_real (z, port, pstate);
0f2d19dd
JB
2420 }
2421 }
2422 break;
2423 case scm_tc7_cvect:
2424 if (n-- > 0)
2425 {
bc86da5d
MD
2426 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2427 SCM_REAL_VALUE (z) =
2428 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2429 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2430 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2431 port, pstate);
0f2d19dd
JB
2432 for (j += inc; n-- > 0; j += inc)
2433 {
b7f3516f 2434 scm_putc (' ', port);
bc86da5d
MD
2435 SCM_REAL_VALUE (z)
2436 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2437 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2438 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2439 port, pstate);
0f2d19dd
JB
2440 }
2441 }
2442 break;
0f2d19dd
JB
2443 }
2444}
2445
2446
1cc91f1b 2447
0f2d19dd 2448int
1bbd0b84 2449scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2450{
2451 SCM v = exp;
c014a02e 2452 unsigned long base = 0;
b7f3516f 2453 scm_putc ('#', port);
0f2d19dd 2454tail:
5c11cc9d 2455 switch SCM_TYP7 (v)
0f2d19dd
JB
2456 {
2457 case scm_tc7_smob:
2458 {
2459 long ndim = SCM_ARRAY_NDIM (v);
2460 base = SCM_ARRAY_BASE (v);
2461 v = SCM_ARRAY_V (v);
2462 if (SCM_ARRAYP (v))
2463
2464 {
b7f3516f 2465 scm_puts ("<enclosed-array ", port);
9882ea19 2466 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2467 scm_putc ('>', port);
0f2d19dd
JB
2468 return 1;
2469 }
2470 else
2471 {
2472 scm_intprint (ndim, 10, port);
2473 goto tail;
2474 }
2475 }
2476 case scm_tc7_bvect:
fee7ef83 2477 if (SCM_EQ_P (exp, v))
0f2d19dd 2478 { /* a uve, not an scm_array */
c014a02e 2479 register long i, j, w;
b7f3516f 2480 scm_putc ('*', port);
c014a02e 2481 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2482 {
92c2555f 2483 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2484 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2485 {
b7f3516f 2486 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2487 w >>= 1;
2488 }
2489 }
c014a02e 2490 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2491 if (j)
2492 {
c014a02e 2493 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2494 for (; j; j--)
2495 {
b7f3516f 2496 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2497 w >>= 1;
2498 }
2499 }
2500 return 1;
2501 }
2502 else
b7f3516f 2503 scm_putc ('b', port);
0f2d19dd
JB
2504 break;
2505 case scm_tc7_string:
b7f3516f 2506 scm_putc ('a', port);
0f2d19dd
JB
2507 break;
2508 case scm_tc7_byvect:
05c33d09 2509 scm_putc ('y', port);
0f2d19dd
JB
2510 break;
2511 case scm_tc7_uvect:
b7f3516f 2512 scm_putc ('u', port);
0f2d19dd
JB
2513 break;
2514 case scm_tc7_ivect:
b7f3516f 2515 scm_putc ('e', port);
0f2d19dd
JB
2516 break;
2517 case scm_tc7_svect:
05c33d09 2518 scm_putc ('h', port);
0f2d19dd 2519 break;
5c11cc9d 2520#ifdef HAVE_LONG_LONGS
0f2d19dd 2521 case scm_tc7_llvect:
5c11cc9d 2522 scm_putc ('l', port);
0f2d19dd
JB
2523 break;
2524#endif
0f2d19dd 2525 case scm_tc7_fvect:
b7f3516f 2526 scm_putc ('s', port);
0f2d19dd 2527 break;
0f2d19dd 2528 case scm_tc7_dvect:
b7f3516f 2529 scm_putc ('i', port);
0f2d19dd
JB
2530 break;
2531 case scm_tc7_cvect:
b7f3516f 2532 scm_putc ('c', port);
0f2d19dd 2533 break;
0f2d19dd 2534 }
b7f3516f 2535 scm_putc ('(', port);
9882ea19 2536 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2537 scm_putc (')', port);
0f2d19dd
JB
2538 return 1;
2539}
2540
3b3b36dd 2541SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2542 (SCM ra),
1e6808ea
MG
2543 "Return an object that would produce an array of the same type\n"
2544 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2545 "@code{make-uniform-array}.")
1bbd0b84 2546#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2547{
2548 int enclosed = 0;
2549 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2550loop:
74014c46 2551 switch SCM_TYP7 (ra)
0f2d19dd
JB
2552 {
2553 default:
276dd677 2554 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
2555 case scm_tc7_smob:
2556 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2557 if (enclosed++)
2558 return SCM_UNSPECIFIED;
2559 ra = SCM_ARRAY_V (ra);
2560 goto loop;
2561 case scm_tc7_vector:
95f5b0f5 2562 case scm_tc7_wvect:
0f2d19dd
JB
2563 return SCM_EOL;
2564 case scm_tc7_bvect:
2565 return SCM_BOOL_T;
2566 case scm_tc7_string:
7866a09b 2567 return SCM_MAKE_CHAR ('a');
0f2d19dd 2568 case scm_tc7_byvect:
7866a09b 2569 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2570 case scm_tc7_uvect:
2571 return SCM_MAKINUM (1L);
2572 case scm_tc7_ivect:
2573 return SCM_MAKINUM (-1L);
2574 case scm_tc7_svect:
38ae064c 2575 return scm_str2symbol ("s");
5c11cc9d 2576#ifdef HAVE_LONG_LONGS
0f2d19dd 2577 case scm_tc7_llvect:
38ae064c 2578 return scm_str2symbol ("l");
0f2d19dd 2579#endif
0f2d19dd 2580 case scm_tc7_fvect:
bc86da5d 2581 return scm_make_real (1.0);
0f2d19dd 2582 case scm_tc7_dvect:
bc86da5d 2583 return scm_make_real (1.0 / 3.0);
0f2d19dd 2584 case scm_tc7_cvect:
bc86da5d 2585 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2586 }
2587}
1bbd0b84 2588#undef FUNC_NAME
0f2d19dd 2589
1cc91f1b 2590
0f2d19dd 2591static SCM
e841c3e0 2592array_mark (SCM ptr)
0f2d19dd 2593{
0f2d19dd
JB
2594 return SCM_ARRAY_V (ptr);
2595}
2596
1cc91f1b 2597
1be6b49c 2598static size_t
e841c3e0 2599array_free (SCM ptr)
0f2d19dd 2600{
405aaef9 2601 scm_must_free (SCM_ARRAY_MEM (ptr));
92c2555f
MV
2602 return sizeof (scm_t_array) +
2603 SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim);
0f2d19dd
JB
2604}
2605
0f2d19dd
JB
2606void
2607scm_init_unif ()
0f2d19dd 2608{
e841c3e0
KN
2609 scm_tc16_array = scm_make_smob_type ("array", 0);
2610 scm_set_smob_mark (scm_tc16_array, array_mark);
2611 scm_set_smob_free (scm_tc16_array, array_free);
2612 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2613 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
0f2d19dd 2614 scm_add_feature ("array");
8dc9439f 2615#ifndef SCM_MAGIC_SNARFER
a0599745 2616#include "libguile/unif.x"
8dc9439f 2617#endif
0f2d19dd 2618}
89e00824
ML
2619
2620/*
2621 Local Variables:
2622 c-file-style: "gnu"
2623 End:
2624*/