行列とベクトル・クラスのメンバー関数定義部は次のようになります。
// matrix18.cpp
// Matrixクラス  Vectorクラス メンバー関数定義部
#include "matrix18.h"
//クラス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と書けるようにする
}
// デフォルトコンストラクタ
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][k] * right.ptr[k][j];
            mat.ptr[i][j] = sum;
        }
    return *this = mat;
}
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;
    }
    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;
    }
    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;
        }
    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; //2つのベクトルは等しい
    else
        return true; //2つのベクトルは異なる
}
| 戻る |
Copyright(c) 1999 Yamada, K