Next: Comparing version numbers, Previous: Unicode utilities, Up: Library modules - Gauche extensions [Contents][Index]

`gauche.uvector`

- Uniform vectors- Module:
**gauche.uvector** -
Provides procedures that work on vectors whose elements are of the same numeric type, as defined in srfi-160 (formerly srfi-4), which has become R7RS large (as

`scheme.vector.@`

.The

`@`

part is actually one of the following tags, indicating the type of elements:`u8`

Unsigned 8-bit integer - an exact integer between 0 and 255.

`s8`

Signed 8-bit integer - an exact integer between -128 and 127.

`u16`

Unsigned 16-bit integer - an exact integer between 0 and 65535.

`s16`

Signed 16-bit integer - an exact integer between -32678 and 32767.

`u32`

Unsigned 32-bit integer - an exact integer between 0 and 2^32 - 1.

`s32`

Signed 32-bit integer - an exact integer between -(2^31) and 2^31 - 1.

`u64`

Unsigned 64-bit integer - an exact integer between 0 and 2^64 - 1.

`s64`

Signed 64-bit integer - an exact integer between -(2^63) and 2^63 - 1.

`f16`

16-bit floating point number (10-bit mantissa and 5-bit exponent), as inexact real.

`f32`

IEEE single-precision floating point number as inexact real.

`f64`

IEEE double-precision floating point number as inexact real.

`c32`

Inexact complex, consists of a pair of 16-bit floating point numbers.

`c64`

Inexact complex, consists of a pair of IEEE single-precision floating point numbers.

`c128`

Inexact complex, consists of a pair of IEEE double-precision floating point numbers.

There are some advantages of using uniform vectors over normal (heterogeneous) vectors. It may be more compact than the normal vectors. Some operations (especially Gauche’s extension of vector arithmetic operations) can bypass type check and conversion of individual elements, thus be more efficient. And it is much easier and efficient to communicate with external libraries that require homogeneous array of numbers; for example, OpenGL binding of Gauche uses uniform vectors extensively.

Gauche’s implementation is a superset of srfi-160 in a few ways:

- Support of
`f16vector`

and`c32vector`

, using 16-bit floating point numbers as used in high-dynamic range image format. - Efficient element-wise arithmetic procedures, e.g.
`@vector-add`

. - Implements the collection framework (see Collection framework)
and the sequence framework (see Sequence framework). So the
methods like
`map`

,`for-each`

,`ref`

or`subseq`

can be used. - Some routines takes optional parameters:
`@vector-ref`

takes optional fallback value.

When you try to store a number out of the range of the vector type,
an error is signaled by default. However, some procedures take
an optional argument `clamp` that specifies alternative behavior
in such a case. `Clamp` argument may take one of the following values.

`#f`

Default behavior (signals an error).

`high`

Clamps high bound; i.e. if the value to be stored is beyond the higher bound of the range, the maximum value is stored instead.

`low`

Clamps low bound; i.e. if the value to be stored is below the lower bound of the range, the minimum value is stored instead.

`both`

Clamps both sides; does both

`high`

and`low`

.

(list->u8vector '(-1)) ⇒ error (list->u8vector '(-1) 'low) ⇒ #u8(0) (list->u8vector '(-1) 'high) ⇒ error (list->u8vector '(3000) 'high) ⇒ #u8(255) (list->u8vector '(-100 20 300) 'both) ⇒ #u8(0 20 255)

In the following description, `@`

can be replaced
for any of `s8`

, `u8`

, `s16`

, `u16`

,
`s32`

, `u32`

, `s64`

, `u64`

,
`f16`

, `f32`

, `f64`

, `c32`

, `c64`

or `c128`

.

Note: R7RS-large provides separate library for each type,
and you should import them individually, for example,
`(use scheme.vector.u8)`

(Gauche way) or
`(import (scheme vector u8))`

(R7RS way).

On the other hand, using `gauche.uvector`

imports all the bindings.

• Uvector basic operations: | ||

• Uvector conversion operations: | ||

• Uvector numeric operations: | ||

• Uvector block I/O: | ||

• Bytevector compatibility: |

Next: Uvector conversion operations, Previous: Uniform vectors, Up: Uniform vectors [Contents][Index]

- Builtin Class:
**<@vector>** -
{

`gauche.uvector`} A class for @vector. It inherits`<sequence>`

.

- Reader Syntax:
`#@(`

`n`…) -
Denotes a literal homogeneous vector.

#s8(3 -2 4) #u32(4154 88357 2 323) #f32(3.14 0.554525 -3.342)

- Function:
**@vector?***obj* -
[R7RS vector.@] {

`gauche.uvector`} Returns`#t`

iff`obj`is a @vector,`#f`

otherwise.

- Function:
**uvector?***obj* {

`gauche.uvector`} Returns`#t`

iff`obj`is of any uniform vector type.

- Function:
**@?***obj* -
[R7RS vector.@] {

`gauche.uvector`} Returns`#t`

iff`obj`can be an element of`@vector`

.

- Function:
**@vector-empty?***obj* -
[R7RS vector.@] {

`gauche.uvector`} The argument must be a @vector. Returns`#t`

iff it is empty.

- Function:
**@vector***x …* -
[R7RS vector.@] {

`gauche.uvector`} Constructs @vector whose elements are numbers`x`…. The numbers must be exact integer for exact integer vectors, and in the valid range of the vector.(s8vector 1 2 3) ⇒ #s8(1 2 3)

- Function:
**make-@vector***len :optional fill* -
[R7RS vector.@] {

`gauche.uvector`} Constructs a @vector of length`len`. The elements are initialized by a number`fill`. For exact integer vectors,`fill`must be an exact integer and in the valid range. If`fill`is omitted, the content of the vector is undefined.(make-u8vector 4 0) ⇒ #u8(0 0 0 0)

- Function:
**make-uvector**`class`

`len`

:optional`fill`

{

`gauche.uvector`} This is a Gauche extension; instead of using separate constructor for each uvector type, you can pass the class of desired uvector.(make-uvector <u8vector> 3) ⇒ #u8(0 0 0) (make-uvector <s8vector> 5 -1) ⇒ #s8(-1 -1 -1 -1 -1)

- Function:
**@vector-unfold***f len seed* - Function:
**@vector-unfold-right***f len seed* -
{

`gauche.uvector`} Construct a @vector of length`len`, with each element as a result of`(f seed)`

,`(f (f seed))`

,`(f (f (f seed)))`

, …. @vector-unfold fills the element from left to right, while @vector-unfold-right from right to left.(u8vector-unfold (cut + 2 <>) 5 0) ⇒ #u8(2 4 6 8 10) (u8vector-unfold-right (pa$ + 2) 5 0) ⇒ #u8(10 8 6 4 2)

- Function:
**@vector-length***vec* -
[R7RS vector.@] {

`gauche.uvector`} Returns the length of the @vector`vec`.Note that the generic function

`size-of`

can be used to obtain the length of`vec`as well, if you import`gauche.collection`

(see Collection framework).(s16vector-length '#s16(111 222 333)) ⇒ 3 (use gauche.collection) (size-of '#s16(111 222 333)) ⇒ 3

- Function:
**uvector-length***uvector* {

`gauche.uvector`} This is a generic version of`@vector-length`

; you can pass any instance of uniform vector, and it returns the number of its elements.

- Function:
**uvector-size***uvector :optional start end* {

`gauche.uvector`} This function can be applied to any type of uniform vectors, and returns the raw size of the`uvector`in number of octets.When

`start`and/or`end`is/are given, the size of data between those indices are calculated. The special value`-1`

for`end`indicates the end of the vector. The returned value matches the number of octets to be written out by`(write-uvector`

.`uvector`port`start``end`)(Do not confuse this with

`uvector-length`

, which returns the number of elements.)(uvector-size '#u8(1 2 3)) ⇒ 3 (uvector-size '#u64(1 2 3)) ⇒ 24 (uvector-size '#u32(0 1 2 3) 2) ⇒ 8 (uvector-size '#u32(0 1 2 3) 0 1) ⇒ 4

- Function:
**uvector-class-element-size***class* {

`gauche.uvector`} Returns the size of an element of a uvector of the given class, in bytes. An error is raised when`class`is not a uvector class.(uvector-class-element-size <u8vector>) ⇒ 1 (uvector-class-element-size <s64vector>) ⇒ 8

- Function:
**@vector-ref***vec k :optional fallback* -
[R7RS vector.@] {

`gauche.uvector`} Returns the`k`-th element of @vector`vec`.If the index

`k`is out of the valid range, an error is signaled unless an optional argument`fallback`is given; in that case,`fallback`is returned.Note that the generic function

`ref`

can be used as well, if you import`gauche.collection`

.(u16vector-ref '#u16(111 222 333) 1) ⇒ 222 (use gauche.collection) (ref '#u16(111 222 333) 1) ⇒ 222

- Function:
**uvector-ref***vec k :optional fallback* {

`gauche.uvector`} Generic version of`@vector-ref`

. It can take any kind of uniform vector to`vec`, and returns its`k`-th element. If the index`k`is out of the valid range, an error is signaled unless an optional argument`fallback`is given; in that case,`fallback`is returned.This is handy to write a generic code that works on any kind of uniform vector, but this is slower than the specific versions. Gauche’s compiler recognizes the specific versions of referencer and generate very efficient code for them, while this generic version becomes a normal procedure call. In inner-loop it can make a big difference.

`(setter uvector-ref)`

is`uvector-set!`

.

- Function:
**@vector-set!***vec k n :optional clamp* -
[R7RS vector.@] {

`gauche.uvector`} Sets a number`n`to the`k`-th element of @vector`vec`. Optional`clamp`argument specifies the behavior when`n`is out of valid range. Default is to signal an error.Note that the setter of the generic function

`ref`

can be used as well, if you import`gauche.collection`

.(let ((v (s32vector -439 852 8933))) (s32vector-set! v 1 4) v) ⇒ #s32vector(-439 4 8933) (use gauche.collection) (let ((v (s32vector -439 852 8933))) (set! (ref v 1) 4) v) ⇒ #s32vector(-439 4 8933)

- Function:
**uvector-set!***vec k val* {

`gauche.uvector`} Generic version of`@vector-set!`

. It can handle any kind of uniform vectors, but a bit slower than the specific versions.

- Function:
**@vector-swap!***vec i j* -
[R7RS vector.@] {

`gauche.uvector`} Interchanges`i`th and`j`th elements of the uvector`vec`. Return value is not specified.

- Function:
**@vector-fill!***vec fill :optional start end* -
{

`gauche.uvector`} Stores`fill`in every element of`vec`, ranging from`start`to`end`of`vec`, if they are given. Return value is not specified.

- Function:
**@vector=**`vec1`… -
[R7RS vector.@] {

`gauche.uvector`} All arguments must be @vectors. Returns`#t`

iff all arguments have the same length and has the same values (in terms of`=`

) at the corresponding position. Zero arguments return`#t`.Note that in Gauche you can compare uvectors with

`equal?`

as well.

- Function:
**@vector=?**`vec1``vec2` -
[SRFI-66] {

`gauche.uvector`} Note: This is provided only for the srfi-66 compatibility. Use`@vector=`

instead.Both arguments must be a @vector. Returns

`#t`

if`vec1`and`vec2`are equal to each other,`#f`

otherwise.

- Function:
**@vector-compare**`vec1``vec2` -
[SRFI-66] {

`gauche.uvector`} Both arguments must be a @vector. Returns`-1`

if`vec1`is smaller than`vec2`,`0`

if both are equal to each other, and`1`

if`vec1`is greater than`vec2`.Shorter vector is smaller than longer vectors. If the lengths of both vectors are the same, elements are compared from left to right.

Note that you can compare uvectors with

`compare`

in Gauche. These are provided because SRFI-66 defines`u8vector-compare`

. You can also use them to indicate arguments are vectors of the specific type.

- Function:
**@vector-copy***vec :optional start end* -
[R7RS vector.@] {

`gauche.uvector`} Returns a fresh copy of uniform vector`vec`. If`start`and/or`end`are given, they limit the range of`vec`to be copied.(u8vector-copy '#u8(1 2 3 4)) ⇒ #u8(1 2 3 4) (u8vector-copy '#u8(1 2 3 4) 2) ⇒ #u8(3 4) (u8vector-copy '#u8(1 2 3 4) 1 3) ⇒ #u8(2 3)

- Function:
**uvector-copy***vec :optional start end* {

`gauche.uvector`} This is a generic version of`@vector-copy`

. You can give any type of uvector to`vec`, and get its copy (or copy of its part, depending on`start`/`end`argument).

- Function:
**@vector-reverse-copy***vec :optional start end* -
[R7RS vector.@] {

`gauche.uvector`} Copies`vec`between`strat`and`end`index, but reversing it.(u8vector-reverse-copy '#u8(1 2 3 4 5)) ⇒ #u8(5 4 3 2 1) (u8vector-reverse-copy '#u8(1 2 3 4 5) 1 4) ⇒ #u8(4 3 2)

- Function:
**@vector-copy!***target tstart source :optional sstart send* -
[R7RS vector.@] {

`gauche.uvector`} Both`target`and`source`must be @vectors, and`target`must be mutable. This procedure copies the elements of`source`, beginning from index`sstart`(inclusive) and up to`send`, into`target`, beginning from index`tstart`.`sstart`and`send`may be omitted, and in that case 0 and the length of`source`are assumed, respectively.(let ((target (u8vector 0 1 2 3 4 5 6))) (u8vector-copy! target 2 '#u8(10 11 12 13 14) 1 4) target) ⇒ #u8(0 1 11 12 13 6)

If the number of elements in the source vector between

`sstart`and`send`is larger than the target vector beginning from`tstart`, the excess elements are silently discarded.It is ok to pass the same vector to

`target`and`source`; it always works even if the regions of source and destination are overlapping.*Note:*This procedure used to take just two uniform vectors,`target`and`source`, and just copies contents of`source`to`target`. Both vectors had to be the same type and same length. The API is revised according to srfi-160. The old interface is still supported for the backward compatibility, but it is deprecated and will be gone in the future releases.Also note that SRFI-66 provides

`uvector-copy!`

with different argument order (see Octet vectors).

- Function:
**@vector-multi-copy!***target tstart tstride source :optional sstart ssize sstride count* -
{

`gauche.uvector`} This procedure allows different parts of the source uvector`source`into various parts of the target uvector`target`, all at once.When

`ssize`is omitted or zero, this procedure does the following:;; For each

`i`from 0 to`count`: (u8vector-copy! target (+ tstart (* i tstride)) source sstart)That is, it copies the content of

`source`(offset by`sstart`, which defaults to 0) into the`target`repeatedly, advancing index with`tstride`. If either the target index reaches the end or`count`copies are made, the procedure returns. See the example:(define t (make-u8vector 10 0)) (u8vector-multi-copy! t 0 4 '#u8(1 2 3)) t ⇒ #u8(1 2 3 0 1 2 3 0 1 2)

If

`ssize`is given and positive, the source is also splitted as follows:;; For each

`i`from 0 to`count`: (u8vector-copy! target (+ tstart (* i tstride)) source (+ sstart (* i sstride)) (+ sstart (* i sstride) ssize))That is, each

`ssize`slice from`source`, is copied into`target`, advancing source index by`sstride`and the destination index by`dstride`. In this case,`sstride`defaults to`ssize`if omitted.(define t (make-u8vector 12 0)) (u8vector-multi-copy! t 0 4 '#u8(1 2 3 4 5 6 7 8 9) 0 3) t ⇒ #u8(1 2 3 0 4 5 6 0 7 8 9 0)

The operation ends when either

`count`slices are copied, or destination index or source index reaches the end.Hint: If you want to copy a part of the source vector repeatedly (instead of to its end), you can specify 0 to

`sstride`:(define t (make-u8vector 12 0)) (u8vector-multi-copy! t 0 4 '#u8(1 2 3 4 5 6 7 8 9) 2 4 0) t ⇒ #u8(3 4 5 6 3 4 5 6 3 4 5 6)

Using collection and sequence framework, you can perform various operations on the homogeneous vectors.

(use gauche.collection) (use gauche.sequence) (fold + 0 '#s32(1 2 3 4)) ⇒ 10 (map-to <f32vector> * '#f32(3.2 1.1 4.3) '#f32(-4.3 2.2 9.4)) ⇒ #f32(-13.760001 2.420000 40.420002) (subseq #u32(1 4 3 4 5) 2 4) ⇒ #u32(3 4)

- Function:
**uvector-copy!***target tstart source :optional sstart send* {

`gauche.uvector`} This is a generic version of`@vector-copy!`

. The destination`target`and the source`source`can be any type of uniform vectors, and they don’t need to match. The copy is done bit-by-bit. So if you copy to a different type of uvector, the result depends on how the numbers are represented internally. This is mainly to manipulate binary data.`Tstart`is interpreted according to the type of`target`, and`sstart`and`send`are interpreted according to the type of`source`.(rlet1 v (make-u8vector 6 0) (uvector-copy! v 1 '#u32(0 #x01020304 0) 1 2)) ⇒ #u8(0 1 2 3 4 0) or #u8(0 4 3 2 1 0)

- Function:
**@vector-append***vec …* -
[R7RS vector.@] {

`gauche.uvector`} All arguments must be @vectors. Returns a fresh vector whose contents are concatenation of the given vectors. (It returns a fresh vector even there’s only one argument).(u8vector-append '#u8(1 2 3) '#u8(4 5) '#u8() '#u8(6 7 8)) ⇒ #u8(1 2 3 4 5 6 7 8)

- Function:
**@vector-concatenate***vecs* -
[R7RS vector.@] {

`gauche.uvector`} Returns a new @vector which is concatenation of the list of @vectors`vecs`.(u8vector-concatenate '(#u8(1 2 3) #u8(4 5 6))) ⇒ #u8(1 2 3 4 5 6)

- Function:
**@vector-append-subvectors***:optional vec start end …* -
[R7RS vector.@] {

`gauche.uvector`} Returns a new @vector which is concatenation of the subvectors of given`vec`s, using accompanied`start`and`end`index.(u8vector-append-subvectors '#u8(1 2 3 4) 1 3 '#u8(5 6 7 8) 0 2) ⇒ #u8(2 3 5 6)

- Variable:
**@vector-comparator** -
[R7RS vector.@] {

`gauche.uvector`} Bound to comparators that can compare two`@vector`

s and to hash a`@vector`

. See Basic comparators, for the details of comparators. These comparators both provides ordering predicate and hash function.

- Function:
**uvector-binary-search***uvector key :optional start end skip rounding* {

`gauche.uvector`} The`uvector`

must contain values in increasing order. This procedure finds the index of an element that is equal to`key`, using binary search. If such element can’t be found,`#f`

is returned.(uvector-binary-search '#u8(0 5 19 32 58 96) 32) ⇒ 3 (uvector-binary-search '#u8(0 5 19 32 58 96) 33) ⇒ #f

The optional

`start`and`end`arguments limits the portion of`uvector`to search;`start`specifies starting index (inclusive) and`end`specifies ending index (exclusive). Passing`#f`

indicates the default value (0 for`start`, the length of the vector for`end`). The returned index is the actual index of the vector, but the elements outside of`start`-`end`range don’t need to be sorted.(uvector-binary-search '#u8(99 99 19 32 58 99) 32 2 5) ⇒ 3 (uvector-binary-search '#u8(99 99 19 32 58 99) 99 2 5) ⇒ #f

The optional

`skip`argument must be a nonnegative exact integer or`#f`

. If it is a positive integer, the number of elements after every key in the`uvector`is ignored. For example, if`skip`is 2 and`uvector`is`#u8(3 100 101 5 102 103 13 104 105)`

, only`3`

,`5`

and`13`

are subject to search, and elements inbetween are ignored. This allows the caller to store*payload*, or associated value to each key, in the`uvector`itself. If`skip`is positive integer, the length of the searched portion of`uvector`must be a multiple of the record size (`skip`+1).`(uvector-binary-search '#u8(3 100 101 5 102 103 13 104 105) 13 #f #f 2) ⇒ 6 (uvector-binary-search '#u8(3 100 101 5 102 103 13 104) 13 #f #f 2) ⇒ ; Error: uvector size (8) isn’t multiple of record size (3)`

Finally,

`rounding`argument adjusts the behavior when the exact match isn’t found. It can be either one of the following values:`#f`

This is the default. The procedure searches the element that is equal to

`key`, and returns`#f`

if such element isn’t found.- a symbol
`floor`

When the exact match isn’t found, the procedure returns an index of the element that’s closest to but not greater than

`key`. If`key`is smaller than all the elements,`#f`

is returned.- a symbol
`ceiling`

When the exact match isn’t found, the procedure returns an index of the element that’s closest to but not smaller than

`key`. If`key`is greater than all the elements,`#f`

is returned.

(uvector-binary-search '#u32(1 10 100 1000 10000) 3757) ⇒ #f (uvector-binary-search '#u32(1 10 100 1000 10000) 3757 #f #f #f 'floor) ⇒ 3 (uvector-binary-search '#u32(1 10 100 1000 10000) 3757 #f #f #f 'ceiling) ⇒ 4

Note: SRFI-133 has

`vector-binary-search`

, which is quite similar to this procedure (see Vector library) but it requires comparison procedure, for it needs to compare general Scheme values. And it does not support`skip`and`rounding`arguments.

Next: Uvector numeric operations, Previous: Uvector basic operations, Up: Uniform vectors [Contents][Index]

- Function:
**@vector->list***vec :optional start end* -
[R7RS vector.@] {

`gauche.uvector`} Converts @vector`vec`to a list. If`start`and/or`end`are given, they limit the range of`vec`to be extracted.Note that the generic function

`coerce-to`

can be used as well, if you import`gauche.collection`

.(u32vector->list '#u32(9 2 5)) ⇒ (9 2 5) (use gauche.collection) (coerce-to <list> '#u32(9 2 5)) ⇒ (9 2 5)

- Function:
**uvector->list***uvec :optional start end* {

`gauche.uvector`} This is a generic version of`@vector->list`

. It can take any kind of uvector as`uvec`. The meaning of optional arguments are the same as`@vector->list`

.

- Function:
**@vector->vector***vec :optional start end* -
[R7RS vector.@] {

`gauche.uvector`} Converts @vector`vec`to a vector. If`start`and/or`end`are given, they limit the range of`vec`to be copied.Note that the generic function

`coerce-to`

can be used as well, if you import`gauche.collection`

.(f32vector->vector '#f32(9.3 2.2 5.5)) ⇒ #(9.3 2.2 5.5) (f32vector->vector '#f32(9.3 2.2 5.5) 2) ⇒ #(5.5) (use gauche.collection) (coerce-to <vector> '#f32(9.3 2.2 5.5)) ⇒ #(9.3 2.2 5.5)

- Function:
**uvector->vector***uvec :optional start end* {

`gauche.uvector`} This is a generic version of`@vector->vector`

. It can take any kind of uvector as`uvec`. The meaning of optional arguments are the same as`@vector->vector`

.

- Function:
**list->@vector***list :optional clamp* -
[R7RS vector.@] {

`gauche.uvector`} Converts a list`list`to a @vector. Optional argument`clamp`specifies the behavior when the element of`list`is out of the valid range. (The`clamp`argument is Gauche’s extension.)Note that the generic function

`coerce-to`

can be used as well, if you import`gauche.collection`

.(list->s64vector '(9 2 5)) ⇒ #s64(9 2 5) (use gauche.collection) (coerce-to <s64vector> '(9 2 5)) ⇒ #s64(9 2 5)

- Function:
**reverse-list->@vector***list :optional clamp* -
[R7RS vector.@] {

`gauche.uvector`} Create a new`@vector`

with the elements of`list`in reverse order. Optional argument`clamp`specifies the behavior when the element of`list`is out of the valid range. (The`clamp`argument is Gauche’s extension.)

- Function:
**vector->@vector***vec :optional start end clamp* -
[R7RS vector.@] {

`gauche.uvector`} Converts a vector`vec`to a @vector. If`start`and/or`end`are given, they limit the range of`vec`to be copied. Optional argument`clamp`specifies the behavior when the element of`vec`is out of the valid range. (The`clamp`argument is Gauche’s extension.)Note that the generic function

`coerce-to`

can be used as well, if you import`gauche.collection`

.(vector->f64vector '#(3.1 5.4 3.2)) ⇒ #f64(3.1 5.4 3.2) (use gauche.collection) (coerce-to <f64vector> '#(3.1 5.4 3.2)) ⇒ #f64(3.1 5.4 3.2)

- Function:
**string->s8vector***string :optional start end immutable?* - Function:
**string->u8vector***string :optional start end immutable?* {

`gauche.uvector`} Returns an s8vector or u8vector whose byte sequence is the same as the internal representation of the given string. Optional range arguments`start`and`end`specifies the*character position*(not the byte position) inside`string`to be converted.By default, the content of the string is copied to a newly created mutable uvector. However, if a true value is given to the optional

`immutable?`argument, the result is an immutable uvector, and it may avoid copying the string body (note that in Gauche, the body of string is immutable;`string-set!`

creates a new body, so changing the original string won’t affect the uvector created by`string->u8vector`

with`immutable?`

flag.)These procedures are useful when you want to access byte sequence of the string randomly.

(string->u8vector "abc") ⇒ #u8(97 98 99)

`(string->u8vector "very large string .... " 0 -1 #t) ⇒ #u8(...) ; immutable, sharing content with the original string`

- Function:
**string->s8vector!***target tstart string :optional start end* - Function:
**string->u8vector!***target tstart string :optional start end* {

`gauche.uvector`}`Target`must be an s8vector or a u8vector, respectively.`Target`must be mutable. Like copies the raw byte representation of`string`into`target`beginning from index`tstart`.Returns

`target`.(let ((target (make-u8vector 10 0))) (string->u8vector! target 3 "abcde")) ⇒ #u8(0 0 0 97 98 99 100 101 0 0)

- Function:
**s8vector->string***vec :optional start end terminator* - Function:
**u8vector->string***vec :optional start end terminator* {

`gauche.uvector`} Converts a byte sequence in s8vector or u8vector to a string that has the same byte sequence. Optional range arguments`start`and`end`specifies the byte position in`vec`to be converted.The optional

`terminator`argument can be an exact integer or`#f`

(default). If it is an exact integer, and it appears in`vec`, the string terminates right before it. For example, you can give 0 as`terminator`to read a NUL-terminated string from a buffer.(u8vector->string '#u8(65 66 0 67 68) 0 5) ⇒ "AB\0CD" (u8vector->string '#u8(65 66 0 67 68) 0 5 0) ⇒ "AB"

Note that these procedure may result an incomplete string if

`vec`contains a byte sequence invalid as the internal encoding of the string.

- Function:
**string->s32vector***string :optional start end* - Function:
**string->u32vector***string :optional start end* {

`gauche.uvector`} Returns an s32vector or u32vector whose elements are the internal codes of the characters in the string. Optional range arguments`start`and`end`specifies the*character position*inside`string`to be converted.These procedures are useful when you want to access the characters in the string randomly.

- Function:
**string->s32vector!***target tstart string :optional start end* - Function:
**string->u32vector!***target tstart string :optional start end* {

`gauche.uvector`}`Target`must be a mutable s32vector or u32vector, respectively. Fill the`target`from position`tstart`with the codepoint of each character of`string`, until either`string`is exhausted or`target`is filled to the end.Optional range arguments

`start`and`end`specifies the*character position*inside`string`to be considered.

- Function:
**s32vector->string***vec :optional start end terminator* - Function:
**u32vector->string***vec :optional start end terminator* {

`gauche.uvector`} Without`start`and`end`, these procedures work like this:(lambda (vec) (map-to <string> integer->char vec)))

Optional range arguments

`start`and`end`limits the range of conversion between them.The optional

`terminator`argument must be an exact integer or`#f`

(default). If an integer is given, and the integer is found in the input, the output string terminates right before it.(u32vector->string '#u32(65 66 0 67 68) 0 5 0) ⇒ "AB"

- Function:
**uvector-alias***uvector-class vec :optional start end* {

`gauche.uvector`} This procedure creates an uvector of class`uvector-class`that shares the storage of the given uniform vector`vec`. If optional`start`and`end`arguments are given, only the specified range of`vec`is used for the new vector. Since the storage is shared, modification of the original vector can be seen from the new vector, or vice versa.The class

`uvector-class`must be either one of the uniform vector class, but is not necessary match the class of the source vector`vec`. In such case, the new vector looks at the same region of`vec`’s memory, but interprets it differently. For example, the following code determines whether Gauche is running on big-endian or little-endian machine:(let ((u8v (uvector-alias <u8vector> #u32(1)))) (if (zero? (u8vector-ref u8v 0)) 'big-endian 'little-endian))

If the

`uvector-class`is other than s8vector or u8vector, the region the new vector points has to meet the alignment requirement. You can assume the beginning of the source vector is aligned suitable for any uniform vectors. So, for example, if you’re creating u32vector from u8vector, the`start`and`end`must be multiple of 4 (or, if they’re omitted, the length of the original u8vector must be multiple of 4). An error is signaled when the given parameters doesn’t satisfy alignment constraint.

Next: Uvector block I/O, Previous: Uvector conversion operations, Up: Uniform vectors [Contents][Index]

These are Gauche extension that allows faster arithmetic over uniform vectors, than extracting and calculating element-wise values.

Most procedures comes with two flavors, a functional version (without `!`

in the name) and a linear-update version (with `!`

in the name).

A functional version assumes the caller treats the arguments and results immutable objects; mutating them later could have unexpected consequences. (Notably, the functional version may return one of its arguments as is, or returns a pre-computed value, so you shouldn’t assume the return values are freshly allocated objects, unless it is noted so explicitly.)

A linear update version may reuse the storage of the designated argument to produce the return value. Gauche tries to reuse the argument as much as possible, but you should always use the return value and shouldn’t assume the argument itself is modified in-place. In fact, after calling linear-updating procedure, you can’t use the argument that may be modified, since you can’t assume the state of the object after calling the procedure.

- Function:
**@vector-add***vec val :optional clamp* - Function:
**@vector-add!***vec val :optional clamp* - Function:
**@vector-sub***vec val :optional clamp* - Function:
**@vector-sub!***vec val :optional clamp* - Function:
**@vector-mul***vec val :optional clamp* - Function:
**@vector-mul!***vec val :optional clamp* -
{

`gauche.uvector`} Element-wise arithmetic.`Vec`must be a @vector, and`val`must be either a @vector, a vector, or a list of the same length as`vec`, or a number (an exact integer for integer vectors, and a real number for f32- and f64-vectors).If

`val`is a @vector, its elements are added to, subtracted from, or multiplied by the corresponding elements of`vec`, respectively, and the results are gathered to a @vector and returned. The linear-update version (those have bang ‘!’ in the name) reuses`vec`to store the result, and also returns it. If the result of calculation goes out of the range of @vector’s element, the behavior is specified by`clamp`optional argument. (For f32vector and f64vector,`clamp`argument is ignored and the result may contain infinity).If

`val`is a number, it is added to, subtracted from, or multiplied by each element of`vec`, respectively.`(s8vector-add '#s8(1 2 3 4) '#s8(5 6 7 8)) ⇒ #s8(6 8 10 12) (u8vector-sub '#u8(1 2 3 4) '#u8(2 2 2 2)) ⇒ error (u8vector-sub '#u8(1 2 3 4) '#u8(2 2 2 2) 'both) ⇒ #u8(0 0 1 2) (f32vector-mul '#f32(3.0 2.0 1.0) 1.5) ⇒ #f32(4.5 3.0 1.5)`

- Function:
**@vector-div***vec val* - Function:
**@vector-div!***vec val* -
{

`gauche.uvector`} Element-wise division of flonum vectors. These are only defined for f16, f32 and f64vector.`val`must be a @vector, a vector or a list of the same length as`vec`, or a real number.(f32vector-div '#f32(1.0 2.0 3.0) 2.0) ⇒ #f32(0.5 1.0 1.5)

- Function:
**@vector-and***vec val* - Function:
**@vector-and!***vec val* - Function:
**@vector-ior***vec val* - Function:
**@vector-ior!***vec val* - Function:
**@vector-xor***vec val* - Function:
**@vector-xor!***vec val* -
{

`gauche.uvector`} Element-wise logical (bitwise) operation. These procedures are only defined for integral vectors.`val`must be a @vector, a vector or a list of the same length as`vec`, or an exact integer. Bitwise and, inclusive or or exclusive or is calculated between each element in`vec`and the corresponding element of`val`(when`val`is a non-scalar value), or`val`itself (when`val`is an integer). The result is returned in a @vector. The linear-update version reuses`vec`to store the result, and also returns it.

- Function:
**@vector-dot***vec0 vec1* -
{

`gauche.uvector`} Calculates the dot product of two @vectors. The length of`vec0`and`vec1`must be the same.

- Function:
**@vector-range-check***vec min max* -
{

`gauche.uvector`}`Vec`must be a @vector, and each of`min`and`max`must be either a @vector, a vector or a list of the same length as`vec`, or a number, or`#f`

.For each element in

`vec`, this procedure checks if the value is between`minval`and`maxval`inclusive, where`minval`and`maxval`are the corresponding values of`min`and`max`(when`min`and/or`max`is/are non-scalar value) or`min`and`max`themselves (when`min`and/or`max`is/are a number). When`min`is`#f`

, negative infinity is assumed. When`max`is`#f`

, positive infinity is assumed.If all the elements in

`vec`are within the range,`#f`

is returned. Otherwise, the index of the leftmost element of`vec`that is out of range is returned.(u8vector-range-check '#u8(3 1 0 2) 0 3) ⇒ #f (u8vector-range-check '#u8(3 1 0 2) 1 3) ⇒ 2 (u8vector-range-check '#u8(4 32 64 98) 0 '#u8(10 40 70 90)) ⇒ 3 ;; Range check in a program (cond ((u8vector-range-check u8v 1 31) => (lambda (i) (errorf "~sth vector element is out of range: ~s" i (u8vector-ref u8v i)))) (else (do-something u8v)))

- Function:
**@vector-clamp***vec min max* - Function:
**@vector-clamp!***vec min max* -
{

`gauche.uvector`}`Vec`must be a @vector, and each of`min`and`max`must be either a @vector, a vector or a list of the same length as`vec`, or a number, or`#f`

.Like @vector-range-check, these procedures check if each element of

`vec`are within the range between`minval`and`maxval`inclusive, which are derived from`min`and`max`. If the value is less than`minval`, it is replaced by`minval`. If the value is grater than`maxval`, it is replaced by`maxval`.@vector-clamp creates a copy of

`vec`and do clamp operation on it, while @vector-clamp! modifies`vec`. Both return the clamped vector.(s8vector-clamp '#s8(8 14 -3 -22 0) -10 10) ⇒ #s8(8 10 -3 -10 0)

Next: Bytevector compatibility, Previous: Uvector numeric operations, Up: Uniform vectors [Contents][Index]

A uniform vector can be seen as an abstraction of a chunk of memory. So you might want to use it for binary I/O. Yes, you can do it.

- Function:
**read-uvector***class size :optional iport endian* {

`gauche.uvector`} Reads`size`elements of uvector of class`class`from`iport`, and returns fleshly created uvector. If`iport`is omitted, the curret input port is used.For example, you can read input as an octet stream as follows:

(with-input-from-string "abcde" (^[] (read-uvector <u8vector> 5))) ⇒ #u8(97 98 99 100 101)

If the input port has already reached EOF, an EOF object is returned. The returned uvector can be shorter than

`size`if the input reaches EOF before`size`elements are read.If the

`iport`is a buffered port with ‘modest’ or ‘none’ buffering mode (see File ports),`read-uvector`

may return before`size`elements are read, even if`iport`hasn’t reached EOF. The ports connected to a pipe or a network socket behave so by default.The data is read as a byte stream, so if you give uniform vectors other than s8vector or u8vector, your result may affected by the endianness. If the optional argument

`endian`is given, the input is interpreted in that endianness. When omitted, the value of the parameter`default-endian`

is used. See Endianness, for more about endian handling.If the size of the input data is unknown and you need to read everything until EOF, use

`port->uvector`

below.R7RS has

`read-bytevector`

; it is the same as passing`<u8vector>`

to`read-uvector`

.

- Function:
**read-uvector!***vec :optional iport start end endian* {

`gauche.uvector`} Reads a chunk of data from the given input port`iport`, and stores it to the uniform vector`vec`. You can give any uniform vector. If optional`start`and`end`arguments are given, they specify the index range in`vec`that is to be filled, and the rest of the vector remains untouched. Otherwise, entire vector is used. A special value -1 for`end`indicates the end of`vec`. If`iport`is omitted, the current input port is used.If the input reached EOF before the required region of

`vec`is filled, the rest of the vector is untouched.If

`iport`is already reached EOF when`read-uvector!`

is called, an EOF object is returned. Otherwise, the procedure returns the number of*elements*read (not bytes).If the

`iport`is a buffered port with ‘modest’ or ‘none’ buffering mode (see File ports),`read-uvector!`

may return before all the elements in`vec`is filled, even if`iport`hasn’t reached EOF. The ports connected to a pipe or a network socket behave so by default. If you know there will be enough data arriving and want to make sure`vec`is filled, change the buffering mode of`iport`to ‘full’.The data is read as a byte stream, so if you give uniform vectors other than s8vector or u8vector, your result may affected by the endianness. If the optional argument

`endian`is given, the input is interpreted in that endianness. When omitted, the value of the parameter`default-endian`

is used. See Endianness, for more about endian handling.

- Function:
**read-block!***vec :optional iport start end endian* {

`gauche.uvector`} An old name of`read-uvector!`

. Supported for the backward compatibility, but new code should use`read-uvector!`

.

- Function:
**port->uvector***iport :optional class* {

`gauche.uvector`} Read data from the input port`iport`until EOF and store them into a uvector of`class`. If`class`is omitted,`<u8vector>`

is used.If you specify a class of uvector whose element is more than an octet, the input data is packed with platform’s native byteorder.

This procedure is parallel to

`port->string`

etc. (see Input utility functions).

- Function:
**write-uvector***vec :optional oport start end endian* {

`gauche.uvector`} Writes out the content of the uniform vector`vec`’as is’ to the output port`oport`. If`oport`is omitted, the current output port is used. If optional`start`and`end`arguments are given, they specify the index range in`vec`to be written out. A special value -1 for`end`indicates the end of`vec`. This procedure returns an unspecified value.If you write out a uniform vector except s8vector and u8vector, the care should be taken about the endianness, as in

`read-uvector`

. The optional argument`endian`specifies the output endian. When it is omitted, the value of the parameter`default-endian`

is used (see Endianness).

- Function:
**write-block***vec :optional oport start end endian* {

`gauche.uvector`} An old name of`write-uvector`

. Supported for the backward compatibility, but new code should use`write-uvector`

.

Previous: Uvector block I/O, Up: Uniform vectors [Contents][Index]

R7RS-small includes bytevectors in its core (`scheme.base`

).
In Gauche, bytevectors are the same as u8vectors.

The basic R7RS bytevector procedures are provided in this module.
Conversion between bytevectors and strings are provided in
`gauche.unicode`

(see Unicode transfer encodings).

- Function:
**bytevector***byte …* {

`gauche.uvector`} [R7RS base] Alias of`u8vector`

. Returns a fresh bytevector (u8vector) with`byte`… as its elements.

- Function:
**bytevector?***obj* {

`gauche.uvector`} [R7RS base] Alias of`u8vector?`

. Returns true iff`obj`is a bytevector (u8vector).

- Function:
**make-bytevector***len :optional byte* {

`gauche.uvector`} [R7RS base] Alias of`make-u8vector`

. Returns a fresh bytevector (u8vector) of length`len`. All elements are initialized by`byte`if given.

- Function:
**bytevector-length***bv* {

`gauche.uvector`} [R7RS base] Alias of`u8vector-length`

. Returns the length of the bytevector (u8vector)`bv`.

- Function:
**bytevector-u8-ref***bv k* - Function:
**bytevector-u8-set!***bv k byte* {

`gauche.uvector`} [R7RS base] Alias of`u8vector-ref`

and`u8vector-set!`

. Read and write`k`-th element of a bytevector (u8vector)`bv`.It is an error to give out-of-bound index.

The return value of

`bytevector-u8-set!`

is unspecified.As Gauche’s extension,

`(setter bytevector-u8-ref)`

is`bytevector-u8-set!`

.

- Function:
**bytevector-copy***bv :optional start end* {

`gauche.uvector`} [R7RS base] Alias of`u8vector-copy`

. Returns a fresh copy of a bytevector (u8vector)`bv`. Optionally you can restrict the range of the source vector by indices`start`(inclusive) and`end`(exclusive).

- Function:
**bytevector-copy!***target tstart source :optional sstart send* {

`gauche.uvector`} [R7RS base] Alias of`u8vector-copy!`

. Both`target`and`source`muse be bytevectors (u8vectors), and`target`must be mutable. Copy the content of`source`(optionally restricting the range between indices`start`(inclusive) and`end`(exclusive)) into`target`starting at the index`tstart`.

- Function:
**bytevector-append***bv …* {

`gauche.uvector`} [R7RS base] Alias of`u8vector-append`

. All arguments must be bytevectors (u8vectors). Returns a fresh bytevector whose elements are the concatenation of elements of`bv`….

- Function:
**bytevector=?***bv1 bv2* {

`gauche.uvector`} Alias of`u8vector=?`

. All arguments must be bytevectors (u8vectors). Returns`#t`

iff all bytevectors are of the same size and content.

Previous: Uvector block I/O, Up: Uniform vectors [Contents][Index]