*** empty log message ***
[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
2a5cd898
RB
52#if HAVE_CONFIG_H
53# include <config.h>
54#endif
55
0f2d19dd 56#include <stdio.h>
e6e2e95a 57#include <errno.h>
783e7774 58#include <string.h>
e6e2e95a 59
a0599745
MD
60#include "libguile/_scm.h"
61#include "libguile/chars.h"
62#include "libguile/eval.h"
63#include "libguile/fports.h"
64#include "libguile/smob.h"
65#include "libguile/strop.h"
66#include "libguile/feature.h"
67#include "libguile/root.h"
68#include "libguile/strings.h"
69#include "libguile/vectors.h"
70
71#include "libguile/validate.h"
72#include "libguile/unif.h"
73#include "libguile/ramap.h"
0f2d19dd 74
3d8d56df
GH
75#ifdef HAVE_UNISTD_H
76#include <unistd.h>
77#endif
78
7beabedb
MG
79#ifdef HAVE_IO_H
80#include <io.h>
81#endif
82
0f2d19dd
JB
83\f
84/* The set of uniform scm_vector types is:
85 * Vector of: Called:
86 * unsigned char string
87 * char byvect
88 * boolean bvect
a515d287
MD
89 * signed long ivect
90 * unsigned long uvect
0f2d19dd
JB
91 * float fvect
92 * double dvect
93 * complex double cvect
94 * short svect
5c11cc9d 95 * long long llvect
0f2d19dd
JB
96 */
97
92c2555f 98scm_t_bits scm_tc16_array;
0f2d19dd 99
afe5177e
GH
100/* return the size of an element in a uniform array or 0 if type not
101 found. */
1be6b49c 102size_t
afe5177e 103scm_uniform_element_size (SCM obj)
0f2d19dd 104{
1be6b49c 105 size_t result;
0f2d19dd 106
afe5177e 107 switch (SCM_TYP7 (obj))
0f2d19dd 108 {
0f2d19dd 109 case scm_tc7_bvect:
0f2d19dd
JB
110 case scm_tc7_uvect:
111 case scm_tc7_ivect:
afe5177e 112 result = sizeof (long);
0f2d19dd 113 break;
afe5177e 114
0f2d19dd 115 case scm_tc7_byvect:
afe5177e 116 result = sizeof (char);
0f2d19dd
JB
117 break;
118
119 case scm_tc7_svect:
afe5177e 120 result = sizeof (short);
0f2d19dd 121 break;
afe5177e 122
2a5cd898 123#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 124 case scm_tc7_llvect:
1be6b49c 125 result = sizeof (long long);
0f2d19dd
JB
126 break;
127#endif
128
0f2d19dd 129 case scm_tc7_fvect:
afe5177e 130 result = sizeof (float);
0f2d19dd 131 break;
afe5177e 132
0f2d19dd 133 case scm_tc7_dvect:
afe5177e 134 result = sizeof (double);
0f2d19dd 135 break;
afe5177e 136
0f2d19dd 137 case scm_tc7_cvect:
afe5177e 138 result = 2 * sizeof (double);
0f2d19dd 139 break;
afe5177e
GH
140
141 default:
142 result = 0;
0f2d19dd 143 }
afe5177e 144 return result;
0f2d19dd
JB
145}
146
bc86da5d
MD
147/* Silly function used not to modify the semantics of the silly
148 * prototype system in order to be backward compatible.
149 */
150static int
151singp (SCM obj)
0f2d19dd 152{
a08b0d00 153 if (!SCM_REALP (obj))
bc86da5d
MD
154 return 0;
155 else
156 {
157 double x = SCM_REAL_VALUE (obj);
158 float fx = x;
159 return (- SCM_FLTMAX < x) && (x < SCM_FLTMAX) && (fx == x);
160 }
0f2d19dd 161}
1cc91f1b 162
0f2d19dd 163SCM
c014a02e 164scm_make_uve (long k, SCM prot)
a3a32939 165#define FUNC_NAME "scm_make_uve"
0f2d19dd
JB
166{
167 SCM v;
c014a02e 168 long i, type;
a3a32939 169
9a09deb1 170 if (SCM_EQ_P (prot, SCM_BOOL_T))
0f2d19dd 171 {
93778877
DH
172 if (k > 0)
173 {
16d4699b
MV
174 SCM_ASSERT_RANGE (1,
175 scm_long2num (k), k <= SCM_BITVECTOR_MAX_LENGTH);
c014a02e 176 i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
228a24ef
DH
177 v = scm_cell (SCM_MAKE_BITVECTOR_TAG (k),
178 (scm_t_bits) scm_gc_malloc (i, "vector"));
93778877
DH
179 }
180 else
228a24ef 181 v = scm_cell (SCM_MAKE_BITVECTOR_TAG (0), 0);
93778877 182 return v;
0f2d19dd 183 }
4260a7fc 184 else if (SCM_CHARP (prot) && (SCM_CHAR (prot) == '\0'))
0f2d19dd 185 {
c014a02e 186 i = sizeof (char) * k;
0f2d19dd 187 type = scm_tc7_byvect;
5b9eb8ae 188 }
7866a09b 189 else if (SCM_CHARP (prot))
0f2d19dd 190 {
c014a02e 191 i = sizeof (char) * k;
be54b15d 192 return scm_allocate_string (i);
0f2d19dd
JB
193 }
194 else if (SCM_INUMP (prot))
195 {
c014a02e 196 i = sizeof (long) * k;
0f2d19dd
JB
197 if (SCM_INUM (prot) > 0)
198 type = scm_tc7_uvect;
199 else
200 type = scm_tc7_ivect;
201 }
74014c46 202 else if (SCM_SYMBOLP (prot) && (1 == SCM_SYMBOL_LENGTH (prot)))
0f2d19dd
JB
203 {
204 char s;
205
86c991c2 206 s = SCM_SYMBOL_CHARS (prot)[0];
0f2d19dd
JB
207 if (s == 's')
208 {
c014a02e 209 i = sizeof (short) * k;
0f2d19dd
JB
210 type = scm_tc7_svect;
211 }
2a5cd898 212#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
213 else if (s == 'l')
214 {
c014a02e 215 i = sizeof (long long) * k;
0f2d19dd
JB
216 type = scm_tc7_llvect;
217 }
218#endif
219 else
220 {
00ffa0e7 221 return scm_c_make_vector (k, SCM_UNDEFINED);
0f2d19dd
JB
222 }
223 }
5b9eb8ae 224 else if (!SCM_INEXACTP (prot))
0f2d19dd 225 /* Huge non-unif vectors are NOT supported. */
5c11cc9d 226 /* no special scm_vector */
00ffa0e7 227 return scm_c_make_vector (k, SCM_UNDEFINED);
bc86da5d 228 else if (singp (prot))
0f2d19dd 229 {
c014a02e 230 i = sizeof (float) * k;
0f2d19dd
JB
231 type = scm_tc7_fvect;
232 }
eb42e2f0 233 else if (SCM_COMPLEXP (prot))
0f2d19dd 234 {
c014a02e 235 i = 2 * sizeof (double) * k;
0f2d19dd
JB
236 type = scm_tc7_cvect;
237 }
238 else
239 {
c014a02e 240 i = sizeof (double) * k;
0f2d19dd
JB
241 type = scm_tc7_dvect;
242 }
0f2d19dd 243
c014a02e 244 SCM_ASSERT_RANGE (1, scm_long2num (k), k <= SCM_UVECTOR_MAX_LENGTH);
5b9eb8ae 245
228a24ef
DH
246 return scm_cell (SCM_MAKE_UVECTOR_TAG (k, type),
247 (scm_t_bits) scm_gc_malloc (i, "vector"));
0f2d19dd 248}
a3a32939
DH
249#undef FUNC_NAME
250
0f2d19dd 251
3b3b36dd 252SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
1e6808ea
MG
253 (SCM v),
254 "Return the number of elements in @var{uve}.")
1bbd0b84 255#define FUNC_NAME s_scm_uniform_vector_length
0f2d19dd
JB
256{
257 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 258 switch SCM_TYP7 (v)
0f2d19dd
JB
259 {
260 default:
276dd677 261 badarg1:SCM_WRONG_TYPE_ARG (1, v);
74014c46
DH
262 case scm_tc7_vector:
263 case scm_tc7_wvect:
264 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v));
0f2d19dd 265 case scm_tc7_string:
74014c46
DH
266 return SCM_MAKINUM (SCM_STRING_LENGTH (v));
267 case scm_tc7_bvect:
268 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v));
0f2d19dd
JB
269 case scm_tc7_byvect:
270 case scm_tc7_uvect:
271 case scm_tc7_ivect:
272 case scm_tc7_fvect:
273 case scm_tc7_dvect:
274 case scm_tc7_cvect:
0f2d19dd 275 case scm_tc7_svect:
2a5cd898 276#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
277 case scm_tc7_llvect:
278#endif
74014c46 279 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v));
0f2d19dd
JB
280 }
281}
1bbd0b84 282#undef FUNC_NAME
0f2d19dd 283
3b3b36dd 284SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
1bbd0b84 285 (SCM v, SCM prot),
1e6808ea
MG
286 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
287 "not. The @var{prototype} argument is used with uniform arrays\n"
288 "and is described elsewhere.")
1bbd0b84 289#define FUNC_NAME s_scm_array_p
0f2d19dd
JB
290{
291 int nprot;
292 int enclosed;
293 nprot = SCM_UNBNDP (prot);
294 enclosed = 0;
295 if (SCM_IMP (v))
296 return SCM_BOOL_F;
c209c88e
GB
297
298 while (SCM_TYP7 (v) == scm_tc7_smob)
0f2d19dd 299 {
0f2d19dd
JB
300 if (!SCM_ARRAYP (v))
301 return SCM_BOOL_F;
302 if (nprot)
303 return SCM_BOOL_T;
304 if (enclosed++)
305 return SCM_BOOL_F;
306 v = SCM_ARRAY_V (v);
c209c88e
GB
307 }
308 if (nprot)
309 return SCM_BOOL(nprot);
310 else
311 {
312 int protp = 0;
313
314 switch (SCM_TYP7 (v))
315 {
316 case scm_tc7_bvect:
9a09deb1 317 protp = (SCM_EQ_P (prot, SCM_BOOL_T));
c209c88e 318 case scm_tc7_string:
4260a7fc 319 protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
c209c88e 320 case scm_tc7_byvect:
4260a7fc 321 protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
c209c88e
GB
322 case scm_tc7_uvect:
323 protp = SCM_INUMP(prot) && SCM_INUM(prot)>0;
324 case scm_tc7_ivect:
325 protp = SCM_INUMP(prot) && SCM_INUM(prot)<=0;
326
327 case scm_tc7_svect:
328 protp = SCM_SYMBOLP (prot)
74014c46 329 && (1 == SCM_SYMBOL_LENGTH (prot))
86c991c2 330 && ('s' == SCM_SYMBOL_CHARS (prot)[0]);
2a5cd898 331#if SCM_SIZEOF_LONG_LONG != 0
c209c88e
GB
332 case scm_tc7_llvect:
333 protp = SCM_SYMBOLP (prot)
74014c46 334 && (1 == SCM_SYMBOL_LENGTH (prot))
86c991c2 335 && ('s' == SCM_SYMBOL_CHARS (prot)[0]);
0f2d19dd 336#endif
c209c88e 337 case scm_tc7_fvect:
bc86da5d 338 protp = singp (prot);
c209c88e
GB
339 case scm_tc7_dvect:
340 protp = SCM_REALP(prot);
341 case scm_tc7_cvect:
eb42e2f0 342 protp = SCM_COMPLEXP(prot);
c209c88e
GB
343 case scm_tc7_vector:
344 case scm_tc7_wvect:
345 protp = SCM_NULLP(prot);
346 default:
347 /* no default */
348 ;
349 }
350 return SCM_BOOL(protp);
0f2d19dd 351 }
0f2d19dd 352}
1bbd0b84 353#undef FUNC_NAME
0f2d19dd
JB
354
355
3b3b36dd 356SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
1bbd0b84 357 (SCM ra),
1e6808ea
MG
358 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
359 "not an array, @code{0} is returned.")
1bbd0b84 360#define FUNC_NAME s_scm_array_rank
0f2d19dd
JB
361{
362 if (SCM_IMP (ra))
1bbd0b84 363 return SCM_INUM0;
0f2d19dd
JB
364 switch (SCM_TYP7 (ra))
365 {
366 default:
367 return SCM_INUM0;
368 case scm_tc7_string:
369 case scm_tc7_vector:
95f5b0f5 370 case scm_tc7_wvect:
0f2d19dd
JB
371 case scm_tc7_byvect:
372 case scm_tc7_uvect:
373 case scm_tc7_ivect:
374 case scm_tc7_fvect:
375 case scm_tc7_cvect:
376 case scm_tc7_dvect:
2a5cd898 377#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
378 case scm_tc7_llvect:
379#endif
380 case scm_tc7_svect:
381 return SCM_MAKINUM (1L);
382 case scm_tc7_smob:
383 if (SCM_ARRAYP (ra))
384 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra));
385 return SCM_INUM0;
386 }
387}
1bbd0b84 388#undef FUNC_NAME
0f2d19dd
JB
389
390
3b3b36dd 391SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 392 (SCM ra),
b380b885
MD
393 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
394 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
1e6808ea 395 "@lisp\n"
b380b885 396 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
1e6808ea 397 "@end lisp")
1bbd0b84 398#define FUNC_NAME s_scm_array_dimensions
0f2d19dd
JB
399{
400 SCM res = SCM_EOL;
1be6b49c 401 size_t k;
92c2555f 402 scm_t_array_dim *s;
0f2d19dd 403 if (SCM_IMP (ra))
1bbd0b84 404 return SCM_BOOL_F;
0f2d19dd
JB
405 switch (SCM_TYP7 (ra))
406 {
407 default:
408 return SCM_BOOL_F;
409 case scm_tc7_string:
410 case scm_tc7_vector:
95f5b0f5 411 case scm_tc7_wvect:
0f2d19dd
JB
412 case scm_tc7_bvect:
413 case scm_tc7_byvect:
414 case scm_tc7_uvect:
415 case scm_tc7_ivect:
416 case scm_tc7_fvect:
417 case scm_tc7_cvect:
418 case scm_tc7_dvect:
419 case scm_tc7_svect:
2a5cd898 420#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
421 case scm_tc7_llvect:
422#endif
74014c46 423 return scm_cons (scm_uniform_vector_length (ra), SCM_EOL);
0f2d19dd
JB
424 case scm_tc7_smob:
425 if (!SCM_ARRAYP (ra))
426 return SCM_BOOL_F;
427 k = SCM_ARRAY_NDIM (ra);
428 s = SCM_ARRAY_DIMS (ra);
429 while (k--)
e2d37336
MD
430 res = scm_cons (s[k].lbnd
431 ? scm_cons2 (SCM_MAKINUM (s[k].lbnd),
432 SCM_MAKINUM (s[k].ubnd),
433 SCM_EOL)
434 : SCM_MAKINUM (1 + s[k].ubnd),
435 res);
0f2d19dd
JB
436 return res;
437 }
438}
1bbd0b84 439#undef FUNC_NAME
0f2d19dd
JB
440
441
e2d37336
MD
442SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
443 (SCM ra),
444 "Return the root vector of a shared array.")
445#define FUNC_NAME s_scm_shared_array_root
446{
447 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
448 return SCM_ARRAY_V (ra);
449}
450#undef FUNC_NAME
451
452
453SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
454 (SCM ra),
455 "Return the root vector index of the first element in the array.")
456#define FUNC_NAME s_scm_shared_array_offset
457{
458 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
459 return SCM_MAKINUM (SCM_ARRAY_BASE (ra));
460}
461#undef FUNC_NAME
462
463
464SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
465 (SCM ra),
466 "For each dimension, return the distance between elements in the root vector.")
467#define FUNC_NAME s_scm_shared_array_increments
468{
469 SCM res = SCM_EOL;
1be6b49c 470 size_t k;
92c2555f 471 scm_t_array_dim *s;
e2d37336
MD
472 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
473 k = SCM_ARRAY_NDIM (ra);
474 s = SCM_ARRAY_DIMS (ra);
475 while (k--)
476 res = scm_cons (SCM_MAKINUM (s[k].inc), res);
477 return res;
478}
479#undef FUNC_NAME
480
481
0f2d19dd
JB
482static char s_bad_ind[] = "Bad scm_array index";
483
1cc91f1b 484
c014a02e 485long
1bbd0b84 486scm_aind (SCM ra, SCM args, const char *what)
b3fcac34 487#define FUNC_NAME what
0f2d19dd
JB
488{
489 SCM ind;
c014a02e
ML
490 register long j;
491 register unsigned long pos = SCM_ARRAY_BASE (ra);
492 register unsigned long k = SCM_ARRAY_NDIM (ra);
92c2555f 493 scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
0f2d19dd 494 if (SCM_INUMP (args))
0f2d19dd 495 {
b3fcac34
DH
496 if (k != 1)
497 scm_error_num_args_subr (what);
0f2d19dd
JB
498 return pos + (SCM_INUM (args) - s->lbnd) * (s->inc);
499 }
1be6b49c 500 while (k && !SCM_NULLP (args))
0f2d19dd
JB
501 {
502 ind = SCM_CAR (args);
503 args = SCM_CDR (args);
b3fcac34
DH
504 if (!SCM_INUMP (ind))
505 scm_misc_error (what, s_bad_ind, SCM_EOL);
0f2d19dd 506 j = SCM_INUM (ind);
685c0d71
DH
507 if (j < s->lbnd || j > s->ubnd)
508 scm_out_of_range (what, ind);
0f2d19dd
JB
509 pos += (j - s->lbnd) * (s->inc);
510 k--;
511 s++;
512 }
b3fcac34
DH
513 if (k != 0 || !SCM_NULLP (args))
514 scm_error_num_args_subr (what);
515
0f2d19dd
JB
516 return pos;
517}
b3fcac34 518#undef FUNC_NAME
0f2d19dd 519
1cc91f1b 520
0f2d19dd 521SCM
1bbd0b84 522scm_make_ra (int ndim)
0f2d19dd
JB
523{
524 SCM ra;
0f2d19dd 525 SCM_DEFER_INTS;
92c2555f 526 SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + scm_tc16_array,
4c9419ac
MV
527 scm_gc_malloc ((sizeof (scm_t_array) +
528 ndim * sizeof (scm_t_array_dim)),
529 "array"));
0f2d19dd
JB
530 SCM_ARRAY_V (ra) = scm_nullvect;
531 SCM_ALLOW_INTS;
532 return ra;
533}
534
535static char s_bad_spec[] = "Bad scm_array dimension";
536/* Increments will still need to be set. */
537
1cc91f1b 538
0f2d19dd 539SCM
1bbd0b84 540scm_shap2ra (SCM args, const char *what)
0f2d19dd 541{
92c2555f 542 scm_t_array_dim *s;
0f2d19dd
JB
543 SCM ra, spec, sp;
544 int ndim = scm_ilength (args);
b3fcac34
DH
545 if (ndim < 0)
546 scm_misc_error (what, s_bad_spec, SCM_EOL);
547
0f2d19dd
JB
548 ra = scm_make_ra (ndim);
549 SCM_ARRAY_BASE (ra) = 0;
550 s = SCM_ARRAY_DIMS (ra);
a3a32939 551 for (; !SCM_NULLP (args); s++, args = SCM_CDR (args))
0f2d19dd
JB
552 {
553 spec = SCM_CAR (args);
a3a32939 554 if (SCM_INUMP (spec))
0f2d19dd 555 {
b3fcac34
DH
556 if (SCM_INUM (spec) < 0)
557 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
558 s->lbnd = 0;
559 s->ubnd = SCM_INUM (spec) - 1;
560 s->inc = 1;
561 }
562 else
563 {
b3fcac34
DH
564 if (!SCM_CONSP (spec) || !SCM_INUMP (SCM_CAR (spec)))
565 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
566 s->lbnd = SCM_INUM (SCM_CAR (spec));
567 sp = SCM_CDR (spec);
b3fcac34
DH
568 if (!SCM_CONSP (sp)
569 || !SCM_INUMP (SCM_CAR (sp))
570 || !SCM_NULLP (SCM_CDR (sp)))
571 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
572 s->ubnd = SCM_INUM (SCM_CAR (sp));
573 s->inc = 1;
574 }
575 }
576 return ra;
577}
578
3b3b36dd 579SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
1e6808ea 580 (SCM dims, SCM prot, SCM fill),
8f85c0c6 581 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
1e6808ea
MG
582 "Create and return a uniform array or vector of type\n"
583 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
584 "length @var{length}. If @var{fill} is supplied, it's used to\n"
585 "fill the array, otherwise @var{prototype} is used.")
1bbd0b84 586#define FUNC_NAME s_scm_dimensions_to_uniform_array
0f2d19dd 587{
1be6b49c 588 size_t k;
c014a02e 589 unsigned long rlen = 1;
92c2555f 590 scm_t_array_dim *s;
0f2d19dd 591 SCM ra;
1be6b49c 592
0f2d19dd 593 if (SCM_INUMP (dims))
cda139a7 594 {
5b9eb8ae 595 SCM answer = scm_make_uve (SCM_INUM (dims), prot);
a3a32939
DH
596 if (!SCM_UNBNDP (fill))
597 scm_array_fill_x (answer, fill);
598 else if (SCM_SYMBOLP (prot))
599 scm_array_fill_x (answer, SCM_MAKINUM (0));
600 else
601 scm_array_fill_x (answer, prot);
602 return answer;
cda139a7 603 }
1be6b49c 604
0c95b57d
GB
605 SCM_ASSERT (SCM_NULLP (dims) || SCM_CONSP (dims),
606 dims, SCM_ARG1, FUNC_NAME);
1bbd0b84 607 ra = scm_shap2ra (dims, FUNC_NAME);
e038c042 608 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
609 s = SCM_ARRAY_DIMS (ra);
610 k = SCM_ARRAY_NDIM (ra);
1be6b49c 611
0f2d19dd
JB
612 while (k--)
613 {
a3a32939
DH
614 s[k].inc = rlen;
615 SCM_ASSERT_RANGE (1, dims, s[k].lbnd <= s[k].ubnd);
0f2d19dd 616 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
0f2d19dd 617 }
a3a32939 618
a3a32939
DH
619 SCM_ARRAY_V (ra) = scm_make_uve (rlen, prot);
620
5c11cc9d 621 if (!SCM_UNBNDP (fill))
a3a32939 622 scm_array_fill_x (ra, fill);
0c95b57d 623 else if (SCM_SYMBOLP (prot))
0f2d19dd
JB
624 scm_array_fill_x (ra, SCM_MAKINUM (0));
625 else
626 scm_array_fill_x (ra, prot);
a3a32939 627
0f2d19dd 628 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
c014a02e 629 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
0f2d19dd
JB
630 return SCM_ARRAY_V (ra);
631 return ra;
632}
1bbd0b84 633#undef FUNC_NAME
0f2d19dd 634
1cc91f1b 635
0f2d19dd 636void
1bbd0b84 637scm_ra_set_contp (SCM ra)
0f2d19dd 638{
1be6b49c 639 size_t k = SCM_ARRAY_NDIM (ra);
0f2d19dd 640 if (k)
0f2d19dd 641 {
c014a02e 642 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
fe0c6dae 643 while (k--)
0f2d19dd 644 {
fe0c6dae
JB
645 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
646 {
e038c042 647 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
fe0c6dae
JB
648 return;
649 }
650 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
651 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 652 }
0f2d19dd 653 }
e038c042 654 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
0f2d19dd
JB
655}
656
657
3b3b36dd 658SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 659 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
660 "@code{make-shared-array} can be used to create shared subarrays of other\n"
661 "arrays. The @var{mapper} is a function that translates coordinates in\n"
662 "the new array into coordinates in the old array. A @var{mapper} must be\n"
663 "linear, and its range must stay within the bounds of the old array, but\n"
664 "it can be otherwise arbitrary. A simple example:\n"
1e6808ea 665 "@lisp\n"
b380b885
MD
666 "(define fred (make-array #f 8 8))\n"
667 "(define freds-diagonal\n"
668 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
669 "(array-set! freds-diagonal 'foo 3)\n"
670 "(array-ref fred 3 3) @result{} foo\n"
671 "(define freds-center\n"
672 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
673 "(array-ref freds-center 0 0) @result{} foo\n"
1e6808ea 674 "@end lisp")
1bbd0b84 675#define FUNC_NAME s_scm_make_shared_array
0f2d19dd
JB
676{
677 SCM ra;
678 SCM inds, indptr;
679 SCM imap;
c014a02e
ML
680 size_t k, i;
681 long old_min, new_min, old_max, new_max;
92c2555f 682 scm_t_array_dim *s;
b3fcac34
DH
683
684 SCM_VALIDATE_REST_ARGUMENT (dims);
34d19ef6
HWN
685 SCM_VALIDATE_ARRAY (1, oldra);
686 SCM_VALIDATE_PROC (2, mapfunc);
1bbd0b84 687 ra = scm_shap2ra (dims, FUNC_NAME);
0f2d19dd
JB
688 if (SCM_ARRAYP (oldra))
689 {
690 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
691 old_min = old_max = SCM_ARRAY_BASE (oldra);
692 s = SCM_ARRAY_DIMS (oldra);
693 k = SCM_ARRAY_NDIM (oldra);
694 while (k--)
695 {
696 if (s[k].inc > 0)
697 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
698 else
699 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
700 }
701 }
702 else
703 {
704 SCM_ARRAY_V (ra) = oldra;
705 old_min = 0;
74014c46 706 old_max = SCM_INUM (scm_uniform_vector_length (oldra)) - 1;
0f2d19dd
JB
707 }
708 inds = SCM_EOL;
709 s = SCM_ARRAY_DIMS (ra);
710 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
711 {
712 inds = scm_cons (SCM_MAKINUM (s[k].lbnd), inds);
713 if (s[k].ubnd < s[k].lbnd)
714 {
715 if (1 == SCM_ARRAY_NDIM (ra))
716 ra = scm_make_uve (0L, scm_array_prototype (ra));
717 else
718 SCM_ARRAY_V (ra) = scm_make_uve (0L, scm_array_prototype (ra));
719 return ra;
720 }
721 }
fdc28395 722 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd 723 if (SCM_ARRAYP (oldra))
c014a02e 724 i = (size_t) scm_aind (oldra, imap, FUNC_NAME);
0f2d19dd
JB
725 else
726 {
727 if (SCM_NINUMP (imap))
728
729 {
b3fcac34
DH
730 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
731 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
732 imap = SCM_CAR (imap);
733 }
734 i = SCM_INUM (imap);
735 }
736 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
737 indptr = inds;
738 k = SCM_ARRAY_NDIM (ra);
739 while (k--)
740 {
741 if (s[k].ubnd > s[k].lbnd)
742 {
898a256f 743 SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
fdc28395 744 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd
JB
745 if (SCM_ARRAYP (oldra))
746
1bbd0b84 747 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
748 else
749 {
750 if (SCM_NINUMP (imap))
0f2d19dd 751 {
b3fcac34
DH
752 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
753 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
754 imap = SCM_CAR (imap);
755 }
756 s[k].inc = (long) SCM_INUM (imap) - i;
757 }
758 i += s[k].inc;
759 if (s[k].inc > 0)
760 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
761 else
762 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
763 }
764 else
765 s[k].inc = new_max - new_min + 1; /* contiguous by default */
766 indptr = SCM_CDR (indptr);
767 }
b3fcac34
DH
768 if (old_min > new_min || old_max < new_max)
769 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
770 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
771 {
74014c46 772 SCM v = SCM_ARRAY_V (ra);
c014a02e 773 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
774 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
775 return v;
0f2d19dd
JB
776 if (s->ubnd < s->lbnd)
777 return scm_make_uve (0L, scm_array_prototype (ra));
778 }
779 scm_ra_set_contp (ra);
780 return ra;
781}
1bbd0b84 782#undef FUNC_NAME
0f2d19dd
JB
783
784
785/* args are RA . DIMS */
af45e3b0
DH
786SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
787 (SCM ra, SCM args),
1e6808ea
MG
788 "Return an array sharing contents with @var{array}, but with\n"
789 "dimensions arranged in a different order. There must be one\n"
790 "@var{dim} argument for each dimension of @var{array}.\n"
791 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
792 "and the rank of the array to be returned. Each integer in that\n"
793 "range must appear at least once in the argument list.\n"
794 "\n"
795 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
796 "dimensions in the array to be returned, their positions in the\n"
797 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
798 "may have the same value, in which case the returned array will\n"
799 "have smaller rank than @var{array}.\n"
800 "\n"
801 "@lisp\n"
b380b885
MD
802 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
803 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
804 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
805 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 806 "@end lisp")
1bbd0b84 807#define FUNC_NAME s_scm_transpose_array
0f2d19dd 808{
34d19ef6
HWN
809 SCM res, vargs;
810 SCM const *ve = &vargs;
92c2555f 811 scm_t_array_dim *s, *r;
0f2d19dd 812 int ndim, i, k;
af45e3b0 813
b3fcac34 814 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 815 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
f5bf2977 816 switch (SCM_TYP7 (ra))
0f2d19dd
JB
817 {
818 default:
276dd677 819 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
820 case scm_tc7_bvect:
821 case scm_tc7_string:
822 case scm_tc7_byvect:
823 case scm_tc7_uvect:
824 case scm_tc7_ivect:
825 case scm_tc7_fvect:
826 case scm_tc7_dvect:
827 case scm_tc7_cvect:
828 case scm_tc7_svect:
2a5cd898 829#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
830 case scm_tc7_llvect:
831#endif
b3fcac34
DH
832 if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
833 SCM_WRONG_NUM_ARGS ();
834 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CAR (args));
685c0d71
DH
835 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args),
836 SCM_EQ_P (SCM_INUM0, SCM_CAR (args)));
0f2d19dd
JB
837 return ra;
838 case scm_tc7_smob:
839 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
840 vargs = scm_vector (args);
b3fcac34
DH
841 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
842 SCM_WRONG_NUM_ARGS ();
843 ve = SCM_VELTS (vargs);
0f2d19dd
JB
844 ndim = 0;
845 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
846 {
20a54673 847 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 848 FUNC_NAME);
0f2d19dd 849 i = SCM_INUM (ve[k]);
685c0d71
DH
850 if (i < 0 || i >= SCM_ARRAY_NDIM (ra))
851 scm_out_of_range (FUNC_NAME, ve[k]);
0f2d19dd
JB
852 if (ndim < i)
853 ndim = i;
854 }
855 ndim++;
856 res = scm_make_ra (ndim);
857 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
858 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
859 for (k = ndim; k--;)
860 {
861 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
862 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
863 }
864 for (k = SCM_ARRAY_NDIM (ra); k--;)
865 {
866 i = SCM_INUM (ve[k]);
867 s = &(SCM_ARRAY_DIMS (ra)[k]);
868 r = &(SCM_ARRAY_DIMS (res)[i]);
869 if (r->ubnd < r->lbnd)
870 {
871 r->lbnd = s->lbnd;
872 r->ubnd = s->ubnd;
873 r->inc = s->inc;
874 ndim--;
875 }
876 else
877 {
878 if (r->ubnd > s->ubnd)
879 r->ubnd = s->ubnd;
880 if (r->lbnd < s->lbnd)
881 {
882 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
883 r->lbnd = s->lbnd;
884 }
885 r->inc += s->inc;
886 }
887 }
b3fcac34
DH
888 if (ndim > 0)
889 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
890 scm_ra_set_contp (res);
891 return res;
892 }
893}
1bbd0b84 894#undef FUNC_NAME
0f2d19dd
JB
895
896/* args are RA . AXES */
af45e3b0
DH
897SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
898 (SCM ra, SCM axes),
b380b885
MD
899 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
900 "the rank of @var{array}. @var{enclose-array} returns an array\n"
901 "resembling an array of shared arrays. The dimensions of each shared\n"
902 "array are the same as the @var{dim}th dimensions of the original array,\n"
903 "the dimensions of the outer array are the same as those of the original\n"
904 "array that did not match a @var{dim}.\n\n"
905 "An enclosed array is not a general Scheme array. Its elements may not\n"
906 "be set using @code{array-set!}. Two references to the same element of\n"
907 "an enclosed array will be @code{equal?} but will not in general be\n"
908 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
909 "enclosed array is unspecified.\n\n"
910 "examples:\n"
1e6808ea 911 "@lisp\n"
b380b885
MD
912 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
913 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
914 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
915 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 916 "@end lisp")
1bbd0b84 917#define FUNC_NAME s_scm_enclose_array
0f2d19dd 918{
af45e3b0 919 SCM axv, res, ra_inr;
92c2555f 920 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 921 int ndim, j, k, ninr, noutr;
af45e3b0 922
b3fcac34 923 SCM_VALIDATE_REST_ARGUMENT (axes);
0f2d19dd 924 if (SCM_NULLP (axes))
0f2d19dd
JB
925 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
926 ninr = scm_ilength (axes);
b3fcac34
DH
927 if (ninr < 0)
928 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
929 ra_inr = scm_make_ra (ninr);
930 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
74014c46 931 switch SCM_TYP7 (ra)
0f2d19dd
JB
932 {
933 default:
276dd677 934 badarg1:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
935 case scm_tc7_string:
936 case scm_tc7_bvect:
937 case scm_tc7_byvect:
938 case scm_tc7_uvect:
939 case scm_tc7_ivect:
940 case scm_tc7_fvect:
941 case scm_tc7_dvect:
942 case scm_tc7_cvect:
943 case scm_tc7_vector:
95f5b0f5 944 case scm_tc7_wvect:
0f2d19dd 945 case scm_tc7_svect:
2a5cd898 946#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
947 case scm_tc7_llvect:
948#endif
949 s->lbnd = 0;
74014c46 950 s->ubnd = SCM_INUM (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
951 s->inc = 1;
952 SCM_ARRAY_V (ra_inr) = ra;
953 SCM_ARRAY_BASE (ra_inr) = 0;
954 ndim = 1;
955 break;
956 case scm_tc7_smob:
957 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
958 s = SCM_ARRAY_DIMS (ra);
959 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
960 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
961 ndim = SCM_ARRAY_NDIM (ra);
962 break;
963 }
964 noutr = ndim - ninr;
b3fcac34
DH
965 if (noutr < 0)
966 SCM_WRONG_NUM_ARGS ();
7866a09b 967 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
0f2d19dd
JB
968 res = scm_make_ra (noutr);
969 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
970 SCM_ARRAY_V (res) = ra_inr;
971 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
972 {
b3fcac34
DH
973 if (!SCM_INUMP (SCM_CAR (axes)))
974 SCM_MISC_ERROR ("bad axis", SCM_EOL);
0f2d19dd
JB
975 j = SCM_INUM (SCM_CAR (axes));
976 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
977 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
978 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
405aaef9 979 SCM_STRING_CHARS (axv)[j] = 1;
0f2d19dd
JB
980 }
981 for (j = 0, k = 0; k < noutr; k++, j++)
982 {
405aaef9 983 while (SCM_STRING_CHARS (axv)[j])
0f2d19dd
JB
984 j++;
985 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
986 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
987 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
988 }
989 scm_ra_set_contp (ra_inr);
990 scm_ra_set_contp (res);
991 return res;
992}
1bbd0b84 993#undef FUNC_NAME
0f2d19dd
JB
994
995
996
af45e3b0
DH
997SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
998 (SCM v, SCM args),
1e6808ea
MG
999 "Return @code{#t} if its arguments would be acceptable to\n"
1000 "@code{array-ref}.")
1bbd0b84 1001#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 1002{
af45e3b0 1003 SCM ind = SCM_EOL;
c014a02e 1004 long pos = 0;
1be6b49c 1005 register size_t k;
c014a02e 1006 register long j;
92c2555f 1007 scm_t_array_dim *s;
af45e3b0 1008
b3fcac34 1009 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
1010 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1011 if (SCM_NIMP (args))
1012
1013 {
1014 ind = SCM_CAR (args);
1015 args = SCM_CDR (args);
1bbd0b84 1016 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1017 pos = SCM_INUM (ind);
1018 }
1019tail:
74014c46 1020 switch SCM_TYP7 (v)
0f2d19dd
JB
1021 {
1022 default:
276dd677 1023 badarg1:SCM_WRONG_TYPE_ARG (1, v);
b3fcac34 1024 wna: SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1025 case scm_tc7_smob:
1026 k = SCM_ARRAY_NDIM (v);
1027 s = SCM_ARRAY_DIMS (v);
1028 pos = SCM_ARRAY_BASE (v);
1029 if (!k)
1030 {
1031 SCM_ASRTGO (SCM_NULLP (ind), wna);
1032 ind = SCM_INUM0;
1033 }
1034 else
1035 while (!0)
1036 {
1037 j = SCM_INUM (ind);
1038 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1039 {
1040 SCM_ASRTGO (--k == scm_ilength (args), wna);
1041 return SCM_BOOL_F;
1042 }
1043 pos += (j - s->lbnd) * (s->inc);
1044 if (!(--k && SCM_NIMP (args)))
1045 break;
1046 ind = SCM_CAR (args);
1047 args = SCM_CDR (args);
1048 s++;
b3fcac34
DH
1049 if (!SCM_INUMP (ind))
1050 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
1051 }
1052 SCM_ASRTGO (0 == k, wna);
1053 v = SCM_ARRAY_V (v);
1054 goto tail;
1055 case scm_tc7_bvect:
1056 case scm_tc7_string:
1057 case scm_tc7_byvect:
1058 case scm_tc7_uvect:
1059 case scm_tc7_ivect:
1060 case scm_tc7_fvect:
1061 case scm_tc7_dvect:
1062 case scm_tc7_cvect:
1063 case scm_tc7_svect:
2a5cd898 1064#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
1065 case scm_tc7_llvect:
1066#endif
1067 case scm_tc7_vector:
95f5b0f5 1068 case scm_tc7_wvect:
74014c46 1069 {
c014a02e 1070 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1071 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1072 return SCM_BOOL(pos >= 0 && pos < length);
1073 }
0f2d19dd
JB
1074 }
1075}
1bbd0b84 1076#undef FUNC_NAME
0f2d19dd
JB
1077
1078
1bbd0b84 1079SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1080
1bbd0b84 1081
3b3b36dd 1082SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1083 (SCM v, SCM args),
8f85c0c6 1084 "@deffnx {Scheme Procedure} array-ref v . args\n"
1e6808ea
MG
1085 "Return the element at the @code{(index1, index2)} element in\n"
1086 "@var{array}.")
1bbd0b84 1087#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd 1088{
c014a02e 1089 long pos;
0f2d19dd 1090
35de7ebe 1091 if (SCM_IMP (v))
0f2d19dd
JB
1092 {
1093 SCM_ASRTGO (SCM_NULLP (args), badarg);
1094 return v;
1095 }
1096 else if (SCM_ARRAYP (v))
0f2d19dd 1097 {
1bbd0b84 1098 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1099 v = SCM_ARRAY_V (v);
1100 }
1101 else
1102 {
c014a02e 1103 unsigned long int length;
0f2d19dd 1104 if (SCM_NIMP (args))
0f2d19dd 1105 {
1bbd0b84 1106 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1107 pos = SCM_INUM (SCM_CAR (args));
1108 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1109 }
1110 else
1111 {
34d19ef6 1112 SCM_VALIDATE_INUM (2, args);
0f2d19dd
JB
1113 pos = SCM_INUM (args);
1114 }
74014c46
DH
1115 length = SCM_INUM (scm_uniform_vector_length (v));
1116 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1117 }
74014c46 1118 switch SCM_TYP7 (v)
0f2d19dd
JB
1119 {
1120 default:
1121 if (SCM_NULLP (args))
1122 return v;
35de7ebe 1123 badarg:
276dd677
DH
1124 SCM_WRONG_TYPE_ARG (1, v);
1125 /* not reached */
c209c88e
GB
1126
1127 outrng:
1128 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1129 wna:
b3fcac34 1130 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1131 case scm_tc7_smob:
1132 { /* enclosed */
1133 int k = SCM_ARRAY_NDIM (v);
1134 SCM res = scm_make_ra (k);
1135 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1136 SCM_ARRAY_BASE (res) = pos;
1137 while (k--)
1138 {
1139 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1140 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1141 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1142 }
1143 return res;
1144 }
1145 case scm_tc7_bvect:
c209c88e 1146 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1147 return SCM_BOOL_T;
1148 else
1149 return SCM_BOOL_F;
1150 case scm_tc7_string:
322ac0c5 1151 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1152 case scm_tc7_byvect:
405aaef9 1153 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1154 case scm_tc7_uvect:
fee7ef83 1155 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1156 case scm_tc7_ivect:
1be6b49c 1157 return scm_long2num (((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1158
1159 case scm_tc7_svect:
4260a7fc 1160 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
2a5cd898 1161#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1162 case scm_tc7_llvect:
1be6b49c 1163 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1164#endif
1165
0f2d19dd 1166 case scm_tc7_fvect:
4260a7fc 1167 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1168 case scm_tc7_dvect:
4260a7fc 1169 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1170 case scm_tc7_cvect:
4260a7fc
DH
1171 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1172 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1173 case scm_tc7_vector:
95f5b0f5 1174 case scm_tc7_wvect:
0f2d19dd
JB
1175 return SCM_VELTS (v)[pos];
1176 }
1177}
1bbd0b84 1178#undef FUNC_NAME
0f2d19dd
JB
1179
1180/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1181 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1182
0f2d19dd 1183SCM
c014a02e 1184scm_cvref (SCM v, unsigned long pos, SCM last)
db4b4ca6 1185#define FUNC_NAME "scm_cvref"
0f2d19dd 1186{
5c11cc9d 1187 switch SCM_TYP7 (v)
0f2d19dd
JB
1188 {
1189 default:
db4b4ca6 1190 SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd 1191 case scm_tc7_bvect:
34d19ef6 1192 if (SCM_BITVEC_REF(v, pos))
0f2d19dd
JB
1193 return SCM_BOOL_T;
1194 else
1195 return SCM_BOOL_F;
1196 case scm_tc7_string:
322ac0c5 1197 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1198 case scm_tc7_byvect:
405aaef9 1199 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1200 case scm_tc7_uvect:
fee7ef83 1201 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1202 case scm_tc7_ivect:
fee7ef83 1203 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1204 case scm_tc7_svect:
4260a7fc 1205 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
2a5cd898 1206#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1207 case scm_tc7_llvect:
1be6b49c 1208 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1209#endif
0f2d19dd 1210 case scm_tc7_fvect:
fee7ef83 1211 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1212 {
4260a7fc 1213 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1214 return last;
1215 }
4260a7fc 1216 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1217 case scm_tc7_dvect:
fee7ef83 1218 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1219 {
4260a7fc 1220 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1221 return last;
1222 }
4260a7fc 1223 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1224 case scm_tc7_cvect:
bc86da5d 1225 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1226 {
4260a7fc
DH
1227 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1228 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1229 return last;
1230 }
4260a7fc
DH
1231 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1232 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1233 case scm_tc7_vector:
95f5b0f5 1234 case scm_tc7_wvect:
0f2d19dd
JB
1235 return SCM_VELTS (v)[pos];
1236 case scm_tc7_smob:
1237 { /* enclosed scm_array */
1238 int k = SCM_ARRAY_NDIM (v);
1239 SCM res = scm_make_ra (k);
1240 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1241 SCM_ARRAY_BASE (res) = pos;
1242 while (k--)
1243 {
1244 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1245 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1246 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1247 }
1248 return res;
1249 }
1250 }
1251}
db4b4ca6
DH
1252#undef FUNC_NAME
1253
0f2d19dd 1254
1bbd0b84
GB
1255SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1256
1cc91f1b 1257
0aa0871f
GH
1258/* Note that args may be a list or an immediate object, depending which
1259 PROC is used (and it's called from C too). */
3b3b36dd 1260SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1261 (SCM v, SCM obj, SCM args),
8f85c0c6
NJ
1262 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1263 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1264 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1265#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1266{
c014a02e 1267 long pos = 0;
b3fcac34 1268
0f2d19dd
JB
1269 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1270 if (SCM_ARRAYP (v))
0f2d19dd 1271 {
1bbd0b84 1272 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1273 v = SCM_ARRAY_V (v);
1274 }
1275 else
1276 {
c014a02e 1277 unsigned long int length;
9a97e362 1278 if (SCM_CONSP (args))
0f2d19dd 1279 {
9a97e362 1280 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), args, SCM_ARG3, FUNC_NAME);
0f2d19dd 1281 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1282 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1283 }
1284 else
1285 {
34d19ef6 1286 SCM_VALIDATE_INUM_COPY (3, args, pos);
0f2d19dd 1287 }
74014c46
DH
1288 length = SCM_INUM (scm_uniform_vector_length (v));
1289 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd
JB
1290 }
1291 switch (SCM_TYP7 (v))
1292 {
35de7ebe 1293 default: badarg1:
276dd677
DH
1294 SCM_WRONG_TYPE_ARG (1, v);
1295 /* not reached */
c209c88e
GB
1296 outrng:
1297 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1298 wna:
b3fcac34 1299 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1300 case scm_tc7_smob: /* enclosed */
1301 goto badarg1;
1302 case scm_tc7_bvect:
4260a7fc 1303 if (SCM_FALSEP (obj))
34d19ef6 1304 SCM_BITVEC_CLR(v, pos);
9a09deb1 1305 else if (SCM_EQ_P (obj, SCM_BOOL_T))
34d19ef6 1306 SCM_BITVEC_SET(v, pos);
0f2d19dd 1307 else
276dd677 1308 badobj:SCM_WRONG_TYPE_ARG (2, obj);
0f2d19dd
JB
1309 break;
1310 case scm_tc7_string:
7866a09b 1311 SCM_ASRTGO (SCM_CHARP (obj), badobj);
322ac0c5 1312 SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1313 break;
1314 case scm_tc7_byvect:
7866a09b
GB
1315 if (SCM_CHARP (obj))
1316 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1317 SCM_ASRTGO (SCM_INUMP (obj), badobj);
405aaef9 1318 ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1319 break;
1bbd0b84 1320 case scm_tc7_uvect:
729dbac3
DH
1321 ((unsigned long *) SCM_UVECTOR_BASE (v))[pos]
1322 = scm_num2ulong (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1323 break;
1bbd0b84 1324 case scm_tc7_ivect:
729dbac3
DH
1325 ((long *) SCM_UVECTOR_BASE (v))[pos]
1326 = scm_num2long (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1327 break;
0f2d19dd 1328 case scm_tc7_svect:
0aa0871f 1329 SCM_ASRTGO (SCM_INUMP (obj), badobj);
729dbac3 1330 ((short *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1331 break;
2a5cd898 1332#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1333 case scm_tc7_llvect:
729dbac3
DH
1334 ((long long *) SCM_UVECTOR_BASE (v))[pos]
1335 = scm_num2long_long (obj, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1336 break;
1337#endif
0f2d19dd 1338 case scm_tc7_fvect:
729dbac3
DH
1339 ((float *) SCM_UVECTOR_BASE (v))[pos]
1340 = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1341 break;
0f2d19dd 1342 case scm_tc7_dvect:
729dbac3
DH
1343 ((double *) SCM_UVECTOR_BASE (v))[pos]
1344 = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1345 break;
1346 case scm_tc7_cvect:
eb42e2f0
DH
1347 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1348 if (SCM_REALP (obj)) {
729dbac3
DH
1349 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_REAL_VALUE (obj);
1350 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = 0.0;
eb42e2f0 1351 } else {
729dbac3
DH
1352 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1353 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
eb42e2f0 1354 }
0f2d19dd 1355 break;
0f2d19dd 1356 case scm_tc7_vector:
95f5b0f5 1357 case scm_tc7_wvect:
34d19ef6 1358 SCM_VECTOR_SET (v, pos, obj);
0f2d19dd
JB
1359 break;
1360 }
1361 return SCM_UNSPECIFIED;
1362}
1bbd0b84 1363#undef FUNC_NAME
0f2d19dd 1364
1d7bdb25
GH
1365/* attempts to unroll an array into a one-dimensional array.
1366 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1367 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1368 wouldn't have contiguous elements. */
3b3b36dd 1369SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1370 (SCM ra, SCM strict),
b380b885
MD
1371 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1372 "without changing their order (last subscript changing fastest), then\n"
1373 "@code{array-contents} returns that shared array, otherwise it returns\n"
1374 "@code{#f}. All arrays made by @var{make-array} and\n"
1375 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1376 "@var{make-shared-array} may not be.\n\n"
1377 "If the optional argument @var{strict} is provided, a shared array will\n"
1378 "be returned only if its elements are stored internally contiguous in\n"
1379 "memory.")
1bbd0b84 1380#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1381{
1382 SCM sra;
1383 if (SCM_IMP (ra))
f3667f52 1384 return SCM_BOOL_F;
5c11cc9d 1385 switch SCM_TYP7 (ra)
0f2d19dd
JB
1386 {
1387 default:
1388 return SCM_BOOL_F;
1389 case scm_tc7_vector:
95f5b0f5 1390 case scm_tc7_wvect:
0f2d19dd
JB
1391 case scm_tc7_string:
1392 case scm_tc7_bvect:
1393 case scm_tc7_byvect:
1394 case scm_tc7_uvect:
1395 case scm_tc7_ivect:
1396 case scm_tc7_fvect:
1397 case scm_tc7_dvect:
1398 case scm_tc7_cvect:
1399 case scm_tc7_svect:
2a5cd898 1400#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
1401 case scm_tc7_llvect:
1402#endif
1403 return ra;
1404 case scm_tc7_smob:
1405 {
c014a02e 1406 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
0f2d19dd
JB
1407 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1408 return SCM_BOOL_F;
1409 for (k = 0; k < ndim; k++)
1410 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1411 if (!SCM_UNBNDP (strict))
1412 {
0f2d19dd
JB
1413 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1414 return SCM_BOOL_F;
1415 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1416 {
74014c46 1417 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
c014a02e
ML
1418 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1419 len % SCM_LONG_BIT)
0f2d19dd
JB
1420 return SCM_BOOL_F;
1421 }
1422 }
74014c46
DH
1423
1424 {
1425 SCM v = SCM_ARRAY_V (ra);
c014a02e 1426 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1427 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1428 return v;
1429 }
1430
0f2d19dd
JB
1431 sra = scm_make_ra (1);
1432 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1433 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1434 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1435 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1436 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1437 return sra;
1438 }
1439 }
1440}
1bbd0b84 1441#undef FUNC_NAME
0f2d19dd 1442
1cc91f1b 1443
0f2d19dd 1444SCM
6e8d25a6 1445scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1446{
1447 SCM ret;
c014a02e
ML
1448 long inc = 1;
1449 size_t k, len = 1;
0f2d19dd
JB
1450 for (k = SCM_ARRAY_NDIM (ra); k--;)
1451 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1452 k = SCM_ARRAY_NDIM (ra);
1453 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1454 {
74014c46 1455 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1456 return ra;
74014c46 1457 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1458 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1459 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1460 return ra;
1461 }
1462 ret = scm_make_ra (k);
1463 SCM_ARRAY_BASE (ret) = 0;
1464 while (k--)
1465 {
1466 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1467 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1468 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1469 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1470 }
08112c95 1471 SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
0f2d19dd
JB
1472 if (copy)
1473 scm_array_copy_x (ra, ret);
1474 return ret;
1475}
1476
1477
1478
3b3b36dd 1479SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1480 (SCM ra, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1481 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1482 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1483 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1484 "If an end of file is encountered,\n"
1485 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1486 "(starting at the beginning) and the remainder of the array is\n"
1487 "unchanged.\n\n"
1488 "The optional arguments @var{start} and @var{end} allow\n"
1489 "a specified region of a vector (or linearized array) to be read,\n"
1490 "leaving the remainder of the vector unchanged.\n\n"
1491 "@code{uniform-array-read!} returns the number of objects read.\n"
1492 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1493 "returned by @code{(current-input-port)}.")
1bbd0b84 1494#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1495{
35de7ebe 1496 SCM cra = SCM_UNDEFINED, v = ra;
c014a02e
ML
1497 long sz, vlen, ans;
1498 long cstart = 0;
1499 long cend;
1500 long offset = 0;
405aaef9 1501 char *base;
35de7ebe 1502
0f2d19dd 1503 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1504 if (SCM_UNBNDP (port_or_fd))
1505 port_or_fd = scm_cur_inp;
1506 else
1507 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1508 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1509 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1510 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1511 ? 0
1512 : SCM_INUM (scm_uniform_vector_length (v)));
35de7ebe 1513
0f2d19dd 1514loop:
35de7ebe 1515 switch SCM_TYP7 (v)
0f2d19dd
JB
1516 {
1517 default:
276dd677 1518 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd
JB
1519 case scm_tc7_smob:
1520 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1521 cra = scm_ra2contig (ra, 0);
1146b6cd 1522 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1523 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1524 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1525 v = SCM_ARRAY_V (cra);
1526 goto loop;
1527 case scm_tc7_string:
74014c46 1528 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1529 sz = sizeof (char);
1530 break;
1531 case scm_tc7_bvect:
74014c46 1532 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1533 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1534 cstart /= SCM_LONG_BIT;
1535 sz = sizeof (long);
74014c46
DH
1536 break;
1537 case scm_tc7_byvect:
1538 base = (char *) SCM_UVECTOR_BASE (v);
1539 sz = sizeof (char);
1540 break;
0f2d19dd
JB
1541 case scm_tc7_uvect:
1542 case scm_tc7_ivect:
74014c46 1543 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1544 sz = sizeof (long);
1545 break;
1546 case scm_tc7_svect:
74014c46 1547 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1548 sz = sizeof (short);
1549 break;
2a5cd898 1550#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1551 case scm_tc7_llvect:
74014c46 1552 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1553 sz = sizeof (long long);
0f2d19dd
JB
1554 break;
1555#endif
0f2d19dd 1556 case scm_tc7_fvect:
74014c46 1557 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1558 sz = sizeof (float);
1559 break;
0f2d19dd 1560 case scm_tc7_dvect:
74014c46 1561 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1562 sz = sizeof (double);
1563 break;
1564 case scm_tc7_cvect:
74014c46 1565 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1566 sz = 2 * sizeof (double);
1567 break;
0f2d19dd 1568 }
405aaef9 1569
1146b6cd
GH
1570 cend = vlen;
1571 if (!SCM_UNBNDP (start))
3d8d56df 1572 {
1146b6cd 1573 offset =
c014a02e 1574 SCM_NUM2LONG (3, start);
35de7ebe 1575
1146b6cd 1576 if (offset < 0 || offset >= cend)
1bbd0b84 1577 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1578
1579 if (!SCM_UNBNDP (end))
1580 {
c014a02e
ML
1581 long tend =
1582 SCM_NUM2LONG (4, end);
3d8d56df 1583
1146b6cd 1584 if (tend <= offset || tend > cend)
1bbd0b84 1585 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1586 cend = tend;
1587 }
0f2d19dd 1588 }
35de7ebe 1589
3d8d56df
GH
1590 if (SCM_NIMP (port_or_fd))
1591 {
92c2555f 1592 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1593 int remaining = (cend - offset) * sz;
405aaef9 1594 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1595
1596 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1597 scm_flush (port_or_fd);
6c951427
GH
1598
1599 ans = cend - offset;
1600 while (remaining > 0)
3d8d56df 1601 {
6c951427
GH
1602 if (pt->read_pos < pt->read_end)
1603 {
1604 int to_copy = min (pt->read_end - pt->read_pos,
1605 remaining);
1606
1607 memcpy (dest, pt->read_pos, to_copy);
1608 pt->read_pos += to_copy;
1609 remaining -= to_copy;
1610 dest += to_copy;
1611 }
1612 else
1613 {
affc96b5 1614 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1615 {
1616 if (remaining % sz != 0)
1617 {
5d2d2ffc 1618 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1619 }
1620 ans -= remaining / sz;
1621 break;
1622 }
6c951427 1623 }
3d8d56df 1624 }
6c951427
GH
1625
1626 if (pt->rw_random)
1627 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1628 }
1629 else /* file descriptor. */
1630 {
1631 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1632 base + (cstart + offset) * sz,
1be6b49c 1633 (sz * (cend - offset))));
3d8d56df 1634 if (ans == -1)
1bbd0b84 1635 SCM_SYSERROR;
3d8d56df 1636 }
0f2d19dd 1637 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1638 ans *= SCM_LONG_BIT;
35de7ebe 1639
fee7ef83 1640 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1641 scm_array_copy_x (cra, ra);
35de7ebe 1642
0f2d19dd
JB
1643 return SCM_MAKINUM (ans);
1644}
1bbd0b84 1645#undef FUNC_NAME
0f2d19dd 1646
3b3b36dd 1647SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1648 (SCM v, SCM port_or_fd, SCM start, SCM end),
8f85c0c6 1649 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
b380b885
MD
1650 "Writes all elements of @var{ura} as binary objects to\n"
1651 "@var{port-or-fdes}.\n\n"
1652 "The optional arguments @var{start}\n"
1653 "and @var{end} allow\n"
1654 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1655 "The number of objects actually written is returned.\n"
b380b885
MD
1656 "@var{port-or-fdes} may be\n"
1657 "omitted, in which case it defaults to the value returned by\n"
1658 "@code{(current-output-port)}.")
1bbd0b84 1659#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1660{
c014a02e
ML
1661 long sz, vlen, ans;
1662 long offset = 0;
1663 long cstart = 0;
1664 long cend;
405aaef9 1665 char *base;
3d8d56df 1666
78446828
MV
1667 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1668
0f2d19dd 1669 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1670 if (SCM_UNBNDP (port_or_fd))
1671 port_or_fd = scm_cur_outp;
1672 else
1673 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1674 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1675 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1676 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1677 ? 0
1678 : SCM_INUM (scm_uniform_vector_length (v)));
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);
d245ce23
MD
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;
2a5cd898 1716#if SCM_SIZEOF_LONG_LONG != 0
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);
34d19ef6 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"
8f85c0c6 1889 "If uve is a unsigned long integer vector all the elements of uve\n"
c7eb8761
MG
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));
34d19ef6 1910 SCM_BITVEC_CLR(v, k);
74014c46
DH
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));
34d19ef6 1918 SCM_BITVEC_SET(v, k);
74014c46
DH
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));
34d19ef6 1968 if (!SCM_BITVEC_REF(v, k))
74014c46
DH
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));
34d19ef6 1977 if (SCM_BITVEC_REF (v, k))
74014c46
DH
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),
8f85c0c6 2010 "Modify @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
34d19ef6 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
cd328b4f 2086SCM_DEFINE (scm_array_to_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}.")
cd328b4f 2090#define FUNC_NAME s_scm_array_to_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 }
2a5cd898 2147#if SCM_SIZEOF_LONG_LONG != 0
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),
8f85c0c6 2186 "@deffnx {Scheme 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;
34d19ef6 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
34d19ef6 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;
2a5cd898 2516#if SCM_SIZEOF_LONG_LONG != 0
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");
2a5cd898 2572#if SCM_SIZEOF_LONG_LONG != 0
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{
4c9419ac
MV
2597 scm_gc_free (SCM_ARRAY_MEM (ptr),
2598 (sizeof (scm_t_array)
2599 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2600 "array");
2601 return 0;
0f2d19dd
JB
2602}
2603
0f2d19dd
JB
2604void
2605scm_init_unif ()
0f2d19dd 2606{
e841c3e0
KN
2607 scm_tc16_array = scm_make_smob_type ("array", 0);
2608 scm_set_smob_mark (scm_tc16_array, array_mark);
2609 scm_set_smob_free (scm_tc16_array, array_free);
2610 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2611 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
0f2d19dd 2612 scm_add_feature ("array");
a0599745 2613#include "libguile/unif.x"
0f2d19dd 2614}
89e00824
ML
2615
2616/*
2617 Local Variables:
2618 c-file-style: "gnu"
2619 End:
2620*/