* srfi/srfi-1.c (srfi1_ilength), libguile/list.c (scm_ilength,
[bpt/guile.git] / libguile / unif.c
CommitLineData
b3fcac34 1/* Copyright (C) 1995,1996,1997,1998,2000,2001 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 }
1be6b49c 476 while (k && !SCM_NULLP (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:
fee7ef83 1187 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
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:
fee7ef83 1194 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
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:
bc86da5d 1201 if (SCM_NIMP (last) && SCM_SLOPPY_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),
1e6808ea
MG
1798 "Return the minimum index of an occurrence of @var{bool} in\n"
1799 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1800 "within the specified range @code{#f} is returned.")
1bbd0b84 1801#define FUNC_NAME s_scm_bit_position
0f2d19dd 1802{
c014a02e
ML
1803 long i, lenw, xbits, pos;
1804 register unsigned long w;
74014c46
DH
1805
1806 SCM_VALIDATE_BOOL (1, item);
1807 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
34d19ef6 1808 SCM_VALIDATE_INUM_COPY (3, k, pos);
74014c46
DH
1809 SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
1810
1811 if (pos == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1812 return SCM_BOOL_F;
74014c46 1813
c014a02e
ML
1814 lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1815 i = pos / SCM_LONG_BIT;
74014c46
DH
1816 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1817 if (SCM_FALSEP (item))
1818 w = ~w;
c014a02e 1819 xbits = (pos % SCM_LONG_BIT);
74014c46
DH
1820 pos -= xbits;
1821 w = ((w >> xbits) << xbits);
c014a02e 1822 xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
74014c46
DH
1823 while (!0)
1824 {
1825 if (w && (i == lenw))
1826 w = ((w << xbits) >> xbits);
1827 if (w)
1828 while (w)
1829 switch (w & 0x0f)
1830 {
1831 default:
1832 return SCM_MAKINUM (pos);
1833 case 2:
1834 case 6:
1835 case 10:
1836 case 14:
1837 return SCM_MAKINUM (pos + 1);
1838 case 4:
1839 case 12:
1840 return SCM_MAKINUM (pos + 2);
1841 case 8:
1842 return SCM_MAKINUM (pos + 3);
1843 case 0:
1844 pos += 4;
1845 w >>= 4;
1846 }
1847 if (++i > lenw)
1848 break;
c014a02e 1849 pos += SCM_LONG_BIT;
f1267706 1850 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1851 if (SCM_FALSEP (item))
1852 w = ~w;
0f2d19dd 1853 }
74014c46 1854 return SCM_BOOL_F;
0f2d19dd 1855}
1bbd0b84 1856#undef FUNC_NAME
0f2d19dd
JB
1857
1858
3b3b36dd 1859SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
c7eb8761
MG
1860 (SCM v, SCM kv, SCM obj),
1861 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1862 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1863 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1864 "AND'ed into @var{bv}.\n\n"
8f85c0c6 1865 "If uve is a unsigned long integer vector all the elements of uve\n"
c7eb8761
MG
1866 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1867 "of @var{bv} corresponding to the indexes in uve are set to\n"
1868 "@var{bool}. The return value is unspecified.")
1bbd0b84 1869#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd 1870{
c014a02e 1871 register long i, k, vlen;
74014c46 1872 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1873 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1874 switch SCM_TYP7 (kv)
0f2d19dd
JB
1875 {
1876 default:
276dd677 1877 badarg2:SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1878 case scm_tc7_uvect:
74014c46
DH
1879 vlen = SCM_BITVECTOR_LENGTH (v);
1880 if (SCM_FALSEP (obj))
1881 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1882 {
c014a02e 1883 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1884 if (k >= vlen)
1885 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1886 SCM_BITVEC_CLR(v, k);
74014c46
DH
1887 }
1888 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1889 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1890 {
c014a02e 1891 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1892 if (k >= vlen)
1893 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1894 SCM_BITVEC_SET(v, k);
74014c46
DH
1895 }
1896 else
276dd677 1897 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1898 break;
1899 case scm_tc7_bvect:
74014c46 1900 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
4260a7fc 1901 if (SCM_FALSEP (obj))
c014a02e 1902 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1903 SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
9a09deb1 1904 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c014a02e 1905 for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1906 SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
0f2d19dd
JB
1907 else
1908 goto badarg3;
1909 break;
1910 }
1911 return SCM_UNSPECIFIED;
1912}
1bbd0b84 1913#undef FUNC_NAME
0f2d19dd
JB
1914
1915
3b3b36dd 1916SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1917 (SCM v, SCM kv, SCM obj),
1e6808ea
MG
1918 "Return\n"
1919 "@lisp\n"
b380b885 1920 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1e6808ea 1921 "@end lisp\n"
b380b885 1922 "@var{bv} is not modified.")
1bbd0b84 1923#define FUNC_NAME s_scm_bit_count_star
0f2d19dd 1924{
c014a02e
ML
1925 register long i, vlen, count = 0;
1926 register unsigned long k;
41b0806d 1927 int fObj = 0;
c209c88e 1928
74014c46 1929 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
0f2d19dd 1930 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1931 switch SCM_TYP7 (kv)
0f2d19dd
JB
1932 {
1933 default:
c209c88e 1934 badarg2:
276dd677 1935 SCM_WRONG_TYPE_ARG (2, kv);
0f2d19dd 1936 case scm_tc7_uvect:
74014c46
DH
1937 vlen = SCM_BITVECTOR_LENGTH (v);
1938 if (SCM_FALSEP (obj))
1939 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1940 {
c014a02e 1941 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1942 if (k >= vlen)
1943 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1944 if (!SCM_BITVEC_REF(v, k))
74014c46
DH
1945 count++;
1946 }
1947 else if (SCM_EQ_P (obj, SCM_BOOL_T))
1948 for (i = SCM_UVECTOR_LENGTH (kv); i;)
1949 {
c014a02e 1950 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
74014c46
DH
1951 if (k >= vlen)
1952 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
34d19ef6 1953 if (SCM_BITVEC_REF (v, k))
74014c46
DH
1954 count++;
1955 }
1956 else
276dd677 1957 badarg3:SCM_WRONG_TYPE_ARG (3, obj);
0f2d19dd
JB
1958 break;
1959 case scm_tc7_bvect:
74014c46
DH
1960 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
1961 if (0 == SCM_BITVECTOR_LENGTH (v))
0f2d19dd 1962 return SCM_INUM0;
4260a7fc 1963 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1964 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
c014a02e
ML
1965 i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
1966 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1967 k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1968 while (1)
0f2d19dd
JB
1969 {
1970 for (; k; k >>= 4)
1971 count += cnt_tab[k & 0x0f];
1972 if (0 == i--)
1973 return SCM_MAKINUM (count);
c209c88e
GB
1974
1975 /* urg. repetitive (see above.) */
c014a02e 1976 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1977 }
1978 }
1979 return SCM_MAKINUM (count);
1980}
1bbd0b84 1981#undef FUNC_NAME
0f2d19dd
JB
1982
1983
3b3b36dd 1984SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1985 (SCM v),
8f85c0c6 1986 "Modify @var{bv} by replacing each element with its negation.")
1bbd0b84 1987#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd 1988{
c014a02e 1989 long int k;
74014c46
DH
1990
1991 SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
1992
1993 k = SCM_BITVECTOR_LENGTH (v);
c014a02e 1994 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
bab246f3 1995 SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
74014c46 1996
0f2d19dd
JB
1997 return SCM_UNSPECIFIED;
1998}
1bbd0b84 1999#undef FUNC_NAME
0f2d19dd
JB
2000
2001
0f2d19dd 2002SCM
c014a02e 2003scm_istr2bve (char *str, long len)
0f2d19dd
JB
2004{
2005 SCM v = scm_make_uve (len, SCM_BOOL_T);
c014a02e
ML
2006 long *data = (long *) SCM_VELTS (v);
2007 register unsigned long mask;
2008 register long k;
2009 register long j;
2010 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
0f2d19dd
JB
2011 {
2012 data[k] = 0L;
c014a02e
ML
2013 j = len - k * SCM_LONG_BIT;
2014 if (j > SCM_LONG_BIT)
2015 j = SCM_LONG_BIT;
0f2d19dd
JB
2016 for (mask = 1L; j--; mask <<= 1)
2017 switch (*str++)
2018 {
2019 case '0':
2020 break;
2021 case '1':
2022 data[k] |= mask;
2023 break;
2024 default:
2025 return SCM_BOOL_F;
2026 }
2027 }
2028 return v;
2029}
2030
2031
1cc91f1b 2032
0f2d19dd 2033static SCM
34d19ef6 2034ra2l (SCM ra, unsigned long base, unsigned long k)
0f2d19dd
JB
2035{
2036 register SCM res = SCM_EOL;
c014a02e
ML
2037 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2038 register size_t i;
0f2d19dd
JB
2039 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2040 return SCM_EOL;
2041 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2042 if (k < SCM_ARRAY_NDIM (ra) - 1)
2043 {
2044 do
2045 {
2046 i -= inc;
2047 res = scm_cons (ra2l (ra, i, k + 1), res);
2048 }
2049 while (i != base);
2050 }
2051 else
2052 do
2053 {
2054 i -= inc;
2055 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2056 }
2057 while (i != base);
2058 return res;
2059}
2060
2061
cd328b4f 2062SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2063 (SCM v),
1e6808ea
MG
2064 "Return a list consisting of all the elements, in order, of\n"
2065 "@var{array}.")
cd328b4f 2066#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2067{
2068 SCM res = SCM_EOL;
c014a02e 2069 register long k;
0f2d19dd 2070 SCM_ASRTGO (SCM_NIMP (v), badarg1);
74014c46 2071 switch SCM_TYP7 (v)
0f2d19dd
JB
2072 {
2073 default:
276dd677 2074 badarg1:SCM_WRONG_TYPE_ARG (1, v);
0f2d19dd
JB
2075 case scm_tc7_smob:
2076 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2077 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2078 case scm_tc7_vector:
95f5b0f5 2079 case scm_tc7_wvect:
0f2d19dd
JB
2080 return scm_vector_to_list (v);
2081 case scm_tc7_string:
2082 return scm_string_to_list (v);
2083 case scm_tc7_bvect:
2084 {
c014a02e
ML
2085 long *data = (long *) SCM_VELTS (v);
2086 register unsigned long mask;
2087 for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2088 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2089 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2090 for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2091 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2092 return res;
2093 }
af7546eb
DH
2094 case scm_tc7_byvect:
2095 {
2096 signed char *data = (signed char *) SCM_VELTS (v);
c014a02e 2097 unsigned long k = SCM_UVECTOR_LENGTH (v);
af7546eb
DH
2098 while (k != 0)
2099 res = scm_cons (SCM_MAKINUM (data[--k]), res);
2100 return res;
2101 }
2102 case scm_tc7_uvect:
2103 {
c014a02e 2104 long *data = (long *)SCM_VELTS(v);
af7546eb 2105 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2106 res = scm_cons(scm_ulong2num(data[k]), res);
af7546eb
DH
2107 return res;
2108 }
2109 case scm_tc7_ivect:
2110 {
c014a02e 2111 long *data = (long *)SCM_VELTS(v);
af7546eb 2112 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
c014a02e 2113 res = scm_cons(scm_long2num(data[k]), res);
af7546eb
DH
2114 return res;
2115 }
2116 case scm_tc7_svect:
2117 {
2118 short *data = (short *)SCM_VELTS(v);
2119 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
1be6b49c 2120 res = scm_cons(scm_short2num (data[k]), res);
af7546eb
DH
2121 return res;
2122 }
2a5cd898 2123#if SCM_SIZEOF_LONG_LONG != 0
af7546eb
DH
2124 case scm_tc7_llvect:
2125 {
1be6b49c 2126 long long *data = (long long *)SCM_VELTS(v);
af7546eb
DH
2127 for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
2128 res = scm_cons(scm_long_long2num(data[k]), res);
2129 return res;
2130 }
0f2d19dd 2131#endif
0f2d19dd
JB
2132 case scm_tc7_fvect:
2133 {
2134 float *data = (float *) SCM_VELTS (v);
74014c46 2135 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2136 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2137 return res;
2138 }
0f2d19dd
JB
2139 case scm_tc7_dvect:
2140 {
2141 double *data = (double *) SCM_VELTS (v);
74014c46 2142 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2143 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2144 return res;
2145 }
2146 case scm_tc7_cvect:
2147 {
2148 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
74014c46 2149 for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2150 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2151 return res;
2152 }
0f2d19dd
JB
2153 }
2154}
1bbd0b84 2155#undef FUNC_NAME
0f2d19dd
JB
2156
2157
c014a02e 2158static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
1cc91f1b 2159
3b3b36dd 2160SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2161 (SCM ndim, SCM prot, SCM lst),
8f85c0c6 2162 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1e6808ea
MG
2163 "Return a uniform array of the type indicated by prototype\n"
2164 "@var{prot} with elements the same as those of @var{lst}.\n"
2165 "Elements must be of the appropriate type, no coercions are\n"
2166 "done.")
1bbd0b84 2167#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2168{
2169 SCM shp = SCM_EOL;
2170 SCM row = lst;
2171 SCM ra;
c014a02e 2172 unsigned long k;
0f2d19dd 2173 long n;
34d19ef6 2174 SCM_VALIDATE_INUM_COPY (1, ndim, k);
0f2d19dd
JB
2175 while (k--)
2176 {
2177 n = scm_ilength (row);
1bbd0b84 2178 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2179 shp = scm_cons (SCM_MAKINUM (n), shp);
2180 if (SCM_NIMP (row))
2181 row = SCM_CAR (row);
2182 }
d12feca3
GH
2183 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2184 SCM_UNDEFINED);
0f2d19dd 2185 if (SCM_NULLP (shp))
0f2d19dd
JB
2186 {
2187 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2188 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2189 return ra;
2190 }
2191 if (!SCM_ARRAYP (ra))
2192 {
c014a02e 2193 unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
74014c46 2194 for (k = 0; k < length; k++, lst = SCM_CDR (lst))
0f2d19dd
JB
2195 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2196 return ra;
2197 }
2198 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2199 return ra;
2200 else
1afff620
KN
2201 badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2202 scm_list_1 (lst));
0f2d19dd 2203}
1bbd0b84 2204#undef FUNC_NAME
0f2d19dd 2205
0f2d19dd 2206static int
c014a02e 2207l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
0f2d19dd 2208{
c014a02e
ML
2209 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2210 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
0f2d19dd
JB
2211 int ok = 1;
2212 if (n <= 0)
4260a7fc 2213 return (SCM_NULLP (lst));
0f2d19dd
JB
2214 if (k < SCM_ARRAY_NDIM (ra) - 1)
2215 {
2216 while (n--)
2217 {
1685446c 2218 if (!SCM_CONSP (lst))
0f2d19dd
JB
2219 return 0;
2220 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2221 base += inc;
2222 lst = SCM_CDR (lst);
2223 }
9ff1720f 2224 if (!SCM_NULLP (lst))
0f2d19dd
JB
2225 return 0;
2226 }
2227 else
2228 {
2229 while (n--)
2230 {
1685446c 2231 if (!SCM_CONSP (lst))
0f2d19dd 2232 return 0;
baa702c8 2233 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2234 base += inc;
2235 lst = SCM_CDR (lst);
2236 }
9ff1720f 2237 if (!SCM_NULLP (lst))
fee7ef83 2238 return 0;
0f2d19dd
JB
2239 }
2240 return ok;
2241}
2242
1cc91f1b 2243
0f2d19dd 2244static void
34d19ef6 2245rapr1 (SCM ra, unsigned long j, unsigned long k, SCM port, scm_print_state *pstate)
0f2d19dd 2246{
c014a02e
ML
2247 long inc = 1;
2248 long n = (SCM_TYP7 (ra) == scm_tc7_smob
b8446ce8
MD
2249 ? 0
2250 : SCM_INUM (scm_uniform_vector_length (ra)));
0f2d19dd
JB
2251 int enclosed = 0;
2252tail:
5c11cc9d 2253 switch SCM_TYP7 (ra)
0f2d19dd
JB
2254 {
2255 case scm_tc7_smob:
2256 if (enclosed++)
2257 {
2258 SCM_ARRAY_BASE (ra) = j;
2259 if (n-- > 0)
9882ea19 2260 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2261 for (j += inc; n-- > 0; j += inc)
2262 {
b7f3516f 2263 scm_putc (' ', port);
0f2d19dd 2264 SCM_ARRAY_BASE (ra) = j;
9882ea19 2265 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2266 }
2267 break;
2268 }
2269 if (k + 1 < SCM_ARRAY_NDIM (ra))
2270 {
c014a02e 2271 long i;
0f2d19dd
JB
2272 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2273 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2274 {
b7f3516f 2275 scm_putc ('(', port);
9882ea19 2276 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2277 scm_puts (") ", port);
0f2d19dd
JB
2278 j += inc;
2279 }
2280 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2281 { /* could be zero size. */
b7f3516f 2282 scm_putc ('(', port);
9882ea19 2283 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2284 scm_putc (')', port);
0f2d19dd
JB
2285 }
2286 break;
2287 }
1be6b49c 2288 if (SCM_ARRAY_NDIM (ra) > 0)
0f2d19dd
JB
2289 { /* Could be zero-dimensional */
2290 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2291 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2292 }
2293 else
2294 n = 1;
2295 ra = SCM_ARRAY_V (ra);
2296 goto tail;
2297 default:
5c11cc9d 2298 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2299 if (n-- > 0)
9882ea19 2300 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2301 for (j += inc; n-- > 0; j += inc)
2302 {
b7f3516f 2303 scm_putc (' ', port);
9882ea19 2304 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2305 }
2306 break;
2307 case scm_tc7_string:
2308 if (n-- > 0)
322ac0c5 2309 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
9882ea19 2310 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2311 for (j += inc; n-- > 0; j += inc)
2312 {
b7f3516f 2313 scm_putc (' ', port);
322ac0c5 2314 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2315 }
2316 else
2317 for (j += inc; n-- > 0; j += inc)
405aaef9 2318 scm_putc (SCM_STRING_CHARS (ra)[j], port);
0f2d19dd
JB
2319 break;
2320 case scm_tc7_byvect:
2321 if (n-- > 0)
4260a7fc 2322 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2323 for (j += inc; n-- > 0; j += inc)
2324 {
b7f3516f 2325 scm_putc (' ', port);
4260a7fc 2326 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2327 }
2328 break;
2329
2330 case scm_tc7_uvect:
5c11cc9d
GH
2331 {
2332 char str[11];
2333
2334 if (n-- > 0)
2335 {
2336 /* intprint can't handle >= 2^31. */
fee7ef83 2337 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2338 scm_puts (str, port);
2339 }
2340 for (j += inc; n-- > 0; j += inc)
2341 {
2342 scm_putc (' ', port);
fee7ef83 2343 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2344 scm_puts (str, port);
2345 }
2346 }
0f2d19dd
JB
2347 case scm_tc7_ivect:
2348 if (n-- > 0)
fee7ef83 2349 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2350 for (j += inc; n-- > 0; j += inc)
2351 {
b7f3516f 2352 scm_putc (' ', port);
fee7ef83 2353 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2354 }
2355 break;
2356
2357 case scm_tc7_svect:
2358 if (n-- > 0)
4260a7fc 2359 scm_intprint (((short *) 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 (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2364 }
2365 break;
2366
0f2d19dd
JB
2367 case scm_tc7_fvect:
2368 if (n-- > 0)
2369 {
bc86da5d
MD
2370 SCM z = scm_make_real (1.0);
2371 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2372 scm_print_real (z, port, pstate);
0f2d19dd
JB
2373 for (j += inc; n-- > 0; j += inc)
2374 {
b7f3516f 2375 scm_putc (' ', port);
bc86da5d
MD
2376 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2377 scm_print_real (z, port, pstate);
0f2d19dd
JB
2378 }
2379 }
2380 break;
0f2d19dd
JB
2381 case scm_tc7_dvect:
2382 if (n-- > 0)
2383 {
bc86da5d
MD
2384 SCM z = scm_make_real (1.0 / 3.0);
2385 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2386 scm_print_real (z, port, pstate);
0f2d19dd
JB
2387 for (j += inc; n-- > 0; j += inc)
2388 {
b7f3516f 2389 scm_putc (' ', port);
bc86da5d
MD
2390 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2391 scm_print_real (z, port, pstate);
0f2d19dd
JB
2392 }
2393 }
2394 break;
2395 case scm_tc7_cvect:
2396 if (n-- > 0)
2397 {
bc86da5d
MD
2398 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2399 SCM_REAL_VALUE (z) =
2400 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2401 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2402 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2403 port, pstate);
0f2d19dd
JB
2404 for (j += inc; n-- > 0; j += inc)
2405 {
b7f3516f 2406 scm_putc (' ', port);
bc86da5d
MD
2407 SCM_REAL_VALUE (z)
2408 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2409 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2410 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2411 port, pstate);
0f2d19dd
JB
2412 }
2413 }
2414 break;
0f2d19dd
JB
2415 }
2416}
2417
2418
1cc91f1b 2419
0f2d19dd 2420int
1bbd0b84 2421scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2422{
2423 SCM v = exp;
c014a02e 2424 unsigned long base = 0;
b7f3516f 2425 scm_putc ('#', port);
0f2d19dd 2426tail:
5c11cc9d 2427 switch SCM_TYP7 (v)
0f2d19dd
JB
2428 {
2429 case scm_tc7_smob:
2430 {
2431 long ndim = SCM_ARRAY_NDIM (v);
2432 base = SCM_ARRAY_BASE (v);
2433 v = SCM_ARRAY_V (v);
2434 if (SCM_ARRAYP (v))
2435
2436 {
b7f3516f 2437 scm_puts ("<enclosed-array ", port);
9882ea19 2438 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2439 scm_putc ('>', port);
0f2d19dd
JB
2440 return 1;
2441 }
2442 else
2443 {
2444 scm_intprint (ndim, 10, port);
2445 goto tail;
2446 }
2447 }
2448 case scm_tc7_bvect:
fee7ef83 2449 if (SCM_EQ_P (exp, v))
0f2d19dd 2450 { /* a uve, not an scm_array */
c014a02e 2451 register long i, j, w;
b7f3516f 2452 scm_putc ('*', port);
c014a02e 2453 for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
0f2d19dd 2454 {
92c2555f 2455 scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
c014a02e 2456 for (j = SCM_LONG_BIT; j; j--)
0f2d19dd 2457 {
b7f3516f 2458 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2459 w >>= 1;
2460 }
2461 }
c014a02e 2462 j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
0f2d19dd
JB
2463 if (j)
2464 {
c014a02e 2465 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2466 for (; j; j--)
2467 {
b7f3516f 2468 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2469 w >>= 1;
2470 }
2471 }
2472 return 1;
2473 }
2474 else
b7f3516f 2475 scm_putc ('b', port);
0f2d19dd
JB
2476 break;
2477 case scm_tc7_string:
b7f3516f 2478 scm_putc ('a', port);
0f2d19dd
JB
2479 break;
2480 case scm_tc7_byvect:
05c33d09 2481 scm_putc ('y', port);
0f2d19dd
JB
2482 break;
2483 case scm_tc7_uvect:
b7f3516f 2484 scm_putc ('u', port);
0f2d19dd
JB
2485 break;
2486 case scm_tc7_ivect:
b7f3516f 2487 scm_putc ('e', port);
0f2d19dd
JB
2488 break;
2489 case scm_tc7_svect:
05c33d09 2490 scm_putc ('h', port);
0f2d19dd 2491 break;
2a5cd898 2492#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 2493 case scm_tc7_llvect:
5c11cc9d 2494 scm_putc ('l', port);
0f2d19dd
JB
2495 break;
2496#endif
0f2d19dd 2497 case scm_tc7_fvect:
b7f3516f 2498 scm_putc ('s', port);
0f2d19dd 2499 break;
0f2d19dd 2500 case scm_tc7_dvect:
b7f3516f 2501 scm_putc ('i', port);
0f2d19dd
JB
2502 break;
2503 case scm_tc7_cvect:
b7f3516f 2504 scm_putc ('c', port);
0f2d19dd 2505 break;
0f2d19dd 2506 }
b7f3516f 2507 scm_putc ('(', port);
9882ea19 2508 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2509 scm_putc (')', port);
0f2d19dd
JB
2510 return 1;
2511}
2512
3b3b36dd 2513SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2514 (SCM ra),
1e6808ea
MG
2515 "Return an object that would produce an array of the same type\n"
2516 "as @var{array}, if used as the @var{prototype} for\n"
b380b885 2517 "@code{make-uniform-array}.")
1bbd0b84 2518#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2519{
2520 int enclosed = 0;
2521 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2522loop:
74014c46 2523 switch SCM_TYP7 (ra)
0f2d19dd
JB
2524 {
2525 default:
276dd677 2526 badarg:SCM_WRONG_TYPE_ARG (1, ra);
0f2d19dd
JB
2527 case scm_tc7_smob:
2528 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2529 if (enclosed++)
2530 return SCM_UNSPECIFIED;
2531 ra = SCM_ARRAY_V (ra);
2532 goto loop;
2533 case scm_tc7_vector:
95f5b0f5 2534 case scm_tc7_wvect:
0f2d19dd
JB
2535 return SCM_EOL;
2536 case scm_tc7_bvect:
2537 return SCM_BOOL_T;
2538 case scm_tc7_string:
7866a09b 2539 return SCM_MAKE_CHAR ('a');
0f2d19dd 2540 case scm_tc7_byvect:
7866a09b 2541 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2542 case scm_tc7_uvect:
2543 return SCM_MAKINUM (1L);
2544 case scm_tc7_ivect:
2545 return SCM_MAKINUM (-1L);
2546 case scm_tc7_svect:
38ae064c 2547 return scm_str2symbol ("s");
2a5cd898 2548#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 2549 case scm_tc7_llvect:
38ae064c 2550 return scm_str2symbol ("l");
0f2d19dd 2551#endif
0f2d19dd 2552 case scm_tc7_fvect:
bc86da5d 2553 return scm_make_real (1.0);
0f2d19dd 2554 case scm_tc7_dvect:
bc86da5d 2555 return scm_make_real (1.0 / 3.0);
0f2d19dd 2556 case scm_tc7_cvect:
bc86da5d 2557 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2558 }
2559}
1bbd0b84 2560#undef FUNC_NAME
0f2d19dd 2561
1cc91f1b 2562
0f2d19dd 2563static SCM
e841c3e0 2564array_mark (SCM ptr)
0f2d19dd 2565{
0f2d19dd
JB
2566 return SCM_ARRAY_V (ptr);
2567}
2568
1cc91f1b 2569
1be6b49c 2570static size_t
e841c3e0 2571array_free (SCM ptr)
0f2d19dd 2572{
4c9419ac
MV
2573 scm_gc_free (SCM_ARRAY_MEM (ptr),
2574 (sizeof (scm_t_array)
2575 + SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim)),
2576 "array");
2577 return 0;
0f2d19dd
JB
2578}
2579
0f2d19dd
JB
2580void
2581scm_init_unif ()
0f2d19dd 2582{
e841c3e0
KN
2583 scm_tc16_array = scm_make_smob_type ("array", 0);
2584 scm_set_smob_mark (scm_tc16_array, array_mark);
2585 scm_set_smob_free (scm_tc16_array, array_free);
2586 scm_set_smob_print (scm_tc16_array, scm_raprin1);
2587 scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
0f2d19dd 2588 scm_add_feature ("array");
a0599745 2589#include "libguile/unif.x"
0f2d19dd 2590}
89e00824
ML
2591
2592/*
2593 Local Variables:
2594 c-file-style: "gnu"
2595 End:
2596*/