ベクトルと行列クラスの メンバー関数定義部

 行列とベクトル・クラスのメンバー関数定義部は次のようになります。

// matrix20.cpp
// Matrixクラス  Vectorクラス メンバー関数定義部
#include "matrix20.h"




// デフォルトコンストラクタ
Matrix::Matrix(int row, int col) : Row(row), Col(col)
{
    new_matrix(); // 行列の領域確保
}

// コピーコンストラクタ
Matrix::Matrix(const Matrix &init) : Row(init.Row), Col(init.Col)
{
    new_matrix(); // 行列の領域確保

    for(int i = 0; i < Row; i++)//要素を代入
        ptr[i] = init.ptr[i];
}

// デストラクタ
Matrix::~Matrix()
{
    del_matrix();
}

// 行列のサイズを設定する
void Matrix::setSize(int row, int col)
{
    del_matrix(); // 行列の領域解放
    Row = row;
    Col = col;
    new_matrix(); // 行列の領域確保
}

//多重定義された代入演算子
Matrix &Matrix::operator=(const Matrix &right)
{
    if(this != &right){  //自己代入をチェックする

        if( (Row != right.Row) || (Col != right.Col) ){
            cout << "エラー:不正な代入(サイズが異なる)" << endl;
            abort();
        }

        for(int i = 0; i < Row; i++) //行ベクトルを代入
            ptr[i] = right.ptr[i];
    }

    return *this; //  x = y = zと書けるようにする
}


// 行列の領域を確保する
void Matrix::new_matrix()
{
    if(Row == 0 || Col == 0){
        Row = 0;
        Col = 0;
        ptr = 0;
        return;
    }
    ptr = new Vector[Row]; //行ベクトルの設定
    if(ptr == 0){
        cout << "エラー:領域確保に失敗しました。\n";
        abort();
    }
    for(int i = 0; i < Row; i++)
        ptr[i].setSize(Col);
}

// 領域を開放する
void Matrix::del_matrix()
{
    delete [] ptr;	//行ベクトルを解放
}

// 多重定義された +=演算子
Matrix &Matrix::operator+=(const Matrix &right)
{
    if((Row != right.Row) || (Col != right.Col)){//サイズのチェック
        cout << "エラー:行列のサイズが一致しません\n";
        abort();
    }
    for (int i = 0; i < Row; i++)
        ptr[i] += right.ptr[i];

    return *this;
}

// 多重定義された -=演算子
Matrix &Matrix::operator-=(const Matrix &right)
{
    if((Row != right.Row) || (Col != right.Col)){//サイズのチェック
        cout << "エラー:行列のサイズが一致しません\n";
        abort();
    }
    for (int i = 0; i < Row; i++)
        ptr[i] -= right.ptr[i];

    return *this;
}

// 多重定義された*=演算子
Matrix &Matrix::operator*=(const Matrix &right)
{
    if((Col != right.Row) || ((Col != right.Col))){//サイズのチェック
        cout << "エラー:行列の型が一致しません\n";
        abort();
    }

    Matrix mat(Row, right.Col); //一時的なオブジェクトを作る
    for (int i = 0; i < Row; i++)
        for(int j = 0; j < right.Col; j++){
            double sum = 0.0;
            for(int k = 0; k < Col; k++)
                sum += ptr[i].ptr[k] * right.ptr[k].ptr[j];
            mat.ptr[i].ptr[j] = sum;
        }

    mat.cleanup();

    return *this = mat;
}

// 微少要素の消去
void Matrix::cleanup()
{
    int i,j;
    double max = 0.0;
    for(i = 0; i < Row; i++)
       for(j = 0; j < Col; j++)
           if(fabs(ptr[i].ptr[j]) > max ) max = fabs(ptr[i].ptr[j]);

    if( max > NEARLY_ZERO )
        for(i = 0; i < Row; i++)
            for(j = 0; j < Col; j++)
                if( fabs(ptr[i].ptr[j]) / max < ZERO_TOLERANCE )
                    ptr[i].ptr[j] = 0.0;
}

