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