Array changes in response to user feedback (and my personal neuroses)

* `list->array' now accepts an optional shape argument, and always returns
  an immutable array

* `vector->array' now accepts an optional shape argument, and always
  returns a mutable array

* Removed `make-mutable-array' because `vector->array' does its job now (I
  never liked the name anyway)

* Renamed `unsafe-mutable-array' to `unsafe-vector->array'

* Added optional type annotation to `array' macro to match `mutable-array'

* Reworded error messages in array broadcasting functions

* Made minor array doc fixes
This commit is contained in:
Neil Toronto 2012-12-17 15:53:44 -07:00
parent 8c66be33e7
commit b8efd58aca
13 changed files with 150 additions and 104 deletions

View File

@ -21,7 +21,7 @@
(let ([shift (- new-dims old-dims)])
(cond [(index? shift) shift]
[else (error 'array-broadcast
"cannot broadcast to lower-dimensional array; given ~e and ~e"
"cannot broadcast to a lower-dimensional shape; given ~e and ~e"
arr new-ds)])))
(define old-js (make-thread-local-indexes old-dims))
(define old-f (unsafe-array-proc arr))
@ -95,8 +95,10 @@
(: array-shape-broadcast (case-> ((Listof Indexes) -> Indexes)
((Listof Indexes) (U #f #t 'permissive) -> Indexes)))
(define (array-shape-broadcast dss [broadcasting (array-broadcasting)])
(define (fail) (error 'array-shape-broadcast "incompatible array shapes (broadcasting ~v): ~a"
broadcasting (string-join (map (λ (ds) (format "~e" ds)) dss) ", ")))
(define (fail) (error 'array-shape-broadcast
"incompatible array shapes (array-broadcasting ~v): ~a"
broadcasting
(string-join (map (λ (ds) (format "~e" ds)) dss) ", ")))
(cond [(empty? dss) #()]
[else (for/fold ([new-ds (first dss)]) ([ds (in-list (rest dss))])
(shape-broadcast2 new-ds ds fail broadcasting))]))

View File

@ -23,14 +23,14 @@
ds (λ () (raise-argument-error 'name "Indexes" ds)))])
(define vs (for/vector #:length (array-shape-size ds) maybe-fill ...
(clause ...) maybe-type ... body ...))
(unsafe-mutable-array ds vs))))]
(unsafe-vector->array ds vs))))]
[(_ name:id for/vector:id (clause ...) (~optional (~seq : A:expr)) body:expr ...+)
(with-syntax ([(maybe-type ...) (if (attribute A) #'(: A) #'())])
(syntax/loc stx
(let ()
(define vs (for/vector (clause ...) maybe-type ... body ...))
(define ds ((inst vector Index) (vector-length vs)))
(unsafe-mutable-array ds vs))))]))
(unsafe-vector->array ds vs))))]))
(define-syntax-rule (for/array: e ...)
(base-for/array: for/array: for/vector: e ...))
@ -49,13 +49,13 @@
ds (λ () (raise-argument-error 'name "Indexes" ds)))])
(define vs (for/vector #:length (array-shape-size ds) maybe-fill ...
(clause ...) body ...))
(unsafe-mutable-array ds vs))))]
(unsafe-vector->array ds vs))))]
[(_ name:id for/vector:id (clause ...) body:expr ...+)
(syntax/loc stx
(let ()
(define vs (for/vector (clause ...) body ...))
(define ds ((inst vector Index) (vector-length vs)))
(unsafe-mutable-array ds vs)))]))
(unsafe-vector->array ds vs)))]))
(define-syntax-rule (for/array e ...)
(base-for/array for/array for/vector e ...))

View File

@ -15,8 +15,6 @@
vector*->array
array->list*
array->vector*
list->array
vector->array
array->list
array->vector)

View File