// 行の交換
void Matrix::swap(int i, int j)
{
    // 引数チェック
    if( ( i < 0  || i >= Row) || ( j < 0  || j >= Row) ){
        cout << "エラー:Matrix::swap()の引数範囲の逸脱\n";
        abort();
    }
    if(i == j ) return;

    // 行ベクトルの交換
    double *temp = ptr[i].ptr;
    ptr[i].ptr = ptr[j].ptr;
    ptr[j].ptr = temp;
}

istream& operator>>(istream& input, Matrix& a)
{
    cout << a.Row << " 行" << a.Col << " 列の行列要素の入力:" << endl;
    for(int i = 0; i < a.Row; i++){
        cout << (i+1) << "行";
        input >> a.ptr[i];
    }

    return input;
}

ostream& operator<<(ostream& output, const Matrix& a)
{
    output.setf(ios::scientific); // 科学表記法
    for(int i = 0; i < a.Row; i++)
        output << a.ptr[i];

    return output;
}

// 多重定義された+演算子
// 2つの行列の和を求め、値渡しで返す
const Matrix operator+(const Matrix &left, const Matrix &right)
{
    return Matrix(left) += right; // 演算子 += を使う
}

// 多重定義された−演算子
// 2つの行列の差を求め、値渡しで返す
const Matrix operator-(const Matrix &left, const Matrix &right)
{
    return Matrix(left) -= right; // 演算子 -= を使う
}

// 多重定義された*演算子
// 行列とベクトルの積を求め、値渡しで返す
const Vector operator*(const Matrix &a, const Vector &x)
{
    if(a.Col != x.Dim){//サイズのチェック
        cout << "エラー:行列とベクトルの型が一致しません\n";
        abort();
    }
    Vector y( a.Row );
    for(int i = 0; i < a.Row; i++){
        double sum = 0.0;
        for(int j = 0; j < a.Col; j++)
            sum += a.ptr[i].ptr[j] * x.ptr[j];
        y[i] = sum;
    }

    y.cleanup();

    return y;
}

// 多重定義された*演算子
// ベクトルと行列の積を求め、値渡しで返す
const Vector operator*(const Vector &x, const Matrix &a)
{
    if(x.Dim != a.Row){//サイズのチェック
        cout << "エラー:ベクトルと行列の型が一致しません\n";
        abort();
    }
    Vector y( a.Col );
    for(int i = 0; i < a.Col; i++){
        double sum = 0.0;
        for(int j = 0; j < a.Row; j++)
            sum +=  x.ptr[j] * a.ptr[j].ptr[i];
        y.ptr[i] = sum;
    }

    y.cleanup();

    return y;
}


// 多重定義された*演算子
// 2つの行列の積
const Matrix operator*(const Matrix &left, const Matrix &right)
{
    if(left.Col != right.Row){//サイズのチェック
        cout << "エラー:行列の型が一致しません\n";
        abort();
    }

    Matrix mat(left.Row, right.Col); //一時的なオブジェクトを作る
    for (int i = 0; i < left.Row; i++)
        for(int j = 0; j < right.Col; j++){
            double sum = 0.0;
            for(int k = 0; k < left.Col; k++)
                sum += left.ptr[i].ptr[k] * right.ptr[k].ptr[j];
            mat.ptr[i].ptr[j] = sum;
        }
    mat.cleanup();

    return mat;
}


//2つの行列が等しいかどうかをチェックし、
//等しいときはtrue,等しくないときは falseを返す
bool operator==(const Matrix &left, const Matrix &right)
{
    if(left.Row != right.Row || left.Col != right.Col) //サイズが違う
        return false;

    for(int i = 0; i < left.Row; i++)
        if( left.ptr[i] != right.ptr[i])
            return false; // 行列の内容が違う

    return true; // 2つの行列は等しい
}

