diff --git a/example/array_ex.cpp b/example/array_ex.cpp index 81fcda6..6e51ab6 100644 --- a/example/array_ex.cpp +++ b/example/array_ex.cpp @@ -36,7 +36,9 @@ int main(int argc, char const *argv[]) try array A(10, 0.0, 1.0); A.log2linear(2); A.show(); + A.linear2log(2); + A.for_each([](double &a, size_t i){ a += 1;}); A.show(); // copy A to a new array @@ -53,24 +55,10 @@ int main(int argc, char const *argv[]) try // create a new 2D array matrix C(5, 5, 1); - std::cout << "C = " << std::endl; - for (int i = 0; i < C.row_size(); i++) - { - for (int j = 0; j < C.col_size(); j++) - { - C[i][j] += i*10 + j; - std::cout << C.at(i,j) << " "; - } - std::cout << std::endl; - } + C.sequence(0, 1, 10); - // access row elements - std::cout << "C[3][:] = " << std::endl; - for (int i = 0; i < C.col_size(); i++) - { - std::cout << C.get(3)[i] << " "; - } - std::cout << std::endl; + std::cout << "C = \n"; + C.show(); // save array to a binary file save_matrix2binary("tmp/array_ex_out", C, "Int"); @@ -78,15 +66,9 @@ int main(int argc, char const *argv[]) try // import 2D array to a new object matrix D; read_binary2matrix("tmp/array_ex_out", D); - std::cout << "D = " << std::endl; - for (int i = 0; i < D.row_size(); i++) - { - for (int j = 0; j < D.col_size(); j++) - { - std::cout << D[i][j] << " "; - } - std::cout << std::endl; - } + + std::cout << "D = \n"; + D.show(); return 0; } catch(std::exception &e) diff --git a/lib/core/array.h b/lib/core/array.h index eabe025..ceb5998 100644 --- a/lib/core/array.h +++ b/lib/core/array.h @@ -488,7 +488,7 @@ namespace gctl * @brief element operate function pointer * */ - typedef void (*foreach_a_ptr)(ArrValType *ele_ptr, size_t id); + typedef void (*foreach_a_ptr)(ArrValType &ele_ptr, size_t id); /** * @brief Operate on each and every element @@ -1235,7 +1235,7 @@ namespace gctl { for (size_t i = 0; i < length_; i++) { - func(&val_[i], i); + func(val_[i], i); } return; } diff --git a/lib/core/matrix.h b/lib/core/matrix.h index e75c4d9..022af98 100644 --- a/lib/core/matrix.h +++ b/lib/core/matrix.h @@ -229,7 +229,17 @@ namespace gctl * @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and * 'RdUniform' for even distributed numbers. */ - void random(MatValType np1, MatValType np2, random_type_e mode = RdNormal, unsigned int seed = 0); + void random_float(MatValType np1, MatValType np2, random_type_e mode = RdNormal, unsigned int seed = 0); + + /** + * @brief Initialize the array with selected random types. + * + * @param[in] np1 Mean (Gauss) or low bound value (Even) + * @param[in] np2 Standard deviation (Gauss) or hig bound value (Even). + * @param[in] mode Random types. 'RdNormal' for Gaussian distributed numbers and + * 'RdUniform' for even distributed numbers. + */ + void random_int(MatValType np1, MatValType np2, unsigned int seed = 0); /** * @brief 对全体元素进行赋值 @@ -267,7 +277,7 @@ namespace gctl * @param row_inc Row increasement. * @param col_inc Column increasement. */ - void sequent(MatValType st_val, MatValType row_inc, MatValType col_inc); + void sequence(MatValType st_val, MatValType row_inc, MatValType col_inc); /** * @brief 获取索引位置元素值 @@ -389,7 +399,7 @@ namespace gctl * @brief element operate function pointer * */ - typedef void (*foreach_m_ptr)(MatValType *ele_ptr, size_t r_id, size_t c_id); + typedef void (*foreach_m_ptr)(MatValType &ele_ptr, size_t r_id, size_t c_id); /** * @brief Operate on each and every element @@ -508,7 +518,7 @@ namespace gctl { if (row_len == 0 || col_len == 0) { - throw std::invalid_argument("Invalid matrix size. gctl::matrix::resize(...)"); + throw std::invalid_argument("[gctl::matrix::resize] Invalid matrix size."); } // nothing needs to be done @@ -572,7 +582,7 @@ namespace gctl { if (init_mat == nullptr) { - throw std::domain_error("Invalid pointer. gctl::matrix::resize(...)"); + throw std::domain_error("[gctl::matrix::resize] Invalid pointer."); } resize(row_len, col_len); @@ -592,7 +602,7 @@ namespace gctl { if (init_mat == nullptr) { - throw std::domain_error("Invalid pointer. gctl::matrix::resize(...)"); + throw std::domain_error("[gctl::matrix::resize] Invalid pointer."); } resize(row_len, col_len); @@ -631,19 +641,16 @@ namespace gctl { if (!b.empty()) { - size_t col_s = b[0].size(); - for (size_t i = 1; i < b.size(); i++) + size_t max_col = 0; + for (size_t i = 0; i < b.size(); i++) { - if (col_s != b[i].size()) - { - throw std::runtime_error("The input 2-D vector is not neatly arranged. From matrix::resize(...)"); - } + max_col = std::max(max_col, b[i].size()); } - resize(b.size(), col_s); + resize(b.size(), max_col, 0); for (size_t i = 0; i < row_length; i++) { - for (size_t j = 0; j < col_length; j++) + for (size_t j = 0; j < b[i].size(); j++) { val[i][j] = b[i][j]; } @@ -660,7 +667,7 @@ namespace gctl { if (b.size() != row_len*col_len) { - throw std::runtime_error("Invalid initializing parameters. From matrix::resize(...)"); + throw std::runtime_error("[gctl::matrix::resize] Invalid matrix parameters."); } resize(row_len, col_len); @@ -711,12 +718,10 @@ namespace gctl } template - void matrix::random(MatValType np1, MatValType np2, random_type_e mode, unsigned int seed) + void matrix::random_float(MatValType np1, MatValType np2, random_type_e mode, unsigned int seed) { - if (empty()) - { - throw gctl::runtime_error("The matrix is not initialized. From gctl::matrix::random(...)"); - } + static_assert(std::is_floating_point::value, + "gctl::matrix::random_float(...) could only be used with a float point type."); if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator(seed); @@ -747,6 +752,27 @@ namespace gctl return; } + template + void matrix::random_int(MatValType np1, MatValType np2, unsigned int seed) + { + static_assert(std::is_integral::value, + "gctl::matrix::random_int(...) could only be used with an integral type."); + + if (seed == 0) seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine generator(seed); + + //添加均匀分布的随机值 + std::uniform_int_distribution dist(np1, np2); + for (size_t i = 0; i < row_length; i++) + { + for (size_t j = 0; j < col_length; j++) + { + val[i][j] = dist(generator); + } + } + return; + } + template void matrix::assign_all(MatValType in_val) { @@ -860,7 +886,7 @@ namespace gctl } template - void matrix::sequent(MatValType st_val, MatValType row_inc, MatValType col_inc) + void matrix::sequence(MatValType st_val, MatValType row_inc, MatValType col_inc) { for (size_t i = 0; i < row_length; i++) { @@ -877,7 +903,7 @@ namespace gctl { #ifdef GCTL_BOUND_CHECK if (row_index >= row_length || col_index >= col_length) - throw std::out_of_range("Invalid index. gctl::matrix::get(...)"); + throw std::out_of_range("[gctl::matrix::get] Invalid index."); #endif // GCTL_BOUND_CHECK return val[row_index]; @@ -888,7 +914,7 @@ namespace gctl { #ifdef GCTL_BOUND_CHECK if (row_index >= row_length || col_index >= col_length) - throw std::out_of_range("Invalid index. gctl::matrix::at(...)"); + throw std::out_of_range("[gctl::matrix::at] Invalid index."); #endif // GCTL_BOUND_CHECK return val[row_index][col_index]; @@ -899,7 +925,7 @@ namespace gctl { #ifdef GCTL_BOUND_CHECK if (row_index >= row_length || col_index >= col_length) - throw std::out_of_range("Invalid index. gctl::matrix::at(...)"); + throw std::out_of_range("[gctl::matrix::at] Invalid index."); #endif // GCTL_BOUND_CHECK return val[row_index][col_index]; @@ -992,7 +1018,7 @@ namespace gctl { if (index >= row_length) { - throw std::out_of_range("Invalid index. gctl::matrix::extract(...)"); + throw std::out_of_range("[gctl::matrix::extract] Invalid index."); } b.resize(col_length); @@ -1005,7 +1031,7 @@ namespace gctl if (index >= col_length) { - throw std::out_of_range("Invalid index. Thrown by gctl::matrix::extract(...)"); + throw std::out_of_range("[gctl::matrix::extract] Invalid index."); } b.resize(row_length); @@ -1050,7 +1076,7 @@ namespace gctl { for (size_t j = 0; j < col_length; j++) { - func(&val[i][j], i, j); + func(val[i][j], i, j); } } return; @@ -1061,9 +1087,10 @@ namespace gctl { for (size_t i = 0; i < row_length; i++) { - for (size_t j = 0; j < col_length; j++) + os << val[i][0]; + for (size_t j = 1; j < col_length; j++) { - os << val[i][j] << sep; + os << sep << val[i][j]; } os << std::endl; } diff --git a/lib/io/text_io.cpp b/lib/io/text_io.cpp index db27365..fd6d85a 100644 --- a/lib/io/text_io.cpp +++ b/lib/io/text_io.cpp @@ -34,9 +34,10 @@ gctl::text_descriptor::text_descriptor() set(); } -gctl::text_descriptor::text_descriptor(std::string filename, std::string file_exten, char att_sym, char tag_sym, char deli, int h_num) +gctl::text_descriptor::text_descriptor(std::string filename, std::string file_exten, + std::string col_order, char deli, char att_sym, char tag_sym, int h_num, int io_psn) { - set(filename, file_exten, att_sym, tag_sym, deli, h_num); + set(filename, file_exten, col_order, deli, att_sym, tag_sym, h_num, io_psn); } gctl::text_descriptor::~text_descriptor() @@ -44,26 +45,70 @@ gctl::text_descriptor::~text_descriptor() clear(); } -void gctl::text_descriptor::set(std::string filename, std::string file_exten, char att_sym, char tag_sym, char deli, int h_num) +void gctl::text_descriptor::set(std::string filename, std::string file_exten, + std::string col_order, char deli, char att_sym, char tag_sym, int h_num, int io_psn) { file_name_ = filename; file_ext_ = file_exten; + col_str_ = col_order; att_sym_ = att_sym; tag_sym_ = tag_sym; delimiter_ = deli; head_num_ = h_num; + float_psn_ = io_psn; return; } void gctl::text_descriptor::clear() { - set(); head_strs_.clear(); annotates_.clear(); tags_.clear(); return; } +void gctl::text_descriptor::set_float_precision(int psn) +{ + float_psn_ = psn; + return; +} + +void gctl::text_descriptor::set_head_number(int n) +{ + head_num_ = n; + return; +} + +void gctl::text_descriptor::set_annotation_symbol(char sym) +{ + att_sym_ = sym; + return; +} + +void gctl::text_descriptor::set_tag_symbol(char sym) +{ + tag_sym_ = sym; + return; +} + +void gctl::text_descriptor::set_column_delimeter(char sym) +{ + delimiter_ = sym; + return; +} + +void gctl::text_descriptor::set_file_extension(std::string ext_s) +{ + file_ext_ = ext_s; + return; +} + +void gctl::text_descriptor::set_column_order(std::string col_s) +{ + col_str_ = col_s; + return; +} + void gctl::read_text_lines(text_descriptor &file_desc, std::vector &out_vec, int start_line, int end_line) { if (start_line < 0 || start_line > end_line) @@ -276,7 +321,7 @@ void gctl::get_xyz_points(std::string filename, array &out_ps, text_de { // read file _2d_vector points_vec; - read_text2vector2d(filename, points_vec, desc, file_ext); + read_text2vector2d(desc, points_vec); get_xyz_points(points_vec, out_ps, order); destroy_vector(points_vec); return; @@ -287,7 +332,7 @@ void gctl::get_xyz_points(std::string filename, array &out_ps, text_de { // read file _2d_vector points_vec; - read_text2vector2d(filename, points_vec, desc, file_ext); + read_text2vector2d(desc, points_vec); get_xyz_points(points_vec, out_ps, order); destroy_vector(points_vec); return; @@ -339,7 +384,7 @@ void gctl::get_data_column(std::string filename, std::initializer_list head_strs_, annotates_, tags_; text_descriptor(); + ~text_descriptor(); /** * @brief Construct a new text descriptor object * * @param filename 文件名 * @param file_exten 文件扩展名 + * @param col_order 列数据索引字符串 * @param att_sym 注释行起始符 * @param tag_sym 标记行起始符 * @param deli 分割符 */ - text_descriptor(std::string filename, std::string file_exten = ".txt", char att_sym = '#', char tag_sym = '>', char deli = ' ', int h_num = 0); - - ~text_descriptor(); + text_descriptor(std::string filename, std::string file_exten = ".txt", + std::string col_order = "0,1,2", char deli = ' ', char att_sym = '#', + char tag_sym = '>', int h_num = 0, int io_psn = 6); /** * @brief 设置文件对象 @@ -71,9 +73,64 @@ namespace gctl * @param tag_sym 标记行起始符 * @param deli 分割符 */ - void set(std::string filename = "Untitled", std::string file_exten = ".txt", char att_sym = '#', char tag_sym = '>', char deli = ' ', int h_num = 0); + void set(std::string filename = "Untitled", std::string file_exten = ".txt", + std::string col_order = "0,1,2", char deli = ' ', char att_sym = '#', + char tag_sym = '>', int h_num = 0, int io_psn = 6); + /** + * @brief 清理向量 + * + */ void clear(); + + /** + * @brief 设置浮点输出精度 + * + * @param psn 有效数字位数 + */ + void set_float_precision(int psn); + + /** + * @brief 设置头信息行数 + * + * @param n 行数 + */ + void set_head_number(int n); + + /** + * @brief 设置注释行标识符 + * + * @param sym 标识符 + */ + void set_annotation_symbol(char sym); + + /** + * @brief 设置标志行标识符 + * + * @param sym 标识符 + */ + void set_tag_symbol(char sym); + + /** + * @brief 设置列分隔符 + * + * @param sym 标识符 + */ + void set_column_delimeter(char sym); + + /** + * @brief 设置文件扩展名 + * + * @param ext_s 扩展名 + */ + void set_file_extension(std::string ext_s); + + /** + * @brief 设置列索引列表 + * + * @param sym 标识符 + */ + void set_column_order(std::string col_s); }; /** @@ -81,42 +138,46 @@ namespace gctl * * @note 文件中的每一行为向量中的一个元素,对应的元素类型需支持>>操作符(一般通过操作符重载实现) * - * @param[in] filename 文件名 - * @param[in] file_ext 文件后缀名(默认包括txt dat xyz csv) + * @param desc 文件描述对象(包括了文件名,描述符等信息) * @param out_vec 返回的一维向量 - * @param[in] annotate 注释行的标记 - * @param[in] head_record 头信息行数 - * @param head_ptr 保存头信息的一维字符串向量的指针 * * @tparam T 模版向量类型 */ template - void read_text2vector(std::string filename, std::vector &out_vec, char annotate = '#', unsigned int head_record = 0, - std::vector *head_ptr = nullptr, std::string file_ext = ".txt,.dat,.xyz,.csv") + void read_text2vector(text_descriptor &desc, std::vector &out_vec) { - std::string tmp_line; - std::stringstream tmp_ss; - std::ifstream infile; - open_matched_infile(infile, filename, file_ext); + open_infile(infile, desc.file_name_, desc.file_ext_); // clear cleanup old table - if (!out_vec.empty()) destroy_vector(out_vec); - if (head_ptr != nullptr && !head_ptr->empty()) destroy_vector(*head_ptr); + out_vec.clear(); + desc.clear(); - if (head_record > 0) + std::string tmp_line; + std::stringstream tmp_ss; + for (int i = 0; i < desc.head_num_; i++) { - for (int i = 0; i < head_record; i++) - { - getline(infile, tmp_line); - if (head_ptr != nullptr) head_ptr->push_back(tmp_line); - } + getline(infile, tmp_line); + desc.head_strs_.push_back(tmp_line); } T tmp_d; while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } else { tmp_ss.clear(); @@ -124,7 +185,7 @@ namespace gctl tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the element: "+tmp_line+". From read_text2vector(...)"); + throw gctl::runtime_error("[gctl::read_text2vector] Fail to parse the line: " + tmp_line); } out_vec.push_back(tmp_d); @@ -134,80 +195,83 @@ namespace gctl infile.close(); return; } - + + /** + * @brief 从文本文件读入行到一维数组 + * + * @note 文件中的每一行为向量中的一个元素,对应的元素类型需支持>>操作符(一般通过操作符重载实现) + * + * @param desc 文件描述对象(包括了文件名,描述符等信息) + * @param out_vec 返回的一维向量 + * + * @tparam T 模版向量类型 + */ template - void read_text2array(std::string filename, array &out_arr, char annotate = '#', unsigned int head_record = 0, - array *head_ptr = nullptr, std::string file_ext = ".txt,.dat,.xyz,.csv") + void read_text2array(text_descriptor &desc, array &out_arr) { - std::string tmp_line; - std::stringstream tmp_ss; - std::ifstream infile; - open_matched_infile(infile, filename, file_ext); + open_infile(infile, desc.file_name_, desc.file_ext_); // clear cleanup old table - if (!out_arr.empty()) out_arr.clear(); - if (head_ptr != nullptr && !head_ptr->empty()) head_ptr->clear(); - if (head_ptr != nullptr && head_record > 0) head_ptr->resize(head_record); + out_arr.clear(); + desc.clear(); - int line_count = 0, annotate_count = 0; + std::string tmp_line; + std::stringstream tmp_ss; + for (int i = 0; i < desc.head_num_; i++) + { + getline(infile, tmp_line); + desc.head_strs_.push_back(tmp_line); + } + + size_t l_count = 0; while (std::getline(infile, tmp_line)) { - line_count++; - if (tmp_line[0] == annotate) annotate_count++; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } + else l_count++; } // reset the file pointer infile.clear(); infile.seekg(0); - if (line_count == 0) + for (int i = 0; i < desc.head_num_; i++) { - throw length_error("File: " + filename + " is empty. From read_text2array(...)"); + getline(infile, tmp_line); } - int arr_size = line_count - annotate_count - head_record; - - if (arr_size <= 0) - { - throw length_error("No valid entrance in the file: " + filename + " From read_text2array(...)"); - } - - out_arr.resize(arr_size); - - int count = 0; - if (head_record > 0) - { - while (count < head_record) - { - std::getline(infile, tmp_line); - if (tmp_line[0] == annotate) continue; - else - { - if (head_ptr != nullptr) head_ptr->at(count) = tmp_line; - count++; - } - } - } - + out_arr.resize(l_count); + l_count = 0; T tmp_d; - count = 0; while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; - else + if (tmp_line[0] != desc.att_sym_ && + tmp_line[0] != desc.tag_sym_) { tmp_ss.clear(); tmp_ss.str(tmp_line); tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the element: "+tmp_line+". From read_text2array(...)"); + throw gctl::runtime_error("[gctl::read_text2vector] Fail to parse the line: " + tmp_line); } - out_arr[count] = tmp_d; - count++; + out_arr[l_count] = tmp_d; + l_count++; } - } + } infile.close(); return; @@ -218,49 +282,37 @@ namespace gctl * * @note 向量中的每个元素保存为一行,对应的元素类型需支持<<操作符(一般通过操作符重载实现) * - * @param[in] filename 保存文件名 - * @param[in] file_ext 保存文件的后缀 + * @param[in] desc 文件描述对象(包括了文件名,描述符等信息) * @param[in] in_vec 待输出的向量 - * @param[in] annotate 注释行的标记 - * @param[in] head_info 头信息向量的指针 - * @param[in] precision 设置输出的数据精度,此值为正时将在<<操作符后附加setprecision(precision)代码段 * * @tparam T 模版向量类型 */ template - void save_vector2text(std::string filename, const std::vector &in_vec, char annotate = '#', - std::vector *head_ptr = nullptr, int precision = -1, std::string file_ext = ".txt,.dat,.xyz,.csv") + void save_vector2text(const text_descriptor &desc, const std::vector &in_vec) { std::ofstream outfile; - open_matched_outfile(outfile, filename, file_ext); + open_outfile(outfile, desc.file_name_, desc.file_ext_); - if (in_vec.empty()) + for (int i = 0; i < desc.head_strs_.size(); i++) { - GCTL_ShowWhatError("The input vector is empty. From save_vector2text(...)", GCTL_WARNING_ERROR, 0, 0, 0); + outfile << desc.head_strs_[i] << std::endl; } - if (head_ptr != nullptr) + for (int i = 0; i < desc.tags_.size(); i++) { - for (int i = 0; i < head_ptr->size(); ++i) - { - outfile << annotate << " " << head_ptr->at(i) << std::endl; - } + outfile << "> " << desc.tags_[i] << std::endl; } - if (precision > 0) + for (int i = 0; i < desc.annotates_.size(); i++) { - for (int i = 0; i < in_vec.size(); i++) - { - outfile << std::setprecision(precision) << in_vec[i] << std::endl; - } - outfile.close(); - return; + outfile << "# " << desc.annotates_[i] << std::endl; } for (int i = 0; i < in_vec.size(); i++) { - outfile << in_vec[i] << std::endl; + outfile << std::setprecision(desc.float_psn_) << in_vec[i] << std::endl; } + outfile.close(); return; } @@ -268,57 +320,48 @@ namespace gctl /** * @brief 保存一维数组到文本文件 * - * @note 数组的每个元素保存为一行,对应的元素类型需支持<<操作符(一般通过操作符重载实现) + * @note 向量中的每个元素保存为一行,对应的元素类型需支持<<操作符(一般通过操作符重载实现) * - * @param[in] filename 保存文件名 - * @param[in] file_ext 保存文件的后缀 + * @param[in] desc 文件描述对象(包括了文件名,描述符等信息) * @param[in] in_arr 待输出的向量 - * @param[in] annotate 注释行的标记 - * @param[in] head_info 头信息向量的指针 - * @param[in] precision 设置输出的数据精度,此值为正时将在<<操作符后附加setprecision(precision)代码段 * * @tparam T 模版向量类型 */ template - void save_array2text(std::string filename, const array &in_arr, const text_descriptor &desc, - int precision = -1, std::string file_ext = ".txt,.dat,.xyz,.csv") + void save_array2text(const text_descriptor &desc, const array &in_arr) { std::ofstream outfile; - open_matched_outfile(outfile, filename, file_ext); + open_outfile(outfile, desc.file_name_, desc.file_ext_); - if (in_arr.empty()) + for (int i = 0; i < desc.head_strs_.size(); i++) { - GCTL_ShowWhatError("The input array is empty. From save_vector2text(...)", GCTL_WARNING_ERROR, 0, 0, 0); + outfile << desc.head_strs_[i] << std::endl; } - for (int i = 0; i < desc.annotates_.size(); ++i) + for (int i = 0; i < desc.tags_.size(); i++) { - outfile << desc.annotates_[i] << std::endl; + outfile << "> " << desc.tags_[i] << std::endl; } - if (precision > 0) + for (int i = 0; i < desc.annotates_.size(); i++) { - for (int i = 0; i < in_arr.size(); i++) - { - outfile << std::fixed << std::setprecision(precision) << in_arr[i] << std::endl; - } - outfile.close(); - return; + outfile << "# " << desc.annotates_[i] << std::endl; } for (int i = 0; i < in_arr.size(); i++) { - outfile << in_arr[i] << std::endl; + outfile << std::setprecision(desc.float_psn_) << in_arr[i] << std::endl; } + outfile.close(); return; } template - void read_text2vector2d(std::string filename, std::vector> &out_vec2d, text_descriptor &desc, std::string file_ext = ".txt,.dat,.xyz,.csv,.tab") + void read_text2vector2d(text_descriptor &desc, std::vector> &out_vec2d) { std::ifstream infile; - open_matched_infile(infile, filename, file_ext); + open_infile(infile, desc.file_name_, desc.file_ext_); // clear old table if (!out_vec2d.empty()) destroy_vector(out_vec2d); @@ -339,10 +382,16 @@ namespace gctl { if (tmp_line[0] == desc.att_sym_) { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); desc.annotates_.push_back(tmp_line); } else if (tmp_line[0] == desc.tag_sym_) { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); desc.tags_.push_back(tmp_line); } else @@ -358,66 +407,35 @@ namespace gctl } template - void save_vector2d2text(std::string filename, const std::vector> &out_vec2d, - char delimiter = ' ', char annotate = '#', std::vector *head_ptr = nullptr, - matrix_order_e order_type = RowMajor, int precision = -1, std::string file_ext = ".txt,.dat,.xyz,.csv") + void save_vector2d2text(const text_descriptor &desc, const std::vector> &out_vec2d, + matrix_order_e order_type = RowMajor) { std::ofstream outfile; - open_matched_outfile(outfile, filename, file_ext); + open_outfile(outfile, desc.file_name_, desc.file_ext_); - if (out_vec2d.empty()) + for (int i = 0; i < desc.head_strs_.size(); i++) { - GCTL_ShowWhatError("The input vector is empty. From save_vector2d2text(...)", GCTL_WARNING_ERROR, 0, 0, 0); + outfile << desc.head_strs_[i] << std::endl; } - if (head_ptr != nullptr) + for (int i = 0; i < desc.tags_.size(); i++) { - for (int i = 0; i < head_ptr->size(); i++) - { - outfile << annotate << " " << head_ptr->at(i) << std::endl; - } + outfile << "> " << desc.tags_[i] << std::endl; + } + + for (int i = 0; i < desc.annotates_.size(); i++) + { + outfile << "# " << desc.annotates_[i] << std::endl; } if (order_type == RowMajor) { - if (precision > 0) - { - for (int i = 0; i < out_vec2d.size(); i++) - { - outfile << std::setprecision(precision) << out_vec2d[i][0]; - for (int j = 1; j < out_vec2d.at(i).size(); j++) - { - outfile << std::setprecision(precision) << delimiter << out_vec2d[i][j]; - } - outfile << std::endl; - } - - outfile.close(); - return; - } - for (int i = 0; i < out_vec2d.size(); i++) { - outfile << out_vec2d[i][0]; + outfile << std::setprecision(desc.float_psn_) << out_vec2d[i][0]; for (int j = 1; j < out_vec2d.at(i).size(); j++) { - outfile << delimiter << out_vec2d[i][j]; - } - outfile << std::endl; - } - - outfile.close(); - return; - } - - if (precision > 0) - { - for (int i = 0; i < out_vec2d[0].size(); i++) - { - outfile << std::setprecision(precision) << out_vec2d[0][i]; - for (int j = 1; j < out_vec2d.size(); j++) - { - outfile << std::setprecision(precision) << delimiter << out_vec2d[j][i]; + outfile << std::setprecision(desc.float_psn_) << desc.delimiter_ << out_vec2d[i][j]; } outfile << std::endl; } @@ -428,10 +446,10 @@ namespace gctl for (int i = 0; i < out_vec2d[0].size(); i++) { - outfile << out_vec2d[0][i]; + outfile << std::setprecision(desc.float_psn_) << out_vec2d[0][i]; for (int j = 1; j < out_vec2d.size(); j++) { - outfile << delimiter << out_vec2d[j][i]; + outfile << std::setprecision(desc.float_psn_) << desc.delimiter_ << out_vec2d[j][i]; } outfile << std::endl; } @@ -441,66 +459,35 @@ namespace gctl } template - void save_matrix2text(std::string filename, const matrix &out_arr2d, - char delimiter = ' ', char annotate = '#', std::vector *head_ptr = nullptr, - matrix_order_e order_type = RowMajor, int precision = -1, std::string file_ext = ".txt,.dat,.xyz,.csv") + void save_matrix2text(const text_descriptor &desc, const matrix &out_arr2d, + matrix_order_e order_type = RowMajor) { std::ofstream outfile; - open_matched_outfile(outfile, filename, file_ext); + open_outfile(outfile, desc.file_name_, desc.file_ext_); - if (out_arr2d.empty()) + for (int i = 0; i < desc.head_strs_.size(); i++) { - GCTL_ShowWhatError("The input array is empty. From save_matrix2text(...)", GCTL_WARNING_ERROR, 0, 0, 0); + outfile << desc.head_strs_[i] << std::endl; } - if (head_ptr != nullptr) + for (int i = 0; i < desc.tags_.size(); i++) { - for (int i = 0; i < head_ptr->size(); i++) - { - outfile << annotate << " " << head_ptr->at(i) << std::endl; - } + outfile << "> " << desc.tags_[i] << std::endl; + } + + for (int i = 0; i < desc.annotates_.size(); i++) + { + outfile << "# " << desc.annotates_[i] << std::endl; } if (order_type == RowMajor) { - if (precision > 0) - { - for (int i = 0; i < out_arr2d.row_size(); i++) - { - outfile << std::setprecision(precision) << out_arr2d[i][0]; - for (int j = 1; j < out_arr2d.col_size(); j++) - { - outfile << std::setprecision(precision) << delimiter << out_arr2d.at(i, j); - } - outfile << std::endl; - } - - outfile.close(); - return; - } - for (int i = 0; i < out_arr2d.row_size(); i++) { - outfile << out_arr2d[i][0]; + outfile << std::setprecision(desc.float_psn_) << out_arr2d[i][0]; for (int j = 1; j < out_arr2d.col_size(); j++) { - outfile << delimiter << out_arr2d.at(i, j); - } - outfile << std::endl; - } - - outfile.close(); - return; - } - - if (precision > 0) - { - for (int i = 0; i < out_arr2d.col_size(); i++) - { - outfile << std::setprecision(precision) << out_arr2d[0][i]; - for (int j = 1; j < out_arr2d.row_size(); j++) - { - outfile << std::setprecision(precision) << delimiter << out_arr2d.at(j, i); + outfile << std::setprecision(desc.float_psn_) << desc.delimiter_ << out_arr2d[i][j]; } outfile << std::endl; } @@ -511,10 +498,10 @@ namespace gctl for (int i = 0; i < out_arr2d.col_size(); i++) { - outfile << out_arr2d[0][i]; + outfile << std::setprecision(desc.float_psn_) << out_arr2d[0][i]; for (int j = 1; j < out_arr2d.row_size(); j++) { - outfile << delimiter << out_arr2d.at(j, i); + outfile << std::setprecision(desc.float_psn_) << desc.delimiter_ << out_arr2d[j][i]; } outfile << std::endl; } @@ -524,20 +511,19 @@ namespace gctl } template - void read_text2vectors(std::string filename, std::string order_str, - char delimiter, char annotate, int head_record, std::vector &out_vec) + void read_text2vectors(text_descriptor &desc, std::vector &out_vec) { std::string tmp_line, tmp_str, tmp_str2; std::stringstream tmp_ss; std::ifstream infile; - open_infile(infile, filename); + open_infile(infile, desc.file_name_, desc.file_ext_); // clear cleanup old table if (!out_vec.empty()) destroy_vector(out_vec); tmp_ss.clear(); - tmp_ss.str(order_str); // get the first index separated by comma + tmp_ss.str(desc.col_str_); // get the first index separated by comma std::getline(tmp_ss, tmp_str, ','); // get input column index int col_id; @@ -547,27 +533,38 @@ namespace gctl if (col_id < 0) { - throw runtime_error("Invalid column index. From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Invalid column index."); } - if (head_record > 0) + for (int i = 0; i < desc.head_num_; i++) { - for (int i = 0; i < head_record; i++) - { - getline(infile, tmp_line); - } + getline(infile, tmp_line); + desc.head_strs_.push_back(tmp_line); } T tmp_d; - if (delimiter != ' ') + if (desc.delimiter_ != ' ') { while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } else { // replace all delimiters to spaces - tmp_str2 = delimiter; + tmp_str2 = desc.delimiter_; replace_all(tmp_str, tmp_line, tmp_str2, " "); tmp_ss.clear(); tmp_ss.str(tmp_str); @@ -581,7 +578,7 @@ namespace gctl tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the line: "+tmp_line+". From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Fail to parse the line: " + tmp_line); } out_vec.push_back(tmp_d); @@ -592,7 +589,20 @@ namespace gctl { while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } else { tmp_ss.clear(); @@ -607,7 +617,7 @@ namespace gctl tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the line: "+tmp_line+". From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Fail to parse the line: " + tmp_line); } out_vec.push_back(tmp_d); @@ -620,20 +630,19 @@ namespace gctl } template - void read_text2vectors(std::string filename, std::string order_str, char delimiter, - char annotate, int head_record, std::vector &out_vec, std::vector&... rest) + void read_text2vectors(text_descriptor &desc, std::vector &out_vec, std::vector&... rest) { std::string tmp_line, tmp_str, tmp_str2; std::stringstream tmp_ss; std::ifstream infile; - open_infile(infile, filename); + open_infile(infile, desc.file_name_, desc.file_ext_); // clear cleanup old table if (!out_vec.empty()) destroy_vector(out_vec); tmp_ss.clear(); - tmp_ss.str(order_str); // get the first index separated by comma + tmp_ss.str(desc.col_str_); // get the first index separated by comma std::getline(tmp_ss, tmp_str, ','); // get input column index int col_id; @@ -643,30 +652,42 @@ namespace gctl if (col_id < 0) { - throw runtime_error("Invalid column index. From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Invalid column index."); } - int position = order_str.find_first_of(','); - std::string tmp_order = order_str.substr(position+1, order_str.length()); + int position = desc.col_str_.find_first_of(','); + std::string tmp_order = desc.col_str_.substr(position+1, desc.col_str_.length()); + desc.set_column_order(tmp_order); - if (head_record > 0) + for (int i = 0; i < desc.head_num_; i++) { - for (int i = 0; i < head_record; i++) - { - getline(infile, tmp_line); - } + getline(infile, tmp_line); + desc.head_strs_.push_back(tmp_line); } T tmp_d; - if (delimiter != ' ') + if (desc.delimiter_ != ' ') { while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } else { // replace all delimiters to spaces - tmp_str2 = delimiter; + tmp_str2 = desc.delimiter_; replace_all(tmp_str, tmp_line, tmp_str2, " "); tmp_ss.clear(); tmp_ss.str(tmp_str); @@ -680,7 +701,7 @@ namespace gctl tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the line: "+tmp_line+". From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Fail to parse the line: " + tmp_line); } out_vec.push_back(tmp_d); @@ -691,7 +712,20 @@ namespace gctl { while (std::getline(infile, tmp_line)) { - if (tmp_line[0] == annotate) continue; + if (tmp_line[0] == desc.att_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.annotates_.push_back(tmp_line); + } + else if (tmp_line[0] == desc.tag_sym_) + { + tmp_line = tmp_line.substr(1); + tmp_line.erase(0, tmp_line.find_first_not_of(" \t")); + tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); + desc.tags_.push_back(tmp_line); + } else { tmp_ss.clear(); @@ -706,7 +740,7 @@ namespace gctl tmp_ss >> tmp_d; if (tmp_ss.fail()) { - throw runtime_error("Fail to parse the line: "+tmp_line+". From read_text2vectors(...)"); + throw runtime_error("[gctl::read_text2vectors] Fail to parse the line: " + tmp_line); } out_vec.push_back(tmp_d); @@ -715,7 +749,7 @@ namespace gctl } infile.close(); - read_text2vectors(filename, tmp_order, delimiter, annotate, head_record, rest...); + read_text2vectors(desc, rest...); return; } @@ -823,7 +857,7 @@ namespace gctl for (int i = 0; i < content_ptr->size(); i++) { tmp_str = content_ptr->at(i).substr(0, content_ptr->at(i).length()-1); - outfile << content_ptr->at(i) << std::endl; + outfile << tmp_str << std::endl; } destroy_vector(*content_ptr);