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