/** * \file utils.hpp * \brief Utilities header * * \author * Christos Choutouridis AEM:8997 * */ #ifndef UTILS_HPP_ #define UTILS_HPP_ #include #include #include #include #include #include /*! * A Logger for entire program. */ struct Log { struct Endl {} endl; //!< a tag object to to use it as a new line request. //! We provide logging via << operator template Log& operator<< (T&& t) { if (session.verbose) { if (line_) { std::cout << "[Log]: " << t; line_ = false; } else std::cout << t; } return *this; } // overload for special end line handling Log& operator<< (Endl e) { (void)e; if (session.verbose) { std::cout << '\n'; line_ = true; } return *this; } private: bool line_ {true}; }; extern Log logger; /*! * A small timing utility based on chrono. */ struct Timing{ using Tpoint = std::chrono::steady_clock::time_point; using microseconds = std::chrono::microseconds; using milliseconds = std::chrono::milliseconds; using seconds = std::chrono::seconds; //! tool to mark the starting point Tpoint start () noexcept { return start_ = std::chrono::steady_clock::now(); } //! tool to mark the ending point Tpoint stop () noexcept { return stop_ = std::chrono::steady_clock::now(); } auto dt () noexcept { return std::chrono::duration_cast(stop_ - start_).count(); } //! tool to print the time interval void print_dt (const char* what) noexcept { if (session.timing) { auto t = stop_ - start_; if (std::chrono::duration_cast(t).count() < 10000) std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [usec]\n"; else if (std::chrono::duration_cast(t).count() < 10000) std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [msec]\n"; else std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [sec]\n"; } } private: Tpoint start_; Tpoint stop_; }; struct Mtx { template static void load(const std::string& filename, const std::string& dataset, MatrixType& matrix) { hid_t file_id{}, dataset_id{}, dataspace_id{}; herr_t read_st; do { // Open file logger << "Load HDF5 file: " << filename << " Dataset: " << dataset << "..."; if ((file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) break; // Open dataset if ((dataset_id = H5Dopen2(file_id, dataset.c_str(), H5P_DEFAULT)) < 0) break; // Get dataspace and allocate memory for read buffer if ((dataspace_id = H5Dget_space(dataset_id)) < 0) break; hsize_t dims[2]; H5Sget_simple_extent_dims(dataspace_id, dims, NULL); matrix.resize(dims[0], dims[1]); // Read the dataset // ToDo: Come up with a better way to do this if constexpr (Type == HDF5_type::DOUBLE) { if ((read_st = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0) break; } else if (Type == HDF5_type::FLOAT) { if ((read_st = H5Dread(dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0) break; } else if (Type == HDF5_type::UINT) { if ((read_st = H5Dread(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0) break; } else if (Type == HDF5_type::INT) { if ((read_st = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0) break; } // Done H5Dclose(dataset_id); H5Sclose(dataspace_id); H5Fclose(file_id); logger << " Done" << logger.endl; return; } while (0); // Error: close everything (if possible) and return false H5Dclose(dataset_id); H5Sclose(dataspace_id); H5Fclose(file_id); throw std::runtime_error("Cannot store to " + filename + " dataset:" + dataset + '\n'); } template static void store(const std::string& filename, const std::string& dataset, MatrixType& matrix) { hid_t file_id{}, dataset_id{}, dataspace_id{}; herr_t write_st; do { // Try to open the file in read-write mode logger << "Store HDF5 file: " << filename << " Dataset: " << dataset << "..."; if (access(session.outMtxFile.c_str(), F_OK) == 0){ if ((file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT)) < 0) break; } else { if ((file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) break; } // Create the dataspace for the dataset hsize_t dims[] = { matrix.rows(), matrix.columns() }; if ((dataspace_id = H5Screate_simple(2, dims, NULL)) < 0) break; // ToDo: Come up with a better way to do this if constexpr (Type == HDF5_type::DOUBLE) { // Create the dataset with default properties if ((dataset_id = H5Dcreate2( file_id, dataset.c_str(), H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) break; // Write the data to the dataset if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 ) break; } else if (Type == HDF5_type::FLOAT) { // Create the dataset with default properties if ((dataset_id = H5Dcreate2( file_id, dataset.c_str(), H5T_NATIVE_FLOAT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) break; // Write the data to the dataset if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 ) break; } else if (Type == HDF5_type::UINT) { // Create the dataset with default properties if ((dataset_id = H5Dcreate2( file_id, dataset.c_str(), H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) break; // Write the data to the dataset if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 ) break; } else if (Type == HDF5_type::INT) { // Create the dataset with default properties if ((dataset_id = H5Dcreate2( file_id, dataset.c_str(), H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) break; // Write the data to the dataset if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 ) break; } // Close the dataset, dataspace, and file H5Dclose(dataset_id); H5Sclose(dataspace_id); H5Fclose(file_id); logger << " Done" << logger.endl; return; } while (0); // Error: close everything (if possible) and return false H5Dclose(dataset_id); H5Sclose(dataspace_id); H5Fclose(file_id); throw std::runtime_error("Cannot store " + filename + " with dataset:" + dataset +'\n'); } }; #endif /* UTILS_HPP_ */