@ -37,7 +37,7 @@
(define (parallel-array->mutable-array arr)
(define size (array-size arr))
(cond
[(zero? size) (unsafe-mutable-array (array-shape arr) (vector))]
[(zero? size) (unsafe-vector->array (array-shape arr) (vector))]
[else
(define ds (array-shape arr))
(define dims (vector-length ds))
@ -61,7 +61,7 @@
(for: ([f (in-list futures)])
(touch f))
(unsafe-mutable-array ds vs))]))
(unsafe-vector->array ds vs))]))
(: parallel-array-strict (All (A) ((Array A) -> (Array A))))
(define (parallel-array-strict arr)

View File

@ -4,13 +4,18 @@
typed/racket/base
(for-syntax racket/base syntax/parse)
"array-syntax.rkt"
(except-in "typed-array-struct.rkt" build-array build-strict-array))
(except-in "typed-array-struct.rkt"
build-array
build-strict-array
list->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-strict-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))])
[build-strict-array (All (A) ((Vectorof Integer) ((Vectorof Index) -> A) -> (Array A)))]
[list->array (All (A) (case-> ((Listof A) -> (Array A))
((Vectorof Integer) (Listof A) -> (Array A))))])
(define-syntax array? (make-rename-transformer #'Array?))
(define-syntax array-shape (make-rename-transformer #'Array-shape))
@ -27,10 +32,13 @@
array-strict
array-strict!
array-strict?
make-unsafe-array-proc
build-array
build-strict-array
list->array
make-unsafe-array-proc
unsafe-build-array
unsafe-build-strict-array
unsafe-list->array
unsafe-array-proc
array-lazy
array
@ -46,8 +54,11 @@
array-lift-comparison)
(define-syntax (array stx)
(syntax-parse stx
[(_ e:expr) (syntax/loc stx (array/syntax array list flat-list->array e))]
(syntax-parse stx #:literals (:)
[(_ e:expr)
(syntax/loc stx (array/syntax array list unsafe-list->array e))]
[(_ e:expr : T:expr)
(syntax/loc stx (array/syntax array (inst list T) unsafe-list->array e))]
[_:id (raise-syntax-error 'array "not allowed as an expression" stx)]))
(define-syntax-rule (array-strict arr-expr)

View File

@ -1,6 +1,7 @@
#lang racket/base
(require (for-syntax racket/base))
(require (for-syntax racket/base)
(only-in typed/racket/base inst Index))
(provide array/syntax)
@ -40,4 +41,4 @@
(with-syntax ([(d ...) ds]
[(v ...) (syntax-vector-flatten #'e)])
(syntax/loc stx
(->array (vector d ...) (constr v ...)))))]))
(->array ((inst vector Index) d ...) (constr v ...)))))]))

View File

@ -5,20 +5,21 @@
(for-syntax racket/base syntax/parse)
"array-syntax.rkt"
(except-in "typed-mutable-array.rkt"
make-mutable-array))
vector->array))
(require/untyped-contract
(begin (require "typed-mutable-array.rkt"))
"typed-mutable-array.rkt"
[make-mutable-array (All (A) ((Vectorof Integer) (Vectorof A) -> (Mutable-Array A)))])
[vector->array (All (A) (case-> ((Vectorof A) -> (Mutable-Array A))
((Vectorof Integer) (Vectorof A) -> (Mutable-Array A))))])
(provide
;; Mutable-Array
Mutable-Array
mutable-array?
mutable-array-data
make-mutable-array
unsafe-mutable-array
vector->array
unsafe-vector->array
mutable-array-copy
mutable-array
;; Conversion
@ -28,7 +29,7 @@
(define-syntax (mutable-array stx)
(syntax-parse stx #:literals (:)
[(_ e:expr)
(syntax/loc stx (array/syntax mutable-array vector make-mutable-array e))]
(syntax/loc stx (array/syntax mutable-array vector unsafe-vector->array e))]
[(_ e:expr : T:expr)
(syntax/loc stx (array/syntax mutable-array (inst vector T) make-mutable-array e))]
(syntax/loc stx (array/syntax mutable-array (inst vector T) unsafe-vector->array e))]
[_:id (raise-syntax-error 'mutable-array "not allowed as an expression" stx)]))

View File

@ -11,14 +11,6 @@
;; Conversion to arrays
(make-to-array-functions list*->array vector*->array)
(: list->array (All (A) ((Listof A) -> (Array A))))
(define (list->array xs)
(vector->array (list->vector xs)))
(: vector->array (All (A) ((Vectorof A) -> (Array A))))
(define (vector->array xs)
(unsafe-mutable-array ((inst vector Index) (vector-length xs)) xs))
(: array->list (All (A) ((Array A) -> (Listof A))))
(define (array->list arr)
(vector->list (array->vector arr)))

View File

@ -113,12 +113,25 @@
(unsafe-build-strict-array ds (λ: ([js : Indexes])
(proc (vector->immutable-vector js))))))
(: 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-list->array (All (A) (Indexes (Listof A) -> (Array A))))
(define (unsafe-list->array ds xs)
(define vs (list->vector xs))
(unsafe-build-strict-array
ds (λ: ([js : Indexes]) (unsafe-vector-ref vs (unsafe-array-index->value-index ds js))))))
ds (λ: ([js : Indexes]) (unsafe-vector-ref vs (unsafe-array-index->value-index ds js)))))
(: list->array (All (A) (case-> ((Listof A) -> (Array A))
(In-Indexes (Listof A) -> (Array A)))))
(define list->array
(case-lambda
[(xs) (unsafe-list->array ((inst vector Index) (length xs)) xs)]
[(ds xs)
(let* ([ds (check-array-shape
ds (λ () (raise-argument-error 'list->array "(Vectorof Index)" 0 ds xs)))]
[size (array-shape-size ds)]
[n (length xs)])
(if (= size n)
(unsafe-list->array ds xs)
(raise-argument-error 'list->array (format "List of length ~e" size) 1 ds xs)))]))
(: array-lazy (All (A) ((Array A) -> (Array A))))
(define (array-lazy arr)

View File

@ -17,28 +17,33 @@
(define mutable-array? Mutable-Array?)
(define mutable-array-data Mutable-Array-data)
(: unsafe-mutable-array (All (A) (Indexes (Vectorof A) -> (Mutable-Array A))))
(define (unsafe-mutable-array ds vs)
(: unsafe-vector->array (All (A) (Indexes (Vectorof A) -> (Mutable-Array A))))
(define (unsafe-vector->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) (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)
(: vector->array (All (A) (case-> ((Vectorof A) -> (Mutable-Array A))
(In-Indexes (Vectorof A) -> (Mutable-Array A)))))
(define vector->array
(case-lambda
[(vs) (unsafe-vector->array ((inst vector Index) (vector-length vs)) vs)]
[(ds vs)
(let* ([ds (check-array-shape
ds (λ () (raise-argument-error 'make-mutable-array "(Vectorof Index)" 0 ds vs)))]
ds (λ () (raise-argument-error 'vector->array "(Vectorof Index)" 0 ds vs)))]
[size (array-shape-size ds)]
[n (vector-length vs)])
(cond [(= size n) (unsafe-mutable-array ds vs)]
[else (raise-argument-error 'mutable-array (format "Vector of length ~e" size) 1 ds vs)])))
(if (= size n)
(unsafe-vector->array ds vs)
(raise-argument-error 'vector->array (format "Vector of length ~e" size) 1 ds vs)))]))
(: mutable-array-copy (All (A) ((Mutable-Array A) -> (Mutable-Array A))))
(define (mutable-array-copy arr)
(unsafe-mutable-array (array-shape arr) (vector-copy-all (mutable-array-data arr))))
(unsafe-vector->array (array-shape arr) (vector-copy-all (mutable-array-data arr))))
(: flat-vector->matrix : (All (A) (Index Index (Vectorof A) -> (Array A))))
(define (flat-vector->matrix m n v)
(make-mutable-array (vector m n) v))
(vector->array (vector m n) v))
;; ===================================================================================================
;; Conversions
@ -47,4 +52,4 @@
(define (array->mutable-array arr)
(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)))
(unsafe-vector->array ds (inline-build-array-data ds (λ (js j) (g js)) A)))

View File

@ -87,7 +87,7 @@
(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?)))]
(unsafe-vector->array ds (list*->flat-vector lst size pred?)))]
[else (raise-shape-error)]))
(: vector*->array (All (A) ((Vectorof* A) ((Vectorof* A) -> Any : A) -> (Array A))))

View File

@ -24,9 +24,9 @@
@title[#:tag "arrays" #:style 'toc]{Arrays}
@(author-neil)
@bold{Performance Warning:} Most of the array-producing functions exported by
@racketmodname[math/array] run 25-50 times slower in untyped Racket, due to the
overhead of checking higher-order contracts. We are working on it.
@bold{Performance Warning:} Indexing the elements of arrays created in untyped Racket
is currently 25-50 times slower than doing the same in Typed Racket, due to the overhead
of checking higher-order contracts. We are working on it.
For now, if you need speed, use the @racketmodname[typed/racket] language.
@ -301,8 +301,8 @@ operations to succeed only if array shapes match exactly:
(array* (index-array #(3 3)) (array 10)))]
Another option is @hyperlink["http://www.r-project.org"]{R}-style permissive broadcasting,
which allows pointwise operations to @italic{always} succeed, by repeating any axis instead
of stretching just singleton axes:
which allows pointwise operations to @italic{always} succeed, by repeating shorter axes' rows
instead of repeating just singleton axes' rows:
@interaction[#:eval typed-eval
(define arr10 (array-map number->string (index-array #(10))))
(define arr3 (array-map number->string (index-array #(3))))
@ -479,12 +479,14 @@ Returns the vector of data that @racket[arr] contains.
@section{Construction}
@defform[(array #[#[...] ...])]{
@defform/subs[(array #[#[...] ...] maybe-type-ann)
[(maybe-type-ann (code:line) (code:line : type))]]{
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
array contents from array shapes and other vectors.
rectangular shape. Using square parentheses is not required, but is encouraged to help visually
distinguish array contents from array indexes and other vectors.
(See the examples for @racket[indexes-array] for an illustration.)
@examples[#:eval typed-eval
(array 0)
@ -492,13 +494,16 @@ array contents from array shapes and other vectors.
(array #[#[1 2 3] #[4 5 6]])
(array #[#[1 2 3] #[4 5]])]
As with the @racket[list] constructor, the type chosen for the array is the narrowest type
all the elements can have. Unlike @racket[list], because @racket[array] is syntax, the only way
to change the element type is to annotate the result.
all the elements can have. Unlike @racket[list], because @racket[array] is syntax, instantiating
@racket[array] with the desired element type is a syntax error:
@interaction[#:eval typed-eval
(list 1 2 3)
(array #[1 2 3])
((inst list Real) 1 2 3)
((inst array Real) #[1 2 3])
((inst array Real) #[1 2 3])]
There are two easy ways to annotate the element type:
@interaction[#:eval typed-eval
(array #[1 2 3] : Real)
(ann (array #[1 2 3]) (Array Real))]
Annotating should rarely be necessary because the @racket[Array] type is covariant.
@ -509,6 +514,8 @@ Normally, the datums within literal vectors are implicitly quoted. However, when
(array #[not okay])
(array #['this 'is 'okay])
(array #['#(an) '#(array) '#(of) '#(vectors)])]
Another way to create an immutable, strict array from literal data is to use @racket[list->array].
}
@defform/subs[(mutable-array #[#[...] ...] maybe-type-ann)
@ -528,6 +535,8 @@ the array's elements:
arr
(array-set! arr #(0) 10.0)
arr]
Another way to create a mutable array from literal data is to use @racket[vector->array].
}
@defproc[(make-array [ds In-Indexes] [value A]) (Array A)]{
@ -586,16 +595,6 @@ Printing a lazy array computes and caches all of its elements, as does applying
@racket[array-strict!] to it.
}
@defproc[(make-mutable-array [ds In-Indexes] [vs (Vectorof A)]) (Mutable-Array A)]{
Returns a mutable array with @tech{shape} @racket[ds] and elements @racket[vs]; assumes
@racket[vs] are in row-major order. If there are too many or too few elements in @racket[vs],
@racket[(make-mutable-array ds vs)] raises an error.
@examples[#:eval typed-eval
(make-mutable-array #(3 3) #(0 1 2 3 4 5 6 7 8))
(make-mutable-array #() #(singleton))
(make-mutable-array #(4) #(1 2 3 4 5))]
}
@defproc[(array->mutable-array [arr (Array A)]) (Mutable-Array A)]{
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.
@ -664,37 +663,60 @@ This is used as an argument type to @racket[list*->array] and as the return type
Like @racket[(Listof* A)], but for vectors. See @racket[vector*->array] and @racket[array->vector*].
}
@deftogether[(@defproc[(list->array [lst (Listof A)]) (Array A)]
@deftogether[(@defproc*[([(list->array [lst (Listof A)]) (Array A)]
[(list->array [ds In-Indexes] [lst (Listof A)]) (Array A)])]
@defproc[(array->list [arr (Array A)]) (Listof A)])]{
Convert lists to single-axis arrays and back. If @racket[arr] has no axes or more than one axis,
it is (conceptually) flattened before being converted to a list.
Convert lists to @tech{strict}, immutable arrays and back.
The two-argument variant of @racket[list->array] assumes the elements in @racket[lst] are in
row-major order.
For @racket[array->list], if @racket[arr] has no axes or more than one axis, it is (conceptually)
flattened before being converted to a list.
@examples[#:eval typed-eval
(list->array '(1 2 3))
(list->array '((1 2 3) (4 5)))
(list->array #(2 2) '(1 2 3 4))
(array->list (array #[1 2 3]))
(array->list (array 10))
(array->list (array #[#[1 2 3] #[4 5 6]]))]
For conversion between nested lists and multidimensional arrays, see @racket[list*->array] and
@racket[array->list*].
For conversion from flat values to mutable arrays, see @racket[vector->array].
}
@deftogether[(@defproc[(vector->array [vec (Vectorof A)]) (Array A)]
@deftogether[(@defproc*[([(vector->array [vec (Vectorof A)]) (Mutable-Array A)]
[(vector->array [ds In-Indexes] [vec (Vectorof A)]) (Mutable-Array A)])]
@defproc[(array->vector [arr (Array A)]) (Vectorof A)])]{
Like @racket[list->array] and @racket[array->list], but for vectors.
@examples[#:eval typed-eval
(vector->array #(1 2 3))
(vector->array #((1 2 3) (4 5)))
(vector->array #(2 2) #(1 2 3 4))
(array->vector (array #[1 2 3]))
(array->vector (array 10))
(array->vector (array #[#[1 2 3] #[4 5 6]]))]
For conversion between nested vectors and multidimensional arrays, see @racket[vector*->array] and
@racket[array->vector*].
}
@defproc[(list*->array [lsts (Listof* A)] [pred? ((Listof* A) -> Any : A)]) (Array A)]{
Converts a nested list of elements of type @racket[A] to an array. The predicate @racket[pred?]
identifies elements of type @racket[A]. The shape of @racket[lsts] must be rectangular.
Converts a nested list of elements of type @racket[A] to a @tech{strict} array.
The predicate @racket[pred?] identifies elements of type @racket[A].
The shape of @racket[lsts] must be rectangular.
@examples[#:eval typed-eval
(list*->array 'singleton symbol?)
(list*->array '(0 1 2 3) byte?)
(list*->array (list (list (list 5) (list 2 3))
(list (list 4.0) (list 1.4 0.2 9.3)))
(make-predicate (Listof Nonnegative-Real)))]
The last example demonstrates why a predicate is required. There is no well-typed Typed Racket
function that behaves like @racket[list*->array] but does not require @racket[pred?], because
without it, there is no way to distinguish between rows and elements.
There is no well-typed Typed Racket function that behaves like @racket[list*->array] but does not
require @racket[pred?].
Without an element predicate, there is no way to prove to the type checker that
@racket[list*->array]'s implementation correctly distinguishes elements from rows.
}
@defproc[(array->list* [arr (Array A)]) (Listof* A)]{
@ -715,9 +737,10 @@ Like @racket[array->list*], but produces nested vectors of elements.
}
@defproc[(array-list->array [arrs (Listof (Array A))] [axis Integer 0]) (Array A)]{
Concatenates @racket[arrs] along axis @racket[axis] to form a new array. If the arrays have
different shapes, they are broadcast first. The axis number @racket[axis] must be nonnegative
and @italic{no greater than} the number of axes after broadcasting.
Concatenates @racket[arrs] along axis @racket[axis] to form a new array.
If the arrays have different shapes, they are broadcast first.
The axis number @racket[axis] must be nonnegative and @italic{no greater than} the number of axes in
the highest dimensional array in @racket[arrs].
@examples[#:eval typed-eval
(array-list->array (list (array 0) (array 1) (array 2) (array 3)))
(array-list->array (list (array 0) (array 1) (array 2) (array 3)) 1)
@ -1756,7 +1779,7 @@ in-unsafe-array-indexes
make-unsafe-array-set-proc
make-unsafe-array-proc
unsafe-build-array
unsafe-mutable-array
unsafe-vector->array
unsafe-flarray
unsafe-array-transform
unsafe-array-axis-reduce

View File

@ -48,7 +48,7 @@
(check-equal? (make-indexes-vector 2 3)
#(#(0 0) #(0 1) #(0 2) #(1 0) #(1 1) #(1 2) #(2 0) #(2 1) #(2 2)))
(let ([arr (make-mutable-array #(4) #(a b c d))])
(let ([arr (vector->array #(4) #(a b c d))])
(check-eq? arr (array-strict arr)))
(let ([arr (build-array #() (λ (js) 'foo))])
@ -87,34 +87,34 @@
;; list*->array
(check-equal? (list*->array 1.0 flonum?)
(make-mutable-array #() #(1.0)))
(vector->array #() #(1.0)))
(check-equal? (list*->array '[] flonum?)
(make-mutable-array #(0) #()))
(vector->array #(0) #()))
(check-equal? (list*->array '[[]] flonum?)
(make-mutable-array #(1 0) #()))
(vector->array #(1 0) #()))
(check-equal? (list*->array '[1.0] flonum?)
(make-mutable-array #(1) #(1.0)))
(vector->array #(1) #(1.0)))
(check-equal? (list*->array '[[1.0]] flonum?)
(make-mutable-array #(1 1) #(1.0)))
(vector->array #(1 1) #(1.0)))
(check-equal? (list*->array '[[[1.0]]] flonum?)
(make-mutable-array #(1 1 1) #(1.0)))
(vector->array #(1 1 1) #(1.0)))
(check-equal? (list*->array '() listof-flonum?)
(make-mutable-array #() #(())))
(vector->array #() #(())))
(check-equal? (list*->array '[()] listof-flonum?)
(make-mutable-array #(1) #(())))
(vector->array #(1) #(())))
(check-equal? (list*->array '[(1.0) (2.0)] listof-flonum?)
(make-mutable-array #(2) #((1.0) (2.0))))
(vector->array #(2) #((1.0) (2.0))))
(check-equal? (list*->array '[((1.0)) ((2.0))] listof-flonum?)
(make-mutable-array #(2 1) #((1.0) (2.0))))
(vector->array #(2 1) #((1.0) (2.0))))
;; ---------------------------------------------------------------------------------------------------
;; array->list*
@ -156,22 +156,22 @@
;; vector*->array
(check-equal? (vector*->array 1.0 flonum?)
(make-mutable-array #() #(1.0)))
(vector->array #() #(1.0)))
(check-equal? ((inst vector*->array Float) #() flonum?)
(make-mutable-array #(0) #()))
(vector->array #(0) #()))
(check-equal? ((inst vector*->array Float) #(#()) flonum?)
(make-mutable-array #(1 0) #()))
(vector->array #(1 0) #()))
(check-equal? ((inst vector*->array Float) #(1.0) flonum?)
(make-mutable-array #(1) #(1.0)))
(vector->array #(1) #(1.0)))
(check-equal? ((inst vector*->array Float) #(#(1.0)) flonum?)
(make-mutable-array #(1 1) #(1.0)))
(vector->array #(1 1) #(1.0)))
(check-equal? ((inst vector*->array Float) #(#(#(1.0))) flonum?)
(make-mutable-array #(1 1 1) #(1.0)))
(vector->array #(1 1 1) #(1.0)))
;; ---------------------------------------------------------------------------------------------------
;; array->vector
@ -303,7 +303,7 @@
(check-equal? (array-map (inst cons Float Float)
(array #[1.0 2.0])
(array #[10.0 20.0]))
(make-mutable-array #(2) #[(1.0 . 10.0) (2.0 . 20.0)]))
(vector->array #(2) #[(1.0 . 10.0) (2.0 . 20.0)]))
;; ---------------------------------------------------------------------------------------------------
;; Fold