*ポータブルテンプレート行列ライブラリ(Portable Tamplate Matrix library)
VisualC++ 6, Borland C++, gccで動作するN,M行列ライブラリです.
Springheadでも使用しており,Springheadに含まれています.
C++のテンプレートを使って,n行m列の行列計算ライブラリを作りました.
テンプレートを用い,管理情報をメモリ上から追放したので,floatの配列を
キャストして行列だと思って演算することなどができます.
全てをテンプレートで静的に解決しています. 行列のサイズやポインタなどを保持するための管理領域を持ちません. そのため, 行列の一部(部分行列,ベクトル,行ベクトル,列ベクトル)などを 直接参照することができる(代入も可能). 配列をキャストして行列として使用することも可能. 行列の掛け算などで,行列のサイズが合わない場合,コンパイル時に コンパイラがエラーを出力する. 行列のサイズを動的に変更することができない. といった特徴をもちます.
処理系依存部分の多いテンプレート機能を活用していながら,全機能が, 3つのコンパイラで使用できます.サポートしているコンパイラは, CL (MS Visual C++ 6.0) bcc32(Borland C++ 5.5.1) gcc(GNU c compiler 2.95.3-5) です.
すでに多くの行列ライブラリがありながら,新たに作成した理由は, TNT,MTL の行列は管理領域をメモリに持つため,配列をキャストして 行列として使用することができない. Blitz は TinyMatrix, TinyVector を持つが,Visual C++ で 使用できない. 私の知る限り,部分行列,部分ベクトルへの参照を返す行列ライブラリ は存在しない. からです.
ポータブル テンプレート 行列クラスライブラリは,ヘッダファイルだけからなる クラスライブラリなので, TMatrix.h, TMatrixUtility.h, TVector.h を同じフォルダに入れておき,.cppファイルからヘッダをインクルードするだけで 使用できます.
簡単なサンプルです.適当なファイル名(たとえば sample.cpp) で保存して コンパイルしてください.コンパイルするためには, visual C++ の場合
cl -GX sample.cpp
gccの場合
gcc sample.cpp -lstdc++
bcc の場合
bcc32 sample.cpp
としてください.
#include "TMatrix.h" // 行列ライブラリのインクルードする. #include <iostream> using namespace PTM; // 行列クラスはPTM名前空間の中で宣言されている. void main(){ TMatrix<2,2,float> mat; // 2行2列の行列を宣言 mat[0][0] = 1; mat[0][1] = 2; mat[1][0] = 3; mat[1][1] = 4; TVector<2,float> vec; // 2次元のベクトルを宣言 vec[0] = 1; vec[1] = 0; std::cout << mat; std::cout << vec << std::endl; std::cout << mat * vec << std::endl; // 掛け算 std::cout << mat + mat << std::endl; // 足し算 std::cout << mat - mat << std::endl; // 引き算 std::cout << mat.trans() << std::endl; // 転置 std::cout << mat.inv() << std::endl; // 逆行列 }
次の演算ができます.
:出力, >>:入力 %:外積(2・3次元のみ) 次のメンバ関数を持ちます. unit(): 向きが等しい単位ベクトルを返す. norm(): ベクトルの大きさ(ノルム)を返す. sub_vector(): 部分ベクトルへの参照を返す.
次の演算ができます.
:出力, >>:入力 次のメンバ関数を持ちます. det(): 行列式を返す. inv(): 逆行列を返す. gauss(): ガウスの消去法で方程式を解く. sub_matrix(): 部分行列への参照を返す. row(): 行ベクトルへの参照を返す. col(): 列ベクトルへの参照を返す. sub_matrix()やrow()には値を代入することもできます.
TMatrix<3,3,float> mat; TVector<3, float> vec; mat.row() = vec;
実装のルール
C++ template狂ライブラリ,boost の行列ライブラリ.
//基本クラス template<class E> class TVectorBase { public: /// 実体(派生クラス)へのアクセス E& expression(){ return *(E*)this; } //< 注目 void add(const E& b){ E& a = expression(); for(int i=0; i<a.size(); ++i){ a.data[i] += b.data[i]; } } }; //派生クラス class TVector: public TVectorBase<TVector> { public: float data[10]; size_t size(){ return 10; } };
派生クラスに自分をキャストするという,奇想天外な方法で,派生クラスのデータに, 基本クラスの関数がアクセスしています.
派生クラスに共用体と要素アクセス関数の実装
class TVec2:public PTM::TVectorBase<DIMENC(2), TVecDesc<TVec2<T>, T> >{ public: union{ T data[2]; struct{ T x,y; }; }; /// 要素のアクセス T& item_impl(size_t i){ return data[i]; } };