1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

Extend core vector-copy to r7rs vector-copy

* libguile/vectors.h: Declare scm_vector_copy_partial.
* libguile/vectors.c (scm_vector_copy_partial): As stated.
  (scm_vector_copy): Reuse scm_vector_copy_partial.
* module/scheme/base.scm: Reuse core vector-copy.
* module/srfi/srfi-43: Reuse core vector-copy.
* test-suite/tests/vectors.test: Test vector-copy.
This commit is contained in:
Daniel Llorens 2021-08-05 19:43:21 +02:00
parent bfda8d3972
commit a34c762de0
6 changed files with 59 additions and 43 deletions

View file

@ -6387,6 +6387,7 @@ Store @var{fill} in every position of @var{vec}. The value
returned by @code{vector-fill!} is unspecified. returned by @code{vector-fill!} is unspecified.
@end deffn @end deffn
@rnindex vector-copy
@deffn {Scheme Procedure} vector-copy vec @deffn {Scheme Procedure} vector-copy vec
@deffnx {C Function} scm_vector_copy (vec) @deffnx {C Function} scm_vector_copy (vec)
Return a copy of @var{vec}. Return a copy of @var{vec}.

View file

@ -265,17 +265,36 @@ scm_c_make_vector (size_t k, SCM fill)
} }
#undef FUNC_NAME #undef FUNC_NAME
SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0, SCM_DEFINE (scm_vector_copy_partial, "vector-copy", 1, 2, 0,
(SCM vec), (SCM vec, SCM start, SCM end),
"Return a copy of @var{vec}.") "Returns a freshly allocated vector containing the elements\n"
#define FUNC_NAME s_scm_vector_copy "of @var{vec} between @var{start} and @var{end}.\n\n"
"@var{start} defaults to 0 and @var{end} defaults to the\n"
"length of @var{vec}.")
#define FUNC_NAME s_scm_vector_copy_partial
{ {
SCM result; SCM result;
if (SCM_I_IS_VECTOR (vec)) if (SCM_I_IS_VECTOR (vec))
{ {
size_t len = SCM_I_VECTOR_LENGTH (vec); size_t cstart = 0, cend = SCM_I_VECTOR_LENGTH (vec);
if (!SCM_UNBNDP (start))
{
cstart = scm_to_size_t (start);
SCM_ASSERT_RANGE (SCM_ARG2, start, cstart<=cend);
if (!SCM_UNBNDP (end))
{
size_t e = scm_to_size_t (end);
SCM_ASSERT_RANGE (SCM_ARG3, end, e>=cstart && e<=cend);
cend = e;
}
}
size_t len = cend-cstart;
result = make_vector (len); result = make_vector (len);
memcpy (SCM_I_VECTOR_WELTS (result), SCM_I_VECTOR_ELTS (vec), len * sizeof(SCM)); memcpy (SCM_I_VECTOR_WELTS (result), SCM_I_VECTOR_ELTS (vec) + cstart,
len * sizeof(SCM));
} }
else else
{ {
@ -290,6 +309,9 @@ SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
("Using vector-copy on arrays is deprecated. " ("Using vector-copy on arrays is deprecated. "
"Use array-copy instead."); "Use array-copy instead.");
if (SCM_UNBNDP (start))
scm_misc_error (s_scm_vector_copy_partial, "Too many arguments", SCM_EOL);
result = make_vector (len); result = make_vector (len);
dst = SCM_I_VECTOR_WELTS (result); dst = SCM_I_VECTOR_WELTS (result);
for (i = 0; i < len; i++, src += inc) for (i = 0; i < len; i++, src += inc)
@ -301,6 +323,12 @@ SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
} }
#undef FUNC_NAME #undef FUNC_NAME
SCM
scm_vector_copy (SCM vec)
{
return scm_vector_copy_partial (vec, SCM_UNDEFINED, SCM_UNDEFINED);
}
SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0, SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
(SCM vec), (SCM vec),

View file

@ -88,7 +88,7 @@ SCM_API SCM *scm_vector_writable_elements (SCM vec,
#define SCM_I_VECTOR_LENGTH(x) (((size_t) SCM_CELL_WORD_0 (x)) >> 8) #define SCM_I_VECTOR_LENGTH(x) (((size_t) SCM_CELL_WORD_0 (x)) >> 8)
SCM_INTERNAL SCM scm_i_vector_equal_p (SCM x, SCM y); SCM_INTERNAL SCM scm_i_vector_equal_p (SCM x, SCM y);
SCM_INTERNAL SCM scm_vector_copy_partial (SCM vec, SCM start, SCM end);
SCM_INTERNAL void scm_init_vectors (void); SCM_INTERNAL void scm_init_vectors (void);

View file

@ -56,7 +56,6 @@
bytevector bytevector-append bytevector bytevector-append
string->vector vector->string string->vector vector->string
(r7:string->utf8 . string->utf8) (r7:string->utf8 . string->utf8)
(r7:vector-copy . vector-copy)
(r7:vector->list . vector->list) (r7:vector->list . vector->list)
(r7:vector-fill! . vector-fill!) (r7:vector-fill! . vector-fill!)
vector-copy! vector-append vector-for-each vector-map vector-copy! vector-append vector-for-each vector-map
@ -116,7 +115,7 @@
(char-ready? . u8-ready?) (char-ready? . u8-ready?)
unless unless
unquote unquote-splicing values unquote unquote-splicing values
vector vector vector-copy
vector-length vector-ref vector-set! vector? vector-length vector-ref vector-set! vector?
when with-exception-handler write-char when with-exception-handler write-char
zero?)) zero?))
@ -433,23 +432,6 @@
;;; vector ;;; vector
(define (%subvector v start end)
(define mlen (- end start))
(define out (make-vector (- end start)))
(define (itr r)
(if (= r mlen)
out
(begin
(vector-set! out r (vector-ref v (+ start r)))
(itr (+ r 1)))))
(itr 0))
(define r7:vector-copy
(case-lambda*
((v) (vector-copy v))
((v start #:optional (end (vector-length v)))
(%subvector v start end))))
(define* (vector-copy! target tstart source (define* (vector-copy! target tstart source
#:optional (sstart 0) (send (vector-length source))) #:optional (sstart 0) (send (vector-length source)))
"Copy a block of elements from SOURCE to TARGET, both of which must be "Copy a block of elements from SOURCE to TARGET, both of which must be
@ -467,7 +449,7 @@ defaults to 0 and SEND defaults to the length of SOURCE."
(case-lambda* (case-lambda*
((v) (vector->list v)) ((v) (vector->list v))
((v start #:optional (end (vector-length v))) ((v start #:optional (end (vector-length v)))
(vector->list (%subvector v start end))))) (vector->list (vector-copy v start end)))))
(define vector-map (define vector-map
(case-lambda* (case-lambda*
@ -518,7 +500,7 @@ defaults to 0 and SEND defaults to the length of SOURCE."
(case-lambda* (case-lambda*
((v) (list->string (vector->list v))) ((v) (list->string (vector->list v)))
((v start #:optional (end (vector-length v))) ((v start #:optional (end (vector-length v)))
(vector->string (%subvector v start end))))) (vector->string (vector-copy v start end)))))
(define r7:vector-fill! (define r7:vector-fill!
(case-lambda* (case-lambda*

View file

@ -204,7 +204,6 @@ error for the number of seeds to vary between iterations."
(define guile-vector-copy (@ (guile) vector-copy)) (define guile-vector-copy (@ (guile) vector-copy))
;; TODO: Enhance Guile core 'vector-copy' to do this.
(define vector-copy (define vector-copy
(case-lambda* (case-lambda*
"(vector-copy vec [start [end [fill]]]) -> vector "(vector-copy vec [start [end [fill]]]) -> vector
@ -217,23 +216,20 @@ VEC, the slots in the new vector that obviously cannot be filled by
elements from VEC are filled with FILL, whose default value is elements from VEC are filled with FILL, whose default value is
unspecified." unspecified."
((v) (guile-vector-copy v)) ((v) (guile-vector-copy v))
((v start) ((v start) (guile-vector-copy v start))
(assert-vector v 'vector-copy)
(let ((len (vector-length v)))
(assert-valid-start start len 'vector-copy)
(let ((result (make-vector (- len start))))
(vector-move-left! v start len result 0)
result)))
((v start end #:optional (fill *unspecified*)) ((v start end #:optional (fill *unspecified*))
(assert-vector v 'vector-copy) (assert-vector v 'vector-copy)
(let ((len (vector-length v))) (let ((len (vector-length v)))
(unless (and (exact-integer? start) (if (<= end len)
(exact-integer? end) (guile-vector-copy v start end)
(<= 0 start end)) (begin
(error-from 'vector-copy "invalid index range" start end)) (unless (and (exact-integer? start)
(let ((result (make-vector (- end start) fill))) (exact-integer? end)
(vector-move-left! v start (min end len) result 0) (<= 0 start end))
result))))) (error-from 'vector-copy "invalid index range" start end))
(let ((result (make-vector (- end start) fill)))
(vector-move-left! v start (min end len) result 0)
result)))))))
(define vector-reverse-copy (define vector-reverse-copy
(let () (let ()

View file

@ -31,6 +31,15 @@
exception:immutable-vector exception:immutable-vector
(vector-set! '#(1 2 3) 0 4))) (vector-set! '#(1 2 3) 0 4)))
(with-test-prefix "vector-copy"
(pass-if "defaults"
(equal? #(1 2 3) (vector-copy #(1 2 3))))
(pass-if "default end"
(equal? #(2 3) (vector-copy #(1 2 3) 1)))
(pass-if "start end"
(equal? #(2) (vector-copy #(1 2 3) 1 2))))
(with-test-prefix "vector->list" (with-test-prefix "vector->list"
(pass-if "simple vector" (pass-if "simple vector"