1 /* Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
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)
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.
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
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
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.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
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.
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. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
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.)
58 #include "libguile/_scm.h"
59 #include "libguile/chars.h"
60 #include "libguile/eval.h"
61 #include "libguile/fports.h"
62 #include "libguile/smob.h"
63 #include "libguile/strop.h"
64 #include "libguile/feature.h"
65 #include "libguile/root.h"
66 #include "libguile/strings.h"
67 #include "libguile/vectors.h"
69 #include "libguile/validate.h"
70 #include "libguile/unif.h"
71 #include "libguile/ramap.h"
78 /* The set of uniform scm_vector types is:
80 * unsigned char string
87 * complex double cvect
92 scm_bits_t scm_tc16_array
;
94 /* return the size of an element in a uniform array or 0 if type not
97 scm_uniform_element_size (SCM obj
)
101 switch (SCM_TYP7 (obj
))
104 result
= sizeof (scm_bits_t
);
108 result
= sizeof (long);
112 result
= sizeof (char);
116 result
= sizeof (short);
119 #ifdef HAVE_LONG_LONGS
121 result
= sizeof (long long);
126 result
= sizeof (float);
130 result
= sizeof (double);
134 result
= 2 * sizeof (double);
143 /* Silly function used not to modify the semantics of the silly
144 * prototype system in order to be backward compatible.
149 if (!SCM_SLOPPY_REALP (obj
))
153 double x
= SCM_REAL_VALUE (obj
);
155 return (- SCM_FLTMAX
< x
) && (x
< SCM_FLTMAX
) && (fx
== x
);
159 #if (SIZEOF_SIZE_T < SCM_SIZEOF_BITS_T)
160 # define CHECK_BYTE_SIZE(s,k) SCM_ASSERT_RANGE (1, scm_bits2num (k), k <= (size_t)(~(size_t)0))
162 # define CHECK_BYTE_SIZE(s,k)
166 scm_make_uve (scm_bits_t k
, SCM prot
)
167 #define FUNC_NAME "scm_make_uve"
172 scm_ubits_t size_in_bytes
;
174 if (SCM_EQ_P (prot
, SCM_BOOL_T
))
179 SCM_ASSERT_RANGE (1, scm_bits2num (k
),
180 k
<= SCM_BITVECTOR_MAX_LENGTH
);
181 size_in_bytes
= sizeof (scm_bits_t
) * ((k
+ SCM_BITS_LENGTH
- 1) /
183 CHECK_BYTE_SIZE (size_in_bytes
, k
);
184 i
= (size_t) size_in_bytes
;
185 SCM_SET_BITVECTOR_BASE (v
, (char *) scm_must_malloc (i
, "vector"));
186 SCM_SET_BITVECTOR_LENGTH (v
, k
);
190 SCM_SET_BITVECTOR_BASE (v
, 0);
191 SCM_SET_BITVECTOR_LENGTH (v
, 0);
195 else if (SCM_CHARP (prot
) && (SCM_CHAR (prot
) == '\0'))
197 size_in_bytes
= sizeof (char) * k
;
198 type
= scm_tc7_byvect
;
200 else if (SCM_CHARP (prot
))
202 size_in_bytes
= sizeof (char) * k
;
203 CHECK_BYTE_SIZE (size_in_bytes
, k
);
204 i
= (size_t) size_in_bytes
;
205 return scm_allocate_string (i
);
207 else if (SCM_INUMP (prot
))
209 size_in_bytes
= sizeof (long) * k
;
210 if (SCM_INUM (prot
) > 0)
211 type
= scm_tc7_uvect
;
213 type
= scm_tc7_ivect
;
215 else if (SCM_SYMBOLP (prot
) && (1 == SCM_SYMBOL_LENGTH (prot
)))
219 s
= SCM_SYMBOL_CHARS (prot
)[0];
222 size_in_bytes
= sizeof (short) * k
;
223 type
= scm_tc7_svect
;
225 #ifdef HAVE_LONG_LONGS
228 size_in_bytes
= sizeof (long long) * k
;
229 type
= scm_tc7_llvect
;
234 return scm_c_make_vector (k
, SCM_UNDEFINED
);
238 else if (!SCM_INEXACTP (prot
))
239 /* Huge non-unif vectors are NOT supported. */
240 /* no special scm_vector */
241 return scm_c_make_vector (k
, SCM_UNDEFINED
);
242 else if (singp (prot
))
244 size_in_bytes
= sizeof (float) * k
;
245 type
= scm_tc7_fvect
;
247 else if (SCM_COMPLEXP (prot
))
249 size_in_bytes
= 2 * sizeof (double) * k
;
250 type
= scm_tc7_cvect
;
254 size_in_bytes
= sizeof (double) * k
;
255 type
= scm_tc7_dvect
;
258 CHECK_BYTE_SIZE (size_in_bytes
, k
);
259 i
= (size_t) size_in_bytes
;
261 SCM_ASSERT_RANGE (1, scm_bits2num (k
), k
<= SCM_UVECTOR_MAX_LENGTH
);
265 SCM_SET_UVECTOR_BASE (v
, (char *) scm_must_malloc (i
? i
: 1, "vector"));
266 SCM_SET_UVECTOR_LENGTH (v
, k
, type
);
273 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
275 "Return the number of elements in @var{uve}.")
276 #define FUNC_NAME s_scm_uniform_vector_length
278 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
282 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
285 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v
));
287 return SCM_MAKINUM (SCM_STRING_LENGTH (v
));
289 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v
));
297 #ifdef HAVE_LONG_LONGS
300 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v
));
305 SCM_DEFINE (scm_array_p
, "array?", 1, 1, 0,
307 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
308 "not. The @var{prototype} argument is used with uniform arrays\n"
309 "and is described elsewhere.")
310 #define FUNC_NAME s_scm_array_p
314 nprot
= SCM_UNBNDP (prot
);
319 while (SCM_TYP7 (v
) == scm_tc7_smob
)
330 return SCM_BOOL(nprot
);
335 switch (SCM_TYP7 (v
))
338 protp
= (SCM_EQ_P (prot
, SCM_BOOL_T
));
340 protp
= SCM_CHARP(prot
) && (SCM_CHAR (prot
) != '\0');
342 protp
= SCM_EQ_P (prot
, SCM_MAKE_CHAR ('\0'));
344 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)>0;
346 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)<=0;
349 protp
= SCM_SYMBOLP (prot
)
350 && (1 == SCM_SYMBOL_LENGTH (prot
))
351 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
352 #ifdef HAVE_LONG_LONGS
354 protp
= SCM_SYMBOLP (prot
)
355 && (1 == SCM_SYMBOL_LENGTH (prot
))
356 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
359 protp
= singp (prot
);
361 protp
= SCM_REALP(prot
);
363 protp
= SCM_COMPLEXP(prot
);
366 protp
= SCM_NULLP(prot
);
371 return SCM_BOOL(protp
);
377 SCM_DEFINE (scm_array_rank
, "array-rank", 1, 0, 0,
379 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
380 "not an array, @code{0} is returned.")
381 #define FUNC_NAME s_scm_array_rank
385 switch (SCM_TYP7 (ra
))
398 #ifdef HAVE_LONG_LONGS
402 return SCM_MAKINUM (1L);
405 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra
));
412 SCM_DEFINE (scm_array_dimensions
, "array-dimensions", 1, 0, 0,
414 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
415 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
417 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
419 #define FUNC_NAME s_scm_array_dimensions
426 switch (SCM_TYP7 (ra
))
441 #ifdef HAVE_LONG_LONGS
444 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
446 if (!SCM_ARRAYP (ra
))
448 k
= SCM_ARRAY_NDIM (ra
);
449 s
= SCM_ARRAY_DIMS (ra
);
451 res
= scm_cons (s
[k
].lbnd
452 ? scm_cons2 (SCM_MAKINUM (s
[k
].lbnd
),
453 SCM_MAKINUM (s
[k
].ubnd
),
455 : SCM_MAKINUM (1 + s
[k
].ubnd
),
463 SCM_DEFINE (scm_shared_array_root
, "shared-array-root", 1, 0, 0,
465 "Return the root vector of a shared array.")
466 #define FUNC_NAME s_scm_shared_array_root
468 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
469 return SCM_ARRAY_V (ra
);
474 SCM_DEFINE (scm_shared_array_offset
, "shared-array-offset", 1, 0, 0,
476 "Return the root vector index of the first element in the array.")
477 #define FUNC_NAME s_scm_shared_array_offset
479 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
480 return SCM_MAKINUM (SCM_ARRAY_BASE (ra
));
485 SCM_DEFINE (scm_shared_array_increments
, "shared-array-increments", 1, 0, 0,
487 "For each dimension, return the distance between elements in the root vector.")
488 #define FUNC_NAME s_scm_shared_array_increments
493 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
494 k
= SCM_ARRAY_NDIM (ra
);
495 s
= SCM_ARRAY_DIMS (ra
);
497 res
= scm_cons (SCM_MAKINUM (s
[k
].inc
), res
);
503 static char s_bad_ind
[] = "Bad scm_array index";
507 scm_aind (SCM ra
, SCM args
, const char *what
)
508 #define FUNC_NAME what
511 register scm_bits_t j
;
512 register scm_bits_t pos
= SCM_ARRAY_BASE (ra
);
513 register size_t k
= SCM_ARRAY_NDIM (ra
);
514 scm_array_dim_t
*s
= SCM_ARRAY_DIMS (ra
);
515 if (SCM_INUMP (args
))
518 scm_error_num_args_subr (what
);
519 return pos
+ (SCM_INUM (args
) - s
->lbnd
) * (s
->inc
);
521 while (k
&& !SCM_NULLP (args
))
523 ind
= SCM_CAR (args
);
524 args
= SCM_CDR (args
);
525 if (!SCM_INUMP (ind
))
526 scm_misc_error (what
, s_bad_ind
, SCM_EOL
);
528 if (j
< s
->lbnd
|| j
> s
->ubnd
)
529 scm_out_of_range (what
, ind
);
530 pos
+= (j
- s
->lbnd
) * (s
->inc
);
534 if (k
!= 0 || !SCM_NULLP (args
))
535 scm_error_num_args_subr (what
);
543 scm_make_ra (int ndim
)
548 SCM_NEWSMOB(ra
, ((scm_bits_t
) ndim
<< 17) + scm_tc16_array
,
549 scm_must_malloc ((sizeof (scm_array_t
) +
550 ndim
* sizeof (scm_array_dim_t
)),
552 SCM_ARRAY_V (ra
) = scm_nullvect
;
557 static char s_bad_spec
[] = "Bad scm_array dimension";
558 /* Increments will still need to be set. */
562 scm_shap2ra (SCM args
, const char *what
)
566 int ndim
= scm_ilength (args
);
568 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
570 ra
= scm_make_ra (ndim
);
571 SCM_ARRAY_BASE (ra
) = 0;
572 s
= SCM_ARRAY_DIMS (ra
);
573 for (; !SCM_NULLP (args
); s
++, args
= SCM_CDR (args
))
575 spec
= SCM_CAR (args
);
576 if (SCM_INUMP (spec
))
578 if (SCM_INUM (spec
) < 0)
579 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
581 s
->ubnd
= SCM_INUM (spec
) - 1;
586 if (!SCM_CONSP (spec
) || !SCM_INUMP (SCM_CAR (spec
)))
587 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
588 s
->lbnd
= SCM_INUM (SCM_CAR (spec
));
591 || !SCM_INUMP (SCM_CAR (sp
))
592 || !SCM_NULLP (SCM_CDR (sp
)))
593 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
594 s
->ubnd
= SCM_INUM (SCM_CAR (sp
));
601 SCM_DEFINE (scm_dimensions_to_uniform_array
, "dimensions->uniform-array", 2, 1, 0,
602 (SCM dims
, SCM prot
, SCM fill
),
603 "@deffnx primitive make-uniform-vector length prototype [fill]\n"
604 "Create and return a uniform array or vector of type\n"
605 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
606 "length @var{length}. If @var{fill} is supplied, it's used to\n"
607 "fill the array, otherwise @var{prototype} is used.")
608 #define FUNC_NAME s_scm_dimensions_to_uniform_array
615 if (SCM_INUMP (dims
))
617 SCM answer
= scm_make_uve (SCM_INUM (dims
), prot
);
618 if (!SCM_UNBNDP (fill
))
619 scm_array_fill_x (answer
, fill
);
620 else if (SCM_SYMBOLP (prot
))
621 scm_array_fill_x (answer
, SCM_MAKINUM (0));
623 scm_array_fill_x (answer
, prot
);
627 SCM_ASSERT (SCM_NULLP (dims
) || SCM_CONSP (dims
),
628 dims
, SCM_ARG1
, FUNC_NAME
);
629 ra
= scm_shap2ra (dims
, FUNC_NAME
);
630 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
631 s
= SCM_ARRAY_DIMS (ra
);
632 k
= SCM_ARRAY_NDIM (ra
);
637 SCM_ASSERT_RANGE (1, dims
, s
[k
].inc
>= 0);
638 SCM_ASSERT_RANGE (1, dims
, s
[k
].lbnd
<= s
[k
].ubnd
);
639 rlen
= (s
[k
].ubnd
- s
[k
].lbnd
+ 1) * s
[k
].inc
;
642 SCM_ARRAY_V (ra
) = scm_make_uve (rlen
, prot
);
644 if (!SCM_UNBNDP (fill
))
645 scm_array_fill_x (ra
, fill
);
646 else if (SCM_SYMBOLP (prot
))
647 scm_array_fill_x (ra
, SCM_MAKINUM (0));
649 scm_array_fill_x (ra
, prot
);
651 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
652 if (s
[0].ubnd
< s
[0].lbnd
|| (0 == s
[0].lbnd
&& 1 == s
[0].inc
))
653 return SCM_ARRAY_V (ra
);
660 scm_ra_set_contp (SCM ra
)
662 size_t k
= SCM_ARRAY_NDIM (ra
);
665 scm_bits_t inc
= SCM_ARRAY_DIMS (ra
)[k
- 1].inc
; /*??*/
668 if (inc
!= SCM_ARRAY_DIMS (ra
)[k
].inc
)
670 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra
);
673 inc
*= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
674 - SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
677 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
681 SCM_DEFINE (scm_make_shared_array
, "make-shared-array", 2, 0, 1,
682 (SCM oldra
, SCM mapfunc
, SCM dims
),
683 "@code{make-shared-array} can be used to create shared subarrays of other\n"
684 "arrays. The @var{mapper} is a function that translates coordinates in\n"
685 "the new array into coordinates in the old array. A @var{mapper} must be\n"
686 "linear, and its range must stay within the bounds of the old array, but\n"
687 "it can be otherwise arbitrary. A simple example:\n"
689 "(define fred (make-array #f 8 8))\n"
690 "(define freds-diagonal\n"
691 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
692 "(array-set! freds-diagonal 'foo 3)\n"
693 "(array-ref fred 3 3) @result{} foo\n"
694 "(define freds-center\n"
695 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
696 "(array-ref freds-center 0 0) @result{} foo\n"
698 #define FUNC_NAME s_scm_make_shared_array
705 scm_bits_t old_min
, new_min
, old_max
, new_max
;
708 SCM_VALIDATE_REST_ARGUMENT (dims
);
709 SCM_VALIDATE_ARRAY (1,oldra
);
710 SCM_VALIDATE_PROC (2,mapfunc
);
711 ra
= scm_shap2ra (dims
, FUNC_NAME
);
712 if (SCM_ARRAYP (oldra
))
714 SCM_ARRAY_V (ra
) = SCM_ARRAY_V (oldra
);
715 old_min
= old_max
= SCM_ARRAY_BASE (oldra
);
716 s
= SCM_ARRAY_DIMS (oldra
);
717 k
= SCM_ARRAY_NDIM (oldra
);
721 old_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
723 old_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
728 SCM_ARRAY_V (ra
) = oldra
;
730 old_max
= SCM_INUM (scm_uniform_vector_length (oldra
)) - 1;
733 s
= SCM_ARRAY_DIMS (ra
);
734 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
736 inds
= scm_cons (SCM_MAKINUM (s
[k
].lbnd
), inds
);
737 if (s
[k
].ubnd
< s
[k
].lbnd
)
739 if (1 == SCM_ARRAY_NDIM (ra
))
740 ra
= scm_make_uve (0L, scm_array_prototype (ra
));
742 SCM_ARRAY_V (ra
) = scm_make_uve (0L, scm_array_prototype (ra
));
746 imap
= scm_apply (mapfunc
, scm_reverse (inds
), SCM_EOL
);
747 if (SCM_ARRAYP (oldra
))
748 i
= scm_aind (oldra
, imap
, FUNC_NAME
);
751 if (SCM_NINUMP (imap
))
754 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
755 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
756 imap
= SCM_CAR (imap
);
760 SCM_ARRAY_BASE (ra
) = new_min
= new_max
= i
;
762 k
= SCM_ARRAY_NDIM (ra
);
765 if (s
[k
].ubnd
> s
[k
].lbnd
)
767 SCM_SETCAR (indptr
, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr
)) + 1));
768 imap
= scm_apply (mapfunc
, scm_reverse (inds
), SCM_EOL
);
769 if (SCM_ARRAYP (oldra
))
771 s
[k
].inc
= scm_aind (oldra
, imap
, FUNC_NAME
) - i
;
774 if (SCM_NINUMP (imap
))
776 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
777 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
778 imap
= SCM_CAR (imap
);
780 s
[k
].inc
= (long) SCM_INUM (imap
) - i
;
784 new_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
786 new_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
789 s
[k
].inc
= new_max
- new_min
+ 1; /* contiguous by default */
790 indptr
= SCM_CDR (indptr
);
792 if (old_min
> new_min
|| old_max
< new_max
)
793 SCM_MISC_ERROR ("mapping out of range", SCM_EOL
);
794 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
796 SCM v
= SCM_ARRAY_V (ra
);
797 scm_bits_t length
= SCM_INUM (scm_uniform_vector_length (v
));
798 if (1 == s
->inc
&& 0 == s
->lbnd
&& length
== 1 + s
->ubnd
)
800 if (s
->ubnd
< s
->lbnd
)
801 return scm_make_uve (0L, scm_array_prototype (ra
));
803 scm_ra_set_contp (ra
);
809 /* args are RA . DIMS */
810 SCM_DEFINE (scm_transpose_array
, "transpose-array", 1, 0, 1,
812 "Return an array sharing contents with @var{array}, but with\n"
813 "dimensions arranged in a different order. There must be one\n"
814 "@var{dim} argument for each dimension of @var{array}.\n"
815 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
816 "and the rank of the array to be returned. Each integer in that\n"
817 "range must appear at least once in the argument list.\n"
819 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
820 "dimensions in the array to be returned, their positions in the\n"
821 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
822 "may have the same value, in which case the returned array will\n"
823 "have smaller rank than @var{array}.\n"
826 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
827 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
828 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
829 " #2((a 4) (b 5) (c 6))\n"
831 #define FUNC_NAME s_scm_transpose_array
833 SCM res
, vargs
, *ve
= &vargs
;
834 scm_array_dim_t
*s
, *r
;
837 SCM_VALIDATE_REST_ARGUMENT (args
);
838 SCM_ASSERT (SCM_NIMP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
839 switch (SCM_TYP7 (ra
))
842 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
852 #ifdef HAVE_LONG_LONGS
855 if (SCM_NULLP (args
) || !SCM_NULLP (SCM_CDR (args
)))
856 SCM_WRONG_NUM_ARGS ();
857 SCM_VALIDATE_INUM (SCM_ARG2
, SCM_CAR (args
));
858 SCM_ASSERT_RANGE (SCM_ARG2
, SCM_CAR (args
),
859 SCM_EQ_P (SCM_INUM0
, SCM_CAR (args
)));
862 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
863 vargs
= scm_vector (args
);
864 if (SCM_VECTOR_LENGTH (vargs
) != SCM_ARRAY_NDIM (ra
))
865 SCM_WRONG_NUM_ARGS ();
866 ve
= SCM_VELTS (vargs
);
868 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
870 SCM_ASSERT (SCM_INUMP (ve
[k
]), ve
[k
], (SCM_ARG2
+ k
),
872 i
= SCM_INUM (ve
[k
]);
873 if (i
< 0 || i
>= SCM_ARRAY_NDIM (ra
))
874 scm_out_of_range (FUNC_NAME
, ve
[k
]);
879 res
= scm_make_ra (ndim
);
880 SCM_ARRAY_V (res
) = SCM_ARRAY_V (ra
);
881 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra
);
884 SCM_ARRAY_DIMS (res
)[k
].lbnd
= 0;
885 SCM_ARRAY_DIMS (res
)[k
].ubnd
= -1;
887 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
889 i
= SCM_INUM (ve
[k
]);
890 s
= &(SCM_ARRAY_DIMS (ra
)[k
]);
891 r
= &(SCM_ARRAY_DIMS (res
)[i
]);
892 if (r
->ubnd
< r
->lbnd
)
901 if (r
->ubnd
> s
->ubnd
)
903 if (r
->lbnd
< s
->lbnd
)
905 SCM_ARRAY_BASE (res
) += (s
->lbnd
- r
->lbnd
) * r
->inc
;
912 SCM_MISC_ERROR ("bad argument list", SCM_EOL
);
913 scm_ra_set_contp (res
);
919 /* args are RA . AXES */
920 SCM_DEFINE (scm_enclose_array
, "enclose-array", 1, 0, 1,
922 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
923 "the rank of @var{array}. @var{enclose-array} returns an array\n"
924 "resembling an array of shared arrays. The dimensions of each shared\n"
925 "array are the same as the @var{dim}th dimensions of the original array,\n"
926 "the dimensions of the outer array are the same as those of the original\n"
927 "array that did not match a @var{dim}.\n\n"
928 "An enclosed array is not a general Scheme array. Its elements may not\n"
929 "be set using @code{array-set!}. Two references to the same element of\n"
930 "an enclosed array will be @code{equal?} but will not in general be\n"
931 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
932 "enclosed array is unspecified.\n\n"
935 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
936 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
937 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
938 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
940 #define FUNC_NAME s_scm_enclose_array
942 SCM axv
, res
, ra_inr
;
943 scm_array_dim_t vdim
, *s
= &vdim
;
944 int ndim
, j
, k
, ninr
, noutr
;
946 SCM_VALIDATE_REST_ARGUMENT (axes
);
947 if (SCM_NULLP (axes
))
948 axes
= scm_cons ((SCM_ARRAYP (ra
) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra
) - 1) : SCM_INUM0
), SCM_EOL
);
949 ninr
= scm_ilength (axes
);
951 SCM_WRONG_NUM_ARGS ();
952 ra_inr
= scm_make_ra (ninr
);
953 SCM_ASRTGO (SCM_NIMP (ra
), badarg1
);
957 badarg1
:SCM_WRONG_TYPE_ARG (1, ra
);
969 #ifdef HAVE_LONG_LONGS
973 s
->ubnd
= SCM_INUM (scm_uniform_vector_length (ra
)) - 1;
975 SCM_ARRAY_V (ra_inr
) = ra
;
976 SCM_ARRAY_BASE (ra_inr
) = 0;
980 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg1
);
981 s
= SCM_ARRAY_DIMS (ra
);
982 SCM_ARRAY_V (ra_inr
) = SCM_ARRAY_V (ra
);
983 SCM_ARRAY_BASE (ra_inr
) = SCM_ARRAY_BASE (ra
);
984 ndim
= SCM_ARRAY_NDIM (ra
);
989 SCM_WRONG_NUM_ARGS ();
990 axv
= scm_make_string (SCM_MAKINUM (ndim
), SCM_MAKE_CHAR (0));
991 res
= scm_make_ra (noutr
);
992 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra_inr
);
993 SCM_ARRAY_V (res
) = ra_inr
;
994 for (k
= 0; k
< ninr
; k
++, axes
= SCM_CDR (axes
))
996 if (!SCM_INUMP (SCM_CAR (axes
)))
997 SCM_MISC_ERROR ("bad axis", SCM_EOL
);
998 j
= SCM_INUM (SCM_CAR (axes
));
999 SCM_ARRAY_DIMS (ra_inr
)[k
].lbnd
= s
[j
].lbnd
;
1000 SCM_ARRAY_DIMS (ra_inr
)[k
].ubnd
= s
[j
].ubnd
;
1001 SCM_ARRAY_DIMS (ra_inr
)[k
].inc
= s
[j
].inc
;
1002 SCM_STRING_CHARS (axv
)[j
] = 1;
1004 for (j
= 0, k
= 0; k
< noutr
; k
++, j
++)
1006 while (SCM_STRING_CHARS (axv
)[j
])
1008 SCM_ARRAY_DIMS (res
)[k
].lbnd
= s
[j
].lbnd
;
1009 SCM_ARRAY_DIMS (res
)[k
].ubnd
= s
[j
].ubnd
;
1010 SCM_ARRAY_DIMS (res
)[k
].inc
= s
[j
].inc
;
1012 scm_ra_set_contp (ra_inr
);
1013 scm_ra_set_contp (res
);
1020 SCM_DEFINE (scm_array_in_bounds_p
, "array-in-bounds?", 1, 0, 1,
1022 "Return @code{#t} if its arguments would be acceptable to\n"
1023 "@code{array-ref}.")
1024 #define FUNC_NAME s_scm_array_in_bounds_p
1029 register scm_bits_t j
;
1032 SCM_VALIDATE_REST_ARGUMENT (args
);
1033 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1034 if (SCM_NIMP (args
))
1037 ind
= SCM_CAR (args
);
1038 args
= SCM_CDR (args
);
1039 SCM_ASSERT (SCM_INUMP (ind
), ind
, SCM_ARG2
, FUNC_NAME
);
1040 pos
= SCM_INUM (ind
);
1046 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1047 wna
: SCM_WRONG_NUM_ARGS ();
1049 k
= SCM_ARRAY_NDIM (v
);
1050 s
= SCM_ARRAY_DIMS (v
);
1051 pos
= SCM_ARRAY_BASE (v
);
1054 SCM_ASRTGO (SCM_NULLP (ind
), wna
);
1061 if (!(j
>= (s
->lbnd
) && j
<= (s
->ubnd
)))
1063 SCM_ASRTGO (--k
== scm_ilength (args
), wna
);
1066 pos
+= (j
- s
->lbnd
) * (s
->inc
);
1067 if (!(--k
&& SCM_NIMP (args
)))
1069 ind
= SCM_CAR (args
);
1070 args
= SCM_CDR (args
);
1072 if (!SCM_INUMP (ind
))
1073 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
1075 SCM_ASRTGO (0 == k
, wna
);
1076 v
= SCM_ARRAY_V (v
);
1079 case scm_tc7_string
:
1080 case scm_tc7_byvect
:
1087 #ifdef HAVE_LONG_LONGS
1088 case scm_tc7_llvect
:
1090 case scm_tc7_vector
:
1093 scm_bits_t length
= SCM_INUM (scm_uniform_vector_length (v
));
1094 SCM_ASRTGO (SCM_NULLP (args
) && SCM_INUMP (ind
), wna
);
1095 return SCM_BOOL(pos
>= 0 && pos
< length
);
1102 SCM_REGISTER_PROC(s_array_ref
, "array-ref", 1, 0, 1, scm_uniform_vector_ref
);
1105 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
1107 "@deffnx primitive array-ref v . args\n"
1108 "Return the element at the @code{(index1, index2)} element in\n"
1110 #define FUNC_NAME s_scm_uniform_vector_ref
1116 SCM_ASRTGO (SCM_NULLP (args
), badarg
);
1119 else if (SCM_ARRAYP (v
))
1121 pos
= scm_aind (v
, args
, FUNC_NAME
);
1122 v
= SCM_ARRAY_V (v
);
1127 if (SCM_NIMP (args
))
1129 SCM_ASSERT (SCM_CONSP (args
) && SCM_INUMP (SCM_CAR (args
)), args
, SCM_ARG2
, FUNC_NAME
);
1130 pos
= SCM_INUM (SCM_CAR (args
));
1131 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args
)), wna
);
1135 SCM_VALIDATE_INUM (2,args
);
1136 pos
= SCM_INUM (args
);
1138 length
= SCM_INUM (scm_uniform_vector_length (v
));
1139 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1144 if (SCM_NULLP (args
))
1147 SCM_WRONG_TYPE_ARG (1, v
);
1151 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1153 SCM_WRONG_NUM_ARGS ();
1156 int k
= SCM_ARRAY_NDIM (v
);
1157 SCM res
= scm_make_ra (k
);
1158 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1159 SCM_ARRAY_BASE (res
) = pos
;
1162 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1163 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1164 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1169 if (SCM_BITVEC_REF (v
, pos
))
1173 case scm_tc7_string
:
1174 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1175 case scm_tc7_byvect
:
1176 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1178 return scm_ulong2num (((unsigned long *) SCM_VELTS (v
))[pos
]);
1180 return scm_long2num (((signed long *) SCM_VELTS (v
))[pos
]);
1183 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1184 #ifdef HAVE_LONG_LONGS
1185 case scm_tc7_llvect
:
1186 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1190 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1192 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1194 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1195 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1196 case scm_tc7_vector
:
1198 return SCM_VELTS (v
)[pos
];
1203 /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1204 tries to recycle conses. (Make *sure* you want them recycled.) */
1207 scm_cvref (SCM v
, scm_bits_t pos
, SCM last
)
1208 #define FUNC_NAME "scm_cvref"
1213 SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1215 if (SCM_BITVEC_REF(v
,pos
))
1219 case scm_tc7_string
:
1220 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1221 case scm_tc7_byvect
:
1222 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1224 return scm_ulong2num(((unsigned long *) SCM_VELTS (v
))[pos
]);
1226 return scm_long2num(((signed long *) SCM_VELTS (v
))[pos
]);
1228 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1229 #ifdef HAVE_LONG_LONGS
1230 case scm_tc7_llvect
:
1231 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1234 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1236 SCM_REAL_VALUE (last
) = ((float *) SCM_CELL_WORD_1 (v
))[pos
];
1239 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1241 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1243 SCM_REAL_VALUE (last
) = ((double *) SCM_CELL_WORD_1 (v
))[pos
];
1246 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1248 if (SCM_NIMP (last
) && SCM_SLOPPY_COMPLEXP (last
))
1250 SCM_COMPLEX_REAL (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
];
1251 SCM_COMPLEX_IMAG (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1];
1254 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1255 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1256 case scm_tc7_vector
:
1258 return SCM_VELTS (v
)[pos
];
1260 { /* enclosed scm_array */
1261 int k
= SCM_ARRAY_NDIM (v
);
1262 SCM res
= scm_make_ra (k
);
1263 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1264 SCM_ARRAY_BASE (res
) = pos
;
1267 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1268 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1269 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1278 SCM_REGISTER_PROC(s_uniform_array_set1_x
, "uniform-array-set1!", 3, 0, 0, scm_array_set_x
);
1281 /* Note that args may be a list or an immediate object, depending which
1282 PROC is used (and it's called from C too). */
1283 SCM_DEFINE (scm_array_set_x
, "array-set!", 2, 0, 1,
1284 (SCM v
, SCM obj
, SCM args
),
1285 "@deffnx primitive uniform-array-set1! v obj args\n"
1286 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1287 "@var{new-value}. The value returned by array-set! is unspecified.")
1288 #define FUNC_NAME s_scm_array_set_x
1292 SCM_VALIDATE_REST_ARGUMENT (args
);
1293 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1296 pos
= scm_aind (v
, args
, FUNC_NAME
);
1297 v
= SCM_ARRAY_V (v
);
1302 if (SCM_NIMP (args
))
1304 SCM_ASSERT (SCM_CONSP(args
) && SCM_INUMP (SCM_CAR (args
)), args
,
1305 SCM_ARG3
, FUNC_NAME
);
1306 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args
)), wna
);
1307 pos
= SCM_INUM (SCM_CAR (args
));
1311 SCM_VALIDATE_INUM_COPY (3,args
,pos
);
1313 length
= SCM_INUM (scm_uniform_vector_length (v
));
1314 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1316 switch (SCM_TYP7 (v
))
1319 SCM_WRONG_TYPE_ARG (1, v
);
1322 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1324 SCM_WRONG_NUM_ARGS ();
1325 case scm_tc7_smob
: /* enclosed */
1328 if (SCM_FALSEP (obj
))
1329 SCM_BITVEC_CLR(v
,pos
);
1330 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1331 SCM_BITVEC_SET(v
,pos
);
1333 badobj
:SCM_WRONG_TYPE_ARG (2, obj
);
1335 case scm_tc7_string
:
1336 SCM_ASRTGO (SCM_CHARP (obj
), badobj
);
1337 SCM_STRING_UCHARS (v
)[pos
] = SCM_CHAR (obj
);
1339 case scm_tc7_byvect
:
1340 if (SCM_CHARP (obj
))
1341 obj
= SCM_MAKINUM ((char) SCM_CHAR (obj
));
1342 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1343 ((char *) SCM_UVECTOR_BASE (v
))[pos
] = SCM_INUM (obj
);
1346 ((unsigned long *) SCM_VELTS(v
))[pos
] = SCM_PACK (scm_num2ulong(obj
, SCM_ARG2
, FUNC_NAME
));
1349 ((long *) SCM_VELTS(v
))[pos
] = SCM_PACK (scm_num2long (obj
, SCM_ARG2
, FUNC_NAME
));
1352 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1353 ((short *) SCM_CELL_WORD_1 (v
))[pos
] = SCM_INUM (obj
);
1355 #ifdef HAVE_LONG_LONGS
1356 case scm_tc7_llvect
:
1357 ((long long *) SCM_CELL_WORD_1 (v
))[pos
] = scm_num2long_long (obj
, SCM_ARG2
, FUNC_NAME
);
1363 ((float *) SCM_CELL_WORD_1 (v
))[pos
] = (float) scm_num2dbl (obj
, FUNC_NAME
);
1366 ((double *) SCM_CELL_WORD_1 (v
))[pos
] = scm_num2dbl (obj
, FUNC_NAME
);
1369 SCM_ASRTGO (SCM_INEXACTP (obj
), badobj
);
1370 if (SCM_REALP (obj
)) {
1371 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
] = SCM_REAL_VALUE (obj
);
1372 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1] = 0.0;
1374 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
] = SCM_COMPLEX_REAL (obj
);
1375 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1] = SCM_COMPLEX_IMAG (obj
);
1378 case scm_tc7_vector
:
1380 SCM_VELTS (v
)[pos
] = obj
;
1383 return SCM_UNSPECIFIED
;
1387 /* attempts to unroll an array into a one-dimensional array.
1388 returns the unrolled array or #f if it can't be done. */
1389 /* if strict is not SCM_UNDEFINED, return #f if returned array
1390 wouldn't have contiguous elements. */
1391 SCM_DEFINE (scm_array_contents
, "array-contents", 1, 1, 0,
1392 (SCM ra
, SCM strict
),
1393 "@deffnx primitive array-contents array strict\n"
1394 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1395 "without changing their order (last subscript changing fastest), then\n"
1396 "@code{array-contents} returns that shared array, otherwise it returns\n"
1397 "@code{#f}. All arrays made by @var{make-array} and\n"
1398 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1399 "@var{make-shared-array} may not be.\n\n"
1400 "If the optional argument @var{strict} is provided, a shared array will\n"
1401 "be returned only if its elements are stored internally contiguous in\n"
1403 #define FUNC_NAME s_scm_array_contents
1408 switch SCM_TYP7 (ra
)
1412 case scm_tc7_vector
:
1414 case scm_tc7_string
:
1416 case scm_tc7_byvect
:
1423 #ifdef HAVE_LONG_LONGS
1424 case scm_tc7_llvect
:
1429 size_t k
, ndim
= SCM_ARRAY_NDIM (ra
);
1431 if (!SCM_ARRAYP (ra
) || !SCM_ARRAY_CONTP (ra
))
1433 for (k
= 0; k
< ndim
; k
++)
1434 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1435 if (!SCM_UNBNDP (strict
))
1437 if (ndim
&& (1 != SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
))
1439 if (scm_tc7_bvect
== SCM_TYP7 (SCM_ARRAY_V (ra
)))
1441 if (len
!= SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) ||
1442 SCM_ARRAY_BASE (ra
) % SCM_BITS_LENGTH
||
1443 len
% SCM_BITS_LENGTH
)
1449 SCM v
= SCM_ARRAY_V (ra
);
1450 scm_bits_t length
= SCM_INUM (scm_uniform_vector_length (v
));
1451 if ((len
== length
) && 0 == SCM_ARRAY_BASE (ra
) && SCM_ARRAY_DIMS (ra
)->inc
)
1455 sra
= scm_make_ra (1);
1456 SCM_ARRAY_DIMS (sra
)->lbnd
= 0;
1457 SCM_ARRAY_DIMS (sra
)->ubnd
= len
- 1;
1458 SCM_ARRAY_V (sra
) = SCM_ARRAY_V (ra
);
1459 SCM_ARRAY_BASE (sra
) = SCM_ARRAY_BASE (ra
);
1460 SCM_ARRAY_DIMS (sra
)->inc
= (ndim
? SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
: 1);
1469 scm_ra2contig (SCM ra
, int copy
)
1475 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
1476 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1477 k
= SCM_ARRAY_NDIM (ra
);
1478 if (SCM_ARRAY_CONTP (ra
) && ((0 == k
) || (1 == SCM_ARRAY_DIMS (ra
)[k
- 1].inc
)))
1480 if (scm_tc7_bvect
!= SCM_TYP7 (SCM_ARRAY_V (ra
)))
1482 if ((len
== SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) &&
1483 0 == SCM_ARRAY_BASE (ra
) % SCM_BITS_LENGTH
&&
1484 0 == len
% SCM_BITS_LENGTH
))
1487 ret
= scm_make_ra (k
);
1488 SCM_ARRAY_BASE (ret
) = 0;
1491 SCM_ARRAY_DIMS (ret
)[k
].lbnd
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
;
1492 SCM_ARRAY_DIMS (ret
)[k
].ubnd
= SCM_ARRAY_DIMS (ra
)[k
].ubnd
;
1493 SCM_ARRAY_DIMS (ret
)[k
].inc
= inc
;
1494 inc
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1496 SCM_ARRAY_V (ret
) = scm_make_uve ((inc
- 1), scm_array_prototype (ra
));
1498 scm_array_copy_x (ra
, ret
);
1504 SCM_DEFINE (scm_uniform_array_read_x
, "uniform-array-read!", 1, 3, 0,
1505 (SCM ra
, SCM port_or_fd
, SCM start
, SCM end
),
1506 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1507 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1508 "binary objects from @var{port-or-fdes}.\n"
1509 "If an end of file is encountered during\n"
1510 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1511 "(starting at the beginning) and the remainder of the array is\n"
1513 "The optional arguments @var{start} and @var{end} allow\n"
1514 "a specified region of a vector (or linearized array) to be read,\n"
1515 "leaving the remainder of the vector unchanged.\n\n"
1516 "@code{uniform-array-read!} returns the number of objects read.\n"
1517 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1518 "returned by @code{(current-input-port)}.")
1519 #define FUNC_NAME s_scm_uniform_array_read_x
1521 SCM cra
= SCM_UNDEFINED
, v
= ra
;
1523 scm_bits_t vlen
, ans
;
1524 scm_bits_t cstart
= 0, cend
= 0;
1525 scm_bits_t offset
= 0;
1528 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1529 if (SCM_UNBNDP (port_or_fd
))
1530 port_or_fd
= scm_cur_inp
;
1532 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1533 || (SCM_OPINPORTP (port_or_fd
)),
1534 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1535 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1541 badarg1
:SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1543 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1544 cra
= scm_ra2contig (ra
, 0);
1545 cstart
+= SCM_ARRAY_BASE (cra
);
1546 vlen
= SCM_ARRAY_DIMS (cra
)->inc
*
1547 (SCM_ARRAY_DIMS (cra
)->ubnd
- SCM_ARRAY_DIMS (cra
)->lbnd
+ 1);
1548 v
= SCM_ARRAY_V (cra
);
1550 case scm_tc7_string
:
1551 base
= SCM_STRING_CHARS (v
);
1555 base
= (char *) SCM_BITVECTOR_BASE (v
);
1556 vlen
= (vlen
+ SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
;
1557 cstart
/= SCM_BITS_LENGTH
;
1558 sz
= sizeof (scm_bits_t
);
1560 case scm_tc7_byvect
:
1561 base
= (char *) SCM_UVECTOR_BASE (v
);
1566 base
= (char *) SCM_UVECTOR_BASE (v
);
1570 base
= (char *) SCM_UVECTOR_BASE (v
);
1571 sz
= sizeof (short);
1573 #ifdef HAVE_LONG_LONGS
1574 case scm_tc7_llvect
:
1575 base
= (char *) SCM_UVECTOR_BASE (v
);
1576 sz
= sizeof (long long);
1580 base
= (char *) SCM_UVECTOR_BASE (v
);
1581 sz
= sizeof (float);
1584 base
= (char *) SCM_UVECTOR_BASE (v
);
1585 sz
= sizeof (double);
1588 base
= (char *) SCM_UVECTOR_BASE (v
);
1589 sz
= 2 * sizeof (double);
1594 if (!SCM_UNBNDP (start
))
1597 SCM_NUM2BITS (3, start
);
1599 if (offset
< 0 || offset
>= cend
)
1600 scm_out_of_range (FUNC_NAME
, start
);
1602 if (!SCM_UNBNDP (end
))
1605 SCM_NUM2BITS (4, end
);
1607 if (tend
<= offset
|| tend
> cend
)
1608 scm_out_of_range (FUNC_NAME
, end
);
1613 if (SCM_NIMP (port_or_fd
))
1615 scm_port_t
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
1616 int remaining
= (cend
- offset
) * sz
;
1617 char *dest
= base
+ (cstart
+ offset
) * sz
;
1619 if (pt
->rw_active
== SCM_PORT_WRITE
)
1620 scm_flush (port_or_fd
);
1622 ans
= cend
- offset
;
1623 while (remaining
> 0)
1625 if (pt
->read_pos
< pt
->read_end
)
1627 int to_copy
= min (pt
->read_end
- pt
->read_pos
,
1630 memcpy (dest
, pt
->read_pos
, to_copy
);
1631 pt
->read_pos
+= to_copy
;
1632 remaining
-= to_copy
;
1637 if (scm_fill_input (port_or_fd
) == EOF
)
1639 if (remaining
% sz
!= 0)
1641 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
1643 ans
-= remaining
/ sz
;
1650 pt
->rw_active
= SCM_PORT_READ
;
1652 else /* file descriptor. */
1654 SCM_SYSCALL (ans
= read (SCM_INUM (port_or_fd
),
1655 base
+ (cstart
+ offset
) * sz
,
1656 (sz
* (cend
- offset
))));
1660 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1661 ans
*= SCM_BITS_LENGTH
;
1663 if (!SCM_EQ_P (v
, ra
) && !SCM_EQ_P (cra
, ra
))
1664 scm_array_copy_x (cra
, ra
);
1666 return SCM_MAKINUM (ans
);
1670 SCM_DEFINE (scm_uniform_array_write
, "uniform-array-write", 1, 3, 0,
1671 (SCM v
, SCM port_or_fd
, SCM start
, SCM end
),
1672 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1673 "Writes all elements of @var{ura} as binary objects to\n"
1674 "@var{port-or-fdes}.\n\n"
1675 "The optional arguments @var{start}\n"
1676 "and @var{end} allow\n"
1677 "a specified region of a vector (or linearized array) to be written.\n\n"
1678 "The number of objects actually written is returned. \n"
1679 "@var{port-or-fdes} may be\n"
1680 "omitted, in which case it defaults to the value returned by\n"
1681 "@code{(current-output-port)}.")
1682 #define FUNC_NAME s_scm_uniform_array_write
1685 scm_bits_t vlen
, ans
;
1686 scm_bits_t offset
= 0, cstart
= 0, cend
;
1689 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
1691 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1692 if (SCM_UNBNDP (port_or_fd
))
1693 port_or_fd
= scm_cur_outp
;
1695 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1696 || (SCM_OPOUTPORTP (port_or_fd
)),
1697 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1698 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1704 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1706 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1707 v
= scm_ra2contig (v
, 1);
1708 cstart
= SCM_ARRAY_BASE (v
);
1709 vlen
= SCM_ARRAY_DIMS (v
)->inc
1710 * (SCM_ARRAY_DIMS (v
)->ubnd
- SCM_ARRAY_DIMS (v
)->lbnd
+ 1);
1711 v
= SCM_ARRAY_V (v
);
1713 case scm_tc7_string
:
1714 base
= SCM_STRING_CHARS (v
);
1718 base
= (char *) SCM_BITVECTOR_BASE (v
);
1719 vlen
= (vlen
+ SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
;
1720 cstart
/= SCM_BITS_LENGTH
;
1721 sz
= sizeof (scm_bits_t
);
1723 case scm_tc7_byvect
:
1724 base
= (char *) SCM_UVECTOR_BASE (v
);
1729 base
= (char *) SCM_UVECTOR_BASE (v
);
1733 base
= (char *) SCM_UVECTOR_BASE (v
);
1734 sz
= sizeof (short);
1736 #ifdef HAVE_LONG_LONGS
1737 case scm_tc7_llvect
:
1738 base
= (char *) SCM_UVECTOR_BASE (v
);
1739 sz
= sizeof (long long);
1743 base
= (char *) SCM_UVECTOR_BASE (v
);
1744 sz
= sizeof (float);
1747 base
= (char *) SCM_UVECTOR_BASE (v
);
1748 sz
= sizeof (double);
1751 base
= (char *) SCM_UVECTOR_BASE (v
);
1752 sz
= 2 * sizeof (double);
1757 if (!SCM_UNBNDP (start
))
1760 SCM_NUM2BITS (3, start
);
1762 if (offset
< 0 || offset
>= cend
)
1763 scm_out_of_range (FUNC_NAME
, start
);
1765 if (!SCM_UNBNDP (end
))
1768 SCM_NUM2BITS (4, end
);
1770 if (tend
<= offset
|| tend
> cend
)
1771 scm_out_of_range (FUNC_NAME
, end
);
1776 if (SCM_NIMP (port_or_fd
))
1778 char *source
= base
+ (cstart
+ offset
) * sz
;
1780 ans
= cend
- offset
;
1781 scm_lfwrite (source
, ans
* sz
, port_or_fd
);
1783 else /* file descriptor. */
1785 SCM_SYSCALL (ans
= write (SCM_INUM (port_or_fd
),
1786 base
+ (cstart
+ offset
) * sz
,
1787 (sz
* (cend
- offset
))));
1791 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1792 ans
*= SCM_BITS_LENGTH
;
1794 return SCM_MAKINUM (ans
);
1799 static char cnt_tab
[16] =
1800 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1802 SCM_DEFINE (scm_bit_count
, "bit-count", 2, 0, 0,
1803 (SCM b
, SCM bitvector
),
1804 "Return the number of occurrences of the boolean @var{b} in\n"
1806 #define FUNC_NAME s_scm_bit_count
1808 SCM_VALIDATE_BOOL (1, b
);
1809 SCM_ASSERT (SCM_BITVECTOR_P (bitvector
), bitvector
, 2, FUNC_NAME
);
1810 if (SCM_BITVECTOR_LENGTH (bitvector
) == 0) {
1813 scm_bits_t count
= 0;
1814 size_t i
= (SCM_BITVECTOR_LENGTH (bitvector
) - 1) / SCM_BITS_LENGTH
;
1815 scm_ubits_t w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1816 if (SCM_FALSEP (b
)) {
1819 w
<<= SCM_BITS_LENGTH
- 1 - ((SCM_BITVECTOR_LENGTH (bitvector
) - 1) % SCM_BITS_LENGTH
);
1822 count
+= cnt_tab
[w
& 0x0f];
1826 return SCM_MAKINUM (count
);
1829 w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1830 if (SCM_FALSEP (b
)) {
1840 SCM_DEFINE (scm_bit_position
, "bit-position", 3, 0, 0,
1841 (SCM item
, SCM v
, SCM k
),
1842 "Return the minimum index of an occurrence of @var{bool} in\n"
1843 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1844 "within the specified range @code{#f} is returned.")
1845 #define FUNC_NAME s_scm_bit_position
1851 register scm_ubits_t w
;
1853 SCM_VALIDATE_BOOL (1, item
);
1854 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG2
, FUNC_NAME
);
1855 SCM_VALIDATE_INUM_COPY (3,k
,pos
);
1856 SCM_ASSERT_RANGE (3, k
, (pos
<= SCM_BITVECTOR_LENGTH (v
)) && (pos
>= 0));
1858 if (pos
== SCM_BITVECTOR_LENGTH (v
))
1861 lenw
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_BITS_LENGTH
; /* watch for part words */
1862 i
= pos
/ SCM_BITS_LENGTH
;
1863 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1864 if (SCM_FALSEP (item
))
1866 xbits
= (pos
% SCM_BITS_LENGTH
);
1868 w
= ((w
>> xbits
) << xbits
);
1869 xbits
= SCM_BITS_LENGTH
- 1 - (SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_BITS_LENGTH
;
1872 if (w
&& (i
== lenw
))
1873 w
= ((w
<< xbits
) >> xbits
);
1879 return SCM_MAKINUM (pos
);
1884 return SCM_MAKINUM (pos
+ 1);
1887 return SCM_MAKINUM (pos
+ 2);
1889 return SCM_MAKINUM (pos
+ 3);
1896 pos
+= SCM_BITS_LENGTH
;
1897 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1898 if (SCM_FALSEP (item
))
1906 SCM_DEFINE (scm_bit_set_star_x
, "bit-set*!", 3, 0, 0,
1907 (SCM v
, SCM kv
, SCM obj
),
1908 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1909 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1910 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1911 "AND'ed into @var{bv}.\n\n"
1912 "If uve is a unsigned integer vector all the elements of uve\n"
1913 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1914 "of @var{bv} corresponding to the indexes in uve are set to\n"
1915 "@var{bool}. The return value is unspecified.")
1916 #define FUNC_NAME s_scm_bit_set_star_x
1920 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1921 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1922 switch SCM_TYP7 (kv
)
1925 badarg2
:SCM_WRONG_TYPE_ARG (2, kv
);
1929 vlen
= SCM_BITVECTOR_LENGTH (v
);
1930 if (SCM_FALSEP (obj
))
1931 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1933 k
= ((unsigned long *) SCM_VELTS (kv
))[--i
];
1935 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1936 SCM_BITVEC_CLR(v
,k
);
1938 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1939 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1941 k
= ((unsigned long *) SCM_VELTS (kv
))[--i
];
1943 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1944 SCM_BITVEC_SET(v
,k
);
1947 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1953 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1954 if (SCM_FALSEP (obj
))
1955 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
; k
--;)
1956 ((scm_ubits_t
*) SCM_VELTS (v
))[k
] &= ~ ((scm_ubits_t
*) SCM_VELTS (kv
))[k
];
1957 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1958 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
; k
--;)
1959 ((scm_ubits_t
*) SCM_VELTS (v
))[k
] |= ((scm_ubits_t
*) SCM_VELTS (kv
))[k
];
1965 return SCM_UNSPECIFIED
;
1970 SCM_DEFINE (scm_bit_count_star
, "bit-count*", 3, 0, 0,
1971 (SCM v
, SCM kv
, SCM obj
),
1974 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1976 "@var{bv} is not modified.")
1977 #define FUNC_NAME s_scm_bit_count_star
1980 scm_bits_t vlen
, count
= 0;
1983 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1984 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1985 switch SCM_TYP7 (kv
)
1989 SCM_WRONG_TYPE_ARG (2, kv
);
1993 vlen
= SCM_BITVECTOR_LENGTH (v
);
1994 if (SCM_FALSEP (obj
))
1995 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1997 k
= ((unsigned long *) SCM_VELTS (kv
))[--i
];
1999 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
2000 if (!SCM_BITVEC_REF(v
,k
))
2003 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
2004 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
2006 k
= ((unsigned long *) SCM_VELTS (kv
))[--i
];
2008 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
2009 if (SCM_BITVEC_REF (v
,k
))
2013 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
2019 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
2020 if (0 == SCM_BITVECTOR_LENGTH (v
))
2022 SCM_ASRTGO (SCM_BOOLP (obj
), badarg3
);
2023 fObj
= SCM_EQ_P (obj
, SCM_BOOL_T
);
2024 i
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_BITS_LENGTH
;
2026 ((scm_ubits_t
*) SCM_VELTS (kv
))[i
]
2027 & (fObj
? ((scm_ubits_t
*) SCM_VELTS (v
))[i
] : ~ ((scm_ubits_t
*) SCM_VELTS (v
))[i
]);
2028 k
<<= SCM_BITS_LENGTH
- 1 - ((SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_BITS_LENGTH
);
2032 count
+= cnt_tab
[k
& 0x0f];
2034 return SCM_MAKINUM (count
);
2036 /* urg. repetitive (see above.) */
2038 ((scm_ubits_t
*) SCM_VELTS (kv
))[i
]
2039 & (fObj
? ((scm_ubits_t
*) SCM_VELTS (v
))[i
] : ~ ((scm_ubits_t
*) SCM_VELTS (v
))[i
]);
2043 return SCM_MAKINUM (count
);
2048 SCM_DEFINE (scm_bit_invert_x
, "bit-invert!", 1, 0, 0,
2050 "Modifies @var{bv} by replacing each element with its negation.")
2051 #define FUNC_NAME s_scm_bit_invert_x
2055 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
2057 k
= SCM_BITVECTOR_LENGTH (v
);
2058 for (k
= (k
+ SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
; k
--;)
2059 ((scm_ubits_t
*) SCM_VELTS (v
))[k
] = ~((scm_ubits_t
*) SCM_VELTS (v
))[k
];
2061 return SCM_UNSPECIFIED
;
2067 scm_istr2bve (char *str
, scm_bits_t len
)
2069 SCM v
= scm_make_uve (len
, SCM_BOOL_T
);
2070 scm_ubits_t
*data
= (scm_ubits_t
*) SCM_VELTS (v
);
2071 register scm_bits_t mask
;
2074 for (k
= 0; k
< (len
+ SCM_BITS_LENGTH
- 1) / SCM_BITS_LENGTH
; k
++)
2077 j
= len
- k
* SCM_BITS_LENGTH
;
2078 if (j
> SCM_BITS_LENGTH
)
2079 j
= SCM_BITS_LENGTH
;
2080 for (mask
= 1L; j
--; mask
<<= 1)
2098 ra2l (SCM ra
, scm_bits_t base
, size_t k
)
2100 register SCM res
= SCM_EOL
;
2101 register scm_bits_t inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2102 register scm_bits_t i
;
2103 if (SCM_ARRAY_DIMS (ra
)[k
].ubnd
< SCM_ARRAY_DIMS (ra
)[k
].lbnd
)
2105 i
= base
+ (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
) * inc
;
2106 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2111 res
= scm_cons (ra2l (ra
, i
, k
+ 1), res
);
2119 res
= scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra
), SCM_MAKINUM (i
)), res
);
2126 SCM_DEFINE (scm_array_to_list
, "array->list", 1, 0, 0,
2128 "Return a list consisting of all the elements, in order, of\n"
2130 #define FUNC_NAME s_scm_array_to_list
2134 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
2138 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
2140 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
2141 return ra2l (v
, SCM_ARRAY_BASE (v
), 0);
2142 case scm_tc7_vector
:
2144 return scm_vector_to_list (v
);
2145 case scm_tc7_string
:
2146 return scm_string_to_list (v
);
2149 scm_ubits_t
*data
= (scm_ubits_t
*) SCM_VELTS (v
);
2150 register scm_ubits_t mask
;
2151 for (k
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_BITS_LENGTH
; k
> 0; k
--)
2152 for (mask
= 1UL << (SCM_BITS_LENGTH
- 1); mask
; mask
>>= 1)
2153 res
= scm_cons (SCM_BOOL(data
[k
] & mask
), res
);
2154 for (mask
= 1L << ((SCM_BITVECTOR_LENGTH (v
) % SCM_BITS_LENGTH
) - 1); mask
; mask
>>= 1)
2155 res
= scm_cons (SCM_BOOL(data
[k
] & mask
), res
);
2158 case scm_tc7_byvect
:
2160 signed char *data
= (signed char *) SCM_VELTS (v
);
2161 scm_bits_t k
= SCM_UVECTOR_LENGTH (v
);
2163 res
= scm_cons (SCM_MAKINUM (data
[--k
]), res
);
2168 scm_ubits_t
*data
= (scm_ubits_t
*) SCM_VELTS(v
);
2169 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2170 res
= scm_cons(scm_ubits2num(data
[k
]), res
);
2175 scm_bits_t
*data
= (scm_bits_t
*) SCM_VELTS(v
);
2176 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2177 res
= scm_cons(scm_bits2num(data
[k
]), res
);
2182 short *data
= (short *)SCM_VELTS(v
);
2183 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2184 res
= scm_cons(scm_short2num (data
[k
]), res
);
2187 #ifdef HAVE_LONG_LONGS
2188 case scm_tc7_llvect
:
2190 long long *data
= (long long *)SCM_VELTS(v
);
2191 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2192 res
= scm_cons(scm_long_long2num(data
[k
]), res
);
2198 float *data
= (float *) SCM_VELTS (v
);
2199 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2200 res
= scm_cons (scm_make_real (data
[k
]), res
);
2205 double *data
= (double *) SCM_VELTS (v
);
2206 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2207 res
= scm_cons (scm_make_real (data
[k
]), res
);
2212 double (*data
)[2] = (double (*)[2]) SCM_VELTS (v
);
2213 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2214 res
= scm_cons (scm_make_complex (data
[k
][0], data
[k
][1]), res
);
2222 static int l2ra (SCM lst
, SCM ra
, scm_bits_t base
, size_t k
);
2224 SCM_DEFINE (scm_list_to_uniform_array
, "list->uniform-array", 3, 0, 0,
2225 (SCM ndim
, SCM prot
, SCM lst
),
2226 "@deffnx procedure list->uniform-vector prot lst\n"
2227 "Return a uniform array of the type indicated by prototype\n"
2228 "@var{prot} with elements the same as those of @var{lst}.\n"
2229 "Elements must be of the appropriate type, no coercions are\n"
2231 #define FUNC_NAME s_scm_list_to_uniform_array
2238 SCM_VALIDATE_INUM_COPY (1,ndim
,k
);
2241 n
= scm_ilength (row
);
2242 SCM_ASSERT (n
>= 0, lst
, SCM_ARG3
, FUNC_NAME
);
2243 shp
= scm_cons (SCM_MAKINUM (n
), shp
);
2245 row
= SCM_CAR (row
);
2247 ra
= scm_dimensions_to_uniform_array (scm_reverse (shp
), prot
,
2249 if (SCM_NULLP (shp
))
2251 SCM_ASRTGO (1 == scm_ilength (lst
), badlst
);
2252 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_EOL
);
2255 if (!SCM_ARRAYP (ra
))
2257 scm_bits_t length
= SCM_INUM (scm_uniform_vector_length (ra
));
2258 for (k
= 0; k
< length
; k
++, lst
= SCM_CDR (lst
))
2259 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_MAKINUM (k
));
2262 if (l2ra (lst
, ra
, SCM_ARRAY_BASE (ra
), 0))
2265 badlst
:SCM_MISC_ERROR ("Bad scm_array contents list: ~S", SCM_LIST1 (lst
));
2270 l2ra (SCM lst
, SCM ra
, scm_bits_t base
, size_t k
)
2272 register scm_bits_t inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2273 register scm_bits_t n
= (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
);
2276 return (SCM_NULLP (lst
));
2277 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2281 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2283 ok
= ok
&& l2ra (SCM_CAR (lst
), ra
, base
, k
+ 1);
2285 lst
= SCM_CDR (lst
);
2287 if (SCM_NNULLP (lst
))
2294 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2296 scm_array_set_x (SCM_ARRAY_V (ra
), SCM_CAR (lst
), SCM_MAKINUM (base
));
2298 lst
= SCM_CDR (lst
);
2300 if (SCM_NNULLP (lst
))
2308 rapr1 (SCM ra
, scm_bits_t j
, size_t k
, SCM port
, scm_print_state
*pstate
)
2311 scm_bits_t n
= (SCM_TYP7 (ra
) == scm_tc7_smob
2313 : SCM_INUM (scm_uniform_vector_length (ra
)));
2316 switch SCM_TYP7 (ra
)
2321 SCM_ARRAY_BASE (ra
) = j
;
2323 scm_iprin1 (ra
, port
, pstate
);
2324 for (j
+= inc
; n
-- > 0; j
+= inc
)
2326 scm_putc (' ', port
);
2327 SCM_ARRAY_BASE (ra
) = j
;
2328 scm_iprin1 (ra
, port
, pstate
);
2332 if (k
+ 1 < SCM_ARRAY_NDIM (ra
))
2335 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2336 for (i
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
; i
< SCM_ARRAY_DIMS (ra
)[k
].ubnd
; i
++)
2338 scm_putc ('(', port
);
2339 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2340 scm_puts (") ", port
);
2343 if (i
== SCM_ARRAY_DIMS (ra
)[k
].ubnd
)
2344 { /* could be zero size. */
2345 scm_putc ('(', port
);
2346 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2347 scm_putc (')', port
);
2351 if (SCM_ARRAY_NDIM (ra
) > 0)
2352 { /* Could be zero-dimensional */
2353 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2354 n
= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
2358 ra
= SCM_ARRAY_V (ra
);
2361 /* scm_tc7_bvect and scm_tc7_llvect only? */
2363 scm_iprin1 (scm_uniform_vector_ref (ra
, SCM_MAKINUM (j
)), port
, pstate
);
2364 for (j
+= inc
; n
-- > 0; j
+= inc
)
2366 scm_putc (' ', port
);
2367 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2370 case scm_tc7_string
:
2372 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2373 if (SCM_WRITINGP (pstate
))
2374 for (j
+= inc
; n
-- > 0; j
+= inc
)
2376 scm_putc (' ', port
);
2377 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2380 for (j
+= inc
; n
-- > 0; j
+= inc
)
2381 scm_putc (SCM_STRING_CHARS (ra
)[j
], port
);
2383 case scm_tc7_byvect
:
2385 scm_intprint (((char *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2386 for (j
+= inc
; n
-- > 0; j
+= inc
)
2388 scm_putc (' ', port
);
2389 scm_intprint (((char *)SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2399 /* intprint can't handle >= 2^31. */
2400 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2401 scm_puts (str
, port
);
2403 for (j
+= inc
; n
-- > 0; j
+= inc
)
2405 scm_putc (' ', port
);
2406 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2407 scm_puts (str
, port
);
2412 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2413 for (j
+= inc
; n
-- > 0; j
+= inc
)
2415 scm_putc (' ', port
);
2416 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2422 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2423 for (j
+= inc
; n
-- > 0; j
+= inc
)
2425 scm_putc (' ', port
);
2426 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2433 SCM z
= scm_make_real (1.0);
2434 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2435 scm_print_real (z
, port
, pstate
);
2436 for (j
+= inc
; n
-- > 0; j
+= inc
)
2438 scm_putc (' ', port
);
2439 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2440 scm_print_real (z
, port
, pstate
);
2447 SCM z
= scm_make_real (1.0 / 3.0);
2448 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2449 scm_print_real (z
, port
, pstate
);
2450 for (j
+= inc
; n
-- > 0; j
+= inc
)
2452 scm_putc (' ', port
);
2453 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2454 scm_print_real (z
, port
, pstate
);
2461 SCM cz
= scm_make_complex (0.0, 1.0), z
= scm_make_real (1.0 / 3.0);
2462 SCM_REAL_VALUE (z
) =
2463 SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2464 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2465 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2467 for (j
+= inc
; n
-- > 0; j
+= inc
)
2469 scm_putc (' ', port
);
2471 = SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2472 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2473 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2484 scm_raprin1 (SCM exp
, SCM port
, scm_print_state
*pstate
)
2487 scm_bits_t base
= 0;
2488 scm_putc ('#', port
);
2494 long ndim
= SCM_ARRAY_NDIM (v
);
2495 base
= SCM_ARRAY_BASE (v
);
2496 v
= SCM_ARRAY_V (v
);
2500 scm_puts ("<enclosed-array ", port
);
2501 rapr1 (exp
, base
, 0, port
, pstate
);
2502 scm_putc ('>', port
);
2507 scm_intprint (ndim
, 10, port
);
2512 if (SCM_EQ_P (exp
, v
))
2513 { /* a uve, not an scm_array */
2517 scm_putc ('*', port
);
2518 for (i
= 0; i
< (SCM_BITVECTOR_LENGTH (exp
) / SCM_BITS_LENGTH
); i
++)
2520 w
= SCM_UNPACK (SCM_VELTS (exp
)[i
]);
2521 for (j
= SCM_BITS_LENGTH
; j
; j
--)
2523 scm_putc (w
& 1 ? '1' : '0', port
);
2527 j
= SCM_BITVECTOR_LENGTH (exp
) % SCM_BITS_LENGTH
;
2530 w
= SCM_UNPACK (SCM_VELTS (exp
)[SCM_BITVECTOR_LENGTH (exp
) / SCM_BITS_LENGTH
]);
2533 scm_putc (w
& 1 ? '1' : '0', port
);
2540 scm_putc ('b', port
);
2542 case scm_tc7_string
:
2543 scm_putc ('a', port
);
2545 case scm_tc7_byvect
:
2546 scm_putc ('y', port
);
2549 scm_putc ('u', port
);
2552 scm_putc ('e', port
);
2555 scm_putc ('h', port
);
2557 #ifdef HAVE_LONG_LONGS
2558 case scm_tc7_llvect
:
2559 scm_putc ('l', port
);
2563 scm_putc ('s', port
);
2566 scm_putc ('i', port
);
2569 scm_putc ('c', port
);
2572 scm_putc ('(', port
);
2573 rapr1 (exp
, base
, 0, port
, pstate
);
2574 scm_putc (')', port
);
2578 SCM_DEFINE (scm_array_prototype
, "array-prototype", 1, 0, 0,
2580 "Return an object that would produce an array of the same type\n"
2581 "as @var{array}, if used as the @var{prototype} for\n"
2582 "@code{make-uniform-array}.")
2583 #define FUNC_NAME s_scm_array_prototype
2586 SCM_ASRTGO (SCM_NIMP (ra
), badarg
);
2588 switch SCM_TYP7 (ra
)
2591 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
2593 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
2595 return SCM_UNSPECIFIED
;
2596 ra
= SCM_ARRAY_V (ra
);
2598 case scm_tc7_vector
:
2603 case scm_tc7_string
:
2604 return SCM_MAKE_CHAR ('a');
2605 case scm_tc7_byvect
:
2606 return SCM_MAKE_CHAR ('\0');
2608 return SCM_MAKINUM (1L);
2610 return SCM_MAKINUM (-1L);
2612 return scm_str2symbol ("s");
2613 #ifdef HAVE_LONG_LONGS
2614 case scm_tc7_llvect
:
2615 return scm_str2symbol ("l");
2618 return scm_make_real (1.0);
2620 return scm_make_real (1.0 / 3.0);
2622 return scm_make_complex (0.0, 1.0);
2629 array_mark (SCM ptr
)
2631 return SCM_ARRAY_V (ptr
);
2636 array_free (SCM ptr
)
2638 scm_must_free (SCM_ARRAY_MEM (ptr
));
2639 return sizeof (scm_array_t
) +
2640 SCM_ARRAY_NDIM (ptr
) * sizeof (scm_array_dim_t
);
2646 scm_tc16_array
= scm_make_smob_type ("array", 0);
2647 scm_set_smob_mark (scm_tc16_array
, array_mark
);
2648 scm_set_smob_free (scm_tc16_array
, array_free
);
2649 scm_set_smob_print (scm_tc16_array
, scm_raprin1
);
2650 scm_set_smob_equalp (scm_tc16_array
, scm_array_equal_p
);
2651 scm_add_feature ("array");
2652 #ifndef SCM_MAGIC_SNARFER
2653 #include "libguile/unif.x"