From 319ea7ea007f82b91a4c5ec0ca75cb123756dbe7 Mon Sep 17 00:00:00 2001 From: Noel Welsh Date: Fri, 3 Dec 2010 12:15:59 +0000 Subject: [PATCH] Change in-fXvector (for flvector and fxvector) to allow start, stop, and end args. Tests segfault in repeatable but apparently unrelated places --- collects/racket/fixnum.rkt | 4 ++- collects/racket/flonum.rkt | 4 ++- collects/racket/private/for.rkt | 6 +++- collects/racket/private/vector-wraps.rkt | 36 ++++++-------------- collects/scribblings/reference/fixnums.scrbl | 33 +++++++++++++++--- collects/scribblings/reference/flonums.scrbl | 34 +++++++++++++++--- 6 files changed, 79 insertions(+), 38 deletions(-) diff --git a/collects/racket/fixnum.rkt b/collects/racket/fixnum.rkt index 1e6a6aeac7..11c23b3704 100644 --- a/collects/racket/fixnum.rkt +++ b/collects/racket/fixnum.rkt @@ -1,6 +1,7 @@ #lang scheme/base (require '#%flfxnum - "private/vector-wraps.rkt") + "private/vector-wraps.rkt" + "unsafe/ops.rkt") (provide fx->fl fl->fx fxabs @@ -18,6 +19,7 @@ (define-vector-wraps "fxvector" fxvector? fxvector-length fxvector-ref fxvector-set! make-fxvector + unsafe-fxvector-ref unsafe-fxvector-set! unsafe-fxvector-length in-fxvector* in-fxvector for/fxvector diff --git a/collects/racket/flonum.rkt b/collects/racket/flonum.rkt index e7f4d65622..fef4fa7a3b 100644 --- a/collects/racket/flonum.rkt +++ b/collects/racket/flonum.rkt @@ -1,6 +1,7 @@ #lang racket/base (require '#%flfxnum - "private/vector-wraps.rkt") + "private/vector-wraps.rkt" + "unsafe/ops.rkt") (provide fl+ fl- fl* fl/ flabs flsqrt flexp fllog @@ -17,6 +18,7 @@ (define-vector-wraps "flvector" flvector? flvector-length flvector-ref flvector-set! make-flvector + unsafe-flvector-ref unsafe-flvector-set! unsafe-flvector-length in-flvector* in-flvector for/flvector diff --git a/collects/racket/private/for.rkt b/collects/racket/private/for.rkt index 0c9ea01e6c..e926bcee2f 100644 --- a/collects/racket/private/for.rkt +++ b/collects/racket/private/for.rkt @@ -60,7 +60,11 @@ define-sequence-syntax make-do-sequence - :do-in) + :do-in + + define-in-vector-like + define-:vector-like-gen + (for-syntax make-in-vector-like)) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; sequence transformers: diff --git a/collects/racket/private/vector-wraps.rkt b/collects/racket/private/vector-wraps.rkt index 9f335e6cf9..5ad461aeb1 100644 --- a/collects/racket/private/vector-wraps.rkt +++ b/collects/racket/private/vector-wraps.rkt @@ -7,6 +7,7 @@ (define-syntax-rule (define-vector-wraps fXvector-str fXvector? fXvector-length fXvector-ref fXvector-set! make-fXvector + unsafe-fXvector-ref unsafe-fXvector-set! unsafe-fXvector-length in-fXvector* in-fXvector for/fXvector @@ -14,32 +15,17 @@ fXvector-copy) (... (begin - (define (in-fXvector* flv) - (let ((n (fXvector-length flv))) - (make-do-sequence - (lambda () - (values (lambda (i) (fXvector-ref flv i)) - add1 - 0 - (lambda (i) (fx< i n)) - (lambda (x) #t) - (lambda (i x) #t)))))) + (define-:vector-like-gen :fXvector-gen unsafe-fXvector-ref) + + (define-in-vector-like in-fXvector* + fXvector-str fXvector? fXvector-length :fXvector-gen) (define-sequence-syntax in-fXvector - (lambda () (syntax in-fXvector*)) - (lambda (stx) - (syntax-case stx () - (((x) (in-fXvector flv-expr)) - (syntax/loc stx - (() (:do-in (((v) flv-expr)) - (when (not (fXvector? v)) - (error 'in-fXvector "expecting a ~a, got ~a" fXvector-str v)) - ((i 0) (n (fXvector-length v))) - (fx< i n) - (((x) (fXvector-ref v i))) - #t - #t - ((add1 i) n)))))))) + (lambda () #'in-fXvector*) + (make-in-vector-like #'fXvector? + #'unsafe-fXvector-length + #'in-fXvector* + #'unsafe-fXvector-ref)) (define (list->fXvector l) (let ((n (length l))) @@ -108,5 +94,5 @@ (let* ([len (- end start)] [vec (make-fXvector len)]) (for ([i (in-range len)]) - (fXvector-set! vec i (fXvector-ref flv (+ i start)))) + (unsafe-fXvector-set! vec i (unsafe-fXvector-ref flv (+ i start)))) vec))))) diff --git a/collects/scribblings/reference/fixnums.scrbl b/collects/scribblings/reference/fixnums.scrbl index 6a7db20dfb..48a21daeb7 100644 --- a/collects/scribblings/reference/fixnums.scrbl +++ b/collects/scribblings/reference/fixnums.scrbl @@ -155,12 +155,35 @@ Creates a fresh @tech{fxvector} of size @racket[(- end start)], with all of the elements of @racket[vec] from @racket[start] (inclusive) to @racket[end] (exclusive).} -@defproc[(in-fxvector (v fxvector?)) sequence?]{ +@defproc[(in-fxvector [vec vector?] + [start exact-nonnegative-integer? 0] + [stop (or/c exact-nonnegative-integer? #f) #f] + [step (and/c exact-integer? (not/c zero?)) 1]) + sequence?]{ + Returns a sequence equivalent to @racket[vec] when no optional + arguments are supplied. -Produces a sequence that gives the elements of @scheme[v] in order. -Inside a @scheme[for] form, this can be optimized to step through the -elements of @scheme[v] efficiently as in @scheme[in-list], -@scheme[in-vector], etc.} + The optional arguments @racket[start], @racket[stop], and + @racket[step] are analogous to @racket[in-range], except that a + @racket[#f] value for @racket[stop] is equivalent to + @racket[(vector-length vec)]. That is, the first element in the + sequence is @racket[(vector-ref vec start)], and each successive + element is generated by adding @racket[step] to index of the previous + element. The sequence stops before an index that would be greater or + equal to @racket[end] if @racket[step] is non-negative, or less or + equal to @racket[end] if @racket[step] is negative. + + If @racket[start] is less than @racket[stop] and @racket[step] is + negative, then the @exnraise[exn:fail:contract:mismatch]. Similarly, + if @racket[start] is more than @racket[stop] and @racket[step] is + positive, then the @exnraise[exn:fail:contract:mismatch]. The + @racket[start] and @racket[stop] values are @emph{not} checked against + the size of @racket[vec], so access can fail when an element is + demanded from the sequence. + + An @racket[in-fxvector] application can provide better + performance for @tech{fxvector} iteration when it appears directly in a @racket[for] clause. +} @deftogether[( @defform*[((for/fxvector (for-clause ...) body ...) diff --git a/collects/scribblings/reference/flonums.scrbl b/collects/scribblings/reference/flonums.scrbl index 3e12674546..225666172c 100644 --- a/collects/scribblings/reference/flonums.scrbl +++ b/collects/scribblings/reference/flonums.scrbl @@ -171,12 +171,36 @@ Creates a fresh @tech{flvector} of size @racket[(- end start)], with all of the elements of @racket[vec] from @racket[start] (inclusive) to @racket[end] (exclusive).} -@defproc[(in-flvector (v flvector?)) sequence?]{ -Produces a sequence that gives the elements of @scheme[v] in order. -Inside a @scheme[for] form, this can be optimized to step through the -elements of @scheme[v] efficiently as in @scheme[in-list], -@scheme[in-vector], etc.} +@defproc[(in-flvector [vec vector?] + [start exact-nonnegative-integer? 0] + [stop (or/c exact-nonnegative-integer? #f) #f] + [step (and/c exact-integer? (not/c zero?)) 1]) + sequence?]{ + Returns a sequence equivalent to @racket[vec] when no optional + arguments are supplied. + + The optional arguments @racket[start], @racket[stop], and + @racket[step] are analogous to @racket[in-range], except that a + @racket[#f] value for @racket[stop] is equivalent to + @racket[(vector-length vec)]. That is, the first element in the + sequence is @racket[(vector-ref vec start)], and each successive + element is generated by adding @racket[step] to index of the previous + element. The sequence stops before an index that would be greater or + equal to @racket[end] if @racket[step] is non-negative, or less or + equal to @racket[end] if @racket[step] is negative. + + If @racket[start] is less than @racket[stop] and @racket[step] is + negative, then the @exnraise[exn:fail:contract:mismatch]. Similarly, + if @racket[start] is more than @racket[stop] and @racket[step] is + positive, then the @exnraise[exn:fail:contract:mismatch]. The + @racket[start] and @racket[stop] values are @emph{not} checked against + the size of @racket[vec], so access can fail when an element is + demanded from the sequence. + + An @racket[in-flvector] application can provide better + performance for @tech{flvector} iteration when it appears directly in a @racket[for] clause. +} @deftogether[( @defform*[((for/flvector (for-clause ...) body ...)