//2つの行列が等しくないかどうかをチェックし、
//等しいときは0,等しくないときは1を返す
bool operator!=(const Matrix &left, const Matrix &right)
{
    if(left == right)
        return false; //等しい
    else
        return true; //異なる
}

// 微少要素の消去
void Vector::cleanup()
{
    int i;
    double max = 0.0;
    for(i = 0; i < Dim; i++)
        if(fabs(ptr[i]) > max ) max = fabs(ptr[i]);

    if( max > NEARLY_ZERO )
        for(i = 0; i < Dim; i++)
            if( fabs(ptr[i]) / max < ZERO_TOLERANCE )
                ptr[i] = 0.0;
}

//クラスVectorのデフォルトコンストラクタ
Vector::Vector(int dim) : Dim(dim)
{
    new_vector();// ベクトルの領域確保

    for(int i = 0; i < Dim; i++)
        ptr[i] = 0.0;
}

//クラスVectorのコピーコンストラクタ
Vector::Vector(const Vector &init) : Dim(init.Dim)
{
    new_vector();// ベクトルの領域確保

    for(int i = 0; i < Dim; i++)
        ptr[i] = init.ptr[i];	//ベクトル要素をコピーする
}

//クラスVectorのコンストラクタ(配列で初期化)
Vector::Vector(const double *vec, int dim) : Dim(dim)
{
    new_vector();// ベクトルの領域確保

    for(int i = 0; i < Dim; i++)
        ptr[i] = vec[i];
}

//クラスVectorのデストラクタ
Vector::~Vector()
{
    del_vector();
}

//ベクトルのサイズを再設定する
void Vector::setSize(int dim)
{
    del_vector();// ベクトルの領域解放
    Dim = dim;
    new_vector();// ベクトルの領域確保
    for(int i = 0; i < Dim; i++) ptr[i] = 0.0; //要素を0.0にする
}

//多重定義された代入演算子
Vector &Vector::operator=(const Vector &right)
{
    if(this != &right){ //自己代入をチェックする

        if(Dim != right.Dim){
            cout << "エラー:不正な代入(サイズが異なる)" << endl;
            abort();
        }

        for(int i = 0; i < Dim; i++)
            ptr[i] = right.ptr[i]; //ベクトルの要素をコピーする
    }

    return *this; //  x = y = zと書けるようにする
}


// ノルムの計算
double Vector::norm() const
{
    double a = 0.0;
    for(int i = 0; i < Dim; i++)
        a += ptr[i]*ptr[i];
    return sqrt( a );
}

// ベクトルを規格化(オブジェクト自身が規格化される)
const Vector &Vector::normalize()
{
    double a = norm();
    if(a < NEARLY_ZERO) return *this; // ノルムゼロのベクトル
    for(int i = 0; i < Dim; i++)
        ptr[i] /= a;

    return *this;
}


// 多重定義された*=演算子
Vector &Vector::operator*=(double c)
{
    for (int i = 0; i < Dim; i++) ptr[i] *= c;

    return *this;
}

// 多重定義された/=演算子
Vector &Vector::operator/=(double c)
{
    if(c < NEARLY_ZERO){
        cout << "エラー:ゼロ除算\n";
        abort();
    }
    for (int i = 0; i < Dim; i++) ptr[i] /= c;

    return *this;
}

// 多重定義された+=演算子
Vector &Vector::operator+=(const Vector &right)
{
    if(Dim != right.Dim){	//サイズのチェック
        cout << "エラー:ベクトルのサイズが一致しません\n";
        abort();
    }
    for (int i = 0; i < Dim; i++)
        ptr[i] += right.ptr[i];

    return *this;
}

