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"
82 /* The set of uniform scm_vector types is:
84 * unsigned char string
91 * complex double cvect
96 scm_t_bits scm_tc16_array
;
98 /* return the size of an element in a uniform array or 0 if type not
101 scm_uniform_element_size (SCM obj
)
105 switch (SCM_TYP7 (obj
))
110 result
= sizeof (long);
114 result
= sizeof (char);
118 result
= sizeof (short);
121 #ifdef HAVE_LONG_LONGS
123 result
= sizeof (long long);
128 result
= sizeof (float);
132 result
= sizeof (double);
136 result
= 2 * sizeof (double);
145 /* Silly function used not to modify the semantics of the silly
146 * prototype system in order to be backward compatible.
151 if (!SCM_SLOPPY_REALP (obj
))
155 double x
= SCM_REAL_VALUE (obj
);
157 return (- SCM_FLTMAX
< x
) && (x
< SCM_FLTMAX
) && (fx
== x
);
162 scm_make_uve (long k
, SCM prot
)
163 #define FUNC_NAME "scm_make_uve"
168 if (SCM_EQ_P (prot
, SCM_BOOL_T
))
173 SCM_ASSERT_RANGE (1, scm_long2num (k
), k
<= SCM_BITVECTOR_MAX_LENGTH
);
174 i
= sizeof (long) * ((k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
);
175 SCM_SET_BITVECTOR_BASE (v
, (char *) scm_must_malloc (i
, "vector"));
176 SCM_SET_BITVECTOR_LENGTH (v
, k
);
180 SCM_SET_BITVECTOR_BASE (v
, 0);
181 SCM_SET_BITVECTOR_LENGTH (v
, 0);
185 else if (SCM_CHARP (prot
) && (SCM_CHAR (prot
) == '\0'))
187 i
= sizeof (char) * k
;
188 type
= scm_tc7_byvect
;
190 else if (SCM_CHARP (prot
))
192 i
= sizeof (char) * k
;
193 return scm_allocate_string (i
);
195 else if (SCM_INUMP (prot
))
197 i
= sizeof (long) * k
;
198 if (SCM_INUM (prot
) > 0)
199 type
= scm_tc7_uvect
;
201 type
= scm_tc7_ivect
;
203 else if (SCM_SYMBOLP (prot
) && (1 == SCM_SYMBOL_LENGTH (prot
)))
207 s
= SCM_SYMBOL_CHARS (prot
)[0];
210 i
= sizeof (short) * k
;
211 type
= scm_tc7_svect
;
213 #ifdef HAVE_LONG_LONGS
216 i
= sizeof (long long) * k
;
217 type
= scm_tc7_llvect
;
222 return scm_c_make_vector (k
, SCM_UNDEFINED
);
225 else if (!SCM_INEXACTP (prot
))
226 /* Huge non-unif vectors are NOT supported. */
227 /* no special scm_vector */
228 return scm_c_make_vector (k
, SCM_UNDEFINED
);
229 else if (singp (prot
))
231 i
= sizeof (float) * k
;
232 type
= scm_tc7_fvect
;
234 else if (SCM_COMPLEXP (prot
))
236 i
= 2 * sizeof (double) * k
;
237 type
= scm_tc7_cvect
;
241 i
= sizeof (double) * k
;
242 type
= scm_tc7_dvect
;
245 SCM_ASSERT_RANGE (1, scm_long2num (k
), k
<= SCM_UVECTOR_MAX_LENGTH
);
249 SCM_SET_UVECTOR_BASE (v
, (char *) scm_must_malloc (i
? i
: 1, "vector"));
250 SCM_SET_UVECTOR_LENGTH (v
, k
, type
);
257 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
259 "Return the number of elements in @var{uve}.")
260 #define FUNC_NAME s_scm_uniform_vector_length
262 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
266 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
269 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v
));
271 return SCM_MAKINUM (SCM_STRING_LENGTH (v
));
273 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v
));
281 #ifdef HAVE_LONG_LONGS
284 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v
));
289 SCM_DEFINE (scm_array_p
, "array?", 1, 1, 0,
291 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
292 "not. The @var{prototype} argument is used with uniform arrays\n"
293 "and is described elsewhere.")
294 #define FUNC_NAME s_scm_array_p
298 nprot
= SCM_UNBNDP (prot
);
303 while (SCM_TYP7 (v
) == scm_tc7_smob
)
314 return SCM_BOOL(nprot
);
319 switch (SCM_TYP7 (v
))
322 protp
= (SCM_EQ_P (prot
, SCM_BOOL_T
));
324 protp
= SCM_CHARP(prot
) && (SCM_CHAR (prot
) != '\0');
326 protp
= SCM_EQ_P (prot
, SCM_MAKE_CHAR ('\0'));
328 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)>0;
330 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)<=0;
333 protp
= SCM_SYMBOLP (prot
)
334 && (1 == SCM_SYMBOL_LENGTH (prot
))
335 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
336 #ifdef HAVE_LONG_LONGS
338 protp
= SCM_SYMBOLP (prot
)
339 && (1 == SCM_SYMBOL_LENGTH (prot
))
340 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
343 protp
= singp (prot
);
345 protp
= SCM_REALP(prot
);
347 protp
= SCM_COMPLEXP(prot
);
350 protp
= SCM_NULLP(prot
);
355 return SCM_BOOL(protp
);
361 SCM_DEFINE (scm_array_rank
, "array-rank", 1, 0, 0,
363 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
364 "not an array, @code{0} is returned.")
365 #define FUNC_NAME s_scm_array_rank
369 switch (SCM_TYP7 (ra
))
382 #ifdef HAVE_LONG_LONGS
386 return SCM_MAKINUM (1L);
389 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra
));
396 SCM_DEFINE (scm_array_dimensions
, "array-dimensions", 1, 0, 0,
398 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
399 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
401 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
403 #define FUNC_NAME s_scm_array_dimensions
410 switch (SCM_TYP7 (ra
))
425 #ifdef HAVE_LONG_LONGS
428 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
430 if (!SCM_ARRAYP (ra
))
432 k
= SCM_ARRAY_NDIM (ra
);
433 s
= SCM_ARRAY_DIMS (ra
);
435 res
= scm_cons (s
[k
].lbnd
436 ? scm_cons2 (SCM_MAKINUM (s
[k
].lbnd
),
437 SCM_MAKINUM (s
[k
].ubnd
),
439 : SCM_MAKINUM (1 + s
[k
].ubnd
),
447 SCM_DEFINE (scm_shared_array_root
, "shared-array-root", 1, 0, 0,
449 "Return the root vector of a shared array.")
450 #define FUNC_NAME s_scm_shared_array_root
452 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
453 return SCM_ARRAY_V (ra
);
458 SCM_DEFINE (scm_shared_array_offset
, "shared-array-offset", 1, 0, 0,
460 "Return the root vector index of the first element in the array.")
461 #define FUNC_NAME s_scm_shared_array_offset
463 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
464 return SCM_MAKINUM (SCM_ARRAY_BASE (ra
));
469 SCM_DEFINE (scm_shared_array_increments
, "shared-array-increments", 1, 0, 0,
471 "For each dimension, return the distance between elements in the root vector.")
472 #define FUNC_NAME s_scm_shared_array_increments
477 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
478 k
= SCM_ARRAY_NDIM (ra
);
479 s
= SCM_ARRAY_DIMS (ra
);
481 res
= scm_cons (SCM_MAKINUM (s
[k
].inc
), res
);
487 static char s_bad_ind
[] = "Bad scm_array index";
491 scm_aind (SCM ra
, SCM args
, const char *what
)
492 #define FUNC_NAME what
496 register unsigned long pos
= SCM_ARRAY_BASE (ra
);
497 register unsigned long k
= SCM_ARRAY_NDIM (ra
);
498 scm_t_array_dim
*s
= SCM_ARRAY_DIMS (ra
);
499 if (SCM_INUMP (args
))
502 scm_error_num_args_subr (what
);
503 return pos
+ (SCM_INUM (args
) - s
->lbnd
) * (s
->inc
);
505 while (k
&& !SCM_NULLP (args
))
507 ind
= SCM_CAR (args
);
508 args
= SCM_CDR (args
);
509 if (!SCM_INUMP (ind
))
510 scm_misc_error (what
, s_bad_ind
, SCM_EOL
);
512 if (j
< s
->lbnd
|| j
> s
->ubnd
)
513 scm_out_of_range (what
, ind
);
514 pos
+= (j
- s
->lbnd
) * (s
->inc
);
518 if (k
!= 0 || !SCM_NULLP (args
))
519 scm_error_num_args_subr (what
);
527 scm_make_ra (int ndim
)
532 SCM_NEWSMOB(ra
, ((scm_t_bits
) ndim
<< 17) + scm_tc16_array
,
533 scm_must_malloc ((sizeof (scm_t_array
) +
534 ndim
* sizeof (scm_t_array_dim
)),
536 SCM_ARRAY_V (ra
) = scm_nullvect
;
541 static char s_bad_spec
[] = "Bad scm_array dimension";
542 /* Increments will still need to be set. */
546 scm_shap2ra (SCM args
, const char *what
)
550 int ndim
= scm_ilength (args
);
552 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
554 ra
= scm_make_ra (ndim
);
555 SCM_ARRAY_BASE (ra
) = 0;
556 s
= SCM_ARRAY_DIMS (ra
);
557 for (; !SCM_NULLP (args
); s
++, args
= SCM_CDR (args
))
559 spec
= SCM_CAR (args
);
560 if (SCM_INUMP (spec
))
562 if (SCM_INUM (spec
) < 0)
563 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
565 s
->ubnd
= SCM_INUM (spec
) - 1;
570 if (!SCM_CONSP (spec
) || !SCM_INUMP (SCM_CAR (spec
)))
571 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
572 s
->lbnd
= SCM_INUM (SCM_CAR (spec
));
575 || !SCM_INUMP (SCM_CAR (sp
))
576 || !SCM_NULLP (SCM_CDR (sp
)))
577 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
578 s
->ubnd
= SCM_INUM (SCM_CAR (sp
));
585 SCM_DEFINE (scm_dimensions_to_uniform_array
, "dimensions->uniform-array", 2, 1, 0,
586 (SCM dims
, SCM prot
, SCM fill
),
587 "@deffnx primitive make-uniform-vector length prototype [fill]\n"
588 "Create and return a uniform array or vector of type\n"
589 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
590 "length @var{length}. If @var{fill} is supplied, it's used to\n"
591 "fill the array, otherwise @var{prototype} is used.")
592 #define FUNC_NAME s_scm_dimensions_to_uniform_array
595 unsigned long rlen
= 1;
599 if (SCM_INUMP (dims
))
601 SCM answer
= scm_make_uve (SCM_INUM (dims
), prot
);
602 if (!SCM_UNBNDP (fill
))
603 scm_array_fill_x (answer
, fill
);
604 else if (SCM_SYMBOLP (prot
))
605 scm_array_fill_x (answer
, SCM_MAKINUM (0));
607 scm_array_fill_x (answer
, prot
);
611 SCM_ASSERT (SCM_NULLP (dims
) || SCM_CONSP (dims
),
612 dims
, SCM_ARG1
, FUNC_NAME
);
613 ra
= scm_shap2ra (dims
, FUNC_NAME
);
614 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
615 s
= SCM_ARRAY_DIMS (ra
);
616 k
= SCM_ARRAY_NDIM (ra
);
621 SCM_ASSERT_RANGE (1, dims
, s
[k
].lbnd
<= s
[k
].ubnd
);
622 rlen
= (s
[k
].ubnd
- s
[k
].lbnd
+ 1) * s
[k
].inc
;
625 SCM_ARRAY_V (ra
) = scm_make_uve (rlen
, prot
);
627 if (!SCM_UNBNDP (fill
))
628 scm_array_fill_x (ra
, fill
);
629 else if (SCM_SYMBOLP (prot
))
630 scm_array_fill_x (ra
, SCM_MAKINUM (0));
632 scm_array_fill_x (ra
, prot
);
634 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
635 if (s
->ubnd
< s
->lbnd
|| (0 == s
->lbnd
&& 1 == s
->inc
))
636 return SCM_ARRAY_V (ra
);
643 scm_ra_set_contp (SCM ra
)
645 size_t k
= SCM_ARRAY_NDIM (ra
);
648 long inc
= SCM_ARRAY_DIMS (ra
)[k
- 1].inc
;
651 if (inc
!= SCM_ARRAY_DIMS (ra
)[k
].inc
)
653 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra
);
656 inc
*= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
657 - SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
660 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
664 SCM_DEFINE (scm_make_shared_array
, "make-shared-array", 2, 0, 1,
665 (SCM oldra
, SCM mapfunc
, SCM dims
),
666 "@code{make-shared-array} can be used to create shared subarrays of other\n"
667 "arrays. The @var{mapper} is a function that translates coordinates in\n"
668 "the new array into coordinates in the old array. A @var{mapper} must be\n"
669 "linear, and its range must stay within the bounds of the old array, but\n"
670 "it can be otherwise arbitrary. A simple example:\n"
672 "(define fred (make-array #f 8 8))\n"
673 "(define freds-diagonal\n"
674 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
675 "(array-set! freds-diagonal 'foo 3)\n"
676 "(array-ref fred 3 3) @result{} foo\n"
677 "(define freds-center\n"
678 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
679 "(array-ref freds-center 0 0) @result{} foo\n"
681 #define FUNC_NAME s_scm_make_shared_array
687 long old_min
, new_min
, old_max
, new_max
;
690 SCM_VALIDATE_REST_ARGUMENT (dims
);
691 SCM_VALIDATE_ARRAY (1,oldra
);
692 SCM_VALIDATE_PROC (2,mapfunc
);
693 ra
= scm_shap2ra (dims
, FUNC_NAME
);
694 if (SCM_ARRAYP (oldra
))
696 SCM_ARRAY_V (ra
) = SCM_ARRAY_V (oldra
);
697 old_min
= old_max
= SCM_ARRAY_BASE (oldra
);
698 s
= SCM_ARRAY_DIMS (oldra
);
699 k
= SCM_ARRAY_NDIM (oldra
);
703 old_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
705 old_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
710 SCM_ARRAY_V (ra
) = oldra
;
712 old_max
= SCM_INUM (scm_uniform_vector_length (oldra
)) - 1;
715 s
= SCM_ARRAY_DIMS (ra
);
716 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
718 inds
= scm_cons (SCM_MAKINUM (s
[k
].lbnd
), inds
);
719 if (s
[k
].ubnd
< s
[k
].lbnd
)
721 if (1 == SCM_ARRAY_NDIM (ra
))
722 ra
= scm_make_uve (0L, scm_array_prototype (ra
));
724 SCM_ARRAY_V (ra
) = scm_make_uve (0L, scm_array_prototype (ra
));
728 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
729 if (SCM_ARRAYP (oldra
))
730 i
= (size_t) scm_aind (oldra
, imap
, FUNC_NAME
);
733 if (SCM_NINUMP (imap
))
736 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
737 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
738 imap
= SCM_CAR (imap
);
742 SCM_ARRAY_BASE (ra
) = new_min
= new_max
= i
;
744 k
= SCM_ARRAY_NDIM (ra
);
747 if (s
[k
].ubnd
> s
[k
].lbnd
)
749 SCM_SETCAR (indptr
, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr
)) + 1));
750 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
751 if (SCM_ARRAYP (oldra
))
753 s
[k
].inc
= scm_aind (oldra
, imap
, FUNC_NAME
) - i
;
756 if (SCM_NINUMP (imap
))
758 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
759 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
760 imap
= SCM_CAR (imap
);
762 s
[k
].inc
= (long) SCM_INUM (imap
) - i
;
766 new_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
768 new_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
771 s
[k
].inc
= new_max
- new_min
+ 1; /* contiguous by default */
772 indptr
= SCM_CDR (indptr
);
774 if (old_min
> new_min
|| old_max
< new_max
)
775 SCM_MISC_ERROR ("mapping out of range", SCM_EOL
);
776 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
778 SCM v
= SCM_ARRAY_V (ra
);
779 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
780 if (1 == s
->inc
&& 0 == s
->lbnd
&& length
== 1 + s
->ubnd
)
782 if (s
->ubnd
< s
->lbnd
)
783 return scm_make_uve (0L, scm_array_prototype (ra
));
785 scm_ra_set_contp (ra
);
791 /* args are RA . DIMS */
792 SCM_DEFINE (scm_transpose_array
, "transpose-array", 1, 0, 1,
794 "Return an array sharing contents with @var{array}, but with\n"
795 "dimensions arranged in a different order. There must be one\n"
796 "@var{dim} argument for each dimension of @var{array}.\n"
797 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
798 "and the rank of the array to be returned. Each integer in that\n"
799 "range must appear at least once in the argument list.\n"
801 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
802 "dimensions in the array to be returned, their positions in the\n"
803 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
804 "may have the same value, in which case the returned array will\n"
805 "have smaller rank than @var{array}.\n"
808 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
809 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
810 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
811 " #2((a 4) (b 5) (c 6))\n"
813 #define FUNC_NAME s_scm_transpose_array
815 SCM res
, vargs
, *ve
= &vargs
;
816 scm_t_array_dim
*s
, *r
;
819 SCM_VALIDATE_REST_ARGUMENT (args
);
820 SCM_ASSERT (SCM_NIMP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
821 switch (SCM_TYP7 (ra
))
824 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
834 #ifdef HAVE_LONG_LONGS
837 if (SCM_NULLP (args
) || !SCM_NULLP (SCM_CDR (args
)))
838 SCM_WRONG_NUM_ARGS ();
839 SCM_VALIDATE_INUM (SCM_ARG2
, SCM_CAR (args
));
840 SCM_ASSERT_RANGE (SCM_ARG2
, SCM_CAR (args
),
841 SCM_EQ_P (SCM_INUM0
, SCM_CAR (args
)));
844 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
845 vargs
= scm_vector (args
);
846 if (SCM_VECTOR_LENGTH (vargs
) != SCM_ARRAY_NDIM (ra
))
847 SCM_WRONG_NUM_ARGS ();
848 ve
= SCM_VELTS (vargs
);
850 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
852 SCM_ASSERT (SCM_INUMP (ve
[k
]), ve
[k
], (SCM_ARG2
+ k
),
854 i
= SCM_INUM (ve
[k
]);
855 if (i
< 0 || i
>= SCM_ARRAY_NDIM (ra
))
856 scm_out_of_range (FUNC_NAME
, ve
[k
]);
861 res
= scm_make_ra (ndim
);
862 SCM_ARRAY_V (res
) = SCM_ARRAY_V (ra
);
863 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra
);
866 SCM_ARRAY_DIMS (res
)[k
].lbnd
= 0;
867 SCM_ARRAY_DIMS (res
)[k
].ubnd
= -1;
869 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
871 i
= SCM_INUM (ve
[k
]);
872 s
= &(SCM_ARRAY_DIMS (ra
)[k
]);
873 r
= &(SCM_ARRAY_DIMS (res
)[i
]);
874 if (r
->ubnd
< r
->lbnd
)
883 if (r
->ubnd
> s
->ubnd
)
885 if (r
->lbnd
< s
->lbnd
)
887 SCM_ARRAY_BASE (res
) += (s
->lbnd
- r
->lbnd
) * r
->inc
;
894 SCM_MISC_ERROR ("bad argument list", SCM_EOL
);
895 scm_ra_set_contp (res
);
901 /* args are RA . AXES */
902 SCM_DEFINE (scm_enclose_array
, "enclose-array", 1, 0, 1,
904 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
905 "the rank of @var{array}. @var{enclose-array} returns an array\n"
906 "resembling an array of shared arrays. The dimensions of each shared\n"
907 "array are the same as the @var{dim}th dimensions of the original array,\n"
908 "the dimensions of the outer array are the same as those of the original\n"
909 "array that did not match a @var{dim}.\n\n"
910 "An enclosed array is not a general Scheme array. Its elements may not\n"
911 "be set using @code{array-set!}. Two references to the same element of\n"
912 "an enclosed array will be @code{equal?} but will not in general be\n"
913 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
914 "enclosed array is unspecified.\n\n"
917 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
918 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
919 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
920 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
922 #define FUNC_NAME s_scm_enclose_array
924 SCM axv
, res
, ra_inr
;
925 scm_t_array_dim vdim
, *s
= &vdim
;
926 int ndim
, j
, k
, ninr
, noutr
;
928 SCM_VALIDATE_REST_ARGUMENT (axes
);
929 if (SCM_NULLP (axes
))
930 axes
= scm_cons ((SCM_ARRAYP (ra
) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra
) - 1) : SCM_INUM0
), SCM_EOL
);
931 ninr
= scm_ilength (axes
);
933 SCM_WRONG_NUM_ARGS ();
934 ra_inr
= scm_make_ra (ninr
);
935 SCM_ASRTGO (SCM_NIMP (ra
), badarg1
);
939 badarg1
:SCM_WRONG_TYPE_ARG (1, ra
);
951 #ifdef HAVE_LONG_LONGS
955 s
->ubnd
= SCM_INUM (scm_uniform_vector_length (ra
)) - 1;
957 SCM_ARRAY_V (ra_inr
) = ra
;
958 SCM_ARRAY_BASE (ra_inr
) = 0;
962 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg1
);
963 s
= SCM_ARRAY_DIMS (ra
);
964 SCM_ARRAY_V (ra_inr
) = SCM_ARRAY_V (ra
);
965 SCM_ARRAY_BASE (ra_inr
) = SCM_ARRAY_BASE (ra
);
966 ndim
= SCM_ARRAY_NDIM (ra
);
971 SCM_WRONG_NUM_ARGS ();
972 axv
= scm_make_string (SCM_MAKINUM (ndim
), SCM_MAKE_CHAR (0));
973 res
= scm_make_ra (noutr
);
974 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra_inr
);
975 SCM_ARRAY_V (res
) = ra_inr
;
976 for (k
= 0; k
< ninr
; k
++, axes
= SCM_CDR (axes
))
978 if (!SCM_INUMP (SCM_CAR (axes
)))
979 SCM_MISC_ERROR ("bad axis", SCM_EOL
);
980 j
= SCM_INUM (SCM_CAR (axes
));
981 SCM_ARRAY_DIMS (ra_inr
)[k
].lbnd
= s
[j
].lbnd
;
982 SCM_ARRAY_DIMS (ra_inr
)[k
].ubnd
= s
[j
].ubnd
;
983 SCM_ARRAY_DIMS (ra_inr
)[k
].inc
= s
[j
].inc
;
984 SCM_STRING_CHARS (axv
)[j
] = 1;
986 for (j
= 0, k
= 0; k
< noutr
; k
++, j
++)
988 while (SCM_STRING_CHARS (axv
)[j
])
990 SCM_ARRAY_DIMS (res
)[k
].lbnd
= s
[j
].lbnd
;
991 SCM_ARRAY_DIMS (res
)[k
].ubnd
= s
[j
].ubnd
;
992 SCM_ARRAY_DIMS (res
)[k
].inc
= s
[j
].inc
;
994 scm_ra_set_contp (ra_inr
);
995 scm_ra_set_contp (res
);
1002 SCM_DEFINE (scm_array_in_bounds_p
, "array-in-bounds?", 1, 0, 1,
1004 "Return @code{#t} if its arguments would be acceptable to\n"
1005 "@code{array-ref}.")
1006 #define FUNC_NAME s_scm_array_in_bounds_p
1014 SCM_VALIDATE_REST_ARGUMENT (args
);
1015 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1016 if (SCM_NIMP (args
))
1019 ind
= SCM_CAR (args
);
1020 args
= SCM_CDR (args
);
1021 SCM_ASSERT (SCM_INUMP (ind
), ind
, SCM_ARG2
, FUNC_NAME
);
1022 pos
= SCM_INUM (ind
);
1028 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1029 wna
: SCM_WRONG_NUM_ARGS ();
1031 k
= SCM_ARRAY_NDIM (v
);
1032 s
= SCM_ARRAY_DIMS (v
);
1033 pos
= SCM_ARRAY_BASE (v
);
1036 SCM_ASRTGO (SCM_NULLP (ind
), wna
);
1043 if (!(j
>= (s
->lbnd
) && j
<= (s
->ubnd
)))
1045 SCM_ASRTGO (--k
== scm_ilength (args
), wna
);
1048 pos
+= (j
- s
->lbnd
) * (s
->inc
);
1049 if (!(--k
&& SCM_NIMP (args
)))
1051 ind
= SCM_CAR (args
);
1052 args
= SCM_CDR (args
);
1054 if (!SCM_INUMP (ind
))
1055 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
1057 SCM_ASRTGO (0 == k
, wna
);
1058 v
= SCM_ARRAY_V (v
);
1061 case scm_tc7_string
:
1062 case scm_tc7_byvect
:
1069 #ifdef HAVE_LONG_LONGS
1070 case scm_tc7_llvect
:
1072 case scm_tc7_vector
:
1075 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
1076 SCM_ASRTGO (SCM_NULLP (args
) && SCM_INUMP (ind
), wna
);
1077 return SCM_BOOL(pos
>= 0 && pos
< length
);
1084 SCM_REGISTER_PROC(s_array_ref
, "array-ref", 1, 0, 1, scm_uniform_vector_ref
);
1087 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
1089 "@deffnx primitive array-ref v . args\n"
1090 "Return the element at the @code{(index1, index2)} element in\n"
1092 #define FUNC_NAME s_scm_uniform_vector_ref
1098 SCM_ASRTGO (SCM_NULLP (args
), badarg
);
1101 else if (SCM_ARRAYP (v
))
1103 pos
= scm_aind (v
, args
, FUNC_NAME
);
1104 v
= SCM_ARRAY_V (v
);
1108 unsigned long int length
;
1109 if (SCM_NIMP (args
))
1111 SCM_ASSERT (SCM_CONSP (args
) && SCM_INUMP (SCM_CAR (args
)), args
, SCM_ARG2
, FUNC_NAME
);
1112 pos
= SCM_INUM (SCM_CAR (args
));
1113 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args
)), wna
);
1117 SCM_VALIDATE_INUM (2,args
);
1118 pos
= SCM_INUM (args
);
1120 length
= SCM_INUM (scm_uniform_vector_length (v
));
1121 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1126 if (SCM_NULLP (args
))
1129 SCM_WRONG_TYPE_ARG (1, v
);
1133 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1135 SCM_WRONG_NUM_ARGS ();
1138 int k
= SCM_ARRAY_NDIM (v
);
1139 SCM res
= scm_make_ra (k
);
1140 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1141 SCM_ARRAY_BASE (res
) = pos
;
1144 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1145 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1146 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1151 if (SCM_BITVEC_REF (v
, pos
))
1155 case scm_tc7_string
:
1156 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1157 case scm_tc7_byvect
:
1158 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1160 return scm_ulong2num (((unsigned long *) SCM_VELTS (v
))[pos
]);
1162 return scm_long2num (((signed long *) SCM_VELTS (v
))[pos
]);
1165 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1166 #ifdef HAVE_LONG_LONGS
1167 case scm_tc7_llvect
:
1168 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1172 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1174 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1176 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1177 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1178 case scm_tc7_vector
:
1180 return SCM_VELTS (v
)[pos
];
1185 /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1186 tries to recycle conses. (Make *sure* you want them recycled.) */
1189 scm_cvref (SCM v
, unsigned long pos
, SCM last
)
1190 #define FUNC_NAME "scm_cvref"
1195 SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1197 if (SCM_BITVEC_REF(v
,pos
))
1201 case scm_tc7_string
:
1202 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1203 case scm_tc7_byvect
:
1204 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1206 return scm_ulong2num(((unsigned long *) SCM_VELTS (v
))[pos
]);
1208 return scm_long2num(((signed long *) SCM_VELTS (v
))[pos
]);
1210 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1211 #ifdef HAVE_LONG_LONGS
1212 case scm_tc7_llvect
:
1213 return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v
))[pos
]);
1216 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1218 SCM_REAL_VALUE (last
) = ((float *) SCM_CELL_WORD_1 (v
))[pos
];
1221 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1223 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1225 SCM_REAL_VALUE (last
) = ((double *) SCM_CELL_WORD_1 (v
))[pos
];
1228 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1230 if (SCM_NIMP (last
) && SCM_SLOPPY_COMPLEXP (last
))
1232 SCM_COMPLEX_REAL (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
];
1233 SCM_COMPLEX_IMAG (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1];
1236 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1237 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1238 case scm_tc7_vector
:
1240 return SCM_VELTS (v
)[pos
];
1242 { /* enclosed scm_array */
1243 int k
= SCM_ARRAY_NDIM (v
);
1244 SCM res
= scm_make_ra (k
);
1245 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1246 SCM_ARRAY_BASE (res
) = pos
;
1249 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1250 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1251 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1260 SCM_REGISTER_PROC(s_uniform_array_set1_x
, "uniform-array-set1!", 3, 0, 0, scm_array_set_x
);
1263 /* Note that args may be a list or an immediate object, depending which
1264 PROC is used (and it's called from C too). */
1265 SCM_DEFINE (scm_array_set_x
, "array-set!", 2, 0, 1,
1266 (SCM v
, SCM obj
, SCM args
),
1267 "@deffnx primitive uniform-array-set1! v obj args\n"
1268 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1269 "@var{new-value}. The value returned by array-set! is unspecified.")
1270 #define FUNC_NAME s_scm_array_set_x
1274 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1277 pos
= scm_aind (v
, args
, FUNC_NAME
);
1278 v
= SCM_ARRAY_V (v
);
1282 unsigned long int length
;
1283 if (SCM_CONSP (args
))
1285 SCM_ASSERT (SCM_INUMP (SCM_CAR (args
)), args
, SCM_ARG3
, FUNC_NAME
);
1286 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args
)), wna
);
1287 pos
= SCM_INUM (SCM_CAR (args
));
1291 SCM_VALIDATE_INUM_COPY (3,args
,pos
);
1293 length
= SCM_INUM (scm_uniform_vector_length (v
));
1294 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1296 switch (SCM_TYP7 (v
))
1299 SCM_WRONG_TYPE_ARG (1, v
);
1302 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1304 SCM_WRONG_NUM_ARGS ();
1305 case scm_tc7_smob
: /* enclosed */
1308 if (SCM_FALSEP (obj
))
1309 SCM_BITVEC_CLR(v
,pos
);
1310 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1311 SCM_BITVEC_SET(v
,pos
);
1313 badobj
:SCM_WRONG_TYPE_ARG (2, obj
);
1315 case scm_tc7_string
:
1316 SCM_ASRTGO (SCM_CHARP (obj
), badobj
);
1317 SCM_STRING_UCHARS (v
)[pos
] = SCM_CHAR (obj
);
1319 case scm_tc7_byvect
:
1320 if (SCM_CHARP (obj
))
1321 obj
= SCM_MAKINUM ((char) SCM_CHAR (obj
));
1322 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1323 ((char *) SCM_UVECTOR_BASE (v
))[pos
] = SCM_INUM (obj
);
1326 ((unsigned long *) SCM_UVECTOR_BASE (v
))[pos
]
1327 = scm_num2ulong (obj
, SCM_ARG2
, FUNC_NAME
);
1330 ((long *) SCM_UVECTOR_BASE (v
))[pos
]
1331 = scm_num2long (obj
, SCM_ARG2
, FUNC_NAME
);
1334 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1335 ((short *) SCM_UVECTOR_BASE (v
))[pos
] = SCM_INUM (obj
);
1337 #ifdef HAVE_LONG_LONGS
1338 case scm_tc7_llvect
:
1339 ((long long *) SCM_UVECTOR_BASE (v
))[pos
]
1340 = scm_num2long_long (obj
, SCM_ARG2
, FUNC_NAME
);
1344 ((float *) SCM_UVECTOR_BASE (v
))[pos
]
1345 = (float) scm_num2dbl (obj
, FUNC_NAME
);
1348 ((double *) SCM_UVECTOR_BASE (v
))[pos
]
1349 = scm_num2dbl (obj
, FUNC_NAME
);
1352 SCM_ASRTGO (SCM_INEXACTP (obj
), badobj
);
1353 if (SCM_REALP (obj
)) {
1354 ((double *) SCM_UVECTOR_BASE (v
))[2 * pos
] = SCM_REAL_VALUE (obj
);
1355 ((double *) SCM_UVECTOR_BASE (v
))[2 * pos
+ 1] = 0.0;
1357 ((double *) SCM_UVECTOR_BASE (v
))[2 * pos
] = SCM_COMPLEX_REAL (obj
);
1358 ((double *) SCM_UVECTOR_BASE (v
))[2 * pos
+ 1] = SCM_COMPLEX_IMAG (obj
);
1361 case scm_tc7_vector
:
1363 SCM_VELTS (v
)[pos
] = obj
;
1366 return SCM_UNSPECIFIED
;
1370 /* attempts to unroll an array into a one-dimensional array.
1371 returns the unrolled array or #f if it can't be done. */
1372 /* if strict is not SCM_UNDEFINED, return #f if returned array
1373 wouldn't have contiguous elements. */
1374 SCM_DEFINE (scm_array_contents
, "array-contents", 1, 1, 0,
1375 (SCM ra
, SCM strict
),
1376 "@deffnx primitive array-contents array strict\n"
1377 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1378 "without changing their order (last subscript changing fastest), then\n"
1379 "@code{array-contents} returns that shared array, otherwise it returns\n"
1380 "@code{#f}. All arrays made by @var{make-array} and\n"
1381 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1382 "@var{make-shared-array} may not be.\n\n"
1383 "If the optional argument @var{strict} is provided, a shared array will\n"
1384 "be returned only if its elements are stored internally contiguous in\n"
1386 #define FUNC_NAME s_scm_array_contents
1391 switch SCM_TYP7 (ra
)
1395 case scm_tc7_vector
:
1397 case scm_tc7_string
:
1399 case scm_tc7_byvect
:
1406 #ifdef HAVE_LONG_LONGS
1407 case scm_tc7_llvect
:
1412 size_t k
, ndim
= SCM_ARRAY_NDIM (ra
), len
= 1;
1413 if (!SCM_ARRAYP (ra
) || !SCM_ARRAY_CONTP (ra
))
1415 for (k
= 0; k
< ndim
; k
++)
1416 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1417 if (!SCM_UNBNDP (strict
))
1419 if (ndim
&& (1 != SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
))
1421 if (scm_tc7_bvect
== SCM_TYP7 (SCM_ARRAY_V (ra
)))
1423 if (len
!= SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) ||
1424 SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
||
1431 SCM v
= SCM_ARRAY_V (ra
);
1432 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
1433 if ((len
== length
) && 0 == SCM_ARRAY_BASE (ra
) && SCM_ARRAY_DIMS (ra
)->inc
)
1437 sra
= scm_make_ra (1);
1438 SCM_ARRAY_DIMS (sra
)->lbnd
= 0;
1439 SCM_ARRAY_DIMS (sra
)->ubnd
= len
- 1;
1440 SCM_ARRAY_V (sra
) = SCM_ARRAY_V (ra
);
1441 SCM_ARRAY_BASE (sra
) = SCM_ARRAY_BASE (ra
);
1442 SCM_ARRAY_DIMS (sra
)->inc
= (ndim
? SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
: 1);
1451 scm_ra2contig (SCM ra
, int copy
)
1456 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
1457 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1458 k
= SCM_ARRAY_NDIM (ra
);
1459 if (SCM_ARRAY_CONTP (ra
) && ((0 == k
) || (1 == SCM_ARRAY_DIMS (ra
)[k
- 1].inc
)))
1461 if (scm_tc7_bvect
!= SCM_TYP7 (SCM_ARRAY_V (ra
)))
1463 if ((len
== SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) &&
1464 0 == SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
&&
1465 0 == len
% SCM_LONG_BIT
))
1468 ret
= scm_make_ra (k
);
1469 SCM_ARRAY_BASE (ret
) = 0;
1472 SCM_ARRAY_DIMS (ret
)[k
].lbnd
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
;
1473 SCM_ARRAY_DIMS (ret
)[k
].ubnd
= SCM_ARRAY_DIMS (ra
)[k
].ubnd
;
1474 SCM_ARRAY_DIMS (ret
)[k
].inc
= inc
;
1475 inc
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1477 SCM_ARRAY_V (ret
) = scm_make_uve ((inc
- 1), scm_array_prototype (ra
));
1479 scm_array_copy_x (ra
, ret
);
1485 SCM_DEFINE (scm_uniform_array_read_x
, "uniform-array-read!", 1, 3, 0,
1486 (SCM ra
, SCM port_or_fd
, SCM start
, SCM end
),
1487 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1488 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1489 "binary objects from @var{port-or-fdes}.\n"
1490 "If an end of file is encountered during\n"
1491 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1492 "(starting at the beginning) and the remainder of the array is\n"
1494 "The optional arguments @var{start} and @var{end} allow\n"
1495 "a specified region of a vector (or linearized array) to be read,\n"
1496 "leaving the remainder of the vector unchanged.\n\n"
1497 "@code{uniform-array-read!} returns the number of objects read.\n"
1498 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1499 "returned by @code{(current-input-port)}.")
1500 #define FUNC_NAME s_scm_uniform_array_read_x
1502 SCM cra
= SCM_UNDEFINED
, v
= ra
;
1509 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1510 if (SCM_UNBNDP (port_or_fd
))
1511 port_or_fd
= scm_cur_inp
;
1513 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1514 || (SCM_OPINPORTP (port_or_fd
)),
1515 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1516 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1522 badarg1
:SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1524 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1525 cra
= scm_ra2contig (ra
, 0);
1526 cstart
+= SCM_ARRAY_BASE (cra
);
1527 vlen
= SCM_ARRAY_DIMS (cra
)->inc
*
1528 (SCM_ARRAY_DIMS (cra
)->ubnd
- SCM_ARRAY_DIMS (cra
)->lbnd
+ 1);
1529 v
= SCM_ARRAY_V (cra
);
1531 case scm_tc7_string
:
1532 base
= SCM_STRING_CHARS (v
);
1536 base
= (char *) SCM_BITVECTOR_BASE (v
);
1537 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1538 cstart
/= SCM_LONG_BIT
;
1541 case scm_tc7_byvect
:
1542 base
= (char *) SCM_UVECTOR_BASE (v
);
1547 base
= (char *) SCM_UVECTOR_BASE (v
);
1551 base
= (char *) SCM_UVECTOR_BASE (v
);
1552 sz
= sizeof (short);
1554 #ifdef HAVE_LONG_LONGS
1555 case scm_tc7_llvect
:
1556 base
= (char *) SCM_UVECTOR_BASE (v
);
1557 sz
= sizeof (long long);
1561 base
= (char *) SCM_UVECTOR_BASE (v
);
1562 sz
= sizeof (float);
1565 base
= (char *) SCM_UVECTOR_BASE (v
);
1566 sz
= sizeof (double);
1569 base
= (char *) SCM_UVECTOR_BASE (v
);
1570 sz
= 2 * sizeof (double);
1575 if (!SCM_UNBNDP (start
))
1578 SCM_NUM2LONG (3, start
);
1580 if (offset
< 0 || offset
>= cend
)
1581 scm_out_of_range (FUNC_NAME
, start
);
1583 if (!SCM_UNBNDP (end
))
1586 SCM_NUM2LONG (4, end
);
1588 if (tend
<= offset
|| tend
> cend
)
1589 scm_out_of_range (FUNC_NAME
, end
);
1594 if (SCM_NIMP (port_or_fd
))
1596 scm_t_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
1597 int remaining
= (cend
- offset
) * sz
;
1598 char *dest
= base
+ (cstart
+ offset
) * sz
;
1600 if (pt
->rw_active
== SCM_PORT_WRITE
)
1601 scm_flush (port_or_fd
);
1603 ans
= cend
- offset
;
1604 while (remaining
> 0)
1606 if (pt
->read_pos
< pt
->read_end
)
1608 int to_copy
= min (pt
->read_end
- pt
->read_pos
,
1611 memcpy (dest
, pt
->read_pos
, to_copy
);
1612 pt
->read_pos
+= to_copy
;
1613 remaining
-= to_copy
;
1618 if (scm_fill_input (port_or_fd
) == EOF
)
1620 if (remaining
% sz
!= 0)
1622 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
1624 ans
-= remaining
/ sz
;
1631 pt
->rw_active
= SCM_PORT_READ
;
1633 else /* file descriptor. */
1635 SCM_SYSCALL (ans
= read (SCM_INUM (port_or_fd
),
1636 base
+ (cstart
+ offset
) * sz
,
1637 (sz
* (cend
- offset
))));
1641 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1642 ans
*= SCM_LONG_BIT
;
1644 if (!SCM_EQ_P (v
, ra
) && !SCM_EQ_P (cra
, ra
))
1645 scm_array_copy_x (cra
, ra
);
1647 return SCM_MAKINUM (ans
);
1651 SCM_DEFINE (scm_uniform_array_write
, "uniform-array-write", 1, 3, 0,
1652 (SCM v
, SCM port_or_fd
, SCM start
, SCM end
),
1653 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1654 "Writes all elements of @var{ura} as binary objects to\n"
1655 "@var{port-or-fdes}.\n\n"
1656 "The optional arguments @var{start}\n"
1657 "and @var{end} allow\n"
1658 "a specified region of a vector (or linearized array) to be written.\n\n"
1659 "The number of objects actually written is returned. \n"
1660 "@var{port-or-fdes} may be\n"
1661 "omitted, in which case it defaults to the value returned by\n"
1662 "@code{(current-output-port)}.")
1663 #define FUNC_NAME s_scm_uniform_array_write
1671 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
1673 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1674 if (SCM_UNBNDP (port_or_fd
))
1675 port_or_fd
= scm_cur_outp
;
1677 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1678 || (SCM_OPOUTPORTP (port_or_fd
)),
1679 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1680 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1686 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1688 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1689 v
= scm_ra2contig (v
, 1);
1690 cstart
= SCM_ARRAY_BASE (v
);
1691 vlen
= SCM_ARRAY_DIMS (v
)->inc
1692 * (SCM_ARRAY_DIMS (v
)->ubnd
- SCM_ARRAY_DIMS (v
)->lbnd
+ 1);
1693 v
= SCM_ARRAY_V (v
);
1695 case scm_tc7_string
:
1696 base
= SCM_STRING_CHARS (v
);
1700 base
= (char *) SCM_BITVECTOR_BASE (v
);
1701 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1702 cstart
/= SCM_LONG_BIT
;
1705 case scm_tc7_byvect
:
1706 base
= (char *) SCM_UVECTOR_BASE (v
);
1711 base
= (char *) SCM_UVECTOR_BASE (v
);
1715 base
= (char *) SCM_UVECTOR_BASE (v
);
1716 sz
= sizeof (short);
1718 #ifdef HAVE_LONG_LONGS
1719 case scm_tc7_llvect
:
1720 base
= (char *) SCM_UVECTOR_BASE (v
);
1721 sz
= sizeof (long long);
1725 base
= (char *) SCM_UVECTOR_BASE (v
);
1726 sz
= sizeof (float);
1729 base
= (char *) SCM_UVECTOR_BASE (v
);
1730 sz
= sizeof (double);
1733 base
= (char *) SCM_UVECTOR_BASE (v
);
1734 sz
= 2 * sizeof (double);
1739 if (!SCM_UNBNDP (start
))
1742 SCM_NUM2LONG (3, start
);
1744 if (offset
< 0 || offset
>= cend
)
1745 scm_out_of_range (FUNC_NAME
, start
);
1747 if (!SCM_UNBNDP (end
))
1750 SCM_NUM2LONG (4, end
);
1752 if (tend
<= offset
|| tend
> cend
)
1753 scm_out_of_range (FUNC_NAME
, end
);
1758 if (SCM_NIMP (port_or_fd
))
1760 char *source
= base
+ (cstart
+ offset
) * sz
;
1762 ans
= cend
- offset
;
1763 scm_lfwrite (source
, ans
* sz
, port_or_fd
);
1765 else /* file descriptor. */
1767 SCM_SYSCALL (ans
= write (SCM_INUM (port_or_fd
),
1768 base
+ (cstart
+ offset
) * sz
,
1769 (sz
* (cend
- offset
))));
1773 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1774 ans
*= SCM_LONG_BIT
;
1776 return SCM_MAKINUM (ans
);
1781 static char cnt_tab
[16] =
1782 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1784 SCM_DEFINE (scm_bit_count
, "bit-count", 2, 0, 0,
1785 (SCM b
, SCM bitvector
),
1786 "Return the number of occurrences of the boolean @var{b} in\n"
1788 #define FUNC_NAME s_scm_bit_count
1790 SCM_VALIDATE_BOOL (1, b
);
1791 SCM_ASSERT (SCM_BITVECTOR_P (bitvector
), bitvector
, 2, FUNC_NAME
);
1792 if (SCM_BITVECTOR_LENGTH (bitvector
) == 0) {
1795 unsigned long int count
= 0;
1796 unsigned long int i
= (SCM_BITVECTOR_LENGTH (bitvector
) - 1) / SCM_LONG_BIT
;
1797 unsigned long int w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1798 if (SCM_FALSEP (b
)) {
1801 w
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (bitvector
) - 1) % SCM_LONG_BIT
);
1804 count
+= cnt_tab
[w
& 0x0f];
1808 return SCM_MAKINUM (count
);
1811 w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1812 if (SCM_FALSEP (b
)) {
1822 SCM_DEFINE (scm_bit_position
, "bit-position", 3, 0, 0,
1823 (SCM item
, SCM v
, SCM k
),
1824 "Return the minimum index of an occurrence of @var{bool} in\n"
1825 "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
1826 "within the specified range @code{#f} is returned.")
1827 #define FUNC_NAME s_scm_bit_position
1829 long i
, lenw
, xbits
, pos
;
1830 register unsigned long w
;
1832 SCM_VALIDATE_BOOL (1, item
);
1833 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG2
, FUNC_NAME
);
1834 SCM_VALIDATE_INUM_COPY (3,k
,pos
);
1835 SCM_ASSERT_RANGE (3, k
, (pos
<= SCM_BITVECTOR_LENGTH (v
)) && (pos
>= 0));
1837 if (pos
== SCM_BITVECTOR_LENGTH (v
))
1840 lenw
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; /* watch for part words */
1841 i
= pos
/ SCM_LONG_BIT
;
1842 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1843 if (SCM_FALSEP (item
))
1845 xbits
= (pos
% SCM_LONG_BIT
);
1847 w
= ((w
>> xbits
) << xbits
);
1848 xbits
= SCM_LONG_BIT
- 1 - (SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
;
1851 if (w
&& (i
== lenw
))
1852 w
= ((w
<< xbits
) >> xbits
);
1858 return SCM_MAKINUM (pos
);
1863 return SCM_MAKINUM (pos
+ 1);
1866 return SCM_MAKINUM (pos
+ 2);
1868 return SCM_MAKINUM (pos
+ 3);
1875 pos
+= SCM_LONG_BIT
;
1876 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1877 if (SCM_FALSEP (item
))
1885 SCM_DEFINE (scm_bit_set_star_x
, "bit-set*!", 3, 0, 0,
1886 (SCM v
, SCM kv
, SCM obj
),
1887 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1888 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1889 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1890 "AND'ed into @var{bv}.\n\n"
1891 "If uve is a unsigned integer vector all the elements of uve\n"
1892 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1893 "of @var{bv} corresponding to the indexes in uve are set to\n"
1894 "@var{bool}. The return value is unspecified.")
1895 #define FUNC_NAME s_scm_bit_set_star_x
1897 register long i
, k
, vlen
;
1898 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1899 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1900 switch SCM_TYP7 (kv
)
1903 badarg2
:SCM_WRONG_TYPE_ARG (2, kv
);
1905 vlen
= SCM_BITVECTOR_LENGTH (v
);
1906 if (SCM_FALSEP (obj
))
1907 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1909 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1911 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1912 SCM_BITVEC_CLR(v
,k
);
1914 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1915 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1917 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1919 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1920 SCM_BITVEC_SET(v
,k
);
1923 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1926 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1927 if (SCM_FALSEP (obj
))
1928 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1929 SCM_BITVECTOR_BASE (v
) [k
] &= ~SCM_BITVECTOR_BASE (kv
) [k
];
1930 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1931 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1932 SCM_BITVECTOR_BASE (v
) [k
] |= SCM_BITVECTOR_BASE (kv
) [k
];
1937 return SCM_UNSPECIFIED
;
1942 SCM_DEFINE (scm_bit_count_star
, "bit-count*", 3, 0, 0,
1943 (SCM v
, SCM kv
, SCM obj
),
1946 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1948 "@var{bv} is not modified.")
1949 #define FUNC_NAME s_scm_bit_count_star
1951 register long i
, vlen
, count
= 0;
1952 register unsigned long k
;
1955 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1956 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1957 switch SCM_TYP7 (kv
)
1961 SCM_WRONG_TYPE_ARG (2, kv
);
1963 vlen
= SCM_BITVECTOR_LENGTH (v
);
1964 if (SCM_FALSEP (obj
))
1965 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1967 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1969 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1970 if (!SCM_BITVEC_REF(v
,k
))
1973 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1974 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1976 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1978 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1979 if (SCM_BITVEC_REF (v
,k
))
1983 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1986 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1987 if (0 == SCM_BITVECTOR_LENGTH (v
))
1989 SCM_ASRTGO (SCM_BOOLP (obj
), badarg3
);
1990 fObj
= SCM_EQ_P (obj
, SCM_BOOL_T
);
1991 i
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
;
1992 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK (SCM_VELTS (v
)[i
]) : ~ SCM_UNPACK (SCM_VELTS (v
)[i
]));
1993 k
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
);
1997 count
+= cnt_tab
[k
& 0x0f];
1999 return SCM_MAKINUM (count
);
2001 /* urg. repetitive (see above.) */
2002 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK(SCM_VELTS (v
)[i
]) : ~SCM_UNPACK (SCM_VELTS (v
)[i
]));
2005 return SCM_MAKINUM (count
);
2010 SCM_DEFINE (scm_bit_invert_x
, "bit-invert!", 1, 0, 0,
2012 "Modifies @var{bv} by replacing each element with its negation.")
2013 #define FUNC_NAME s_scm_bit_invert_x
2017 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
2019 k
= SCM_BITVECTOR_LENGTH (v
);
2020 for (k
= (k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
2021 SCM_BITVECTOR_BASE (v
) [k
] = ~SCM_BITVECTOR_BASE (v
) [k
];
2023 return SCM_UNSPECIFIED
;
2029 scm_istr2bve (char *str
, long len
)
2031 SCM v
= scm_make_uve (len
, SCM_BOOL_T
);
2032 long *data
= (long *) SCM_VELTS (v
);
2033 register unsigned long mask
;
2036 for (k
= 0; k
< (len
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
++)
2039 j
= len
- k
* SCM_LONG_BIT
;
2040 if (j
> SCM_LONG_BIT
)
2042 for (mask
= 1L; j
--; mask
<<= 1)
2060 ra2l (SCM ra
,unsigned long base
,unsigned long k
)
2062 register SCM res
= SCM_EOL
;
2063 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2065 if (SCM_ARRAY_DIMS (ra
)[k
].ubnd
< SCM_ARRAY_DIMS (ra
)[k
].lbnd
)
2067 i
= base
+ (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
) * inc
;
2068 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2073 res
= scm_cons (ra2l (ra
, i
, k
+ 1), res
);
2081 res
= scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra
), SCM_MAKINUM (i
)), res
);
2088 SCM_DEFINE (scm_t_arrayo_list
, "array->list", 1, 0, 0,
2090 "Return a list consisting of all the elements, in order, of\n"
2092 #define FUNC_NAME s_scm_t_arrayo_list
2096 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
2100 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
2102 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
2103 return ra2l (v
, SCM_ARRAY_BASE (v
), 0);
2104 case scm_tc7_vector
:
2106 return scm_vector_to_list (v
);
2107 case scm_tc7_string
:
2108 return scm_string_to_list (v
);
2111 long *data
= (long *) SCM_VELTS (v
);
2112 register unsigned long mask
;
2113 for (k
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; k
> 0; k
--)
2114 for (mask
= 1UL << (SCM_LONG_BIT
- 1); mask
; mask
>>= 1)
2115 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2116 for (mask
= 1L << ((SCM_BITVECTOR_LENGTH (v
) % SCM_LONG_BIT
) - 1); mask
; mask
>>= 1)
2117 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2120 case scm_tc7_byvect
:
2122 signed char *data
= (signed char *) SCM_VELTS (v
);
2123 unsigned long k
= SCM_UVECTOR_LENGTH (v
);
2125 res
= scm_cons (SCM_MAKINUM (data
[--k
]), res
);
2130 long *data
= (long *)SCM_VELTS(v
);
2131 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2132 res
= scm_cons(scm_ulong2num(data
[k
]), res
);
2137 long *data
= (long *)SCM_VELTS(v
);
2138 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2139 res
= scm_cons(scm_long2num(data
[k
]), res
);
2144 short *data
= (short *)SCM_VELTS(v
);
2145 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2146 res
= scm_cons(scm_short2num (data
[k
]), res
);
2149 #ifdef HAVE_LONG_LONGS
2150 case scm_tc7_llvect
:
2152 long long *data
= (long long *)SCM_VELTS(v
);
2153 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2154 res
= scm_cons(scm_long_long2num(data
[k
]), res
);
2160 float *data
= (float *) SCM_VELTS (v
);
2161 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2162 res
= scm_cons (scm_make_real (data
[k
]), res
);
2167 double *data
= (double *) SCM_VELTS (v
);
2168 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2169 res
= scm_cons (scm_make_real (data
[k
]), res
);
2174 double (*data
)[2] = (double (*)[2]) SCM_VELTS (v
);
2175 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2176 res
= scm_cons (scm_make_complex (data
[k
][0], data
[k
][1]), res
);
2184 static int l2ra(SCM lst
, SCM ra
, unsigned long base
, unsigned long k
);
2186 SCM_DEFINE (scm_list_to_uniform_array
, "list->uniform-array", 3, 0, 0,
2187 (SCM ndim
, SCM prot
, SCM lst
),
2188 "@deffnx procedure list->uniform-vector prot lst\n"
2189 "Return a uniform array of the type indicated by prototype\n"
2190 "@var{prot} with elements the same as those of @var{lst}.\n"
2191 "Elements must be of the appropriate type, no coercions are\n"
2193 #define FUNC_NAME s_scm_list_to_uniform_array
2200 SCM_VALIDATE_INUM_COPY (1,ndim
,k
);
2203 n
= scm_ilength (row
);
2204 SCM_ASSERT (n
>= 0, lst
, SCM_ARG3
, FUNC_NAME
);
2205 shp
= scm_cons (SCM_MAKINUM (n
), shp
);
2207 row
= SCM_CAR (row
);
2209 ra
= scm_dimensions_to_uniform_array (scm_reverse (shp
), prot
,
2211 if (SCM_NULLP (shp
))
2213 SCM_ASRTGO (1 == scm_ilength (lst
), badlst
);
2214 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_EOL
);
2217 if (!SCM_ARRAYP (ra
))
2219 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (ra
));
2220 for (k
= 0; k
< length
; k
++, lst
= SCM_CDR (lst
))
2221 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_MAKINUM (k
));
2224 if (l2ra (lst
, ra
, SCM_ARRAY_BASE (ra
), 0))
2227 badlst
:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2233 l2ra (SCM lst
, SCM ra
, unsigned long base
, unsigned long k
)
2235 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2236 register long n
= (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
);
2239 return (SCM_NULLP (lst
));
2240 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2244 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2246 ok
= ok
&& l2ra (SCM_CAR (lst
), ra
, base
, k
+ 1);
2248 lst
= SCM_CDR (lst
);
2250 if (SCM_NNULLP (lst
))
2257 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2259 scm_array_set_x (SCM_ARRAY_V (ra
), SCM_CAR (lst
), SCM_MAKINUM (base
));
2261 lst
= SCM_CDR (lst
);
2263 if (SCM_NNULLP (lst
))
2271 rapr1 (SCM ra
,unsigned long j
,unsigned long k
,SCM port
,scm_print_state
*pstate
)
2274 long n
= (SCM_TYP7 (ra
) == scm_tc7_smob
2276 : SCM_INUM (scm_uniform_vector_length (ra
)));
2279 switch SCM_TYP7 (ra
)
2284 SCM_ARRAY_BASE (ra
) = j
;
2286 scm_iprin1 (ra
, port
, pstate
);
2287 for (j
+= inc
; n
-- > 0; j
+= inc
)
2289 scm_putc (' ', port
);
2290 SCM_ARRAY_BASE (ra
) = j
;
2291 scm_iprin1 (ra
, port
, pstate
);
2295 if (k
+ 1 < SCM_ARRAY_NDIM (ra
))
2298 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2299 for (i
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
; i
< SCM_ARRAY_DIMS (ra
)[k
].ubnd
; i
++)
2301 scm_putc ('(', port
);
2302 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2303 scm_puts (") ", port
);
2306 if (i
== SCM_ARRAY_DIMS (ra
)[k
].ubnd
)
2307 { /* could be zero size. */
2308 scm_putc ('(', port
);
2309 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2310 scm_putc (')', port
);
2314 if (SCM_ARRAY_NDIM (ra
) > 0)
2315 { /* Could be zero-dimensional */
2316 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2317 n
= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
2321 ra
= SCM_ARRAY_V (ra
);
2324 /* scm_tc7_bvect and scm_tc7_llvect only? */
2326 scm_iprin1 (scm_uniform_vector_ref (ra
, SCM_MAKINUM (j
)), port
, pstate
);
2327 for (j
+= inc
; n
-- > 0; j
+= inc
)
2329 scm_putc (' ', port
);
2330 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2333 case scm_tc7_string
:
2335 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2336 if (SCM_WRITINGP (pstate
))
2337 for (j
+= inc
; n
-- > 0; j
+= inc
)
2339 scm_putc (' ', port
);
2340 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2343 for (j
+= inc
; n
-- > 0; j
+= inc
)
2344 scm_putc (SCM_STRING_CHARS (ra
)[j
], port
);
2346 case scm_tc7_byvect
:
2348 scm_intprint (((char *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2349 for (j
+= inc
; n
-- > 0; j
+= inc
)
2351 scm_putc (' ', port
);
2352 scm_intprint (((char *)SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2362 /* intprint can't handle >= 2^31. */
2363 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2364 scm_puts (str
, port
);
2366 for (j
+= inc
; n
-- > 0; j
+= inc
)
2368 scm_putc (' ', port
);
2369 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2370 scm_puts (str
, port
);
2375 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2376 for (j
+= inc
; n
-- > 0; j
+= inc
)
2378 scm_putc (' ', port
);
2379 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2385 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2386 for (j
+= inc
; n
-- > 0; j
+= inc
)
2388 scm_putc (' ', port
);
2389 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2396 SCM z
= scm_make_real (1.0);
2397 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2398 scm_print_real (z
, port
, pstate
);
2399 for (j
+= inc
; n
-- > 0; j
+= inc
)
2401 scm_putc (' ', port
);
2402 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2403 scm_print_real (z
, port
, pstate
);
2410 SCM z
= scm_make_real (1.0 / 3.0);
2411 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2412 scm_print_real (z
, port
, pstate
);
2413 for (j
+= inc
; n
-- > 0; j
+= inc
)
2415 scm_putc (' ', port
);
2416 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2417 scm_print_real (z
, port
, pstate
);
2424 SCM cz
= scm_make_complex (0.0, 1.0), z
= scm_make_real (1.0 / 3.0);
2425 SCM_REAL_VALUE (z
) =
2426 SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2427 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2428 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2430 for (j
+= inc
; n
-- > 0; j
+= inc
)
2432 scm_putc (' ', port
);
2434 = SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2435 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2436 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2447 scm_raprin1 (SCM exp
, SCM port
, scm_print_state
*pstate
)
2450 unsigned long base
= 0;
2451 scm_putc ('#', port
);
2457 long ndim
= SCM_ARRAY_NDIM (v
);
2458 base
= SCM_ARRAY_BASE (v
);
2459 v
= SCM_ARRAY_V (v
);
2463 scm_puts ("<enclosed-array ", port
);
2464 rapr1 (exp
, base
, 0, port
, pstate
);
2465 scm_putc ('>', port
);
2470 scm_intprint (ndim
, 10, port
);
2475 if (SCM_EQ_P (exp
, v
))
2476 { /* a uve, not an scm_array */
2477 register long i
, j
, w
;
2478 scm_putc ('*', port
);
2479 for (i
= 0; i
< (SCM_BITVECTOR_LENGTH (exp
)) / SCM_LONG_BIT
; i
++)
2481 scm_t_bits w
= SCM_UNPACK (SCM_VELTS (exp
)[i
]);
2482 for (j
= SCM_LONG_BIT
; j
; j
--)
2484 scm_putc (w
& 1 ? '1' : '0', port
);
2488 j
= SCM_BITVECTOR_LENGTH (exp
) % SCM_LONG_BIT
;
2491 w
= SCM_UNPACK (SCM_VELTS (exp
)[SCM_BITVECTOR_LENGTH (exp
) / SCM_LONG_BIT
]);
2494 scm_putc (w
& 1 ? '1' : '0', port
);
2501 scm_putc ('b', port
);
2503 case scm_tc7_string
:
2504 scm_putc ('a', port
);
2506 case scm_tc7_byvect
:
2507 scm_putc ('y', port
);
2510 scm_putc ('u', port
);
2513 scm_putc ('e', port
);
2516 scm_putc ('h', port
);
2518 #ifdef HAVE_LONG_LONGS
2519 case scm_tc7_llvect
:
2520 scm_putc ('l', port
);
2524 scm_putc ('s', port
);
2527 scm_putc ('i', port
);
2530 scm_putc ('c', port
);
2533 scm_putc ('(', port
);
2534 rapr1 (exp
, base
, 0, port
, pstate
);
2535 scm_putc (')', port
);
2539 SCM_DEFINE (scm_array_prototype
, "array-prototype", 1, 0, 0,
2541 "Return an object that would produce an array of the same type\n"
2542 "as @var{array}, if used as the @var{prototype} for\n"
2543 "@code{make-uniform-array}.")
2544 #define FUNC_NAME s_scm_array_prototype
2547 SCM_ASRTGO (SCM_NIMP (ra
), badarg
);
2549 switch SCM_TYP7 (ra
)
2552 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
2554 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
2556 return SCM_UNSPECIFIED
;
2557 ra
= SCM_ARRAY_V (ra
);
2559 case scm_tc7_vector
:
2564 case scm_tc7_string
:
2565 return SCM_MAKE_CHAR ('a');
2566 case scm_tc7_byvect
:
2567 return SCM_MAKE_CHAR ('\0');
2569 return SCM_MAKINUM (1L);
2571 return SCM_MAKINUM (-1L);
2573 return scm_str2symbol ("s");
2574 #ifdef HAVE_LONG_LONGS
2575 case scm_tc7_llvect
:
2576 return scm_str2symbol ("l");
2579 return scm_make_real (1.0);
2581 return scm_make_real (1.0 / 3.0);
2583 return scm_make_complex (0.0, 1.0);
2590 array_mark (SCM ptr
)
2592 return SCM_ARRAY_V (ptr
);
2597 array_free (SCM ptr
)
2599 scm_must_free (SCM_ARRAY_MEM (ptr
));
2600 return sizeof (scm_t_array
) +
2601 SCM_ARRAY_NDIM (ptr
) * sizeof (scm_t_array_dim
);
2607 scm_tc16_array
= scm_make_smob_type ("array", 0);
2608 scm_set_smob_mark (scm_tc16_array
, array_mark
);
2609 scm_set_smob_free (scm_tc16_array
, array_free
);
2610 scm_set_smob_print (scm_tc16_array
, scm_raprin1
);
2611 scm_set_smob_equalp (scm_tc16_array
, scm_array_equal_p
);
2612 scm_add_feature ("array");
2613 #ifndef SCM_MAGIC_SNARFER
2614 #include "libguile/unif.x"