For Gauche 0.9.5


Next: , Previous: , Up: ライブラリモジュール - Gauche拡張モジュール   [Contents][Index]

9.35 gauche.uvector - ユニフォームベクタ

Module: gauche.uvector

SRFI-4(SRFI-4)に定義されている、 要素が同一の数値型であるようなベクタを提供します。

Gaucheの実装は、SRFI-4の仕様を次のように拡張しています。

通常のベクタではなくSRFI-4ベクタを使うことにより得られる利点がいくつかあります。 まず、SRFI-4ベクタは通常のベクタよりもコンパクトです。 いくつかのオペレーション(特に、Gaucheの拡張仕様であるベクタ上の数値演算)では、 型検査と型変換を個々の要素に対して行わなくても良いため、 極めて効率の良い演算が可能です。さらに、 数値の配列を扱う外部のライブラリとのインタフェースが容易です。 例えば、GaucheのOpenGLバインディングではSRFI-4ベクタを多用しています。

以下の11タイプのベクタが定義されます。

s8vector

要素が -2^7 から 2^7-1 の間の正確な整数であるベクタ

u8vector

要素が 0 から 2^8-1 の間の正確な整数であるベクタ

s16vector

要素が -2^15 から 2^15-1 の間の正確な整数であるベクタ

u16vector

要素が 0 から 2^16-1 の間の正確な整数であるベクタ

s32vector

要素が -2^31 から 2^31-1 の間の正確な整数であるベクタ

u32vector

要素が 0 から 2^32-1 の間の正確な整数であるベクタ

s64vector

要素が -2^63 から 2^63-1 の間の正確な整数であるベクタ

u64vector

要素が 0 から 2^64-1 の間の正確な整数であるベクタ

f16vector

要素が、16ビット浮動小数点数(half floatとしても知られている)で表現 し得るような不正確な実数であるベクタ

f32vector

要素が、GaucheをコンパイルしたCコンパイラのfloatで表現し得るような 不正確な実数(通常IEEE単精度浮動少数点数)であるベクタ

f64vector

要素が、GaucheをコンパイルしたCコンパイラのdoubleで表現し得るような 不正確な実数(通常IEEE倍精度浮動少数点数)であるベクタ

ベクタの型が許す範囲外の値を格納しようとした場合、通常はエラーとなります。 いくつかの手続きは省略可能な引数clampによって、 そのような場合に別のふるまいを指定することができます。 clampには以下のいずれかの値を与えることが出来ます。

#f

デフォルト (エラーを通知)

high

高い方の値をクランプ、すなわち、格納しようとする値が許される値の最大値より大きかった 場合は、可能な最大値を代わりに格納します。

low

低い方の値をクランプ、すなわち、格納しようとする値が許される値の最小値より大きかった 場合は、可能な最小値を代わりに格納します。

both

高いほうと低いほうの両方の値をクランプします。

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

以下の記述では、TAGs8, u8, s16, u16, s32, u32, s64, u64, f16, f32, f64 のいずれにも置き換えて読むことができるものとします。


Next: , Previous: , Up: ユニフォームベクタ   [Contents][Index]

9.35.1 ユニフォームベクタの基本操作

Builtin Class: < TAGvector>

TAGvectorのクラス。<sequence>を継承します。

Reader Syntax: #TAG(n …)

リテラルの単一型のベクタを記述します。

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

[SRFI-4] objTAGvectorなら#tを、そうでなければ#fを返します。

Function: uvector? obj

objがいずれかの型のユニフォームベクタなら#tを、 そうでなければ#fを返します。

Function: TAGvector x

[SRFI-4] 数値x … を要素に持つTAGvectorを作成して返します。 正確な整数のベクタに対しては、数値は正確な整数でなければならず、 また有効な範囲内の値でなければなりません。

(s8vector 1 2 3) ⇒ #s8(1 2 3)
Function: make- TAGvector len :optional fill

[SRFI-4] 長さlenTAGvectorを作成して返します。各要素はfillで 初期化されます。正確な整数のベクタに対しては、fillは正確な整数でなければならず、 また有効な範囲内の値でなければなりません。 fillが省略された場合、各要素の初期値は不定です。

