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