行列クラスについて
ここでは3次正方行列のもつメソッドについて記載します.
(2次,4次でも要素数の違いがあるだけでほぼ同じメソッドをもっています)
正方行列を使用する場合は,ベクトルクラスと同様に,使用する次数 N ( N = 2, 3, 4 ) に応じてヘッダをインクルードします.
行列のクラスのためのヘッダ |
#include <kvs/MatrixNN> |
変数を宣言する場合は,3次正方行列 の省略型としては
f :float型, d:double型
を宣言することができます.
これはfloat型,double型はKVS内で
Matrix33f, Matrix33d
という名前を付け直されているためです(typedefによって).
本来はtemplateクラスによって,
kvs::Matrix33<float> A;
と記述します.ですので,float型,double型以外の型を使用する場合は
kvs::Matrix33<unsigned char> B;
とすれば行列クラスを使うことができます.
n×m行列の生成
n行m列の行列クラスのオブジェクトを生成するには,.
ヘッダ #include <kvs/Matrixr>
をインクルードし,例えばfloat型の5行6列の行列を定義したい場合は
kvs::Matrix<float> A( 5, 6 );
のようにすればよい.
行列クラスのもつメソッド
行列クラスに用意されているメソッドについては実際に,
(KVSのソースをダウンロードしたディレクトリ) kvs-src/Source/Core/Matrix/Matrix33.h
を見てみて下さい.
ここでは,各メソッドについて使い方を簡単に説明します.
コンストラクタ
float型の行列kvs::Matrix33f を作成する方法としては以下のように4種類用意されています.
※初期値を指定しないでオブジェクトを生成した場合には,初期値 0 が入ります.
// 1. 値を指定しない
kvs::Matrix33f A;
// 2. 要素を1つ1つ記述する
kvs::Matrix33f B( 1.0, 2.0, 0.0,
2.0, 2.0, 1.0,
0.0, 1.0, 3.0 );
// 3. 3次元ベクトルを3つ並べる
kvs::Vector3f v0( 1.0, 1.0, 1.0 );
kvs::Vector3f v1( 2.0, 2.0, 1.0 );
kvs::Vector3f v2( 1.0, 2.0, 4.0 );
// v0, v1, v2 は行ベクトルとしてそれぞれ1行目,2行目,3行目にセットされる
kvs::Matrix33f C( v0, v1, v2 );
// 4. 配列を代入する
float elem[9] = { 1.0, 2.0, 3.0,
4.0, 5.0, 6.0,
7.0, 8.0, 9.0 };
kvs::Matrix33f D( elem );
4番目の配列を代入するコンストラクタは explicit が付いたコンストラクタですので型に注意しましょう.
値の代入: 演算子[ ], set( )
配列と同様に演算子[ ] を使えるほか,値を代入するメソッド set( ) があります.
また,set( ) は引数の渡し方によってオーバーロードされており,コンストラクタと同様に「要素を1つ1つ記述する」,「3次元ベクトルを3つ並べる」,「配列を代入する」の3種類があります.
// 演算子 [ ] で値を代入する
A[0][0] = 1.0; A[0][1] = 1.0; A[0][2] = 3.0;
A[1][0] = 4.0; A[1][1] = 1.0; A[1][2] = 0.0;
A[2][0] = 2.0; A[2][1] = 0.0; A[2][2] = 2.0;
// 要素1つ1つを代入する
A.set( 1.0, 2.0, 2.0,
2.0, 2.0, 1.0,
0.0, 1.0, 3.0 );
// 3次元ベクトルを3つ代入する
A.set( v0, v1, v2 );
// 配列を代入する
A.set( elem );
値の取得: 演算子[ ]
代入と同様に演算子 [ ] が使えます.
float a11 = A[1][1];
std::cout << A[0][0] << " " << A[0][1] << " " << A[0][2] << std::endl;
全要素のクリア: setZero(), setOnes(), setIdentity() など
値を直接代入する他に,成分を固定の値にするメソッドがあります.
setZero():全要素を 0 にする
setOnes():全要素を 1 にする
setIdentity():単位行列にする
setConstant():全要素を引数で渡した値にする
setDiagonal():対角要素を引数で渡した値にした対角行列にする
setRandom():全要素に乱数を設定する
B.setZero(); // 全要素を 0 にする
B.setOnes(); // 全要素を 1 にする
B.setIdentity(); // 単位行列にする
B.setConstant( 5.0 ); // 全要素を 5.0 にする
B.setDiagonal( 2.0 ); // 全対角要素が 2 となる
kvs::Vector3f diag( 1.0, 2.0, 3.0 );
B.setDiagonal( diag ); // 対角要素に diag の成分が設定される
// 乱数を設定するための引数はVectorクラスと同様であり,シードや範囲も設定できる
B.setRandom(); // 全要素に乱数が設定される.
静的メンバ関数: Zero(), Onese(), Identity() など
行列クラスにも静的メンバ関数が用意されており,上述の全要素のクリアと同様のものに加えて,回転行列がある.
Zero():零行列を返す
Ones():要素が全て 1 の行列を返す
Identity():単位行列を返す
Constant(): 全要素を引数で渡した値にした行列を返す
Diagonal():対角要素に引数を代入した対角行列を返す
Random() :全要素に乱数を代入した行列を返す
RotationX(),RotationY(),RotationZ():それぞれx, y, z軸中心の回転を行う行列を返す(引数は角度[degree])
C = kvs::Matrix33f::Zero(); // 零行列を返す
C = kvs::Matrix33f::Ones(); // 要素全てが1の行列を返す
C = kvs::Matrix33f::Identity(); // 単位行列を返す
C = kvs::Matrix33f::Constant( 3.0 ); // 全要素を3にした行列を返す
C = kvs::Matrix33f::Diagonal( 1.0 ); // 対角要素が全て 1 の対角行列を返す
C = kvs::Matrix33f::Random(); // 全要素を乱数で設定した行列を返す
C = kvs::Matrix33f::RotationX( 90.0 ); // x軸周りに90度回転する回転行列を返す
転置行列: transpose( ), transposed( )
転置行列を求めるメソッドには,以下の2種類があります.
transpose( )は自身を上書きして転置行列とし,
transposed( ) は転置を計算したあとの行列を戻り値にして自身を変更しません.
// 自身に上書き
A.transpose( );
// 転置行列を返す(自身に上書きしない)
kvs::Matrix33f E = B.transposed( );
逆行列: invert( ), inverted( )
逆行列を求めるメソッドにも転置乗列の時と同様に,自身を上書きするメソッドといないメソッドがあります.
invert( ) は自身を上書きして逆行列とし,
inverted( )は逆行列を計算した結果の行列を戻り値にして自身を変更しません.
// 自身に上書き
C.invert( );
// 転置行列を返す(自身に上書きしない)
const kvs::Matrix33f F = B.inverted( );
トレース: trace( ), 行列式: determinant( ),階数: rank()
行列のトレースと行列式,行列の階数を計算するメソッドがあります.
戻り値の型は行列クラスを宣言したときと同じ型になります.
// トレース
float tr = A.trace();
// 逆行列
float det = A.determinant();
// 階数
size_t r = A.rank();
行列の性質確認: 対称行列かどうか:isSymmetric(),対角行列かどうか:isDiagonal()
行列が,対称行列か否か,対角行列か否かを確認することが出来ます.
戻り値は bool 値です.
// 対称行列かどうか?
if( A.isSymmetric() ) {
std::cout << "この行列は対角行列です" << std::endl;
}
// 対角行列かどうか
if( !A.isDiagonal() ) {
std::cout << "この行列は対角行列ではありません" << std::endl;
}
オーバーロードされた演算子
標準出力: 出力演算子<<
行列の要素を:
1 2 3
4 5 6
7 8 9
のように標準出力することが出来ます.
std::cout << A ;
四則演算子: +, -, *, /
演算子 + (+=) は行列の要素同士の足し算を行います.
演算子 - ( -= ) も同様です.また,オブジェクトに - をつけると各成分に - をつけたベクトルになります.
C = A + B;
A+=C;
A -= B;
std::cout << -A << std::endl;
演算子 * ( *= ) は行列の積,変数と行列の各要素,ベクトルと行列の積の3種類があります.
変数と行列のかけ算では,複合演算子 *= を用いる場合には変数と行列の順番に注意して下さい.
ベクトルと行列の積では,行列を演算子の前に書いた場合は行列と行ベクトルのかけ算を実行し,行列を演算子の後ろに書いた場には列ベクトルと行列のかけ算を実行します.どちらの場合も戻り値はベクトル型になります.
// 行列同士のかけ算
C = A*B;
A*=B;
// 変数と行列のかけ算
int i = 10;
C = i*B;
C = B*i; // この2つは同じ値になります
C *= i; // 計算可能です
i*=C; // !!! エラーになります !!!
// 行列とベクトルのかけ算
A.set( 1, 1, 1, 1, 1, 1, 2, 2, 2);
v0.set( 1, 1, 1);
kvs::Vector3f x = v0*A; // 行ベクトルと行列のかけ算
kvs::Vector3f y = A*v0; // 列ベクトルと行列のかけ算
演算子 / (/= ) は変数と行列の各要素の割り算です.
かけ算の時と同様に,割り算の場合には,変数と行列の順番に注意して下さい.
D = C/i;
C /= i;
D = i/C; // !!! エラーになります !!!
i /= C; // !!! エラーになります !!!
関係演算子: ==, !=
行列同士が等しいか(各要素の値がすべて一致するか)どうかを判定する関係演算子があります.
戻り値は bool型です.
// 値が等しいかどうか
if( A == B ) {
std::cout << "A == B" << std::endl;
} else if( A != B ) {
std::cout << "A != B" << std::endl;
}
以上の内容をまとめたプログラム: MatrixTest.tgz
Modefied at June 25, 2014
at May 10, 2021