(make-u8vector 4 0) ⇒ #u8(0 0 0 0)
Function: make-uvector class len :optional fill

これはGaucheの拡張です。各ユニフォームベクタの型に対応する関数を呼ぶかわりに、 欲しいユニフォームベクタのクラスを渡してベクタを作ることができます。

(make-uvector <u8vector> 3)    ⇒ #u8(0 0 0)
(make-uvector <s8vector> 5 -1) ⇒ #s8(-1 -1 -1 -1 -1)
Function: TAG vector-length vec

[SRFI-4] TAGvector vecの長さを返します。

モジュールgauche.collectionをインポートしていれば、 vecの長さを知るのに、総称関数size-ofを使うこともできます (コレクションフレームワーク参照)。

(s16vector-length '#s16(111 222 333)) ⇒ 3

(use gauche.collection)
(size-of '#s16(111 222 333)) ⇒ 3
Function: uvector-length uvector

これはTAGvector-lengthの汎用バージョンです。 どんな型のユニフォームベクタでも渡すことができ、 その要素数が返されます。

Function: uvector-size uvector :optional start end

この手続きは全てのユニフォームベクタに適用することができます。 uvectorのバイナリデータとしてのサイズをオクテット数で返します。

startおよび/またはendが与えられた場合は、 これらのインデックスの間のデータについてのみサイズが計算されます。 endには、ベクタ終端を示すために-1を与えることもできます。 返される値は (write-uvector uvector port start end) によって 出力されるオクテット数と一致します。

(要素数を返すuvector-lengthと混同しないようにしてください。)

(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

与えられたクラスのユニフォームベクタの1要素が占める大きさをバイト数で返します。 classがユニフォームベクタのクラスでない場合はエラーが投げられます。

(uvector-class-element-size <u8vector>)  ⇒ 1
(uvector-class-element-size <s64vector>) ⇒ 8
Function: TAG vector-ref vec k :optional fallback

[SRFI-4+] TAGvector veck番目の要素を返します。

kが有効な範囲外であった場合、通常はエラーが通知されますが、 省略可能な引数fallbackが与えられている場合はそれが返されます。

モジュールgauche.collectionをインポートしていれば、 総称関数refを使うこともできます。

(u16vector-ref '#u16(111 222 333) 1) ⇒ 222

(use gauche.collection)
(ref '#u16(111 222 333) 1) ⇒ 222
Function: uvector-ref vec k :optional fallback

TAGvector-refの汎用バージョンです。 vecにどんな種類のユニフォームベクタを取ることができ、 そのk番めの要素を返します。 kが有効な範囲外であった場合、通常はエラーが通知されますが、 省略可能な引数fallbackが与えられている場合はそれが返されます。

この手続きは様々な種類のユニフォームベクタに対して動作するような一般的なコードを 書く際にとても便利ですが、それぞれの種類のユニフォームベクタ専用の アクセサに比べると遅いです。GaucheのコンパイラはTAGvector-refの 呼び出しを認識して非常に効率の良いコードを出すのに対し、 この手続きは通常の手続き呼び出しになるからです。内部のループ内で呼び出す場合、 これは大きな差になるかもしれません。

なお、(setter uvector-ref)uvector-set!です。

Function: TAG vector-set! vec k n :optional clamp

[SRFI-4+] TAGvector veck番目の要素に数値nをセットします。 省略可能な引数clampが、nが正しい範囲外の数であった場合の動作を指定します。 デフォルトではエラーが通知されます。

モジュールgauche.collectionをインポートしていれば、 総称関数refのsetter手続きを使うこともできます。

(let ((v (s32vector -439 852 8933)))
  (s32vector-set! v 1 4)
  v)
 ⇒ #s32vector(-439 4 8933)

(use gauche.collection)
(let ((v (s32vector -439 852 8933)))
  (set! (ref v 1) 4)
  v)
 ⇒ #s32vector(-439 4 8933)
Function: uvector-set! vec k val

TAGvector-set!の汎用バージョンです。全ての種類の ユニフォームベクタを扱えますが、特定のユニフォームベクタ用のセッターを 使うよりやや遅いです。

Function: TAG vector-fill! vec fill :optional start end

vecのすべて要素にfillをセットします。 startendで要素の範囲を指定することも出来ます。

Function: TAG vector-copy vec :optional start end

ベクタvecをコピーします。 省略可能な引数startendが与えられた場合、 それらは取り出される要素の範囲を制限します。

(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

これはTAGvector-copyの汎用バージョンです。 どんな型のuvectorでもvecに渡すことができ、そのコピー (もしくは、start/endによっては一部のコピー)が返されます。

Function: TAG vector-copy! target tstart source :optional sstart send

target および source はともに TAGvector でなければ なりません。さらに、target は変更可能でなければなりません。 この手続きは、sourceの要素を、インデックスsstartから(これを含み) send までを、target へインデックス tstartからコピーします。 sstartおよびsendは省略可能で、その場合には、それぞれ、 0 および sourceの長さが仮定されます。

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

もし、コピー元のベクタの sstartsend の間にある要素の 数がコピー先のベクタのtstart以降の部分よりも大きければ、超過分の ベクタはだまって捨てられます。

targetsourceに同一のベクタを渡しても構いません。 コピー先とコピー元の領域が重なっていても、コピーは常に正しく行われます。

注意事項: この手続きは以前はユニフォームベクタ target および source のみを引数としてとり、source の内容を target へ コピーするためだけに使われました。両方のベクタは同じ型で、同じ長さでなけ ればなりませんでした。この API は string-copy! (SRFI-13) および vector-copy! (SRFI-133)にあわせて現在の形式に改訂されています。 旧来のインタフェースもバックワードコンパチビリティのためにサポートされて いますが、これは廃止予定で、将来のリリースではサポートされなくなります。

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

この手続きは、コピー元ベクタsourceの異なる部分を コピー先ベクタtargetの異なる部分へと一度にコピーするのに使えます。

ssizeが省略されるか0の場合、この手続きは次の動作をします。

;; For each i from 0 to count:
(TAGvector-copy! target (+ tstart (* i tstride))
                 source sstart)

つまり、sourceベクタの内容 (sstartが指定されてればそこから、 指定が無ければ最初から)をtargetベクタに、tstrideづつインデックスを 進めながらコピーします。コピー先のインデックスがtargetベクタの範囲を 越えるか、countが指定されていればその回数分だけコピーが済むかすれば 手続きは終了します。次の例を見てください。

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

ssizeに正の整数が与えられた場合は、コピー元ベクタもssizeごとに 分割されます。

;; For each i from 0 to count:
(TAGvector-copy! target (+ tstart (* i tstride))
                 source (+ sstart (* i sstride))
                        (+ sstart (* i sstride) ssize))

つまり、コピー元インデックスをsstrideづつ、コピー先を dstrideづつ増やしながら、コピー元からそれぞれssize分のデータが切り出されて targetにコピーされます。この場合、sstrideは省略されると ssizeと同じになります。

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

操作はcount個のデータ片がコピーされるか、コピー元あるいはコピー先の インデックスがそれぞれのベクタの終端に達したら終わります。

ヒント: コピー元のベクタの中程だけ (最後までではなく) をコピーしたい場合は、 sstrideに0を与えればできます。

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

コレクションやシーケンスフレームワークを使うと、さらに様々な操作を 行うことができます。

(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

これはTAGvector-copy!の汎用バージョンです。 コピー元sourceとコピー先targetはユニフォームベクタであれば どの型でも許され、また両者の型が異なっていても構いません。 ビット表現がそのままコピーされます。従って異なる型のユニフォームベクタ間で コピーした場合は、結果は数値の内部表現に依存します。 そのような用法は、バイナリデータを扱う時には便利でしょう。

tstarttargetの型によって解釈され、 sstartsendsourceの型によって解釈されます。

(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: TAG vector-append vec …

引数はすべてTAGvectorでなければなりません。 引数ベクタの内容を全てつなぎ合わせた新たなベクタを返します。

(u8vector-append '#u8(1 2 3) '#u8(4 5) '#u8() '#u8(6 7 8))
  ⇒ #u8(1 2 3 4 5 6 7 8)

Next: , Previous: , Up: ユニフォームベクタ   [Contents][Index]

9.35.2 ユニフォームベクタの変換

Function: TAG vector->list vec :optional start end

[SRFI-4+] TAGvector vecをリストに変換します。 省略可能な引数startendが与えられた場合、 それらは取り出される要素の範囲を制限します。

モジュールgauche.collectionをインポートしていれば、 総称関数coerce-toを使うこともできます。

(u32vector->list '#u32(9 2 5)) ⇒ (9 2 5)

(use gauche.collection)
(coerce-to <list> '#u32(9 2 5)) ⇒ (9 2 5)
Function: TAG vector->vector vec :optional start end

TAGvector vecをベクタに変換します。 省略可能な引数startendが与えられた場合、 それらは取り出される要素の範囲を制限します。

モジュールgauche.collectionをインポートしていれば、 総称関数coerce-toを使うこともできます。

(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+] リストlistTAGvectorに変換します。 省略可能な引数clampが、リスト内の要素が正しい範囲外の数であった場合の 動作を指定します。

モジュールgauche.collectionをインポートしていれば、 総称関数coerce-toを使うこともできます。

(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

ベクタvecTAGvectorに変換します。 省略可能な引数startendが与えられた場合、 それらは取り出される要素の範囲を制限します。 省略可能な引数clampが、ベクタ内の要素が正しい範囲外の数であった場合の 動作を指定します。

モジュールgauche.collectionをインポートしていれば、 総称関数coerce-toを使うこともできます。

(vector->f64vector '#(3.1 5.4 3.2)) ⇒ #f64(3.1 5.4 3.2)

(use gauche.collection)
(coerce-to <f64vector> '#(3.1 5.4 3.2)) ⇒ #f64(3.1 5.4 3.2)
Function: string->s8vector string :optional start end immutable?
Function: string->u8vector string :optional start end immutable?

与えられた文字列の内部表現のバイト列と同じバイト列を持つs8vectorもしくは u8vectorを返します。省略可能な範囲引数startendは、 変換される文字列中の文字位置を指定します (バイト位置ではないことに注意)。

デフォルトでは、元の文字列の内容が新たに作られる変更可能なユニフォームベクタへと コピーされ、そのベクタが返されます。しかし、省略可能引数immutable?に 真の値が渡された場合、返されるユニフォームベクタは変更不可能となり、 また文字列本体のコピーが避けられる可能性があります。 (Gaucheでは、文字列本体は変更不可能で、string-set!は新たな 文字列本体を作り出します。したがってstring->u8vectorimmutable?#tを渡してユニフォームベクタを作った後、 元の文字列を変更しても、作られたユニフォームベクタは変更されません。)

これらの手続きは、文字を構成するバイト列をランダムにアクセスしたい場合などに 有用です。

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

;; 内部コードがEUCの場合
(string->u8vector "いろは") ⇒ #u8(164 164 164 237 164 207)
(string->u8vector "very large string .... " 0 -1 #t)
  ⇒ #u8(...)  ; 変更不可、元の文字列と内容を共有
Function: string->s8vector! target tstart string :optional start end
Function: string->u8vector! target tstart string :optional start end

target は、それぞれ s8vector あるいは u8vector でなければなりません。 target は、変更可能でなければなりません。 string の生バイト表現を target へインデックス tstart からコピーします。

target を返します。

(let ((target (make-u8vector 10 0)))
  (string->u8vector! target 3 "abcde"))
 ⇒ #u8(0 0 0 97 98 99 100 101 0 0)
Function: s8vector->string vec :optional start end terminator
Function: u8vector->string vec :optional start end terminator

与えられたs8vectorもしくはu8vector vecのバイト列と同じ内部バイト列を 持つ文字列を作成して返します。省略可能な範囲引数startendは、 vec中の変換されるべき範囲をバイト位置で指定します。

省略可能引数terminatorは正確な整数か#fでなければなりません (#fがデフォルト)。正確な整数が与えられた場合、vecの中に その数値が現れれば、その直前までが結果の文字列となります。 例えば0を与えることで、バッファからNUL終端された文字列を読むことができます。

(u8vector->string '#u8(65 66 0 67 68) 0 5)   ⇒ "AB\0CD"
(u8vector->string '#u8(65 66 0 67 68) 0 5 0) ⇒ "AB"

vec中のバイト列が文字列の内部表現として不正な値を持っていた場合は、 不完全な文字列が返されます。

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

与えられた文字列stringの各文字の内部コードを値として持つ s32vectorもしくはu32vectorを返します。 省略可能な範囲引数startendは、 変換される文字列中の文字位置を指定します。

これらの手続きは、文字列中の文字をランダムにアクセスする場合に便利です。

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

targetは変更可能なs32vectorもしくはu32vectorでなければなりません。 targetの場所tstartから、stringの各文字のコードポイントを 順に埋めてゆきます。targetベクタの終端に達するか、文字が無くなるまで繰り返します。

省略可能な引数startendstring内の文字位置のインデックスで、 考慮するstringの範囲を制限します。

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

startendを考えなければ、 これらの手続きは次のコードのような動作をします:

(lambda (vec) (map-to <string> integer->char vec)))

省略可能な範囲引数startendは、 vec中の変換されるべき範囲を指定します。

省略可能引数terminatorは、正確な整数か#fでなければ なりません (#fがデフォルト)。正確な整数が与えられ、 入力にその数値が見つかった場合は、出力の文字列はその直前で 打ちきられます。

(u32vector->string '#u32(65 66 0 67 68) 0 5 0) ⇒ "AB"
Function: uvector-alias uvector-class vec :optional start end

この手続きは、クラスがuvector-classであり、 ユニフォームベクタvecのメモリ領域を共有するような 新しいユニフォームベクタを作成して返します。 省略可能な引数startendが与えられた場合は vecの内容のうちそれらのインデックスで指定される範囲のみが使われます。 メモリ領域が共有されているので、vecに加える変更は 新しいベクタから見えますし、その逆も可能です。

クラスuvector-classはユニフォームベクタのクラスでなければなりませんが、 vecのクラスと一致している必要はありません。 そのような場合は、新しいベクタはvecと同じメモリ領域の値を 異なる値と解釈するかもしれません。 例えば、次のコードはGaucheが走っているマシンが リトルエンディアンであるかビッグエンディアンであるかを判定します。

(let ((u8v (uvector-alias <u8vector> #u32(1))))
  (if (zero? (u8vector-ref u8v 0))
      'big-endian
      'little-endian))

uvector-classがs8vectorかu8vector以外の場合、 新しいベクタが指す領域は、そのベクタの要素のアラインメントの要請に したがっていなければなりません。 ユニフォームベクタの開始点は常に全てのユニフォームベクタのアラインメント要請を 満たします。したがって、例えばu8vectorからu32vectorを作成する場合、 startおよびendは4の倍数でなければなりません (あるいは、start/endが省略された場合、vecの長さが 4の倍数でなければなりません)。 与えられたパラメータでアラインメントの要請が満たせない場合はエラーが通知されます。


Next: , Previous: , Up: ユニフォームベクタ   [Contents][Index]

9.35.3 ユニフォームベクタの数値演算

Function: TAG vector-add vec val :optional clamp
Function: TAG vector-add! vec val :optional clamp
Function: TAG vector-sub vec val :optional clamp
Function: TAG vector-sub! vec val :optional clamp
Function: TAG vector-mul vec val :optional clamp
Function: TAG vector-mul! vec val :optional clamp

要素毎の計算手続きです。vecTAGvectorでなければなりません。 また、valvecと同じ長さのTAGvectorかベクタかリスト、 あるいは数値(整数ベクタに対しては正確な整数、実数ベクタに対しては実数) でなければなりません。

valTAGvectorの場合、 vecと対応する要素毎に加算、減算、乗算が行われ、 結果がTAGvectorとして返されます。 破壊的なバージョン(名前に‘!’がついているもの)では、vecが 結果を格納するために再利用されます。 演算の結果がTAGvectorの要素の値域外になった場合の動作は 省略可能な引数clampによって指定されます。 (f32vectorとf64vectorでは、値域外になった要素にはinfinityが格納され、 clampの値は無視されます)。

valが数値である場合、vecの各要素とその数値の間で演算が行われます。

(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: TAG vector-div vec val
Function: TAG vector-div! vec val

要素毎の除算です。これらはf32vectorとf64vectorのみに対して定義されます。 valvecと同じ大きさのTAGvectorかベクタかリスト、 あるいは実数でなければなりません。

(f32vector-div '#f32(1.0 2.0 3.0) 2.0) ⇒ #f32(0.5 1.0 1.5)
Function: TAG vector-and vec val
Function: TAG vector-and! vec val
Function: TAG vector-ior vec val
Function: TAG vector-ior! vec val
Function: TAG vector-xor vec val
Function: TAG vector-xor! vec val

要素毎の論理(ビット)演算です。 これらの手続きは整数ベクタに対してのみ定義されています。 valvecと同じ大きさのTAGvectorかベクタかリスト、 あるいは正確な整数でなければなりません。vecの各要素と、対応するvalの要素 (valが非スカラー値の場合)もしくはval自身 (valが整数の場合)とのビット毎のand, inclusive orまたはexclusive or が計算され、結果がTAGvectorで返されます。 破壊的なバージョン(名前に‘!’がついているもの)では、vecが 結果を格納するために再利用されます。

Function: TAG vector-dot vec0 vec1

ふたつのTAGvectorの内積を計算します。 vec0vec1の長さは等しくなければなりません。

Function: TAG vector-range-check vec min max

vecTAGvectorでなければなりません。 minmaxはそれぞれ、vecと同じ長さのTAGvector、 ベクタ、リストのいずれかか、実数もしくは#fでなければなりません。

vecの各要素に対して、この手続きはそれが対応するminvalmaxval の間にあるかどうかを検査します。minvalmaxvalも範囲に含みます。 ここで、minvalmaxvalは、min/maxが非スカラー値 であればvecの要素に対応するそれぞれの要素、 min/maxが数値であればその数値そのものです。 min#fの場合、最小値はマイナス無限大と考えられます。 max#fの場合、最大値はプラス無限大と考えられます。

vecの全ての要素が範囲内であった場合は#fが返されます。 そうでなければ、範囲を外れた要素のうちもっとも左のもののvec内での インデックスが返されます。

(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: TAG vector-clamp vec min max
Function: TAG vector-clamp! vec min max

vecTAGvectorでなければなりません。 minmaxはそれぞれ、vecと同じ長さのTAGvector、 ベクタ、リストのいずれかか、実数もしくは#fでなければなりません。

TAGvector-range-checkと同じように、この手続きはvecの各要素が minおよびmaxで指定される最小値と最大値の間にあるかどうかを 検査します。要素が最小値より小さかった場合はそれが最小値に置き換えられます。 要素が最大値より大きかった場合はそれが最大値に置き換えられます。

TAGvector-clampはvecのコピーを作ってそれに対して クランプ操作を行います。TAGvector-clamp!はvecを直接 変更します。どちらもクランプ操作が行われた後のTAGvectorを返します。

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

Previous: , Up: ユニフォームベクタ   [Contents][Index]

9.35.4 ユニフォームベクタのブロック入出力

ユニフォームベクタは、メモリの固まりを抽象化しているものと考えることも できます。それなら、それをバイナリI/Oに使えないでしょうか。もちろんできます。

Function: read-uvector class size :optional iport endian

クラスclassのユニフォームベクタの要素をsize個、iportから 読み込み、それを新たに作ったユニフォームベクタとして返します。 iportが省略された場合は、現在の入力ポートが使われます。

例えば次のようにして、入力をオクテットストリームとして読み込めます:

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

入力ポートが既にEOFに達していた場合はEOFオブジェクトが返されます。 size要素を読む前に入力がEOFに達した場合、返されるuvectorの長さは sizeより短いものとなります。

iportがバッファードポートであり、そのバッファリングモードが ‘modest’ か ‘none’ であった場合、read-uvectoriportが EOFに達していなくても、size要素を読む前に戻ることがあります (バッファリングモードについてはファイルポートを参照して下さい)。 パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。

データはバイトストリームとして読まれるので、 s8vectorとu8vector以外のユニフォームベクタを与えた場合は 結果がエンディアンに影響を受けることに注意して下さい。 省略可能引数endianによって、入力データのエンディアンを指定 することができます。省略した場合はパラメータdefault-endianの 値が使われます。エンディアンの扱いについてより詳しくはエンディアンを参照して ください。

入力データの大きさが不明で、EOFまで全てを読み込みたい場合は、下の port->uvectorを使ってください。

R7RSにはread-bytevectorがあります。これはread-uvector<u8vector>を渡すのと等価です。

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

与えられた入力ポートiportからデータの固まりを読みだし、それを ユニフォームベクタvecに格納します。 どんな種類のユニフォームベクタでも与えることができます。 省略可能な引数startendが与えられた場合は、 それらがvec中でデータが格納されるべき領域のインデックスの範囲を 示します。endについては-1でvecの最後を示すこともできます。 その範囲外のvecの値は変更されません。 startendが与えられなかった場合はvec全体が使われます。 iportが省略された場合はカレント入力ポートが使われます。

要求された領域を埋め終る前に入力がEOFに達した場合は、ベクタの残りの部分は 変更されません。

read-uvector!が呼ばれた時既にiportがEOFに達していた場合は EOFが、そうでなければ読まれた要素の数 (バイト数ではありません) が返されます。

iportがバッファードポートであり、そのバッファリングモードが ‘modest’ か ‘none’ であった場合、read-uvector!iportが EOFに達していなくても、vecを埋める前に戻ることがあります (バッファリングモードについてはファイルポートを参照して下さい)。 パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。 もし、十分なデータが到着することがわかっており、vecを確実に埋めたい場合は ポートのバッファリングモードを‘full’に変更して下さい。

データはバイトストリームとして読まれるので、 s8vectorとu8vector以外のユニフォームベクタを与えた場合は 結果がエンディアンに影響を受けることに注意して下さい。 省略可能引数endianによって、入力データのエンディアンを指定 することができます。省略した場合はパラメータdefault-endianの 値が使われます。エンディアンの扱いについてより詳しくはエンディアンを参照して ください。

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

read-uvector!の古い名前です。互換性のためサポートされていますが、 新しいコードではread-uvector!を使ってください。

Function: port->uvector iport :optional class

入力ポートiportからEOFまでデータを読み込み、classクラスの ユニフォームベクタに格納して返します。classが省略された場合は <u8vector>が使われます。

要素が1オクテット以上のユニフォームベクタのクラスを指定した場合、 各要素はプラットフォームのネイティブバイトオーダーで埋められます。

この手続きは組み込みのport->string等と対応しています (入力ユーティリティ手続き参照)。

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

ユニフォームベクタvecの内容を「そのまま」oportに書き出します。 oportが省略された場合はカレント出力ポートが使われます。 省略可能な引数startendが与えられた場合は、 それらのインデックスの範囲が示すvecの内容のみが出力されます。 endに-1を渡してvecの最後を示すこともできます。 この手続きの返す値は未定義です。

s8vectoru8vector以外のユニフォームベクタを与えた場合、 read-uvectorと同じようにエンディアンの影響を受けることに注意して 下さい。省略可能引数endianによって出力のエンディアンを 指定できます。省略した場合はパラメータdefault-endianの値が 使われます (エンディアン参照)。

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

write-uvectorの古い名前です。互換性のためサポートされていますが、 新しいコードではwrite-uvectorを使ってください。


Previous: , Up: ユニフォームベクタ   [Contents][Index]