Skip to content

Instantly share code, notes, and snippets.

@komasaru
Created July 29, 2020 02:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/4a9e5a866e08bf4927fccba7d2f6e827 to your computer and use it in GitHub Desktop.
Save komasaru/4a9e5a866e08bf4927fccba7d2f6e827 to your computer and use it in GitHub Desktop.
C++ source code to do LU-decomposition by inner-product form.
#include "file.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
bool File::get_text(std::vector<std::vector<double>>& data) {
try {
// ファイル OPEN
std::ifstream ifs(f_data);
if (!ifs.is_open()) return false; // 読み込み失敗
// ファイル READ
std::string buf; // 1行分バッファ
while (getline(ifs, buf)) {
std::vector<double> rec; // 1行分ベクタ
std::istringstream iss(buf); // 文字列ストリーム
std::string field; // 1列分文字列
// 1行分文字列を1行分ベクタに追加
double s;
while (iss >> s)
rec.push_back(s);
// 1行分ベクタを data ベクタに追加
if (rec.size() != 0) data.push_back(rec);
}
} catch (...) {
std::cerr << "EXCEPTION!" << std::endl;
return false;
}
return true; // 読み込み成功
}
#ifndef REGRESSION_LINE_FILE_HPP_
#define REGRESSION_LINE_FILE_HPP_
#include <fstream>
#include <string>
#include <vector>
class File {
std::string f_data;
public:
File(std::string f_data) : f_data(f_data) {}
bool get_text(std::vector<std::vector<double>>&);
};
#endif
#include "lu_decomposition.hpp"
#include <iostream>
#include <sstream>
#include <vector>
/**
* @brief 行列サイズ取得
*
* @return 行列サイズ(unsigned int)
*/
unsigned int LuDecomposition::get_size() {
return data.size();
}
/**
* @brief LU 分解(内積形式ガウス法(inner-product form))
* (L の対角要素を 1 とする)
*
* @param[ref] m x m 行列(配列) mtx (double)
* @return 真偽(bool)
* @retval true 成功
* @retval false 失敗
*/
bool LuDecomposition::lu_decompose_inner_product(
std::vector<std::vector<double>>& mtx
) {
std::size_t i; // loop インデックス
std::size_t j; // loop インデックス
std::size_t k; // loop インデックス
std::size_t m; // 行列サイズ
double tmp; // 一時退避用
try {
m = get_size();
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
tmp = mtx[j][k];
for (i = j + 1; i < m; i++)
mtx[i][k] -= mtx[i][j] * tmp;
}
if (mtx[k][k] == 0) {
std::cout << "[ERROR] Can't divide by 0!" << std::endl;
return false; // 計算失敗
}
tmp = 1.0 / mtx[k][k];
for (i = k + 1; i < m; i++)
mtx[i][k] *= tmp;
}
} catch (...) {
return false; // 計算失敗
}
return true; // 計算成功
}
#ifndef REGRESSION_LINE_LU_DECOMPOSITION_HPP_
#define REGRESSION_LINE_LU_DECOMPOSITION_HPP_
#include <vector>
class LuDecomposition {
std::vector<std::vector<double>> data; // 元データ
public:
LuDecomposition(std::vector<std::vector<double>>& data) : data(data) {}
// コンストラクタ
unsigned int get_size(); // 行列サイズ取得
bool lu_decompose_inner_product(std::vector<std::vector<double>>&);
// LU 分解(内積形式ガウス法)
};
#endif
/***********************************************************
LU 分解
: 内積形式ガウス法(inner-product form)
DATE AUTHOR VERSION
2020.07.27 mk-mode.com 1.00 新規作成
Copyright(C) 2020 mk-mode.com All Rights Reserved.
***********************************************************/
#include "lu_decomposition.hpp"
#include "file.hpp"
#include <cstdlib> // for EXIT_XXXX
#include <iomanip> // for setprecision
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char* argv[]) {
std::string f_data; // データファイル名
std::vector<std::vector<double>> data; // データ配列
std::size_t i; // loop インデックス
std::size_t j; // loop インデックス
unsigned int m; // 行列サイズ
try {
// コマンドライン引数のチェック
if (argc != 2) {
std::cerr << "[ERROR] Number of arguments is wrong!\n"
<< "[USAGE] ./lu_decomposition_inner_product <file_name>"
<< std::endl;
return EXIT_FAILURE;
}
// ファイル名取得
f_data = argv[1];
// データ取得
File file(f_data);
if (!file.get_text(data)) {
std::cout << "[ERROR] Failed to read the file!" << std::endl;
return EXIT_FAILURE;
}
// 計算用オプジェクトのインスタンス化
LuDecomposition lu(data);
// 行列サイズ
m = lu.get_size();
// データ一覧出力
std::cout << "A = " << std::endl;
std::cout << std::fixed << std::setprecision(4);
for (i = 0; i < m; i++) {
for (j = 0; j < m; j++)
std::cout << std::setw(10) << std::right << data[i][j];
std::cout << std::endl;
}
// 計算
if (!lu.lu_decompose_inner_product(data)) {
std::cout << "[ERROR] Failed to decompose!" << std::endl;
return EXIT_FAILURE;
}
// 結果出力
std::cout << "LU = " << std::endl;
std::cout << std::fixed << std::setprecision(4);
for (i = 0; i < m; i++) {
for (j = 0; j < m; j++)
std::cout << std::setw(10) << std::right << data[i][j];
std::cout << std::endl;
}
} catch (...) {
std::cerr << "EXCEPTION!" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment