`gauche.uvector`

- Uniform vector library ¶- Module:
**gauche.uvector**¶ -
Provides procedures that work on uniform vectors (see Uniform vectors). This module is a superset of R7RS uniform vector library (

`scheme.vector.@`

) and SRFI-4.The

`@`

part is actually one of`u8`

,`s8`

,`u16`

,`s16`

,`u32`

,`s32`

,`u64`

,`s64`

,`f16`

,`f32`

,`f64`

,`c32`

,`c64`

or`c128`

.

Gauche’s extension to SRFI-160 is as follows:

- 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
`gauche.collection`

- Collection framework) and the sequence framework (see`gauche.sequence`

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

The following procedures are built-in; see Uniform vectors:

make-@vector uvector? @vector? uvector-ref @vector-ref uvector-set! @vector-set! uvector-length

- 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-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.Type-specific constructors (

`make-s8vector`

etc.) are defined in the core library (see Uniform vectors).(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`¶ -
[R7RS vector.@] {

`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-unfold!**`f vec start end seed`¶ - Function:
**@vector-unfold-right!**`f vec start end seed`¶ -
[R7RS vector.@] {

`gauche.uvector`

} Fill an @vector`vec`between`start`-th index (inclusive) and`end`-th index (exclusive), with the values generated by`f`, which is called with two arguments, the integer index and the current seed value.In

`@vector-unfold!`

,`f`is first called with`start`and`seed`. It must return two values, the element to put to`vec`and the next seed value. Then`f`is called with`start`+ 1 and the previously returnd seed value, and so on, until`end`-`start`elements are generated.`@vector-unfold-right!`

works similarly, but the elements are generated from right (`end`-1) to left (`start`).If

`start`>=`end`,`f`is never called and`vec`isn’t altered. It is an error if the index falls out of range of`vec`.Return an unspecified vlaue.

- 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`gauche.collection`

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

- 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-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`srfi.66`

- Octet vectors).

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

`gauche.uvector`

}

- Function:
**@vector-reverse-copy!**`target tstart source :optional start end`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

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

- Function:
**@vector-take**`vec n`¶ - Function:
**@vector-take-right**`vec n`¶ - Function:
**@vector-drop**`vec n`¶ - Function:
**@vector-drop-right**`vec n`¶ -
[R7RS vector.@] {

`gauche.uvector`

} Returns a new uvector that has the first`n`elements, the last`n`elements, the elements without the first`n`elements, and the elements without the last`n`elements, respectively.`N`must be a nonnegative exact integer no greater than the length of`vec`.(u8vector-take '#u8(0 1 2 3 4 5) 4) ⇒ #u8(0 1 2 3) (u8vector-drop '#u8(0 1 2 3 4 5) 4) ⇒ #u8(4 5) (u8vector-take-right '#u8(0 1 2 3 4 5) 4) ⇒ #u8(2 3 4 5) (u8vector-drop-right '#u8(0 1 2 3 4 5) 4) ⇒ #u8(0 1)

You can also use

`uvector-alias`

to obtain a partial uvector that shares the storage with the original uvector, avoiding copying overhead.

- Function:
**@vector-segment**`vec n`¶ -
[R7RS vector.@] {

`gauche.uvector`

} Segment`vec`into fresh uvectors of length`n`, and returns a list of them. The last uvector may be shorter than`n`if the length of`vec`is not a multiple of`n`.`N`must be a positive exact integer.(u8vector-segment '#u8(0 1 2 3 4 5 6 7) 3) ⇒ (#u8(0 1 2) #u8(3 4 5) #u8(6 7))

- Function:
**@vector-fold**`kons knil vec vec2 …`¶ - Function:
**@vector-fold-right**`kons knil vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-unfold!**`f vec start end seed`¶ - Function:
**@vector-unfold-right!**`f vec start end seed`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-map**`f vec vec2 …`¶ - Function:
**@vector-map!**`f vec vec2 …`¶ - Function:
**@vector-for-each**`f vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-count**`pred vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-cumulate**`f knil vec`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-take-while**`pred vec`¶ - Function:
**@vector-take-while-right**`pred vec`¶ - Function:
**@vector-drop-while**`pred vec`¶ - Function:
**@vector-drop-while-right**`pred vec`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-index**`pred vec vec2 …`¶ - Function:
**@vector-index-right**`pred vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-skip**`pred vec vec2 …`¶ - Function:
**@vector-skip-right**`pred vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-any**`pred vec vec2 …`¶ - Function:
**@vector-every**`pred vec vec2 …`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-partition**`pred vec`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**@vector-filter**`pred vec`¶ - Function:
**@vector-remove**`pred vec`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**make-@vector-generator**`vec`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- 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`scheme.vector`

- R7RS vectors) but it requires comparison procedure, for it needs to compare general Scheme values. And it does not support`skip`and`rounding`arguments.

- 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:
**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.

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)

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.

- Function:
**read-bytevector**`size :optional iport`¶ [R7RS base] {

`gauche.uvector`

} Equivalent to`(read-uvector <u8vector> size iport)`

. This is an R7RS base procedure.

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

}**Deprecated.**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:
**read-bytevector!**`bv :optional iport start end`¶ [R7RS base] {

`gauche.uvector.`

} Similar to`read-uvector!`

, but`bv`must be a u8vector. This is an R7RS base procedure.

- 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-@vector**`vec :optional port`¶ -
[R7RS vector.@] {

`gauche.uvector`

}

- Function:
**write-bytevector**`bv :optional oport start end`¶ [R7RS base] {

`gauche.uvector`

} Similar to`write-uvector`

, but`bv`must be a u8vector. This is an R7RS base procedure.

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

`gauche.uvector`

}**Deprecated.**An old name of`write-uvector`

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

.

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)
and `srfi.181`

(see Transcoded ports).

- 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][R7RS bytevector] Returns a fresh bytevector (u8vector) of length`len`. All elements are initialized by`byte`if given.R7RS base accepts an exact integer between 0 and 255 inclusive as

`byte`. R7RS bytevector extends the range to -128 to 255 inclusive, while the negative value is wrapped-around by modulo 255. This procedure supports the extended range.

- 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-s8-ref**`bv k`¶ - Function:
**bytevector-s8-set!**`bv k signed-byte`¶ {

`gauche.uvector`

} [R7RS bytevector] Like`bytevector-u8-ref`

and`bytevector-u8-set!`

, but treates octets as a signed byte, ranging from -128 to 127, inclusive.As Gauche’s extension,

`(setter bytevector-s8-ref)`

is`bytevector-s8-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-copy!-r6**`src sstart target tstart len`¶ {

`gauche.uvector`

} This is a compatibility procedure for R6RS`bytevector-copy!`

(hence the suffix`-r6`

). When R6RS bytevectors are adpoted as R7RS-large`scheme.bytevector`

, the R6RS version of`bytevector-copy!`

comes into R7RS as well (hence R7RS has two different`bytevector-copy!`

, one in`scheme.base`

and one in`scheme.bytevector`

).It’s unfortunate that R6RS tends to break tradition and invent a new API; here, the arguments differ from other

`*-copy!`

procedures: This procedure copies from`src`, starting from`sstart`and length`len`, to`target`starting`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`

} [R7RS bytevector] Alias of`u8vector=?`

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

iff all bytevectors are of the same size and content.

DRAFT