[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.31 gauche.uvector - Uniform vectors

Module: gauche.uvector

Provides vectors whose elements are of the same numeric type, as defined in SRFI-4 (SRFI-4).

Gauche’s implementation is a superset of SRFI-4 in a few ways:

There are some advantages of using SRFI-4 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 SRFI-4 vectors extensively.

The following ten types of vectors are defined.

s8vector

Elements are exact integers in the range between -2^7 and 2^7-1

u8vector

Elements are exact integers in the range between 0 and 2^8-1

s16vector

Elements are exact integers in the range between -2^15 and 2^15-1

u16vector

Elements are exact integers in the range between 0 and 2^16-1

s32vector

Elements are exact integers in the range between -2^31 and 2^31-1

u32vector

Elements are exact integers in the range between 0 and 2^32-1

s64vector

Elements are exact integers in the range between -2^63 and 2^63-1

u64vector

Elements are exact integers in the range between 0 and 2^64-1

f16vector

Elements are inexact real numbers representable in 16bits float (a.k.a half float)

f32vector

Elements are inexact real numbers representable in the float of C compiler that compiles Gauche. Usually it is a single precision IEEE floating point number.

f64vector

Elements are inexact real numbers representable in the double of C compiler that compiles Gauche. Usually it is a double precision IEEE floating point number.

When you try to store a number out of the range of the vector type, an error is signalled 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, TAG can be replaced for any of s8, u8, s16, u16, s32, u32, s64, u64, f16, f32, f64.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.31.1 Uvector basic operations

Builtin Class: <TAGvector>

A class for TAGvector. It inherits <sequence>.

Reader Syntax: #TAG(n …)

Denotes a literal homogeneous vector.

 
#s8(3 -2 4)
#u32(4154 88357 2 323)
#f32(3.14 0.554525 -3.342)
Function: TAGvector? obj

[SRFI-4] Returns #t if obj is a TAGvector, #f otherwise.

Function: TAGvector x

[SRFI-4] Constructs TAGvector 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-TAGvector len :optional fill

[SRFI-4] Constructs a TAGvector 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: TAGvector-length vec

[SRFI-4] Returns the length of the TAGvector 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 section 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

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-block uvector port start end).

 
(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: TAGvector-ref vec k :optional fallback

[SRFI-4+] Returns the k-th element of TAGvector vec.

If the index k is out of the valid range, an error is signalled 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: TAGvector-set! vec k n :optional clamp

[SRFI-4+] Sets a number n to the k-th element of TAGvector 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: TAGvector-fill! vec fill :optional start end

Stores fill in every element of vec, ranging from start to end of vec, if they are given.

Function: TAGvector-copy vec :optional start end

Copies the srfi-4 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: TAGvector-copy! target tstart source :optional sstart send

Both target and source must be TAGvectors, 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.

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 to the current form to make it parallel with string-copy! (SRFI-13) and vector-copy! (SRFI-43). The old interface is still supported for the backward compatibility, but it is deprecated and will be gone in the future releases.

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

This is a generic version of TAGvector-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)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.31.2 Uvector conversion operations

Function: TAGvector->list vec :optional start end

[SRFI-4+] Converts TAGvector 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: TAGvector->vector vec :optional start end

Converts TAGvector 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: list->TAGvector list :optional clamp

[SRFI-4+] Converts a list list to a TAGvector. Optional argument clamp specifies the behavior when the element of list is out of the valid range.

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: vector->TAGvector vec :optional start end clamp

Converts a vector vec to a TAGvector. 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.

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
Function: string->u8vector string :optional start end

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 inside string to be converted.

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

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

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

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
Function: u8vector->string vec :optional start end

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.

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

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: s32vector->string vec :optional start end
Function: u32vector->string vec :optional start end

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.

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

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 signalled when the given parameters doesn’t satisfy alignment constraint.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.31.3 Uvector numeric operations

Function: TAGvector-add vec val :optional clamp
Function: TAGvector-add! vec val :optional clamp
Function: TAGvector-sub vec val :optional clamp
Function: TAGvector-sub! vec val :optional clamp
Function: TAGvector-mul vec val :optional clamp
Function: TAGvector-mul! vec val :optional clamp

Element-wise arithmetic. Vec must be a TAGvector, and val must be either a TAGvector, 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 TAGvector, its elements are added to, subtracted from, or multiplied by the corresponding elements of vec, respectively, and the results are gathered to a TAGvector and returned. The destructive version (those have bang ‘!’ in the name) reuses vec to store the result. If the result of calculation goes out of the range of TAGvector’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: TAGvector-div vec val
Function: TAGvector-div! vec val

Element-wise division of flonum vectors. These are only defined for f16, f32 and f64vector. val must be a TAGvector, 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: TAGvector-and vec val
Function: TAGvector-and! vec val
Function: TAGvector-ior vec val
Function: TAGvector-ior! vec val
Function: TAGvector-xor vec val
Function: TAGvector-xor! vec val

Element-wise logical (bitwise) operation. These procedures are only defined for integral vectors. val must be a TAGvector, 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 TAGvector. The destructive version reuses vec to store the result.

Function: TAGvector-dot vec0 vec1

Calculates the dot product of two TAGvectors. The length of vec0 and vec1 must be the same.

Function: TAGvector-range-check vec min max

Vec must be a TAGvector, and each of min and max must be either a TAGvector, 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: TAGvector-clamp vec min max
Function: TAGvector-clamp! vec min max

Vec must be a TAGvector, and each of min and max must be either a TAGvector, a vector or a list of the same length as vec, or a number, or #f.

Like TAGvector-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.

TAGvector-clamp creates a copy of vec and do clamp operation on it, while TAGvector-clamp! modifies vec. Both return the clamped vector.

 
(s8vector-clamp '#s8(8 14 -3 -22 0) -10 10) ⇒ #s8(8 10 -3 -10 0)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.31.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-block! vec :optional iport start end endian

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-block! 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 section File ports), read-block! 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 section Endianness, for more about endian handling.

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

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-block!. The optional argument endian specifies the output endian. When it is omitted, the value of the parameter default-endian is used (See section Endianness).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on May 28, 2012 using texi2html 1.82.