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