1 /* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 This file has code for arrays in lots of variants (double, integer,
21 unsigned etc. ). It suffers from hugely repetitive code because
22 there is similar (but different) code for every variant included. (urg.)
36 #include "libguile/_scm.h"
37 #include "libguile/__scm.h"
38 #include "libguile/eq.h"
39 #include "libguile/chars.h"
40 #include "libguile/eval.h"
41 #include "libguile/fports.h"
42 #include "libguile/smob.h"
43 #include "libguile/feature.h"
44 #include "libguile/root.h"
45 #include "libguile/strings.h"
46 #include "libguile/srfi-13.h"
47 #include "libguile/srfi-4.h"
48 #include "libguile/vectors.h"
49 #include "libguile/list.h"
50 #include "libguile/deprecation.h"
52 #include "libguile/validate.h"
53 #include "libguile/unif.h"
54 #include "libguile/ramap.h"
55 #include "libguile/print.h"
56 #include "libguile/read.h"
67 /* The set of uniform scm_vector types is:
68 * Vector of: Called: Replaced by:
69 * unsigned char string
70 * char byvect s8 or u8, depending on signedness of 'char'
72 * signed long ivect s32
73 * unsigned long uvect u32
76 * complex double cvect c64
78 * long long llvect s64
81 scm_t_bits scm_tc16_array
;
82 static SCM exactly_one_third
;
85 /* Silly function used not to modify the semantics of the silly
86 * prototype system in order to be backward compatible.
95 double x
= SCM_REAL_VALUE (obj
);
97 return (- SCM_FLTMAX
< x
) && (x
< SCM_FLTMAX
) && (fx
== x
);
102 static SCM scm_i_proc_make_vector
;
103 static SCM scm_i_proc_make_string
;
104 static SCM scm_i_proc_make_u1vector
;
106 #if SCM_ENABLE_DEPRECATED
108 SCM_SYMBOL (scm_sym_s
, "s");
109 SCM_SYMBOL (scm_sym_l
, "l");
111 SCM
scm_make_u1vector (SCM len
, SCM fill
);
113 SCM_DEFINE (scm_make_u1vector
, "make-u1vector", 1, 1, 0,
116 #define FUNC_NAME s_scm_make_u1vector
118 long k
= scm_to_long (len
);
122 SCM_ASSERT_RANGE (1, scm_from_long (k
),
123 k
<= SCM_BITVECTOR_MAX_LENGTH
);
124 i
= sizeof (long) * ((k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
);
125 return scm_cell (SCM_MAKE_BITVECTOR_TAG (k
),
126 (scm_t_bits
) scm_gc_malloc (i
, "vector"));
129 return scm_cell (SCM_MAKE_BITVECTOR_TAG (0), 0);
134 scm_i_convert_old_prototype (SCM proto
)
138 /* All new 'prototypes' are creator procedures.
140 if (scm_is_true (scm_procedure_p (proto
)))
143 if (scm_is_eq (proto
, SCM_BOOL_T
))
144 new_proto
= scm_i_proc_make_u1vector
;
145 else if (scm_is_eq (proto
, SCM_MAKE_CHAR ('a')))
146 new_proto
= scm_i_proc_make_string
;
147 else if (scm_is_eq (proto
, SCM_MAKE_CHAR (0)))
148 new_proto
= scm_i_proc_make_s8vector
;
149 else if (scm_is_eq (proto
, scm_sym_s
))
150 new_proto
= scm_i_proc_make_s16vector
;
151 else if (scm_is_true (scm_eqv_p (proto
, scm_from_int (1))))
152 new_proto
= scm_i_proc_make_u32vector
;
153 else if (scm_is_true (scm_eqv_p (proto
, scm_from_int (-1))))
154 new_proto
= scm_i_proc_make_s32vector
;
155 else if (scm_is_eq (proto
, scm_sym_l
))
156 new_proto
= scm_i_proc_make_s64vector
;
157 else if (scm_is_true (scm_eqv_p (proto
, scm_from_double (1.0))))
158 new_proto
= scm_i_proc_make_f32vector
;
159 else if (scm_is_true (scm_eqv_p (proto
, scm_divide (scm_from_int (1),
161 new_proto
= scm_i_proc_make_f64vector
;
162 else if (scm_is_true (scm_eqv_p (proto
, scm_c_make_rectangular (0, 1))))
163 new_proto
= scm_i_proc_make_c64vector
;
164 else if (scm_is_null (proto
))
165 new_proto
= scm_i_proc_make_vector
;
169 scm_c_issue_deprecation_warning
170 ("Using prototypes with arrays is deprecated. "
171 "Use creator functions instead.");
177 scm_i_get_old_prototype (SCM uvec
)
179 if (SCM_BITVECTOR_P (uvec
))
181 else if (scm_is_string (uvec
))
182 return SCM_MAKE_CHAR ('a');
183 else if (scm_is_true (scm_s8vector_p (uvec
)))
184 return SCM_MAKE_CHAR ('\0');
185 else if (scm_is_true (scm_s16vector_p (uvec
)))
187 else if (scm_is_true (scm_u32vector_p (uvec
)))
188 return scm_from_int (1);
189 else if (scm_is_true (scm_s32vector_p (uvec
)))
190 return scm_from_int (-1);
191 else if (scm_is_true (scm_s64vector_p (uvec
)))
193 else if (scm_is_true (scm_f32vector_p (uvec
)))
194 return scm_from_double (1.0);
195 else if (scm_is_true (scm_f64vector_p (uvec
)))
196 return scm_divide (scm_from_int (1), scm_from_int (3));
197 else if (scm_is_true (scm_c64vector_p (uvec
)))
198 return scm_c_make_rectangular (0, 1);
199 else if (scm_is_true (scm_vector_p (uvec
)))
202 return SCM_UNSPECIFIED
;
208 scm_make_uve (long k
, SCM prot
)
209 #define FUNC_NAME "scm_make_uve"
211 #if SCM_ENABLE_DEPRECATED
212 prot
= scm_i_convert_old_prototype (prot
);
214 return scm_call_1 (prot
, scm_from_long (k
));
218 SCM_DEFINE (scm_array_p
, "array?", 1, 1, 0,
220 "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
221 "not. The @var{prototype} argument is used with uniform arrays\n"
222 "and is described elsewhere.")
223 #define FUNC_NAME s_scm_array_p
227 nprot
= SCM_UNBNDP (prot
);
232 while (SCM_ARRAYP (v
))
243 if (scm_is_uniform_vector (v
))
249 #if SCM_ENABLE_DEPRECATED
250 prot
= scm_i_convert_old_prototype (prot
);
252 return scm_eq_p (prot
, scm_i_uniform_vector_creator (v
));
255 else if (scm_is_true (scm_vector_p (v
)))
261 #if SCM_ENABLE_DEPRECATED
262 prot
= scm_i_convert_old_prototype (prot
);
264 return scm_eq_p (prot
, scm_i_proc_make_vector
);
270 switch (SCM_TYP7 (v
))
285 switch (SCM_TYP7 (v
))
288 protp
= (scm_is_eq (prot
, SCM_BOOL_T
));
291 protp
= SCM_CHARP(prot
) && (SCM_CHAR (prot
) != '\0');
295 protp
= scm_is_null(prot
);
301 return scm_from_bool(protp
);
307 SCM_DEFINE (scm_array_rank
, "array-rank", 1, 0, 0,
309 "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
310 "not an array, @code{0} is returned.")
311 #define FUNC_NAME s_scm_array_rank
313 if (scm_is_uniform_vector (ra
))
314 return scm_from_int (1);
318 switch (SCM_TYP7 (ra
))
325 return scm_from_int (1);
328 return scm_from_size_t (SCM_ARRAY_NDIM (ra
));
335 SCM_DEFINE (scm_array_dimensions
, "array-dimensions", 1, 0, 0,
337 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
338 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
340 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
342 #define FUNC_NAME s_scm_array_dimensions
350 if (scm_is_uniform_vector (ra
))
351 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
353 switch (SCM_TYP7 (ra
))
361 return scm_cons (scm_uniform_vector_length (ra
), SCM_EOL
);
363 if (!SCM_ARRAYP (ra
))
365 k
= SCM_ARRAY_NDIM (ra
);
366 s
= SCM_ARRAY_DIMS (ra
);
368 res
= scm_cons (s
[k
].lbnd
369 ? scm_cons2 (scm_from_long (s
[k
].lbnd
),
370 scm_from_long (s
[k
].ubnd
),
372 : scm_from_long (1 + s
[k
].ubnd
),
380 SCM_DEFINE (scm_shared_array_root
, "shared-array-root", 1, 0, 0,
382 "Return the root vector of a shared array.")
383 #define FUNC_NAME s_scm_shared_array_root
385 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
386 return SCM_ARRAY_V (ra
);
391 SCM_DEFINE (scm_shared_array_offset
, "shared-array-offset", 1, 0, 0,
393 "Return the root vector index of the first element in the array.")
394 #define FUNC_NAME s_scm_shared_array_offset
396 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
397 return scm_from_int (SCM_ARRAY_BASE (ra
));
402 SCM_DEFINE (scm_shared_array_increments
, "shared-array-increments", 1, 0, 0,
404 "For each dimension, return the distance between elements in the root vector.")
405 #define FUNC_NAME s_scm_shared_array_increments
410 SCM_ASSERT (SCM_ARRAYP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
411 k
= SCM_ARRAY_NDIM (ra
);
412 s
= SCM_ARRAY_DIMS (ra
);
414 res
= scm_cons (scm_from_long (s
[k
].inc
), res
);
420 static char s_bad_ind
[] = "Bad scm_array index";
424 scm_aind (SCM ra
, SCM args
, const char *what
)
425 #define FUNC_NAME what
429 register unsigned long pos
= SCM_ARRAY_BASE (ra
);
430 register unsigned long k
= SCM_ARRAY_NDIM (ra
);
431 scm_t_array_dim
*s
= SCM_ARRAY_DIMS (ra
);
432 if (scm_is_integer (args
))
435 scm_error_num_args_subr (what
);
436 return pos
+ (scm_to_long (args
) - s
->lbnd
) * (s
->inc
);
438 while (k
&& scm_is_pair (args
))
440 ind
= SCM_CAR (args
);
441 args
= SCM_CDR (args
);
442 if (!scm_is_integer (ind
))
443 scm_misc_error (what
, s_bad_ind
, SCM_EOL
);
444 j
= scm_to_long (ind
);
445 if (j
< s
->lbnd
|| j
> s
->ubnd
)
446 scm_out_of_range (what
, ind
);
447 pos
+= (j
- s
->lbnd
) * (s
->inc
);
451 if (k
!= 0 || !scm_is_null (args
))
452 scm_error_num_args_subr (what
);
460 scm_make_ra (int ndim
)
464 SCM_NEWSMOB(ra
, ((scm_t_bits
) ndim
<< 17) + scm_tc16_array
,
465 scm_gc_malloc ((sizeof (scm_t_array
) +
466 ndim
* sizeof (scm_t_array_dim
)),
468 SCM_ARRAY_V (ra
) = scm_nullvect
;
473 static char s_bad_spec
[] = "Bad scm_array dimension";
474 /* Increments will still need to be set. */
478 scm_shap2ra (SCM args
, const char *what
)
482 int ndim
= scm_ilength (args
);
484 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
486 ra
= scm_make_ra (ndim
);
487 SCM_ARRAY_BASE (ra
) = 0;
488 s
= SCM_ARRAY_DIMS (ra
);
489 for (; !scm_is_null (args
); s
++, args
= SCM_CDR (args
))
491 spec
= SCM_CAR (args
);
492 if (scm_is_integer (spec
))
494 if (scm_to_long (spec
) < 0)
495 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
497 s
->ubnd
= scm_to_long (spec
) - 1;
502 if (!scm_is_pair (spec
) || !scm_is_integer (SCM_CAR (spec
)))
503 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
504 s
->lbnd
= scm_to_long (SCM_CAR (spec
));
506 if (!scm_is_pair (sp
)
507 || !scm_is_integer (SCM_CAR (sp
))
508 || !scm_is_null (SCM_CDR (sp
)))
509 scm_misc_error (what
, s_bad_spec
, SCM_EOL
);
510 s
->ubnd
= scm_to_long (SCM_CAR (sp
));
517 SCM_DEFINE (scm_dimensions_to_uniform_array
, "dimensions->uniform-array", 2, 1, 0,
518 (SCM dims
, SCM prot
, SCM fill
),
519 "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
520 "Create and return a uniform array or vector of type\n"
521 "corresponding to @var{prototype} with dimensions @var{dims} or\n"
522 "length @var{length}. If @var{fill} is supplied, it's used to\n"
523 "fill the array, otherwise @var{prototype} is used.")
524 #define FUNC_NAME s_scm_dimensions_to_uniform_array
527 unsigned long rlen
= 1;
531 if (scm_is_integer (dims
))
533 SCM answer
= scm_make_uve (scm_to_long (dims
), prot
);
534 if (!SCM_UNBNDP (fill
))
535 scm_array_fill_x (answer
, fill
);
536 else if (scm_is_symbol (prot
) || scm_is_eq (prot
, SCM_MAKE_CHAR (0)))
537 scm_array_fill_x (answer
, scm_from_int (0));
538 else if (scm_is_false (scm_procedure_p (prot
)))
539 scm_array_fill_x (answer
, prot
);
543 SCM_ASSERT (scm_is_null (dims
) || scm_is_pair (dims
),
544 dims
, SCM_ARG1
, FUNC_NAME
);
545 ra
= scm_shap2ra (dims
, FUNC_NAME
);
546 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
547 s
= SCM_ARRAY_DIMS (ra
);
548 k
= SCM_ARRAY_NDIM (ra
);
553 SCM_ASSERT_RANGE (1, dims
, s
[k
].lbnd
<= s
[k
].ubnd
);
554 rlen
= (s
[k
].ubnd
- s
[k
].lbnd
+ 1) * s
[k
].inc
;
557 SCM_ARRAY_V (ra
) = scm_make_uve (rlen
, prot
);
559 if (!SCM_UNBNDP (fill
))
560 scm_array_fill_x (ra
, fill
);
561 else if (scm_is_symbol (prot
) || scm_is_eq (prot
, SCM_MAKE_CHAR (0)))
562 scm_array_fill_x (ra
, scm_from_int (0));
563 else if (scm_is_false (scm_procedure_p (prot
)))
564 scm_array_fill_x (ra
, prot
);
566 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
567 if (s
->ubnd
< s
->lbnd
|| (0 == s
->lbnd
&& 1 == s
->inc
))
568 return SCM_ARRAY_V (ra
);
575 scm_ra_set_contp (SCM ra
)
577 size_t k
= SCM_ARRAY_NDIM (ra
);
580 long inc
= SCM_ARRAY_DIMS (ra
)[k
- 1].inc
;
583 if (inc
!= SCM_ARRAY_DIMS (ra
)[k
].inc
)
585 SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra
);
588 inc
*= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
589 - SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
592 SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra
);
596 SCM_DEFINE (scm_make_shared_array
, "make-shared-array", 2, 0, 1,
597 (SCM oldra
, SCM mapfunc
, SCM dims
),
598 "@code{make-shared-array} can be used to create shared subarrays of other\n"
599 "arrays. The @var{mapper} is a function that translates coordinates in\n"
600 "the new array into coordinates in the old array. A @var{mapper} must be\n"
601 "linear, and its range must stay within the bounds of the old array, but\n"
602 "it can be otherwise arbitrary. A simple example:\n"
604 "(define fred (make-array #f 8 8))\n"
605 "(define freds-diagonal\n"
606 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
607 "(array-set! freds-diagonal 'foo 3)\n"
608 "(array-ref fred 3 3) @result{} foo\n"
609 "(define freds-center\n"
610 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
611 "(array-ref freds-center 0 0) @result{} foo\n"
613 #define FUNC_NAME s_scm_make_shared_array
619 long old_min
, new_min
, old_max
, new_max
;
622 SCM_VALIDATE_REST_ARGUMENT (dims
);
623 SCM_VALIDATE_ARRAY (1, oldra
);
624 SCM_VALIDATE_PROC (2, mapfunc
);
625 ra
= scm_shap2ra (dims
, FUNC_NAME
);
626 if (SCM_ARRAYP (oldra
))
628 SCM_ARRAY_V (ra
) = SCM_ARRAY_V (oldra
);
629 old_min
= old_max
= SCM_ARRAY_BASE (oldra
);
630 s
= SCM_ARRAY_DIMS (oldra
);
631 k
= SCM_ARRAY_NDIM (oldra
);
635 old_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
637 old_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
642 SCM_ARRAY_V (ra
) = oldra
;
644 old_max
= scm_to_long (scm_uniform_vector_length (oldra
)) - 1;
647 s
= SCM_ARRAY_DIMS (ra
);
648 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
650 inds
= scm_cons (scm_from_long (s
[k
].lbnd
), inds
);
651 if (s
[k
].ubnd
< s
[k
].lbnd
)
653 if (1 == SCM_ARRAY_NDIM (ra
))
654 ra
= scm_make_uve (0L, scm_array_prototype (ra
));
656 SCM_ARRAY_V (ra
) = scm_make_uve (0L, scm_array_prototype (ra
));
660 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
661 if (SCM_ARRAYP (oldra
))
662 i
= (size_t) scm_aind (oldra
, imap
, FUNC_NAME
);
665 if (!scm_is_integer (imap
))
667 if (scm_ilength (imap
) != 1 || !scm_is_integer (SCM_CAR (imap
)))
668 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
669 imap
= SCM_CAR (imap
);
671 i
= scm_to_size_t (imap
);
673 SCM_ARRAY_BASE (ra
) = new_min
= new_max
= i
;
675 k
= SCM_ARRAY_NDIM (ra
);
678 if (s
[k
].ubnd
> s
[k
].lbnd
)
680 SCM_SETCAR (indptr
, scm_sum (SCM_CAR (indptr
), scm_from_int (1)));
681 imap
= scm_apply_0 (mapfunc
, scm_reverse (inds
));
682 if (SCM_ARRAYP (oldra
))
684 s
[k
].inc
= scm_aind (oldra
, imap
, FUNC_NAME
) - i
;
687 if (!scm_is_integer (imap
))
689 if (scm_ilength (imap
) != 1 || !scm_is_integer (SCM_CAR (imap
)))
690 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
691 imap
= SCM_CAR (imap
);
693 s
[k
].inc
= scm_to_long (imap
) - i
;
697 new_max
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
699 new_min
+= (s
[k
].ubnd
- s
[k
].lbnd
) * s
[k
].inc
;
702 s
[k
].inc
= new_max
- new_min
+ 1; /* contiguous by default */
703 indptr
= SCM_CDR (indptr
);
705 if (old_min
> new_min
|| old_max
< new_max
)
706 SCM_MISC_ERROR ("mapping out of range", SCM_EOL
);
707 if (1 == SCM_ARRAY_NDIM (ra
) && 0 == SCM_ARRAY_BASE (ra
))
709 SCM v
= SCM_ARRAY_V (ra
);
710 unsigned long int length
= scm_to_ulong (scm_uniform_vector_length (v
));
711 if (1 == s
->inc
&& 0 == s
->lbnd
&& length
== 1 + s
->ubnd
)
713 if (s
->ubnd
< s
->lbnd
)
714 return scm_make_uve (0L, scm_array_prototype (ra
));
716 scm_ra_set_contp (ra
);
722 /* args are RA . DIMS */
723 SCM_DEFINE (scm_transpose_array
, "transpose-array", 1, 0, 1,
725 "Return an array sharing contents with @var{array}, but with\n"
726 "dimensions arranged in a different order. There must be one\n"
727 "@var{dim} argument for each dimension of @var{array}.\n"
728 "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
729 "and the rank of the array to be returned. Each integer in that\n"
730 "range must appear at least once in the argument list.\n"
732 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
733 "dimensions in the array to be returned, their positions in the\n"
734 "argument list to dimensions of @var{array}. Several @var{dim}s\n"
735 "may have the same value, in which case the returned array will\n"
736 "have smaller rank than @var{array}.\n"
739 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
740 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
741 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
742 " #2((a 4) (b 5) (c 6))\n"
744 #define FUNC_NAME s_scm_transpose_array
747 SCM
const *ve
= &vargs
;
748 scm_t_array_dim
*s
, *r
;
751 SCM_VALIDATE_REST_ARGUMENT (args
);
752 SCM_ASSERT (SCM_NIMP (ra
), ra
, SCM_ARG1
, FUNC_NAME
);
754 if (scm_is_uniform_vector (ra
))
756 /* Make sure that we are called with a single zero as
759 if (scm_is_null (args
) || !scm_is_null (SCM_CDR (args
)))
760 SCM_WRONG_NUM_ARGS ();
761 SCM_VALIDATE_INT_COPY (SCM_ARG2
, SCM_CAR (args
), i
);
762 SCM_ASSERT_RANGE (SCM_ARG2
, SCM_CAR (args
), i
== 0);
766 switch (SCM_TYP7 (ra
))
769 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
772 if (scm_is_null (args
) || !scm_is_null (SCM_CDR (args
)))
773 SCM_WRONG_NUM_ARGS ();
774 SCM_VALIDATE_INT_COPY (SCM_ARG2
, SCM_CAR (args
), i
);
775 SCM_ASSERT_RANGE (SCM_ARG2
, SCM_CAR (args
), i
== 0);
778 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg
);
779 vargs
= scm_vector (args
);
780 if (SCM_VECTOR_LENGTH (vargs
) != SCM_ARRAY_NDIM (ra
))
781 SCM_WRONG_NUM_ARGS ();
782 ve
= SCM_VELTS (vargs
);
784 for (k
= 0; k
< SCM_ARRAY_NDIM (ra
); k
++)
786 i
= scm_to_signed_integer (ve
[k
], 0, SCM_ARRAY_NDIM(ra
));
791 res
= scm_make_ra (ndim
);
792 SCM_ARRAY_V (res
) = SCM_ARRAY_V (ra
);
793 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra
);
796 SCM_ARRAY_DIMS (res
)[k
].lbnd
= 0;
797 SCM_ARRAY_DIMS (res
)[k
].ubnd
= -1;
799 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
801 i
= scm_to_int (ve
[k
]);
802 s
= &(SCM_ARRAY_DIMS (ra
)[k
]);
803 r
= &(SCM_ARRAY_DIMS (res
)[i
]);
804 if (r
->ubnd
< r
->lbnd
)
813 if (r
->ubnd
> s
->ubnd
)
815 if (r
->lbnd
< s
->lbnd
)
817 SCM_ARRAY_BASE (res
) += (s
->lbnd
- r
->lbnd
) * r
->inc
;
824 SCM_MISC_ERROR ("bad argument list", SCM_EOL
);
825 scm_ra_set_contp (res
);
831 /* args are RA . AXES */
832 SCM_DEFINE (scm_enclose_array
, "enclose-array", 1, 0, 1,
834 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
835 "the rank of @var{array}. @var{enclose-array} returns an array\n"
836 "resembling an array of shared arrays. The dimensions of each shared\n"
837 "array are the same as the @var{dim}th dimensions of the original array,\n"
838 "the dimensions of the outer array are the same as those of the original\n"
839 "array that did not match a @var{dim}.\n\n"
840 "An enclosed array is not a general Scheme array. Its elements may not\n"
841 "be set using @code{array-set!}. Two references to the same element of\n"
842 "an enclosed array will be @code{equal?} but will not in general be\n"
843 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
844 "enclosed array is unspecified.\n\n"
847 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
848 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
849 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
850 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
852 #define FUNC_NAME s_scm_enclose_array
854 SCM axv
, res
, ra_inr
;
856 scm_t_array_dim vdim
, *s
= &vdim
;
857 int ndim
, j
, k
, ninr
, noutr
;
859 SCM_VALIDATE_REST_ARGUMENT (axes
);
860 if (scm_is_null (axes
))
861 axes
= scm_cons ((SCM_ARRAYP (ra
) ? scm_from_size_t (SCM_ARRAY_NDIM (ra
) - 1) : SCM_INUM0
), SCM_EOL
);
862 ninr
= scm_ilength (axes
);
864 SCM_WRONG_NUM_ARGS ();
865 ra_inr
= scm_make_ra (ninr
);
866 SCM_ASRTGO (SCM_NIMP (ra
), badarg1
);
868 if (scm_is_uniform_vector (ra
))
874 badarg1
:SCM_WRONG_TYPE_ARG (1, ra
);
881 s
->ubnd
= scm_to_long (scm_uniform_vector_length (ra
)) - 1;
883 SCM_ARRAY_V (ra_inr
) = ra
;
884 SCM_ARRAY_BASE (ra_inr
) = 0;
888 SCM_ASRTGO (SCM_ARRAYP (ra
), badarg1
);
889 s
= SCM_ARRAY_DIMS (ra
);
890 SCM_ARRAY_V (ra_inr
) = SCM_ARRAY_V (ra
);
891 SCM_ARRAY_BASE (ra_inr
) = SCM_ARRAY_BASE (ra
);
892 ndim
= SCM_ARRAY_NDIM (ra
);
897 SCM_WRONG_NUM_ARGS ();
898 axv
= scm_make_string (scm_from_int (ndim
), SCM_MAKE_CHAR (0));
899 res
= scm_make_ra (noutr
);
900 SCM_ARRAY_BASE (res
) = SCM_ARRAY_BASE (ra_inr
);
901 SCM_ARRAY_V (res
) = ra_inr
;
902 for (k
= 0; k
< ninr
; k
++, axes
= SCM_CDR (axes
))
904 if (!scm_is_integer (SCM_CAR (axes
)))
905 SCM_MISC_ERROR ("bad axis", SCM_EOL
);
906 j
= scm_to_int (SCM_CAR (axes
));
907 SCM_ARRAY_DIMS (ra_inr
)[k
].lbnd
= s
[j
].lbnd
;
908 SCM_ARRAY_DIMS (ra_inr
)[k
].ubnd
= s
[j
].ubnd
;
909 SCM_ARRAY_DIMS (ra_inr
)[k
].inc
= s
[j
].inc
;
910 scm_c_string_set_x (axv
, j
, SCM_MAKE_CHAR (1));
912 c_axv
= scm_i_string_chars (axv
);
913 for (j
= 0, k
= 0; k
< noutr
; k
++, j
++)
917 SCM_ARRAY_DIMS (res
)[k
].lbnd
= s
[j
].lbnd
;
918 SCM_ARRAY_DIMS (res
)[k
].ubnd
= s
[j
].ubnd
;
919 SCM_ARRAY_DIMS (res
)[k
].inc
= s
[j
].inc
;
921 scm_remember_upto_here_1 (axv
);
922 scm_ra_set_contp (ra_inr
);
923 scm_ra_set_contp (res
);
930 SCM_DEFINE (scm_array_in_bounds_p
, "array-in-bounds?", 1, 0, 1,
932 "Return @code{#t} if its arguments would be acceptable to\n"
934 #define FUNC_NAME s_scm_array_in_bounds_p
942 SCM_VALIDATE_REST_ARGUMENT (args
);
943 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
947 ind
= SCM_CAR (args
);
948 args
= SCM_CDR (args
);
949 pos
= scm_to_long (ind
);
953 if (scm_is_uniform_vector (v
))
959 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
960 wna
: SCM_WRONG_NUM_ARGS ();
962 k
= SCM_ARRAY_NDIM (v
);
963 s
= SCM_ARRAY_DIMS (v
);
964 pos
= SCM_ARRAY_BASE (v
);
967 SCM_ASRTGO (scm_is_null (ind
), wna
);
973 j
= scm_to_long (ind
);
974 if (!(j
>= (s
->lbnd
) && j
<= (s
->ubnd
)))
976 SCM_ASRTGO (--k
== scm_ilength (args
), wna
);
979 pos
+= (j
- s
->lbnd
) * (s
->inc
);
980 if (!(--k
&& SCM_NIMP (args
)))
982 ind
= SCM_CAR (args
);
983 args
= SCM_CDR (args
);
985 if (!scm_is_integer (ind
))
986 SCM_MISC_ERROR (s_bad_ind
, SCM_EOL
);
988 SCM_ASRTGO (0 == k
, wna
);
997 unsigned long length
= scm_to_ulong (scm_uniform_vector_length (v
));
998 SCM_ASRTGO (scm_is_null (args
) && scm_is_integer (ind
), wna
);
999 return scm_from_bool(pos
>= 0 && pos
< length
);
1006 SCM_DEFINE (scm_array_ref
, "array-ref", 1, 0, 1,
1008 "Return the element at the @code{(index1, index2)} element in\n"
1010 #define FUNC_NAME s_scm_array_ref
1016 SCM_ASRTGO (scm_is_null (args
), badarg
);
1019 else if (SCM_ARRAYP (v
))
1021 pos
= scm_aind (v
, args
, FUNC_NAME
);
1022 v
= SCM_ARRAY_V (v
);
1026 unsigned long int length
;
1027 if (SCM_NIMP (args
))
1029 SCM_ASSERT (scm_is_pair (args
), args
, SCM_ARG2
, FUNC_NAME
);
1030 pos
= scm_to_long (SCM_CAR (args
));
1031 SCM_ASRTGO (scm_is_null (SCM_CDR (args
)), wna
);
1035 pos
= scm_to_long (args
);
1037 length
= scm_to_ulong (scm_uniform_vector_length (v
));
1038 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1041 if (scm_is_uniform_vector (v
))
1042 return scm_uniform_vector_ref (v
, scm_from_long (pos
));
1047 if (scm_is_null (args
))
1050 SCM_WRONG_TYPE_ARG (1, v
);
1054 scm_out_of_range (FUNC_NAME
, scm_from_long (pos
));
1056 SCM_WRONG_NUM_ARGS ();
1059 int k
= SCM_ARRAY_NDIM (v
);
1060 SCM res
= scm_make_ra (k
);
1061 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1062 SCM_ARRAY_BASE (res
) = pos
;
1065 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1066 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1067 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1072 if (SCM_BITVEC_REF (v
, pos
))
1076 case scm_tc7_string
:
1077 return scm_c_string_ref (v
, pos
);
1078 case scm_tc7_vector
:
1080 return SCM_VELTS (v
)[pos
];
1085 /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1086 tries to recycle conses. (Make *sure* you want them recycled.) */
1089 scm_cvref (SCM v
, unsigned long pos
, SCM last
)
1090 #define FUNC_NAME "scm_cvref"
1092 if (scm_is_uniform_vector (v
))
1093 return scm_uniform_vector_ref (v
, scm_from_ulong (pos
));
1098 SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1100 if (SCM_BITVEC_REF(v
, pos
))
1104 case scm_tc7_string
:
1105 return scm_c_string_ref (v
, pos
);
1106 case scm_tc7_vector
:
1108 return SCM_VELTS (v
)[pos
];
1110 { /* enclosed scm_array */
1111 int k
= SCM_ARRAY_NDIM (v
);
1112 SCM res
= scm_make_ra (k
);
1113 SCM_ARRAY_V (res
) = SCM_ARRAY_V (v
);
1114 SCM_ARRAY_BASE (res
) = pos
;
1117 SCM_ARRAY_DIMS (res
)[k
].ubnd
= SCM_ARRAY_DIMS (v
)[k
].ubnd
;
1118 SCM_ARRAY_DIMS (res
)[k
].lbnd
= SCM_ARRAY_DIMS (v
)[k
].lbnd
;
1119 SCM_ARRAY_DIMS (res
)[k
].inc
= SCM_ARRAY_DIMS (v
)[k
].inc
;
1128 SCM_REGISTER_PROC(s_uniform_array_set1_x
, "uniform-array-set1!", 3, 0, 0, scm_array_set_x
);
1131 /* Note that args may be a list or an immediate object, depending which
1132 PROC is used (and it's called from C too). */
1133 SCM_DEFINE (scm_array_set_x
, "array-set!", 2, 0, 1,
1134 (SCM v
, SCM obj
, SCM args
),
1135 "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
1136 "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
1137 "@var{new-value}. The value returned by array-set! is unspecified.")
1138 #define FUNC_NAME s_scm_array_set_x
1142 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1145 pos
= scm_aind (v
, args
, FUNC_NAME
);
1146 v
= SCM_ARRAY_V (v
);
1150 unsigned long int length
;
1151 if (scm_is_pair (args
))
1153 SCM_ASRTGO (scm_is_null (SCM_CDR (args
)), wna
);
1154 pos
= scm_to_long (SCM_CAR (args
));
1158 pos
= scm_to_long (args
);
1160 length
= scm_to_ulong (scm_uniform_vector_length (v
));
1161 SCM_ASRTGO (pos
>= 0 && pos
< length
, outrng
);
1164 if (scm_is_uniform_vector (v
))
1165 return scm_uniform_vector_set_x (v
, scm_from_long (pos
), obj
);
1167 switch (SCM_TYP7 (v
))
1170 SCM_WRONG_TYPE_ARG (1, v
);
1173 scm_out_of_range (FUNC_NAME
, scm_from_long (pos
));
1175 SCM_WRONG_NUM_ARGS ();
1176 case scm_tc7_smob
: /* enclosed */
1179 if (scm_is_false (obj
))
1180 SCM_BITVEC_CLR(v
, pos
);
1181 else if (scm_is_eq (obj
, SCM_BOOL_T
))
1182 SCM_BITVEC_SET(v
, pos
);
1184 badobj
:SCM_WRONG_TYPE_ARG (2, obj
);
1186 case scm_tc7_string
:
1187 SCM_ASRTGO (SCM_CHARP (obj
), badobj
);
1188 scm_c_string_set_x (v
, pos
, obj
);
1190 case scm_tc7_vector
:
1192 SCM_VECTOR_SET (v
, pos
, obj
);
1195 return SCM_UNSPECIFIED
;
1199 /* attempts to unroll an array into a one-dimensional array.
1200 returns the unrolled array or #f if it can't be done. */
1201 /* if strict is not SCM_UNDEFINED, return #f if returned array
1202 wouldn't have contiguous elements. */
1203 SCM_DEFINE (scm_array_contents
, "array-contents", 1, 1, 0,
1204 (SCM ra
, SCM strict
),
1205 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1206 "without changing their order (last subscript changing fastest), then\n"
1207 "@code{array-contents} returns that shared array, otherwise it returns\n"
1208 "@code{#f}. All arrays made by @var{make-array} and\n"
1209 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1210 "@var{make-shared-array} may not be.\n\n"
1211 "If the optional argument @var{strict} is provided, a shared array will\n"
1212 "be returned only if its elements are stored internally contiguous in\n"
1214 #define FUNC_NAME s_scm_array_contents
1218 if (scm_is_uniform_vector (ra
))
1224 switch SCM_TYP7 (ra
)
1228 case scm_tc7_vector
:
1230 case scm_tc7_string
:
1235 size_t k
, ndim
= SCM_ARRAY_NDIM (ra
), len
= 1;
1236 if (!SCM_ARRAYP (ra
) || !SCM_ARRAY_CONTP (ra
))
1238 for (k
= 0; k
< ndim
; k
++)
1239 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1240 if (!SCM_UNBNDP (strict
))
1242 if (ndim
&& (1 != SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
))
1244 if (scm_tc7_bvect
== SCM_TYP7 (SCM_ARRAY_V (ra
)))
1246 if (len
!= SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) ||
1247 SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
||
1254 SCM v
= SCM_ARRAY_V (ra
);
1255 unsigned long length
= scm_to_ulong (scm_uniform_vector_length (v
));
1256 if ((len
== length
) && 0 == SCM_ARRAY_BASE (ra
) && SCM_ARRAY_DIMS (ra
)->inc
)
1260 sra
= scm_make_ra (1);
1261 SCM_ARRAY_DIMS (sra
)->lbnd
= 0;
1262 SCM_ARRAY_DIMS (sra
)->ubnd
= len
- 1;
1263 SCM_ARRAY_V (sra
) = SCM_ARRAY_V (ra
);
1264 SCM_ARRAY_BASE (sra
) = SCM_ARRAY_BASE (ra
);
1265 SCM_ARRAY_DIMS (sra
)->inc
= (ndim
? SCM_ARRAY_DIMS (ra
)[ndim
- 1].inc
: 1);
1274 scm_ra2contig (SCM ra
, int copy
)
1279 for (k
= SCM_ARRAY_NDIM (ra
); k
--;)
1280 len
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1281 k
= SCM_ARRAY_NDIM (ra
);
1282 if (SCM_ARRAY_CONTP (ra
) && ((0 == k
) || (1 == SCM_ARRAY_DIMS (ra
)[k
- 1].inc
)))
1284 if (scm_tc7_bvect
!= SCM_TYP7 (SCM_ARRAY_V (ra
)))
1286 if ((len
== SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra
)) &&
1287 0 == SCM_ARRAY_BASE (ra
) % SCM_LONG_BIT
&&
1288 0 == len
% SCM_LONG_BIT
))
1291 ret
= scm_make_ra (k
);
1292 SCM_ARRAY_BASE (ret
) = 0;
1295 SCM_ARRAY_DIMS (ret
)[k
].lbnd
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
;
1296 SCM_ARRAY_DIMS (ret
)[k
].ubnd
= SCM_ARRAY_DIMS (ra
)[k
].ubnd
;
1297 SCM_ARRAY_DIMS (ret
)[k
].inc
= inc
;
1298 inc
*= SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1;
1300 SCM_ARRAY_V (ret
) = scm_make_uve (inc
, scm_array_prototype (ra
));
1302 scm_array_copy_x (ra
, ret
);
1308 SCM_DEFINE (scm_uniform_array_read_x
, "uniform-array-read!", 1, 3, 0,
1309 (SCM ra
, SCM port_or_fd
, SCM start
, SCM end
),
1310 "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1311 "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
1312 "binary objects from @var{port-or-fdes}.\n"
1313 "If an end of file is encountered,\n"
1314 "the objects up to that point are put into @var{ura}\n"
1315 "(starting at the beginning) and the remainder of the array is\n"
1317 "The optional arguments @var{start} and @var{end} allow\n"
1318 "a specified region of a vector (or linearized array) to be read,\n"
1319 "leaving the remainder of the vector unchanged.\n\n"
1320 "@code{uniform-array-read!} returns the number of objects read.\n"
1321 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1322 "returned by @code{(current-input-port)}.")
1323 #define FUNC_NAME s_scm_uniform_array_read_x
1325 SCM cra
= SCM_UNDEFINED
, v
= ra
;
1332 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1333 if (SCM_UNBNDP (port_or_fd
))
1334 port_or_fd
= scm_cur_inp
;
1336 SCM_ASSERT (scm_is_integer (port_or_fd
)
1337 || (SCM_OPINPORTP (port_or_fd
)),
1338 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1339 vlen
= (SCM_TYP7 (v
) == scm_tc7_smob
1341 : scm_to_long (scm_uniform_vector_length (v
)));
1344 if (scm_is_uniform_vector (v
))
1346 base
= scm_uniform_vector_elements (v
);
1347 sz
= scm_uniform_vector_element_size (v
);
1353 badarg1
:SCM_WRONG_TYPE_ARG (SCM_ARG1
, v
);
1355 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1356 cra
= scm_ra2contig (ra
, 0);
1357 cstart
+= SCM_ARRAY_BASE (cra
);
1358 vlen
= SCM_ARRAY_DIMS (cra
)->inc
*
1359 (SCM_ARRAY_DIMS (cra
)->ubnd
- SCM_ARRAY_DIMS (cra
)->lbnd
+ 1);
1360 v
= SCM_ARRAY_V (cra
);
1362 case scm_tc7_string
:
1363 base
= NULL
; /* writing to strings is special, see below. */
1367 base
= (char *) SCM_BITVECTOR_BASE (v
);
1368 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1369 cstart
/= SCM_LONG_BIT
;
1375 if (!SCM_UNBNDP (start
))
1378 SCM_NUM2LONG (3, start
);
1380 if (offset
< 0 || offset
>= cend
)
1381 scm_out_of_range (FUNC_NAME
, start
);
1383 if (!SCM_UNBNDP (end
))
1386 SCM_NUM2LONG (4, end
);
1388 if (tend
<= offset
|| tend
> cend
)
1389 scm_out_of_range (FUNC_NAME
, end
);
1394 if (SCM_NIMP (port_or_fd
))
1396 scm_t_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
1397 int remaining
= (cend
- offset
) * sz
;
1398 size_t off
= (cstart
+ offset
) * sz
;
1400 if (pt
->rw_active
== SCM_PORT_WRITE
)
1401 scm_flush (port_or_fd
);
1403 ans
= cend
- offset
;
1404 while (remaining
> 0)
1406 if (pt
->read_pos
< pt
->read_end
)
1408 int to_copy
= min (pt
->read_end
- pt
->read_pos
,
1414 char *b
= scm_i_string_writable_chars (v
);
1415 memcpy (b
+ off
, pt
->read_pos
, to_copy
);
1416 scm_i_string_stop_writing ();
1419 memcpy (base
+ off
, pt
->read_pos
, to_copy
);
1420 pt
->read_pos
+= to_copy
;
1421 remaining
-= to_copy
;
1426 if (scm_fill_input (port_or_fd
) == EOF
)
1428 if (remaining
% sz
!= 0)
1430 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
1432 ans
-= remaining
/ sz
;
1439 pt
->rw_active
= SCM_PORT_READ
;
1441 else /* file descriptor. */
1446 char *b
= scm_i_string_writable_chars (v
);
1447 SCM_SYSCALL (ans
= read (scm_to_int (port_or_fd
),
1448 b
+ (cstart
+ offset
) * sz
,
1449 (sz
* (cend
- offset
))));
1450 scm_i_string_stop_writing ();
1453 SCM_SYSCALL (ans
= read (scm_to_int (port_or_fd
),
1454 base
+ (cstart
+ offset
) * sz
,
1455 (sz
* (cend
- offset
))));
1459 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1460 ans
*= SCM_LONG_BIT
;
1462 if (!scm_is_eq (v
, ra
) && !scm_is_eq (cra
, ra
))
1463 scm_array_copy_x (cra
, ra
);
1465 return scm_from_long (ans
);
1469 SCM_DEFINE (scm_uniform_array_write
, "uniform-array-write", 1, 3, 0,
1470 (SCM v
, SCM port_or_fd
, SCM start
, SCM end
),
1471 "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1472 "Writes all elements of @var{ura} as binary objects to\n"
1473 "@var{port-or-fdes}.\n\n"
1474 "The optional arguments @var{start}\n"
1475 "and @var{end} allow\n"
1476 "a specified region of a vector (or linearized array) to be written.\n\n"
1477 "The number of objects actually written is returned.\n"
1478 "@var{port-or-fdes} may be\n"
1479 "omitted, in which case it defaults to the value returned by\n"
1480 "@code{(current-output-port)}.")
1481 #define FUNC_NAME s_scm_uniform_array_write
1489 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
1491 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1492 if (SCM_UNBNDP (port_or_fd
))
1493 port_or_fd
= scm_cur_outp
;
1495 SCM_ASSERT (scm_is_integer (port_or_fd
)
1496 || (SCM_OPOUTPORTP (port_or_fd
)),
1497 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
1498 vlen
= (SCM_TYP7 (v
) == scm_tc7_smob
1500 : scm_to_long (scm_uniform_vector_length (v
)));
1503 if (scm_is_uniform_vector (v
))
1505 base
= scm_uniform_vector_elements (v
);
1506 sz
= scm_uniform_vector_element_size (v
);
1512 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1514 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1515 v
= scm_ra2contig (v
, 1);
1516 cstart
= SCM_ARRAY_BASE (v
);
1517 vlen
= (SCM_ARRAY_DIMS (v
)->inc
1518 * (SCM_ARRAY_DIMS (v
)->ubnd
- SCM_ARRAY_DIMS (v
)->lbnd
+ 1));
1519 v
= SCM_ARRAY_V (v
);
1521 case scm_tc7_string
:
1522 base
= scm_i_string_chars (v
);
1526 base
= (char *) SCM_BITVECTOR_BASE (v
);
1527 vlen
= (vlen
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1528 cstart
/= SCM_LONG_BIT
;
1534 if (!SCM_UNBNDP (start
))
1537 SCM_NUM2LONG (3, start
);
1539 if (offset
< 0 || offset
>= cend
)
1540 scm_out_of_range (FUNC_NAME
, start
);
1542 if (!SCM_UNBNDP (end
))
1545 SCM_NUM2LONG (4, end
);
1547 if (tend
<= offset
|| tend
> cend
)
1548 scm_out_of_range (FUNC_NAME
, end
);
1553 if (SCM_NIMP (port_or_fd
))
1555 const char *source
= base
+ (cstart
+ offset
) * sz
;
1557 ans
= cend
- offset
;
1558 scm_lfwrite (source
, ans
* sz
, port_or_fd
);
1560 else /* file descriptor. */
1562 SCM_SYSCALL (ans
= write (scm_to_int (port_or_fd
),
1563 base
+ (cstart
+ offset
) * sz
,
1564 (sz
* (cend
- offset
))));
1568 if (SCM_TYP7 (v
) == scm_tc7_bvect
)
1569 ans
*= SCM_LONG_BIT
;
1571 return scm_from_long (ans
);
1576 static char cnt_tab
[16] =
1577 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1579 SCM_DEFINE (scm_bit_count
, "bit-count", 2, 0, 0,
1580 (SCM b
, SCM bitvector
),
1581 "Return the number of occurrences of the boolean @var{b} in\n"
1583 #define FUNC_NAME s_scm_bit_count
1585 SCM_VALIDATE_BOOL (1, b
);
1586 SCM_ASSERT (SCM_BITVECTOR_P (bitvector
), bitvector
, 2, FUNC_NAME
);
1587 if (SCM_BITVECTOR_LENGTH (bitvector
) == 0) {
1590 unsigned long int count
= 0;
1591 unsigned long int i
= (SCM_BITVECTOR_LENGTH (bitvector
) - 1) / SCM_LONG_BIT
;
1592 unsigned long int w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1593 if (scm_is_false (b
)) {
1596 w
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (bitvector
) - 1) % SCM_LONG_BIT
);
1599 count
+= cnt_tab
[w
& 0x0f];
1603 return scm_from_ulong (count
);
1606 w
= SCM_UNPACK (SCM_VELTS (bitvector
)[i
]);
1607 if (scm_is_false (b
)) {
1617 SCM_DEFINE (scm_bit_position
, "bit-position", 3, 0, 0,
1618 (SCM item
, SCM v
, SCM k
),
1619 "Return the index of the first occurrance of @var{item} in bit\n"
1620 "vector @var{v}, starting from @var{k}. If there is no\n"
1621 "@var{item} entry between @var{k} and the end of\n"
1622 "@var{bitvector}, then return @code{#f}. For example,\n"
1625 "(bit-position #t #*000101 0) @result{} 3\n"
1626 "(bit-position #f #*0001111 3) @result{} #f\n"
1628 #define FUNC_NAME s_scm_bit_position
1630 long i
, lenw
, xbits
, pos
;
1631 register unsigned long w
;
1633 SCM_VALIDATE_BOOL (1, item
);
1634 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG2
, FUNC_NAME
);
1635 pos
= scm_to_long (k
);
1636 SCM_ASSERT_RANGE (3, k
, (pos
<= SCM_BITVECTOR_LENGTH (v
)) && (pos
>= 0));
1638 if (pos
== SCM_BITVECTOR_LENGTH (v
))
1641 lenw
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; /* watch for part words */
1642 i
= pos
/ SCM_LONG_BIT
;
1643 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1644 if (scm_is_false (item
))
1646 xbits
= (pos
% SCM_LONG_BIT
);
1648 w
= ((w
>> xbits
) << xbits
);
1649 xbits
= SCM_LONG_BIT
- 1 - (SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
;
1652 if (w
&& (i
== lenw
))
1653 w
= ((w
<< xbits
) >> xbits
);
1659 return scm_from_long (pos
);
1664 return scm_from_long (pos
+ 1);
1667 return scm_from_long (pos
+ 2);
1669 return scm_from_long (pos
+ 3);
1676 pos
+= SCM_LONG_BIT
;
1677 w
= SCM_UNPACK (SCM_VELTS (v
)[i
]);
1678 if (scm_is_false (item
))
1686 SCM_DEFINE (scm_bit_set_star_x
, "bit-set*!", 3, 0, 0,
1687 (SCM v
, SCM kv
, SCM obj
),
1688 "Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
1689 "selecting the entries to change. The return value is\n"
1692 "If @var{kv} is a bit vector, then those entries where it has\n"
1693 "@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
1694 "@var{kv} and @var{v} must be the same length. When @var{obj}\n"
1695 "is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
1696 "@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
1699 "(define bv #*01000010)\n"
1700 "(bit-set*! bv #*10010001 #t)\n"
1702 "@result{} #*11010011\n"
1705 "If @var{kv} is a u32vector, then its elements are\n"
1706 "indices into @var{v} which are set to @var{obj}.\n"
1709 "(define bv #*01000010)\n"
1710 "(bit-set*! bv #u32(5 2 7) #t)\n"
1712 "@result{} #*01100111\n"
1714 #define FUNC_NAME s_scm_bit_set_star_x
1716 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1718 if (SCM_BITVECTOR_P (kv
))
1722 if (SCM_BITVECTOR_LENGTH (v
) != SCM_BITVECTOR_LENGTH (kv
))
1723 scm_misc_error (NULL
,
1724 "bit vectors must have equal length",
1727 if (scm_is_false (obj
))
1728 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1730 SCM_BITVECTOR_BASE (v
) [k
] &= ~SCM_BITVECTOR_BASE (kv
) [k
];
1731 else if (scm_is_eq (obj
, SCM_BOOL_T
))
1732 for (k
= (SCM_BITVECTOR_LENGTH (v
) + SCM_LONG_BIT
- 1) / SCM_LONG_BIT
;
1734 SCM_BITVECTOR_BASE (v
) [k
] |= SCM_BITVECTOR_BASE (kv
) [k
];
1736 scm_wrong_type_arg_msg (NULL
, 0, obj
, "boolean");
1738 else if (scm_is_true (scm_u32vector_p (kv
)))
1740 size_t vlen
= SCM_BITVECTOR_LENGTH (v
);
1741 size_t ulen
= scm_c_uniform_vector_length (kv
);
1745 if (scm_to_bool (obj
) == 0)
1746 for (i
= 0; i
< ulen
; i
++)
1748 /* XXX - poof, there goes the uniform vector efficiency
1751 k
= scm_to_uint32 (scm_uniform_vector_ref (kv
,
1752 scm_from_size_t (i
)));
1754 scm_out_of_range (FUNC_NAME
, scm_from_uint32 (k
));
1755 SCM_BITVEC_CLR(v
, k
);
1758 for (i
= 0; i
< ulen
; i
++)
1760 k
= scm_to_uint32 (scm_uniform_vector_ref (kv
,
1761 scm_from_size_t (i
)));
1763 scm_out_of_range (FUNC_NAME
, scm_from_uint32 (k
));
1764 SCM_BITVEC_SET(v
, k
);
1768 scm_wrong_type_arg_msg (NULL
, 0, kv
, "bitvector or u32vector");
1770 return SCM_UNSPECIFIED
;
1775 SCM_DEFINE (scm_bit_count_star
, "bit-count*", 3, 0, 0,
1776 (SCM v
, SCM kv
, SCM obj
),
1777 "Return a count of how many entries in bit vector @var{v} are\n"
1778 "equal to @var{obj}, with @var{kv} selecting the entries to\n"
1781 "If @var{kv} is a bit vector, then those entries where it has\n"
1782 "@code{#t} are the ones in @var{v} which are considered.\n"
1783 "@var{kv} and @var{v} must be the same length.\n"
1785 "If @var{kv} is a u32vector, then it contains\n"
1786 "the indexes in @var{v} to consider.\n"
1791 "(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
1792 "(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
1794 #define FUNC_NAME s_scm_bit_count_star
1798 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1800 if (SCM_BITVECTOR_P (kv
))
1805 if (SCM_BITVECTOR_LENGTH (v
) != SCM_BITVECTOR_LENGTH (kv
))
1806 scm_misc_error (NULL
,
1807 "bit vectors must have equal length",
1810 if (0 == SCM_BITVECTOR_LENGTH (v
))
1813 fObj
= scm_to_bool (obj
);
1815 i
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
;
1816 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK (SCM_VELTS (v
)[i
]) : ~ SCM_UNPACK (SCM_VELTS (v
)[i
]));
1817 k
<<= SCM_LONG_BIT
- 1 - ((SCM_BITVECTOR_LENGTH (v
) - 1) % SCM_LONG_BIT
);
1821 count
+= cnt_tab
[k
& 0x0f];
1823 return scm_from_long (count
);
1825 /* urg. repetitive (see above.) */
1826 k
= SCM_UNPACK (SCM_VELTS (kv
)[i
]) & (fObj
? SCM_UNPACK(SCM_VELTS (v
)[i
]) : ~SCM_UNPACK (SCM_VELTS (v
)[i
]));
1829 else if (scm_is_true (scm_u32vector_p (kv
)))
1831 size_t vlen
= SCM_BITVECTOR_LENGTH (v
);
1832 size_t ulen
= scm_c_uniform_vector_length (kv
);
1836 if (scm_to_bool (obj
) == 0)
1837 for (i
= 0; i
< ulen
; i
++)
1839 k
= scm_to_uint32 (scm_uniform_vector_ref (kv
,
1840 scm_from_size_t (i
)));
1842 scm_out_of_range (FUNC_NAME
, scm_from_long (k
));
1843 if (!SCM_BITVEC_REF(v
, k
))
1847 for (i
= 0; i
< ulen
; i
++)
1849 k
= scm_to_uint32 (scm_uniform_vector_ref (kv
,
1850 scm_from_size_t (i
)));
1852 scm_out_of_range (FUNC_NAME
, scm_from_long (k
));
1853 if (SCM_BITVEC_REF (v
, k
))
1858 scm_wrong_type_arg_msg (NULL
, 0, kv
, "bitvector or u32vector");
1860 return scm_from_long (count
);
1865 SCM_DEFINE (scm_bit_invert_x
, "bit-invert!", 1, 0, 0,
1867 "Modify the bit vector @var{v} by replacing each element with\n"
1869 #define FUNC_NAME s_scm_bit_invert_x
1873 SCM_ASSERT (SCM_BITVECTOR_P (v
), v
, SCM_ARG1
, FUNC_NAME
);
1875 k
= SCM_BITVECTOR_LENGTH (v
);
1876 for (k
= (k
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
--;)
1877 SCM_BITVECTOR_BASE (v
) [k
] = ~SCM_BITVECTOR_BASE (v
) [k
];
1879 return SCM_UNSPECIFIED
;
1885 scm_istr2bve (SCM str
)
1887 size_t len
= scm_i_string_length (str
);
1888 SCM v
= scm_make_u1vector (scm_from_size_t (len
), SCM_UNDEFINED
);
1889 long *data
= (long *) SCM_VELTS (v
);
1890 register unsigned long mask
;
1893 const char *c_str
= scm_i_string_chars (str
);
1895 for (k
= 0; k
< (len
+ SCM_LONG_BIT
- 1) / SCM_LONG_BIT
; k
++)
1898 j
= len
- k
* SCM_LONG_BIT
;
1899 if (j
> SCM_LONG_BIT
)
1901 for (mask
= 1L; j
--; mask
<<= 1)
1919 ra2l (SCM ra
, unsigned long base
, unsigned long k
)
1921 register SCM res
= SCM_EOL
;
1922 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
1924 if (SCM_ARRAY_DIMS (ra
)[k
].ubnd
< SCM_ARRAY_DIMS (ra
)[k
].lbnd
)
1926 i
= base
+ (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
) * inc
;
1927 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
1932 res
= scm_cons (ra2l (ra
, i
, k
+ 1), res
);
1940 res
= scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra
), scm_from_size_t (i
)), res
);
1947 SCM_DEFINE (scm_array_to_list
, "array->list", 1, 0, 0,
1949 "Return a list consisting of all the elements, in order, of\n"
1951 #define FUNC_NAME s_scm_array_to_list
1956 if (scm_is_uniform_vector (v
))
1957 return scm_uniform_vector_to_list (v
);
1959 SCM_ASRTGO (SCM_NIMP (v
), badarg1
);
1963 badarg1
:SCM_WRONG_TYPE_ARG (1, v
);
1965 SCM_ASRTGO (SCM_ARRAYP (v
), badarg1
);
1966 return ra2l (v
, SCM_ARRAY_BASE (v
), 0);
1967 case scm_tc7_vector
:
1969 return scm_vector_to_list (v
);
1970 case scm_tc7_string
:
1971 return scm_string_to_list (v
);
1974 long *data
= (long *) SCM_VELTS (v
);
1975 register unsigned long mask
;
1976 for (k
= (SCM_BITVECTOR_LENGTH (v
) - 1) / SCM_LONG_BIT
; k
> 0; k
--)
1977 for (mask
= 1UL << (SCM_LONG_BIT
- 1); mask
; mask
>>= 1)
1978 res
= scm_cons (scm_from_bool(((long *) data
)[k
] & mask
), res
);
1979 for (mask
= 1L << ((SCM_BITVECTOR_LENGTH (v
) % SCM_LONG_BIT
) - 1); mask
; mask
>>= 1)
1980 res
= scm_cons (scm_from_bool(((long *) data
)[k
] & mask
), res
);
1988 static int l2ra(SCM lst
, SCM ra
, unsigned long base
, unsigned long k
);
1990 SCM_DEFINE (scm_list_to_uniform_array
, "list->uniform-array", 3, 0, 0,
1991 (SCM ndim
, SCM prot
, SCM lst
),
1992 "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
1993 "Return a uniform array of the type indicated by prototype\n"
1994 "@var{prot} with elements the same as those of @var{lst}.\n"
1995 "Elements must be of the appropriate type, no coercions are\n"
1998 "The argument @var{ndim} determines the number of dimensions\n"
1999 "of the array. It is either an exact integer, giving the\n"
2000 " number directly, or a list of exact integers, whose length\n"
2001 "specifies the number of dimensions and each element is the\n"
2002 "lower index bound of its dimension.")
2003 #define FUNC_NAME s_scm_list_to_uniform_array
2011 if (scm_is_integer (ndim
))
2013 size_t k
= scm_to_size_t (ndim
);
2016 shape
= scm_cons (scm_length (row
), shape
);
2018 row
= scm_car (row
);
2025 shape
= scm_cons (scm_list_2 (scm_car (ndim
),
2026 scm_sum (scm_sum (scm_car (ndim
),
2028 scm_from_int (-1))),
2030 ndim
= scm_cdr (ndim
);
2031 if (scm_is_pair (ndim
))
2032 row
= scm_car (row
);
2038 ra
= scm_dimensions_to_uniform_array (scm_reverse_x (shape
, SCM_EOL
), prot
,
2040 if (scm_is_null (shape
))
2042 SCM_ASRTGO (1 == scm_ilength (lst
), badlst
);
2043 scm_array_set_x (ra
, SCM_CAR (lst
), SCM_EOL
);
2046 if (!SCM_ARRAYP (ra
))
2048 unsigned long length
= scm_to_ulong (scm_uniform_vector_length (ra
));
2049 for (k
= 0; k
< length
; k
++, lst
= SCM_CDR (lst
))
2050 scm_array_set_x (ra
, SCM_CAR (lst
), scm_from_ulong (k
));
2053 if (l2ra (lst
, ra
, SCM_ARRAY_BASE (ra
), 0))
2056 badlst
:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
2062 l2ra (SCM lst
, SCM ra
, unsigned long base
, unsigned long k
)
2064 register long inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2065 register long n
= (1 + SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
);
2068 return (scm_is_null (lst
));
2069 if (k
< SCM_ARRAY_NDIM (ra
) - 1)
2073 if (!scm_is_pair (lst
))
2075 ok
= ok
&& l2ra (SCM_CAR (lst
), ra
, base
, k
+ 1);
2077 lst
= SCM_CDR (lst
);
2079 if (!scm_is_null (lst
))
2086 if (!scm_is_pair (lst
))
2088 scm_array_set_x (SCM_ARRAY_V (ra
), SCM_CAR (lst
), scm_from_ulong (base
));
2090 lst
= SCM_CDR (lst
);
2092 if (!scm_is_null (lst
))
2100 rapr1 (SCM ra
, unsigned long j
, unsigned long k
, SCM port
, scm_print_state
*pstate
)
2103 long n
= (SCM_TYP7 (ra
) == scm_tc7_smob
2105 : scm_to_long (scm_uniform_vector_length (ra
)));
2108 switch SCM_TYP7 (ra
)
2113 SCM_ARRAY_BASE (ra
) = j
;
2115 scm_iprin1 (ra
, port
, pstate
);
2116 for (j
+= inc
; n
-- > 0; j
+= inc
)
2118 scm_putc (' ', port
);
2119 SCM_ARRAY_BASE (ra
) = j
;
2120 scm_iprin1 (ra
, port
, pstate
);
2124 if (k
+ 1 < SCM_ARRAY_NDIM (ra
))
2127 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2128 for (i
= SCM_ARRAY_DIMS (ra
)[k
].lbnd
; i
< SCM_ARRAY_DIMS (ra
)[k
].ubnd
; i
++)
2130 scm_putc ('(', port
);
2131 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2132 scm_puts (") ", port
);
2135 if (i
== SCM_ARRAY_DIMS (ra
)[k
].ubnd
)
2136 { /* could be zero size. */
2137 scm_putc ('(', port
);
2138 rapr1 (ra
, j
, k
+ 1, port
, pstate
);
2139 scm_putc (')', port
);
2143 if (SCM_ARRAY_NDIM (ra
) > 0)
2144 { /* Could be zero-dimensional */
2145 inc
= SCM_ARRAY_DIMS (ra
)[k
].inc
;
2146 n
= (SCM_ARRAY_DIMS (ra
)[k
].ubnd
- SCM_ARRAY_DIMS (ra
)[k
].lbnd
+ 1);
2150 ra
= SCM_ARRAY_V (ra
);
2153 /* scm_tc7_bvect and scm_tc7_llvect only? */
2155 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2156 for (j
+= inc
; n
-- > 0; j
+= inc
)
2158 scm_putc (' ', port
);
2159 scm_iprin1 (scm_cvref (ra
, j
, SCM_UNDEFINED
), port
, pstate
);
2162 case scm_tc7_string
:
2165 src
= scm_i_string_chars (ra
);
2167 scm_iprin1 (SCM_MAKE_CHAR (src
[j
]), port
, pstate
);
2168 if (SCM_WRITINGP (pstate
))
2169 for (j
+= inc
; n
-- > 0; j
+= inc
)
2171 scm_putc (' ', port
);
2172 scm_iprin1 (SCM_MAKE_CHAR (src
[j
]), port
, pstate
);
2175 for (j
+= inc
; n
-- > 0; j
+= inc
)
2176 scm_putc (src
[j
], port
);
2177 scm_remember_upto_here_1 (ra
);
2184 /* Print dimension DIM of ARRAY.
2188 scm_i_print_array_dimension (SCM array
, int dim
, int base
,
2189 SCM port
, scm_print_state
*pstate
)
2191 scm_t_array_dim
*dim_spec
= SCM_ARRAY_DIMS (array
) + dim
;
2194 scm_putc ('(', port
);
2197 scm_putc ('{', port
);
2198 scm_intprint (dim_spec
->lbnd
, 10, port
);
2199 scm_putc (':', port
);
2200 scm_intprint (dim_spec
->ubnd
, 10, port
);
2201 scm_putc (':', port
);
2202 scm_intprint (dim_spec
->inc
, 10, port
);
2203 scm_putc ('}', port
);
2206 for (idx
= dim_spec
->lbnd
; idx
<= dim_spec
->ubnd
; idx
++)
2208 if (dim
< SCM_ARRAY_NDIM(array
)-1)
2209 scm_i_print_array_dimension (array
, dim
+1, base
, port
, pstate
);
2211 scm_iprin1 (scm_cvref (SCM_ARRAY_V (array
), base
, SCM_UNDEFINED
),
2213 if (idx
< dim_spec
->ubnd
)
2214 scm_putc (' ', port
);
2215 base
+= dim_spec
->inc
;
2218 scm_putc (')', port
);
2223 scm_i_legacy_tag (SCM v
)
2225 switch (SCM_TYP7 (v
))
2229 case scm_tc7_string
:
2231 case scm_tc7_vector
:
2239 /* Print a array. (Only for strict arrays, not for strings, uniform
2240 vectors, vectors and other stuff that can masquerade as an array.)
2243 /* The array tag is generally of the form
2245 * #<rank><unif><@lower><@lower>...
2247 * <rank> is a positive integer in decimal giving the rank of the
2248 * array. It is omitted when the rank is 1 and the array is
2249 * non-shared and has zero-origin. For shared arrays and for a
2250 * non-zero origin, the rank is always printed even when it is 1 to
2251 * dinstinguish them from ordinary vectors.
2253 * <unif> is the tag for a uniform (or homogenous) numeric vector,
2254 * like u8, s16, etc, as defined by SRFI-4. It is omitted when the
2255 * array is not uniform.
2257 * <@lower> is a 'at' sign followed by a integer in decimal giving the
2258 * lower bound of a dimension. There is one <@lower> for each
2259 * dimension. When all lower bounds are zero, all <@lower> are
2264 * #(1 2 3) is non-uniform array of rank 1 with lower bound 0 in
2265 * dimension 0. (I.e., a regular vector.)
2267 * #@2(1 2 3) is non-uniform array of rank 1 with lower bound 2 in
2270 * #2((1 2 3) (4 5 6)) is a non-uniform array of rank 2; a 3x3
2271 * matrix with index ranges 0..2 and 0..2.
2273 * #u32(0 1 2) is a uniform u8 array of rank 1.
2275 * #2u32@2@3((1 2) (2 3)) is a uniform u8 array of rank 2 with index
2276 * ranges 2..3 and 3..4.
2280 scm_i_print_array (SCM array
, SCM port
, scm_print_state
*pstate
)
2282 long ndim
= SCM_ARRAY_NDIM (array
);
2283 scm_t_array_dim
*dim_specs
= SCM_ARRAY_DIMS (array
);
2284 unsigned long base
= SCM_ARRAY_BASE (array
);
2287 scm_putc ('#', port
);
2288 if (ndim
!= 1 || dim_specs
[0].lbnd
!= 0)
2289 scm_intprint (ndim
, 10, port
);
2290 if (scm_is_uniform_vector (SCM_ARRAY_V (array
)))
2291 scm_puts (scm_i_uniform_vector_tag (SCM_ARRAY_V (array
)), port
);
2293 scm_puts (scm_i_legacy_tag (SCM_ARRAY_V (array
)), port
);
2294 for (i
= 0; i
< ndim
; i
++)
2295 if (dim_specs
[i
].lbnd
!= 0)
2297 for (i
= 0; i
< ndim
; i
++)
2299 scm_putc ('@', port
);
2300 scm_uintprint (dim_specs
[i
].lbnd
, 10, port
);
2306 scm_putc ('{', port
);
2307 scm_uintprint (base
, 10, port
);
2308 scm_putc ('}', port
);
2311 return scm_i_print_array_dimension (array
, 0, base
, port
, pstate
);
2314 /* Read an array. This function can also read vectors and uniform
2315 vectors. Also, the conflict between '#f' and '#f32' and '#f64' is
2318 C is the first character read after the '#'.
2326 static SCM scm_i_proc_make_vector
;
2328 static tag_proto tag_proto_table
[] = {
2329 { "", &scm_i_proc_make_vector
},
2330 { "u8", &scm_i_proc_make_u8vector
},
2331 { "s8", &scm_i_proc_make_s8vector
},
2332 { "u16", &scm_i_proc_make_u16vector
},
2333 { "s16", &scm_i_proc_make_s16vector
},
2334 { "u32", &scm_i_proc_make_u32vector
},
2335 { "s32", &scm_i_proc_make_s32vector
},
2336 { "u64", &scm_i_proc_make_u64vector
},
2337 { "s64", &scm_i_proc_make_s64vector
},
2338 { "f32", &scm_i_proc_make_f32vector
},
2339 { "f64", &scm_i_proc_make_f64vector
},
2344 scm_i_tag_to_prototype (const char *tag
, SCM port
)
2348 for (tp
= tag_proto_table
; tp
->tag
; tp
++)
2349 if (!strcmp (tp
->tag
, tag
))
2350 return *(tp
->proto_var
);
2352 #if SCM_ENABLE_DEPRECATED
2354 /* Recognize the old syntax, producing the old prototypes.
2356 SCM proto
= SCM_EOL
;
2357 const char *instead
;
2361 proto
= SCM_MAKE_CHAR ('a');
2365 proto
= scm_from_int (1);
2369 proto
= scm_from_int (-1);
2373 proto
= scm_from_double (1.0);
2377 proto
= scm_divide (scm_from_int (1), scm_from_int (3));
2381 proto
= SCM_MAKE_CHAR (0);
2385 proto
= scm_from_locale_symbol ("s");
2389 proto
= scm_from_locale_symbol ("l");
2393 proto
= scm_c_make_rectangular (0.0, 1.0);
2397 if (!scm_is_eq (proto
, SCM_EOL
) && tag
[1] == '\0')
2399 scm_c_issue_deprecation_warning_fmt
2400 ("The tag '%c' is deprecated for uniform vectors. "
2401 "Use '%s' instead.", tag
[0], instead
);
2407 scm_i_input_error (NULL
, port
,
2408 "unrecognized uniform array tag: ~a",
2409 scm_list_1 (scm_from_locale_string (tag
)));
2414 scm_i_read_array (SCM port
, int c
)
2421 SCM lower_bounds
, elements
;
2423 /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
2424 the array code can not deal with zero-length dimensions yet, and
2425 we want to allow zero-length vectors, of course.
2429 scm_ungetc (c
, port
);
2430 return scm_vector (scm_read (port
));
2433 /* Disambiguate between '#f' and uniform floating point vectors.
2437 c
= scm_getc (port
);
2438 if (c
!= '3' && c
!= '6')
2441 scm_ungetc (c
, port
);
2448 goto continue_reading_tag
;
2451 /* Read rank. We disallow arrays of rank zero since they do not
2452 seem to work reliably yet. */
2455 while ('0' <= c
&& c
<= '9')
2457 rank
= 10*rank
+ c
-'0';
2459 c
= scm_getc (port
);
2464 scm_i_input_error (NULL
, port
,
2465 "array rank must be positive", SCM_EOL
);
2469 continue_reading_tag
:
2470 while (c
!= EOF
&& c
!= '(' && c
!= '@' && tag_len
< 80)
2473 c
= scm_getc (port
);
2475 tag
[tag_len
] = '\0';
2477 /* Read lower bounds. */
2478 lower_bounds
= SCM_EOL
;
2481 /* Yeah, right, we should use some ready-made integer parsing
2488 c
= scm_getc (port
);
2492 c
= scm_getc (port
);
2494 while ('0' <= c
&& c
<= '9')
2496 lbnd
= 10*lbnd
+ c
-'0';
2497 c
= scm_getc (port
);
2499 lower_bounds
= scm_cons (scm_from_long (sign
*lbnd
), lower_bounds
);
2502 /* Read nested lists of elements.
2505 scm_i_input_error (NULL
, port
,
2506 "missing '(' in vector or array literal",
2508 scm_ungetc (c
, port
);
2509 elements
= scm_read (port
);
2511 if (scm_is_null (lower_bounds
))
2512 lower_bounds
= scm_from_size_t (rank
);
2513 else if (scm_ilength (lower_bounds
) != rank
)
2514 scm_i_input_error (NULL
, port
,
2515 "the number of lower bounds must match the array rank",
2518 /* Construct array. */
2519 return scm_list_to_uniform_array (lower_bounds
,
2520 scm_i_tag_to_prototype (tag
, port
),
2525 scm_raprin1 (SCM exp
, SCM port
, scm_print_state
*pstate
)
2528 unsigned long base
= 0;
2530 if (SCM_ARRAYP (exp
) && !SCM_ARRAYP (SCM_ARRAY_V (exp
)))
2531 return scm_i_print_array (exp
, port
, pstate
);
2533 scm_putc ('#', port
);
2539 long ndim
= SCM_ARRAY_NDIM (v
);
2540 base
= SCM_ARRAY_BASE (v
);
2541 v
= SCM_ARRAY_V (v
);
2545 scm_puts ("<enclosed-array ", port
);
2546 rapr1 (exp
, base
, 0, port
, pstate
);
2547 scm_putc ('>', port
);
2552 scm_intprint (ndim
, 10, port
);
2557 if (scm_is_eq (exp
, v
))
2558 { /* a uve, not an scm_array */
2559 register long i
, j
, w
;
2560 scm_putc ('*', port
);
2561 for (i
= 0; i
< (SCM_BITVECTOR_LENGTH (exp
)) / SCM_LONG_BIT
; i
++)
2563 scm_t_bits w
= SCM_UNPACK (SCM_VELTS (exp
)[i
]);
2564 for (j
= SCM_LONG_BIT
; j
; j
--)
2566 scm_putc (w
& 1 ? '1' : '0', port
);
2570 j
= SCM_BITVECTOR_LENGTH (exp
) % SCM_LONG_BIT
;
2573 w
= SCM_UNPACK (SCM_VELTS (exp
)[SCM_BITVECTOR_LENGTH (exp
) / SCM_LONG_BIT
]);
2576 scm_putc (w
& 1 ? '1' : '0', port
);
2583 scm_putc ('b', port
);
2585 case scm_tc7_string
:
2586 scm_putc ('a', port
);
2589 scm_putc ('(', port
);
2590 rapr1 (exp
, base
, 0, port
, pstate
);
2591 scm_putc (')', port
);
2595 SCM_DEFINE (scm_array_creator
, "array-creator", 1, 0, 0,
2597 "Return a procedure that would produce an array of the same type\n"
2598 "as @var{array}, if used as the @var{creator} with\n"
2599 "@code{make-uniform-array}.")
2600 #define FUNC_NAME s_scm_array_creator
2605 if (SCM_ARRAYP (ra
))
2607 ra
= SCM_ARRAY_V (ra
);
2611 if (scm_is_uniform_vector (ra
))
2612 return scm_i_uniform_vector_creator (ra
);
2613 else if (scm_is_true (scm_vector_p (ra
)))
2614 return scm_i_proc_make_vector
;
2615 else if (scm_is_string (ra
))
2616 return scm_i_proc_make_string
;
2617 else if (SCM_BITVECTOR_P (ra
))
2618 return scm_i_proc_make_u1vector
;
2619 else if (SCM_ARRAYP (ra
))
2620 scm_misc_error (NULL
, "creator not known for enclosed array: ~a",
2621 scm_list_1 (orig_ra
));
2623 scm_wrong_type_arg_msg (NULL
, 0, ra
, "array");
2625 scm_misc_error (NULL
, "creator not known for array content: ~a",
2630 SCM_DEFINE (scm_array_prototype
, "array-prototype", 1, 0, 0,
2632 "Return an object that would produce an array of the same type\n"
2633 "as @var{array}, if used as the @var{prototype} for\n"
2634 "@code{make-uniform-array}.")
2635 #define FUNC_NAME s_scm_array_prototype
2638 SCM_ASRTGO (SCM_NIMP (ra
), badarg
);
2640 switch SCM_TYP7 (ra
)
2643 badarg
:SCM_WRONG_TYPE_ARG (1, ra
);
2645 if (SCM_ARRAYP (ra
))
2648 return SCM_UNSPECIFIED
;
2649 ra
= SCM_ARRAY_V (ra
);
2654 SCM proto
= scm_i_get_old_prototype (ra
);
2655 if (scm_is_eq (SCM_UNSPECIFIED
, proto
))
2659 case scm_tc7_vector
:
2664 case scm_tc7_string
:
2665 return SCM_MAKE_CHAR ('a');
2672 array_mark (SCM ptr
)
2674 return SCM_ARRAY_V (ptr
);
2679 array_free (SCM ptr
)
2681 scm_gc_free (SCM_ARRAY_MEM (ptr
),
2682 (sizeof (scm_t_array
)
2683 + SCM_ARRAY_NDIM (ptr
) * sizeof (scm_t_array_dim
)),
2691 scm_tc16_array
= scm_make_smob_type ("array", 0);
2692 scm_set_smob_mark (scm_tc16_array
, array_mark
);
2693 scm_set_smob_free (scm_tc16_array
, array_free
);
2694 scm_set_smob_print (scm_tc16_array
, scm_raprin1
);
2695 scm_set_smob_equalp (scm_tc16_array
, scm_array_equal_p
);
2696 exactly_one_third
= scm_permanent_object (scm_divide (scm_from_int (1),
2698 scm_add_feature ("array");
2699 #include "libguile/unif.x"
2701 scm_i_proc_make_vector
= scm_variable_ref (scm_c_lookup ("make-vector"));
2702 scm_i_proc_make_string
= scm_variable_ref (scm_c_lookup ("make-string"));
2703 scm_i_proc_make_u1vector
= scm_variable_ref (scm_c_lookup ("make-u1vector"));