diff --git a/collects/math/private/array/array-print.rkt b/collects/math/private/array/array-print.rkt index 727abf4168..6bfd51de63 100644 --- a/collects/math/private/array/array-print.rkt +++ b/collects/math/private/array/array-print.rkt @@ -18,10 +18,7 @@ (: print-array (All (A) ((Array A) Symbol Output-Port (U #t #f 0 1) -> Any))) ;; The logic in `print-array' causes the REPL printer to try printing an array in each layout, and ;; keep the first successful one. An overflowing line means failure. -(define (print-array orig-arr name port mode) - ;; Try to compute each element only once - (define arr (array-lazy orig-arr)) - +(define (print-array arr name port mode) ;; Called to print array elements; may recur (e.g. printing arrays of arrays) ;; We never have to consider the `mode' argument again after defining `recur-print' (define recur-print diff --git a/collects/math/private/array/array-struct.rkt b/collects/math/private/array/array-struct.rkt index a2613e3df4..e4d9e2f6c9 100644 --- a/collects/math/private/array/array-struct.rkt +++ b/collects/math/private/array/array-struct.rkt @@ -4,17 +4,17 @@ typed/racket/base (for-syntax racket/base syntax/parse) "array-syntax.rkt" - (except-in "typed-array-struct.rkt" build-array)) + (except-in "typed-array-struct.rkt" build-array build-strict-array)) (require/untyped-contract (begin (require "typed-array-struct.rkt")) "typed-array-struct.rkt" - [build-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]) + [build-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))] + [build-strict-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]) (define-syntax array? (make-rename-transformer #'Array?)) (define-syntax array-shape (make-rename-transformer #'Array-shape)) (define-syntax array-size (make-rename-transformer #'Array-size)) -(define-syntax array-strict? (make-rename-transformer #'Array-strict?)) (define-syntax unsafe-array-proc (make-rename-transformer #'Array-unsafe-proc)) (provide @@ -24,10 +24,13 @@ array-shape array-dims array-size + array-strict + array-strict! array-strict? make-unsafe-array-proc build-array unsafe-build-array + unsafe-build-strict-array unsafe-array-proc array-lazy array @@ -44,6 +47,10 @@ (define-syntax (array stx) (syntax-parse stx - [(_ e:expr) - (syntax/loc stx (array/syntax array list flat-list->array e))] + [(_ e:expr) (syntax/loc stx (array/syntax array list flat-list->array e))] [_:id (raise-syntax-error 'array "not allowed as an expression" stx)])) + +(define-syntax-rule (array-strict arr-expr) + (let ([arr arr-expr]) + (array-strict! arr) + arr)) diff --git a/collects/math/private/array/fcarray-struct.rkt b/collects/math/private/array/fcarray-struct.rkt index c07cedc4a3..af7e4084c7 100644 --- a/collects/math/private/array/fcarray-struct.rkt +++ b/collects/math/private/array/fcarray-struct.rkt @@ -32,7 +32,7 @@ Float-Complex ds (λ (j v) (unsafe-flvector-set! xs j (real-part v)) (unsafe-flvector-set! ys j (imag-part v))))) - (fcarray ds 0 #t proc set-proc xs ys)) + (fcarray ds (flvector-length xs) (box #t) void proc set-proc xs ys)) (: unsafe-vector->fcarray (Indexes (Vectorof Number) -> FCArray)) (define (unsafe-vector->fcarray ds zs) diff --git a/collects/math/private/array/flarray-struct.rkt b/collects/math/private/array/flarray-struct.rkt index 75d5474913..d0f430473c 100644 --- a/collects/math/private/array/flarray-struct.rkt +++ b/collects/math/private/array/flarray-struct.rkt @@ -25,7 +25,7 @@ (define (unsafe-flarray ds vs) (define proc (make-unsafe-array-proc ds (λ (j) (unsafe-flvector-ref vs j)))) (define set-proc (make-unsafe-array-set-proc Float ds (λ (j v) (unsafe-flvector-set! vs j v)))) - (flarray ds 0 #t proc set-proc vs)) + (flarray ds (flvector-length vs) (box #t) void proc set-proc vs)) (: unsafe-vector->flarray (Indexes (Vectorof Real) -> FlArray)) (define (unsafe-vector->flarray ds vs) diff --git a/collects/math/private/array/mutable-array.rkt b/collects/math/private/array/mutable-array.rkt index 048df3182b..e214d952dc 100644 --- a/collects/math/private/array/mutable-array.rkt +++ b/collects/math/private/array/mutable-array.rkt @@ -23,7 +23,6 @@ mutable-array ;; Conversion array->mutable-array - array-strict flat-vector->matrix) (define-syntax (mutable-array stx) diff --git a/collects/math/private/array/typed-array-constructors.rkt b/collects/math/private/array/typed-array-constructors.rkt index 5e50d26d32..4ba51bbc6b 100644 --- a/collects/math/private/array/typed-array-constructors.rkt +++ b/collects/math/private/array/typed-array-constructors.rkt @@ -10,7 +10,7 @@ (define (make-array ds v) (let ([ds (check-array-shape ds (λ () (raise-argument-error 'make-array "(Vectorof Index)" 0 ds v)))]) - (unsafe-build-array ds (λ (js) v)))) + (unsafe-build-strict-array ds (λ (js) v)))) (: axis-index-array (In-Indexes Integer -> (Array Index))) (define (axis-index-array ds k) @@ -18,21 +18,21 @@ ds (λ () (raise-argument-error 'axis-index-array "(Vectorof Index)" 0 ds k)))] [dims (vector-length ds)]) (cond [(and (0 . <= . k) (k . < . dims)) - (unsafe-build-array ds (λ: ([js : Indexes]) (unsafe-vector-ref js k)))] + (unsafe-build-strict-array ds (λ: ([js : Indexes]) (unsafe-vector-ref js k)))] [else (raise-argument-error 'axis-index-array (format "Index < ~a" dims) 1 ds k)]))) (: index-array (In-Indexes -> (Array Index))) (define (index-array ds) (let ([ds (check-array-shape ds (λ () (raise-argument-error 'index-array "(Vectorof Index)" ds)))]) - (unsafe-build-array ds (λ: ([js : Indexes]) - (assert (unsafe-array-index->value-index ds js) index?))))) + (unsafe-build-strict-array ds (λ: ([js : Indexes]) + (assert (unsafe-array-index->value-index ds js) index?))))) (: indexes-array (In-Indexes -> (Array Indexes))) (define (indexes-array ds) (let ([ds (check-array-shape ds (λ () (raise-argument-error 'indexes-array "(Vectorof Index)" ds)))]) - (unsafe-build-array ds (λ: ([js : Indexes]) (vector-copy-all js))))) + (unsafe-build-strict-array ds (λ: ([js : Indexes]) (vector-copy-all js))))) (: diagonal-array (All (A) (Integer Integer A A -> (Array A)))) (define (diagonal-array dims size on-value off-value) @@ -42,15 +42,15 @@ (define: ds : Indexes (make-vector dims size)) ;; specialize for various cases (cond [(or (dims . <= . 1) (size . <= . 1)) - (unsafe-build-array ds (λ: ([js : Indexes]) on-value))] + (unsafe-build-strict-array ds (λ: ([js : Indexes]) on-value))] [(= dims 2) - (unsafe-build-array + (unsafe-build-strict-array ds (λ: ([js : Indexes]) (define j0 (unsafe-vector-ref js 0)) (define j1 (unsafe-vector-ref js 1)) (if (= j0 j1) on-value off-value)))] [else - (unsafe-build-array + (unsafe-build-strict-array ds (λ: ([js : Indexes]) (define j0 (unsafe-vector-ref js 0)) (let: loop : A ([i : Nonnegative-Fixnum 1]) diff --git a/collects/math/private/array/typed-array-struct.rkt b/collects/math/private/array/typed-array-struct.rkt index 087d10bb0d..a8df1228ca 100644 --- a/collects/math/private/array/typed-array-struct.rkt +++ b/collects/math/private/array/typed-array-struct.rkt @@ -37,16 +37,6 @@ ;; =================================================================================================== ;; Array data type: a function whose domain has a rectangular shape -(: array-guard (All (A) (Indexes Index Boolean (Indexes -> A) Symbol - -> (Values Indexes Index Boolean (Indexes -> A))))) -(define (array-guard ds size strict? proc name) - (cond [(zero? size) - (let ([size (array-shape-size ds)]) - (cond [(index? size) (values (vector->immutable-vector ds) size strict? proc)] - [else (error 'array "array size ~e (for shape ~e) is too large (is not an Index)" - size ds)]))] - [else (values (vector->immutable-vector ds) size strict? proc)])) - #| (: array-procedure (All (A) ((Array A) In-Indexes -> A))) (define (array-procedure arr js) @@ -55,9 +45,9 @@ (struct: (A) Array ([shape : Indexes] [size : Index] - [strict? : Boolean] + [strict? : (Boxof Boolean)] + [strict! : (-> Void)] [unsafe-proc : (Indexes -> A)]) - #:guard array-guard #:property prop:custom-print-quotable 'never #:property prop:custom-write (λ (arr port mode) ((array-custom-printer) arr 'array port mode)) #:property prop:equal+hash (list array-recur-equal? array-hash-code array-hash-code) @@ -70,42 +60,79 @@ (ref (unsafe-array-index->value-index ds js)))) (: array-dims (All (A) ((Array A) -> Index))) -(begin-encourage-inline - (define (array-dims arr) (vector-length (Array-shape arr)))) +(define (array-dims arr) + (vector-length (Array-shape arr))) + +(: array-strict? (All (A) ((Array A) -> Boolean))) +(define (array-strict? arr) + (unbox (Array-strict? arr))) + +(: array-strict! (All (A) ((Array A) -> Void))) +(define (array-strict! arr) + (define strict? (Array-strict? arr)) + (unless (unbox strict?) + ((Array-strict! arr)) + (set-box! strict? #t))) + +(: unsafe-build-array (All (A) (Indexes (Indexes -> A) -> (Array A)))) +(define (unsafe-build-array ds f) + (define size (check-array-shape-size 'unsafe-build-array ds)) + (define: data : (U #f (Vectorof A)) #f) + (define (strict!) + (set! data (inline-build-array-data ds (λ (js j) (f js)) A))) + (define unsafe-proc + (λ: ([js : Indexes]) + (let ([data data]) + (if data + (unsafe-vector-ref data (unsafe-array-index->value-index ds js)) + (f js))))) + (Array ds size ((inst box Boolean) #f) strict! unsafe-proc)) + +(: unsafe-build-strict-array (All (A) (Indexes (Indexes -> A) -> (Array A)))) +(define (unsafe-build-strict-array ds f) + (define size (check-array-shape-size 'unsafe-build-strict-array ds)) + (Array ds size (box #t) void f)) (: build-array (All (A) (In-Indexes (Indexes -> A) -> (Array A)))) (define (build-array ds proc) (let ([ds (check-array-shape ds (λ () (raise-argument-error 'build-array "(Vectorof Index)" 0 ds proc)))]) - (Array ds 0 #f (λ: ([js : Indexes]) - (proc (vector->immutable-vector js)))))) + (unsafe-build-array ds (λ: ([js : Indexes]) + (proc (vector->immutable-vector js)))))) -(: unsafe-build-array (All (A) (Indexes (Indexes -> A) -> (Array A)))) -(define (unsafe-build-array ds proc) - (Array ds 0 #f proc)) +(: build-strict-array (All (A) (In-Indexes (Indexes -> A) -> (Array A)))) +(define (build-strict-array ds proc) + (let ([ds (check-array-shape + ds (λ () (raise-argument-error 'build-strict-array "(Vectorof Index)" 0 ds proc)))]) + (unsafe-build-strict-array ds (λ: ([js : Indexes]) + (proc (vector->immutable-vector js)))))) -(: flat-list->array (All (A) ((Vectorof Integer) (Listof A) -> (Array A)))) +(: flat-list->array (All (A) (In-Indexes (Listof A) -> (Array A)))) (define (flat-list->array ds lst) (let ([ds (check-array-shape ds (λ () (raise-argument-error 'array "(Vectorof Index)" ds)))]) (define vs (list->vector lst)) - (unsafe-build-array + (unsafe-build-strict-array ds (λ: ([js : Indexes]) (unsafe-vector-ref vs (unsafe-array-index->value-index ds js)))))) (: array-lazy (All (A) ((Array A) -> (Array A)))) (define (array-lazy arr) (define ds (Array-shape arr)) + (define size (Array-size arr)) (define proc (Array-unsafe-proc arr)) (define: vs : (Vectorof (Promise A)) (inline-build-array-data ds (λ (js j) ;; Because `delay' captures js in its closure, if we don't make this copy, `js' will have ;; been mutated by the time the promise is forced + ;; Using vector->immutable-vector to copy won't work: `proc' might need to mutate `js' (let ([js (vector-copy-all js)]) (delay (proc js)))) (Promise A))) - (unsafe-build-array - ds (λ: ([js : Indexes]) - (force (unsafe-vector-ref vs (unsafe-array-index->value-index ds js)))))) + (define (strict!) (for: ([v (in-vector vs)]) (force v))) + (define unsafe-proc + (λ: ([js : Indexes]) + (force (unsafe-vector-ref vs (unsafe-array-index->value-index ds js))))) + (Array ds size ((inst box Boolean) #f) strict! unsafe-proc)) ;; =================================================================================================== ;; Abstract settable array data type diff --git a/collects/math/private/array/typed-mutable-array.rkt b/collects/math/private/array/typed-mutable-array.rkt index 66d630195c..c926bb48ec 100644 --- a/collects/math/private/array/typed-mutable-array.rkt +++ b/collects/math/private/array/typed-mutable-array.rkt @@ -21,7 +21,7 @@ (define (unsafe-mutable-array ds vs) (define proc (make-unsafe-array-proc ds (λ (j) (unsafe-vector-ref vs j)))) (define set-proc (make-unsafe-array-set-proc A ds (λ (j v) (unsafe-vector-set! vs j v)))) - (Mutable-Array ds (vector-length vs) #t proc set-proc vs)) + (Mutable-Array ds (vector-length vs) (box #t) void proc set-proc vs)) (: make-mutable-array (All (A) (In-Indexes (Vectorof A) -> (Mutable-Array A)))) (define (make-mutable-array ds vs) @@ -48,8 +48,3 @@ (define ds (array-shape arr)) (define g (unsafe-array-proc arr)) (unsafe-mutable-array ds (inline-build-array-data ds (λ (js j) (g js)) A))) - -(: array-strict (All (A) ((Array A) -> (Array A)))) -(define (array-strict arr) - (cond [(array-strict? arr) arr] - [else (array->mutable-array arr)])) diff --git a/collects/math/private/array/typed-utils.rkt b/collects/math/private/array/typed-utils.rkt index 5444c7d272..7007149dc7 100644 --- a/collects/math/private/array/typed-utils.rkt +++ b/collects/math/private/array/typed-utils.rkt @@ -37,6 +37,12 @@ (loop (+ i 1) (* n d))] [else n]))) + (: check-array-shape-size (Symbol Indexes -> Index)) + (define (check-array-shape-size name ds) + (define size (array-shape-size ds)) + (cond [(index? size) size] + [else (error name "array size ~e (for shape ~e) is too large (is not an Index)" size ds)])) + (: check-array-shape (In-Indexes (-> Nothing) -> Indexes)) (define (check-array-shape ds fail) (define dims (vector-length ds)) diff --git a/collects/math/private/array/untyped-array-convert.rkt b/collects/math/private/array/untyped-array-convert.rkt index a7a6497e76..2e7a34975f 100644 --- a/collects/math/private/array/untyped-array-convert.rkt +++ b/collects/math/private/array/untyped-array-convert.rkt @@ -84,7 +84,7 @@ (raise-argument-error 'list*->array "rectangular (Listof* A)" lst)) (define ds (list-shape lst pred?)) - (cond [(pred? lst) (unsafe-build-array #() (λ (js) lst))] + (cond [(pred? lst) (unsafe-build-strict-array #() (λ (js) lst))] [ds (let ([ds (check-array-shape ds raise-shape-error)]) (define size (array-shape-size ds)) (unsafe-mutable-array ds (list*->flat-vector lst size pred?)))] @@ -97,7 +97,7 @@ (raise-argument-error 'vector*->array "rectangular (Vectorof* A)" vec)) (define ds (vector-shape vec pred?)) - (cond [(pred? vec) (unsafe-build-array #() (λ (js) vec))] + (cond [(pred? vec) (unsafe-build-strict-array #() (λ (js) vec))] [ds (let ([ds (check-array-shape ds raise-shape-error)]) (define dims (vector-length ds)) (unsafe-build-array diff --git a/collects/math/scribblings/math-array.scrbl b/collects/math/scribblings/math-array.scrbl index 95a2990b03..4d0e78d586 100644 --- a/collects/math/scribblings/math-array.scrbl +++ b/collects/math/scribblings/math-array.scrbl @@ -82,14 +82,14 @@ are @deftech{non-strict}. Almost all array functions exported by @racket[math/ar non-strict arrays. Exceptions are noted in the documentation. @bold{Non-strict arrays are not lazy.} By default, arrays do not cache computed elements, but -like functions, recompute them every time they are referred to. See @secref{array:strictness} -for details. +like functions, recompute them every time they are referred to. Unlike functions, they can have +every element computed and cached at once. See @secref{array:strictness} for details. A @deftech{pointwise} operation is one that operates on each array element independently, on each corresponding pair of elements from two arrays independently, or on a corresponding collection of elements from many arrays independently. This is usually done using @racket[array-map]. -When a pointwise operation is performed on two arrays with different shapes, the arrays are +When a pointwise operation is performed on arrays with different shapes, the arrays are @deftech{broadcast} so that their shapes match. See @secref{array:broadcasting} for details. @subsection{Quick Start} @@ -113,9 +113,9 @@ Arrays can be made @tech{strict} using @racket[array-strict] or @racket[array->m @interaction[#:eval typed-eval (array-strict arr) (array->mutable-array arr)] -The difference is that @racket[(array-strict arr)] returns @racket[arr] whenever @racket[arr] is -already strict. (It therefore has a less precise return type.) -See @secref{array:strictness} for details. +While @racket[(array-strict arr)] causes @racket[arr] to compute and store all of its elements +at once, @racket[array->mutable-array] makes a strict copy. See @secref{array:strictness} for +details. Arrays can be indexed using @racket[array-ref], and settable arrays can be mutated using @racket[array-set!]: @@ -189,17 +189,18 @@ between array operations, so not doing so provides opportunities for future para @margin-note*{Still, it is easier to reason about non-strict array performance than lazy array performance.} -The downside is that it is more difficult to reason about the performance characteristics of -operations on non-strict arrays. Also, when using arrays, you must decide which arrays to make -strict. (This can be done using the @racket[array-strict] function.) Fortunately, there is a -simple rule of thumb: +One downside is that it is more difficult to reason about the performance characteristics of +operations on non-strict arrays. Also, when using arrays, the user must decide which arrays to make +strict. (This can be done using @racket[array-strict!] or @racket[array-strict].) Fortunately, +there is a simple rule of thumb: @nested[#:style 'inset]{@bold{Make arrays strict when you must refer to most of their elements more than once or twice.}} Additionally, having to name an array is a good indicator that it should be strict. In the following example, which computes @racket[(+ (expt x x) (expt x x))] for @racket[x] from @racket[0] -to @racket[2499], every element in @racket[xrr] is computed twice: +to @racket[2499], elements in @racket[xrr] are computed twice whenever elements in @racket[res] +are referred to: @racketblock[(define xrr (array-expt (index-array #(50 50)) (index-array #(50 50)))) (define res (array+ xrr xrr))] @@ -208,12 +209,9 @@ Having to name @racket[xrr] means we should make it strict: (array-expt (index-array #(50 50)) (index-array #(50 50))))) (define res (array+ xrr xrr))] -Doing so halves the time it takes to compute @racket[res]'s elements because each -@racket[(expt x x)] is computed only once. +Doing so halves the time it takes to compute @racket[res]'s elements. -An exception to these guidelines is non-strict arrays returned from constructors like -@racket[make-array], which barely compute anything at all. Such exceptions are noted in each -function's documentation. Another exception is returning an array from a function. In this +An exception to these guidelines is returning an array from a function. In this case, application sites should make the array strict, if necessary. If you cannot determine whether to make arrays strict, or are using arrays for so-called @@ -423,9 +421,27 @@ their predicates have @racket[Struct] filters: @defproc[(array-strict? [arr (Array A)]) Boolean]{ Returns @racket[#t] when @racket[arr] is @tech{strict}. @examples[#:eval typed-eval - (define arr (array #[0 1 2 3])) + (define arr (array+ (array 10) (array #[0 1 2 3]))) (array-strict? arr) - (array-strict? (array-strict arr))] + (array-strict! arr) + (array-strict? arr)] +} + +@defproc[(array-strict! [arr (Array A)]) Void]{ +Causes @racket[arr] to compute and store all of its elements. Thereafter, @racket[arr] +computes its elements by retrieving them from the store. + +If @racket[arr] is already strict, @racket[(array-strict! arr)] does nothing. +} + +@defform[(array-strict arr) + #:contracts ([arr (Array A)])]{ +An expression form of @racket[array-strict!], which is often more convenient. First evaluates +@racket[(array-strict! arr)], then returns @racket[arr]. + +This is a macro so that Typed Racket will preserve @racket[arr]'s type exactly. If it were a +function, @racket[(array-strict arr)] would always have the type @racket[(Array A)], even if +@racket[arr] were a subtype of @racket[(Array A)], such as @racket[(Mutable-Array A)]. } @defproc[(array-shape [arr (Array A)]) Indexes]{ @@ -463,7 +479,7 @@ Returns the vector of data that @racket[arr] contains. @section{Construction} @defform[(array #[#[...] ...])]{ -Creates an @racket[Array] from nested rows of expressions. +Creates a @tech{strict} @racket[Array] from nested rows of expressions. The vector syntax @racket[#[...]] delimits rows. These may be nested to any depth, and must have a rectangular shape. Using square parentheses is not required, but is encouraged to help distinguish @@ -515,17 +531,17 @@ the array's elements: @defproc[(make-array [ds In-Indexes] [value A]) (Array A)]{ Returns an array with @tech{shape} @racket[ds], with every element's value as @racket[value]. -Analogous to @racket[make-vector], but the result is @tech{non-strict}. +Analogous to @racket[make-vector], but does not allocate storage for its elements. @examples[#:eval typed-eval (make-array #() 5) (make-array #(1 2) 'sym) (make-array #(4 0 2) "Invisible")] -It is useless to make a strict copy of an array returned by @racket[make-array]. +The arrays returned by @racket[make-array] are @tech{strict}. } @defproc[(build-array [ds In-Indexes] [proc (Indexes -> A)]) (Array A)]{ Returns an array with @tech{shape} @racket[ds] and @tech{procedure} @racket[proc]. -Analogous to @racket[build-vector], but the result is @tech{non-strict}. +Analogous to @racket[build-vector], but returns a @tech{non-strict} array. @examples[#:eval typed-eval (eval:alts (define: fibs : (Array Natural) @@ -539,23 +555,12 @@ Analogous to @racket[build-vector], but the result is @tech{non-strict}. (eval:alts fibs (ann (array #[0 1 1 2 3 5 8 13 21 34]) (Array Natural)))] -Because @racket[build-array] returns a non-strict array, @racket[fibs] may refer to itself +Because @racket[build-array] returns non-strict arrays, @racket[fibs] may refer to itself within its definition. Of course, this naïve implementation computes its elements in time exponential in the size of @racket[fibs]. A quick, widely applicable fix is given in @racket[array-lazy]'s documentation. } -@defproc[(array-strict [arr (Array A)]) (Array A)]{ -Returns a @tech{strict} array with the same elements as @racket[arr]. If -@racket[(array-strict? arr)] is @racket[#t], returns @racket[arr]. - -Currently, if @racket[(array-strict? arr)] is @racket[#f], @racket[(array-strict arr)] returns -a new @racket[Mutable-Array]. Typed Racket code is unlikely to accidentally rely on this fact -(see @racket[mutable-array?] for the reason), but untyped Racket code could easily do so. Refrain. -The type used for new strict arrays could change to another descendant of @racket[Array] in a -future release. Use @racket[array->mutable-array] to reliably get a mutable array. -} - @defproc[(array-lazy [arr (Array A)]) (Array A)]{ Returns a @tech{non-strict} array with the same elements as @racket[arr], but element computations are cached and reused. @@ -577,7 +582,7 @@ time. Speeding it up to linear time only requires wrapping its definition with @ fibs (ann (array #[0 1 1 2 3 5 8 13 21 34]) (Array Natural)))] Printing a lazy array computes and caches all of its elements, as does applying -@racket[array-strict] to it. +@racket[array-strict!] to it. } @defproc[(make-mutable-array [ds In-Indexes] [vs (Vectorof A)]) (Mutable-Array A)]{ @@ -591,16 +596,12 @@ Returns a mutable array with @tech{shape} @racket[ds] and elements @racket[vs]; } @defproc[(array->mutable-array [arr (Array A)]) (Mutable-Array A)]{ -Returns a mutable array with the same elements as @racket[arr]. - -While @racket[array-strict] may return any subtype of @racket[Array], @racket[array->mutable-array] -always returns a @racket[Mutable-Array]. Additionally, @racket[(array-strict arr)] may return -@racket[arr] if @racket[arr] is already strict, but @racket[array->mutable-array] always makes a -copy. +Returns a mutable array with the same elements as @racket[arr]. The result is a copy of +@racket[arr], even when @racket[arr] is mutable. } @defproc[(mutable-array-copy [arr (Mutable-Array A)]) (Mutable-Array A)]{ -Like @racket[(array->mutable-array arr)], but is restricted to mutable arrays. It is also faster. +Like @racket[(array->mutable-array arr)], but restricted to mutable arrays. It is also faster. } @defproc[(indexes-array [ds In-Indexes]) (Array Indexes)]{ @@ -611,6 +612,8 @@ array. (indexes-array #(4)) (indexes-array #(2 3)) (indexes-array #(4 0 2))] +The resulting array does not allocate storage for its elements, and is @tech{strict}. +(It is essentially the identity function for the domain @racket[ds].) } @defproc[(index-array [ds In-Indexes]) (Array Index)]{ @@ -619,6 +622,7 @@ the array. @examples[#:eval typed-eval (index-array #(2 3)) (array-flatten (index-array #(2 3)))] +Like @racket[indexes-array], this does not allocate storage for its elements, and is @tech{strict}. } @defproc[(axis-index-array [ds In-Indexes] [axis Integer]) (Array Index)]{ @@ -629,7 +633,7 @@ Returns an array with @tech{shape} @racket[ds], with each element set to its pos (axis-index-array #(3 3) 0) (axis-index-array #(3 3) 1) (axis-index-array #() 0)] -It is useless to make a strict copy of an array returned by @racket[axis-index-array]. +Like @racket[indexes-array], this does not allocate storage for its elements, and is @tech{strict}. } @defproc[(diagonal-array [dims Integer] [axes-length Integer] [on-value A] [off-value A]) @@ -639,6 +643,7 @@ on the diagonal (i.e. at indexes of the form @racket[(vector j j ...)] for @rack have the value @racket[on-value]; the rest have the value @racket[off-value]. @examples[#:eval typed-eval (diagonal-array 2 7 1 0)] +Like @racket[indexes-array], this does not allocate storage for its elements, and is @tech{strict}. } diff --git a/collects/math/tests/mandelbrot-test.rkt b/collects/math/tests/mandelbrot-test.rkt index 6bbc4da811..e923e797fc 100644 --- a/collects/math/tests/mandelbrot-test.rkt +++ b/collects/math/tests/mandelbrot-test.rkt @@ -9,13 +9,13 @@ (define x (list->array (sequence->list (in-range -2.0 0.800001 step)))) (define y (array-slice-ref (list->array (sequence->list (in-range -1.4 1.400001 step))) (list ::... (::new 1)))) - (define c (array->fcarray (array+ x (array-scale y +1.0i)))) + (define c (array->fcarray (array-make-rectangular x y))) (define-values (z divtime) (for/fold: ([z : FCArray c] - [divtime : (Array Integer) (make-array (array-shape c) max-iters)] + [divtime : (Array Integer) (array max-iters)] ) ([i (in-range max-iters)]) (let ([z (fcarray+ (fcarray-sqr z) c)]) - (values z (array-strict (array-if (array-and (array> (fcarray-magnitude z) (flarray 4.0)) + (values z (array-strict (array-if (array-and (array> (fcarray-magnitude z) (array 4.0)) (array= divtime (array max-iters))) (array i) divtime))))))