1 /* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 This file has code for arrays in lots of variants (double, integer,
21 unsigned etc. ). It suffers from hugely repetitive code because
22 there is similar (but different) code for every variant included. (urg.)
36 #include "libguile/_scm.h"
37 #include "libguile/chars.h"
38 #include "libguile/eval.h"
39 #include "libguile/fports.h"
40 #include "libguile/smob.h"
41 #include "libguile/strop.h"
42 #include "libguile/feature.h"
43 #include "libguile/root.h"
44 #include "libguile/strings.h"
45 #include "libguile/vectors.h"
47 #include "libguile/validate.h"
48 #include "libguile/unif.h"
49 #include "libguile/ramap.h"
60 /* The set of uniform scm_vector types is:
62 * unsigned char string
69 * complex double cvect
74 scm_t_bits scm_tc16_array
;
75 static SCM exactly_one_third
;
77 /* return the size of an element in a uniform array or 0 if type not
80 scm_uniform_element_size (SCM obj
)
84 switch (SCM_TYP7 (obj
))
89 result
= sizeof (long);
93 result
= sizeof (char);
97 result
= sizeof (short);
100 #if SCM_SIZEOF_LONG_LONG != 0
102 result
= sizeof (long long);
107 result
= sizeof (float);
111 result
= sizeof (double);
115 result
= 2 * sizeof (double);
124 /* Silly function used not to modify the semantics of the silly
125 * prototype system in order to be backward compatible.
130 if (!SCM_REALP (obj
))
134 double x
= SCM_REAL_VALUE (obj
);
136 return (- SCM_FLTMAX
< x
) && (x
< SCM_FLTMAX
) && (fx
== x
);
141 scm_make_uve (long k
, SCM prot
)
142 #define FUNC_NAME "scm_make_uve"
147 if (SCM_EQ_P (prot
, SCM_BOOL_T
))
152 scm_long2num (k
), k
<= SCM_BITVECTOR_MAX_LENGTH
);
153 i
= sizeof (long) * ((k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
);
154 v
= scm_cell (SCM_MAKE_BITVECTOR_TAG (k
),
155 (scm_t_bits
) scm_gc_malloc (i
, "vector"));
158 v
= scm_cell (SCM_MAKE_BITVECTOR_TAG (0), 0);
161 else if (SCM_CHARP (prot
) && (SCM_CHAR (prot
) == '\0'))
163 i
= sizeof (char) * k
;
164 type
= scm_tc7_byvect
;
166 else if (SCM_CHARP (prot
))
168 i
= sizeof (char) * k
;
169 return scm_allocate_string (i
);
171 else if (SCM_INUMP (prot
))
173 i
= sizeof (long) * k
;
174 if (SCM_INUM (prot
) > 0)
175 type
= scm_tc7_uvect
;
177 type
= scm_tc7_ivect
;
179 else if (SCM_FRACTIONP (prot
))
181 if (scm_num_eq_p (exactly_one_third
, prot
))
184 else if (SCM_SYMBOLP (prot
) && (1 == SCM_SYMBOL_LENGTH (prot
)))
188 s
= SCM_SYMBOL_CHARS (prot
)[0];
191 i
= sizeof (short) * k
;
192 type
= scm_tc7_svect
;
194 #if SCM_SIZEOF_LONG_LONG != 0
197 i
= sizeof (long long) * k
;
198 type
= scm_tc7_llvect
;
203 return scm_c_make_vector (k
, SCM_UNDEFINED
);
206 else if (!SCM_INEXACTP (prot
))
207 /* Huge non-unif vectors are NOT supported. */
208 /* no special scm_vector */
209 return scm_c_make_vector (k
, SCM_UNDEFINED
);
210 else if (singp (prot
))
212 i
= sizeof (float) * k
;
213 type
= scm_tc7_fvect
;
215 else if (SCM_COMPLEXP (prot
))
217 i
= 2 * sizeof (double) * k
;
218 type
= scm_tc7_cvect
;
223 i
= sizeof (double) * k
;
224 type
= scm_tc7_dvect
;
227 SCM_ASSERT_RANGE (1, scm_long2num (k
), k
<= SCM_UVECTOR_MAX_LENGTH
);
229 return scm_cell (SCM_MAKE_UVECTOR_TAG (k
, type
),
230 (scm_t_bits
) scm_gc_malloc (i
, "vector"));
235 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
237 "Return the number of elements in @var{uve}.")
238 #define FUNC_NAME s_scm_uniform_vector_length
240 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
244 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
247 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v
));
249 return SCM_MAKINUM (SCM_STRING_LENGTH (v
));
251 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v
));
259 #if SCM_SIZEOF_LONG_LONG != 0
262 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v
));
267 SCM_DEFINE (scm_array_p
, "array?", 1, 1, 0,
269 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
270 "not. The @var{prototype} argument is used with uniform arrays\n"
271 "and is described elsewhere.")
272 #define FUNC_NAME s_scm_array_p
276 nprot
= SCM_UNBNDP (prot
);
281 while (SCM_TYP7 (v
) == scm_tc7_smob
)
292 return SCM_BOOL(nprot
);
297 switch (SCM_TYP7 (v
))
300 protp
= (SCM_EQ_P (prot
, SCM_BOOL_T
));
303 protp
= SCM_CHARP(prot
) && (SCM_CHAR (prot
) != '\0');
306 protp
= SCM_EQ_P (prot
, SCM_MAKE_CHAR ('\0'));
309 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)>0;
312 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)<=0;
315 protp
= SCM_SYMBOLP (prot
)
316 && (1 == SCM_SYMBOL_LENGTH (prot
))
317 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
319 #if SCM_SIZEOF_LONG_LONG != 0
321 protp
= SCM_SYMBOLP (prot
)
322 && (1 == SCM_SYMBOL_LENGTH (prot
))
323 && ('l' == SCM_SYMBOL_CHARS (prot
)[0]);
327 protp
= singp (prot
);
330 protp
= ((SCM_REALP(prot
) && ! singp (prot
))
331 || (SCM_FRACTIONP (prot
)
332 && scm_num_eq_p (exactly_one_third
, prot
)));
335 protp
= SCM_COMPLEXP(prot
);
339 protp
= SCM_NULLP(prot
);
345 return SCM_BOOL(protp
);
351 SCM_DEFINE (scm_array_rank
, "array-rank", 1, 0, 0,
353 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
354 "not an array, @code{0} is returned.")
355 #define FUNC_NAME s_scm_array_rank
359 switch (SCM_TYP7 (ra
))
372 #if SCM_SIZEOF_LONG_LONG != 0
376 return SCM_MAKINUM (1L);
379 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra
));
386 SCM_DEFINE (scm_array_dimensions
, "array-dimensions", 1, 0, 0,
388 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
389 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
391 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
393 #define FUNC_NAME s_scm_array_dimensions
400 switch (SCM_TYP7 (ra
))
415 #if SCM_SIZEOF_LONG_LONG != 0
418 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
420 if (!SCM_ARRAYP (ra
))
422 k
= SCM_ARRAY_NDIM (ra
);
423 s
= SCM_ARRAY_DIMS (ra
);
425 res
= scm_cons (s
[k
].lbnd
426 ? scm_cons2 (SCM_MAKINUM (s
[k
].lbnd
),
427 SCM_MAKINUM (s
[k
].ubnd
),
429 : SCM_MAKINUM (1 + s
[k
].ubnd
),
437 SCM_DEFINE (scm_shared_array_root
, "shared-array-root", 1, 0, 0,
439 "Return the root vector of a shared array.")
440 #define FUNC_NAME s_scm_shared_array_root
442 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
443 return SCM_ARRAY_V (ra
);
448 SCM_DEFINE (scm_shared_array_offset
, "shared-array-offset", 1, 0, 0,
450 "Return the root vector index of the first element in the array.")
451 #define FUNC_NAME s_scm_shared_array_offset
453 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
454 return SCM_MAKINUM (SCM_ARRAY_BASE (ra
));
459 SCM_DEFINE (scm_shared_array_increments
, "shared-array-increments", 1, 0, 0,
461 "For each dimension, return the distance between elements in the root vector.")
462 #define FUNC_NAME s_scm_shared_array_increments
467 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
468 k
= SCM_ARRAY_NDIM (ra
);
469 s
= SCM_ARRAY_DIMS (ra
);
471 res
= scm_cons (SCM_MAKINUM (s
[k
].inc
), res
);
477 static char s_bad_ind
[] = "Bad scm_array index";
481 scm_aind (SCM ra
, SCM args
, const char *what
)
482 #define FUNC_NAME what
486 register unsigned long pos
= SCM_ARRAY_BASE (ra
);
487 register unsigned long k
= SCM_ARRAY_NDIM (ra
);
488 scm_t_array_dim
*s
= SCM_ARRAY_DIMS (ra
);
489 if (SCM_INUMP (args
))
492 scm_error_num_args_subr (what
);
493 return pos
+ (SCM_INUM (args
) - s
->lbnd
) * (s
->inc
);
495 while (k
&& SCM_CONSP (args
))
497 ind
= SCM_CAR (args
);
498 args
= SCM_CDR (args
);
499 if (!SCM_INUMP (ind
))
500 scm_misc_error (what
, s_bad_ind
, SCM_EOL
);
502 if (j
< s
->lbnd
|| j
> s
->ubnd
)
503 scm_out_of_range (what
, ind
);
504 pos
+= (j
- s
->lbnd
) * (s
->inc
);
508 if (k
!= 0 || !SCM_NULLP (args
))
509 scm_error_num_args_subr (what
);
517 scm_make_ra (int ndim
)
521 SCM_NEWSMOB(ra
, ((scm_t_bits
) ndim
<< 17) + scm_tc16_array
,
522 scm_gc_malloc ((sizeof (scm_t_array
) +
523 ndim
* sizeof (scm_t_array_dim
)),
525 SCM_ARRAY_V (ra
) = scm_nullvect
;
530 static char s_bad_spec
[] = "Bad scm_array dimension";
531 /* Increments will still need to be set. */
535 scm_shap2ra (SCM args
, const char *what
)
539 int ndim
= scm_ilength (args
);
541 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
543 ra
= scm_make_ra (ndim
);
544 SCM_ARRAY_BASE (ra
) = 0;
545 s
= SCM_ARRAY_DIMS (ra
);
546 for (; !SCM_NULLP (args
); s
++, args
= SCM_CDR (args
))
548 spec
= SCM_CAR (args
);
549 if (SCM_INUMP (spec
))
551 if (SCM_INUM (spec
) < 0)
552 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
554 s
->ubnd
= SCM_INUM (spec
) - 1;
559 if (!SCM_CONSP (spec
) || !SCM_INUMP (SCM_CAR (spec
)))
560 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
561 s
->lbnd
= SCM_INUM (SCM_CAR (spec
));
564 || !SCM_INUMP (SCM_CAR (sp
))
565 || !SCM_NULLP (SCM_CDR (sp
)))
566 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
567 s
->ubnd
= SCM_INUM (SCM_CAR (sp
));
574 SCM_DEFINE (scm_dimensions_to_uniform_array
, "dimensions->uniform-array", 2, 1, 0,
575 (SCM dims
, SCM prot
, SCM fill
),
576 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
577 "Create and return a uniform array or vector of type\n"
578 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
579 "length @var{length}. If @var{fill} is supplied, it's used to\n"
580 "fill the array, otherwise @var{prototype} is used.")
581 #define FUNC_NAME s_scm_dimensions_to_uniform_array
584 unsigned long rlen
= 1;
588 if (SCM_INUMP (dims
))
590 SCM answer
= scm_make_uve (SCM_INUM (dims
), prot
);
591 if (!SCM_UNBNDP (fill
))
592 scm_array_fill_x (answer
, fill
);
593 else if (SCM_SYMBOLP (prot
))
594 scm_array_fill_x (answer
, SCM_MAKINUM (0));
596 scm_array_fill_x (answer
, prot
);
600 SCM_ASSERT (SCM_NULLP (dims
) || SCM_CONSP (dims
),
601 dims
, SCM_ARG1
, FUNC_NAME
);
602 ra
= scm_shap2ra (dims
, FUNC_NAME
);
603 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
604 s
= SCM_ARRAY_DIMS (ra
);
605 k
= SCM_ARRAY_NDIM (ra
);
610 SCM_ASSERT_RANGE (1, dims
, s
[k
].lbnd
<= s
[k
].ubnd
);
611 rlen
= (s
[k
].ubnd
- s
[k
].lbnd
+ 1) * s
[k
].inc
;
614 SCM_ARRAY_V (ra
) = scm_make_uve (rlen
, prot
);
616 if (!SCM_UNBNDP (fill
))
617 scm_array_fill_x (ra
, fill
);
618 else if (SCM_SYMBOLP (prot
))
619 scm_array_fill_x (ra
, SCM_MAKINUM (0));
621 scm_array_fill_x (ra
, prot
);
623 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
624 if (s
->ubnd
< s
->lbnd
|| (0 == s
->lbnd
&& 1 == s
->inc
))
625 return SCM_ARRAY_V (ra
);
632 scm_ra_set_contp (SCM ra
)
634 size_t k
= SCM_ARRAY_NDIM (ra
);
637 long inc
= SCM_ARRAY_DIMS (ra
)[k
- 1].inc
;
640 if (inc
!= SCM_ARRAY_DIMS (ra
)[k
].inc
)
642 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra
);
645 inc
*= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
646 - SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
649 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
653 SCM_DEFINE (scm_make_shared_array
, "make-shared-array", 2, 0, 1,
654 (SCM oldra
, SCM mapfunc
, SCM dims
),
655 "@code{make-shared-array} can be used to create shared subarrays of other\n"
656 "arrays. The @var{mapper} is a function that translates coordinates in\n"
657 "the new array into coordinates in the old array. A @var{mapper} must be\n"
658 "linear, and its range must stay within the bounds of the old array, but\n"
659 "it can be otherwise arbitrary. A simple example:\n"
661 "(define fred (make-array #f 8 8))\n"
662 "(define freds-diagonal\n"
663 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
664 "(array-set! freds-diagonal 'foo 3)\n"
665 "(array-ref fred 3 3) @result{} foo\n"
666 "(define freds-center\n"
667 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
668 "(array-ref freds-center 0 0) @result{} foo\n"
670 #define FUNC_NAME s_scm_make_shared_array
676 long old_min
, new_min
, old_max
, new_max
;
679 SCM_VALIDATE_REST_ARGUMENT (dims
);
680 SCM_VALIDATE_ARRAY (1, oldra
);
681 SCM_VALIDATE_PROC (2, mapfunc
);
682 ra
= scm_shap2ra (dims
, FUNC_NAME
);
683 if (SCM_ARRAYP (oldra
))
685 SCM_ARRAY_V (ra
) = SCM_ARRAY_V (oldra
);
686 old_min
= old_max
= SCM_ARRAY_BASE (oldra
);
687 s
= SCM_ARRAY_DIMS (oldra
);
688 k
= SCM_ARRAY_NDIM (oldra
);
692 old_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
694 old_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
699 SCM_ARRAY_V (ra
) = oldra
;
701 old_max
= SCM_INUM (scm_uniform_vector_length (oldra
)) - 1;
704 s
= SCM_ARRAY_DIMS (ra
);
705 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
707 inds
= scm_cons (SCM_MAKINUM (s
[k
].lbnd
), inds
);
708 if (s
[k
].ubnd
< s
[k
].lbnd
)
710 if (1 == SCM_ARRAY_NDIM (ra
))
711 ra
= scm_make_uve (0L, scm_array_prototype (ra
));
713 SCM_ARRAY_V (ra
) = scm_make_uve (0L, scm_array_prototype (ra
));
717 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
718 if (SCM_ARRAYP (oldra
))
719 i
= (size_t) scm_aind (oldra
, imap
, FUNC_NAME
);
722 if (SCM_NINUMP (imap
))
725 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
726 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
727 imap
= SCM_CAR (imap
);
731 SCM_ARRAY_BASE (ra
) = new_min
= new_max
= i
;
733 k
= SCM_ARRAY_NDIM (ra
);
736 if (s
[k
].ubnd
> s
[k
].lbnd
)
738 SCM_SETCAR (indptr
, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr
)) + 1));
739 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
740 if (SCM_ARRAYP (oldra
))
742 s
[k
].inc
= scm_aind (oldra
, imap
, FUNC_NAME
) - i
;
745 if (SCM_NINUMP (imap
))
747 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
748 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
749 imap
= SCM_CAR (imap
);
751 s
[k
].inc
= (long) SCM_INUM (imap
) - i
;
755 new_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
757 new_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
760 s
[k
].inc
= new_max
- new_min
+ 1; /* contiguous by default */
761 indptr
= SCM_CDR (indptr
);
763 if (old_min
> new_min
|| old_max
< new_max
)
764 SCM_MISC_ERROR ("mapping out of range", SCM_EOL
);
765 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
767 SCM v
= SCM_ARRAY_V (ra
);
768 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
769 if (1 == s
->inc
&& 0 == s
->lbnd
&& length
== 1 + s
->ubnd
)
771 if (s
->ubnd
< s
->lbnd
)
772 return scm_make_uve (0L, scm_array_prototype (ra
));
774 scm_ra_set_contp (ra
);
780 /* args are RA . DIMS */
781 SCM_DEFINE (scm_transpose_array
, "transpose-array", 1, 0, 1,
783 "Return an array sharing contents with @var{array}, but with\n"
784 "dimensions arranged in a different order. There must be one\n"
785 "@var{dim} argument for each dimension of @var{array}.\n"
786 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
787 "and the rank of the array to be returned. Each integer in that\n"
788 "range must appear at least once in the argument list.\n"
790 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
791 "dimensions in the array to be returned, their positions in the\n"
792 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
793 "may have the same value, in which case the returned array will\n"
794 "have smaller rank than @var{array}.\n"
797 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
798 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
799 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
800 " #2((a 4) (b 5) (c 6))\n"
802 #define FUNC_NAME s_scm_transpose_array
805 SCM
const *ve
= &vargs
;
806 scm_t_array_dim
*s
, *r
;
809 SCM_VALIDATE_REST_ARGUMENT (args
);
810 SCM_ASSERT (SCM_NIMP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
811 switch (SCM_TYP7 (ra
))
814 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
824 #if SCM_SIZEOF_LONG_LONG != 0
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
)));
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
);
840 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
842 SCM_ASSERT (SCM_INUMP (ve
[k
]), ve
[k
], (SCM_ARG2
+ k
),
844 i
= SCM_INUM (ve
[k
]);
845 if (i
< 0 || i
>= SCM_ARRAY_NDIM (ra
))
846 scm_out_of_range (FUNC_NAME
, ve
[k
]);
851 res
= scm_make_ra (ndim
);
852 SCM_ARRAY_V (res
) = SCM_ARRAY_V (ra
);
853 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra
);
856 SCM_ARRAY_DIMS (res
)[k
].lbnd
= 0;
857 SCM_ARRAY_DIMS (res
)[k
].ubnd
= -1;
859 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
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
)
873 if (r
->ubnd
> s
->ubnd
)
875 if (r
->lbnd
< s
->lbnd
)
877 SCM_ARRAY_BASE (res
) += (s
->lbnd
- r
->lbnd
) * r
->inc
;
884 SCM_MISC_ERROR ("bad argument list", SCM_EOL
);
885 scm_ra_set_contp (res
);
891 /* args are RA . AXES */
892 SCM_DEFINE (scm_enclose_array
, "enclose-array", 1, 0, 1,
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"
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"
912 #define FUNC_NAME s_scm_enclose_array
914 SCM axv
, res
, ra_inr
;
915 scm_t_array_dim vdim
, *s
= &vdim
;
916 int ndim
, j
, k
, ninr
, noutr
;
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
);
923 SCM_WRONG_NUM_ARGS ();
924 ra_inr
= scm_make_ra (ninr
);
925 SCM_ASRTGO (SCM_NIMP (ra
), badarg1
);
929 badarg1
:SCM_WRONG_TYPE_ARG (1, ra
);
941 #if SCM_SIZEOF_LONG_LONG != 0
945 s
->ubnd
= SCM_INUM (scm_uniform_vector_length (ra
)) - 1;
947 SCM_ARRAY_V (ra_inr
) = ra
;
948 SCM_ARRAY_BASE (ra_inr
) = 0;
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
);
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
))
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;
976 for (j
= 0, k
= 0; k
< noutr
; k
++, j
++)
978 while (SCM_STRING_CHARS (axv
)[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
;
984 scm_ra_set_contp (ra_inr
);
985 scm_ra_set_contp (res
);
992 SCM_DEFINE (scm_array_in_bounds_p
, "array-in-bounds?", 1, 0, 1,
994 "Return @code{#t} if its arguments would be acceptable to\n"
996 #define FUNC_NAME s_scm_array_in_bounds_p
1004 SCM_VALIDATE_REST_ARGUMENT (args
);
1005 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1006 if (SCM_NIMP (args
))
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
);
1018 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1019 wna
: SCM_WRONG_NUM_ARGS ();
1021 k
= SCM_ARRAY_NDIM (v
);
1022 s
= SCM_ARRAY_DIMS (v
);
1023 pos
= SCM_ARRAY_BASE (v
);
1026 SCM_ASRTGO (SCM_NULLP (ind
), wna
);
1033 if (!(j
>= (s
->lbnd
) && j
<= (s
->ubnd
)))
1035 SCM_ASRTGO (--k
== scm_ilength (args
), wna
);
1038 pos
+= (j
- s
->lbnd
) * (s
->inc
);
1039 if (!(--k
&& SCM_NIMP (args
)))
1041 ind
= SCM_CAR (args
);
1042 args
= SCM_CDR (args
);
1044 if (!SCM_INUMP (ind
))
1045 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
1047 SCM_ASRTGO (0 == k
, wna
);
1048 v
= SCM_ARRAY_V (v
);
1051 case scm_tc7_string
:
1052 case scm_tc7_byvect
:
1059 #if SCM_SIZEOF_LONG_LONG != 0
1060 case scm_tc7_llvect
:
1062 case scm_tc7_vector
:
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
);
1074 SCM_REGISTER_PROC(s_array_ref
, "array-ref", 1, 0, 1, scm_uniform_vector_ref
);
1077 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
1079 "@deffnx {Scheme Procedure} array-ref v . args\n"
1080 "Return the element at the @code{(index1, index2)} element in\n"
1082 #define FUNC_NAME s_scm_uniform_vector_ref
1088 SCM_ASRTGO (SCM_NULLP (args
), badarg
);
1091 else if (SCM_ARRAYP (v
))
1093 pos
= scm_aind (v
, args
, FUNC_NAME
);
1094 v
= SCM_ARRAY_V (v
);
1098 unsigned long int length
;
1099 if (SCM_NIMP (args
))
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
);
1107 SCM_VALIDATE_INUM (2, args
);
1108 pos
= SCM_INUM (args
);
1110 length
= SCM_INUM (scm_uniform_vector_length (v
));
1111 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1116 if (SCM_NULLP (args
))
1119 SCM_WRONG_TYPE_ARG (1, v
);
1123 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1125 SCM_WRONG_NUM_ARGS ();
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
;
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
;
1141 if (SCM_BITVEC_REF (v
, pos
))
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
]);
1150 return scm_ulong2num (((unsigned long *) SCM_VELTS (v
))[pos
]);
1152 return scm_long2num (((signed long *) SCM_VELTS (v
))[pos
]);
1155 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1156 #if SCM_SIZEOF_LONG_LONG != 0
1157 case scm_tc7_llvect
:
1158 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1162 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1164 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
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
:
1170 return SCM_VELTS (v
)[pos
];
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.) */
1179 scm_cvref (SCM v
, unsigned long pos
, SCM last
)
1180 #define FUNC_NAME "scm_cvref"
1185 SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1187 if (SCM_BITVEC_REF(v
, pos
))
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
]);
1196 return scm_ulong2num(((unsigned long *) SCM_VELTS (v
))[pos
]);
1198 return scm_long2num(((signed long *) SCM_VELTS (v
))[pos
]);
1200 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1201 #if SCM_SIZEOF_LONG_LONG != 0
1202 case scm_tc7_llvect
:
1203 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1206 if (SCM_REALP (last
) && !SCM_EQ_P (last
, scm_flo0
))
1208 SCM_REAL_VALUE (last
) = ((float *) SCM_CELL_WORD_1 (v
))[pos
];
1211 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1213 if (SCM_REALP (last
) && !SCM_EQ_P (last
, scm_flo0
))
1215 SCM_REAL_VALUE (last
) = ((double *) SCM_CELL_WORD_1 (v
))[pos
];
1218 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1220 if (SCM_COMPLEXP (last
))
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];
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
:
1230 return SCM_VELTS (v
)[pos
];
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
;
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
;
1250 SCM_REGISTER_PROC(s_uniform_array_set1_x
, "uniform-array-set1!", 3, 0, 0, scm_array_set_x
);
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). */
1255 SCM_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
1264 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1267 pos
= scm_aind (v
, args
, FUNC_NAME
);
1268 v
= SCM_ARRAY_V (v
);
1272 unsigned long int length
;
1273 if (SCM_CONSP (args
))
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
));
1281 SCM_VALIDATE_INUM_COPY (3, args
, pos
);
1283 length
= SCM_INUM (scm_uniform_vector_length (v
));
1284 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1286 switch (SCM_TYP7 (v
))
1289 SCM_WRONG_TYPE_ARG (1, v
);
1292 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1294 SCM_WRONG_NUM_ARGS ();
1295 case scm_tc7_smob
: /* enclosed */
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
);
1303 badobj
:SCM_WRONG_TYPE_ARG (2, obj
);
1305 case scm_tc7_string
:
1306 SCM_ASRTGO (SCM_CHARP (obj
), badobj
);
1307 SCM_STRING_UCHARS (v
)[pos
] = SCM_CHAR (obj
);
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
);
1316 ((unsigned long *) SCM_UVECTOR_BASE (v
))[pos
]
1317 = scm_num2ulong (obj
, SCM_ARG2
, FUNC_NAME
);
1320 ((long *) SCM_UVECTOR_BASE (v
))[pos
]
1321 = scm_num2long (obj
, SCM_ARG2
, FUNC_NAME
);
1324 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1325 ((short *) SCM_UVECTOR_BASE (v
))[pos
] = SCM_INUM (obj
);
1327 #if SCM_SIZEOF_LONG_LONG != 0
1328 case scm_tc7_llvect
:
1329 ((long long *) SCM_UVECTOR_BASE (v
))[pos
]
1330 = scm_num2long_long (obj
, SCM_ARG2
, FUNC_NAME
);
1334 ((float *) SCM_UVECTOR_BASE (v
))[pos
]
1335 = (float) scm_num2dbl (obj
, FUNC_NAME
);
1338 ((double *) SCM_UVECTOR_BASE (v
))[pos
]
1339 = scm_num2dbl (obj
, FUNC_NAME
);
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;
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
);
1351 case scm_tc7_vector
:
1353 SCM_VECTOR_SET (v
, pos
, obj
);
1356 return SCM_UNSPECIFIED
;
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. */
1364 SCM_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"
1375 #define FUNC_NAME s_scm_array_contents
1380 switch SCM_TYP7 (ra
)
1384 case scm_tc7_vector
:
1386 case scm_tc7_string
:
1388 case scm_tc7_byvect
:
1395 #if SCM_SIZEOF_LONG_LONG != 0
1396 case scm_tc7_llvect
:
1401 size_t k
, ndim
= SCM_ARRAY_NDIM (ra
), len
= 1;
1402 if (!SCM_ARRAYP (ra
) || !SCM_ARRAY_CONTP (ra
))
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
))
1408 if (ndim
&& (1 != SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
))
1410 if (scm_tc7_bvect
== SCM_TYP7 (SCM_ARRAY_V (ra
)))
1412 if (len
!= SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) ||
1413 SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
||
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
)
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);
1440 scm_ra2contig (SCM ra
, int copy
)
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
)))
1450 if (scm_tc7_bvect
!= SCM_TYP7 (SCM_ARRAY_V (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
))
1457 ret
= scm_make_ra (k
);
1458 SCM_ARRAY_BASE (ret
) = 0;
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;
1466 SCM_ARRAY_V (ret
) = scm_make_uve (inc
, scm_array_prototype (ra
));
1468 scm_array_copy_x (ra
, ret
);
1474 SCM_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"
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
1491 SCM cra
= SCM_UNDEFINED
, v
= ra
;
1498 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1499 if (SCM_UNBNDP (port_or_fd
))
1500 port_or_fd
= scm_cur_inp
;
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
1507 : SCM_INUM (scm_uniform_vector_length (v
)));
1513 badarg1
:SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
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
);
1522 case scm_tc7_string
:
1523 base
= SCM_STRING_CHARS (v
);
1527 base
= (char *) SCM_BITVECTOR_BASE (v
);
1528 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1529 cstart
/= SCM_LONG_BIT
;
1532 case scm_tc7_byvect
:
1533 base
= (char *) SCM_UVECTOR_BASE (v
);
1538 base
= (char *) SCM_UVECTOR_BASE (v
);
1542 base
= (char *) SCM_UVECTOR_BASE (v
);
1543 sz
= sizeof (short);
1545 #if SCM_SIZEOF_LONG_LONG != 0
1546 case scm_tc7_llvect
:
1547 base
= (char *) SCM_UVECTOR_BASE (v
);
1548 sz
= sizeof (long long);
1552 base
= (char *) SCM_UVECTOR_BASE (v
);
1553 sz
= sizeof (float);
1556 base
= (char *) SCM_UVECTOR_BASE (v
);
1557 sz
= sizeof (double);
1560 base
= (char *) SCM_UVECTOR_BASE (v
);
1561 sz
= 2 * sizeof (double);
1566 if (!SCM_UNBNDP (start
))
1569 SCM_NUM2LONG (3, start
);
1571 if (offset
< 0 || offset
>= cend
)
1572 scm_out_of_range (FUNC_NAME
, start
);
1574 if (!SCM_UNBNDP (end
))
1577 SCM_NUM2LONG (4, end
);
1579 if (tend
<= offset
|| tend
> cend
)
1580 scm_out_of_range (FUNC_NAME
, end
);
1585 if (SCM_NIMP (port_or_fd
))
1587 scm_t_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
1588 int remaining
= (cend
- offset
) * sz
;
1589 char *dest
= base
+ (cstart
+ offset
) * sz
;
1591 if (pt
->rw_active
== SCM_PORT_WRITE
)
1592 scm_flush (port_or_fd
);
1594 ans
= cend
- offset
;
1595 while (remaining
> 0)
1597 if (pt
->read_pos
< pt
->read_end
)
1599 int to_copy
= min (pt
->read_end
- pt
->read_pos
,
1602 memcpy (dest
, pt
->read_pos
, to_copy
);
1603 pt
->read_pos
+= to_copy
;
1604 remaining
-= to_copy
;
1609 if (scm_fill_input (port_or_fd
) == EOF
)
1611 if (remaining
% sz
!= 0)
1613 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
1615 ans
-= remaining
/ sz
;
1622 pt
->rw_active
= SCM_PORT_READ
;
1624 else /* file descriptor. */
1626 SCM_SYSCALL (ans
= read (SCM_INUM (port_or_fd
),
1627 base
+ (cstart
+ offset
) * sz
,
1628 (sz
* (cend
- offset
))));
1632 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1633 ans
*= SCM_LONG_BIT
;
1635 if (!SCM_EQ_P (v
, ra
) && !SCM_EQ_P (cra
, ra
))
1636 scm_array_copy_x (cra
, ra
);
1638 return SCM_MAKINUM (ans
);
1642 SCM_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
1662 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
1664 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1665 if (SCM_UNBNDP (port_or_fd
))
1666 port_or_fd
= scm_cur_outp
;
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
1673 : SCM_INUM (scm_uniform_vector_length (v
)));
1679 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
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
);
1688 case scm_tc7_string
:
1689 base
= SCM_STRING_CHARS (v
);
1693 base
= (char *) SCM_BITVECTOR_BASE (v
);
1694 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1695 cstart
/= SCM_LONG_BIT
;
1698 case scm_tc7_byvect
:
1699 base
= (char *) SCM_UVECTOR_BASE (v
);
1704 base
= (char *) SCM_UVECTOR_BASE (v
);
1708 base
= (char *) SCM_UVECTOR_BASE (v
);
1709 sz
= sizeof (short);
1711 #if SCM_SIZEOF_LONG_LONG != 0
1712 case scm_tc7_llvect
:
1713 base
= (char *) SCM_UVECTOR_BASE (v
);
1714 sz
= sizeof (long long);
1718 base
= (char *) SCM_UVECTOR_BASE (v
);
1719 sz
= sizeof (float);
1722 base
= (char *) SCM_UVECTOR_BASE (v
);
1723 sz
= sizeof (double);
1726 base
= (char *) SCM_UVECTOR_BASE (v
);
1727 sz
= 2 * sizeof (double);
1732 if (!SCM_UNBNDP (start
))
1735 SCM_NUM2LONG (3, start
);
1737 if (offset
< 0 || offset
>= cend
)
1738 scm_out_of_range (FUNC_NAME
, start
);
1740 if (!SCM_UNBNDP (end
))
1743 SCM_NUM2LONG (4, end
);
1745 if (tend
<= offset
|| tend
> cend
)
1746 scm_out_of_range (FUNC_NAME
, end
);
1751 if (SCM_NIMP (port_or_fd
))
1753 char *source
= base
+ (cstart
+ offset
) * sz
;
1755 ans
= cend
- offset
;
1756 scm_lfwrite (source
, ans
* sz
, port_or_fd
);
1758 else /* file descriptor. */
1760 SCM_SYSCALL (ans
= write (SCM_INUM (port_or_fd
),
1761 base
+ (cstart
+ offset
) * sz
,
1762 (sz
* (cend
- offset
))));
1766 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1767 ans
*= SCM_LONG_BIT
;
1769 return SCM_MAKINUM (ans
);
1774 static char cnt_tab
[16] =
1775 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1777 SCM_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"
1781 #define FUNC_NAME s_scm_bit_count
1783 SCM_VALIDATE_BOOL (1, b
);
1784 SCM_ASSERT (SCM_BITVECTOR_P (bitvector
), bitvector
, 2, FUNC_NAME
);
1785 if (SCM_BITVECTOR_LENGTH (bitvector
) == 0) {
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
)) {
1794 w
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (bitvector
) - 1) % SCM_LONG_BIT
);
1797 count
+= cnt_tab
[w
& 0x0f];
1801 return SCM_MAKINUM (count
);
1804 w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1805 if (SCM_FALSEP (b
)) {
1815 SCM_DEFINE (scm_bit_position
, "bit-position", 3, 0, 0,
1816 (SCM item
, SCM v
, SCM k
),
1817 "Return the index of the first occurrance of @var{item} in bit\n"
1818 "vector @var{v}, starting from @var{k}. If there is no\n"
1819 "@var{item} entry between @var{k} and the end of\n"
1820 "@var{bitvector}, then return @code{#f}. For example,\n"
1823 "(bit-position #t #*000101 0) @result{} 3\n"
1824 "(bit-position #f #*0001111 3) @result{} #f\n"
1826 #define FUNC_NAME s_scm_bit_position
1828 long i
, lenw
, xbits
, pos
;
1829 register unsigned long w
;
1831 SCM_VALIDATE_BOOL (1, item
);
1832 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG2
, FUNC_NAME
);
1833 SCM_VALIDATE_INUM_COPY (3, k
, pos
);
1834 SCM_ASSERT_RANGE (3, k
, (pos
<= SCM_BITVECTOR_LENGTH (v
)) && (pos
>= 0));
1836 if (pos
== SCM_BITVECTOR_LENGTH (v
))
1839 lenw
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; /* watch for part words */
1840 i
= pos
/ SCM_LONG_BIT
;
1841 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1842 if (SCM_FALSEP (item
))
1844 xbits
= (pos
% SCM_LONG_BIT
);
1846 w
= ((w
>> xbits
) << xbits
);
1847 xbits
= SCM_LONG_BIT
- 1 - (SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
;
1850 if (w
&& (i
== lenw
))
1851 w
= ((w
<< xbits
) >> xbits
);
1857 return SCM_MAKINUM (pos
);
1862 return SCM_MAKINUM (pos
+ 1);
1865 return SCM_MAKINUM (pos
+ 2);
1867 return SCM_MAKINUM (pos
+ 3);
1874 pos
+= SCM_LONG_BIT
;
1875 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1876 if (SCM_FALSEP (item
))
1884 SCM_DEFINE (scm_bit_set_star_x
, "bit-set*!", 3, 0, 0,
1885 (SCM v
, SCM kv
, SCM obj
),
1886 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1887 "selecting the entries to change. The return value is\n"
1890 "If @var{kv} is a bit vector, then those entries where it has\n"
1891 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1892 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1893 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1894 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1897 "(define bv #*01000010)\n"
1898 "(bit-set*! bv #*10010001 #t)\n"
1900 "@result{} #*11010011\n"
1903 "If @var{kv} is a uniform vector of unsigned long integers, then\n"
1904 "they're indexes into @var{v} which are set to @var{obj}.\n"
1907 "(define bv #*01000010)\n"
1908 "(bit-set*! bv #u(5 2 7) #t)\n"
1910 "@result{} #*01100111\n"
1912 #define FUNC_NAME s_scm_bit_set_star_x
1914 register long i
, k
, vlen
;
1915 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1916 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1917 switch SCM_TYP7 (kv
)
1920 badarg2
:SCM_WRONG_TYPE_ARG (2, kv
);
1922 vlen
= SCM_BITVECTOR_LENGTH (v
);
1923 if (SCM_FALSEP (obj
))
1924 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1926 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1928 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1929 SCM_BITVEC_CLR(v
, k
);
1931 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1932 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1934 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1936 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1937 SCM_BITVEC_SET(v
, k
);
1940 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1943 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1944 if (SCM_FALSEP (obj
))
1945 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1946 SCM_BITVECTOR_BASE (v
) [k
] &= ~SCM_BITVECTOR_BASE (kv
) [k
];
1947 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1948 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1949 SCM_BITVECTOR_BASE (v
) [k
] |= SCM_BITVECTOR_BASE (kv
) [k
];
1954 return SCM_UNSPECIFIED
;
1959 SCM_DEFINE (scm_bit_count_star
, "bit-count*", 3, 0, 0,
1960 (SCM v
, SCM kv
, SCM obj
),
1961 "Return a count of how many entries in bit vector @var{v} are\n"
1962 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
1965 "If @var{kv} is a bit vector, then those entries where it has\n"
1966 "@code{#t} are the ones in @var{v} which are considered.\n"
1967 "@var{kv} and @var{v} must be the same length.\n"
1969 "If @var{kv} is a uniform vector of unsigned long integers, then\n"
1970 "it's the indexes in @var{v} to consider.\n"
1975 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
1976 "(bit-count* #*01110111 #u(7 0 4) #f) @result{} 2\n"
1978 #define FUNC_NAME s_scm_bit_count_star
1980 register long i
, vlen
, count
= 0;
1981 register unsigned long k
;
1984 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1985 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1986 switch SCM_TYP7 (kv
)
1990 SCM_WRONG_TYPE_ARG (2, kv
);
1992 vlen
= SCM_BITVECTOR_LENGTH (v
);
1993 if (SCM_FALSEP (obj
))
1994 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1996 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1998 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1999 if (!SCM_BITVEC_REF(v
, k
))
2002 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
2003 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
2005 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
2007 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
2008 if (SCM_BITVEC_REF (v
, k
))
2012 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
2015 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
2016 if (0 == SCM_BITVECTOR_LENGTH (v
))
2018 SCM_ASRTGO (SCM_BOOLP (obj
), badarg3
);
2019 fObj
= SCM_EQ_P (obj
, SCM_BOOL_T
);
2020 i
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
;
2021 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK (SCM_VELTS (v
)[i
]) : ~ SCM_UNPACK (SCM_VELTS (v
)[i
]));
2022 k
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
);
2026 count
+= cnt_tab
[k
& 0x0f];
2028 return SCM_MAKINUM (count
);
2030 /* urg. repetitive (see above.) */
2031 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK(SCM_VELTS (v
)[i
]) : ~SCM_UNPACK (SCM_VELTS (v
)[i
]));
2034 return SCM_MAKINUM (count
);
2039 SCM_DEFINE (scm_bit_invert_x
, "bit-invert!", 1, 0, 0,
2041 "Modify the bit vector @var{v} by replacing each element with\n"
2043 #define FUNC_NAME s_scm_bit_invert_x
2047 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
2049 k
= SCM_BITVECTOR_LENGTH (v
);
2050 for (k
= (k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
2051 SCM_BITVECTOR_BASE (v
) [k
] = ~SCM_BITVECTOR_BASE (v
) [k
];
2053 return SCM_UNSPECIFIED
;
2059 scm_istr2bve (char *str
, long len
)
2061 SCM v
= scm_make_uve (len
, SCM_BOOL_T
);
2062 long *data
= (long *) SCM_VELTS (v
);
2063 register unsigned long mask
;
2066 for (k
= 0; k
< (len
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
++)
2069 j
= len
- k
* SCM_LONG_BIT
;
2070 if (j
> SCM_LONG_BIT
)
2072 for (mask
= 1L; j
--; mask
<<= 1)
2090 ra2l (SCM ra
, unsigned long base
, unsigned long k
)
2092 register SCM res
= SCM_EOL
;
2093 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2095 if (SCM_ARRAY_DIMS (ra
)[k
].ubnd
< SCM_ARRAY_DIMS (ra
)[k
].lbnd
)
2097 i
= base
+ (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
) * inc
;
2098 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2103 res
= scm_cons (ra2l (ra
, i
, k
+ 1), res
);
2111 res
= scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra
), SCM_MAKINUM (i
)), res
);
2118 SCM_DEFINE (scm_array_to_list
, "array->list", 1, 0, 0,
2120 "Return a list consisting of all the elements, in order, of\n"
2122 #define FUNC_NAME s_scm_array_to_list
2126 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
2130 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
2132 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
2133 return ra2l (v
, SCM_ARRAY_BASE (v
), 0);
2134 case scm_tc7_vector
:
2136 return scm_vector_to_list (v
);
2137 case scm_tc7_string
:
2138 return scm_string_to_list (v
);
2141 long *data
= (long *) SCM_VELTS (v
);
2142 register unsigned long mask
;
2143 for (k
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; k
> 0; k
--)
2144 for (mask
= 1UL << (SCM_LONG_BIT
- 1); mask
; mask
>>= 1)
2145 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2146 for (mask
= 1L << ((SCM_BITVECTOR_LENGTH (v
) % SCM_LONG_BIT
) - 1); mask
; mask
>>= 1)
2147 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2150 case scm_tc7_byvect
:
2152 signed char *data
= (signed char *) SCM_VELTS (v
);
2153 unsigned long k
= SCM_UVECTOR_LENGTH (v
);
2155 res
= scm_cons (SCM_MAKINUM (data
[--k
]), res
);
2160 long *data
= (long *)SCM_VELTS(v
);
2161 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2162 res
= scm_cons(scm_ulong2num(data
[k
]), res
);
2167 long *data
= (long *)SCM_VELTS(v
);
2168 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2169 res
= scm_cons(scm_long2num(data
[k
]), res
);
2174 short *data
= (short *)SCM_VELTS(v
);
2175 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2176 res
= scm_cons(scm_short2num (data
[k
]), res
);
2179 #if SCM_SIZEOF_LONG_LONG != 0
2180 case scm_tc7_llvect
:
2182 long long *data
= (long long *)SCM_VELTS(v
);
2183 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2184 res
= scm_cons(scm_long_long2num(data
[k
]), res
);
2190 float *data
= (float *) SCM_VELTS (v
);
2191 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2192 res
= scm_cons (scm_make_real (data
[k
]), res
);
2197 double *data
= (double *) SCM_VELTS (v
);
2198 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2199 res
= scm_cons (scm_make_real (data
[k
]), res
);
2204 double (*data
)[2] = (double (*)[2]) SCM_VELTS (v
);
2205 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2206 res
= scm_cons (scm_make_complex (data
[k
][0], data
[k
][1]), res
);
2214 static int l2ra(SCM lst
, SCM ra
, unsigned long base
, unsigned long k
);
2216 SCM_DEFINE (scm_list_to_uniform_array
, "list->uniform-array", 3, 0, 0,
2217 (SCM ndim
, SCM prot
, SCM lst
),
2218 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
2219 "Return a uniform array of the type indicated by prototype\n"
2220 "@var{prot} with elements the same as those of @var{lst}.\n"
2221 "Elements must be of the appropriate type, no coercions are\n"
2223 #define FUNC_NAME s_scm_list_to_uniform_array
2230 SCM_VALIDATE_INUM_COPY (1, ndim
, k
);
2233 n
= scm_ilength (row
);
2234 SCM_ASSERT (n
>= 0, lst
, SCM_ARG3
, FUNC_NAME
);
2235 shp
= scm_cons (SCM_MAKINUM (n
), shp
);
2237 row
= SCM_CAR (row
);
2239 ra
= scm_dimensions_to_uniform_array (scm_reverse (shp
), prot
,
2241 if (SCM_NULLP (shp
))
2243 SCM_ASRTGO (1 == scm_ilength (lst
), badlst
);
2244 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_EOL
);
2247 if (!SCM_ARRAYP (ra
))
2249 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (ra
));
2250 for (k
= 0; k
< length
; k
++, lst
= SCM_CDR (lst
))
2251 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_MAKINUM (k
));
2254 if (l2ra (lst
, ra
, SCM_ARRAY_BASE (ra
), 0))
2257 badlst
:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2263 l2ra (SCM lst
, SCM ra
, unsigned long base
, unsigned long k
)
2265 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2266 register long n
= (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
);
2269 return (SCM_NULLP (lst
));
2270 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2274 if (!SCM_CONSP (lst
))
2276 ok
= ok
&& l2ra (SCM_CAR (lst
), ra
, base
, k
+ 1);
2278 lst
= SCM_CDR (lst
);
2280 if (!SCM_NULLP (lst
))
2287 if (!SCM_CONSP (lst
))
2289 scm_array_set_x (SCM_ARRAY_V (ra
), SCM_CAR (lst
), SCM_MAKINUM (base
));
2291 lst
= SCM_CDR (lst
);
2293 if (!SCM_NULLP (lst
))
2301 rapr1 (SCM ra
, unsigned long j
, unsigned long k
, SCM port
, scm_print_state
*pstate
)
2304 long n
= (SCM_TYP7 (ra
) == scm_tc7_smob
2306 : SCM_INUM (scm_uniform_vector_length (ra
)));
2309 switch SCM_TYP7 (ra
)
2314 SCM_ARRAY_BASE (ra
) = j
;
2316 scm_iprin1 (ra
, port
, pstate
);
2317 for (j
+= inc
; n
-- > 0; j
+= inc
)
2319 scm_putc (' ', port
);
2320 SCM_ARRAY_BASE (ra
) = j
;
2321 scm_iprin1 (ra
, port
, pstate
);
2325 if (k
+ 1 < SCM_ARRAY_NDIM (ra
))
2328 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2329 for (i
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
; i
< SCM_ARRAY_DIMS (ra
)[k
].ubnd
; i
++)
2331 scm_putc ('(', port
);
2332 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2333 scm_puts (") ", port
);
2336 if (i
== SCM_ARRAY_DIMS (ra
)[k
].ubnd
)
2337 { /* could be zero size. */
2338 scm_putc ('(', port
);
2339 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2340 scm_putc (')', port
);
2344 if (SCM_ARRAY_NDIM (ra
) > 0)
2345 { /* Could be zero-dimensional */
2346 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2347 n
= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
2351 ra
= SCM_ARRAY_V (ra
);
2354 /* scm_tc7_bvect and scm_tc7_llvect only? */
2356 scm_iprin1 (scm_uniform_vector_ref (ra
, SCM_MAKINUM (j
)), port
, pstate
);
2357 for (j
+= inc
; n
-- > 0; j
+= inc
)
2359 scm_putc (' ', port
);
2360 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2363 case scm_tc7_string
:
2365 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2366 if (SCM_WRITINGP (pstate
))
2367 for (j
+= inc
; n
-- > 0; j
+= inc
)
2369 scm_putc (' ', port
);
2370 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2373 for (j
+= inc
; n
-- > 0; j
+= inc
)
2374 scm_putc (SCM_STRING_CHARS (ra
)[j
], port
);
2376 case scm_tc7_byvect
:
2378 scm_intprint (((char *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2379 for (j
+= inc
; n
-- > 0; j
+= inc
)
2381 scm_putc (' ', port
);
2382 scm_intprint (((char *)SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2392 /* intprint can't handle >= 2^31. */
2393 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2394 scm_puts (str
, port
);
2396 for (j
+= inc
; n
-- > 0; j
+= inc
)
2398 scm_putc (' ', port
);
2399 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2400 scm_puts (str
, port
);
2405 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2406 for (j
+= inc
; n
-- > 0; j
+= inc
)
2408 scm_putc (' ', port
);
2409 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2415 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2416 for (j
+= inc
; n
-- > 0; j
+= inc
)
2418 scm_putc (' ', port
);
2419 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2426 SCM z
= scm_make_real (1.0);
2427 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2428 scm_print_real (z
, port
, pstate
);
2429 for (j
+= inc
; n
-- > 0; j
+= inc
)
2431 scm_putc (' ', port
);
2432 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2433 scm_print_real (z
, port
, pstate
);
2440 SCM z
= scm_make_real (1.0 / 3.0);
2441 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2442 scm_print_real (z
, port
, pstate
);
2443 for (j
+= inc
; n
-- > 0; j
+= inc
)
2445 scm_putc (' ', port
);
2446 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2447 scm_print_real (z
, port
, pstate
);
2454 SCM cz
= scm_make_complex (0.0, 1.0), z
= scm_make_real (1.0 / 3.0);
2455 SCM_REAL_VALUE (z
) =
2456 SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2457 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2458 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2460 for (j
+= inc
; n
-- > 0; j
+= inc
)
2462 scm_putc (' ', port
);
2464 = SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2465 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2466 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2477 scm_raprin1 (SCM exp
, SCM port
, scm_print_state
*pstate
)
2480 unsigned long base
= 0;
2481 scm_putc ('#', port
);
2487 long ndim
= SCM_ARRAY_NDIM (v
);
2488 base
= SCM_ARRAY_BASE (v
);
2489 v
= SCM_ARRAY_V (v
);
2493 scm_puts ("<enclosed-array ", port
);
2494 rapr1 (exp
, base
, 0, port
, pstate
);
2495 scm_putc ('>', port
);
2500 scm_intprint (ndim
, 10, port
);
2505 if (SCM_EQ_P (exp
, v
))
2506 { /* a uve, not an scm_array */
2507 register long i
, j
, w
;
2508 scm_putc ('*', port
);
2509 for (i
= 0; i
< (SCM_BITVECTOR_LENGTH (exp
)) / SCM_LONG_BIT
; i
++)
2511 scm_t_bits w
= SCM_UNPACK (SCM_VELTS (exp
)[i
]);
2512 for (j
= SCM_LONG_BIT
; j
; j
--)
2514 scm_putc (w
& 1 ? '1' : '0', port
);
2518 j
= SCM_BITVECTOR_LENGTH (exp
) % SCM_LONG_BIT
;
2521 w
= SCM_UNPACK (SCM_VELTS (exp
)[SCM_BITVECTOR_LENGTH (exp
) / SCM_LONG_BIT
]);
2524 scm_putc (w
& 1 ? '1' : '0', port
);
2531 scm_putc ('b', port
);
2533 case scm_tc7_string
:
2534 scm_putc ('a', port
);
2536 case scm_tc7_byvect
:
2537 scm_putc ('y', port
);
2540 scm_putc ('u', port
);
2543 scm_putc ('e', port
);
2546 scm_putc ('h', port
);
2548 #if SCM_SIZEOF_LONG_LONG != 0
2549 case scm_tc7_llvect
:
2550 scm_putc ('l', port
);
2554 scm_putc ('s', port
);
2557 scm_putc ('i', port
);
2560 scm_putc ('c', port
);
2563 scm_putc ('(', port
);
2564 rapr1 (exp
, base
, 0, port
, pstate
);
2565 scm_putc (')', port
);
2569 SCM_DEFINE (scm_array_prototype
, "array-prototype", 1, 0, 0,
2571 "Return an object that would produce an array of the same type\n"
2572 "as @var{array}, if used as the @var{prototype} for\n"
2573 "@code{make-uniform-array}.")
2574 #define FUNC_NAME s_scm_array_prototype
2577 SCM_ASRTGO (SCM_NIMP (ra
), badarg
);
2579 switch SCM_TYP7 (ra
)
2582 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
2584 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
2586 return SCM_UNSPECIFIED
;
2587 ra
= SCM_ARRAY_V (ra
);
2589 case scm_tc7_vector
:
2594 case scm_tc7_string
:
2595 return SCM_MAKE_CHAR ('a');
2596 case scm_tc7_byvect
:
2597 return SCM_MAKE_CHAR ('\0');
2599 return SCM_MAKINUM (1L);
2601 return SCM_MAKINUM (-1L);
2603 return scm_str2symbol ("s");
2604 #if SCM_SIZEOF_LONG_LONG != 0
2605 case scm_tc7_llvect
:
2606 return scm_str2symbol ("l");
2609 return scm_make_real (1.0);
2611 return exactly_one_third
;
2613 return scm_make_complex (0.0, 1.0);
2620 array_mark (SCM ptr
)
2622 return SCM_ARRAY_V (ptr
);
2627 array_free (SCM ptr
)
2629 scm_gc_free (SCM_ARRAY_MEM (ptr
),
2630 (sizeof (scm_t_array
)
2631 + SCM_ARRAY_NDIM (ptr
) * sizeof (scm_t_array_dim
)),
2639 scm_tc16_array
= scm_make_smob_type ("array", 0);
2640 scm_set_smob_mark (scm_tc16_array
, array_mark
);
2641 scm_set_smob_free (scm_tc16_array
, array_free
);
2642 scm_set_smob_print (scm_tc16_array
, scm_raprin1
);
2643 scm_set_smob_equalp (scm_tc16_array
, scm_array_equal_p
);
2644 exactly_one_third
= scm_permanent_object (scm_make_ratio (SCM_MAKINUM (1),
2646 scm_add_feature ("array");
2647 #include "libguile/unif.x"