Changed how array strictness works: `array-strict' now makes the
original array strict instead of returning a new strict array. (Finally!) The hard part is keeping the Array type covariant. The solution is to keep the store in the closure of the array's procedure instead of in the Array struct itself.
This commit is contained in:
parent
d7163142be
commit
e4f5a0598f
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
mutable-array
|
||||
;; Conversion
|
||||
array->mutable-array
|
||||
array-strict
|
||||
flat-vector->matrix)
|
||||
|
||||
(define-syntax (mutable-array stx)
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}.
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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))))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user