gauche.uvector
- ユニフォームベクタライブラリ ¶ユニフォームベクタを扱う手続きを提供します
(ユニフォームベクタ参照)。
このモジュールは、R7RSユニフォームベクタライブラリ
(scheme.vector.@
)とSRFI-4のスーパーセットです。
@
の部分は実際には要素の型を示す次タグのいずれかです:
u8
, s8
, u16
,
s16
, u32
, s32
, u64
, s64
,
f16
, f32
, f64
, c32
, c64
, c128
。
Gaucheで拡張されている機能は次のとおりです:
f16vector
とc32vector
のサポート。
@vector-add
など、効率の良い要素単位の演算手続き。
gauche.collection
- コレクションフレームワーク参照)と
シーケンスフレームワーク (gauche.sequence
- シーケンスフレームワーク参照)の実装。
例えば map
, for-each
, ref
, subseq
等の
メソッドが使えます。
@vector-ref
は省略可能なデフォルト値を取ります。
ベクタの型が許す範囲外の値を格納しようとした場合、通常はエラーとなります。 いくつかの手続きは省略可能な引数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)
以下の記述では、@
は
s8
, u8
, s16
, u16
,
s32
, u32
, s64
, u64
,
f16
, f32
, f64
, c32
, c64
, c128
のいずれにも置き換えて読むことができるものとします。
註: R7RS-largeでは、それぞれの型に対して個別のライブラリがあり、
例えばu8
ベクタが使いたければ
(use scheme.vector.u8)
(Gauche式)
あるいは (import (scheme vector u8))
(R7RS式)
のようにする必要があります。
一方、gauche.uvector
使った場合は全ての手続きがインポートされます。
• ユニフォームベクタの基本操作: | ||
• ユニフォームベクタの変換: | ||
• ユニフォームベクタの数値演算: | ||
• ユニフォームベクタのブロック入出力: | ||
• バイトベクタ互換性: |
次の手続きは組み込みです。ユニフォームベクタ参照:
make-@vector uvector? @vector? uvector-ref @vector-ref uvector-set! @vector-set! uvector-length
[R7RS vector.@]
{gauche.uvector
}
引数が@ベクタの要素に収まるなら#t
を、そうでなければ#f
を返します。
[R7RS vector.@]
{gauche.uvector
}
引数は@vectorでなければなりません。
それが空なら#t
を、そうでなければ#fを返します。
[R7RS vector.@]
{gauche.uvector
}
数値x … を要素に持つ@vectorを作成して返します。
正確な整数のベクタに対しては、数値は正確な整数でなければならず、
また有効な範囲内の値でなければなりません。
(s8vector 1 2 3) ⇒ #s8(1 2 3)
class
len
:optional fill
¶{gauche.uvector
}
これはGaucheの拡張です。各ユニフォームベクタの型に対応する関数を呼ぶかわりに、
欲しいユニフォームベクタのクラスを渡してベクタを作ることができます。
型ごとのコンストラクタ (make-s8vector
等)はコアのライブラリで提供
されています (ユニフォームベクタ参照)。
(make-uvector <u8vector> 3) ⇒ #u8(0 0 0) (make-uvector <s8vector> 5 -1) ⇒ #s8(-1 -1 -1 -1 -1)
[R7RS vector.@]
{gauche.uvector
}
長さlenの@vectorを作り、
(f seed)
、(f (f seed))
、
(f (f (f seed)))
、… の結果を順に要素とします。
@vector-unfoldは左から右に、
@vector-unfold-rightは右から左に埋めてゆきます。
(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)
[R7RS vector.@]
{gauche.uvector
}
@vectorであるvecの、start要素目(含む)からend要素目(含まない)
までを、fの呼び出し結果で埋めてゆきます。fは整数のインデックスと
現在のシード値を引数にして呼ばれます。
@vector-unfold!
では、fはまずstartとseedを引数にして
呼ばれます。fはstartに埋めるべき値と次のシード値の2値を返さねばなりません。
次にfはstart+1と戻されたシード値を引数に呼ばれ…と、
それがend-start回繰り返されます。
@vector-unfold-right!
も同様に動作しますが、右から左、
つまりend-1から始めてstartに向けて値が埋めてゆかれます。
start >= end であった場合、fは呼ばれることなく、 vecは変更されません。もしインデックスがvecの範囲の外に出た場合は エラーが投げられます。
戻り値は未規定です。
[R7RS vector.@]
{gauche.uvector
}
@vector 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
{gauche.uvector
}
この手続きは全てのユニフォームベクタに適用することができます。
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
{gauche.uvector
}
与えられたクラスのユニフォームベクタの1要素が占める大きさをバイト数で返します。
classがユニフォームベクタのクラスでない場合はエラーが投げられます。
(uvector-class-element-size <u8vector>) ⇒ 1 (uvector-class-element-size <s64vector>) ⇒ 8
[R7RS vector.@]
{gauche.uvector
}
ユニフォームベクタvecのi番目とj番目の要素を入れ替えます。
戻り値は規定されていません。
{gauche.uvector
}
vecのすべて要素にfillをセットします。
startとendで要素の範囲を指定することも出来ます。
戻り値は規定されていません。
[R7RS vector.@]
{gauche.uvector
}
全ての引数は@vectorでなければなりません。
引数が全て同じ長さで、対応する要素が同じ価(=
の意味で)なら#t
を、
そうでなければ#f
を返します。
Gaucheでは、uvectorはequal?
で比較することができます。
[SRFI-66]{gauche.uvector
}
註: これはSRFI-66との互換性のためだけに提供されています。
@vector=
を使ってください。
引数はどちらも@vectorでなければなりません。
両引数が等価なら#t
が、そうでなければ#f
が返されます。
[SRFI-66]{gauche.uvector
}
引数はどちらも@vectorでなければなりません。
vec1がvec2よりも小さければ-1
が、
両者が等しければ0
が、
vec1がvec2よりも大きければ1
が返されます。
短い方のベクタが常に小さいと評価されます。長さが等しい場合は要素を左から順に比較します。
Gaucheでは、uvectorはcompare
で比較することができます。
これらの手続きが提供されるのは、SRFI-66がu8vector-compare
を定義しているためです。
引数が特定の型のベクタであることを明示したい場合に使っても良いでしょう。
[R7RS vector.@]
{gauche.uvector
}
ベクタ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)
{gauche.uvector
}
これは@vector-copy
の汎用バージョンです。
どんな型のuvectorでもvecに渡すことができ、そのコピー
(もしくは、start/endによっては一部のコピー)が返されます。
[R7RS vector.@]
{gauche.uvector
}
vecの要素を逆順にしたコピーを作って返します。
省略可能なstartとendはコピー範囲を限定します。
(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)
[R7RS vector.@]
{gauche.uvector
}
target および source はともに @vector でなければ
なりません。さらに、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)
もし、コピー元のベクタの sstart と send の間にある要素の 数がコピー先のベクタのtstart以降の部分よりも大きければ、超過分の ベクタはだまって捨てられます。
targetとsourceに同一のベクタを渡しても構いません。 コピー先とコピー元の領域が重なっていても、コピーは常に正しく行われます。
注意事項: この手続きは以前はユニフォームベクタ target および source のみを引数としてとり、source の内容を target へ コピーするためだけに使われました。両方のベクタは同じ型で、同じ長さでなけ ればなりませんでした。この API はSRFI-160にあわせて現在の形式に改訂されています。 旧来のインタフェースも後方互換性のためにサポートされて いますが、これは廃止予定で、将来のリリースではサポートされなくなります。
また、SRFI-66もu8vector-copy!
を提供していますが、
引数の順序が異なります(srfi.66
- オクテットベクタ参照)。
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
{gauche.uvector
}
この手続きは、コピー元ベクタsourceの異なる部分を
コピー先ベクタtargetの異なる部分へと一度にコピーするのに使えます。
ssizeが省略されるか0の場合、この手続きは次の動作をします。
;; For each i from 0 to count: (u8vector-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: (u8vector-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)
{gauche.uvector
}
これは@vector-copy!
の汎用バージョンです。
コピー元sourceとコピー先targetはユニフォームベクタであれば
どの型でも許され、また両者の型が異なっていても構いません。
ビット表現がそのままコピーされます。従って異なる型のユニフォームベクタ間で
コピーした場合は、結果は数値の内部表現に依存します。
そのような用法は、バイナリデータを扱う時には便利でしょう。
tstartはtargetの型によって解釈され、 sstartとsendは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)
[R7RS vector.@]
{gauche.uvector
}
引数はすべて@vectorでなければなりません。
引数ベクタの内容を全てつなぎ合わせた新たなベクタを返します。
(引数が一つだけの場合も、新たにアロケートされたベクタが返されます。)
(u8vector-append '#u8(1 2 3) '#u8(4 5) '#u8() '#u8(6 7 8)) ⇒ #u8(1 2 3 4 5 6 7 8)
[R7RS vector.@]
{gauche.uvector
}
@vectorのリストvecsにあるベクタを全て連結した新たな
@vectorを返します。
(u8vector-concatenate '(#u8(1 2 3) #u8(4 5 6))) ⇒ #u8(1 2 3 4 5 6)
[R7RS vector.@]
{gauche.uvector
}
各vecのstartとendで指定される範囲のサブベクタを
連結した新たな@vectorを返します。
(u8vector-append-subvectors '#u8(1 2 3 4) 1 3 '#u8(5 6 7 8) 0 2) ⇒ #u8(2 3 5 6)
[R7RS vector.@]
{gauche.uvector
}
それぞれ、最初のn要素、最後のn要素、最初のn要素を取り残り、
および最後のn要素を取り除いた残り、を要素とするuvectorを作って返します。
nは非負の正確な整数で、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)
なお、uvector-alias
を使うと、元のuvectorと記憶領域を共有する
部分的なuvectorを得ることができます。コピーのオーバヘッドを避けることができます。
[R7RS vector.@]
{gauche.uvector
}
vecを長さnの新たなuvectorに分割し、そのリストを返します。
vecの長さがnの倍数でなければ、最後のuvectorはnより短くなります。
nは正の正確な整数でなければなりません。
(u8vector-segment '#u8(0 1 2 3 4 5 6 7) 3) ⇒ (#u8(0 1 2) #u8(3 4 5) #u8(6 7))
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
[R7RS vector.@]
{gauche.uvector
}
ふたつの@vector
を比較したり、@vector
のハッシュを取ったりできる
比較器に束縛された変数です。比較器の詳細については
基本的な比較器を参照してください。
これらの比較器は順序手続きとハッシュ関数を両方とも実装しています。
{gauche.uvector
}
uvectorは値が昇順に格納されたユニフォームベクタでなければなりません。
この手続きは二分探索を使って、keyと一致する要素を探し、そのインデックスを返します。
一致する要素が無ければ#f
が返されます。
(uvector-binary-search '#u8(0 5 19 32 58 96) 32) ⇒ 3 (uvector-binary-search '#u8(0 5 19 32 58 96) 33) ⇒ #f
省略可能引数startとendはuvector中の探すべき部分を制限します。
startが開始インデックス(その要素も含む)、endが終了インデックス
(その要素自体は含まない)です。
#f
を渡すとデフォルト値(startは0、endはベクタの長さ)と
みなされます。返ってくるインデックスはベクタ全体から見たインデックスになりますが、
start-end間以外のuvectorの要素はソートされている必要はありません。
(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
省略可能なskip引数は、非負の正確な整数か#f
でなければなりません。
skipが正の整数の場合、uvector中の各キーに続くskip個の要素を
飛ばして探索します。例えばskipが2でuvectorが
#u8(3 100 101 5 102 103 13 104 105)
であれば、
3
、5
、13
だけが探索の対象となります。
この機能を使うと、キーに結びつけられた値(ペイロード)をuvector中に直接
格納したまま探索を行うことができます。skipが正の整数の場合、
uvectorの探索が行われる部分の大きさは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)
最後に、rounding引数は一致する要素が見つからなかった場合の振る舞いを 調整します。値は以下のいずれかでなければなりません。
#f
これがデフォルトです。keyと等しい要素だけを探し、
見つからなければ#f
を返します。
floor
keyと等しい要素がみつからなかった場合、keyを越えない、もっとも近い
要素のインデックスを返します。keyがどの要素よりも小さい場合は#f
が
返されます。
ceiling
keyと等しい要素がみつからなかった場合、keyを下回らない、もっとも近い
要素のインデックスを返します。keyがどの要素よりも大きい場合は#f
が
返されます。
(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
註: SRFI-133のvector-binary-search
はこの手続きと良く似ています
(scheme.vector
- R7RSベクタ参照)。ただし、
そちらは一般のScheme値を相手にするために、比較手続きも取ります。
またskipとrounding引数の機能はサポートされません。
[R7RS vector.@]
{gauche.uvector
}
@vector 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)
{gauche.uvector
}
これは@vector->list
の汎用バージョンで、
ユニフォームベクタなら何であれuvecに取ることができます。
省略可能引数の意味は@vector->list
と同じです。
[R7RS vector.@]
{gauche.uvector
}
@vector 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)
{gauche.uvector
}
これは@vector->vector
の汎用バージョンで、
ユニフォームベクタなら何であれuvecに取ることができます。
省略可能引数の意味は@vector->vector
と同じです。
[R7RS vector.@]
{gauche.uvector
}
リストlistを@vectorに変換します。
省略可能な引数clampが、リスト内の要素が正しい範囲外の数であった場合の
動作を指定します。
(clamp引数はGauche独自拡張です。)
モジュール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)
[R7RS vector.@]
{gauche.uvector
}
listの要素を逆順に持つ新たな@vector
を作って返します。
省略可能な引数clampが、リスト内の要素が正しい範囲外の数であった場合の
動作を指定します。
(clamp引数はGauche独自拡張です。)
[R7RS vector.@]
{gauche.uvector
}
ベクタvecを@vectorに変換します。
省略可能な引数startとendが与えられた場合、
それらは取り出される要素の範囲を制限します。
省略可能な引数clampが、ベクタ内の要素が正しい範囲外の数であった場合の
動作を指定します。
(clamp引数はGauche独自拡張です。)
モジュール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)
{gauche.uvector
}
この手続きは、クラスが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の倍数でなければなりません)。 与えられたパラメータでアラインメントの要請が満たせない場合はエラーが通知されます。
ここに上げる手続きはGaucheの拡張で、 ユニフォームベクタ全体に渡る演算を、要素ごとに計算するよりも速く行います。
ほとんどの手続きには関数型バージョン(名前に!
の無いもの)と
線形更新バージョン(名前に!
のついたもの)の二つが用意されています。
関数型バージョンは、呼び出し元が引数と戻り値を変更不可なオブジェクトとして 扱うことを期待します。後からそれらを変更することは予想外の結果を引き起こすかも しれません(特に、関数型バージョンでは引数に渡されたオブジェクトをそのまま 返したり、既に計算済みの値を返したりする可能性もあるので、 特に記述されてなければ、戻り値が常に新たにアロケートされたものであると考えてはいけません。)
線形更新バージョンは、結果を作るために特定の引数のメモリを再利用する可能性が あります。Gaucheではアロケーションを最小化するようにできるだけメモリの再利用をしますが、 引数がその場で変更されていることをあてにしてはいけません。必ず戻り値を利用するように してください。 変更され得る引数については、呼び出し後にそれがどういう状態になっているかは定義されません。
{gauche.uvector
}
要素毎の計算手続きです。vecは@vectorでなければなりません。
また、valはvecと同じ長さの@vectorかベクタかリスト、
あるいは数値(整数ベクタに対しては正確な整数、実数ベクタに対しては実数)
でなければなりません。
valが@vectorの場合、 vecと対応する要素毎に加算、減算、乗算が行われ、 結果が@vectorとして返されます。 線形更新バージョン(名前に‘!’がついているもの)では、vecが 結果を格納するために再利用され、またそれが返されます。 演算の結果が@vectorの要素の値域外になった場合の動作は 省略可能な引数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)
{gauche.uvector
}
要素毎の除算です。これらはf32vectorとf64vectorのみに対して定義されます。
valはvecと同じ大きさの@vectorかベクタかリスト、
あるいは実数でなければなりません。
(f32vector-div '#f32(1.0 2.0 3.0) 2.0) ⇒ #f32(0.5 1.0 1.5)
{gauche.uvector
}
要素毎の論理(ビット)演算です。
これらの手続きは整数ベクタに対してのみ定義されています。
valはvecと同じ大きさの@vectorかベクタかリスト、
あるいは正確な整数でなければなりません。vecの各要素と、対応するvalの要素
(valが非スカラー値の場合)もしくはval自身
(valが整数の場合)とのビット毎のand, inclusive orまたはexclusive or
が計算され、結果が@vectorで返されます。
線形更新バージョン(名前に‘!’がついているもの)では、vecが
結果を格納するために再利用され、またそれが返されます。
{gauche.uvector
}
ふたつの@vectorの内積を計算します。
vec0とvec1の長さは等しくなければなりません。
{gauche.uvector
}
vecは@vectorでなければなりません。
minとmaxはそれぞれ、vecと同じ長さの@vector、
ベクタ、リストのいずれかか、実数もしくは#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)))
{gauche.uvector
}
vecは@vectorでなければなりません。
minとmaxはそれぞれ、vecと同じ長さの@vector、
ベクタ、リストのいずれかか、実数もしくは#f
でなければなりません。
@vector-range-checkと同じように、この手続きはvecの各要素が minおよびmaxで指定される最小値と最大値の間にあるかどうかを 検査します。要素が最小値より小さかった場合はそれが最小値に置き換えられます。 要素が最大値より大きかった場合はそれが最大値に置き換えられます。
@vector-clampはvecのコピーを作ってそれに対して クランプ操作を行います。@vector-clamp!はvecを直接 変更します。どちらもクランプ操作が行われた後の@vectorを返します。
(s8vector-clamp '#s8(8 14 -3 -22 0) -10 10) ⇒ #s8(8 10 -3 -10 0)
ユニフォームベクタは、メモリの固まりを抽象化しているものと考えることも できます。それなら、それをバイナリI/Oに使えないでしょうか。もちろんできます。
{gauche.uvector
}
クラス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-uvector
はiportが
EOFに達していなくても、size要素を読む前に戻ることがあります
(バッファリングモードについてはファイルポートを参照して下さい)。
パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。
データはバイトストリームとして読まれるので、
s8vectorとu8vector以外のユニフォームベクタを与えた場合は
結果がエンディアンに影響を受けることに注意して下さい。
省略可能引数endianによって、入力データのエンディアンを指定
することができます。省略した場合はパラメータdefault-endian
の
値が使われます。エンディアンの扱いについてより詳しくはエンディアンネスを参照して
ください。
入力データの大きさが不明で、EOFまで全てを読み込みたい場合は、下の
port->uvector
を使ってください。
[R7RS base]
{gauche.uvector
}
(read-uvector <u8vector> size iport)
と等価です。
R7RS baseにある手続きです。
{gauche.uvector
}
与えられた入力ポートiportからデータの固まりを読みだし、それを
ユニフォームベクタvecに格納します。
どんな種類のユニフォームベクタでも与えることができます。
省略可能な引数startとendが与えられた場合は、
それらがvec中でデータが格納されるべき領域のインデックスの範囲を
示します。endについては-1でvecの最後を示すこともできます。
その範囲外のvecの値は変更されません。
start、endが与えられなかった場合はvec全体が使われます。
iportが省略された場合はカレント入力ポートが使われます。
要求された領域を埋め終る前に入力がEOFに達した場合は、ベクタの残りの部分は 変更されません。
read-uvector!
が呼ばれた時既にiportがEOFに達していた場合は
EOFが、そうでなければ読まれた要素の数 (バイト数ではありません) が返されます。
iportがバッファードポートであり、そのバッファリングモードが
‘modest’ か ‘none’ であった場合、read-uvector!
はiportが
EOFに達していなくても、vecを埋める前に戻ることがあります
(バッファリングモードについてはファイルポートを参照して下さい)。
パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。
もし、十分なデータが到着することがわかっており、vecを確実に埋めたい場合は
ポートのバッファリングモードを‘full’に変更して下さい。
データはバイトストリームとして読まれるので、
s8vectorとu8vector以外のユニフォームベクタを与えた場合は
結果がエンディアンに影響を受けることに注意して下さい。
省略可能引数endianによって、入力データのエンディアンを指定
することができます。省略した場合はパラメータdefault-endian
の
値が使われます。エンディアンの扱いについてより詳しくはエンディアンネスを参照して
ください。
{gauche.uvector
}
Deprecated.
read-uvector!
の古い名前です。互換性のためサポートされていますが、
新しいコードではread-uvector!
を使ってください。
{gauche.uvector
}
入力ポートiportからEOFまでデータを読み込み、classクラスの
ユニフォームベクタに格納して返します。classが省略された場合は
<u8vector>
が使われます。
要素が1オクテット以上のユニフォームベクタのクラスを指定した場合、 各要素はプラットフォームのネイティブバイトオーダーで埋められます。
この手続きは組み込みのport->string
等と対応しています
(入力ユーティリティ手続き参照)。
[R7RS base]
{gauche.uvector.
}
read-uvector!
と似ていますが、bvはu8vectorでなければなりません。
これはR7RS baseにある手続きです。
{gauche.uvector
}
ユニフォームベクタvecの内容を「そのまま」oportに書き出します。
oportが省略された場合はカレント出力ポートが使われます。
省略可能な引数startとendが与えられた場合は、
それらのインデックスの範囲が示すvecの内容のみが出力されます。
endに-1を渡してvecの最後を示すこともできます。
この手続きの返す値は未定義です。
s8vector
とu8vector
以外のユニフォームベクタを与えた場合、
read-uvector
と同じようにエンディアンの影響を受けることに注意して
下さい。省略可能引数endianによって出力のエンディアンを
指定できます。省略した場合はパラメータdefault-endian
の値が
使われます (エンディアンネス参照)。
[R7RS vector.@]
{gauche.uvector
}
[R7RS base]
{gauche.uvector
}
write-uvector
と似ていますが、bvはu8vectorでなければなりません。
R7RS baseの手続きです。
{gauche.uvector
}
Deprecated.
write-uvector
の古い名前です。互換性のためサポートされていますが、
新しいコードではwrite-uvector
を使ってください。
R7RS-smallはコア(scheme.base
)にバイトベクタを含んでいます。
Gaucheでは、バイトベクタはu8vectorと同じです。
R7RSのバイトベクタの基本的な手続きはこのモジュールで提供されます。
ただし、文字列とバイトベクタの変換手続きは
gauche.unicode
(Unicode transfer encodings参照)および
srfi.181
(符号変換ポート参照)にあります。
{gauche.uvector
}
[R7RS base]
u8vector
の別名です。byte …を要素とするバイトベクタ(u8vector)を
新たに作って返します。
{gauche.uvector
}
[R7RS base]
u8vector?
の別名です。objがバイトベクタ(u8vector)なら
#t
を、そうでなければ#f
を返します。
{gauche.uvector
}
[R7RS base][R7RS bytevector]
長さlenの新たなバイトベクタ(u8vector)を作って返します。
byteが与えられていれば、全ての要素をそれで初期化します。
R7RS baseではbyteの範囲を0から255(両端含む)としていますが、 R7RS bytevectorではそれを-128から255(両端含む)に拡張しています。 負の場合は256を法としてラップアラウンドします。この手続きは拡張範囲をサポートします。
{gauche.uvector
}
[R7RS base]
u8vector-length
の別名です。バイトベクタ(u8vector) bvの長さを返します。
{gauche.uvector
}
[R7RS base]
u8vector-ref
とu8vector-set!
の別名です。
バイトベクタ(u8vector) bv のk番目の要素を返す/セットします。
kが領域外ならエラーが投げられます。
bytevector-u8-set!
の戻り値は規定されていません。
Gaucheの拡張として、(setter bytevector-u8-ref)
は
bytevector-u8-set!
になっています。
{gauche.uvector
}
[R7RS bytevector]
オクテットを-128から127までの符号つきバイトと扱うことを除き、
それぞれbytevector-u8-ref
およびbytevector-u8-set!
と同じです。
Gaucheの拡張として、(setter bytevector-s8-ref)
は
bytevector-s8-set!
になっています。
{gauche.uvector
}
[R7RS base]
u8vector-copy
の別名です。
バイトベクタ(u8vector) bv の新たなコピーを作って返します。
インデックスstartとendでコピーする範囲を限定することができます
(startは含まれ、endは含まれない)。
{gauche.uvector
}
[R7RS base]
u8vector-copy!
の別名です。
targetとsourceはバイトベクタ(u8vector)で、targetは
変更可能でなければなりません。sourceの内容 (startとendで
範囲を限定することもできます) をtargetのtstart以降へとコピーします。
{gauche.uvector
}
これはR6RSのbytevector-copy!
との互換ルーチンです
(なので-r6
サフィックスがついています)。
R6RSバイトベクタライブラリがR7RS-largeにもscheme.bytevector
として
採り入れられたので、R6RSバージョンのbytevector-copy!
もR7RSに入ってきました。
(なのでR7RSには二つの異なるbytevector-copy!
があります。
ひとつはscheme.base
に、もうひとつはscheme.bytevector
に。)
残念なことに、R6RSはしばしば伝統を破って新しいAPIを発明することがあり、
この手続きもそのひとつで、他の*-copy!
系の手続きと引数が異なります。
この手続きでは、バイトベクタsrcのsstartからlenの長さのデータを
targetのtstartからの領域にコピーします。
{gauche.uvector
}
[R7RS base]
u8vector-append
の別名です。
全ての引数はバイトベクタ(u8vector)でなければなりません。
引数の全ての要素をつなげた新たなバイトベクタを作って返します。
{gauche.uvector
}
[R7RS bytevector]
u8vector=?
の別名です。全ての引数はバイトベクタ(u8vector)でなければなりません。
引数の大きさと内容が一致している時に限り#t
を返します。