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