This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home. For a version of this page that may be more recent, see NumericVectorsCowan in WG2's repo for R7RS-large.

Numeric­Vectors­Cowan

cowan
2016-05-18 04:28:46
21history
source

This is a proposal for a simple API for specialized numeric vectors distinguished by their representation type. The u8 type is the same as the R7RS bytevector type, but the other types are all disjoint from all other Scheme types. This API is more restricted than BytevectorsCowan, except that it is possible to dispatch on the different types of numeric vectors. It may be useful for Schemes on the JVM or the CLR to use this API to provide access to the platform's native numeric vectors.

This design subsumes SRFI 4. There are many procedures, but many of them can be easily inlined by even a very dumb compiler, providing high efficiency. The procedures provided in the present proposal are the numeric-vector analogues of the R7RS-small vector API.

Representation types

The [type] values are:

u8
unsigned 8-bit integer
s8
signed 8-bit integer
u16
unsigned 16-bit integer
s16
signed 16-bit integer
u32
unsigned 32-bit integer
s32
signed 32-bit integer
u64
unsigned 64-bit integer
s64
signed 64-bit integer
f32
32-bit float
f64
64-bit float
c64
64-bit complex number
c128
128-bit complex number

Constructors

(make-[type]vector k [ fill ])

Returns a newly allocated numeric vector of length k. Fill is converted to a binary value according to [type] and used to fill the vector; if fill is not specified, the values of the elements are unspecified. It is an error if fill cannot be converted to [type].

([type]vector v ... )

Returns a newly allocated numeric vector of length k, where k is the number of arguments to the procedure. It is filled with the binary values resulting from encoding the v arguments according to [type]. It is an error if an argument cannot be converted to [type].

([type]vector-unfold proc length initial-seed)

Returns a newly allocated [type]vector whose length is length and iterates across each index k between 0 and length, applying proc at each iteration to the current index and current seed, in that order, to receive 2 values: first, the element to put in the kth slot of the new vector and a new seed for the next iteration. Note that the termination condition is different from the unfold procedure of SRFI 1.

Examples:

(s8vector-unfold (lambda (i x) (values x (- x 1))) 10 0) => #s8(0 -1 -2 -3 -4 -5 -6 -7 -8 -9)

Construct a vector of the sequence of integers in the range [0,n).

(u8vector-unfold values n) => #u8(0 1 2 ... n-2 n-1)

Copy vector.

(f64vector-unfold (λ (i) (vector-ref vector i)) (vector-length vector))

([type]vector-unfold-right proc length initial-seed)

Like [type]vector-unfold, but it uses proc to generate elements from right-to-left, rather than left-to-right. The first index used is length - 1. Note that the termination condition is different from the unfold-right procedure of SRFI 1.

Examples:

Construct a vector of pairs of non-negative integers whose values sum to 4.

(u8vector-unfold-right (λ (i x) (values (cons i x) (+ x 1))) 5 0) => #u8((0 . 4) (1 . 3) (2 . 2) (3 . 1) (4 . 0))

Reverse vector.

(float64-vector-unfold-right (λ (i x) (values (f64vector-ref vector x) (+ x 1))) (f64vector-length vector) 0)

([type]vector-copy [type]vec [start [end]])

Allocates a new [type]vector whose length is end - start and fills it with elements from [type]vec. Examples:

([type]vector-reverse-copy [type]vec [start [end]])

Like [type]vector-copy, but it copies the elements in the reverse order from [type]vec.

([type]vector-append [type]vec ...)

Returns a newly allocated vector that contains all elements in order from the locations in the [type]vecs.

Predicates

([type]vector? obj)

Returns #t if obj is a [type]vector, and #f if it is not.

([type]vector-empty? [type]vector)

Returns #t if [type]vector has length 0, and #f otherwise.

Selectors

([type]vector-ref [type]vector k)

Returns a Scheme number corresponding to the kth element of [type]vector. Note that u8vector-ref is the same as the R7RS-small procedure bytevector-u8-ref.

Mutators

([type]vector-set! [type]vector k v)

