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