This is a proposal for a bytevector API whose procedures allow a bytevector to be viewed as one of several kinds of numeric vectors. This design subsumes SRFI 4, except that users cannot distinguish different types of numeric vectors by predicates, since they are all bytevectors. It differs from related designs such as SRFI 63, SRFI 66, and R6RS in that each procedure listed below actually represents many procedures, one for each defined representation type. This makes for a lot of 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.
A <type> consists of a <principal type> followed by an <endianism>.
The <principal type> values are:
The <endianism> values are:
Endianism is not applicable to the u8 and s8 types. Thus there are 3 * 14 - 4, or 38, representation types altogether.
The s and u types correspond to limited ranges of exact integers, the f types to limited ranges of inexact real numbers, and the c types to limited ranges of inexact complex numbers.
The number of bytes occupied by a representation type is the number of bits expressed in its name divided by 8. This value is designated by b in the descriptions of procedures.
(make-<type>-bytevectorvector k [ fill ])
Returns a newly allocated bytevector of length k * b.Fill is converted to a binary value according to `<type> and used to fill the bytevector; if fill is not specified, the values of the elements are unspecified. It is an error if fill cannot be converted to <type>.
(<type>-bytevector v ... )
Returns a newly allocated bytevector of length k * b, 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>-bytevector-ref bytevector k)
Returns a Scheme number corresponding to the binary value encoded according to <type> beginning at offset k * b in bytevector. This procedure treats bytevector as a uniformly typed vector.
(bytevector-<type>-ref bytevector k)
Returns a Scheme number corresponding to the binary value encoded according to <type> beginning at offset k in bytevector. This procedure treats bytevector as potentially containing more than one type.
Note that bytevector-u8-ref is defined in the small language.
(<type>-bytevector-set! numvector k v)
Converts v to a binary value encoded according to <type> and places it into bytevector beginning at offset k * b. This procedure treats bytevector as a uniformly typed vector. It is an error if v cannot be converted to <type>.
(bytevector-<type>-set! bytevector k v)
Converts v to a binary value encoded according to <type> and places it into bytevector beginning at offset k. This procedure treats bytevector as potentially containing more than one type. It is an error if v cannot be converted to <type>.
Note that bytevector-u8-set! is defined in the small language.
It is an error if a value being used to fill an element of a <type>vector cannot be converted to <type>, or if start (inclusive), end (inclusive), or at are out of range, or if an existing bytevector is being overflowed.
(vector-><type>-bytevector vector [start [ end ] ])
Returns a newly allocated bytevector of length end * b - start * b, filled with the corresponding elements of vector.
(list-><type>-bytevector list)
Returns a newly allocated bytevector whose length is the length of list times b, filled with the elements of list.
(vector-><type>-bytevector! bytevector at vector [start [ end ] ])
Writes the elements of vector from start to end into bytevector starting at at.
(list-><type>-bytevector! list bytevector at)
Writes the elements of list into bytevector starting at at.
It is an error if start (inclusive), end (inclusive), or at are out of range, or if an existing vector is being overflowed.
(<type>-bytevector->vector bytevector [ start [ end ] ])
(<type>-bytevector->list bytevector [ start [ end ] ])
Returns a newly allocated vector or list of length end - start with the elements of bytevector from start * b to end * b.
(<type>-bytevector->vector! vector at bytevector [start [ end ] ])
Writes the elements of bytevector from start * b to end * b into vector starting at at.
(<type>-bytevector-length bytevector)
Returns the length of bytevector / b, rounded toward zero.
(<type>-bytevector-fill! bytevector fill [ [ start ] end ] )
Stores fill in the elements of bytevector viewed as a <type>vector from start * b to end * b. An error is signaled if fill cannot be converted to <type>.
(<type>-bytevector-map proc bytevector ...)
Returns a newly allocated bytevector which contains the results of applying proc to the elements of the bytevectors in an unspecified order.
(<type>-bytevector-map! proc output-bytevector bytevector ...)
Returns a newly allocated bytevector which contains the results of applying proc to the elements of the bytevectors in an unspecified order. Returns an unspecified value.
(<type>-bytevector-for-each proc bytevector ...)
Applies proc to the elements of the bytevectors in order from first to last. Returns an unspecified value.
See the procedures of VectorsCowan, with the exceptions of the ones defined here.
For mapping C structs onto bytevectors, see StructuresCowan or StructuresTaylan.
Since there are a great many procedures, it makes sense to factor this into separate libraries. Most programs won't require all the representation types, so factoring horizontally into 38 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.
This syntax-rules macro by Ian Price will be helpful in implementing lots of similar but not identical procedures for the 38 types.