(scm_is_eq): 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
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{
144 SCM_ASSERT_RANGE (1, scm_long2num (k), k <= SCM_UVECTOR_MAX_LENGTH);
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{
9a09deb1 155 if (SCM_EQ_P (prot, SCM_BOOL_T))
0f2d19dd 156 {
93778877
DH
157 if (k > 0)
158 {
711a9fd7 159 long i;
16d4699b
MV
160 SCM_ASSERT_RANGE (1,
161 scm_long2num (k), 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);
0f2d19dd 173 else if (SCM_INUMP (prot))
711a9fd7
MD
174 return make_uve (SCM_INUM (prot) > 0 ? scm_tc7_uvect : scm_tc7_ivect,
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:
221 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v));
0f2d19dd 222 case scm_tc7_string:
74014c46
DH
223 return SCM_MAKINUM (SCM_STRING_LENGTH (v));
224 case scm_tc7_bvect:
225 return SCM_MAKINUM (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
74014c46 236 return SCM_MAKINUM (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)
266 return SCM_BOOL(nprot);
267 else
268 {
269 int protp = 0;
270
271 switch (SCM_TYP7 (v))
272 {
273 case scm_tc7_bvect:
9a09deb1 274 protp = (SCM_EQ_P (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:
4260a7fc 280 protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
7c183c95 281 break;
c209c88e
GB
282 case scm_tc7_uvect:
283 protp = SCM_INUMP(prot) && SCM_INUM(prot)>0;
7c183c95 284 break;
c209c88e
GB
285 case scm_tc7_ivect:
286 protp = SCM_INUMP(prot) && SCM_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 }
319 return SCM_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:
350 return SCM_MAKINUM (1L);
351 case scm_tc7_smob:
352 if (SCM_ARRAYP (ra))
353 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra));
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
MD
399 res = scm_cons (s[k].lbnd
400 ? scm_cons2 (SCM_MAKINUM (s[k].lbnd),
401 SCM_MAKINUM (s[k].ubnd),
402 SCM_EOL)
403 : SCM_MAKINUM (1 + s[k].ubnd),
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);
428 return SCM_MAKINUM (SCM_ARRAY_BASE (ra));
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--)
445 res = scm_cons (SCM_MAKINUM (s[k].inc), res);
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);
0f2d19dd 463 if (SCM_INUMP (args))
0f2d19dd 464 {
b3fcac34
DH
465 if (k != 1)
466 scm_error_num_args_subr (what);
0f2d19dd
JB
467 return pos + (SCM_INUM (args) - s->lbnd) * (s->inc);
468 }
13824149 469 while (k && SCM_CONSP (args))
0f2d19dd
JB
470 {
471 ind = SCM_CAR (args);
472 args = SCM_CDR (args);
b3fcac34
DH
473 if (!SCM_INUMP (ind))
474 scm_misc_error (what, s_bad_ind, SCM_EOL);
0f2d19dd 475 j = SCM_INUM (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);
a3a32939 523 if (SCM_INUMP (spec))
0f2d19dd 524 {
b3fcac34
DH
525 if (SCM_INUM (spec) < 0)
526 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
527 s->lbnd = 0;
528 s->ubnd = SCM_INUM (spec) - 1;
529 s->inc = 1;
530 }
531 else
532 {
b3fcac34
DH
533 if (!SCM_CONSP (spec) || !SCM_INUMP (SCM_CAR (spec)))
534 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
535 s->lbnd = SCM_INUM (SCM_CAR (spec));
536 sp = SCM_CDR (spec);
b3fcac34
DH
537 if (!SCM_CONSP (sp)
538 || !SCM_INUMP (SCM_CAR (sp))
539 || !SCM_NULLP (SCM_CDR (sp)))
540 scm_misc_error (what, s_bad_spec, SCM_EOL);
0f2d19dd
JB
541 s->ubnd = SCM_INUM (SCM_CAR (sp));
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
0f2d19dd 562 if (SCM_INUMP (dims))
cda139a7 563 {
5b9eb8ae 564 SCM answer = scm_make_uve (SCM_INUM (dims), prot);
a3a32939
DH
565 if (!SCM_UNBNDP (fill))
566 scm_array_fill_x (answer, fill);
567 else if (SCM_SYMBOLP (prot))
568 scm_array_fill_x (answer, SCM_MAKINUM (0));
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))
0f2d19dd
JB
593 scm_array_fill_x (ra, SCM_MAKINUM (0));
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;
74014c46 675 old_max = SCM_INUM (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 {
681 inds = scm_cons (SCM_MAKINUM (s[k].lbnd), inds);
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 {
696 if (SCM_NINUMP (imap))
697
698 {
b3fcac34
DH
699 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
700 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
701 imap = SCM_CAR (imap);
702 }
703 i = SCM_INUM (imap);
704 }
705 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
706 indptr = inds;
707 k = SCM_ARRAY_NDIM (ra);
708 while (k--)
709 {
710 if (s[k].ubnd > s[k].lbnd)
711 {
898a256f 712 SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
fdc28395 713 imap = scm_apply_0 (mapfunc, scm_reverse (inds));
0f2d19dd
JB
714 if (SCM_ARRAYP (oldra))
715
1bbd0b84 716 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
717 else
718 {
719 if (SCM_NINUMP (imap))
0f2d19dd 720 {
b3fcac34
DH
721 if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
722 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
723 imap = SCM_CAR (imap);
724 }
725 s[k].inc = (long) SCM_INUM (imap) - i;
726 }
727 i += s[k].inc;
728 if (s[k].inc > 0)
729 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
730 else
731 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
732 }
733 else
734 s[k].inc = new_max - new_min + 1; /* contiguous by default */
735 indptr = SCM_CDR (indptr);
736 }
b3fcac34
DH
737 if (old_min > new_min || old_max < new_max)
738 SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
0f2d19dd
JB
739 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
740 {
74014c46 741 SCM v = SCM_ARRAY_V (ra);
c014a02e 742 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
743 if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
744 return v;
0f2d19dd
JB
745 if (s->ubnd < s->lbnd)
746 return scm_make_uve (0L, scm_array_prototype (ra));
747 }
748 scm_ra_set_contp (ra);
749 return ra;
750}
1bbd0b84 751#undef FUNC_NAME
0f2d19dd
JB
752
753
754/* args are RA . DIMS */
af45e3b0
DH
755SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
756 (SCM ra, SCM args),
1e6808ea
MG
757 "Return an array sharing contents with @var{array}, but with\n"
758 "dimensions arranged in a different order. There must be one\n"
759 "@var{dim} argument for each dimension of @var{array}.\n"
760 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
761 "and the rank of the array to be returned. Each integer in that\n"
762 "range must appear at least once in the argument list.\n"
763 "\n"
764 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
765 "dimensions in the array to be returned, their positions in the\n"
766 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
767 "may have the same value, in which case the returned array will\n"
768 "have smaller rank than @var{array}.\n"
769 "\n"
770 "@lisp\n"
b380b885
MD
771 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
772 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
773 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
774 " #2((a 4) (b 5) (c 6))\n"
1e6808ea 775 "@end lisp")
1bbd0b84 776#define FUNC_NAME s_scm_transpose_array
0f2d19dd 777{
34d19ef6
HWN
778 SCM res, vargs;
779 SCM const *ve = &vargs;
92c2555f 780 scm_t_array_dim *s, *r;
0f2d19dd 781 int ndim, i, k;
af45e3b0 782
b3fcac34 783 SCM_VALIDATE_REST_ARGUMENT (args);
1bbd0b84 784 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
f5bf2977 785 switch (SCM_TYP7 (ra))
0f2d19dd
JB
786 {
787 default:
276dd677 788 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
789 case scm_tc7_bvect:
790 case scm_tc7_string:
791 case scm_tc7_byvect:
792 case scm_tc7_uvect:
793 case scm_tc7_ivect:
794 case scm_tc7_fvect:
795 case scm_tc7_dvect:
796 case scm_tc7_cvect:
797 case scm_tc7_svect:
2a5cd898 798#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
799 case scm_tc7_llvect:
800#endif
b3fcac34
DH
801 if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
802 SCM_WRONG_NUM_ARGS ();
803 SCM_VALIDATE_INUM (SCM_ARG2, SCM_CAR (args));
685c0d71
DH
804 SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args),
805 SCM_EQ_P (SCM_INUM0, SCM_CAR (args)));
0f2d19dd
JB
806 return ra;
807 case scm_tc7_smob:
808 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
809 vargs = scm_vector (args);
b3fcac34
DH
810 if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
811 SCM_WRONG_NUM_ARGS ();
812 ve = SCM_VELTS (vargs);
0f2d19dd
JB
813 ndim = 0;
814 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
815 {
20a54673 816 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 817 FUNC_NAME);
0f2d19dd 818 i = SCM_INUM (ve[k]);
685c0d71
DH
819 if (i < 0 || i >= SCM_ARRAY_NDIM (ra))
820 scm_out_of_range (FUNC_NAME, ve[k]);
0f2d19dd
JB
821 if (ndim < i)
822 ndim = i;
823 }
824 ndim++;
825 res = scm_make_ra (ndim);
826 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
827 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
828 for (k = ndim; k--;)
829 {
830 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
831 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
832 }
833 for (k = SCM_ARRAY_NDIM (ra); k--;)
834 {
835 i = SCM_INUM (ve[k]);
836 s = &(SCM_ARRAY_DIMS (ra)[k]);
837 r = &(SCM_ARRAY_DIMS (res)[i]);
838 if (r->ubnd < r->lbnd)
839 {
840 r->lbnd = s->lbnd;
841 r->ubnd = s->ubnd;
842 r->inc = s->inc;
843 ndim--;
844 }
845 else
846 {
847 if (r->ubnd > s->ubnd)
848 r->ubnd = s->ubnd;
849 if (r->lbnd < s->lbnd)
850 {
851 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
852 r->lbnd = s->lbnd;
853 }
854 r->inc += s->inc;
855 }
856 }
b3fcac34
DH
857 if (ndim > 0)
858 SCM_MISC_ERROR ("bad argument list", SCM_EOL);
0f2d19dd
JB
859 scm_ra_set_contp (res);
860 return res;
861 }
862}
1bbd0b84 863#undef FUNC_NAME
0f2d19dd
JB
864
865/* args are RA . AXES */
af45e3b0
DH
866SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
867 (SCM ra, SCM axes),
b380b885
MD
868 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
869 "the rank of @var{array}. @var{enclose-array} returns an array\n"
870 "resembling an array of shared arrays. The dimensions of each shared\n"
871 "array are the same as the @var{dim}th dimensions of the original array,\n"
872 "the dimensions of the outer array are the same as those of the original\n"
873 "array that did not match a @var{dim}.\n\n"
874 "An enclosed array is not a general Scheme array. Its elements may not\n"
875 "be set using @code{array-set!}. Two references to the same element of\n"
876 "an enclosed array will be @code{equal?} but will not in general be\n"
877 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
878 "enclosed array is unspecified.\n\n"
879 "examples:\n"
1e6808ea 880 "@lisp\n"
b380b885
MD
881 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
882 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
883 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
884 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
1e6808ea 885 "@end lisp")
1bbd0b84 886#define FUNC_NAME s_scm_enclose_array
0f2d19dd 887{
af45e3b0 888 SCM axv, res, ra_inr;
92c2555f 889 scm_t_array_dim vdim, *s = &vdim;
0f2d19dd 890 int ndim, j, k, ninr, noutr;
af45e3b0 891
b3fcac34 892 SCM_VALIDATE_REST_ARGUMENT (axes);
0f2d19dd 893 if (SCM_NULLP (axes))
0f2d19dd
JB
894 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
895 ninr = scm_ilength (axes);
b3fcac34
DH
896 if (ninr < 0)
897 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
898 ra_inr = scm_make_ra (ninr);
899 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
74014c46 900 switch SCM_TYP7 (ra)
0f2d19dd
JB
901 {
902 default:
276dd677 903 badarg1:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
904 case scm_tc7_string:
905 case scm_tc7_bvect:
906 case scm_tc7_byvect:
907 case scm_tc7_uvect:
908 case scm_tc7_ivect:
909 case scm_tc7_fvect:
910 case scm_tc7_dvect:
911 case scm_tc7_cvect:
912 case scm_tc7_vector:
95f5b0f5 913 case scm_tc7_wvect:
0f2d19dd 914 case scm_tc7_svect:
2a5cd898 915#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
916 case scm_tc7_llvect:
917#endif
918 s->lbnd = 0;
74014c46 919 s->ubnd = SCM_INUM (scm_uniform_vector_length (ra)) - 1;
0f2d19dd
JB
920 s->inc = 1;
921 SCM_ARRAY_V (ra_inr) = ra;
922 SCM_ARRAY_BASE (ra_inr) = 0;
923 ndim = 1;
924 break;
925 case scm_tc7_smob:
926 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
927 s = SCM_ARRAY_DIMS (ra);
928 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
929 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
930 ndim = SCM_ARRAY_NDIM (ra);
931 break;
932 }
933 noutr = ndim - ninr;
b3fcac34
DH
934 if (noutr < 0)
935 SCM_WRONG_NUM_ARGS ();
7866a09b 936 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
0f2d19dd
JB
937 res = scm_make_ra (noutr);
938 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
939 SCM_ARRAY_V (res) = ra_inr;
940 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
941 {
b3fcac34
DH
942 if (!SCM_INUMP (SCM_CAR (axes)))
943 SCM_MISC_ERROR ("bad axis", SCM_EOL);
0f2d19dd
JB
944 j = SCM_INUM (SCM_CAR (axes));
945 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
946 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
947 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
405aaef9 948 SCM_STRING_CHARS (axv)[j] = 1;
0f2d19dd
JB
949 }
950 for (j = 0, k = 0; k < noutr; k++, j++)
951 {
405aaef9 952 while (SCM_STRING_CHARS (axv)[j])
0f2d19dd
JB
953 j++;
954 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
955 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
956 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
957 }
958 scm_ra_set_contp (ra_inr);
959 scm_ra_set_contp (res);
960 return res;
961}
1bbd0b84 962#undef FUNC_NAME
0f2d19dd
JB
963
964
965
af45e3b0
DH
966SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
967 (SCM v, SCM args),
1e6808ea
MG
968 "Return @code{#t} if its arguments would be acceptable to\n"
969 "@code{array-ref}.")
1bbd0b84 970#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 971{
af45e3b0 972 SCM ind = SCM_EOL;
c014a02e 973 long pos = 0;
1be6b49c 974 register size_t k;
c014a02e 975 register long j;
92c2555f 976 scm_t_array_dim *s;
af45e3b0 977
b3fcac34 978 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
979 SCM_ASRTGO (SCM_NIMP (v), badarg1);
980 if (SCM_NIMP (args))
981
982 {
983 ind = SCM_CAR (args);
984 args = SCM_CDR (args);
1bbd0b84 985 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
986 pos = SCM_INUM (ind);
987 }
988tail:
74014c46 989 switch SCM_TYP7 (v)
0f2d19dd
JB
990 {
991 default:
276dd677 992 badarg1:SCM_WRONG_TYPE_ARG (1, v);
b3fcac34 993 wna: SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
994 case scm_tc7_smob:
995 k = SCM_ARRAY_NDIM (v);
996 s = SCM_ARRAY_DIMS (v);
997 pos = SCM_ARRAY_BASE (v);
998 if (!k)
999 {
1000 SCM_ASRTGO (SCM_NULLP (ind), wna);
1001 ind = SCM_INUM0;
1002 }
1003 else
1004 while (!0)
1005 {
1006 j = SCM_INUM (ind);
1007 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1008 {
1009 SCM_ASRTGO (--k == scm_ilength (args), wna);
1010 return SCM_BOOL_F;
1011 }
1012 pos += (j - s->lbnd) * (s->inc);
1013 if (!(--k && SCM_NIMP (args)))
1014 break;
1015 ind = SCM_CAR (args);
1016 args = SCM_CDR (args);
1017 s++;
b3fcac34
DH
1018 if (!SCM_INUMP (ind))
1019 SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
0f2d19dd
JB
1020 }
1021 SCM_ASRTGO (0 == k, wna);
1022 v = SCM_ARRAY_V (v);
1023 goto tail;
1024 case scm_tc7_bvect:
1025 case scm_tc7_string:
1026 case scm_tc7_byvect:
1027 case scm_tc7_uvect:
1028 case scm_tc7_ivect:
1029 case scm_tc7_fvect:
1030 case scm_tc7_dvect:
1031 case scm_tc7_cvect:
1032 case scm_tc7_svect:
2a5cd898 1033#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
1034 case scm_tc7_llvect:
1035#endif
1036 case scm_tc7_vector:
95f5b0f5 1037 case scm_tc7_wvect:
74014c46 1038 {
c014a02e 1039 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1040 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1041 return SCM_BOOL(pos >= 0 && pos < length);
1042 }
0f2d19dd
JB
1043 }
1044}
1bbd0b84 1045#undef FUNC_NAME
0f2d19dd
JB
1046
1047
1bbd0b84 1048SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1049
1bbd0b84 1050
3b3b36dd 1051SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1052 (SCM v, SCM args),
8f85c0c6 1053 "@deffnx {Scheme Procedure} array-ref v . args\n"
1e6808ea
MG
1054 "Return the element at the @code{(index1, index2)} element in\n"
1055 "@var{array}.")
1bbd0b84 1056#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd 1057{
c014a02e 1058 long pos;
0f2d19dd 1059
35de7ebe 1060 if (SCM_IMP (v))
0f2d19dd
JB
1061 {
1062 SCM_ASRTGO (SCM_NULLP (args), badarg);
1063 return v;
1064 }
1065 else if (SCM_ARRAYP (v))
0f2d19dd 1066 {
1bbd0b84 1067 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1068 v = SCM_ARRAY_V (v);
1069 }
1070 else
1071 {
c014a02e 1072 unsigned long int length;
0f2d19dd 1073 if (SCM_NIMP (args))
0f2d19dd 1074 {
1bbd0b84 1075 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1076 pos = SCM_INUM (SCM_CAR (args));
1077 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1078 }
1079 else
1080 {
34d19ef6 1081 SCM_VALIDATE_INUM (2, args);
0f2d19dd
JB
1082 pos = SCM_INUM (args);
1083 }
74014c46
DH
1084 length = SCM_INUM (scm_uniform_vector_length (v));
1085 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd 1086 }
74014c46 1087 switch SCM_TYP7 (v)
0f2d19dd
JB
1088 {
1089 default:
1090 if (SCM_NULLP (args))
1091 return v;
35de7ebe 1092 badarg:
276dd677
DH
1093 SCM_WRONG_TYPE_ARG (1, v);
1094 /* not reached */
c209c88e
GB
1095
1096 outrng:
1097 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1098 wna:
b3fcac34 1099 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1100 case scm_tc7_smob:
1101 { /* enclosed */
1102 int k = SCM_ARRAY_NDIM (v);
1103 SCM res = scm_make_ra (k);
1104 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1105 SCM_ARRAY_BASE (res) = pos;
1106 while (k--)
1107 {
1108 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1109 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1110 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1111 }
1112 return res;
1113 }
1114 case scm_tc7_bvect:
c209c88e 1115 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1116 return SCM_BOOL_T;
1117 else
1118 return SCM_BOOL_F;
1119 case scm_tc7_string:
322ac0c5 1120 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1121 case scm_tc7_byvect:
405aaef9 1122 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1123 case scm_tc7_uvect:
fee7ef83 1124 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1125 case scm_tc7_ivect:
1be6b49c 1126 return scm_long2num (((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1127
1128 case scm_tc7_svect:
4260a7fc 1129 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
2a5cd898 1130#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1131 case scm_tc7_llvect:
1be6b49c 1132 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1133#endif
1134
0f2d19dd 1135 case scm_tc7_fvect:
4260a7fc 1136 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1137 case scm_tc7_dvect:
4260a7fc 1138 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1139 case scm_tc7_cvect:
4260a7fc
DH
1140 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1141 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1142 case scm_tc7_vector:
95f5b0f5 1143 case scm_tc7_wvect:
0f2d19dd
JB
1144 return SCM_VELTS (v)[pos];
1145 }
1146}
1bbd0b84 1147#undef FUNC_NAME
0f2d19dd
JB
1148
1149/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1150 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1151
0f2d19dd 1152SCM
c014a02e 1153scm_cvref (SCM v, unsigned long pos, SCM last)
db4b4ca6 1154#define FUNC_NAME "scm_cvref"
0f2d19dd 1155{
5c11cc9d 1156 switch SCM_TYP7 (v)
0f2d19dd
JB
1157 {
1158 default:
db4b4ca6 1159 SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd 1160 case scm_tc7_bvect:
34d19ef6 1161 if (SCM_BITVEC_REF(v, pos))
0f2d19dd
JB
1162 return SCM_BOOL_T;
1163 else
1164 return SCM_BOOL_F;
1165 case scm_tc7_string:
322ac0c5 1166 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
0f2d19dd 1167 case scm_tc7_byvect:
405aaef9 1168 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
0f2d19dd 1169 case scm_tc7_uvect:
fee7ef83 1170 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1171 case scm_tc7_ivect:
fee7ef83 1172 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1173 case scm_tc7_svect:
4260a7fc 1174 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
2a5cd898 1175#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1176 case scm_tc7_llvect:
1be6b49c 1177 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1178#endif
0f2d19dd 1179 case scm_tc7_fvect:
3ea39242 1180 if (SCM_REALP (last) && !SCM_EQ_P (last, scm_flo0))
0f2d19dd 1181 {
4260a7fc 1182 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1183 return last;
1184 }
4260a7fc 1185 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1186 case scm_tc7_dvect:
3ea39242 1187 if (SCM_REALP (last) && !SCM_EQ_P (last, scm_flo0))
0f2d19dd 1188 {
4260a7fc 1189 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1190 return last;
1191 }
4260a7fc 1192 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1193 case scm_tc7_cvect:
3ea39242 1194 if (SCM_COMPLEXP (last))
0f2d19dd 1195 {
4260a7fc
DH
1196 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1197 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1198 return last;
1199 }
4260a7fc
DH
1200 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1201 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1202 case scm_tc7_vector:
95f5b0f5 1203 case scm_tc7_wvect:
0f2d19dd
JB
1204 return SCM_VELTS (v)[pos];
1205 case scm_tc7_smob:
1206 { /* enclosed scm_array */
1207 int k = SCM_ARRAY_NDIM (v);
1208 SCM res = scm_make_ra (k);
1209 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1210 SCM_ARRAY_BASE (res) = pos;
1211 while (k--)
1212 {
1213 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1214 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1215 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1216 }
1217 return res;
1218 }
1219 }
1220}
db4b4ca6
DH
1221#undef FUNC_NAME
1222
0f2d19dd 1223
1bbd0b84
GB
1224SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1225
1cc91f1b 1226
0aa0871f
GH
1227/* Note that args may be a list or an immediate object, depending which
1228 PROC is used (and it's called from C too). */
3b3b36dd 1229SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1230 (SCM v, SCM obj, SCM args),
8f85c0c6
NJ
1231 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1232 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
b380b885 1233 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1234#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1235{
c014a02e 1236 long pos = 0;
b3fcac34 1237
0f2d19dd
JB
1238 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1239 if (SCM_ARRAYP (v))
0f2d19dd 1240 {
1bbd0b84 1241 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1242 v = SCM_ARRAY_V (v);
1243 }
1244 else
1245 {
c014a02e 1246 unsigned long int length;
9a97e362 1247 if (SCM_CONSP (args))
0f2d19dd 1248 {
9a97e362 1249 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), args, SCM_ARG3, FUNC_NAME);
0f2d19dd 1250 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1251 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1252 }
1253 else
1254 {
34d19ef6 1255 SCM_VALIDATE_INUM_COPY (3, args, pos);
0f2d19dd 1256 }
74014c46
DH
1257 length = SCM_INUM (scm_uniform_vector_length (v));
1258 SCM_ASRTGO (pos >= 0 && pos < length, outrng);
0f2d19dd
JB
1259 }
1260 switch (SCM_TYP7 (v))
1261 {
35de7ebe 1262 default: badarg1:
276dd677
DH
1263 SCM_WRONG_TYPE_ARG (1, v);
1264 /* not reached */
c209c88e
GB
1265 outrng:
1266 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1267 wna:
b3fcac34 1268 SCM_WRONG_NUM_ARGS ();
0f2d19dd
JB
1269 case scm_tc7_smob: /* enclosed */
1270 goto badarg1;
1271 case scm_tc7_bvect:
4260a7fc 1272 if (SCM_FALSEP (obj))
34d19ef6 1273 SCM_BITVEC_CLR(v, pos);
9a09deb1 1274 else if (SCM_EQ_P (obj, SCM_BOOL_T))
34d19ef6 1275 SCM_BITVEC_SET(v, pos);
0f2d19dd 1276 else
276dd677 1277 badobj:SCM_WRONG_TYPE_ARG (2, obj);
0f2d19dd
JB
1278 break;
1279 case scm_tc7_string:
7866a09b 1280 SCM_ASRTGO (SCM_CHARP (obj), badobj);
322ac0c5 1281 SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1282 break;
1283 case scm_tc7_byvect:
7866a09b
GB
1284 if (SCM_CHARP (obj))
1285 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1286 SCM_ASRTGO (SCM_INUMP (obj), badobj);
405aaef9 1287 ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1288 break;
1bbd0b84 1289 case scm_tc7_uvect:
729dbac3
DH
1290 ((unsigned long *) SCM_UVECTOR_BASE (v))[pos]
1291 = scm_num2ulong (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1292 break;
1bbd0b84 1293 case scm_tc7_ivect:
729dbac3
DH
1294 ((long *) SCM_UVECTOR_BASE (v))[pos]
1295 = scm_num2long (obj, SCM_ARG2, FUNC_NAME);
c209c88e 1296 break;
0f2d19dd 1297 case scm_tc7_svect:
0aa0871f 1298 SCM_ASRTGO (SCM_INUMP (obj), badobj);
729dbac3 1299 ((short *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
0f2d19dd 1300 break;
2a5cd898 1301#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1302 case scm_tc7_llvect:
729dbac3
DH
1303 ((long long *) SCM_UVECTOR_BASE (v))[pos]
1304 = scm_num2long_long (obj, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1305 break;
1306#endif
0f2d19dd 1307 case scm_tc7_fvect:
729dbac3
DH
1308 ((float *) SCM_UVECTOR_BASE (v))[pos]
1309 = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1310 break;
0f2d19dd 1311 case scm_tc7_dvect:
729dbac3
DH
1312 ((double *) SCM_UVECTOR_BASE (v))[pos]
1313 = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1314 break;
1315 case scm_tc7_cvect:
eb42e2f0
DH
1316 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1317 if (SCM_REALP (obj)) {
729dbac3
DH
1318 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_REAL_VALUE (obj);
1319 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = 0.0;
eb42e2f0 1320 } else {
729dbac3
DH
1321 ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1322 ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
eb42e2f0 1323 }
0f2d19dd 1324 break;
0f2d19dd 1325 case scm_tc7_vector:
95f5b0f5 1326 case scm_tc7_wvect:
34d19ef6 1327 SCM_VECTOR_SET (v, pos, obj);
0f2d19dd
JB
1328 break;
1329 }
1330 return SCM_UNSPECIFIED;
1331}
1bbd0b84 1332#undef FUNC_NAME
0f2d19dd 1333
1d7bdb25
GH
1334/* attempts to unroll an array into a one-dimensional array.
1335 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1336 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1337 wouldn't have contiguous elements. */
3b3b36dd 1338SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1339 (SCM ra, SCM strict),
b380b885
MD
1340 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1341 "without changing their order (last subscript changing fastest), then\n"
1342 "@code{array-contents} returns that shared array, otherwise it returns\n"
1343 "@code{#f}. All arrays made by @var{make-array} and\n"
1344 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1345 "@var{make-shared-array} may not be.\n\n"
1346 "If the optional argument @var{strict} is provided, a shared array will\n"
1347 "be returned only if its elements are stored internally contiguous in\n"
1348 "memory.")
1bbd0b84 1349#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1350{
1351 SCM sra;
1352 if (SCM_IMP (ra))
f3667f52 1353 return SCM_BOOL_F;
5c11cc9d 1354 switch SCM_TYP7 (ra)
0f2d19dd
JB
1355 {
1356 default:
1357 return SCM_BOOL_F;
1358 case scm_tc7_vector:
95f5b0f5 1359 case scm_tc7_wvect:
0f2d19dd
JB
1360 case scm_tc7_string:
1361 case scm_tc7_bvect:
1362 case scm_tc7_byvect:
1363 case scm_tc7_uvect:
1364 case scm_tc7_ivect:
1365 case scm_tc7_fvect:
1366 case scm_tc7_dvect:
1367 case scm_tc7_cvect:
1368 case scm_tc7_svect:
2a5cd898 1369#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
1370 case scm_tc7_llvect:
1371#endif
1372 return ra;
1373 case scm_tc7_smob:
1374 {
c014a02e 1375 size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
0f2d19dd
JB
1376 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1377 return SCM_BOOL_F;
1378 for (k = 0; k < ndim; k++)
1379 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1380 if (!SCM_UNBNDP (strict))
1381 {
0f2d19dd
JB
1382 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1383 return SCM_BOOL_F;
1384 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1385 {
74014c46 1386 if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
c014a02e
ML
1387 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1388 len % SCM_LONG_BIT)
0f2d19dd
JB
1389 return SCM_BOOL_F;
1390 }
1391 }
74014c46
DH
1392
1393 {
1394 SCM v = SCM_ARRAY_V (ra);
c014a02e 1395 unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
74014c46
DH
1396 if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1397 return v;
1398 }
1399
0f2d19dd
JB
1400 sra = scm_make_ra (1);
1401 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1402 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1403 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1404 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1405 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1406 return sra;
1407 }
1408 }
1409}
1bbd0b84 1410#undef FUNC_NAME
0f2d19dd 1411
1cc91f1b 1412
0f2d19dd 1413SCM
6e8d25a6 1414scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1415{
1416 SCM ret;
c014a02e
ML
1417 long inc = 1;
1418 size_t k, len = 1;
0f2d19dd
JB
1419 for (k = SCM_ARRAY_NDIM (ra); k--;)
1420 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1421 k = SCM_ARRAY_NDIM (ra);
1422 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1423 {
74014c46 1424 if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
0f2d19dd 1425 return ra;
74014c46 1426 if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
c014a02e
ML
1427 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1428 0 == len % SCM_LONG_BIT))
0f2d19dd
JB
1429 return ra;
1430 }
1431 ret = scm_make_ra (k);
1432 SCM_ARRAY_BASE (ret) = 0;
1433 while (k--)
1434 {
1435 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1436 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1437 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1438 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1439 }
08112c95 1440 SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
0f2d19dd
JB
1441 if (copy)
1442 scm_array_copy_x (ra, ret);
1443 return ret;
1444}
1445
1446
1447
3b3b36dd 1448SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1449 (SCM ra, SCM port_or_fd, SCM start, SCM end),
8f85c0c6
NJ
1450 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1451 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
b380b885 1452 "binary objects from @var{port-or-fdes}.\n"
8f85c0c6
NJ
1453 "If an end of file is encountered,\n"
1454 "the objects up to that point are put into @var{ura}\n"
b380b885
MD
1455 "(starting at the beginning) and the remainder of the array is\n"
1456 "unchanged.\n\n"
1457 "The optional arguments @var{start} and @var{end} allow\n"
1458 "a specified region of a vector (or linearized array) to be read,\n"
1459 "leaving the remainder of the vector unchanged.\n\n"
1460 "@code{uniform-array-read!} returns the number of objects read.\n"
1461 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1462 "returned by @code{(current-input-port)}.")
1bbd0b84 1463#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1464{
35de7ebe 1465 SCM cra = SCM_UNDEFINED, v = ra;
c014a02e
ML
1466 long sz, vlen, ans;
1467 long cstart = 0;
1468 long cend;
1469 long offset = 0;
405aaef9 1470 char *base;
35de7ebe 1471
0f2d19dd 1472 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1473 if (SCM_UNBNDP (port_or_fd))
1474 port_or_fd = scm_cur_inp;
1475 else
1476 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1477 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1478 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1479 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1480 ? 0
1481 : SCM_INUM (scm_uniform_vector_length (v)));
35de7ebe 1482
0f2d19dd 1483loop:
35de7ebe 1484 switch SCM_TYP7 (v)
0f2d19dd
JB
1485 {
1486 default:
276dd677 1487 badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
0f2d19dd
JB
1488 case scm_tc7_smob:
1489 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1490 cra = scm_ra2contig (ra, 0);
1146b6cd 1491 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1492 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1493 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1494 v = SCM_ARRAY_V (cra);
1495 goto loop;
1496 case scm_tc7_string:
74014c46 1497 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1498 sz = sizeof (char);
1499 break;
1500 case scm_tc7_bvect:
74014c46 1501 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1502 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1503 cstart /= SCM_LONG_BIT;
1504 sz = sizeof (long);
74014c46
DH
1505 break;
1506 case scm_tc7_byvect:
1507 base = (char *) SCM_UVECTOR_BASE (v);
1508 sz = sizeof (char);
1509 break;
0f2d19dd
JB
1510 case scm_tc7_uvect:
1511 case scm_tc7_ivect:
74014c46 1512 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1513 sz = sizeof (long);
1514 break;
1515 case scm_tc7_svect:
74014c46 1516 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1517 sz = sizeof (short);
1518 break;
2a5cd898 1519#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1520 case scm_tc7_llvect:
74014c46 1521 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1522 sz = sizeof (long long);
0f2d19dd
JB
1523 break;
1524#endif
0f2d19dd 1525 case scm_tc7_fvect:
74014c46 1526 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1527 sz = sizeof (float);
1528 break;
0f2d19dd 1529 case scm_tc7_dvect:
74014c46 1530 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1531 sz = sizeof (double);
1532 break;
1533 case scm_tc7_cvect:
74014c46 1534 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1535 sz = 2 * sizeof (double);
1536 break;
0f2d19dd 1537 }
405aaef9 1538
1146b6cd
GH
1539 cend = vlen;
1540 if (!SCM_UNBNDP (start))
3d8d56df 1541 {
1146b6cd 1542 offset =
c014a02e 1543 SCM_NUM2LONG (3, start);
35de7ebe 1544
1146b6cd 1545 if (offset < 0 || offset >= cend)
1bbd0b84 1546 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1547
1548 if (!SCM_UNBNDP (end))
1549 {
c014a02e
ML
1550 long tend =
1551 SCM_NUM2LONG (4, end);
3d8d56df 1552
1146b6cd 1553 if (tend <= offset || tend > cend)
1bbd0b84 1554 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1555 cend = tend;
1556 }
0f2d19dd 1557 }
35de7ebe 1558
3d8d56df
GH
1559 if (SCM_NIMP (port_or_fd))
1560 {
92c2555f 1561 scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
6c951427 1562 int remaining = (cend - offset) * sz;
405aaef9 1563 char *dest = base + (cstart + offset) * sz;
6c951427
GH
1564
1565 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1566 scm_flush (port_or_fd);
6c951427
GH
1567
1568 ans = cend - offset;
1569 while (remaining > 0)
3d8d56df 1570 {
6c951427
GH
1571 if (pt->read_pos < pt->read_end)
1572 {
1573 int to_copy = min (pt->read_end - pt->read_pos,
1574 remaining);
1575
1576 memcpy (dest, pt->read_pos, to_copy);
1577 pt->read_pos += to_copy;
1578 remaining -= to_copy;
1579 dest += to_copy;
1580 }
1581 else
1582 {
affc96b5 1583 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1584 {
1585 if (remaining % sz != 0)
1586 {
5d2d2ffc 1587 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1588 }
1589 ans -= remaining / sz;
1590 break;
1591 }
6c951427 1592 }
3d8d56df 1593 }
6c951427
GH
1594
1595 if (pt->rw_random)
1596 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1597 }
1598 else /* file descriptor. */
1599 {
1600 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
405aaef9 1601 base + (cstart + offset) * sz,
1be6b49c 1602 (sz * (cend - offset))));
3d8d56df 1603 if (ans == -1)
1bbd0b84 1604 SCM_SYSERROR;
3d8d56df 1605 }
0f2d19dd 1606 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1607 ans *= SCM_LONG_BIT;
35de7ebe 1608
fee7ef83 1609 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1610 scm_array_copy_x (cra, ra);
35de7ebe 1611
0f2d19dd
JB
1612 return SCM_MAKINUM (ans);
1613}
1bbd0b84 1614#undef FUNC_NAME
0f2d19dd 1615
3b3b36dd 1616SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1617 (SCM v, SCM port_or_fd, SCM start, SCM end),
8f85c0c6 1618 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
b380b885
MD
1619 "Writes all elements of @var{ura} as binary objects to\n"
1620 "@var{port-or-fdes}.\n\n"
1621 "The optional arguments @var{start}\n"
1622 "and @var{end} allow\n"
1623 "a specified region of a vector (or linearized array) to be written.\n\n"
9401323e 1624 "The number of objects actually written is returned.\n"
b380b885
MD
1625 "@var{port-or-fdes} may be\n"
1626 "omitted, in which case it defaults to the value returned by\n"
1627 "@code{(current-output-port)}.")
1bbd0b84 1628#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1629{
c014a02e
ML
1630 long sz, vlen, ans;
1631 long offset = 0;
1632 long cstart = 0;
1633 long cend;
405aaef9 1634 char *base;
3d8d56df 1635
78446828
MV
1636 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1637
0f2d19dd 1638 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1639 if (SCM_UNBNDP (port_or_fd))
1640 port_or_fd = scm_cur_outp;
1641 else
1642 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1643 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1644 port_or_fd, SCM_ARG2, FUNC_NAME);
d245ce23
MD
1645 vlen = (SCM_TYP7 (v) == scm_tc7_smob
1646 ? 0
1647 : SCM_INUM (scm_uniform_vector_length (v)));
1648
0f2d19dd 1649loop:
3d8d56df 1650 switch SCM_TYP7 (v)
0f2d19dd
JB
1651 {
1652 default:
276dd677 1653 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
1654 case scm_tc7_smob:
1655 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1656 v = scm_ra2contig (v, 1);
1146b6cd 1657 cstart = SCM_ARRAY_BASE (v);
d245ce23
MD
1658 vlen = (SCM_ARRAY_DIMS (v)->inc
1659 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
0f2d19dd
JB
1660 v = SCM_ARRAY_V (v);
1661 goto loop;
0f2d19dd 1662 case scm_tc7_string:
74014c46 1663 base = SCM_STRING_CHARS (v);
0f2d19dd
JB
1664 sz = sizeof (char);
1665 break;
1666 case scm_tc7_bvect:
74014c46 1667 base = (char *) SCM_BITVECTOR_BASE (v);
c014a02e
ML
1668 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1669 cstart /= SCM_LONG_BIT;
1670 sz = sizeof (long);
74014c46
DH
1671 break;
1672 case scm_tc7_byvect:
1673 base = (char *) SCM_UVECTOR_BASE (v);
1674 sz = sizeof (char);
1675 break;
0f2d19dd
JB
1676 case scm_tc7_uvect:
1677 case scm_tc7_ivect:
74014c46 1678 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1679 sz = sizeof (long);
1680 break;
1681 case scm_tc7_svect:
74014c46 1682 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1683 sz = sizeof (short);
1684 break;
2a5cd898 1685#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 1686 case scm_tc7_llvect:
74014c46 1687 base = (char *) SCM_UVECTOR_BASE (v);
1be6b49c 1688 sz = sizeof (long long);
0f2d19dd
JB
1689 break;
1690#endif
0f2d19dd 1691 case scm_tc7_fvect:
74014c46 1692 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1693 sz = sizeof (float);
1694 break;
0f2d19dd 1695 case scm_tc7_dvect:
74014c46 1696 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1697 sz = sizeof (double);
1698 break;
1699 case scm_tc7_cvect:
74014c46 1700 base = (char *) SCM_UVECTOR_BASE (v);
0f2d19dd
JB
1701 sz = 2 * sizeof (double);
1702 break;
0f2d19dd 1703 }
3d8d56df 1704
1146b6cd
GH
1705 cend = vlen;
1706 if (!SCM_UNBNDP (start))
3d8d56df 1707 {
1146b6cd 1708 offset =
c014a02e 1709 SCM_NUM2LONG (3, start);
3d8d56df 1710
1146b6cd 1711 if (offset < 0 || offset >= cend)
1bbd0b84 1712 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1713
1714 if (!SCM_UNBNDP (end))
1715 {
c014a02e
ML
1716 long tend =
1717 SCM_NUM2LONG (4, end);
3d8d56df 1718
1146b6cd 1719 if (tend <= offset || tend > cend)
1bbd0b84 1720 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1721 cend = tend;
1722 }
3d8d56df
GH
1723 }
1724
1725 if (SCM_NIMP (port_or_fd))
1726 {
405aaef9 1727 char *source = base + (cstart + offset) * sz;
6c951427
GH
1728
1729 ans = cend - offset;
265e6a4d 1730 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1731 }
1732 else /* file descriptor. */
1733 {
1734 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
405aaef9 1735 base + (cstart + offset) * sz,
1be6b49c 1736 (sz * (cend - offset))));
3d8d56df 1737 if (ans == -1)
1bbd0b84 1738 SCM_SYSERROR;
3d8d56df 1739 }
0f2d19dd 1740 if (SCM_TYP7 (v) == scm_tc7_bvect)
c014a02e 1741 ans *= SCM_LONG_BIT;
3d8d56df 1742
0f2d19dd
JB
1743 return SCM_MAKINUM (ans);
1744}
1bbd0b84 1745#undef FUNC_NAME
0f2d19dd
JB
1746
1747
1748static char cnt_tab[16] =
1749{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1750
3b3b36dd 1751SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
c7eb8761 1752 (SCM b, SCM bitvector),
1e6808ea 1753 "Return the number of occurrences of the boolean @var{b} in\n"
c7eb8761 1754 "@var{bitvector}.")
1bbd0b84 1755#define FUNC_NAME s_scm_bit_count
0f2d19dd 1756{
44e47754 1757 SCM_VALIDATE_BOOL (1, b);
74014c46
DH
1758 SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
1759 if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
44e47754
DH
1760 return SCM_INUM0;
1761 } else {
c014a02e
ML
1762 unsigned long int count = 0;
1763 unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1764 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
44e47754
DH
1765 if (SCM_FALSEP (b)) {
1766 w = ~w;
1767 };
c014a02e 1768 w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
44e47754
DH
1769 while (1) {
1770 while (w) {
1771 count += cnt_tab[w & 0x0f];
1772 w >>= 4;
1773 }
1774 if (i == 0) {
1775 return SCM_MAKINUM (count);
1776 } else {
1777 --i;
1778 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1779 if (SCM_FALSEP (b)) {
1780 w = ~w;
0f2d19dd 1781 }
44e47754 1782 }
0f2d19dd 1783 }
44e47754 1784 }
0f2d19dd 1785}
1bbd0b84 1786#undef FUNC_NAME
0f2d19dd
JB
1787
1788
3b3b36dd 1789SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1790 (SCM item, SCM v, SCM k),
88ecf5cb
KR
1791 "Return the index of the first occurrance of @var{item} in bit\n"
1792 "vector @var{v}, starting from @var{k}. If there is no\n"
1793 "@var{item} entry between @var{k} and the end of\n"
1794 "@var{bitvector}, then return @code{#f}. For example,\n"
1795 "\n"
1796 "@example\n"
1797 "(bit-position #t #*000101 0) @result{} 3\n"
1798 "(bit-position #f #*0001111 3) @result{} #f\n"
1799 "@end example")
1bbd0b84 1800#define FUNC_NAME s_scm_bit_position
0f2d19dd 1801{
c014a02e
ML
1802 long i, lenw, xbits, pos;
1803 register unsigned long w;
74014c46
DH
1804
1805 SCM_VALIDATE_BOOL (1, item);
1806 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
34d19ef6 1807 SCM_VALIDATE_INUM_COPY (3, k, pos);
74014c46
DH
1808 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1809
1810 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1811 return SCM_BOOL_F;
74014c46 1812
c014a02e
ML
1813 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1814 i = pos / SCM_LONG_BIT;
74014c46
DH
1815 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1816 if (SCM_FALSEP (item))
1817 w = ~w;
c014a02e 1818 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1819 pos -= xbits;
1820 w = ((w >> xbits) << xbits);
c014a02e 1821 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1822 while (!0)
1823 {
1824 if (w && (i == lenw))
1825 w = ((w << xbits) >> xbits);
1826 if (w)
1827 while (w)
1828 switch (w & 0x0f)
1829 {
1830 default:
1831 return SCM_MAKINUM (pos);
1832 case 2:
1833 case 6:
1834 case 10:
1835 case 14:
1836 return SCM_MAKINUM (pos + 1);
1837 case 4:
1838 case 12:
1839 return SCM_MAKINUM (pos + 2);
1840 case 8:
1841 return SCM_MAKINUM (pos + 3);
1842 case 0:
1843 pos += 4;
1844 w >>= 4;
1845 }
1846 if (++i > lenw)
1847 break;
c014a02e 1848 pos += SCM_LONG_BIT;
f1267706 1849 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1850 if (SCM_FALSEP (item))
1851 w = ~w;
0f2d19dd 1852 }
74014c46 1853 return SCM_BOOL_F;
0f2d19dd 1854}
1bbd0b84 1855#undef FUNC_NAME
0f2d19dd
JB
1856
1857
3b3b36dd 1858SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761 1859 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1860 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1861 "selecting the entries to change. The return value is\n"
1862 "unspecified.\n"
1863 "\n"
1864 "If @var{kv} is a bit vector, then those entries where it has\n"
1865 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1866 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1867 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1868 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1869 "\n"
1870 "@example\n"
1871 "(define bv #*01000010)\n"
1872 "(bit-set*! bv #*10010001 #t)\n"
1873 "bv\n"
1874 "@result{} #*11010011\n"
1875 "@end example\n"
1876 "\n"
1877 "If @var{kv} is a uniform vector of unsigned long integers, then\n"
1878 "they're indexes into @var{v} which are set to @var{obj}.\n"
1879 "\n"
1880 "@example\n"
1881 "(define bv #*01000010)\n"
1882 "(bit-set*! bv #u(5 2 7) #t)\n"
1883 "bv\n"
1884 "@result{} #*01100111\n"
1885 "@end example")
1bbd0b84 1886#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1887{
c014a02e 1888 register long i, k, vlen;
74014c46 1889 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1890 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1891 switch SCM_TYP7 (kv)
0f2d19dd
JB
1892 {
1893 default:
276dd677 1894 badarg2:SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1895 case scm_tc7_uvect:
74014c46
DH
1896 vlen = SCM_BITVECTOR_LENGTH (v);
1897 if (SCM_FALSEP (obj))
1898 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1899 {
c014a02e 1900 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1901 if (k >= vlen)
1902 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1903 SCM_BITVEC_CLR(v, k);
74014c46
DH
1904 }
1905 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1906 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1907 {
c014a02e 1908 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1909 if (k >= vlen)
1910 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1911 SCM_BITVEC_SET(v, k);
74014c46
DH
1912 }
1913 else
276dd677 1914 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1915 break;
1916 case scm_tc7_bvect:
74014c46 1917 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1918 if (SCM_FALSEP (obj))
c014a02e 1919 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1920 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
9a09deb1 1921 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c014a02e 1922 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1923 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
0f2d19dd
JB
1924 else
1925 goto badarg3;
1926 break;
1927 }
1928 return SCM_UNSPECIFIED;
1929}
1bbd0b84 1930#undef FUNC_NAME
0f2d19dd
JB
1931
1932
3b3b36dd 1933SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1934 (SCM v, SCM kv, SCM obj),
88ecf5cb
KR
1935 "Return a count of how many entries in bit vector @var{v} are\n"
1936 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
1937 "consider.\n"
1938 "\n"
1939 "If @var{kv} is a bit vector, then those entries where it has\n"
1940 "@code{#t} are the ones in @var{v} which are considered.\n"
1941 "@var{kv} and @var{v} must be the same length.\n"
1942 "\n"
1943 "If @var{kv} is a uniform vector of unsigned long integers, then\n"
1944 "it's the indexes in @var{v} to consider.\n"
1945 "\n"
1946 "For example,\n"
1947 "\n"
1948 "@example\n"
1949 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
1950 "(bit-count* #*01110111 #u(7 0 4) #f) @result{} 2\n"
1951 "@end example")
1bbd0b84 1952#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1953{
c014a02e
ML
1954 register long i, vlen, count = 0;
1955 register unsigned long k;
41b0806d 1956 int fObj = 0;
c209c88e 1957
74014c46 1958 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1959 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1960 switch SCM_TYP7 (kv)
0f2d19dd
JB
1961 {
1962 default:
c209c88e 1963 badarg2:
276dd677 1964 SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1965 case scm_tc7_uvect:
74014c46
DH
1966 vlen = SCM_BITVECTOR_LENGTH (v);
1967 if (SCM_FALSEP (obj))
1968 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1969 {
c014a02e 1970 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1971 if (k >= vlen)
1972 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1973 if (!SCM_BITVEC_REF(v, k))
74014c46
DH
1974 count++;
1975 }
1976 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1977 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1978 {
c014a02e 1979 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1980 if (k >= vlen)
1981 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1982 if (SCM_BITVEC_REF (v, k))
74014c46
DH
1983 count++;
1984 }
1985 else
276dd677 1986 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1987 break;
1988 case scm_tc7_bvect:
74014c46
DH
1989 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1990 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1991 return SCM_INUM0;
4260a7fc 1992 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1993 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
c014a02e
ML
1994 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1995 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1996 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1997 while (1)
0f2d19dd
JB
1998 {
1999 for (; k; k >>= 4)
2000 count += cnt_tab[k & 0x0f];
2001 if (0 == i--)
2002 return SCM_MAKINUM (count);
c209c88e
GB
2003
2004 /* urg. repetitive (see above.) */
c014a02e 2005 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
2006 }
2007 }
2008 return SCM_MAKINUM (count);
2009}
1bbd0b84 2010#undef FUNC_NAME
0f2d19dd
JB
2011
2012
3b3b36dd 2013SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 2014 (SCM v),
88ecf5cb
KR
2015 "Modify the bit vector @var{v} by replacing each element with\n"
2016 "its negation.")
1bbd0b84 2017#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 2018{
c014a02e 2019 long int k;
74014c46
DH
2020
2021 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
2022
2023 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 2024 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 2025 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 2026
0f2d19dd
JB
2027 return SCM_UNSPECIFIED;
2028}
1bbd0b84 2029#undef FUNC_NAME
0f2d19dd
JB
2030
2031
0f2d19dd 2032SCM
c014a02e 2033scm_istr2bve (char *str, long len)
0f2d19dd
JB
2034{
2035 SCM v = scm_make_uve (len, SCM_BOOL_T);
c014a02e
ML
2036 long *data = (long *) SCM_VELTS (v);
2037 register unsigned long mask;
2038 register long k;
2039 register long j;
2040 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
2041 {
2042 data[k] = 0L;
c014a02e
ML
2043 j = len - k * SCM_LONG_BIT;
2044 if (j > SCM_LONG_BIT)
2045 j = SCM_LONG_BIT;
0f2d19dd
JB
2046 for (mask = 1L; j--; mask <<= 1)
2047 switch (*str++)
2048 {
2049 case '0':
2050 break;
2051 case '1':
2052 data[k] |= mask;
2053 break;
2054 default:
2055 return SCM_BOOL_F;
2056 }
2057 }
2058 return v;
2059}
2060
2061
1cc91f1b 2062
0f2d19dd 2063static SCM
34d19ef6 2064ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd
JB
2065{
2066 register SCM res = SCM_EOL;
c014a02e
ML
2067 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2068 register size_t i;
0f2d19dd
JB
2069 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2070 return SCM_EOL;
2071 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2072 if (k < SCM_ARRAY_NDIM (ra) - 1)
2073 {
2074 do
2075 {
2076 i -= inc;
2077 res = scm_cons (ra2l (ra, i, k + 1), res);
2078 }
2079 while (i != base);
2080 }
2081 else
2082 do
2083 {
2084 i -= inc;
2085 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2086 }
2087 while (i != base);
2088 return res;
2089}
2090
2091
cd328b4f 2092SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2093 (SCM v),
1e6808ea
MG
2094 "Return a list consisting of all the elements, in order, of\n"
2095 "@var{array}.")
cd328b4f 2096#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2097{
2098 SCM res = SCM_EOL;
c014a02e 2099 register long k;
0f2d19dd 2100 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2101 switch SCM_TYP7 (v)
0f2d19dd
JB
2102 {
2103 default:
276dd677 2104 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
2105 case scm_tc7_smob:
2106 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2107 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2108 case scm_tc7_vector:
95f5b0f5 2109 case scm_tc7_wvect:
0f2d19dd
JB
2110 return scm_vector_to_list (v);
2111 case scm_tc7_string:
2112 return scm_string_to_list (v);
2113 case scm_tc7_bvect:
2114 {
c014a02e
ML
2115 long *data = (long *) SCM_VELTS (v);
2116 register unsigned long mask;
2117 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2118 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2119 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2120 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2121 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2122 return res;
2123 }
af7546eb
DH
2124 case scm_tc7_byvect:
2125 {
2126 signed char *data = (signed char *) SCM_VELTS (v);
c014a02e 2127 unsigned long k = SCM_UVECTOR_LENGTH (v);
af7546eb
DH
2128 while (k != 0)
2129 res = scm_cons (SCM_MAKINUM (data[--k]), res);
2130 return res;
2131 }
2132 case scm_tc7_uvect:
2133 {
c014a02e 2134 long *data = (long *)SCM_VELTS(v);
af7546eb 2135 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2136 res = scm_cons(scm_ulong2num(data[k]), res);
af7546eb
DH
2137 return res;
2138 }
2139 case scm_tc7_ivect:
2140 {
c014a02e 2141 long *data = (long *)SCM_VELTS(v);
af7546eb 2142 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2143 res = scm_cons(scm_long2num(data[k]), res);
af7546eb
DH
2144 return res;
2145 }
2146 case scm_tc7_svect:
2147 {
2148 short *data = (short *)SCM_VELTS(v);
2149 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
1be6b49c 2150 res = scm_cons(scm_short2num (data[k]), res);
af7546eb
DH
2151 return res;
2152 }
2a5cd898 2153#if SCM_SIZEOF_LONG_LONG != 0
af7546eb
DH
2154 case scm_tc7_llvect:
2155 {
1be6b49c 2156 long long *data = (long long *)SCM_VELTS(v);
af7546eb
DH
2157 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
2158 res = scm_cons(scm_long_long2num(data[k]), res);
2159 return res;
2160 }
0f2d19dd 2161#endif
0f2d19dd
JB
2162 case scm_tc7_fvect:
2163 {
2164 float *data = (float *) SCM_VELTS (v);
74014c46 2165 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2166 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2167 return res;
2168 }
0f2d19dd
JB
2169 case scm_tc7_dvect:
2170 {
2171 double *data = (double *) SCM_VELTS (v);
74014c46 2172 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2173 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2174 return res;
2175 }
2176 case scm_tc7_cvect:
2177 {
2178 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2179 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2180 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2181 return res;
2182 }
0f2d19dd
JB
2183 }
2184}
1bbd0b84 2185#undef FUNC_NAME
0f2d19dd
JB
2186
2187
c014a02e 2188static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2189
3b3b36dd 2190SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2191 (SCM ndim, SCM prot, SCM lst),
8f85c0c6 2192 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1e6808ea
MG
2193 "Return a uniform array of the type indicated by prototype\n"
2194 "@var{prot} with elements the same as those of @var{lst}.\n"
2195 "Elements must be of the appropriate type, no coercions are\n"
2196 "done.")
1bbd0b84 2197#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2198{
2199 SCM shp = SCM_EOL;
2200 SCM row = lst;
2201 SCM ra;
c014a02e 2202 unsigned long k;
0f2d19dd 2203 long n;
34d19ef6 2204 SCM_VALIDATE_INUM_COPY (1, ndim, k);
0f2d19dd
JB
2205 while (k--)
2206 {
2207 n = scm_ilength (row);
1bbd0b84 2208 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2209 shp = scm_cons (SCM_MAKINUM (n), shp);
2210 if (SCM_NIMP (row))
2211 row = SCM_CAR (row);
2212 }
d12feca3
GH
2213 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2214 SCM_UNDEFINED);
0f2d19dd 2215 if (SCM_NULLP (shp))
0f2d19dd
JB
2216 {
2217 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2218 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2219 return ra;
2220 }
2221 if (!SCM_ARRAYP (ra))
2222 {
c014a02e 2223 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
74014c46 2224 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2225 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2226 return ra;
2227 }
2228 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2229 return ra;
2230 else
1afff620
KN
2231 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2232 scm_list_1 (lst));
0f2d19dd 2233}
1bbd0b84 2234#undef FUNC_NAME
0f2d19dd 2235
0f2d19dd 2236static int
c014a02e 2237l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2238{
c014a02e
ML
2239 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2240 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2241 int ok = 1;
2242 if (n <= 0)
4260a7fc 2243 return (SCM_NULLP (lst));
0f2d19dd
JB
2244 if (k < SCM_ARRAY_NDIM (ra) - 1)
2245 {
2246 while (n--)
2247 {
1685446c 2248 if (!SCM_CONSP (lst))
0f2d19dd
JB
2249 return 0;
2250 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2251 base += inc;
2252 lst = SCM_CDR (lst);
2253 }
9ff1720f 2254 if (!SCM_NULLP (lst))
0f2d19dd
JB
2255 return 0;
2256 }
2257 else
2258 {
2259 while (n--)
2260 {
1685446c 2261 if (!SCM_CONSP (lst))
0f2d19dd 2262 return 0;
baa702c8 2263 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2264 base += inc;
2265 lst = SCM_CDR (lst);
2266 }
9ff1720f 2267 if (!SCM_NULLP (lst))
fee7ef83 2268 return 0;
0f2d19dd
JB
2269 }
2270 return ok;
2271}
2272
1cc91f1b 2273
0f2d19dd 2274static void
34d19ef6 2275rapr1 (SCM ra, unsigned long j, unsigned long k, SCM port, scm_print_state *pstate)
0f2d19dd 2276{
c014a02e
ML
2277 long inc = 1;
2278 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8
MD
2279 ? 0
2280 : SCM_INUM (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2281 int enclosed = 0;
2282tail:
5c11cc9d 2283 switch SCM_TYP7 (ra)
0f2d19dd
JB
2284 {
2285 case scm_tc7_smob:
2286 if (enclosed++)
2287 {
2288 SCM_ARRAY_BASE (ra) = j;
2289 if (n-- > 0)
9882ea19 2290 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2291 for (j += inc; n-- > 0; j += inc)
2292 {
b7f3516f 2293 scm_putc (' ', port);
0f2d19dd 2294 SCM_ARRAY_BASE (ra) = j;
9882ea19 2295 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2296 }
2297 break;
2298 }
2299 if (k + 1 < SCM_ARRAY_NDIM (ra))
2300 {
c014a02e 2301 long i;
0f2d19dd
JB
2302 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2303 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2304 {
b7f3516f 2305 scm_putc ('(', port);
9882ea19 2306 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2307 scm_puts (") ", port);
0f2d19dd
JB
2308 j += inc;
2309 }
2310 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2311 { /* could be zero size. */
b7f3516f 2312 scm_putc ('(', port);
9882ea19 2313 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2314 scm_putc (')', port);
0f2d19dd
JB
2315 }
2316 break;
2317 }
1be6b49c 2318 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2319 { /* Could be zero-dimensional */
2320 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2321 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2322 }
2323 else
2324 n = 1;
2325 ra = SCM_ARRAY_V (ra);
2326 goto tail;
2327 default:
5c11cc9d 2328 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2329 if (n-- > 0)
9882ea19 2330 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2331 for (j += inc; n-- > 0; j += inc)
2332 {
b7f3516f 2333 scm_putc (' ', port);
9882ea19 2334 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2335 }
2336 break;
2337 case scm_tc7_string:
2338 if (n-- > 0)
322ac0c5 2339 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2340 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2341 for (j += inc; n-- > 0; j += inc)
2342 {
b7f3516f 2343 scm_putc (' ', port);
322ac0c5 2344 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2345 }
2346 else
2347 for (j += inc; n-- > 0; j += inc)
405aaef9 2348 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2349 break;
2350 case scm_tc7_byvect:
2351 if (n-- > 0)
4260a7fc 2352 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2353 for (j += inc; n-- > 0; j += inc)
2354 {
b7f3516f 2355 scm_putc (' ', port);
4260a7fc 2356 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2357 }
2358 break;
2359
2360 case scm_tc7_uvect:
5c11cc9d
GH
2361 {
2362 char str[11];
2363
2364 if (n-- > 0)
2365 {
2366 /* intprint can't handle >= 2^31. */
fee7ef83 2367 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2368 scm_puts (str, port);
2369 }
2370 for (j += inc; n-- > 0; j += inc)
2371 {
2372 scm_putc (' ', port);
fee7ef83 2373 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2374 scm_puts (str, port);
2375 }
2376 }
0f2d19dd
JB
2377 case scm_tc7_ivect:
2378 if (n-- > 0)
fee7ef83 2379 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2380 for (j += inc; n-- > 0; j += inc)
2381 {
b7f3516f 2382 scm_putc (' ', port);
fee7ef83 2383 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2384 }
2385 break;
2386
2387 case scm_tc7_svect:
2388 if (n-- > 0)
4260a7fc 2389 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2390 for (j += inc; n-- > 0; j += inc)
2391 {
b7f3516f 2392 scm_putc (' ', port);
4260a7fc 2393 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2394 }
2395 break;
2396
0f2d19dd
JB
2397 case scm_tc7_fvect:
2398 if (n-- > 0)
2399 {
bc86da5d
MD
2400 SCM z = scm_make_real (1.0);
2401 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2402 scm_print_real (z, port, pstate);
0f2d19dd
JB
2403 for (j += inc; n-- > 0; j += inc)
2404 {
b7f3516f 2405 scm_putc (' ', port);
bc86da5d
MD
2406 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2407 scm_print_real (z, port, pstate);
0f2d19dd
JB
2408 }
2409 }
2410 break;
0f2d19dd
JB
2411 case scm_tc7_dvect:
2412 if (n-- > 0)
2413 {
bc86da5d
MD
2414 SCM z = scm_make_real (1.0 / 3.0);
2415 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2416 scm_print_real (z, port, pstate);
0f2d19dd
JB
2417 for (j += inc; n-- > 0; j += inc)
2418 {
b7f3516f 2419 scm_putc (' ', port);
bc86da5d
MD
2420 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2421 scm_print_real (z, port, pstate);
0f2d19dd
JB
2422 }
2423 }
2424 break;
2425 case scm_tc7_cvect:
2426 if (n-- > 0)
2427 {
bc86da5d
MD
2428 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2429 SCM_REAL_VALUE (z) =
2430 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2431 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2432 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2433 port, pstate);
0f2d19dd
JB
2434 for (j += inc; n-- > 0; j += inc)
2435 {
b7f3516f 2436 scm_putc (' ', port);
bc86da5d
MD
2437 SCM_REAL_VALUE (z)
2438 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2439 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2440 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2441 port, pstate);
0f2d19dd
JB
2442 }
2443 }
2444 break;
0f2d19dd
JB
2445 }
2446}
2447
2448
1cc91f1b 2449
0f2d19dd 2450int
1bbd0b84 2451scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2452{
2453 SCM v = exp;
c014a02e 2454 unsigned long base = 0;
b7f3516f 2455 scm_putc ('#', port);
0f2d19dd 2456tail:
5c11cc9d 2457 switch SCM_TYP7 (v)
0f2d19dd
JB
2458 {
2459 case scm_tc7_smob:
2460 {
2461 long ndim = SCM_ARRAY_NDIM (v);
2462 base = SCM_ARRAY_BASE (v);
2463 v = SCM_ARRAY_V (v);
2464 if (SCM_ARRAYP (v))
2465
2466 {
b7f3516f 2467 scm_puts ("<enclosed-array ", port);
9882ea19 2468 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2469 scm_putc ('>', port);
0f2d19dd
JB
2470 return 1;
2471 }
2472 else
2473 {
2474 scm_intprint (ndim, 10, port);
2475 goto tail;
2476 }
2477 }
2478 case scm_tc7_bvect:
fee7ef83 2479 if (SCM_EQ_P (exp, v))
0f2d19dd 2480 { /* a uve, not an scm_array */
c014a02e 2481 register long i, j, w;
b7f3516f 2482 scm_putc ('*', port);
c014a02e 2483 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2484 {
92c2555f 2485 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2486 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2487 {
b7f3516f 2488 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2489 w >>= 1;
2490 }
2491 }
c014a02e 2492 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2493 if (j)
2494 {
c014a02e 2495 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2496 for (; j; j--)
2497 {
b7f3516f 2498 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2499 w >>= 1;
2500 }
2501 }
2502 return 1;
2503 }
2504 else
b7f3516f 2505 scm_putc ('b', port);
0f2d19dd
JB
2506 break;
2507 case scm_tc7_string:
b7f3516f 2508 scm_putc ('a', port);
0f2d19dd
JB
2509 break;
2510 case scm_tc7_byvect:
05c33d09 2511 scm_putc ('y', port);
0f2d19dd
JB
2512 break;
2513 case scm_tc7_uvect:
b7f3516f 2514 scm_putc ('u', port);
0f2d19dd
JB
2515 break;
2516 case scm_tc7_ivect:
b7f3516f 2517 scm_putc ('e', port);
0f2d19dd
JB
2518 break;
2519 case scm_tc7_svect:
05c33d09 2520 scm_putc ('h', port);
0f2d19dd 2521 break;
2a5cd898 2522#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 2523 case scm_tc7_llvect:
5c11cc9d 2524 scm_putc ('l', port);
0f2d19dd
JB
2525 break;
2526#endif
0f2d19dd 2527 case scm_tc7_fvect:
b7f3516f 2528 scm_putc ('s', port);
0f2d19dd 2529 break;
0f2d19dd 2530 case scm_tc7_dvect:
b7f3516f 2531 scm_putc ('i', port);
0f2d19dd
JB
2532 break;
2533 case scm_tc7_cvect:
b7f3516f 2534 scm_putc ('c', port);
0f2d19dd 2535 break;
0f2d19dd 2536 }
b7f3516f 2537 scm_putc ('(', port);
9882ea19 2538 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2539 scm_putc (')', port);
0f2d19dd
JB
2540 return 1;
2541}
2542
3b3b36dd 2543SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2544 (SCM ra),
1e6808ea
MG
2545 "Return an object that would produce an array of the same type\n"
2546 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2547 "@code{make-uniform-array}.")
1bbd0b84 2548#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2549{
2550 int enclosed = 0;
2551 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2552loop:
74014c46 2553 switch SCM_TYP7 (ra)
0f2d19dd
JB
2554 {
2555 default:
276dd677 2556 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
2557 case scm_tc7_smob:
2558 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2559 if (enclosed++)
2560 return SCM_UNSPECIFIED;
2561 ra = SCM_ARRAY_V (ra);
2562 goto loop;
2563 case scm_tc7_vector:
95f5b0f5 2564 case scm_tc7_wvect:
0f2d19dd
JB
2565 return SCM_EOL;
2566 case scm_tc7_bvect:
2567 return SCM_BOOL_T;
2568 case scm_tc7_string:
7866a09b 2569 return SCM_MAKE_CHAR ('a');
0f2d19dd 2570 case scm_tc7_byvect:
7866a09b 2571 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2572 case scm_tc7_uvect:
2573 return SCM_MAKINUM (1L);
2574 case scm_tc7_ivect:
2575 return SCM_MAKINUM (-1L);
2576 case scm_tc7_svect:
38ae064c 2577 return scm_str2symbol ("s");
2a5cd898 2578#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 2579 case scm_tc7_llvect:
38ae064c 2580 return scm_str2symbol ("l");
0f2d19dd 2581#endif
0f2d19dd 2582 case scm_tc7_fvect:
bc86da5d 2583 return scm_make_real (1.0);
0f2d19dd 2584 case scm_tc7_dvect:
7c183c95 2585 return exactly_one_third;
0f2d19dd 2586 case scm_tc7_cvect:
bc86da5d 2587 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2588 }
2589}
1bbd0b84 2590#undef FUNC_NAME
0f2d19dd 2591
1cc91f1b 2592
0f2d19dd 2593static SCM
e841c3e0 2594array_mark (SCM ptr)
0f2d19dd 2595{
0f2d19dd
JB
2596 return SCM_ARRAY_V (ptr);
2597}
2598
1cc91f1b 2599
1be6b49c 2600static size_t
e841c3e0 2601array_free (SCM ptr)
0f2d19dd 2602{
4c9419ac
MV
2603 scm_gc_free (SCM_ARRAY_MEM (ptr),
2604 (sizeof (scm_t_array)
2605 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2606 "array");
2607 return 0;
0f2d19dd
JB
2608}
2609
0f2d19dd
JB
2610void
2611scm_init_unif ()
0f2d19dd 2612{
e841c3e0
KN
2613 scm_tc16_array = scm_make_smob_type ("array", 0);
2614 scm_set_smob_mark (scm_tc16_array, array_mark);
2615 scm_set_smob_free (scm_tc16_array, array_free);
2616 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2617 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
7c183c95
KR
2618 exactly_one_third = scm_permanent_object (scm_make_ratio (SCM_MAKINUM (1),
2619 SCM_MAKINUM (3)));
0f2d19dd 2620 scm_add_feature ("array");
a0599745 2621#include "libguile/unif.x"
0f2d19dd 2622}
89e00824
ML
2623
2624/*
2625 Local Variables:
2626 c-file-style: "gnu"
2627 End:
2628*/