// 多重定義された-=演算子
Vector &Vector::operator-=(const Vector &right)
{
    if(Dim != right.Dim){ //サイズのチェック
        cout << "エラー:ベクトルのサイズが一致しません\n";
        abort();
    }
    for (int i = 0; i < Dim; i++)
        ptr[i] -= right.ptr[i];

    return *this;
}

// 多重定義された+演算子
// 2つのベクトルの和を求め、値渡しで返す
const Vector operator+(const Vector &left, const Vector &right)
{
    return Vector(left) += right;// 演算子 += を使う
}

// 多重定義された−演算子
// 2つのベクトルの差を求め、値渡しで返す
const Vector operator-(const Vector &left, const Vector &right)
{
    return Vector(left) -= right;// 演算子 -= を使う
}

// 多重定義された*演算子
// ベクトルのスカラー倍 (実数×ベクトル)
const Vector operator*(double c, const Vector &right)
{
    return Vector(right) *= c;   // 演算子 *= を使う
}

// 多重定義された*演算子
// ベクトルのスカラー倍 (ベクトル×実数)
// 実数×ベクトル用の関数を使う
const Vector operator*(const Vector &left, double c)
{
    return Vector(left) *= c;   // 演算子 *= を使う
}

// 多重定義された/演算子
// ベクトルを実数で割り算する
const Vector operator/(const Vector &left, double c)
{
    return Vector(left) /= c;   // 演算子 /= を使う
}

//多重定義された演算子*を使った内積
double operator*(const Vector &left, const Vector &right)
{
    if(left.Dim != right.Dim){
        cout << "エラー:ベクトルの型が違います。\n";
        abort();
    }
    double a = 0.0;
    for(int i = 0; i < left.Dim; i++)
        a += left.ptr[i] * right.ptr[i];

    return a;
}

//2つのベクトルが等しいかどうかをチェックし、
//等しいときは true,等しくないときは falseを返す
bool operator==(const Vector &left, const Vector &right)
{
    if(left.Dim != right.Dim)
        return false;    //ベクトルのサイズが異なる

    for(int i = 0; i < left.Dim; i++)
        if( fabs( left.ptr[i] - right.ptr[i] ) > NEARLY_ZERO )
            return false;   //ベクトルの内容が異なる

    return true; //2つのベクトルは等しい
}

//2つのベクトルが等しくないかどうかをチェックし、
//等しいときは false,等しくないときは trueを返す
bool operator!=(const Vector &left, const Vector &right)
{
    if(left == right)
        return false; //2つのベクトルは等しい
    else
        return true; //2つのベクトルは異なる
}


// ベクトルの領域確保
void Vector::new_vector()
{
    if(Dim == 0){ // 次元数が0の場合ポインタをヌルにセット
        ptr = 0;
        return;
    }

    ptr = new double[Dim];//ベクトルのメモリー領域を確保する
    if(ptr == 0){
        cout << "エラー:メモリー領域が確保できませんでした\n";
        abort();
    }
}

// ベクトルの領域解放
void Vector::del_vector()
{
    delete [] ptr; //ベクトルのメモリー領域を開放する
}

//クラスVectorの多重定義されたストリーム挿入演算子
ostream &operator<<(ostream &output, const Vector &a)
{
    output.setf(ios::scientific); // 科学表記法
    for(int i = 0; i < a.Dim; i++){
        output << setw(15) << a.ptr[i];
        if( !( (i+1) % 5 ) ) output << endl;
    }
    if( a.Dim % 5 ) output << endl;

    return output; // cout << x << yと書けるようにする
}

//クラスVectorの多重定義されたストリーム抽出演算子
//ベクトルの全要素の値を入力する
istream &operator>>(istream &input, Vector &a)
{
    cout << "ベクトル(次元数 " << a.Dim
    << " )の要素をスペースで区切って入力してください:" << endl;

    for(int i = 0; i < a.Dim; i++)
        input >> a.ptr[i];

    return input; // cin >> x >> yと書けるようにする
}

| 戻る |

Copyright(c) 1999 Yamada, K