next up previous contents
Next: 4次のRunge-Kutta 法 Up: プログラミングにおける問題点と対策 Previous: プログラミングにおける問題点と対策

VectorクラスとMatrixクラス

就職試験などのために卒業研究の時間が確保しにくいので,Matrix クラスは手 元にあった本
Bruce Eckel: Using C++, Osborne McGraw-Hill(1989)
のソースコードを使うことにした.しかしながら,C++ は発展途上の言語である からバージョンによる変化も激しく Bruce のテキストは今や古い感じを与える. GNU のgcc は3.0 からISO C++(文献[7]に相当)に準拠したので,gcc でコンパイルできなければならない.しかし,Bruce のソースコードにはVisual C++ v.6 でコンパイル可能であってもLinux のgcc v.3.0以上でエラーになる箇所がある.そこで必要な箇所のみ採用し,C++ のバイブルである
Bjarne Stroustrup: プログラミング言語C++ 第3版,アジソン・ウェスレイ(1998)
を参考にして書き換えた.

ベクトルは行列の特殊であるから継承関係にある.Vectorクラスを Matrixクラ スのサブクラスとして定義するのが数学から見ても素直な考え方である.しかし 内積の定義に問題が生じる.内積は行列の積を使って $ {}^t\mathbf a \mathbf b$で定義される.ここで $ {}^t\mathbf a$$ \mathbf a$の転置行列である.しかし転置はC++の演算子でないので,プログラムの中では内積を関数形で

     const int VLEN = 3;
     vector a, b;
     double x;
     x = transpose(a)* b
と書かざるをえない.ここで ``*'' は行列の積を表す.内積はしばしば 現れる演算なので,もっと簡潔に表したい.そこでVectorクラスとMatrixクラス をおのおの独立なクラスとして定義した.行列の四則演算はMatrixクラスの定義 の中で
    matrix operator+(const matrix& rval);  // matrix addition
    matrix operator-(const matrix& rval);  // matrix subtraction
    matrix operator-();                    // unary minus
    matrix operator*(const matrix& rval);  // matrix multiplication
    matrix operator*(const double  rval);  // scalar multiplication

//引数の値に基づいて新しい値を生成するだけの演算子
    matrix operator+(const matrix& a, const matrix& b);
    matrix operator-(const matrix& a, const matrix& b);
    matrix operator*(const matrix& a, double b);
    matrix operator*(double a, const matrix& b);
    matrix operator/(const matrix &a, double b);
    matrix operator/(double a, const matrix& b);
とプロトタイプ宣言してある.一方ベクトルの四則演算はVectorクラスの中で
// Unary -								
    const vector operator-(){
        vector v;
        for(int i=0;i<VLEN;i++) v.element[i] = -element[i];
             return v;
    }
//Binary operator	 +,-,*,/
    friend  const vector operator+(const  vector&, const vector&);
    friend  const vector operator-(const  vector&, const vector&);	
    friend  vector operator*(double, const vector&);
    friend  double operator*(const  vector&, const vector&);
    friend  vector operator*(const matrix&, const vector&);
    friend  vector operator*(const  vector&, double);
    friend  vector operator/(const  vector&, double);
		
// Binary operator +=, -=, *=, /=
   vector& operator+=(const vector& b){
       for(int i=0;i<VLEN;i++)element[i] += b.element[i];
           return *this;
       }
   vector& operator-=(const vector& b){
       for(int i=0;i<VLEN;i++)element[i] -= b.element[i];
           return *this;
       }
   vector& operator*=(double b){
       for(int i=0;i<VLEN;i++)element[i] *= b;
           return *this;
       }
   vector& operator/=(double  b){
       for(int i=0;i<VLEN;i++)element[i] /= b;
           return *this;
   }
と定義している.行列$ A$とベクトル$ b$の績のプロトタイプ宣言は
    friend double operator*(const matrix& A, const vector& b);
である,これにより,ベクトルの内績と行列の績に同じシンボル''*''が使え,ま たベクトルと行列の積も A*b と表現できる.

勿論演算子の多重定義を用いることはいいことばかりでなく,一時オブジェクト の生成と消滅にコストが掛かり,効率を損ねる.今回は処理能力はそれほど要求されな いと考え,一時オブジェクトは問題にならないと判断した.


Kawabata Shigetoku
平成15年4月28日