行列とベクトル・クラスのメンバー関数定義部は次のようになります。
// 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