For Development HEAD DRAFTSearch (procedure/syntax/module):

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

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.


9.38.1 Uvector basic operations

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 ith and jth 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 vecs, 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 @vectors 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.


9.38.2 Uvector conversion operations

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.


9.38.3 Uvector numeric operations

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)

9.38.4 Uvector block I/O

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.


9.38.5 Bytevector compatibility

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.

Function: bytevector->u8-list bv
Function: u8-list->bytevector list

[R7RS bytevector] Convert a u8vector to a list of bytes, and vice versa. Same as u8vector->list and list->u8vector, except to not taking optional start/end arguments.



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT