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