Converts v to a binary value encoded according to [type] and places it into the kth element of [type]vector. It is an error if v cannot be converted to [type]. Note that u8vector-set! is the same as the R7RS-small procedure bytevector-u8-set!.

Conversions to numeric vectors

It is an error if a value being used to fill an element of a [type]vector cannot be converted to [type].

(vector->[type]vector vector [start [ end ] ])

Returns a newly allocated [type]vector of length end - start, filled with the corresponding elements of vector.

(list->[type]vector list)

Returns a newly allocated [type]vector whose length is the length of list, filled with the elements of list.

(vector->[type]vector! [type]vector at vector [start [ end ] ])

Writes the elements of vector from start to end into [type]vector starting at at.

(list->[type]vector! list [type]vector at)

Writes the elements of list into [type]vector starting at at.

Conversions from numeric vectors

([type]vector->vector [type]vector [ start [ end ] ])

([type]vector->list [type]vector [ start [ end ] ])

Returns a newly allocated vector or list of length end - start with the elements of [type]vector from start to end.

([type]vector->vector! vector at [type]vector [start [ end ] ])

Writes the elements of [type]vector from start to end into vector starting at at.

== The whole numeric vector ==

([type]vector-length [type]vector)

Returns the length of [type]vector.

([type]vector-copy [type]vector [ [ start ] end ] )

Copies the elements of [type]vector from start to end into a newly allocated [type]vector.

([type]vector-copy! to at from [ [ start ] end ] )

Copies the elements of from from start to end into to starting at at.

[type]vector-append [type]vector ...)

Returns a newly allocated [type]vector whose elements are the concatenation of the elements in [type]vectors. It is an error if the [type]vectors are not all of the same type.

([type]vector-fill! [type]vector fill [ [ start ] end ] )

Stores fill in the elements of [type]vector. An error is signaled if fill cannot be converted to [type].

Mapping

([type]vector-map proc [type]vector ...)

Returns a newly allocated [type]vector which contains the results of applying proc to the elements of the [type]vectors in an unspecified order.

([type]vector-map! proc output-[type]vector [type]vector ...)

Writes the results of applying proc to the elements of the [type]vectors into the corresponding elements of output-[type]vector in an unspecified order. It is not an error for output-[type]vector to be the same as one of the [type]vectors. Returns an unspecified value.

([type]vector-for-each proc [type]vector ...)

Applies proc to the elements of the [type]vectors in order from first to last and discards the results. Returns an unspecified value.

Input and output

(read-[type]vector k [ port ])

Read k * b bytes from port into a newly allocated [type]vector and returns it.

(read-[type]vector! [type]vector [ port [ start [ end ] ] ])

Read end * b - start * b bytes from port into [type]vector starting at start. Returns the number of bytes read divided by b, or an eof object if no bytes are available. If the number of bytes available is not a multiple of b, the value of the element of [type]vector for which b bytes are not available is unspecified.

(write-[type]vector [type]vector [ port [ start [ end'' ] ] ])

Write end * b - start * b bytes to port from [type]vector starting at start. Returns an unspecified value.

TODO

[type]vector-fold, [type]vector-fold-right [type]vector-unfold, [type]vector-unfold-right, [type]vector-unfold! [type]vector-index, [type]vector-index-right [type]vector-skip, [type]vector-skip-right [type]vector-binary-search [type]vector-any, [type]vector-every, [type]vector-partition [type]vector-reverse-copy, [type]vector-reverse-copy! [type]vector-count, [type]vector-cumulate [type]vector-swap!, [type]vector-fill! [type]vector-reverse!, [type]vector-copy!, [type]vector-reverse-copy! [type]vector-unfold!, [type]vector-unfold-right!

Packaging

Since there are many procedures, it makes sense to factor this into separate libraries. Most programs won't require all the representation types, so factoring horizontally into 12 libraries based on that is a simple approach. If the result is still too large, then we can factor vertically based on expected uses for the function. SRFI 4 provides just 8 procedures per type: the basic and multi-argument constructors, the predicate, the basic accessor, the basic mutator, length, and conversion to and from lists.

Implementation

This syntax-rules macro by Ian Price will be helpful in implementing lots of similar but not identical procedures for the 12 types.