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:
Neil Toronto 2012-11-29 22:12:45 -09:00
parent d7163142be
commit e4f5a0598f
12 changed files with 134 additions and 98 deletions

View File

@ -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

View File

@ -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))

View File

@ -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)

View File

@ -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)

View File

@ -23,7 +23,6 @@
mutable-array
;; Conversion
array->mutable-array
array-strict
flat-vector->matrix)
(define-syntax (mutable-array stx)

View File

@ -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])

View File

@ -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

View File

@ -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)]))

View File

@ -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))

View File

@ -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

View File

@ -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}.
}

View File

@ -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))))))