[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gauche.uvector
- ユニフォームベクタ SRFI-4(SRFI-4)に定義されている、 要素が同一の数値型であるようなベクタを提供します。
Gaucheの実装は、SRFI-4の仕様を次のように拡張しています。
TAGvector->list
は省略可能なstartとendのインデックスを取り、
TAGvector-ref
は省略可能なデフォルト値を取ります。
TAGvector-copy
,
TAGvector-copy!
)、
変換 (TAGvector->vector
, vector->TAGvector
)、
及び各種算術演算(TAGvector-add
等)。
gauche.collection
- コレクションフレームワーク参照)と
シーケンスフレームワーク (gauche.sequence
- シーケンスフレームワーク参照)の実装。
例えば map
, for-each
, ref
, subseq
等の
メソッドがSRFI-4ベクタに対して使えます。
f16vector
のサポート。
フォーマットはハイダイナミックレンジイメージ等に使われている、
1符号ビット、5指数ビット、10仮数ビットです。
通常のベクタではなくSRFI-4ベクタを使うことにより得られる利点がいくつかあります。 まず、SRFI-4ベクタは通常のベクタよりもコンパクトです。 いくつかのオペレーション(特に、Gaucheの拡張仕様であるベクタ上の数値演算)では、 型検査と型変換を個々の要素に対して行わなくても良いため、 極めて効率の良い演算が可能です。さらに、 数値の配列を扱う外部のライブラリとのインタフェースが容易です。 例えば、GaucheのOpenGLバインディングではSRFI-4ベクタを多用しています。
以下の10タイプのベクタが定義されます。
要素が -2^7 から 2^7-1 の間の正確な整数であるベクタ
要素が 0 から 2^8-1 の間の正確な整数であるベクタ
要素が -2^15 から 2^15-1 の間の正確な整数であるベクタ
要素が 0 から 2^16-1 の間の正確な整数であるベクタ
要素が -2^31 から 2^31-1 の間の正確な整数であるベクタ
要素が 0 から 2^32-1 の間の正確な整数であるベクタ
要素が -2^63 から 2^63-1 の間の正確な整数であるベクタ
要素が 0 から 2^64-1 の間の正確な整数であるベクタ
要素が、16ビット浮動小数点数(half floatとしても知られている)で表現 し得るような不正確な実数であるベクタ
要素が、GaucheをコンパイルしたCコンパイラのfloat
で表現し得るような
不正確な実数(通常IEEE単精度浮動少数点数)であるベクタ
要素が、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) |
以下の記述では、TAG
は
s8
, u8
, s16
, u16
,
s32
, u32
, s64
, u64
,
f16
, f32
, f64
のいずれにも置き換えて読むことができるものとします。
9.25.1 ユニフォームベクタの基本操作 | ||
9.25.2 ユニフォームベクタの変換 | ||
9.25.3 ユニフォームベクタの数値演算 | ||
9.25.4 ユニフォームベクタのブロック入出力 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
TAGvectorのクラス。<sequence>
を継承します。
#TAG(n …)
リテラルの単一型のベクタを記述します。
#s8(3 -2 4) #u32(4154 88357 2 323) #f32(3.14 0.554525 -3.342) |
[SRFI-4]
objがTAGvectorなら#t
を、そうでなければ#f
を返します。
[SRFI-4] 数値x … を要素に持つTAGvectorを作成して返します。 正確な整数のベクタに対しては、数値は正確な整数でなければならず、 また有効な範囲内の値でなければなりません。
(s8vector 1 2 3) ⇒ #s8(1 2 3) |
[SRFI-4] 長さlenのTAGvectorを作成して返します。各要素はfillで 初期化されます。正確な整数のベクタに対しては、fillは正確な整数でなければならず、 また有効な範囲内の値でなければなりません。 fillが省略された場合、各要素の初期値は不定です。
(make-u8vector 4 0) ⇒ #u8(0 0 0 0) |
[SRFI-4] TAGvector vecの長さを返します。
モジュールgauche.collection
をインポートしていれば、
vecの長さを知るのに、総称関数size-of
を使うこともできます
(gauche.collection
- コレクションフレームワーク参照)。
(s16vector-length '#s16(111 222 333)) ⇒ 3 (use gauche.collection) (size-of '#s16(111 222 333)) ⇒ 3 |
[SRFI-4+] TAGvector vecのk番目の要素を返します。
kが有効な範囲外であった場合、通常はエラーが通知されますが、 省略可能な引数fallbackが与えられている場合はそれが返されます。
モジュールgauche.collection
をインポートしていれば、
総称関数ref
を使うこともできます。
(u16vector-ref '#u16(111 222 333) 1) ⇒ 222 (use gauche.collection) (ref '#u16(111 222 333) 1) ⇒ 222 |
[SRFI-4+] TAGvector vecのk番目の要素に数値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) |
vecのすべて要素にfillをセットします。 startとendで要素の範囲を指定することも出来ます。
ベクタvecをコピーします。 省略可能な引数startとendが与えられた場合、 それらは取り出される要素の範囲を制限します。
(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) |
target および source はともに TAGvector でなければ なりません。さらに、target は変更可能でなければなりません。 この手続きは、startの要素を、インデックスsstartから(これを含み) send までを、target へインデックス tstartからコピーします。 sstartおよびtstartは省略可能で、その場合には、それぞれ、 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) |
もし、コピー元のベクタの sstart と send の間にある要素の 数がコピー先のベクタのtstart以降の部分よりも大きければ、超過分の ベクタはだまって捨てられます。
注意事項: この手続きは以前はユニフォームベクタ target および
source のみを引数としてとり、source の内容を target へ
コピーするためだけに使われました。両方のベクタは同じ型で、同じ長さでなけ
ればなりませんでした。この API は string-copy!
(SRFI-13) および
vector-copy!
(SRFI-43)にあわせて現在の形式に改訂されています。
旧来のインタフェースもバックワードコンパチビリティのためにサポートされて
いますが、これは廃止予定で、将来のリリースではサポートされなくなります。
コレクションやシーケンスフレームワークを使うと、さらに様々な操作を 行うことができます。
(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) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[SRFI-4+] TAGvector vecをリストに変換します。 省略可能な引数startとendが与えられた場合、 それらは取り出される要素の範囲を制限します。
モジュール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) |
TAGvector vecをベクタに変換します。 省略可能な引数startとendが与えられた場合、 それらは取り出される要素の範囲を制限します。
モジュール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) |
[SRFI-4+] リストlistをTAGvectorに変換します。 省略可能な引数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) |
ベクタvecをTAGvectorに変換します。 省略可能な引数startとendが与えられた場合、 それらは取り出される要素の範囲を制限します。 省略可能な引数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) |
与えられた文字列の内部表現のバイト列と同じバイト列を持つs8vectorもしくは u8vectorを返します。省略可能な範囲引数start、endは、 変換される文字列中の文字位置を指定します。
これらの手続きは、文字を構成するバイト列をランダムにアクセスしたい場合などに 有用です。
(string->u8vector "abc") ⇒ #u8(97 98 99) ;; 内部コードがEUCの場合 (string->u8vector "いろは") ⇒ #u8(164 164 164 237 164 207) |
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) |
与えられたs8vectorもしくはu8vector vecのバイト列と同じ内部バイト列を 持つ文字列を作成して返します。省略可能な範囲引数start、endは、 vec中の変換されるべき範囲をバイト位置で指定します。
vec中のバイト列が文字列の内部表現として不正な値を持っていた場合は、 不完全な文字列が返されます。
与えられた文字列stringの各文字の内部コードを値として持つ s32vectorもしくはu32vectorを返します。 省略可能な範囲引数start、endは、 変換される文字列中の文字位置を指定します。
これらの手続きは、文字列中の文字をランダムにアクセスする場合に便利です。
startとendを考えなければ、 これらの手続きは次のコードのような動作をします:
(lambda (vec) (map-to <string> integer->char vec))) |
省略可能な範囲引数start、endは、 vec中の変換されるべき範囲を指定します。
この手続きは、クラスがuvector-classであり、 ユニフォームベクタvecのメモリ領域を共有するような 新しいユニフォームベクタを作成して返します。 省略可能な引数startとendが与えられた場合は 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の倍数でなければなりません)。 与えられたパラメータでアラインメントの要請が満たせない場合はエラーが通知されます。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
要素毎の計算手続きです。vecはTAGvectorでなければなりません。 また、valはvecと同じ長さのTAGvectorかベクタかリスト、 あるいは数値(整数ベクタに対しては正確な整数、実数ベクタに対しては実数) でなければなりません。
valがTAGvectorの場合、 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)
|
要素毎の除算です。これらはf32vectorとf64vectorのみに対して定義されます。 valはvecと同じ大きさのTAGvectorかベクタかリスト、 あるいは実数でなければなりません。
(f32vector-div '#f32(1.0 2.0 3.0) 2.0) ⇒ #f32(0.5 1.0 1.5) |
要素毎の論理(ビット)演算です。 これらの手続きは整数ベクタに対してのみ定義されています。 valはvecと同じ大きさのTAGvectorかベクタかリスト、 あるいは正確な整数でなければなりません。vecの各要素と、対応するvalの要素 (valが非スカラー値の場合)もしくはval自身 (valが整数の場合)とのビット毎のand, inclusive orまたはexclusive or が計算され、結果がTAGvectorで返されます。 破壊的なバージョン(名前に`!'がついているもの)では、vecが 結果を格納するために再利用されます。
ふたつのTAGvectorの内積を計算します。 vec0とvec1の長さは等しくなければなりません。
vecはTAGvectorでなければなりません。
minとmaxはそれぞれ、vecと同じ長さのTAGvector、
ベクタ、リストのいずれかか、実数もしくは#f
でなければなりません。
vecの各要素に対して、この手続きはそれが対応するminvalとmaxval
の間にあるかどうかを検査します。minvalとmaxvalも範囲に含みます。
ここで、minvalとmaxvalは、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))) |
vecはTAGvectorでなければなりません。
minとmaxはそれぞれ、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) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ユニフォームベクタは、メモリの固まりを抽象化しているものと考えることも できます。それなら、それをバイナリI/Oに使えないでしょうか。もちろんできます。
与えられた入力ポートiportからデータの固まりを読みだし、それを ユニフォームベクタvecに格納します。 どんな種類のユニフォームベクタでも与えることができます。 省略可能な引数startとendが与えられた場合は、 それらがvec中でデータが格納されるべき領域のインデックスの範囲を 示します。endについては-1でvecの最後を示すこともできます。 その範囲外のvecの値は変更されません。 start、endが与えられなかった場合はvec全体が使われます。 iportが省略された場合はカレント入力ポートが使われます。
要求された領域を埋め終る前に入力がEOFに達した場合は、ベクタの残りの部分は 変更されません。
read-block!
が呼ばれた時既にiportがEOFに達していた場合は
EOFが、そうでなければ読まれた要素の数 (バイト数ではありません) が返されます。
iportがバッファードポートであり、そのバッファリングモードが
`modest' か `none' であった場合、read-block!
はiportが
EOFに達していなくても、vecを埋める前に戻ることがあります
(バッファリングモードについてはファイルポート)を参照して下さい。
パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。
もし、十分なデータが到着することがわかっており、vecを確実に埋めたい場合は
ポートのバッファリングモードを`full'に変更して下さい。
データはバイトストリームとして読まれるので、
s8vectorとu8vector以外のユニフォームベクタを与えた場合は
結果がエンディアンに影響を受けることに注意して下さい。
例えば入力が#x01, #x02, #x03, #x04
というバイトシーケンスだったと
します。これをu32vectorに読み込んだ場合、最初の要素は
ビッグエンディアンでは#x01020304
になりますが、
リトルエンディアンでは#x04030201
となるでしょう。
デフォルトではプラットフォームのエンディアンが使われます。
エンディアンを指定したい場合は、シンボルbig-endian
もしくは
little-endian
をendian引数に渡して下さい。
(実際には、単純なビッグ/リトル以外のエンディアンも存在します。
binary.io
- バイナリI/Oの議論も参照してください。)
ユニフォームベクタvecの内容を「そのまま」oportに書き出します。 oportが省略された場合はカレント出力ポートが使われます。 省略可能な引数startとendが与えられた場合は、 それらのインデックスの範囲が示すvecの内容のみが出力されます。 endに-1を渡してvecの最後を示すこともできます。 この手続きの返す値は未定義です。
s8vector
とu8vector
以外のユニフォームベクタを与えた場合、
read-block!
と同じようにエンディアンの影響を受けることに注意して
下さい。u32vector中の数値#x01020304
は、
endian引数によって
バイトシーケンス#x01, #x02, #x03, #x04
と
なるかもしれませんし、#x04, #x03, #x02, #x01
となるかもしれません。
endian引数のデフォルト値はプラットフォームによって異なります。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.