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