1 /* Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
46 This file has code for arrays in lots of variants (double, integer,
47 unsigned etc. ). It suffers from hugely repetitive code because
48 there is similar (but different) code for every variant included. (urg.)
58 #include "libguile/_scm.h"
59 #include "libguile/chars.h"
60 #include "libguile/eval.h"
61 #include "libguile/fports.h"
62 #include "libguile/smob.h"
63 #include "libguile/strop.h"
64 #include "libguile/feature.h"
65 #include "libguile/root.h"
66 #include "libguile/strings.h"
67 #include "libguile/vectors.h"
69 #include "libguile/validate.h"
70 #include "libguile/unif.h"
71 #include "libguile/ramap.h"
78 /* The set of uniform scm_vector types is:
80 * unsigned char string
87 * complex double cvect
92 scm_bits_t scm_tc16_array
;
94 /* return the size of an element in a uniform array or 0 if type not
97 scm_uniform_element_size (SCM obj
)
101 switch (SCM_TYP7 (obj
))
106 result
= sizeof (long);
110 result
= sizeof (char);
114 result
= sizeof (short);
117 #ifdef HAVE_LONG_LONGS
119 result
= sizeof (long_long
);
124 result
= sizeof (float);
128 result
= sizeof (double);
132 result
= 2 * sizeof (double);
141 /* Silly function used not to modify the semantics of the silly
142 * prototype system in order to be backward compatible.
147 if (!SCM_SLOPPY_REALP (obj
))
151 double x
= SCM_REAL_VALUE (obj
);
153 return (- SCM_FLTMAX
< x
) && (x
< SCM_FLTMAX
) && (fx
== x
);
158 scm_make_uve (long k
, SCM prot
)
159 #define FUNC_NAME "scm_make_uve"
164 if (SCM_EQ_P (prot
, SCM_BOOL_T
))
169 SCM_ASSERT_RANGE (1, scm_long2num (k
), k
<= SCM_BITVECTOR_MAX_LENGTH
);
170 i
= sizeof (long) * ((k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
);
171 SCM_SET_BITVECTOR_BASE (v
, (char *) scm_must_malloc (i
, "vector"));
172 SCM_SET_BITVECTOR_LENGTH (v
, k
);
176 SCM_SET_BITVECTOR_BASE (v
, 0);
177 SCM_SET_BITVECTOR_LENGTH (v
, 0);
181 else if (SCM_CHARP (prot
) && (SCM_CHAR (prot
) == '\0'))
183 i
= sizeof (char) * k
;
184 type
= scm_tc7_byvect
;
186 else if (SCM_CHARP (prot
))
188 i
= sizeof (char) * k
;
189 return scm_allocate_string (i
);
191 else if (SCM_INUMP (prot
))
193 i
= sizeof (long) * k
;
194 if (SCM_INUM (prot
) > 0)
195 type
= scm_tc7_uvect
;
197 type
= scm_tc7_ivect
;
199 else if (SCM_SYMBOLP (prot
) && (1 == SCM_SYMBOL_LENGTH (prot
)))
203 s
= SCM_SYMBOL_CHARS (prot
)[0];
206 i
= sizeof (short) * k
;
207 type
= scm_tc7_svect
;
209 #ifdef HAVE_LONG_LONGS
212 i
= sizeof (long_long
) * k
;
213 type
= scm_tc7_llvect
;
218 return scm_c_make_vector (k
, SCM_UNDEFINED
);
221 else if (!SCM_INEXACTP (prot
))
222 /* Huge non-unif vectors are NOT supported. */
223 /* no special scm_vector */
224 return scm_c_make_vector (k
, SCM_UNDEFINED
);
225 else if (singp (prot
))
227 i
= sizeof (float) * k
;
228 type
= scm_tc7_fvect
;
230 else if (SCM_COMPLEXP (prot
))
232 i
= 2 * sizeof (double) * k
;
233 type
= scm_tc7_cvect
;
237 i
= sizeof (double) * k
;
238 type
= scm_tc7_dvect
;
241 SCM_ASSERT_RANGE (1, scm_long2num (k
), k
<= SCM_UVECTOR_MAX_LENGTH
);
245 SCM_SET_UVECTOR_BASE (v
, (char *) scm_must_malloc (i
? i
: 1, "vector"));
246 SCM_SET_UVECTOR_LENGTH (v
, k
, type
);
253 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
255 "Returns the number of elements in @var{uve}.")
256 #define FUNC_NAME s_scm_uniform_vector_length
258 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
262 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
265 return SCM_MAKINUM (SCM_VECTOR_LENGTH (v
));
267 return SCM_MAKINUM (SCM_STRING_LENGTH (v
));
269 return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v
));
277 #ifdef HAVE_LONG_LONGS
280 return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v
));
285 SCM_DEFINE (scm_array_p
, "array?", 1, 1, 0,
287 "Returns @code{#t} if the @var{obj} is an array, and @code{#f} if not.\n\n"
288 "The @var{prototype} argument is used with uniform arrays and is described\n"
290 #define FUNC_NAME s_scm_array_p
294 nprot
= SCM_UNBNDP (prot
);
299 while (SCM_TYP7 (v
) == scm_tc7_smob
)
310 return SCM_BOOL(nprot
);
315 switch (SCM_TYP7 (v
))
318 protp
= (SCM_EQ_P (prot
, SCM_BOOL_T
));
320 protp
= SCM_CHARP(prot
) && (SCM_CHAR (prot
) != '\0');
322 protp
= SCM_EQ_P (prot
, SCM_MAKE_CHAR ('\0'));
324 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)>0;
326 protp
= SCM_INUMP(prot
) && SCM_INUM(prot
)<=0;
329 protp
= SCM_SYMBOLP (prot
)
330 && (1 == SCM_SYMBOL_LENGTH (prot
))
331 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
332 #ifdef HAVE_LONG_LONGS
334 protp
= SCM_SYMBOLP (prot
)
335 && (1 == SCM_SYMBOL_LENGTH (prot
))
336 && ('s' == SCM_SYMBOL_CHARS (prot
)[0]);
339 protp
= singp (prot
);
341 protp
= SCM_REALP(prot
);
343 protp
= SCM_COMPLEXP(prot
);
346 protp
= SCM_NULLP(prot
);
351 return SCM_BOOL(protp
);
357 SCM_DEFINE (scm_array_rank
, "array-rank", 1, 0, 0,
359 "Returns the number of dimensions of @var{obj}. If @var{obj} is not an\n"
360 "array, @code{0} is returned.")
361 #define FUNC_NAME s_scm_array_rank
365 switch (SCM_TYP7 (ra
))
378 #ifdef HAVE_LONG_LONGS
382 return SCM_MAKINUM (1L);
385 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra
));
392 SCM_DEFINE (scm_array_dimensions
, "array-dimensions", 1, 0, 0,
394 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
395 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
397 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
399 #define FUNC_NAME s_scm_array_dimensions
406 switch (SCM_TYP7 (ra
))
421 #ifdef HAVE_LONG_LONGS
424 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
426 if (!SCM_ARRAYP (ra
))
428 k
= SCM_ARRAY_NDIM (ra
);
429 s
= SCM_ARRAY_DIMS (ra
);
431 res
= scm_cons (s
[k
].lbnd
432 ? scm_cons2 (SCM_MAKINUM (s
[k
].lbnd
),
433 SCM_MAKINUM (s
[k
].ubnd
),
435 : SCM_MAKINUM (1 + s
[k
].ubnd
),
443 SCM_DEFINE (scm_shared_array_root
, "shared-array-root", 1, 0, 0,
445 "Return the root vector of a shared array.")
446 #define FUNC_NAME s_scm_shared_array_root
448 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
449 return SCM_ARRAY_V (ra
);
454 SCM_DEFINE (scm_shared_array_offset
, "shared-array-offset", 1, 0, 0,
456 "Return the root vector index of the first element in the array.")
457 #define FUNC_NAME s_scm_shared_array_offset
459 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
460 return SCM_MAKINUM (SCM_ARRAY_BASE (ra
));
465 SCM_DEFINE (scm_shared_array_increments
, "shared-array-increments", 1, 0, 0,
467 "For each dimension, return the distance between elements in the root vector.")
468 #define FUNC_NAME s_scm_shared_array_increments
473 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
474 k
= SCM_ARRAY_NDIM (ra
);
475 s
= SCM_ARRAY_DIMS (ra
);
477 res
= scm_cons (SCM_MAKINUM (s
[k
].inc
), res
);
483 static char s_bad_ind
[] = "Bad scm_array index";
487 scm_aind (SCM ra
, SCM args
, const char *what
)
488 #define FUNC_NAME what
492 register scm_sizet pos
= SCM_ARRAY_BASE (ra
);
493 register scm_sizet k
= SCM_ARRAY_NDIM (ra
);
494 scm_array_dim
*s
= SCM_ARRAY_DIMS (ra
);
495 if (SCM_INUMP (args
))
498 scm_error_num_args_subr (what
);
499 return pos
+ (SCM_INUM (args
) - s
->lbnd
) * (s
->inc
);
501 while (k
&& SCM_NIMP (args
))
503 ind
= SCM_CAR (args
);
504 args
= SCM_CDR (args
);
505 if (!SCM_INUMP (ind
))
506 scm_misc_error (what
, s_bad_ind
, SCM_EOL
);
508 if (j
< s
->lbnd
|| j
> s
->ubnd
)
509 scm_out_of_range (what
, ind
);
510 pos
+= (j
- s
->lbnd
) * (s
->inc
);
514 if (k
!= 0 || !SCM_NULLP (args
))
515 scm_error_num_args_subr (what
);
523 scm_make_ra (int ndim
)
528 SCM_NEWSMOB(ra
, ((long) ndim
<< 17) + scm_tc16_array
,
529 scm_must_malloc ((long) (sizeof (scm_array
) + ndim
* sizeof (scm_array_dim
)),
531 SCM_ARRAY_V (ra
) = scm_nullvect
;
536 static char s_bad_spec
[] = "Bad scm_array dimension";
537 /* Increments will still need to be set. */
541 scm_shap2ra (SCM args
, const char *what
)
545 int ndim
= scm_ilength (args
);
547 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
549 ra
= scm_make_ra (ndim
);
550 SCM_ARRAY_BASE (ra
) = 0;
551 s
= SCM_ARRAY_DIMS (ra
);
552 for (; !SCM_NULLP (args
); s
++, args
= SCM_CDR (args
))
554 spec
= SCM_CAR (args
);
555 if (SCM_INUMP (spec
))
557 if (SCM_INUM (spec
) < 0)
558 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
560 s
->ubnd
= SCM_INUM (spec
) - 1;
565 if (!SCM_CONSP (spec
) || !SCM_INUMP (SCM_CAR (spec
)))
566 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
567 s
->lbnd
= SCM_INUM (SCM_CAR (spec
));
570 || !SCM_INUMP (SCM_CAR (sp
))
571 || !SCM_NULLP (SCM_CDR (sp
)))
572 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
573 s
->ubnd
= SCM_INUM (SCM_CAR (sp
));
580 SCM_DEFINE (scm_dimensions_to_uniform_array
, "dimensions->uniform-array", 2, 1, 0,
581 (SCM dims
, SCM prot
, SCM fill
),
582 "@deffnx primitive make-uniform-vector length prototype [fill]\n"
583 "Creates and returns a uniform array or vector of type corresponding to\n"
584 "@var{prototype} with dimensions @var{dims} or length @var{length}. If\n"
585 "@var{fill} is supplied, it's used to fill the array, otherwise \n"
586 "@var{prototype} is used.")
587 #define FUNC_NAME s_scm_dimensions_to_uniform_array
590 unsigned long int rlen
= 1;
593 if (SCM_INUMP (dims
))
595 SCM answer
= scm_make_uve (SCM_INUM (dims
), prot
);
596 if (!SCM_UNBNDP (fill
))
597 scm_array_fill_x (answer
, fill
);
598 else if (SCM_SYMBOLP (prot
))
599 scm_array_fill_x (answer
, SCM_MAKINUM (0));
601 scm_array_fill_x (answer
, prot
);
604 SCM_ASSERT (SCM_NULLP (dims
) || SCM_CONSP (dims
),
605 dims
, SCM_ARG1
, FUNC_NAME
);
606 ra
= scm_shap2ra (dims
, FUNC_NAME
);
607 SCM_SETOR_CAR (ra
, SCM_ARRAY_CONTIGUOUS
);
608 s
= SCM_ARRAY_DIMS (ra
);
609 k
= SCM_ARRAY_NDIM (ra
);
613 SCM_ASSERT_RANGE (1, dims
, s
[k
].lbnd
<= s
[k
].ubnd
);
614 rlen
= (s
[k
].ubnd
- s
[k
].lbnd
+ 1) * s
[k
].inc
;
617 SCM_ARRAY_V (ra
) = scm_make_uve (rlen
, prot
);
619 if (!SCM_UNBNDP (fill
))
620 scm_array_fill_x (ra
, fill
);
621 else if (SCM_SYMBOLP (prot
))
622 scm_array_fill_x (ra
, SCM_MAKINUM (0));
624 scm_array_fill_x (ra
, prot
);
626 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
627 if (s
->ubnd
< s
->lbnd
|| (0 == s
->lbnd
&& 1 == s
->inc
))
628 return SCM_ARRAY_V (ra
);
635 scm_ra_set_contp (SCM ra
)
637 scm_sizet k
= SCM_ARRAY_NDIM (ra
);
640 long inc
= SCM_ARRAY_DIMS (ra
)[k
- 1].inc
;
643 if (inc
!= SCM_ARRAY_DIMS (ra
)[k
].inc
)
645 SCM_SETAND_CAR (ra
, ~SCM_ARRAY_CONTIGUOUS
);
648 inc
*= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
649 - SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
652 SCM_SETOR_CAR (ra
, SCM_ARRAY_CONTIGUOUS
);
656 SCM_DEFINE (scm_make_shared_array
, "make-shared-array", 2, 0, 1,
657 (SCM oldra
, SCM mapfunc
, SCM dims
),
658 "@code{make-shared-array} can be used to create shared subarrays of other\n"
659 "arrays. The @var{mapper} is a function that translates coordinates in\n"
660 "the new array into coordinates in the old array. A @var{mapper} must be\n"
661 "linear, and its range must stay within the bounds of the old array, but\n"
662 "it can be otherwise arbitrary. A simple example:\n"
664 "(define fred (make-array #f 8 8))\n"
665 "(define freds-diagonal\n"
666 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
667 "(array-set! freds-diagonal 'foo 3)\n"
668 "(array-ref fred 3 3) @result{} foo\n"
669 "(define freds-center\n"
670 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
671 "(array-ref freds-center 0 0) @result{} foo\n"
673 #define FUNC_NAME s_scm_make_shared_array
679 long old_min
, new_min
, old_max
, new_max
;
682 SCM_VALIDATE_REST_ARGUMENT (dims
);
683 SCM_VALIDATE_ARRAY (1,oldra
);
684 SCM_VALIDATE_PROC (2,mapfunc
);
685 ra
= scm_shap2ra (dims
, FUNC_NAME
);
686 if (SCM_ARRAYP (oldra
))
688 SCM_ARRAY_V (ra
) = SCM_ARRAY_V (oldra
);
689 old_min
= old_max
= SCM_ARRAY_BASE (oldra
);
690 s
= SCM_ARRAY_DIMS (oldra
);
691 k
= SCM_ARRAY_NDIM (oldra
);
695 old_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
697 old_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
702 SCM_ARRAY_V (ra
) = oldra
;
704 old_max
= SCM_INUM (scm_uniform_vector_length (oldra
)) - 1;
707 s
= SCM_ARRAY_DIMS (ra
);
708 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
710 inds
= scm_cons (SCM_MAKINUM (s
[k
].lbnd
), inds
);
711 if (s
[k
].ubnd
< s
[k
].lbnd
)
713 if (1 == SCM_ARRAY_NDIM (ra
))
714 ra
= scm_make_uve (0L, scm_array_prototype (ra
));
716 SCM_ARRAY_V (ra
) = scm_make_uve (0L, scm_array_prototype (ra
));
720 imap
= scm_apply (mapfunc
, scm_reverse (inds
), SCM_EOL
);
721 if (SCM_ARRAYP (oldra
))
722 i
= (scm_sizet
) scm_aind (oldra
, imap
, FUNC_NAME
);
725 if (SCM_NINUMP (imap
))
728 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
729 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
730 imap
= SCM_CAR (imap
);
734 SCM_ARRAY_BASE (ra
) = new_min
= new_max
= i
;
736 k
= SCM_ARRAY_NDIM (ra
);
739 if (s
[k
].ubnd
> s
[k
].lbnd
)
741 SCM_SETCAR (indptr
, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr
)) + 1));
742 imap
= scm_apply (mapfunc
, scm_reverse (inds
), SCM_EOL
);
743 if (SCM_ARRAYP (oldra
))
745 s
[k
].inc
= scm_aind (oldra
, imap
, FUNC_NAME
) - i
;
748 if (SCM_NINUMP (imap
))
750 if (scm_ilength (imap
) != 1 || !SCM_INUMP (SCM_CAR (imap
)))
751 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
752 imap
= SCM_CAR (imap
);
754 s
[k
].inc
= (long) SCM_INUM (imap
) - i
;
758 new_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
760 new_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
763 s
[k
].inc
= new_max
- new_min
+ 1; /* contiguous by default */
764 indptr
= SCM_CDR (indptr
);
766 if (old_min
> new_min
|| old_max
< new_max
)
767 SCM_MISC_ERROR ("mapping out of range", SCM_EOL
);
768 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
770 SCM v
= SCM_ARRAY_V (ra
);
771 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
772 if (1 == s
->inc
&& 0 == s
->lbnd
&& length
== 1 + s
->ubnd
)
774 if (s
->ubnd
< s
->lbnd
)
775 return scm_make_uve (0L, scm_array_prototype (ra
));
777 scm_ra_set_contp (ra
);
783 /* args are RA . DIMS */
784 SCM_DEFINE (scm_transpose_array
, "transpose-array", 1, 0, 1,
786 "Returns an array sharing contents with @var{array}, but with dimensions\n"
787 "arranged in a different order. There must be one @var{dim} argument for\n"
788 "each dimension of @var{array}. @var{dim0}, @var{dim1}, @dots{} should\n"
789 "be integers between 0 and the rank of the array to be returned. Each\n"
790 "integer in that range must appear at least once in the argument list.\n\n"
791 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to dimensions\n"
792 "in the array to be returned, their positions in the argument list to\n"
793 "dimensions of @var{array}. Several @var{dim}s may have the same value,\n"
794 "in which case the returned array will have smaller rank than\n"
798 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
799 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
800 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
801 " #2((a 4) (b 5) (c 6))\n"
803 #define FUNC_NAME s_scm_transpose_array
805 SCM res
, vargs
, *ve
= &vargs
;
806 scm_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 #ifdef HAVE_LONG_LONGS
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_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 #ifdef HAVE_LONG_LONGS
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 "Returns @code{#t} if its arguments would be acceptable to array-ref.")
995 #define FUNC_NAME s_scm_array_in_bounds_p
999 register scm_sizet k
;
1003 SCM_VALIDATE_REST_ARGUMENT (args
);
1004 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1005 if (SCM_NIMP (args
))
1008 ind
= SCM_CAR (args
);
1009 args
= SCM_CDR (args
);
1010 SCM_ASSERT (SCM_INUMP (ind
), ind
, SCM_ARG2
, FUNC_NAME
);
1011 pos
= SCM_INUM (ind
);
1017 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1018 wna
: SCM_WRONG_NUM_ARGS ();
1020 k
= SCM_ARRAY_NDIM (v
);
1021 s
= SCM_ARRAY_DIMS (v
);
1022 pos
= SCM_ARRAY_BASE (v
);
1025 SCM_ASRTGO (SCM_NULLP (ind
), wna
);
1032 if (!(j
>= (s
->lbnd
) && j
<= (s
->ubnd
)))
1034 SCM_ASRTGO (--k
== scm_ilength (args
), wna
);
1037 pos
+= (j
- s
->lbnd
) * (s
->inc
);
1038 if (!(--k
&& SCM_NIMP (args
)))
1040 ind
= SCM_CAR (args
);
1041 args
= SCM_CDR (args
);
1043 if (!SCM_INUMP (ind
))
1044 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
1046 SCM_ASRTGO (0 == k
, wna
);
1047 v
= SCM_ARRAY_V (v
);
1050 case scm_tc7_string
:
1051 case scm_tc7_byvect
:
1058 #ifdef HAVE_LONG_LONGS
1059 case scm_tc7_llvect
:
1061 case scm_tc7_vector
:
1064 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
1065 SCM_ASRTGO (SCM_NULLP (args
) && SCM_INUMP (ind
), wna
);
1066 return SCM_BOOL(pos
>= 0 && pos
< length
);
1073 SCM_REGISTER_PROC(s_array_ref
, "array-ref", 1, 0, 1, scm_uniform_vector_ref
);
1076 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
1078 "@deffnx primitive array-ref v . args\n"
1079 "Returns the element at the @code{(index1, index2)} element in @var{array}.")
1080 #define FUNC_NAME s_scm_uniform_vector_ref
1086 SCM_ASRTGO (SCM_NULLP (args
), badarg
);
1089 else if (SCM_ARRAYP (v
))
1091 pos
= scm_aind (v
, args
, FUNC_NAME
);
1092 v
= SCM_ARRAY_V (v
);
1096 unsigned long int length
;
1097 if (SCM_NIMP (args
))
1099 SCM_ASSERT (SCM_CONSP (args
) && SCM_INUMP (SCM_CAR (args
)), args
, SCM_ARG2
, FUNC_NAME
);
1100 pos
= SCM_INUM (SCM_CAR (args
));
1101 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args
)), wna
);
1105 SCM_VALIDATE_INUM (2,args
);
1106 pos
= SCM_INUM (args
);
1108 length
= SCM_INUM (scm_uniform_vector_length (v
));
1109 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1114 if (SCM_NULLP (args
))
1117 SCM_WRONG_TYPE_ARG (1, v
);
1121 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (pos
));
1123 SCM_WRONG_NUM_ARGS ();
1126 int k
= SCM_ARRAY_NDIM (v
);
1127 SCM res
= scm_make_ra (k
);
1128 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1129 SCM_ARRAY_BASE (res
) = pos
;
1132 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1133 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1134 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1139 if (SCM_BITVEC_REF (v
, pos
))
1143 case scm_tc7_string
:
1144 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1145 case scm_tc7_byvect
:
1146 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1148 return scm_ulong2num (((unsigned long *) SCM_VELTS (v
))[pos
]);
1150 return scm_long2num(((signed long *) SCM_VELTS (v
))[pos
]);
1153 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1154 #ifdef HAVE_LONG_LONGS
1155 case scm_tc7_llvect
:
1156 return scm_long_long2num (((long_long
*) SCM_CELL_WORD_1 (v
))[pos
]);
1160 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1162 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1164 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1165 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1166 case scm_tc7_vector
:
1168 return SCM_VELTS (v
)[pos
];
1173 /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1174 tries to recycle conses. (Make *sure* you want them recycled.) */
1177 scm_cvref (SCM v
, scm_sizet pos
, SCM last
)
1178 #define FUNC_NAME "scm_cvref"
1183 SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1185 if (SCM_BITVEC_REF(v
,pos
))
1189 case scm_tc7_string
:
1190 return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v
)[pos
]);
1191 case scm_tc7_byvect
:
1192 return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v
))[pos
]);
1194 return scm_ulong2num(((unsigned long *) SCM_VELTS (v
))[pos
]);
1196 return scm_long2num(((signed long *) SCM_VELTS (v
))[pos
]);
1198 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v
))[pos
]);
1199 #ifdef HAVE_LONG_LONGS
1200 case scm_tc7_llvect
:
1201 return scm_long_long2num (((long_long
*) SCM_CELL_WORD_1 (v
))[pos
]);
1204 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1206 SCM_REAL_VALUE (last
) = ((float *) SCM_CELL_WORD_1 (v
))[pos
];
1209 return scm_make_real (((float *) SCM_CELL_WORD_1 (v
))[pos
]);
1211 if (SCM_NIMP (last
) && !SCM_EQ_P (last
, scm_flo0
) && SCM_SLOPPY_REALP (last
))
1213 SCM_REAL_VALUE (last
) = ((double *) SCM_CELL_WORD_1 (v
))[pos
];
1216 return scm_make_real (((double *) SCM_CELL_WORD_1 (v
))[pos
]);
1218 if (SCM_NIMP (last
) && SCM_SLOPPY_COMPLEXP (last
))
1220 SCM_COMPLEX_REAL (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
];
1221 SCM_COMPLEX_IMAG (last
) = ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1];
1224 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v
))[2 * pos
],
1225 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1]);
1226 case scm_tc7_vector
:
1228 return SCM_VELTS (v
)[pos
];
1230 { /* enclosed scm_array */
1231 int k
= SCM_ARRAY_NDIM (v
);
1232 SCM res
= scm_make_ra (k
);
1233 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1234 SCM_ARRAY_BASE (res
) = pos
;
1237 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1238 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1239 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1248 SCM_REGISTER_PROC(s_uniform_array_set1_x
, "uniform-array-set1!", 3, 0, 0, scm_array_set_x
);
1251 /* Note that args may be a list or an immediate object, depending which
1252 PROC is used (and it's called from C too). */
1253 SCM_DEFINE (scm_array_set_x
, "array-set!", 2, 0, 1,
1254 (SCM v
, SCM obj
, SCM args
),
1255 "@deffnx primitive uniform-array-set1! v obj args\n"
1256 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1257 "@var{new-value}. The value returned by array-set! is unspecified.")
1258 #define FUNC_NAME s_scm_array_set_x
1262 SCM_VALIDATE_REST_ARGUMENT (args
);
1263 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1266 pos
= scm_aind (v
, args
, FUNC_NAME
);
1267 v
= SCM_ARRAY_V (v
);
1271 unsigned long int length
;
1272 if (SCM_NIMP (args
))
1274 SCM_ASSERT (SCM_CONSP(args
) && SCM_INUMP (SCM_CAR (args
)), args
,
1275 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 SCM_VELTS(v
)[pos
] = SCM_PACK (scm_num2ulong(obj
, (char *)SCM_ARG2
, FUNC_NAME
));
1319 SCM_VELTS(v
)[pos
] = SCM_PACK (scm_num2long(obj
, (char *)SCM_ARG2
, FUNC_NAME
));
1322 SCM_ASRTGO (SCM_INUMP (obj
), badobj
);
1323 ((short *) SCM_CELL_WORD_1 (v
))[pos
] = SCM_INUM (obj
);
1325 #ifdef HAVE_LONG_LONGS
1326 case scm_tc7_llvect
:
1327 ((long_long
*) SCM_CELL_WORD_1 (v
))[pos
] = scm_num2long_long (obj
, (char *)SCM_ARG2
, FUNC_NAME
);
1333 ((float *) SCM_CELL_WORD_1 (v
))[pos
] = (float) scm_num2dbl (obj
, FUNC_NAME
);
1336 ((double *) SCM_CELL_WORD_1 (v
))[pos
] = scm_num2dbl (obj
, FUNC_NAME
);
1339 SCM_ASRTGO (SCM_INEXACTP (obj
), badobj
);
1340 if (SCM_REALP (obj
)) {
1341 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
] = SCM_REAL_VALUE (obj
);
1342 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1] = 0.0;
1344 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
] = SCM_COMPLEX_REAL (obj
);
1345 ((double *) SCM_CELL_WORD_1 (v
))[2 * pos
+ 1] = SCM_COMPLEX_IMAG (obj
);
1348 case scm_tc7_vector
:
1350 SCM_VELTS (v
)[pos
] = obj
;
1353 return SCM_UNSPECIFIED
;
1357 /* attempts to unroll an array into a one-dimensional array.
1358 returns the unrolled array or #f if it can't be done. */
1359 /* if strict is not SCM_UNDEFINED, return #f if returned array
1360 wouldn't have contiguous elements. */
1361 SCM_DEFINE (scm_array_contents
, "array-contents", 1, 1, 0,
1362 (SCM ra
, SCM strict
),
1363 "@deffnx primitive array-contents array strict\n"
1364 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1365 "without changing their order (last subscript changing fastest), then\n"
1366 "@code{array-contents} returns that shared array, otherwise it returns\n"
1367 "@code{#f}. All arrays made by @var{make-array} and\n"
1368 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1369 "@var{make-shared-array} may not be.\n\n"
1370 "If the optional argument @var{strict} is provided, a shared array will\n"
1371 "be returned only if its elements are stored internally contiguous in\n"
1373 #define FUNC_NAME s_scm_array_contents
1378 switch SCM_TYP7 (ra
)
1382 case scm_tc7_vector
:
1384 case scm_tc7_string
:
1386 case scm_tc7_byvect
:
1393 #ifdef HAVE_LONG_LONGS
1394 case scm_tc7_llvect
:
1399 scm_sizet k
, ndim
= SCM_ARRAY_NDIM (ra
), len
= 1;
1400 if (!SCM_ARRAYP (ra
) || !SCM_ARRAY_CONTP (ra
))
1402 for (k
= 0; k
< ndim
; k
++)
1403 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1404 if (!SCM_UNBNDP (strict
))
1406 if (ndim
&& (1 != SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
))
1408 if (scm_tc7_bvect
== SCM_TYP7 (SCM_ARRAY_V (ra
)))
1410 if (len
!= SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) ||
1411 SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
||
1418 SCM v
= SCM_ARRAY_V (ra
);
1419 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (v
));
1420 if ((len
== length
) && 0 == SCM_ARRAY_BASE (ra
) && SCM_ARRAY_DIMS (ra
)->inc
)
1424 sra
= scm_make_ra (1);
1425 SCM_ARRAY_DIMS (sra
)->lbnd
= 0;
1426 SCM_ARRAY_DIMS (sra
)->ubnd
= len
- 1;
1427 SCM_ARRAY_V (sra
) = SCM_ARRAY_V (ra
);
1428 SCM_ARRAY_BASE (sra
) = SCM_ARRAY_BASE (ra
);
1429 SCM_ARRAY_DIMS (sra
)->inc
= (ndim
? SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
: 1);
1438 scm_ra2contig (SCM ra
, int copy
)
1442 scm_sizet k
, len
= 1;
1443 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
1444 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1445 k
= SCM_ARRAY_NDIM (ra
);
1446 if (SCM_ARRAY_CONTP (ra
) && ((0 == k
) || (1 == SCM_ARRAY_DIMS (ra
)[k
- 1].inc
)))
1448 if (scm_tc7_bvect
!= SCM_TYP7 (SCM_ARRAY_V (ra
)))
1450 if ((len
== SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) &&
1451 0 == SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
&&
1452 0 == len
% SCM_LONG_BIT
))
1455 ret
= scm_make_ra (k
);
1456 SCM_ARRAY_BASE (ret
) = 0;
1459 SCM_ARRAY_DIMS (ret
)[k
].lbnd
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
;
1460 SCM_ARRAY_DIMS (ret
)[k
].ubnd
= SCM_ARRAY_DIMS (ra
)[k
].ubnd
;
1461 SCM_ARRAY_DIMS (ret
)[k
].inc
= inc
;
1462 inc
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1464 SCM_ARRAY_V (ret
) = scm_make_uve ((inc
- 1), scm_array_prototype (ra
));
1466 scm_array_copy_x (ra
, ret
);
1472 SCM_DEFINE (scm_uniform_array_read_x
, "uniform-array-read!", 1, 3, 0,
1473 (SCM ra
, SCM port_or_fd
, SCM start
, SCM end
),
1474 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1475 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1476 "binary objects from @var{port-or-fdes}.\n"
1477 "If an end of file is encountered during\n"
1478 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1479 "(starting at the beginning) and the remainder of the array is\n"
1481 "The optional arguments @var{start} and @var{end} allow\n"
1482 "a specified region of a vector (or linearized array) to be read,\n"
1483 "leaving the remainder of the vector unchanged.\n\n"
1484 "@code{uniform-array-read!} returns the number of objects read.\n"
1485 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1486 "returned by @code{(current-input-port)}.")
1487 #define FUNC_NAME s_scm_uniform_array_read_x
1489 SCM cra
= SCM_UNDEFINED
, v
= ra
;
1496 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1497 if (SCM_UNBNDP (port_or_fd
))
1498 port_or_fd
= scm_cur_inp
;
1500 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1501 || (SCM_OPINPORTP (port_or_fd
)),
1502 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1503 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1509 badarg1
:SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1511 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1512 cra
= scm_ra2contig (ra
, 0);
1513 cstart
+= SCM_ARRAY_BASE (cra
);
1514 vlen
= SCM_ARRAY_DIMS (cra
)->inc
*
1515 (SCM_ARRAY_DIMS (cra
)->ubnd
- SCM_ARRAY_DIMS (cra
)->lbnd
+ 1);
1516 v
= SCM_ARRAY_V (cra
);
1518 case scm_tc7_string
:
1519 base
= SCM_STRING_CHARS (v
);
1523 base
= (char *) SCM_BITVECTOR_BASE (v
);
1524 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1525 cstart
/= SCM_LONG_BIT
;
1528 case scm_tc7_byvect
:
1529 base
= (char *) SCM_UVECTOR_BASE (v
);
1534 base
= (char *) SCM_UVECTOR_BASE (v
);
1538 base
= (char *) SCM_UVECTOR_BASE (v
);
1539 sz
= sizeof (short);
1541 #ifdef HAVE_LONG_LONGS
1542 case scm_tc7_llvect
:
1543 base
= (char *) SCM_UVECTOR_BASE (v
);
1544 sz
= sizeof (long_long
);
1548 base
= (char *) SCM_UVECTOR_BASE (v
);
1549 sz
= sizeof (float);
1552 base
= (char *) SCM_UVECTOR_BASE (v
);
1553 sz
= sizeof (double);
1556 base
= (char *) SCM_UVECTOR_BASE (v
);
1557 sz
= 2 * sizeof (double);
1562 if (!SCM_UNBNDP (start
))
1565 SCM_NUM2LONG (3, start
);
1567 if (offset
< 0 || offset
>= cend
)
1568 scm_out_of_range (FUNC_NAME
, start
);
1570 if (!SCM_UNBNDP (end
))
1573 SCM_NUM2LONG (4, end
);
1575 if (tend
<= offset
|| tend
> cend
)
1576 scm_out_of_range (FUNC_NAME
, end
);
1581 if (SCM_NIMP (port_or_fd
))
1583 scm_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
1584 int remaining
= (cend
- offset
) * sz
;
1585 char *dest
= base
+ (cstart
+ offset
) * sz
;
1587 if (pt
->rw_active
== SCM_PORT_WRITE
)
1588 scm_flush (port_or_fd
);
1590 ans
= cend
- offset
;
1591 while (remaining
> 0)
1593 if (pt
->read_pos
< pt
->read_end
)
1595 int to_copy
= min (pt
->read_end
- pt
->read_pos
,
1598 memcpy (dest
, pt
->read_pos
, to_copy
);
1599 pt
->read_pos
+= to_copy
;
1600 remaining
-= to_copy
;
1605 if (scm_fill_input (port_or_fd
) == EOF
)
1607 if (remaining
% sz
!= 0)
1609 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
1611 ans
-= remaining
/ sz
;
1618 pt
->rw_active
= SCM_PORT_READ
;
1620 else /* file descriptor. */
1622 SCM_SYSCALL (ans
= read (SCM_INUM (port_or_fd
),
1623 base
+ (cstart
+ offset
) * sz
,
1624 (scm_sizet
) (sz
* (cend
- offset
))));
1628 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1629 ans
*= SCM_LONG_BIT
;
1631 if (!SCM_EQ_P (v
, ra
) && !SCM_EQ_P (cra
, ra
))
1632 scm_array_copy_x (cra
, ra
);
1634 return SCM_MAKINUM (ans
);
1638 SCM_DEFINE (scm_uniform_array_write
, "uniform-array-write", 1, 3, 0,
1639 (SCM v
, SCM port_or_fd
, SCM start
, SCM end
),
1640 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1641 "Writes all elements of @var{ura} as binary objects to\n"
1642 "@var{port-or-fdes}.\n\n"
1643 "The optional arguments @var{start}\n"
1644 "and @var{end} allow\n"
1645 "a specified region of a vector (or linearized array) to be written.\n\n"
1646 "The number of objects actually written is returned. \n"
1647 "@var{port-or-fdes} may be\n"
1648 "omitted, in which case it defaults to the value returned by\n"
1649 "@code{(current-output-port)}.")
1650 #define FUNC_NAME s_scm_uniform_array_write
1658 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
1660 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1661 if (SCM_UNBNDP (port_or_fd
))
1662 port_or_fd
= scm_cur_outp
;
1664 SCM_ASSERT (SCM_INUMP (port_or_fd
)
1665 || (SCM_OPOUTPORTP (port_or_fd
)),
1666 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1667 vlen
= SCM_INUM (scm_uniform_vector_length (v
));
1673 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1675 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1676 v
= scm_ra2contig (v
, 1);
1677 cstart
= SCM_ARRAY_BASE (v
);
1678 vlen
= SCM_ARRAY_DIMS (v
)->inc
1679 * (SCM_ARRAY_DIMS (v
)->ubnd
- SCM_ARRAY_DIMS (v
)->lbnd
+ 1);
1680 v
= SCM_ARRAY_V (v
);
1682 case scm_tc7_string
:
1683 base
= SCM_STRING_CHARS (v
);
1687 base
= (char *) SCM_BITVECTOR_BASE (v
);
1688 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1689 cstart
/= SCM_LONG_BIT
;
1692 case scm_tc7_byvect
:
1693 base
= (char *) SCM_UVECTOR_BASE (v
);
1698 base
= (char *) SCM_UVECTOR_BASE (v
);
1702 base
= (char *) SCM_UVECTOR_BASE (v
);
1703 sz
= sizeof (short);
1705 #ifdef HAVE_LONG_LONGS
1706 case scm_tc7_llvect
:
1707 base
= (char *) SCM_UVECTOR_BASE (v
);
1708 sz
= sizeof (long_long
);
1712 base
= (char *) SCM_UVECTOR_BASE (v
);
1713 sz
= sizeof (float);
1716 base
= (char *) SCM_UVECTOR_BASE (v
);
1717 sz
= sizeof (double);
1720 base
= (char *) SCM_UVECTOR_BASE (v
);
1721 sz
= 2 * sizeof (double);
1726 if (!SCM_UNBNDP (start
))
1729 SCM_NUM2LONG (3, start
);
1731 if (offset
< 0 || offset
>= cend
)
1732 scm_out_of_range (FUNC_NAME
, start
);
1734 if (!SCM_UNBNDP (end
))
1737 SCM_NUM2LONG (4, end
);
1739 if (tend
<= offset
|| tend
> cend
)
1740 scm_out_of_range (FUNC_NAME
, end
);
1745 if (SCM_NIMP (port_or_fd
))
1747 char *source
= base
+ (cstart
+ offset
) * sz
;
1749 ans
= cend
- offset
;
1750 scm_lfwrite (source
, ans
* sz
, port_or_fd
);
1752 else /* file descriptor. */
1754 SCM_SYSCALL (ans
= write (SCM_INUM (port_or_fd
),
1755 base
+ (cstart
+ offset
) * sz
,
1756 (scm_sizet
) (sz
* (cend
- offset
))));
1760 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1761 ans
*= SCM_LONG_BIT
;
1763 return SCM_MAKINUM (ans
);
1768 static char cnt_tab
[16] =
1769 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1771 SCM_DEFINE (scm_bit_count
, "bit-count", 2, 0, 0,
1772 (SCM b
, SCM bitvector
),
1773 "Returns the number of occurrences of the boolean @var{b} in\n"
1775 #define FUNC_NAME s_scm_bit_count
1777 SCM_VALIDATE_BOOL (1, b
);
1778 SCM_ASSERT (SCM_BITVECTOR_P (bitvector
), bitvector
, 2, FUNC_NAME
);
1779 if (SCM_BITVECTOR_LENGTH (bitvector
) == 0) {
1782 unsigned long int count
= 0;
1783 unsigned long int i
= (SCM_BITVECTOR_LENGTH (bitvector
) - 1) / SCM_LONG_BIT
;
1784 unsigned long int w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1785 if (SCM_FALSEP (b
)) {
1788 w
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (bitvector
) - 1) % SCM_LONG_BIT
);
1791 count
+= cnt_tab
[w
& 0x0f];
1795 return SCM_MAKINUM (count
);
1798 w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1799 if (SCM_FALSEP (b
)) {
1809 SCM_DEFINE (scm_bit_position
, "bit-position", 3, 0, 0,
1810 (SCM item
, SCM v
, SCM k
),
1811 "Returns the minimum index of an occurrence of @var{bool} in @var{bv}\n"
1812 "which is at least @var{k}. If no @var{bool} occurs within the specified\n"
1813 "range @code{#f} is returned.")
1814 #define FUNC_NAME s_scm_bit_position
1816 long i
, lenw
, xbits
, pos
;
1817 register unsigned long w
;
1819 SCM_VALIDATE_BOOL (1, item
);
1820 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG2
, FUNC_NAME
);
1821 SCM_VALIDATE_INUM_COPY (3,k
,pos
);
1822 SCM_ASSERT_RANGE (3, k
, (pos
<= SCM_BITVECTOR_LENGTH (v
)) && (pos
>= 0));
1824 if (pos
== SCM_BITVECTOR_LENGTH (v
))
1827 lenw
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; /* watch for part words */
1828 i
= pos
/ SCM_LONG_BIT
;
1829 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1830 if (SCM_FALSEP (item
))
1832 xbits
= (pos
% SCM_LONG_BIT
);
1834 w
= ((w
>> xbits
) << xbits
);
1835 xbits
= SCM_LONG_BIT
- 1 - (SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
;
1838 if (w
&& (i
== lenw
))
1839 w
= ((w
<< xbits
) >> xbits
);
1845 return SCM_MAKINUM (pos
);
1850 return SCM_MAKINUM (pos
+ 1);
1853 return SCM_MAKINUM (pos
+ 2);
1855 return SCM_MAKINUM (pos
+ 3);
1862 pos
+= SCM_LONG_BIT
;
1863 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1864 if (SCM_FALSEP (item
))
1872 SCM_DEFINE (scm_bit_set_star_x
, "bit-set*!", 3, 0, 0,
1873 (SCM v
, SCM kv
, SCM obj
),
1874 "If uve is a bit-vector @var{bv} and uve must be of the same\n"
1875 "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
1876 "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
1877 "AND'ed into @var{bv}.\n\n"
1878 "If uve is a unsigned integer vector all the elements of uve\n"
1879 "must be between 0 and the @code{length} of @var{bv}. The bits\n"
1880 "of @var{bv} corresponding to the indexes in uve are set to\n"
1881 "@var{bool}. The return value is unspecified.")
1882 #define FUNC_NAME s_scm_bit_set_star_x
1884 register long i
, k
, vlen
;
1885 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1886 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1887 switch SCM_TYP7 (kv
)
1890 badarg2
:SCM_WRONG_TYPE_ARG (2, kv
);
1892 vlen
= SCM_BITVECTOR_LENGTH (v
);
1893 if (SCM_FALSEP (obj
))
1894 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1896 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1898 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1899 SCM_BITVEC_CLR(v
,k
);
1901 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1902 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1904 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1906 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1907 SCM_BITVEC_SET(v
,k
);
1910 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1913 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1914 if (SCM_FALSEP (obj
))
1915 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1916 SCM_UNPACK (SCM_VELTS (v
)[k
]) &= ~ SCM_UNPACK(SCM_VELTS (kv
)[k
]);
1917 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1918 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1919 SCM_UNPACK (SCM_VELTS (v
)[k
]) |= SCM_UNPACK (SCM_VELTS (kv
)[k
]);
1924 return SCM_UNSPECIFIED
;
1929 SCM_DEFINE (scm_bit_count_star
, "bit-count*", 3, 0, 0,
1930 (SCM v
, SCM kv
, SCM obj
),
1933 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1935 "@var{bv} is not modified.")
1936 #define FUNC_NAME s_scm_bit_count_star
1938 register long i
, vlen
, count
= 0;
1939 register unsigned long k
;
1942 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1943 SCM_ASRTGO (SCM_NIMP (kv
), badarg2
);
1944 switch SCM_TYP7 (kv
)
1948 SCM_WRONG_TYPE_ARG (2, kv
);
1950 vlen
= SCM_BITVECTOR_LENGTH (v
);
1951 if (SCM_FALSEP (obj
))
1952 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1954 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1956 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1957 if (!SCM_BITVEC_REF(v
,k
))
1960 else if (SCM_EQ_P (obj
, SCM_BOOL_T
))
1961 for (i
= SCM_UVECTOR_LENGTH (kv
); i
;)
1963 k
= SCM_UNPACK (SCM_VELTS (kv
)[--i
]);
1965 scm_out_of_range (FUNC_NAME
, SCM_MAKINUM (k
));
1966 if (SCM_BITVEC_REF (v
,k
))
1970 badarg3
:SCM_WRONG_TYPE_ARG (3, obj
);
1973 SCM_ASSERT (SCM_BITVECTOR_LENGTH (v
) == SCM_BITVECTOR_LENGTH (kv
), v
, SCM_ARG1
, FUNC_NAME
);
1974 if (0 == SCM_BITVECTOR_LENGTH (v
))
1976 SCM_ASRTGO (SCM_BOOLP (obj
), badarg3
);
1977 fObj
= SCM_EQ_P (obj
, SCM_BOOL_T
);
1978 i
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
;
1979 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK (SCM_VELTS (v
)[i
]) : ~ SCM_UNPACK (SCM_VELTS (v
)[i
]));
1980 k
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
);
1984 count
+= cnt_tab
[k
& 0x0f];
1986 return SCM_MAKINUM (count
);
1988 /* urg. repetitive (see above.) */
1989 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK(SCM_VELTS (v
)[i
]) : ~SCM_UNPACK (SCM_VELTS (v
)[i
]));
1992 return SCM_MAKINUM (count
);
1997 SCM_DEFINE (scm_bit_invert_x
, "bit-invert!", 1, 0, 0,
1999 "Modifies @var{bv} by replacing each element with its negation.")
2000 #define FUNC_NAME s_scm_bit_invert_x
2004 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
2006 k
= SCM_BITVECTOR_LENGTH (v
);
2007 for (k
= (k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
2008 SCM_UNPACK (SCM_VELTS (v
)[k
]) = ~SCM_UNPACK (SCM_VELTS (v
)[k
]);
2010 return SCM_UNSPECIFIED
;
2016 scm_istr2bve (char *str
, long len
)
2018 SCM v
= scm_make_uve (len
, SCM_BOOL_T
);
2019 long *data
= (long *) SCM_VELTS (v
);
2020 register unsigned long mask
;
2023 for (k
= 0; k
< (len
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
++)
2026 j
= len
- k
* SCM_LONG_BIT
;
2027 if (j
> SCM_LONG_BIT
)
2029 for (mask
= 1L; j
--; mask
<<= 1)
2047 ra2l (SCM ra
,scm_sizet base
,scm_sizet k
)
2049 register SCM res
= SCM_EOL
;
2050 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2051 register scm_sizet i
;
2052 if (SCM_ARRAY_DIMS (ra
)[k
].ubnd
< SCM_ARRAY_DIMS (ra
)[k
].lbnd
)
2054 i
= base
+ (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
) * inc
;
2055 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2060 res
= scm_cons (ra2l (ra
, i
, k
+ 1), res
);
2068 res
= scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra
), SCM_MAKINUM (i
)), res
);
2075 SCM_DEFINE (scm_array_to_list
, "array->list", 1, 0, 0,
2077 "Returns a list consisting of all the elements, in order, of @var{array}.")
2078 #define FUNC_NAME s_scm_array_to_list
2082 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
2086 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
2088 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
2089 return ra2l (v
, SCM_ARRAY_BASE (v
), 0);
2090 case scm_tc7_vector
:
2092 return scm_vector_to_list (v
);
2093 case scm_tc7_string
:
2094 return scm_string_to_list (v
);
2097 long *data
= (long *) SCM_VELTS (v
);
2098 register unsigned long mask
;
2099 for (k
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; k
> 0; k
--)
2100 for (mask
= 1UL << (SCM_LONG_BIT
- 1); mask
; mask
>>= 1)
2101 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2102 for (mask
= 1L << ((SCM_BITVECTOR_LENGTH (v
) % SCM_LONG_BIT
) - 1); mask
; mask
>>= 1)
2103 res
= scm_cons (SCM_BOOL(((long *) data
)[k
] & mask
), res
);
2106 case scm_tc7_uvect
: {
2107 long *data
= (long *)SCM_VELTS(v
);
2108 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2109 res
= scm_cons(scm_ulong2num(data
[k
]), res
);
2112 case scm_tc7_ivect
: {
2113 long *data
= (long *)SCM_VELTS(v
);
2114 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2115 res
= scm_cons(scm_long2num(data
[k
]), res
);
2118 case scm_tc7_svect
: {
2120 data
= (short *)SCM_VELTS(v
);
2121 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2122 res
= scm_cons(SCM_MAKINUM (data
[k
]), res
);
2125 #ifdef HAVE_LONG_LONGS
2126 case scm_tc7_llvect
: {
2128 data
= (long_long
*)SCM_VELTS(v
);
2129 for (k
= SCM_UVECTOR_LENGTH(v
) - 1; k
>= 0; k
--)
2130 res
= scm_cons(scm_long_long2num(data
[k
]), res
);
2138 float *data
= (float *) SCM_VELTS (v
);
2139 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2140 res
= scm_cons (scm_make_real (data
[k
]), res
);
2145 double *data
= (double *) SCM_VELTS (v
);
2146 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2147 res
= scm_cons (scm_make_real (data
[k
]), res
);
2152 double (*data
)[2] = (double (*)[2]) SCM_VELTS (v
);
2153 for (k
= SCM_UVECTOR_LENGTH (v
) - 1; k
>= 0; k
--)
2154 res
= scm_cons (scm_make_complex (data
[k
][0], data
[k
][1]), res
);
2162 static int l2ra(SCM lst
, SCM ra
, scm_sizet base
, scm_sizet k
);
2164 SCM_DEFINE (scm_list_to_uniform_array
, "list->uniform-array", 3, 0, 0,
2165 (SCM ndim
, SCM prot
, SCM lst
),
2166 "@deffnx procedure list->uniform-vector prot lst\n"
2167 "Returns a uniform array of the type indicated by prototype @var{prot}\n"
2168 "with elements the same as those of @var{lst}. Elements must be of the\n"
2169 "appropriate type, no coercions are done.")
2170 #define FUNC_NAME s_scm_list_to_uniform_array
2177 SCM_VALIDATE_INUM_COPY (1,ndim
,k
);
2180 n
= scm_ilength (row
);
2181 SCM_ASSERT (n
>= 0, lst
, SCM_ARG3
, FUNC_NAME
);
2182 shp
= scm_cons (SCM_MAKINUM (n
), shp
);
2184 row
= SCM_CAR (row
);
2186 ra
= scm_dimensions_to_uniform_array (scm_reverse (shp
), prot
,
2188 if (SCM_NULLP (shp
))
2190 SCM_ASRTGO (1 == scm_ilength (lst
), badlst
);
2191 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_EOL
);
2194 if (!SCM_ARRAYP (ra
))
2196 unsigned long int length
= SCM_INUM (scm_uniform_vector_length (ra
));
2197 for (k
= 0; k
< length
; k
++, lst
= SCM_CDR (lst
))
2198 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_MAKINUM (k
));
2201 if (l2ra (lst
, ra
, SCM_ARRAY_BASE (ra
), 0))
2204 badlst
:SCM_MISC_ERROR ("Bad scm_array contents list: ~S", SCM_LIST1 (lst
));
2209 l2ra (SCM lst
, SCM ra
, scm_sizet base
, scm_sizet k
)
2211 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2212 register long n
= (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
);
2215 return (SCM_NULLP (lst
));
2216 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2220 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2222 ok
= ok
&& l2ra (SCM_CAR (lst
), ra
, base
, k
+ 1);
2224 lst
= SCM_CDR (lst
);
2226 if (SCM_NNULLP (lst
))
2233 if (SCM_IMP (lst
) || SCM_NCONSP (lst
))
2235 scm_array_set_x (SCM_ARRAY_V (ra
), SCM_CAR (lst
), SCM_MAKINUM (base
));
2237 lst
= SCM_CDR (lst
);
2239 if (SCM_NNULLP (lst
))
2247 rapr1 (SCM ra
,scm_sizet j
,scm_sizet k
,SCM port
,scm_print_state
*pstate
)
2250 long n
= (SCM_TYP7 (ra
) == scm_tc7_smob
2252 : SCM_INUM (scm_uniform_vector_length (ra
)));
2255 switch SCM_TYP7 (ra
)
2260 SCM_ARRAY_BASE (ra
) = j
;
2262 scm_iprin1 (ra
, port
, pstate
);
2263 for (j
+= inc
; n
-- > 0; j
+= inc
)
2265 scm_putc (' ', port
);
2266 SCM_ARRAY_BASE (ra
) = j
;
2267 scm_iprin1 (ra
, port
, pstate
);
2271 if (k
+ 1 < SCM_ARRAY_NDIM (ra
))
2274 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2275 for (i
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
; i
< SCM_ARRAY_DIMS (ra
)[k
].ubnd
; i
++)
2277 scm_putc ('(', port
);
2278 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2279 scm_puts (") ", port
);
2282 if (i
== SCM_ARRAY_DIMS (ra
)[k
].ubnd
)
2283 { /* could be zero size. */
2284 scm_putc ('(', port
);
2285 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2286 scm_putc (')', port
);
2292 { /* Could be zero-dimensional */
2293 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2294 n
= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
2298 ra
= SCM_ARRAY_V (ra
);
2301 /* scm_tc7_bvect and scm_tc7_llvect only? */
2303 scm_iprin1 (scm_uniform_vector_ref (ra
, SCM_MAKINUM (j
)), port
, pstate
);
2304 for (j
+= inc
; n
-- > 0; j
+= inc
)
2306 scm_putc (' ', port
);
2307 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2310 case scm_tc7_string
:
2312 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2313 if (SCM_WRITINGP (pstate
))
2314 for (j
+= inc
; n
-- > 0; j
+= inc
)
2316 scm_putc (' ', port
);
2317 scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra
)[j
]), port
, pstate
);
2320 for (j
+= inc
; n
-- > 0; j
+= inc
)
2321 scm_putc (SCM_STRING_CHARS (ra
)[j
], port
);
2323 case scm_tc7_byvect
:
2325 scm_intprint (((char *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2326 for (j
+= inc
; n
-- > 0; j
+= inc
)
2328 scm_putc (' ', port
);
2329 scm_intprint (((char *)SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2339 /* intprint can't handle >= 2^31. */
2340 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2341 scm_puts (str
, port
);
2343 for (j
+= inc
; n
-- > 0; j
+= inc
)
2345 scm_putc (' ', port
);
2346 sprintf (str
, "%lu", ((unsigned long *) SCM_VELTS (ra
))[j
]);
2347 scm_puts (str
, port
);
2352 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2353 for (j
+= inc
; n
-- > 0; j
+= inc
)
2355 scm_putc (' ', port
);
2356 scm_intprint (((signed long *) SCM_VELTS (ra
))[j
], 10, port
);
2362 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2363 for (j
+= inc
; n
-- > 0; j
+= inc
)
2365 scm_putc (' ', port
);
2366 scm_intprint (((short *) SCM_CELL_WORD_1 (ra
))[j
], 10, port
);
2373 SCM z
= scm_make_real (1.0);
2374 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2375 scm_print_real (z
, port
, pstate
);
2376 for (j
+= inc
; n
-- > 0; j
+= inc
)
2378 scm_putc (' ', port
);
2379 SCM_REAL_VALUE (z
) = ((float *) SCM_VELTS (ra
))[j
];
2380 scm_print_real (z
, port
, pstate
);
2387 SCM z
= scm_make_real (1.0 / 3.0);
2388 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2389 scm_print_real (z
, port
, pstate
);
2390 for (j
+= inc
; n
-- > 0; j
+= inc
)
2392 scm_putc (' ', port
);
2393 SCM_REAL_VALUE (z
) = ((double *) SCM_VELTS (ra
))[j
];
2394 scm_print_real (z
, port
, pstate
);
2401 SCM cz
= scm_make_complex (0.0, 1.0), z
= scm_make_real (1.0 / 3.0);
2402 SCM_REAL_VALUE (z
) =
2403 SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2404 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2405 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2407 for (j
+= inc
; n
-- > 0; j
+= inc
)
2409 scm_putc (' ', port
);
2411 = SCM_COMPLEX_REAL (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
];
2412 SCM_COMPLEX_IMAG (cz
) = ((double *) SCM_VELTS (ra
))[2 * j
+ 1];
2413 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz
) ? z
: cz
),
2424 scm_raprin1 (SCM exp
, SCM port
, scm_print_state
*pstate
)
2428 scm_putc ('#', port
);
2434 long ndim
= SCM_ARRAY_NDIM (v
);
2435 base
= SCM_ARRAY_BASE (v
);
2436 v
= SCM_ARRAY_V (v
);
2440 scm_puts ("<enclosed-array ", port
);
2441 rapr1 (exp
, base
, 0, port
, pstate
);
2442 scm_putc ('>', port
);
2447 scm_intprint (ndim
, 10, port
);
2452 if (SCM_EQ_P (exp
, v
))
2453 { /* a uve, not an scm_array */
2454 register long i
, j
, w
;
2455 scm_putc ('*', port
);
2456 for (i
= 0; i
< (SCM_BITVECTOR_LENGTH (exp
)) / SCM_LONG_BIT
; i
++)
2458 scm_bits_t w
= SCM_UNPACK (SCM_VELTS (exp
)[i
]);
2459 for (j
= SCM_LONG_BIT
; j
; j
--)
2461 scm_putc (w
& 1 ? '1' : '0', port
);
2465 j
= SCM_BITVECTOR_LENGTH (exp
) % SCM_LONG_BIT
;
2468 w
= SCM_UNPACK (SCM_VELTS (exp
)[SCM_BITVECTOR_LENGTH (exp
) / SCM_LONG_BIT
]);
2471 scm_putc (w
& 1 ? '1' : '0', port
);
2478 scm_putc ('b', port
);
2480 case scm_tc7_string
:
2481 scm_putc ('a', port
);
2483 case scm_tc7_byvect
:
2484 scm_putc ('y', port
);
2487 scm_putc ('u', port
);
2490 scm_putc ('e', port
);
2493 scm_putc ('h', port
);
2495 #ifdef HAVE_LONG_LONGS
2496 case scm_tc7_llvect
:
2497 scm_putc ('l', port
);
2501 scm_putc ('s', port
);
2504 scm_putc ('i', port
);
2507 scm_putc ('c', port
);
2510 scm_putc ('(', port
);
2511 rapr1 (exp
, base
, 0, port
, pstate
);
2512 scm_putc (')', port
);
2516 SCM_DEFINE (scm_array_prototype
, "array-prototype", 1, 0, 0,
2518 "Returns an object that would produce an array of the same type as\n"
2519 "@var{array}, if used as the @var{prototype} for\n"
2520 "@code{make-uniform-array}.")
2521 #define FUNC_NAME s_scm_array_prototype
2524 SCM_ASRTGO (SCM_NIMP (ra
), badarg
);
2526 switch SCM_TYP7 (ra
)
2529 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
2531 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
2533 return SCM_UNSPECIFIED
;
2534 ra
= SCM_ARRAY_V (ra
);
2536 case scm_tc7_vector
:
2541 case scm_tc7_string
:
2542 return SCM_MAKE_CHAR ('a');
2543 case scm_tc7_byvect
:
2544 return SCM_MAKE_CHAR ('\0');
2546 return SCM_MAKINUM (1L);
2548 return SCM_MAKINUM (-1L);
2550 return scm_str2symbol ("s");
2551 #ifdef HAVE_LONG_LONGS
2552 case scm_tc7_llvect
:
2553 return scm_str2symbol ("l");
2556 return scm_make_real (1.0);
2558 return scm_make_real (1.0 / 3.0);
2560 return scm_make_complex (0.0, 1.0);
2567 array_mark (SCM ptr
)
2569 return SCM_ARRAY_V (ptr
);
2574 array_free (SCM ptr
)
2576 scm_must_free (SCM_ARRAY_MEM (ptr
));
2577 return sizeof (scm_array
) + SCM_ARRAY_NDIM (ptr
) * sizeof (scm_array_dim
);
2583 scm_tc16_array
= scm_make_smob_type ("array", 0);
2584 scm_set_smob_mark (scm_tc16_array
, array_mark
);
2585 scm_set_smob_free (scm_tc16_array
, array_free
);
2586 scm_set_smob_print (scm_tc16_array
, scm_raprin1
);
2587 scm_set_smob_equalp (scm_tc16_array
, scm_array_equal_p
);
2588 scm_add_feature ("array");
2589 #ifndef SCM_MAGIC_SNARFER
2590 #include "libguile/unif.x"