From af2c80e437d3947dc16b772e8daac67b9653b417 Mon Sep 17 00:00:00 2001 From: Marcin Kirsz <mkirsz@ed.ac.uk> Date: Thu, 27 Feb 2025 17:23:53 +0000 Subject: [PATCH] WiP --- include/tadah/core/aed_type.h | 4 + include/tadah/core/aeds_type.h | 4 + include/tadah/core/config.h | 142 ++++++++++++++----- include/tadah/core/core_types.h | 4 + include/tadah/core/element.h | 7 +- include/tadah/core/fd_type.h | 4 + include/tadah/core/lapack.h | 4 + include/tadah/core/maths.h | 4 + include/tadah/core/normaliser_core.h | 5 + include/tadah/core/periodic_table.h | 4 + include/tadah/core/registry.h | 6 +- include/tadah/core/utils.h | 4 + include/tadah/core/vec3d.h | 5 + include/tadah/core/vec3d_math_inl.h | 4 + include/tadah/core/vec3d_soa_const_view.h | 5 + include/tadah/core/vec3d_soa_view.h | 4 + include/tadah/core/vec3d_soa_view_math_inl.h | 4 + include/tadah/core/vec3dview.h | 4 + include/tadah/core/vec3dview_math_inl.h | 4 + src/aed_type.cpp | 5 + src/aeds_type.cpp | 4 + src/config.cpp | 5 + src/element.cpp | 23 +-- src/fd_type.cpp | 4 + src/lapack.cpp | 6 + src/maths.cpp | 4 + src/normaliser_core.cpp | 5 + src/periodic_table.cpp | 5 + src/utils.cpp | 5 + 29 files changed, 245 insertions(+), 43 deletions(-) diff --git a/include/tadah/core/aed_type.h b/include/tadah/core/aed_type.h index 9b05b7a..9b74a71 100644 --- a/include/tadah/core/aed_type.h +++ b/include/tadah/core/aed_type.h @@ -9,6 +9,9 @@ #include <iostream> #include <chrono> +namespace tadah { +namespace core { + class aed_type { double *data_ = nullptr; size_t size_ = 0; @@ -276,5 +279,6 @@ inline std::ostream& operator<<(std::ostream& os, const aed_type& v) { // } // }; +}} #endif // AED_TYPE2_H diff --git a/include/tadah/core/aeds_type.h b/include/tadah/core/aeds_type.h index 37f5e99..ac22d3f 100644 --- a/include/tadah/core/aeds_type.h +++ b/include/tadah/core/aeds_type.h @@ -7,6 +7,9 @@ #include <cstring> #include <iostream> +namespace tadah { +namespace core { + class aeds_type2 { /* Column major order * @@ -69,4 +72,5 @@ public: friend std::ostream& operator<<(std::ostream& os, const aeds_type2& v); }; +}} #endif // AEDS_TYPE2_H diff --git a/include/tadah/core/config.h b/include/tadah/core/config.h index 25eacc6..778689b 100644 --- a/include/tadah/core/config.h +++ b/include/tadah/core/config.h @@ -17,6 +17,10 @@ CMRC_DECLARE(CORE); +namespace tadah { +namespace core { + + /** \brief A dictionary for key - value pairs. * * This dictionary object must be used in the workflow @@ -66,37 +70,111 @@ public: */ const std::vector<std::string>& operator()(const std::string key) const; - /** \brief Fill array with the values from the key. - * - * The array must be initialised to appropriate size. - * - * Usage example: - * - * \code{.cpp} - * # Create new config object and read config file - * Config config("config_file"); - * - * # Fill array with config values of type double - * std::vector<double> vd(10); - * c.get<std::vector<double>>("RCUT2B", vd); - * \endcode - * - * \tparam T indexable array - */ - template <typename T> - void get(const std::string key, T & value) const { - if (c.count(to_upper(key))==0) - throw std::runtime_error(knf+key); - int i=0; - try { - for (auto v : c.at(to_upper(key))) { - std::istringstream iss(v); - iss >> value[i++]; - } - } catch (...) { - throw std::runtime_error("Config: Failed getting reading/writing to an array "+key); + /** + * @brief A C++11-friendly type trait to detect if T has a .size() method. + * + * - Primary template: yields false if T does not have a .size() method. + * - Partial specialization: yields true if calling T::size() is valid. + */ + template<typename, typename = void> + struct has_size : std::false_type {}; + + // This partial specialization is chosen if (void)std::declval<U>().size() is valid. + template<typename U> + struct has_size<U, typename std::enable_if< + std::is_same< + decltype(std::declval<U>().size()), + decltype(std::declval<U>().size()) + >::value + >::type> : std::true_type {}; + + /** + * @brief Helper function that checks size at runtime (only if T has .size()). + * + * SFINAE: This overload is *only* compiled if T has a .size() method. + * + * @throw std::runtime_error if the container is too small. + */ + template<typename T> + typename std::enable_if<has_size<T>::value, void>::type + check_size_if_applicable(const T &arr, std::size_t required, const std::string &key) const + { + if (arr.size() < required) { + throw std::runtime_error("Config array too small for key: " + key); + } + } + + /** + * @brief Overload that does nothing if T *does not* have .size(). + * + * SFINAE: This is only compiled for types that have no .size() method. + */ + template<typename T> + typename std::enable_if<!has_size<T>::value, void>::type + check_size_if_applicable(const T&, std::size_t, const std::string&) const + { + // Do nothing: for types like raw pointers. + } + + /** + * @brief Fill an existing array-like type @p arr with config values under @p key. + * + * - If @p arr has .size(), a check verifies @p arr can hold all config values. + * - If @p arr does not have .size() (e.g., raw pointer), no check is performed. + * - If parsing fails or key is missing, a runtime error is thrown. + * + * ### Usage example + * \code{.cpp} + * // Assume a config with a key "MyKey" of 4 numeric values. + * Config cfg("config_file"); + * + * // 1) Use a container with .size(), e.g. std::vector<double>: + * std::vector<double> vec(5); // capacity 5 + * cfg.get("MyKey", vec); // Will check vec.size() >= 4 + * + * // 2) Use a raw pointer (no .size()): + * double arr[10]; + * cfg.get("MyKey", arr); // No size check performed. Caller must ensure arr is big enough. + * \endcode + * + * @tparam T container or pointer type that supports operator[]. + * @param key Name of the config key (case-insensitive). + * @param arr Destination where parsed values are stored. + * @throws std::runtime_error on key-not-found, array-too-small, or parse failure. + */ + template <typename T> + void get(const std::string &key, T &arr) const { + // Convert to uppercase for case-insensitive retrieval. + const auto upperKey = to_upper(key); + + // Check presence of the key in our config container. + const std::size_t numValues = c.count(upperKey); + if (numValues == 0) { + throw std::runtime_error(knf + key); + } + + // If T has .size(), do a runtime size check. If not, do nothing. + check_size_if_applicable(arr, numValues, key); + + try { + // For demonstration, assume c.at(...) returns a list of strings to be parsed. + const auto &values = c.at(upperKey); + for (std::size_t i = 0; i < values.size(); ++i) { + std::istringstream iss(values[i]); + iss >> arr[i]; // Works for both pointer indexing and container operator[] + if (iss.fail()) { + throw std::runtime_error( + "Config: Conversion failed for key: " + key + + " at value: '" + values[i] + "'" + ); + } + } + } catch (...) { + throw std::runtime_error( + "Config: Failed reading/writing to an array [" + key + "]" + ); + } } - } /** \brief Return the first value for the key. * @@ -316,6 +394,6 @@ private: const static std::string knf;//="Key not found: "; }; - - +} +} #endif diff --git a/include/tadah/core/core_types.h b/include/tadah/core/core_types.h index a98a2d2..25061f0 100644 --- a/include/tadah/core/core_types.h +++ b/include/tadah/core/core_types.h @@ -8,6 +8,9 @@ #include <vector> +namespace tadah { +namespace core { + typedef Vec3d force_type; typedef aed_type t_type; typedef aed_type rho_type; @@ -35,4 +38,5 @@ class mat { #endif ///////////////////////////////////////// +}} #endif diff --git a/include/tadah/core/element.h b/include/tadah/core/element.h index cc37c4e..f1e910e 100644 --- a/include/tadah/core/element.h +++ b/include/tadah/core/element.h @@ -5,6 +5,9 @@ #include <functional> #include <string> +namespace tadah { +namespace core { + struct Element { private: void check(const std::string &symbol, const int Z); @@ -29,9 +32,11 @@ struct Element { static int toAtomicNumber(const std::string &symbol); static std::string toSymbol(int Z); }; +}} + namespace std { template <> - struct hash<Element>; + struct hash<tadah::core::Element>; } #endif diff --git a/include/tadah/core/fd_type.h b/include/tadah/core/fd_type.h index 4b665d6..5211cf2 100644 --- a/include/tadah/core/fd_type.h +++ b/include/tadah/core/fd_type.h @@ -12,6 +12,9 @@ #include <cstring> #include <limits> +namespace tadah { +namespace core { + class fd_type { size_t rows_ = 0; double* data_ = nullptr; @@ -84,4 +87,5 @@ public: bool operator==(const fd_type& v1) const; }; +}} #endif // FD_TYPE_H diff --git a/include/tadah/core/lapack.h b/include/tadah/core/lapack.h index 3a92dea..99945b8 100644 --- a/include/tadah/core/lapack.h +++ b/include/tadah/core/lapack.h @@ -3,6 +3,9 @@ #include <tadah/core/maths.h> +namespace tadah { +namespace core { + extern "C" { /** @@ -213,4 +216,5 @@ double norm_X(Matrix &A, char norm='1'); aed_type solve_posv(Matrix &A, aed_type /*&*/T, char uplo='U'); double condition_number(Matrix &A, char uplo='U'); +}} #endif diff --git a/include/tadah/core/maths.h b/include/tadah/core/maths.h index eec93ed..b890c0a 100644 --- a/include/tadah/core/maths.h +++ b/include/tadah/core/maths.h @@ -17,6 +17,9 @@ #include <array> +namespace tadah { +namespace core { + template <typename D> class Matrix_Base { // column-major order @@ -440,4 +443,5 @@ public: typedef Matrix3d_T<> Matrix3d; +}} #endif diff --git a/include/tadah/core/normaliser_core.h b/include/tadah/core/normaliser_core.h index 621a26c..5232ab5 100644 --- a/include/tadah/core/normaliser_core.h +++ b/include/tadah/core/normaliser_core.h @@ -4,6 +4,9 @@ #include <tadah/core/config.h> #include <tadah/core/core_types.h> +namespace tadah { +namespace core { + // We do calculate and store st. dev. and mean // for the first column of Phi matrix // for linear kernel, first column are 1s @@ -26,4 +29,6 @@ class Normaliser_Core { void normalise(fd_type &fd); void normalise(fd_type &fd, size_t k); }; + +}} #endif diff --git a/include/tadah/core/periodic_table.h b/include/tadah/core/periodic_table.h index acc199b..672d386 100644 --- a/include/tadah/core/periodic_table.h +++ b/include/tadah/core/periodic_table.h @@ -5,6 +5,9 @@ #include <map> #include <tadah/core/element.h> +namespace tadah { +namespace core { + struct PeriodicTable { static std::map<std::string, Element> symbol; static std::map<std::string, Element> name; @@ -29,4 +32,5 @@ struct PeriodicTable { static void init_masses(); }; +}} #endif diff --git a/include/tadah/core/registry.h b/include/tadah/core/registry.h index a39e9d3..f0afb3c 100644 --- a/include/tadah/core/registry.h +++ b/include/tadah/core/registry.h @@ -8,10 +8,12 @@ #include <sstream> #include <iostream> +namespace tadah { +namespace core { + template<typename T, typename... Args> using Factory = std::function<T*(Args&...)>; -namespace CONFIG { template<typename Base, typename... Args> struct Registry { @@ -41,6 +43,6 @@ Base* factory(const std::string& type, Args&... args) { throw std::runtime_error(oss.str()); } -} +}} #endif diff --git a/include/tadah/core/utils.h b/include/tadah/core/utils.h index 2516067..213a363 100644 --- a/include/tadah/core/utils.h +++ b/include/tadah/core/utils.h @@ -12,6 +12,8 @@ #include <tuple> #include <cstddef> +namespace tadah { +namespace core { /** Vector printing to streams */ template <typename T> @@ -314,4 +316,6 @@ std::vector<histogram_bin> generate_2d_histogram( const std::vector<std::pair<double,double>>& data_2d, int x_bins, int y_bins); + +}} #endif diff --git a/include/tadah/core/vec3d.h b/include/tadah/core/vec3d.h index 0a7a0a7..2e38a4c 100644 --- a/include/tadah/core/vec3d.h +++ b/include/tadah/core/vec3d.h @@ -7,6 +7,9 @@ #include <string> #include <limits> +namespace tadah { +namespace core { + class Vec3d { public: double v[3] = { }; @@ -138,4 +141,6 @@ public: // We'll declare multiply by Matrix3d in separate file "vec3d_math_inl.h" }; + +}} #endif diff --git a/include/tadah/core/vec3d_math_inl.h b/include/tadah/core/vec3d_math_inl.h index b0e70c0..66a91ae 100644 --- a/include/tadah/core/vec3d_math_inl.h +++ b/include/tadah/core/vec3d_math_inl.h @@ -5,6 +5,9 @@ #include <tadah/core/vec3d.h> #include <tadah/core/maths.h> +namespace tadah { +namespace core { + /** * @brief Inline method: multiply in-place by a 3x3 matrix => x = M*x * @@ -24,5 +27,6 @@ inline Vec3d& transformBy(Vec3d &v, const Matrix3d &M) return v; } +}} #endif // VEC3D_MATH_INL_H diff --git a/include/tadah/core/vec3d_soa_const_view.h b/include/tadah/core/vec3d_soa_const_view.h index bb3fe2b..a55d1a6 100644 --- a/include/tadah/core/vec3d_soa_const_view.h +++ b/include/tadah/core/vec3d_soa_const_view.h @@ -8,6 +8,9 @@ #include <iostream> #include <tadah/core/vec3d.h> // for returning Vec3d in operations (e.g. cross, etc.) +namespace tadah { +namespace core { + /** * @class Vec3dSoAConstView * @brief A read-only "view" into SoA data for x,y,z. @@ -148,5 +151,7 @@ public: } }; +}} + #endif // VEC3D_SOA_CONST_VIEW_H diff --git a/include/tadah/core/vec3d_soa_view.h b/include/tadah/core/vec3d_soa_view.h index b8f530b..4c25f6b 100644 --- a/include/tadah/core/vec3d_soa_view.h +++ b/include/tadah/core/vec3d_soa_view.h @@ -8,6 +8,9 @@ #include <iostream> #include <tadah/core/vec3d.h> // so we can return Vec3d in operations (e.g. operator+, cross, etc.) +namespace tadah { +namespace core { + /** * @class Vec3dSoAView * @brief A non-owning "view" into SoA data for x,y,z. @@ -179,5 +182,6 @@ public: } }; +}} #endif // VEC3D_SOA_VIEW_H diff --git a/include/tadah/core/vec3d_soa_view_math_inl.h b/include/tadah/core/vec3d_soa_view_math_inl.h index f010117..7f1ced5 100644 --- a/include/tadah/core/vec3d_soa_view_math_inl.h +++ b/include/tadah/core/vec3d_soa_view_math_inl.h @@ -5,6 +5,9 @@ #include <tadah/core/vec3d_soa_view.h> #include <tadah/core/maths.h> +namespace tadah { +namespace core { + /** * @brief Inline function to multiply Vec3dSoAView by a 3x3 matrix in place: * x => M*x @@ -26,5 +29,6 @@ inline Vec3dSoAView& transformBy(Vec3dSoAView &view, const Matrix3d &M) return view; } +}} #endif // VEC3D_SOA_VIEW_MATH_INL_H diff --git a/include/tadah/core/vec3dview.h b/include/tadah/core/vec3dview.h index 50b2c54..fa057a8 100644 --- a/include/tadah/core/vec3dview.h +++ b/include/tadah/core/vec3dview.h @@ -8,6 +8,9 @@ #include <tadah/core/vec3d.h> // so we can return Vec3d from some operations +namespace tadah { +namespace core { + /** * @class Vec3dView * @brief A non-owning "view" of 3 doubles in memory, providing @@ -194,5 +197,6 @@ public: } }; +}} #endif // VEC3DVIEW_H diff --git a/include/tadah/core/vec3dview_math_inl.h b/include/tadah/core/vec3dview_math_inl.h index 4e5fe19..e817e29 100644 --- a/include/tadah/core/vec3dview_math_inl.h +++ b/include/tadah/core/vec3dview_math_inl.h @@ -5,6 +5,9 @@ #include <tadah/core/vec3dview.h> #include <tadah/core/maths.h> +namespace tadah { +namespace core { + /** * @brief Inline multiply: x = M*x for a pointer-based Vec3dView */ @@ -21,5 +24,6 @@ inline Vec3dView& transformBy(Vec3dView &v, const Matrix3d &M) return v; } +}} #endif // VEC3DVIEW_MATH_INL_H diff --git a/src/aed_type.cpp b/src/aed_type.cpp index 7bf86d7..fb843d0 100644 --- a/src/aed_type.cpp +++ b/src/aed_type.cpp @@ -1,5 +1,8 @@ #include <tadah/core/aed_type.h> +namespace tadah { +namespace core { + aed_type& aed_type::operator=(const aed_type& other) { if (this != &other) { if (allocated_) { @@ -89,3 +92,5 @@ void aed_type::random(int seed, double lower, double upper) { (*this)[i] = unif(engine); } } + +}} diff --git a/src/aeds_type.cpp b/src/aeds_type.cpp index 70b91c4..6ea8c6f 100644 --- a/src/aeds_type.cpp +++ b/src/aeds_type.cpp @@ -1,6 +1,9 @@ #include <tadah/core/aeds_type.h> #include <tadah/core/aed_type.h> +namespace tadah { +namespace core { + aeds_type2::aeds_type2() {} aeds_type2::aeds_type2(size_t dim, size_t natoms) @@ -115,4 +118,5 @@ std::ostream& operator<<(std::ostream& os, const aeds_type2& v) { } return os; } +}} diff --git a/src/config.cpp b/src/config.cpp index 345e741..560e1c7 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,6 +1,9 @@ #include <tadah/core/config.h> #include <sstream> +namespace tadah { +namespace core { + Config::Config() { read_tadah_configuration(); @@ -343,3 +346,5 @@ void Config::deserialize(const std::vector<char>& buffer) { } +} +} diff --git a/src/element.cpp b/src/element.cpp index 4742236..1c6e90d 100644 --- a/src/element.cpp +++ b/src/element.cpp @@ -1,6 +1,9 @@ #include <tadah/core/element.h> #include <tadah/core/periodic_table.h> +namespace tadah { +namespace core { + void Element::check(const std::string &symbol, const int Z) { if (symbol.size() > 2) throw std::runtime_error("Wrong symbol: "+symbol); @@ -34,18 +37,22 @@ bool Element::operator<(const Element& other) const { bool Element::operator>(const Element& other) const { return this->Z > other.Z; } +int Element::toAtomicNumber(const std::string &symbol) { + return PeriodicTable::find_by_symbol(symbol).Z; +} +std::string Element::toSymbol(int Z) { + return PeriodicTable::find_by_Z(Z).symbol; +} + +}} + namespace std { template <> - struct hash<Element> { - size_t operator()(const Element &e) const { + struct hash<tadah::core::Element> { + size_t operator()(const tadah::core::Element &e) const { return hash<int>()(e.Z); } }; } -int Element::toAtomicNumber(const std::string &symbol) { - return PeriodicTable::find_by_symbol(symbol).Z; -} -std::string Element::toSymbol(int Z) { - return PeriodicTable::find_by_Z(Z).symbol; -} + diff --git a/src/fd_type.cpp b/src/fd_type.cpp index 892ee88..a478261 100644 --- a/src/fd_type.cpp +++ b/src/fd_type.cpp @@ -1,6 +1,9 @@ #include <tadah/core/fd_type.h> #include <tadah/core/aed_type.h> +namespace tadah { +namespace core { + fd_type::fd_type(const fd_type& other) : rows_(other.rows_) { data_ = static_cast<double*>(malloc(3 * rows_ * sizeof(double))); @@ -127,3 +130,4 @@ bool fd_type::operator==(const fd_type& v1) const { return isApprox(v1, EPS); } +}} diff --git a/src/lapack.cpp b/src/lapack.cpp index 916256e..0ad89dc 100644 --- a/src/lapack.cpp +++ b/src/lapack.cpp @@ -1,4 +1,8 @@ #include <tadah/core/lapack.h> + +namespace tadah { +namespace core { + // Some usefull operations on vectors and matrices aed_type T_dgemv(Matrix &mat, aed_type &vec, char trans) { int m = mat.rows(); @@ -75,3 +79,5 @@ double condition_number(Matrix &A, char uplo) { return 1/rcond; } + +}} diff --git a/src/maths.cpp b/src/maths.cpp index 8026e45..0f7681e 100644 --- a/src/maths.cpp +++ b/src/maths.cpp @@ -1 +1,5 @@ #include <tadah/core/maths.h> + +namespace tadah { +namespace core { +}} diff --git a/src/normaliser_core.cpp b/src/normaliser_core.cpp index f3f9b0c..824d54c 100644 --- a/src/normaliser_core.cpp +++ b/src/normaliser_core.cpp @@ -1,5 +1,8 @@ #include <tadah/core/normaliser_core.h> +namespace tadah { +namespace core { + Normaliser_Core::Normaliser_Core () {} Normaliser_Core::Normaliser_Core (Config &c): bias(c.get<bool>("BIAS")), @@ -65,3 +68,5 @@ void Normaliser_Core::normalise(fd_type &fd, size_t k) { } } } + +}} diff --git a/src/periodic_table.cpp b/src/periodic_table.cpp index 0488631..40a8f00 100644 --- a/src/periodic_table.cpp +++ b/src/periodic_table.cpp @@ -1,5 +1,8 @@ #include <tadah/core/periodic_table.h> +namespace tadah { +namespace core { + // Definition of static members std::map<std::string, Element> PeriodicTable::symbol; std::map<std::string, Element> PeriodicTable::name; @@ -351,3 +354,5 @@ void PeriodicTable::init_masses() { masses[117] = 294.000; // Tennessine masses[118] = 294.000; // Oganesson } + +}} diff --git a/src/utils.cpp b/src/utils.cpp index 7714325..c306192 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -8,6 +8,9 @@ #include <cmath> #include <limits> +namespace tadah { +namespace core { + v_type logspace(double start, double stop, int num, double base) { if (start==0) { throw std::runtime_error("log series cannot start at 0\n"); @@ -306,3 +309,5 @@ std::vector<histogram_bin> generate_2d_histogram( return histogram_bins; } + +}} -- GitLab