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