From d5c16c511365224d923fdbc90268d6896cb6bb9e Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 19 Sep 2023 20:45:40 +0200 Subject: [PATCH 01/30] ==[ Porting epoch to std::chrono | WIP ]== --- .clangd | 2 +- CMakeLists.txt | 167 ++--- .../kep3/core_astro/convert_julian_dates.hpp | 24 +- include/kep3/detail/type_name.hpp | 1 + include/kep3/epoch.hpp | 251 +++++--- include/kep3/planets/keplerian.hpp | 8 +- src/epoch.cpp | 586 +++++++++++------- src/planets/keplerian.cpp | 197 +++--- test/CMakeLists.txt | 5 +- test/epoch_test_chrono.cpp | 97 +++ 10 files changed, 834 insertions(+), 504 deletions(-) create mode 100644 test/epoch_test_chrono.cpp diff --git a/.clangd b/.clangd index 0305393d..8a7bf3f9 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,2 @@ CompileFlags: - Add: '-std=c++17' \ No newline at end of file + Add: '-std=c++20' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 52b3ff37..5b4688c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,9 @@ cmake_minimum_required(VERSION 3.18.0) # NOTE: this should be done before the project command since the latter can set # CMAKE_BUILD_TYPE itself (it does so for nmake). if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - FORCE) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." + FORCE) endif() project(kep3 VERSION 0.0.1 LANGUAGES CXX C) @@ -22,8 +22,8 @@ message(STATUS "kep3 version: ${kep3_VERSION}") include(YACMACompilerLinkerSettings) # Build options. -option(kep3_BUILD_TESTS "Build unit tests." OFF) -option(kep3_BUILD_BENCHMARKS "Build benchmarks." OFF) +option(kep3_BUILD_TESTS "Build unit tests." ON) +option(kep3_BUILD_BENCHMARKS "Build benchmarks." ON) option(kep3_BUILD_PYTHON_BINDINGS "Build Python bindings." OFF) # NOTE: on Unix systems, the correct library installation path @@ -41,90 +41,97 @@ if(UNIX AND NOT APPLE) else() set(_kep3_INSTALL_LIBDIR_DEFAULT "lib") endif() + if(NOT kep3_INSTALL_LIBDIR) set(kep3_INSTALL_LIBDIR "${_kep3_INSTALL_LIBDIR_DEFAULT}" CACHE STRING "Library installation directory." FORCE) endif() + mark_as_advanced(kep3_INSTALL_LIBDIR) message(STATUS "Library installation directory: ${kep3_INSTALL_LIBDIR}") # Assemble the flags. set(kep3_CXX_FLAGS_DEBUG ${YACMA_CXX_FLAGS} ${YACMA_CXX_FLAGS_DEBUG}) set(kep3_CXX_FLAGS_RELEASE ${YACMA_CXX_FLAGS}) + if(YACMA_COMPILER_IS_MSVC) - # On both cl and clang-cl, disable the idiotic minmax macros and enable the bigobj option. - # Also, enable the WIN32_LEAN_AND_MEAN definition: - # https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly - list(APPEND kep3_CXX_FLAGS_DEBUG "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") - list(APPEND kep3_CXX_FLAGS_RELEASE "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") - if(YACMA_COMPILER_IS_CLANGXX) - # clang-cl emits various warnings, let's just silence them. - # NOTE: at one point in the recent past, MSVC added an options similar to GCC's isystem: - # https://blogs.msdn.microsoft.com/vcblog/2017/12/13/broken-warnings-theory/ - # We probably just need to wait for this to be picked up by CMake/clang-cl. Let's - # revisit the issue in the future. - list(APPEND _kep3_CLANG_CL_DISABLED_WARNINGS - "-Wno-unused-variable" - "-Wno-inconsistent-dllimport" - "-Wno-unknown-pragmas" - "-Wno-unused-parameter" - "-Wno-sign-compare" - "-Wno-deprecated-declarations" - "-Wno-deprecated-dynamic-exception-spec" - "-Wno-old-style-cast" - "-Wno-sign-conversion" - "-Wno-non-virtual-dtor" - "-Wno-deprecated" - "-Wno-shadow" - "-Wno-shorten-64-to-32" - "-Wno-reserved-id-macro" - "-Wno-undef" - "-Wno-c++98-compat-pedantic" - "-Wno-documentation-unknown-command" - "-Wno-zero-as-null-pointer-constant" - "-Wno-language-extension-token" - "-Wno-gnu-anonymous-struct" - "-Wno-nested-anon-types" - "-Wno-documentation" - "-Wno-comma" - "-Wno-nonportable-system-include-path" - "-Wno-global-constructors" - "-Wno-redundant-parens" - "-Wno-exit-time-destructors" - "-Wno-missing-noreturn" - "-Wno-switch-enum" - "-Wno-covered-switch-default" - "-Wno-float-equal" - "-Wno-double-promotion" - "-Wno-microsoft-enum-value" - "-Wno-missing-prototypes" - "-Wno-implicit-fallthrough" - "-Wno-format-nonliteral" - "-Wno-cast-qual" - "-Wno-disabled-macro-expansion" - "-Wno-unused-private-field" - "-Wno-unused-template" - "-Wno-unused-macros" - "-Wno-extra-semi-stmt" - "-Wno-c++98-compat") - list(APPEND kep3_CXX_FLAGS_DEBUG ${_kep3_CLANG_CL_DISABLED_WARNINGS}) - list(APPEND kep3_CXX_FLAGS_RELEASE ${_kep3_CLANG_CL_DISABLED_WARNINGS}) - unset(_kep3_CLANG_CL_DISABLED_WARNINGS) - else() - # Same as above, disable some cl warnings. - list(APPEND kep3_CXX_FLAGS_DEBUG "/wd4459" "/wd4127" "/wd4251") - list(APPEND kep3_CXX_FLAGS_RELEASE "/wd4459" "/wd4127" "/wd4251") - endif() - # Enable strict conformance mode, if supported. - set(CMAKE_REQUIRED_QUIET TRUE) - check_cxx_compiler_flag("/permissive-" _kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) - unset(CMAKE_REQUIRED_QUIET) - if(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) - message(STATUS "The '/permissive-' flag is supported, enabling it.") - list(APPEND kep3_CXX_FLAGS_DEBUG "/permissive-") - list(APPEND kep3_CXX_FLAGS_RELEASE "/permissive-") - endif() - unset(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + # On both cl and clang-cl, disable the idiotic minmax macros and enable the bigobj option. + # Also, enable the WIN32_LEAN_AND_MEAN definition: + # https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly + list(APPEND kep3_CXX_FLAGS_DEBUG "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") + list(APPEND kep3_CXX_FLAGS_RELEASE "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") + + if(YACMA_COMPILER_IS_CLANGXX) + # clang-cl emits various warnings, let's just silence them. + # NOTE: at one point in the recent past, MSVC added an options similar to GCC's isystem: + # https://blogs.msdn.microsoft.com/vcblog/2017/12/13/broken-warnings-theory/ + # We probably just need to wait for this to be picked up by CMake/clang-cl. Let's + # revisit the issue in the future. + list(APPEND _kep3_CLANG_CL_DISABLED_WARNINGS + "-Wno-unused-variable" + "-Wno-inconsistent-dllimport" + "-Wno-unknown-pragmas" + "-Wno-unused-parameter" + "-Wno-sign-compare" + "-Wno-deprecated-declarations" + "-Wno-deprecated-dynamic-exception-spec" + "-Wno-old-style-cast" + "-Wno-sign-conversion" + "-Wno-non-virtual-dtor" + "-Wno-deprecated" + "-Wno-shadow" + "-Wno-shorten-64-to-32" + "-Wno-reserved-id-macro" + "-Wno-undef" + "-Wno-c++98-compat-pedantic" + "-Wno-documentation-unknown-command" + "-Wno-zero-as-null-pointer-constant" + "-Wno-language-extension-token" + "-Wno-gnu-anonymous-struct" + "-Wno-nested-anon-types" + "-Wno-documentation" + "-Wno-comma" + "-Wno-nonportable-system-include-path" + "-Wno-global-constructors" + "-Wno-redundant-parens" + "-Wno-exit-time-destructors" + "-Wno-missing-noreturn" + "-Wno-switch-enum" + "-Wno-covered-switch-default" + "-Wno-float-equal" + "-Wno-double-promotion" + "-Wno-microsoft-enum-value" + "-Wno-missing-prototypes" + "-Wno-implicit-fallthrough" + "-Wno-format-nonliteral" + "-Wno-cast-qual" + "-Wno-disabled-macro-expansion" + "-Wno-unused-private-field" + "-Wno-unused-template" + "-Wno-unused-macros" + "-Wno-extra-semi-stmt" + "-Wno-c++98-compat") + list(APPEND kep3_CXX_FLAGS_DEBUG ${_kep3_CLANG_CL_DISABLED_WARNINGS}) + list(APPEND kep3_CXX_FLAGS_RELEASE ${_kep3_CLANG_CL_DISABLED_WARNINGS}) + unset(_kep3_CLANG_CL_DISABLED_WARNINGS) + else() + # Same as above, disable some cl warnings. + list(APPEND kep3_CXX_FLAGS_DEBUG "/wd4459" "/wd4127" "/wd4251") + list(APPEND kep3_CXX_FLAGS_RELEASE "/wd4459" "/wd4127" "/wd4251") + endif() + + # Enable strict conformance mode, if supported. + set(CMAKE_REQUIRED_QUIET TRUE) + check_cxx_compiler_flag("/permissive-" _kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + unset(CMAKE_REQUIRED_QUIET) + + if(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + message(STATUS "The '/permissive-' flag is supported, enabling it.") + list(APPEND kep3_CXX_FLAGS_DEBUG "/permissive-") + list(APPEND kep3_CXX_FLAGS_RELEASE "/permissive-") + endif() + + unset(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) endif() # List of source files. @@ -155,6 +162,7 @@ target_compile_options(kep3 PRIVATE # Ensure that C++20 is employed when both compiling and consuming kep3. target_compile_features(kep3 PUBLIC cxx_std_20) + # Enforce vanilla C++20 when compiling kep3. set_property(TARGET kep3 PROPERTY CXX_EXTENSIONS NO) @@ -162,6 +170,7 @@ target_include_directories(kep3 PUBLIC $ $ $) + # Boost. # NOTE: need 1.73 for atomic_ref. find_package(Boost 1.73 REQUIRED) @@ -175,6 +184,7 @@ target_link_libraries(kep3 PUBLIC fmt::fmt) find_package(heyoka CONFIG REQUIRED) target_link_libraries(kep3 PUBLIC heyoka::heyoka) message(STATUS "heyoka version: ${heyoka_VERSION}") + if(heyoka_VERSION VERSION_LESS 0.21.0) message(FATAL_ERROR "heyoka>=0.21.0 is required, but heyoka ${heyoka_VERSION} was found instead") endif() @@ -205,6 +215,7 @@ install(TARGETS kep3 ARCHIVE DESTINATION "${kep3_INSTALL_LIBDIR}" RUNTIME DESTINATION bin ) + if(kep3_BUILD_TESTS) enable_testing() add_subdirectory(test) diff --git a/include/kep3/core_astro/convert_julian_dates.hpp b/include/kep3/core_astro/convert_julian_dates.hpp index b26c509e..0c81a9b1 100644 --- a/include/kep3/core_astro/convert_julian_dates.hpp +++ b/include/kep3/core_astro/convert_julian_dates.hpp @@ -10,13 +10,23 @@ #ifndef kep3_CONVERT_JULIAN_DATES_H #define kep3_CONVERT_JULIAN_DATES_H -namespace kep3 { -inline double jd2mjd(double in) { return (in - 2400000.5); } -inline double jd2mjd2000(double in) { return (in - 2451544.5); } -inline double mjd2jd(double in) { return (in + 2400000.5); } -inline double mjd2mjd2000(double in) { return (in - 51544); } -inline double mjd20002jd(double in) { return (in + 2451544.5); } -inline double mjd20002mjd(double in) { return (in + 51544); } +#include +#include "kep3/epoch.hpp" +namespace kep3 +{ + + // inline double jd2mjd(double in) { return (in - 2400000.5); } + // inline double jd2mjd2000(double in) { return (in - 2451544.5); } + // inline double mjd2jd(double in) { return (in + 2400000.5); } + // inline double mjd2mjd2000(double in) { return (in - 51544); } + // inline double mjd20002jd(double in) { return (in + 2451544.5); } + // inline double mjd20002mjd(double in) { return (in + 51544); } + inline constexpr MJD2KClock::time_point jd2mjd(const MJD2KClock::time_point& in) { return in - 207360043200s; } + inline constexpr MJD2KClock::time_point jd2mjd2000(const MJD2KClock::time_point& in) { return in - 211813444800s; } + inline constexpr MJD2KClock::time_point mjd2jd(const MJD2KClock::time_point& in) { return in + 207360043200s; } + inline constexpr MJD2KClock::time_point mjd2mjd2000(const MJD2KClock::time_point& in) { return in - 4453401600s; } + inline constexpr MJD2KClock::time_point mjd20002jd(const MJD2KClock::time_point& in) { return in + 211813444800s; } + inline constexpr MJD2KClock::time_point mjd20002mjd(const MJD2KClock::time_point& in) { return in + 4453401600s; } } // namespace kep3 #endif // kep3_CONVERT_JULIAN_DATES_H diff --git a/include/kep3/detail/type_name.hpp b/include/kep3/detail/type_name.hpp index 0b41c327..a25abbf6 100644 --- a/include/kep3/detail/type_name.hpp +++ b/include/kep3/detail/type_name.hpp @@ -46,6 +46,7 @@ template inline std::string type_name() { break; case 3u: ret += " const volatile"; + break; default: // you should never go here throw; diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 6a18f502..df41508d 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -7,8 +7,8 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef kep3_EPOCH_H -#define kep3_EPOCH_H +#ifndef EPOCH_HPP +#define EPOCH_HPP #include @@ -18,6 +18,9 @@ #include #include +#include +#include + #include #include @@ -26,89 +29,169 @@ * This namespace contains astrodynamics and space flight mechanics routines * that are related to keplerian motions or models. */ -namespace kep3 { - -/// epoch class. -/** - * This class defines and contains a non-gregorian date (i.e. a date expressed - * in julian form). It also provides the user with an interface to boost - * gregorian dates (see boost documentation at - * http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html) - * using the posix time. - * The date is defined in MJD2000 (double) as a - * private member - * - * @author Dario Izzo (dario.izzo _AT_ googlemail.com) - */ -class kep3_DLL_PUBLIC epoch { -public: - /** Types of non gregorian dates supported. Julian Date (JD) is the number of - * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is - * the number of days passed since November 17, 1858 at 00:00 am. The Modified - * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, - * 2000 at 00:00am. - */ - enum julian_type { MJD2000, MJD, JD }; - - /** Constructors */ - explicit epoch(const double & = 0., julian_type = MJD2000); - epoch(const boost::gregorian::greg_day &day, - const boost::gregorian::greg_month &month, - const boost::gregorian::greg_year &year); - explicit epoch(const boost::posix_time::ptime &posix_time); - - /** Computing non-gregorian dates */ - [[nodiscard]] double mjd2000() const; - [[nodiscard]] double jd() const; - [[nodiscard]] double mjd() const; - - /** Interface to boost::posix_time::ptime */ - [[nodiscard]] boost::posix_time::ptime get_posix_time() const; - void set_posix_time(const boost::posix_time::ptime &); - - /** operators overloads for sum diff (epoch-days) and the comparison operators - * **/ - epoch &operator+=(double rhs); - epoch &operator-=(double rhs); - kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend epoch operator+(epoch lhs, double rhs); - kep3_DLL_PUBLIC friend epoch operator-(epoch lhs, double rhs); - kep3_DLL_PUBLIC friend double operator-(const epoch &lhs, const epoch &rhs); - -private: - // Serialization code - friend class boost::serialization::access; - template void serialize(Archive &ar, const unsigned int) { - ar &m_mjd2000; - } - // Serialization code (END) - - /// the modified julian date 2000 stored in a double - double m_mjd2000; -}; - -kep3_DLL_PUBLIC epoch epoch_from_string(const std::string &date); -kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string &date); - -kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, - const epoch &epoch_in); -kep3_DLL_PUBLIC bool operator>(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC bool operator<(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC bool operator>=(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC bool operator<=(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC bool operator==(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC bool operator!=(const epoch &c1, const epoch &c2); -kep3_DLL_PUBLIC epoch operator+(epoch lhs, double rhs); -kep3_DLL_PUBLIC epoch operator-(epoch lhs, double rhs); -kep3_DLL_PUBLIC double operator-(const epoch &lhs, const epoch &rhs); +namespace kep3 +{ + + using namespace std::literals; + namespace chr = std::chrono; + + // struct MJD2KClock + // { + + // using Clock = chr::system_clock; + // using rep = long long int; + // using period = typename Clock::period; + // using duration = typename Clock::duration; + // using time_point = typename chr::time_point; + + // static constexpr bool is_steady = Clock::is_steady; + // static constexpr typename Clock::time_point ref_epoch = + // chr::sys_days{ chr::year(2000) / chr::month(1) / chr::day(1) }; + + // static time_point now() { return time_point(Clock::now() - ref_epoch); } + + // static time_t to_time_t(const time_point& t) + // { + // return Clock::to_time_t(ref_epoch + t.time_since_epoch()); + // } + + // static time_point from_time_t(time_t t) + // { + // return time_point(Clock::from_time_t(t) - ref_epoch); + // } + // }; + struct MJD2KClock: public chr::system_clock + { + + using rep = long long int; + using period = std::ratio<1>; + using duration = chr::duration; + using time_point = chr::time_point; + static constexpr bool is_steady = false; + static constexpr chr::seconds unix_diff{ 946684800s }; + + static constexpr time_point ref_epoch{ MJD2KClock::time_point{} + unix_diff }; + + static std::time_t to_time_t(const time_point& t) noexcept + { + return std::time_t(chr::duration_cast(t.time_since_epoch() + unix_diff).count()); + } + + static time_point from_time_t(std::time_t t) noexcept + { + return time_point(chr::seconds(t) - unix_diff); + } + }; + + using namespace std::literals; + /// epoch class. + /** + * This class defines and contains a non-gregorian date (i.e. a date expressed + * in julian form). It also provides the user with an interface to boost + * gregorian dates (see boost documentation at + * http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html) + * using the posix time. + * The date is defined in MJD2000 (double) as a + * private member + * + * @author Dario Izzo (dario.izzo _AT_ googlemail.com) + */ + class kep3_DLL_PUBLIC epoch + { + public: + /** Types of non gregorian dates supported. Julian Date (JD) is the number of + * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is + * the number of days passed since November 17, 1858 at 00:00 am. The Modified + * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, + * 2000 at 00:00am. + */ + enum class julian_type { MJD2000, MJD, JD }; + + /** Constructors */ + explicit epoch(const double epoch_in = 0.0, const julian_type epoch_type = julian_type::MJD2000); + explicit epoch(const int year, const int month, const int day, const int hour = 0, const int minute = 0, const int second = 0); + explicit epoch(const boost::posix_time::ptime& posix_time); + + /** Computing non-gregorian dates */ + [[nodiscard]] MJD2KClock::time_point mjd2000() const; + [[nodiscard]] MJD2KClock::time_point jd() const; + [[nodiscard]] MJD2KClock::time_point mjd() const; + + /** Interface to boost::posix_time::ptime */ + [[nodiscard]] boost::posix_time::ptime get_posix_time() const; + + void set(const int year, const int month, const int day, const int hour = 0, + const int minute = 0, const int second = 0); + MJD2KClock::time_point make_tm(const int year, const int month, const int day, + const int hour = 0, const int minute = 0, const int second = 0); + + // Calendar conversions + MJD2KClock::time_point tp_from_seconds(const double seconds) const; + MJD2KClock::time_point tp_from_days(const double days) const; + void set_tp_mjd2000(const double epoch_in); + void set_tp_mjd(const double epoch_in); + void set_tp_jd(const double epoch_in); + + // Duration conversions + MJD2KClock::rep as_sec(); + double as_days(); + + // Printing + static const char* as_utc_string(const MJD2KClock::time_point&); + static std::time_t as_gmtime(const MJD2KClock::time_point&); + + /** operators overloads for sum diff (epoch-days) and the comparison + * operators + * **/ + + std::chrono::seconds day2sec(const double days) const; + kep3_DLL_PUBLIC epoch epoch_from_string(const std::string& date); + kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string& date); + + kep3_DLL_PUBLIC friend std::ostream& operator<<(std::ostream& s, epoch const& epoch_in); + template> + kep3_DLL_PUBLIC friend epoch& operator+=(epoch& ep, T rhs); + template> + kep3_DLL_PUBLIC friend epoch& operator-=(epoch& ep, T rhs); + kep3_DLL_PUBLIC friend bool operator>(const epoch& c1, const epoch& c2); + kep3_DLL_PUBLIC friend bool operator<(const epoch& c1, const epoch& c2); + kep3_DLL_PUBLIC friend bool operator>=(const epoch& c1, const epoch& c2); + kep3_DLL_PUBLIC friend bool operator<=(const epoch& c1, const epoch& c2); + kep3_DLL_PUBLIC friend bool operator==(const epoch& c1, const epoch& c2); + kep3_DLL_PUBLIC friend bool operator!=(const epoch& c1, const epoch& c2); + template> + kep3_DLL_PUBLIC friend epoch operator+(const epoch& lhs, T rhs); + template> + kep3_DLL_PUBLIC friend epoch operator-(const epoch& lhs, T rhs); + kep3_DLL_PUBLIC friend MJD2KClock::rep operator-(const epoch lhs, const epoch rhs); + + private: + // Serialization code + friend class boost::serialization::access; + template void serialize(Archive& ar, const unsigned int) + { + ar& m_mjd2000; + } + // Serialization code (END) + + /// the modified julian date 2000 stored in a double + double m_mjd2000; + MJD2KClock::time_point tp; + }; + // kep3_DLL_PUBLIC bool operator>(const epoch& c1, const epoch& c2); + // kep3_DLL_PUBLIC bool operator<(const epoch& c1, const epoch& c2); + // kep3_DLL_PUBLIC bool operator>=(const epoch& c1, const epoch& c2); + // kep3_DLL_PUBLIC bool operator<=(const epoch& c1, const epoch& c2); + // kep3_DLL_PUBLIC bool operator==(const epoch& c1, const epoch& c2); + // kep3_DLL_PUBLIC bool operator!=(const epoch& c1, const epoch& c2); + // template> + // kep3_DLL_PUBLIC epoch operator+(const epoch& lhs, T rhs); + // template> + // kep3_DLL_PUBLIC epoch operator-(const epoch& lhs, T rhs); + // kep3_DLL_PUBLIC MJD2KClock::rep operator-(const epoch lhs, const epoch rhs); } // end of namespace kep3 -template <> struct fmt::formatter : ostream_formatter {}; +template <> struct fmt::formatter: ostream_formatter {}; -#endif // kep3_EPOCH_H +#endif // EPOCH_HPP diff --git a/include/kep3/planets/keplerian.hpp b/include/kep3/planets/keplerian.hpp index dccdba3f..e8ef6434 100644 --- a/include/kep3/planets/keplerian.hpp +++ b/include/kep3/planets/keplerian.hpp @@ -26,24 +26,24 @@ namespace kep3::udpla { class kep3_DLL_PUBLIC keplerian { kep3::epoch m_ref_epoch; - std::array, 2> m_pos_vel_0; std::string m_name; double m_mu_central_body; double m_mu_self; double m_radius; - double m_safe_radius; bool m_ellipse; + double m_safe_radius; + std::array, 2> m_pos_vel_0; friend class boost::serialization::access; template void serialize(Archive &ar, unsigned) { ar &m_ref_epoch; - ar &m_pos_vel_0; ar &m_name; ar &m_mu_central_body; ar &m_mu_self; ar &m_radius; - ar &m_safe_radius; ar &m_ellipse; + ar &m_safe_radius; + ar &m_pos_vel_0; } public: diff --git a/src/epoch.cpp b/src/epoch.cpp index 40ca411f..ffbe3702 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -8,249 +8,363 @@ // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include +#include #include #include -#include -#include +#include "kep3/core_astro/convert_julian_dates.hpp" +#include "kep3/epoch.hpp" // This is set to the precision of the boost date library (microseconds is // default, nanoseconds can be set when compiling boosts. Note that the code has // not been checked in that case) #define BOOST_DATE_PRECISION 1e-6 -namespace kep3 { -using ::boost::gregorian::date; -using ::boost::gregorian::greg_day; -using ::boost::gregorian::greg_month; -using ::boost::gregorian::greg_year; -using ::boost::posix_time::ptime; -using ::boost::posix_time::time_duration; -using ::boost::posix_time::time_from_string; -using ::boost::posix_time::from_iso_string; - - -/// Constructor. -/** - * Constructs an epoch from a non-gregorian date. - * \param[in] epoch_in A double indicating the non-gregorian date - * \param[in] epoch_type One of [epoch::MJD2000, epoch::MJD, epoch::JD] - */ -epoch::epoch(const double &epoch_in, julian_type epoch_type) - : m_mjd2000(epoch_in) { - switch (epoch_type) { - case MJD2000: - break; - case MJD: - m_mjd2000 = mjd2mjd2000(epoch_in); - break; - case JD: - m_mjd2000 = jd2mjd2000(epoch_in); - break; - } -} - -/// Constructor. -/** - * Constructs an epoch from a gregorian date. The time of the day is assumed to - * be midnight. \param[in] year The gregorian year \param[in] month The month of - * the year \param[in] day The day of the month - */ -epoch::epoch(const greg_day &day, const greg_month &month, - const greg_year &year) - : m_mjd2000(0) { - // member m_mjd2000 will be here assigned. - set_posix_time(ptime(date(year, month, day))); -} - -/// Constructor. -/** - * Constructs an epoch from a boost ptime object (posix time) - * \param[in] posix_time The posix_time - */ -epoch::epoch(const ptime &posix_time) { - time_duration dt = posix_time - ptime(date(2000, 1, 1)); - bool flag = false; - if (dt.is_negative()) { - flag = true; - dt = dt.invert_sign(); - } - double fr_secs = - static_cast(dt.fractional_seconds()) * BOOST_DATE_PRECISION; - m_mjd2000 = static_cast(dt.hours()) / 24.0 + - static_cast(dt.minutes()) / 1440.0 + - (static_cast(dt.seconds()) + fr_secs) / 86400.0; - if (flag) { - m_mjd2000 = -m_mjd2000; - } -} - -/// jd getter. -/** - * Returns the julian date - * - * @return double containing the julian date - * - */ -double epoch::jd() const { return mjd20002jd(m_mjd2000); } - -/// mjd getter. -/** - * Returns the modified julian date - * - * @return double containing the modified julian date - * - */ -double epoch::mjd() const { return mjd20002mjd(m_mjd2000); } - -/// mjd2000 getter. -/** - * Gets the modified julian date 2000 - * @return const reference to mjd2000 - */ -double epoch::mjd2000() const { return m_mjd2000; } - -/// Extracts the posix time -/** - * Returns the posix_time representation of the epoch. The method evaluates - * from the mjd2000 the number of days, months, seconds and - * micro/nano seconds passed since the 1st of January 2000 and uses this - * information to build the posix time - * - * @return ptime containing the posix time - * - */ -ptime epoch::get_posix_time() const { - long hrs = 0., min = 0., sec = 0., fsec = 0.; - bool flag = false; - double copy = m_mjd2000; - if (copy < 0) { - copy = -copy; - flag = true; - } - hrs = static_cast(copy * 24); - min = static_cast((copy * 24 - static_cast(hrs)) * 60); - sec = static_cast((((copy * 24 - static_cast(hrs)) * 60) - - static_cast(min)) * - 60); - double dblfsec = ((((copy * 24 - static_cast(hrs)) * 60) - - static_cast(min)) * - 60) - - static_cast(sec); - std::ostringstream fsecstr; - fsecstr << std::setiosflags(std::ios::fixed) - << std::setprecision( - -static_cast(std::log10(BOOST_DATE_PRECISION))) - << dblfsec; - fsec = boost::lexical_cast(fsecstr.str().substr( - 2, static_cast(-std::log10(BOOST_DATE_PRECISION) + 1))); - ptime retval; - if (flag) { - retval = ptime(date(2000, 1, 1), time_duration(-hrs, -min, -sec, -fsec)); - } else { - retval = ptime(date(2000, 1, 1), time_duration(hrs, min, sec, fsec)); - } - return retval; -} - -/// Sets the epoch from a posix time -/** - * Sets the epoch to a particular posix_time. - * - * \param[in] posix_time containing the posix time - * - */ -void epoch::set_posix_time(const ptime &posix_time) { - - m_mjd2000 = epoch(posix_time).mjd2000(); -} - -epoch &epoch::operator+=(double rhs) { - /* addition of rhs to *this takes place here */ - m_mjd2000 += rhs; - return *this; // return the result by reference -} - -epoch &epoch::operator-=(double rhs) { - /* addition of rhs to *this takes place here */ - m_mjd2000 -= rhs; - return *this; // return the result by reference -} - -/// Returns an epoch constructed from a delimited string containing a date -/** - * Builds an epoch from a delimited string. Excess digits in fractional seconds - * will be dropped. Ex: "1:02:03.123456999" => "1:02:03.123456". This behavior - * depends on the precision defined in astro_constant.h used to compile - * - * Example: - * std::string ts("2002-01-20 23:59:54.003"); - * epoch e(epoch_from_string(ts)) - * - */ -epoch epoch_from_string(const std::string &date) { - return epoch(time_from_string(date)); -} - -/// Returns an epoch constructed from a non delimited iso string containing a -/// date -/** - * Builds an epoch from a non delimited iso string containing a date. - * - * Example: - * std::string ts("20020131T235959"); - * epoch e(epoch_from_iso_string(ts)) - * - */ -epoch epoch_from_iso_string(const std::string &date) { - return epoch( - from_iso_string(date)); -} - -/// Overload the stream operator for kep_toolbox::epoch -/** - * Streams out a date in the format 2000-Jan-01 00:12:30.123457 - * - * \param[in] s stream to which the epoch will be sent - * \param[in] now epoch to be sent to stream - * - * \return reference to s - * - */ -std::ostream &operator<<(std::ostream &s, const epoch &epoch_in) { - s << epoch_in.get_posix_time(); - return s; -} -bool operator>(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 > c2.m_mjd2000; -} -bool operator<(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 < c2.m_mjd2000; -} -bool operator>=(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 >= c2.m_mjd2000; -} -bool operator<=(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 <= c2.m_mjd2000; -} -bool operator==(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 == c2.m_mjd2000; -} -bool operator!=(const epoch &c1, const epoch &c2) { - return c1.m_mjd2000 != c2.m_mjd2000; -} -epoch operator+(epoch lhs, double rhs) { - lhs += rhs; // reuse compound assignment - return lhs; // return the result by value (uses move constructor) -} -epoch operator-(epoch lhs, double rhs) { - lhs -= rhs; // reuse compound assignment - return lhs; // return the result by value (uses move constructor) -} -double operator-(const epoch &lhs, const epoch &rhs) { - return lhs.mjd2000() - - rhs.mjd2000(); // return the result by value (uses move constructor) -} - -} // namespace kep3 \ No newline at end of file +namespace kep3 +{ + using ::boost::gregorian::date; + using ::boost::gregorian::greg_day; + using ::boost::gregorian::greg_month; + using ::boost::gregorian::greg_year; + using ::boost::posix_time::from_iso_string; + using ::boost::posix_time::ptime; + using ::boost::posix_time::time_duration; + using ::boost::posix_time::time_from_string; + + using namespace std::literals; + + /// Constructor. + /** + * Constructs an epoch from a non-gregorian date. + * \param[in] epoch_in A double indicating the non-gregorian date + * \param[in] epoch_type One of [epoch::julian_type::MJD2000, + * epoch::julian_type::MJD, epoch::julian_type::JD] + */ + epoch::epoch(const double epoch_in, const julian_type epoch_type) + : + m_mjd2000(epoch_in) + { + switch (epoch_type) + { + case julian_type::MJD2000: + set_tp_mjd2000(epoch_in); + break; + case julian_type::MJD: + set_tp_mjd(epoch_in); + break; + case julian_type::JD: + set_tp_jd(epoch_in); + break; + default: + throw; + } + } + + /// Constructor. + /** + * Constructs an epoch from a gregorian date. The time of the day is assumed to + * be midnight. \param[in] year The gregorian year \param[in] month The month of + * the year \param[in] day The day of the month + */ + epoch::epoch(const int year, const int month, const int day, + const int hour, const int minute, const int second) + : + m_mjd2000(0), + tp(make_tm(year, month, day, hour, minute, second)) + { + } + + /// Constructor. + /** + * Constructs an epoch from a boost ptime object (posix time) + * \param[in] posix_time The posix_time + */ + epoch::epoch(const boost::posix_time::ptime& posix_time) + { + + time_duration dt = posix_time - ptime(date(2000, 1, 1)); + bool flag = false; + if (dt.is_negative()) + { + flag = true; + dt = dt.invert_sign(); + } + const double fr_secs = + static_cast(dt.fractional_seconds()) * BOOST_DATE_PRECISION; + m_mjd2000 = static_cast(dt.hours()) / 24.0 + + static_cast(dt.minutes()) / 1440.0 + + (static_cast(dt.seconds()) + fr_secs) / 86400.0; + if (flag) + { + m_mjd2000 = -m_mjd2000; + } + + tp = tp_from_seconds(flag ? -dt.total_seconds() : dt.total_seconds()); + // std::cout << "Posix time: " << posix_time << "\n"; + // std::cout << "Time point : " << epoch::as_utc_string(tp) << "\n"; + } + + MJD2KClock::time_point epoch::make_tm(const int year, const int month, const int day, + const int hr, const int min, const int sec) + { + std::tm t{}; + t.tm_year = year - 1900; + t.tm_mon = month - 1; + t.tm_mday = day; + t.tm_hour = hr; + t.tm_min = min; + t.tm_sec = sec; + auto tm{ std::mktime(&t) }; + auto utctm{ std::gmtime(&tm) }; + + return MJD2KClock::from_time_t(std::mktime(utctm)); + } + + /// jd getter. + /** + * Returns the julian date + * + * @return double containing the julian date + * + */ + // double epoch::jd() const { return mjd20002jd(m_mjd2000); } + MJD2KClock::time_point epoch::jd() const { return mjd20002jd(tp); } + + /// mjd getter. + /** + * Returns the modified julian date + * + * @return double containing the modified julian date + * + */ + MJD2KClock::time_point epoch::mjd() const { return mjd20002mjd(tp); } + + /// mjd2000 getter. + /** + * Gets the modified julian date 2000 + * @return const reference to mjd2000 + */ + MJD2KClock::time_point epoch::mjd2000() const { return tp; } + + /// Extracts the posix time + /** + * Returns the posix_time representation of the epoch. The method evaluates + * from the mjd2000 the number of days, months, seconds and + * micro/nano seconds passed since the 1st of January 2000 and uses this + * information to build the posix time + * + * @return ptime containing the posix time + * + */ + ptime epoch::get_posix_time() const + { + long hrs = 0., min = 0., sec = 0., fsec = 0.; + bool flag = false; + double copy = m_mjd2000; + if (copy < 0) + { + copy = -copy; + flag = true; + } + hrs = static_cast(copy * 24); + min = static_cast((copy * 24 - static_cast(hrs)) * 60); + sec = static_cast((((copy * 24 - static_cast(hrs)) * 60) - + static_cast(min)) * 60); + const double dblfsec = ((((copy * 24 - static_cast(hrs)) * 60) - + static_cast(min)) * 60) - + static_cast(sec); + std::ostringstream fsecstr; + fsecstr << std::setiosflags(std::ios::fixed) + << std::setprecision( + -static_cast(std::log10(BOOST_DATE_PRECISION))) + << dblfsec; + fsec = boost::lexical_cast(fsecstr.str().substr( + 2, static_cast(-std::log10(BOOST_DATE_PRECISION) + 1))); + ptime retval; + if (flag) + { + retval = ptime(date(2000, 1, 1), time_duration(-hrs, -min, -sec, -fsec)); + } + else + { + retval = ptime(date(2000, 1, 1), time_duration(hrs, min, sec, fsec)); + } + + ptime temp_pt = boost::posix_time::from_time_t(MJD2KClock::to_time_t(tp)); + + return temp_pt; + } + + /// Sets the epoch from a posix time + /** + * Sets the epoch to a particular posix_time. + * + * \param[in] posix_time containing the posix time + * + */ + void epoch::set(const int year, const int month, const int day, + const int hour, const int minute, const int second) + { + tp = make_tm(year, month, day, hour, minute, second); + } + + MJD2KClock::time_point epoch::tp_from_seconds(const double seconds) const + { + return MJD2KClock::time_point{} + chr::round(chr::duration>(seconds)); + } + + MJD2KClock::time_point epoch::tp_from_days(const double days) const + { + return MJD2KClock::time_point{} + day2sec(days); + } + + std::chrono::seconds epoch::day2sec(const double days) const + { + return chr::round(chr::duration>(days)); + } + + void epoch::set_tp_mjd2000(const double days) + { + tp = tp_from_days(days); + std::cout << days << " days in MJD2000: " << epoch::as_utc_string(tp); + } + void epoch::set_tp_mjd(const double days) + { + tp = mjd2mjd2000(tp_from_days(days)); + std::cout << days << " days in MJD: " << epoch::as_utc_string(tp); + } + void epoch::set_tp_jd(const double days) + { + tp = jd2mjd2000(tp_from_days(days)); + std::cout << days << " in JD: " << epoch::as_utc_string(tp); + } + + MJD2KClock::rep epoch::as_sec() + { + return tp.time_since_epoch().count(); + } + double epoch::as_days() + { + return std::chrono::duration>(tp.time_since_epoch()).count(); + } + + std::time_t epoch::as_gmtime(const MJD2KClock::time_point& tp) + { + auto tt{ MJD2KClock::to_time_t(tp) }; + auto utc = std::gmtime(&tt); + return std::mktime(utc); + } + + const char* epoch::as_utc_string(const MJD2KClock::time_point& tp) + { + auto tm = epoch::as_gmtime(tp); + return std::ctime(&tm); + } + + template> + epoch& operator+=(epoch& ep, T rhs) + { + /* addition of rhs to *this takes place here */ + ep.tp += rhs; + return ep; // return the result by reference + } + + template> + epoch& operator-=(epoch& ep, T rhs) + { + /* addition of rhs to *this takes place here */ + ep.tp -= rhs; + return ep; // return the result by reference + } + + /// Returns an epoch constructed from a delimited string containing a date + /** + * Builds an epoch from a delimited string. Excess digits in fractional seconds + * will be dropped. Ex: "1:02:03.123456999" => "1:02:03.123456". This behavior + * depends on the precision defined in astro_constant.h used to compile + * + * Example: + * std::string ts("2002-01-20 23:59:54.003"); + * epoch e(epoch_from_string(ts)) + * + */ + epoch epoch_from_string(const std::string& date) + { + return epoch(time_from_string(date)); + } + + /// Returns an epoch constructed from a non delimited iso string containing a + /// date + /** + * Builds an epoch from a non delimited iso string containing a date. + * + * Example: + * std::string ts("20020131T235959"); + * epoch e(epoch_from_iso_string(ts)) + * + */ + epoch epoch_from_iso_string(const std::string& date) + { + return epoch(from_iso_string(date)); + } + + /// Overload the stream operator for kep_toolbox::epoch + /** + * Streams out a date in the format 2000-Jan-01 00:12:30.123457 + * + * \param[in] s stream to which the epoch will be sent + * \param[in] now epoch to be sent to stream + * + * \return reference to s + * + */ + std::ostream& operator<<(std::ostream& s, const epoch& ep) + { + s << epoch::as_utc_string(ep.tp); + return s; + } + bool operator>(const epoch& c1, const epoch& c2) + { + return c1.tp > c2.tp; + } + bool operator<(const epoch& c1, const epoch& c2) + { + return c1.tp < c2.tp; + } + bool operator>=(const epoch& c1, const epoch& c2) + { + return c1.tp >= c2.tp; + } + bool operator<=(const epoch& c1, const epoch& c2) + { + return c1.tp <= c2.tp; + } + bool operator==(const epoch& c1, const epoch& c2) + { + return c1.tp == c2.tp; + } + bool operator!=(const epoch& c1, const epoch& c2) + { + return c1.tp != c2.tp; + } + + // template> + // epoch operator+(const epoch& lhs, T rhs) + // { + // lhs += rhs; // reuse compound assignment + // return lhs; // return the result by value (uses move constructor) + // } + // template> + // epoch operator-(const epoch& lhs, T rhs) + // { + // lhs -= rhs; // reuse compound assignment + // return lhs; // return the result by value (uses move constructor) + // } + MJD2KClock::rep operator-(const epoch lhs, const epoch rhs) + { + return (lhs - rhs); // return the result by value (uses move constructor) + } + +} // namespace kep3 diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index dd881b87..acc9544d 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -22,94 +22,103 @@ #include #include -namespace kep3::udpla { +namespace kep3::udpla +{ -keplerian::keplerian(const epoch &ref_epoch, - const std::array, 2> &pos_vel, - double mu_central_body, std::string name, - std::array added_params) + keplerian::keplerian(const epoch& ref_epoch, + const std::array, 2>& pos_vel, + double mu_central_body, std::string name, + std::array added_params) : m_ref_epoch(ref_epoch), m_name(std::move(name)), - m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), - m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), - m_pos_vel_0(pos_vel) { - double R = + m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), + m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), + m_pos_vel_0(pos_vel) + { + double R = std::sqrt(pos_vel[0][0] * pos_vel[0][0] + pos_vel[0][1] * pos_vel[0][1] + pos_vel[0][2] * pos_vel[0][2]); - double en = (pos_vel[1][0] * pos_vel[1][0] + pos_vel[1][1] * pos_vel[1][1] + - pos_vel[1][2] * pos_vel[1][2]) / - 2. - - mu_central_body / R; - (en > 0) ? m_ellipse = false : m_ellipse = true; -} - -keplerian::keplerian(const epoch &ref_epoch, const std::array &par, - double mu_central_body, std::string name, - std::array added_params) - : m_ref_epoch(ref_epoch), m_name(std::move(name)), - m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), - m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), - m_pos_vel_0() { - - if (par[0] * (1 - par[1]) <= 0) { - throw std::domain_error( - "A Keplerian planet constructor was called with with non compatible " - "a,e:" - "The following must hold: a<0 -> e>1 [a>0 -> e<1]."); + double en = (pos_vel[1][0] * pos_vel[1][0] + pos_vel[1][1] * pos_vel[1][1] + + pos_vel[1][2] * pos_vel[1][2]) / + 2. - + mu_central_body / R; + (en > 0) ? m_ellipse = false : m_ellipse = true; } - m_pos_vel_0 = kep3::par2ic(par, mu_central_body); - (par[0] < 0) ? m_ellipse = false : m_ellipse = true; -} - -std::array, 2> -keplerian::eph(const kep3::epoch &ep) const { - // 1 - We compute the dt - double dt = (ep.mjd2000() - m_ref_epoch.mjd2000()) * DAY2SEC; - // 2 - We propagate (make a copy as we do not want to change m_pos_vel_0) - auto retval(m_pos_vel_0); - kep3::propagate_lagrangian(retval, dt, m_mu_central_body); - return retval; -} - -std::string keplerian::get_name() const { return m_name; } - -double keplerian::get_mu_central_body() const { return m_mu_central_body; } -double keplerian::get_mu_self() const { return m_mu_self; } - -double keplerian::get_radius() const { return m_radius; } - -double keplerian::get_safe_radius() const { return m_safe_radius; } + keplerian::keplerian(const epoch& ref_epoch, const std::array& par, + double mu_central_body, std::string name, + std::array added_params) + : m_ref_epoch(ref_epoch), m_name(std::move(name)), + m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), + m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), + m_pos_vel_0() + { + + if (par[0] * (1 - par[1]) <= 0) + { + throw std::domain_error( + "A Keplerian planet constructor was called with with non compatible " + "a,e:" + "The following must hold: a<0 -> e>1 [a>0 -> e<1]."); + } + m_pos_vel_0 = kep3::par2ic(par, mu_central_body); + (par[0] < 0) ? m_ellipse = false : m_ellipse = true; + } -kep3::epoch keplerian::get_ref_epoch() const { return m_ref_epoch; } + std::array, 2> + keplerian::eph(const kep3::epoch& ep) const + { + // 1 - We compute the dt + auto dt = (ep - m_ref_epoch); + // 2 - We propagate (make a copy as we do not want to change m_pos_vel_0) + auto retval(m_pos_vel_0); + kep3::propagate_lagrangian(retval, dt, m_mu_central_body); + return retval; + } -std::array keplerian::elements(kep3::elements_type el_type) const { - std::array retval{}; - switch (el_type) { - case kep3::elements_type::KEP_F: - retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); - break; - case kep3::elements_type::KEP_M: - if (!m_ellipse) { - throw std::logic_error("Mean anomaly is only available for ellipses."); + std::string keplerian::get_name() const { return m_name; } + + double keplerian::get_mu_central_body() const { return m_mu_central_body; } + + double keplerian::get_mu_self() const { return m_mu_self; } + + double keplerian::get_radius() const { return m_radius; } + + double keplerian::get_safe_radius() const { return m_safe_radius; } + + kep3::epoch keplerian::get_ref_epoch() const { return m_ref_epoch; } + + std::array keplerian::elements(kep3::elements_type el_type) const + { + std::array retval{}; + switch (el_type) + { + case kep3::elements_type::KEP_F: + retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); + break; + case kep3::elements_type::KEP_M: + if (!m_ellipse) + { + throw std::logic_error("Mean anomaly is only available for ellipses."); + } + retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); + retval[5] = kep3::f2m(retval[5], retval[1]); + break; + case kep3::elements_type::MEQ: + retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body); + break; + case kep3::elements_type::MEQ_R: + retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body, true); + break; + default: + throw std::logic_error("You should not go here!"); } - retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); - retval[5] = kep3::f2m(retval[5], retval[1]); - break; - case kep3::elements_type::MEQ: - retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body); - break; - case kep3::elements_type::MEQ_R: - retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body, true); - break; - default: - throw std::logic_error("You should not go here!"); + return retval; } - return retval; -} -std::string keplerian::get_extra_info() const { - auto par = elements(); - std::string retval = + std::string keplerian::get_extra_info() const + { + auto par = elements(); + std::string retval = fmt::format("Keplerian planet elements: \n") + fmt::format("Semi major axis (AU): {}\n", par[0] / kep3::AU) + fmt::format("Eccentricity: {}\n", par[1]) + @@ -117,23 +126,25 @@ std::string keplerian::get_extra_info() const { fmt::format("Big Omega (deg.): {}\n", par[3] * kep3::RAD2DEG) + fmt::format("Small omega (deg.): {}\n", par[4] * kep3::RAD2DEG) + fmt::format("True anomly (deg.): {}\n", par[5] * kep3::RAD2DEG); - if (m_ellipse) { - retval += fmt::format("Mean anomly (deg.): {}\n", - kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); + if (m_ellipse) + { + retval += fmt::format("Mean anomly (deg.): {}\n", + kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); + } + retval += fmt::format("Elements reference epoch (MJD2000): {}\n", + m_ref_epoch.mjd2000().time_since_epoch().count()) + + fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + + fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + + fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); + return retval; + } + + std::ostream& operator<<(std::ostream& os, + const kep3::udpla::keplerian& udpla) + { + os << udpla.get_extra_info() << std::endl; + return os; } - retval += fmt::format("Elements reference epoch (MJD2000): {}\n", - m_ref_epoch.mjd2000()) + - fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + - fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + - fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); - return retval; -} - -std::ostream &operator<<(std::ostream &os, - const kep3::udpla::keplerian &udpla) { - os << udpla.get_extra_info() << std::endl; - return os; -} } // namespace kep3::udpla diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 112b9864..d20d9105 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,6 +20,7 @@ function(ADD_kep3_TESTCASE arg1) "$<$:${kep3_CXX_FLAGS_RELEASE}>" "$<$:${kep3_CXX_FLAGS_RELEASE}>" ) + # Setup the C++ standard. target_compile_features(${arg1} PRIVATE cxx_std_20) set_property(TARGET ${arg1} PROPERTY CXX_EXTENSIONS NO) @@ -27,7 +28,9 @@ function(ADD_kep3_TESTCASE arg1) endfunction() ADD_kep3_TESTCASE(convert_anomalies_test) -ADD_kep3_TESTCASE(epoch_test) + +# ADD_kep3_TESTCASE(epoch_test) +ADD_kep3_TESTCASE(epoch_test_chrono) ADD_kep3_TESTCASE(planet_test) ADD_kep3_TESTCASE(planet_keplerian_test) ADD_kep3_TESTCASE(ic2par2ic_test) diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp new file mode 100644 index 00000000..1b8046ca --- /dev/null +++ b/test/epoch_test_chrono.cpp @@ -0,0 +1,97 @@ +// Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani +// (bluescarni@gmail.com) +// +// This file is part of the kep3 library. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include +#include +#include + +#include "kep3/epoch.hpp" + +#include "catch.hpp" + +using kep3::epoch; +// using kep3::epoch_from_iso_string; +// using kep3::epoch_from_string; +using boost::gregorian::date; +using boost::posix_time::ptime; + +using namespace std::literals; + +TEST_CASE("construct") +{ + // test syntax + REQUIRE_NOTHROW(epoch()); + REQUIRE_NOTHROW(epoch(123.456)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD2000)); + REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(2034, 12, 31)); + // // > 2000 + boost::posix_time::ptime posix_time_test(date(2034, 12, 31)); + REQUIRE_NOTHROW(epoch(posix_time_test)); + REQUIRE(epoch(posix_time_test).get_posix_time() == posix_time_test); + std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << "\n"; + std::cout << "Boost1: " << posix_time_test << "\n"; + + // // < 2000 + boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); + REQUIRE_NOTHROW(epoch(posix_time_test2)); + REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); + std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << "\n"; + std::cout << "Boost2: " << posix_time_test2 << "\n"; + + // // test conversions + REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); + REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); + REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); + std::cout << "Chrono3: " << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << "\n"; + std::cout << "Chrono3-1: " << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << "\n"; + REQUIRE(epoch(2034, 12, 31).jd() == epoch(posix_time_test).jd()); + +} + +// TEST_CASE("epoch_operators") +// { +// REQUIRE(epoch(0.) == epoch(0.)); +// REQUIRE(epoch(0.) != epoch(1.)); +// REQUIRE(epoch(1.) > epoch(0.)); +// REQUIRE(epoch(1.) >= epoch(1.)); +// REQUIRE(epoch(1.) >= epoch(0.)); +// REQUIRE(epoch(0.) < epoch(1.)); +// REQUIRE(epoch(1.) <= epoch(1.)); +// epoch today(0.); +// today += 100.; +// REQUIRE(today == epoch(100.)); +// today -= 100.; +// REQUIRE(today == epoch(0.)); +// auto yesterday = today - 1.; +// REQUIRE(yesterday == epoch(-1.)); +// today = yesterday + 1; +// REQUIRE(today == epoch(0.)); +// REQUIRE(today - yesterday == 1.); +// REQUIRE_NOTHROW((std::cout << epoch())); +// } + +// TEST_CASE("conversions_from_string") { +// { +// std::string ts("20020131T000000"); +// epoch e(epoch_from_iso_string(ts)); +// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 31)))); +// } +// { +// std::string ts("2002-01-20 00:00:00.000"); +// epoch e(epoch_from_string(ts)); +// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 20)))); +// } +// } From f31fecc63882bb7d05caee790f9fbd1c83155552 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 19 Sep 2023 21:00:00 +0200 Subject: [PATCH 02/30] ==[ JD is slightly broken ]== --- include/kep3/epoch.hpp | 2 +- src/epoch.cpp | 3 +++ test/epoch_test_chrono.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index df41508d..8e4f3400 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -79,7 +79,7 @@ namespace kep3 static time_point from_time_t(std::time_t t) noexcept { - return time_point(chr::seconds(t) - unix_diff); + return chr::time_point_cast(time_point(chr::seconds(t) - unix_diff)); } }; diff --git a/src/epoch.cpp b/src/epoch.cpp index ffbe3702..146f50ca 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -96,6 +96,9 @@ namespace kep3 m_mjd2000 = static_cast(dt.hours()) / 24.0 + static_cast(dt.minutes()) / 1440.0 + (static_cast(dt.seconds()) + fr_secs) / 86400.0; + + // NOTE: Why not this? + // m_mjd2000 = dt.total_seconds() / 86400.0; if (flag) { m_mjd2000 = -m_mjd2000; diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp index 1b8046ca..2970be0e 100644 --- a/test/epoch_test_chrono.cpp +++ b/test/epoch_test_chrono.cpp @@ -57,7 +57,7 @@ TEST_CASE("construct") REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); std::cout << "Chrono3: " << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << "\n"; std::cout << "Chrono3-1: " << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << "\n"; - REQUIRE(epoch(2034, 12, 31).jd() == epoch(posix_time_test).jd()); + REQUIRE(epoch(2034, 12, 31).jd().time_since_epoch().count() == epoch(posix_time_test).jd().time_since_epoch().count()); } From f8c858d4da4f48b4ac5bc86f2319631afbefa5a9 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Fri, 22 Sep 2023 09:08:45 +0200 Subject: [PATCH 03/30] ==[ Minor update ]== --- test/epoch_test_chrono.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp index 2970be0e..9f04e7c9 100644 --- a/test/epoch_test_chrono.cpp +++ b/test/epoch_test_chrono.cpp @@ -57,7 +57,7 @@ TEST_CASE("construct") REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); std::cout << "Chrono3: " << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << "\n"; std::cout << "Chrono3-1: " << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << "\n"; - REQUIRE(epoch(2034, 12, 31).jd().time_since_epoch().count() == epoch(posix_time_test).jd().time_since_epoch().count()); + REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } From 1726069eea1bbaa17ec116f917efd6cbb8ad53e3 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Fri, 29 Sep 2023 11:26:33 +0200 Subject: [PATCH 04/30] WIP - Migration to chrono mostly complete. PR, take 2 --- CMakeLists.txt | 4 +- .../kep3/core_astro/convert_julian_dates.hpp | 43 ++- include/kep3/epoch.hpp | 249 ++++++------ include/kep3/planets/keplerian.hpp | 2 +- src/epoch.cpp | 365 +++++++----------- src/planets/keplerian.cpp | 198 +++++----- test/epoch_test_chrono.cpp | 129 ++++--- test/planet_test.cpp | 10 +- 8 files changed, 489 insertions(+), 511 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b4688c5..e38aa6d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ message(STATUS "kep3 version: ${kep3_VERSION}") include(YACMACompilerLinkerSettings) # Build options. -option(kep3_BUILD_TESTS "Build unit tests." ON) -option(kep3_BUILD_BENCHMARKS "Build benchmarks." ON) +option(kep3_BUILD_TESTS "Build unit tests." OFF) +option(kep3_BUILD_BENCHMARKS "Build benchmarks." OFF) option(kep3_BUILD_PYTHON_BINDINGS "Build Python bindings." OFF) # NOTE: on Unix systems, the correct library installation path diff --git a/include/kep3/core_astro/convert_julian_dates.hpp b/include/kep3/core_astro/convert_julian_dates.hpp index 0c81a9b1..67d97b37 100644 --- a/include/kep3/core_astro/convert_julian_dates.hpp +++ b/include/kep3/core_astro/convert_julian_dates.hpp @@ -7,11 +7,11 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef kep3_CONVERT_JULIAN_DATES_H -#define kep3_CONVERT_JULIAN_DATES_H +#ifndef CONVERT_JULIAN_DATES_HPP +#define CONVERT_JULIAN_DATES_HPP -#include #include "kep3/epoch.hpp" +#include namespace kep3 { @@ -21,12 +21,35 @@ namespace kep3 // inline double mjd2mjd2000(double in) { return (in - 51544); } // inline double mjd20002jd(double in) { return (in + 2451544.5); } // inline double mjd20002mjd(double in) { return (in + 51544); } - inline constexpr MJD2KClock::time_point jd2mjd(const MJD2KClock::time_point& in) { return in - 207360043200s; } - inline constexpr MJD2KClock::time_point jd2mjd2000(const MJD2KClock::time_point& in) { return in - 211813444800s; } - inline constexpr MJD2KClock::time_point mjd2jd(const MJD2KClock::time_point& in) { return in + 207360043200s; } - inline constexpr MJD2KClock::time_point mjd2mjd2000(const MJD2KClock::time_point& in) { return in - 4453401600s; } - inline constexpr MJD2KClock::time_point mjd20002jd(const MJD2KClock::time_point& in) { return in + 211813444800s; } - inline constexpr MJD2KClock::time_point mjd20002mjd(const MJD2KClock::time_point& in) { return in + 4453401600s; } + inline constexpr kep_clock::time_point jd2mjd( const kep_clock::time_point& in ) + { + return in - 207360043200s; + } + inline constexpr kep_clock::time_point + jd2mjd2000( const kep_clock::time_point& in ) + { + return in - 211813444800s; + } + inline constexpr kep_clock::time_point mjd2jd( const kep_clock::time_point& in ) + { + return in + 207360043200s; + } + inline constexpr kep_clock::time_point + mjd2mjd2000( const kep_clock::time_point& in ) + { + return in - 4453401600s; + } + inline constexpr kep_clock::time_point + mjd20002jd( const kep_clock::time_point& in ) + { + return in + 211813444800s; + } + inline constexpr kep_clock::time_point + mjd20002mjd( const kep_clock::time_point& in ) + { + return in + 4453401600s; + } + } // namespace kep3 -#endif // kep3_CONVERT_JULIAN_DATES_H +#endif // CONVERT_JULIAN_DATES_HPP diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 8e4f3400..0670a4c0 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -7,83 +7,60 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef EPOCH_HPP -#define EPOCH_HPP +#ifndef kep3_EPOCH_HPP +#define kep3_EPOCH_HPP #include -#include - -#include -#include -#include - #include #include +#include #include #include +#include +#include /// Keplerian Toolbox /** * This namespace contains astrodynamics and space flight mechanics routines * that are related to keplerian motions or models. */ +using namespace std::literals; +namespace chr = std::chrono; +using lint = long int; +using llint = long long int; +template +using dur = chr::duration>; + namespace kep3 { - using namespace std::literals; - namespace chr = std::chrono; - - // struct MJD2KClock - // { - - // using Clock = chr::system_clock; - // using rep = long long int; - // using period = typename Clock::period; - // using duration = typename Clock::duration; - // using time_point = typename chr::time_point; - - // static constexpr bool is_steady = Clock::is_steady; - // static constexpr typename Clock::time_point ref_epoch = - // chr::sys_days{ chr::year(2000) / chr::month(1) / chr::day(1) }; - - // static time_point now() { return time_point(Clock::now() - ref_epoch); } - - // static time_t to_time_t(const time_point& t) - // { - // return Clock::to_time_t(ref_epoch + t.time_since_epoch()); - // } - - // static time_point from_time_t(time_t t) - // { - // return time_point(Clock::from_time_t(t) - ref_epoch); - // } - // }; - struct MJD2KClock: public chr::system_clock + struct kep_clock : public chr::system_clock { - - using rep = long long int; - using period = std::ratio<1>; + using rep = int_fast64_t; + using period = std::ratio<1, 1'000'000>; using duration = chr::duration; - using time_point = chr::time_point; + using time_point = chr::time_point; static constexpr bool is_steady = false; - static constexpr chr::seconds unix_diff{ 946684800s }; + static constexpr chr::seconds y2k_offset{ 946684800s }; - static constexpr time_point ref_epoch{ MJD2KClock::time_point{} + unix_diff }; + static constexpr time_point ref_epoch{ kep_clock::time_point{} + y2k_offset }; - static std::time_t to_time_t(const time_point& t) noexcept + static std::time_t to_time_t( const time_point& t ) noexcept { - return std::time_t(chr::duration_cast(t.time_since_epoch() + unix_diff).count()); + return static_cast( + chr::duration_cast( t.time_since_epoch() + y2k_offset ) + .count() ); } - static time_point from_time_t(std::time_t t) noexcept + static time_point from_time_t( std::time_t t ) noexcept { - return chr::time_point_cast(time_point(chr::seconds(t) - unix_diff)); + return chr::time_point_cast( + time_point( chr::seconds( t ) - y2k_offset ) ); } }; - using namespace std::literals; /// epoch class. /** * This class defines and contains a non-gregorian date (i.e. a date expressed @@ -98,100 +75,150 @@ namespace kep3 */ class kep3_DLL_PUBLIC epoch { - public: + public: /** Types of non gregorian dates supported. Julian Date (JD) is the number of * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is * the number of days passed since November 17, 1858 at 00:00 am. The Modified * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, * 2000 at 00:00am. */ - enum class julian_type { MJD2000, MJD, JD }; + enum class julian_type + { + MJD2000, + MJD, + JD + }; /** Constructors */ - explicit epoch(const double epoch_in = 0.0, const julian_type epoch_type = julian_type::MJD2000); - explicit epoch(const int year, const int month, const int day, const int hour = 0, const int minute = 0, const int second = 0); - explicit epoch(const boost::posix_time::ptime& posix_time); + epoch( const double epoch_in = 0.0, + const julian_type epoch_type = julian_type::MJD2000 ); + + template + epoch( const dur& duration ) + : tp{ kep_clock::time_point{} + duration } + { + std::cout << "Constructor const & \n"; + } + + template + epoch( dur&& duration ) + : tp{ kep_clock::time_point{} + duration } + { + std::cout << "Constructor && \n"; + } + + epoch( const kep_clock::time_point& time_point ); + epoch( kep_clock::time_point&& time_point ); + + epoch( const int yr, const int mon, const int day, const int hr = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0 ); /** Computing non-gregorian dates */ - [[nodiscard]] MJD2KClock::time_point mjd2000() const; - [[nodiscard]] MJD2KClock::time_point jd() const; - [[nodiscard]] MJD2KClock::time_point mjd() const; + [[nodiscard]] kep_clock::time_point mjd2000() const; + [[nodiscard]] kep_clock::time_point jd() const; + [[nodiscard]] kep_clock::time_point mjd() const; /** Interface to boost::posix_time::ptime */ - [[nodiscard]] boost::posix_time::ptime get_posix_time() const; + // [[nodiscard]] boost::posix_time::ptime get_posix_time() const; - void set(const int year, const int month, const int day, const int hour = 0, - const int minute = 0, const int second = 0); - MJD2KClock::time_point make_tm(const int year, const int month, const int day, - const int hour = 0, const int minute = 0, const int second = 0); + static constexpr kep_clock::time_point make_tp( const int yr, const int mon, const int day, const int hr = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0 ); + static constexpr kep_clock::time_point make_tp( const double epoch_in, const julian_type epoch_type ); - // Calendar conversions - MJD2KClock::time_point tp_from_seconds(const double seconds) const; - MJD2KClock::time_point tp_from_days(const double days) const; - void set_tp_mjd2000(const double epoch_in); - void set_tp_mjd(const double epoch_in); - void set_tp_jd(const double epoch_in); + // Conversions + // double tp_from_seconds(const double seconds) const; + static constexpr kep_clock::time_point tp_from_days( const double days ); + // void set_tp_mjd2000( const double epoch_in ); + // void set_tp_mjd( const double epoch_in ); + // void set_tp_jd( const double epoch_in ); // Duration conversions - MJD2KClock::rep as_sec(); - double as_days(); + static constexpr double as_sec( kep_clock::duration d ) + { + return std::chrono::duration( d ) + .count(); + } + // double as_days(); // Printing - static const char* as_utc_string(const MJD2KClock::time_point&); - static std::time_t as_gmtime(const MJD2KClock::time_point&); + static const char* as_utc_string( const kep_clock::time_point& ); + // static std::time_t as_gmtime(const kep_clock::time_point &); - /** operators overloads for sum diff (epoch-days) and the comparison + /** operator overloads for sum and diff (epoch-days) and comparison * operators * **/ - std::chrono::seconds day2sec(const double days) const; - kep3_DLL_PUBLIC epoch epoch_from_string(const std::string& date); - kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string& date); - - kep3_DLL_PUBLIC friend std::ostream& operator<<(std::ostream& s, epoch const& epoch_in); - template> - kep3_DLL_PUBLIC friend epoch& operator+=(epoch& ep, T rhs); - template> - kep3_DLL_PUBLIC friend epoch& operator-=(epoch& ep, T rhs); - kep3_DLL_PUBLIC friend bool operator>(const epoch& c1, const epoch& c2); - kep3_DLL_PUBLIC friend bool operator<(const epoch& c1, const epoch& c2); - kep3_DLL_PUBLIC friend bool operator>=(const epoch& c1, const epoch& c2); - kep3_DLL_PUBLIC friend bool operator<=(const epoch& c1, const epoch& c2); - kep3_DLL_PUBLIC friend bool operator==(const epoch& c1, const epoch& c2); - kep3_DLL_PUBLIC friend bool operator!=(const epoch& c1, const epoch& c2); - template> - kep3_DLL_PUBLIC friend epoch operator+(const epoch& lhs, T rhs); - template> - kep3_DLL_PUBLIC friend epoch operator-(const epoch& lhs, T rhs); - kep3_DLL_PUBLIC friend MJD2KClock::rep operator-(const epoch lhs, const epoch rhs); - - private: + // std::chrono::seconds day2sec(const double days) const; + // kep3_DLL_PUBLIC epoch epoch_from_string(const std::string &date); + // kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string &date); + + kep3_DLL_PUBLIC friend std::ostream& operator<<( std::ostream& s, + epoch const& epoch_in ); + template + kep3_DLL_PUBLIC epoch& operator+=( dur&& duration ) + { + /* addition of rhs to *this takes place here */ + tp += chr::duration_cast( duration ); + return *this; + } + template + kep3_DLL_PUBLIC epoch& operator-=( dur&& duration ) + { + /* addition of rhs to *this takes place here */ + tp -= chr::duration_cast( duration ); + return *this; + } + + kep3_DLL_PUBLIC friend bool operator>( const epoch& c1, const epoch& c2 ); + kep3_DLL_PUBLIC friend bool operator<( const epoch& c1, const epoch& c2 ); + kep3_DLL_PUBLIC friend bool operator>=( const epoch& c1, const epoch& c2 ); + kep3_DLL_PUBLIC friend bool operator<=( const epoch& c1, const epoch& c2 ); + kep3_DLL_PUBLIC friend bool operator==( const epoch& c1, const epoch& c2 ); + kep3_DLL_PUBLIC friend bool operator!=( const epoch& c1, const epoch& c2 ); + // template + // kep3_DLL_PUBLIC friend epoch operator+( const epoch& lhs, dur&& rhs ); + // template + // kep3_DLL_PUBLIC friend epoch operator-( const epoch& lhs, dur&& rhs ); + + template + kep3_DLL_PUBLIC epoch operator+( dur&& duration ) + { + return epoch( tp + chr::duration_cast( duration ) ); + } + template + kep3_DLL_PUBLIC epoch operator-( dur&& duration ) + { + std::cout << "operator-()\n"; + return epoch( tp - chr::duration_cast( duration ) ); + } + + kep3_DLL_PUBLIC friend kep_clock::duration operator-( const epoch lhs, const epoch rhs ); + + kep3_DLL_PUBLIC epoch operator=( const epoch& ep ) + { + std::cout << "operator=()\n"; + return { ep.tp }; + } + // kep3_DLL_PUBLIC friend epoch& operator=( epoch&& ep ); + + private: // Serialization code friend class boost::serialization::access; - template void serialize(Archive& ar, const unsigned int) + template + void serialize( Archive& ar, const unsigned int ) { - ar& m_mjd2000; + ar&( *this ); } // Serialization code (END) /// the modified julian date 2000 stored in a double - double m_mjd2000; - MJD2KClock::time_point tp; + // double m_mjd2000; + kep_clock::time_point tp; }; - // kep3_DLL_PUBLIC bool operator>(const epoch& c1, const epoch& c2); - // kep3_DLL_PUBLIC bool operator<(const epoch& c1, const epoch& c2); - // kep3_DLL_PUBLIC bool operator>=(const epoch& c1, const epoch& c2); - // kep3_DLL_PUBLIC bool operator<=(const epoch& c1, const epoch& c2); - // kep3_DLL_PUBLIC bool operator==(const epoch& c1, const epoch& c2); - // kep3_DLL_PUBLIC bool operator!=(const epoch& c1, const epoch& c2); - // template> - // kep3_DLL_PUBLIC epoch operator+(const epoch& lhs, T rhs); - // template> - // kep3_DLL_PUBLIC epoch operator-(const epoch& lhs, T rhs); - // kep3_DLL_PUBLIC MJD2KClock::rep operator-(const epoch lhs, const epoch rhs); } // end of namespace kep3 -template <> struct fmt::formatter: ostream_formatter {}; +template <> +struct fmt::formatter : fmt::ostream_formatter +{ +}; -#endif // EPOCH_HPP +#endif // kep3_EPOCH_HPP diff --git a/include/kep3/planets/keplerian.hpp b/include/kep3/planets/keplerian.hpp index e8ef6434..55fba10a 100644 --- a/include/kep3/planets/keplerian.hpp +++ b/include/kep3/planets/keplerian.hpp @@ -52,7 +52,7 @@ class kep3_DLL_PUBLIC keplerian { explicit keplerian(const epoch &ref_epoch, const std::array &par, double mu_central_body = 1., std::string name = "Unknown", std::array added_params = {-1., -1., -1.}); - explicit keplerian(const epoch &ref_epoch = kep3::epoch(0), + explicit keplerian(const epoch &ref_epoch = kep3::epoch(), const std::array, 2> &pos_vel = {{{1.0, 0.0, 0.0}, {0., 1.0, 0.0}}}, double mu_central_body = 1., std::string name = "Unknown", diff --git a/src/epoch.cpp b/src/epoch.cpp index 146f50ca..39305b6e 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -7,124 +7,90 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include +#include #include #include #include #include #include +#include #include "kep3/core_astro/convert_julian_dates.hpp" #include "kep3/epoch.hpp" -// This is set to the precision of the boost date library (microseconds is -// default, nanoseconds can be set when compiling boosts. Note that the code has -// not been checked in that case) -#define BOOST_DATE_PRECISION 1e-6 - namespace kep3 { - using ::boost::gregorian::date; - using ::boost::gregorian::greg_day; - using ::boost::gregorian::greg_month; - using ::boost::gregorian::greg_year; - using ::boost::posix_time::from_iso_string; - using ::boost::posix_time::ptime; - using ::boost::posix_time::time_duration; - using ::boost::posix_time::time_from_string; - - using namespace std::literals; /// Constructor. /** * Constructs an epoch from a non-gregorian date. * \param[in] epoch_in A double indicating the non-gregorian date * \param[in] epoch_type One of [epoch::julian_type::MJD2000, - * epoch::julian_type::MJD, epoch::julian_type::JD] + * \param[in] epoch_type epoch::julian_type::MJD2000 */ - epoch::epoch(const double epoch_in, const julian_type epoch_type) - : - m_mjd2000(epoch_in) + epoch::epoch( const double epoch_in, const julian_type epoch_type ) + : tp{ make_tp( epoch_in, epoch_type ) } + { - switch (epoch_type) - { - case julian_type::MJD2000: - set_tp_mjd2000(epoch_in); - break; - case julian_type::MJD: - set_tp_mjd(epoch_in); - break; - case julian_type::JD: - set_tp_jd(epoch_in); - break; - default: - throw; - } } /// Constructor. /** * Constructs an epoch from a gregorian date. The time of the day is assumed to - * be midnight. \param[in] year The gregorian year \param[in] month The month of - * the year \param[in] day The day of the month + * be midnight. \param[in] yr The gregorian year \param[in] mon The month of the + * year [0-11] \param[in] day The day of the month [1-31] \param[in] hr The hour + * of the day [0-23] \param[in] min The minutes [0-59] \param[in] s The seconds + * [0-59] \param[in] ms The milliseconds [0-999] \param[in] us The milliseconds + * [0-999] */ - epoch::epoch(const int year, const int month, const int day, - const int hour, const int minute, const int second) - : - m_mjd2000(0), - tp(make_tm(year, month, day, hour, minute, second)) + epoch::epoch( const int yr, const int mon, const int day, const int hr, const int min, const int s, const int ms, const int us ) + : tp{ make_tp( yr, mon, day, hr, min, s, ms, us ) } { } /// Constructor. /** - * Constructs an epoch from a boost ptime object (posix time) - * \param[in] posix_time The posix_time + * Constructs an epoch from a std::chrono::duration. + * The reference point is assumed to be MJD 0. + * \param[in] time The time as a duration */ - epoch::epoch(const boost::posix_time::ptime& posix_time) + // template + // epoch::epoch( const dur& time ) + // : tp{ kep_clock::time_point( T( time ) ) } + // { + // } + + epoch::epoch( const kep_clock::time_point& time_point ) + : tp{ time_point } { - - time_duration dt = posix_time - ptime(date(2000, 1, 1)); - bool flag = false; - if (dt.is_negative()) - { - flag = true; - dt = dt.invert_sign(); - } - const double fr_secs = - static_cast(dt.fractional_seconds()) * BOOST_DATE_PRECISION; - m_mjd2000 = static_cast(dt.hours()) / 24.0 + - static_cast(dt.minutes()) / 1440.0 + - (static_cast(dt.seconds()) + fr_secs) / 86400.0; - - // NOTE: Why not this? - // m_mjd2000 = dt.total_seconds() / 86400.0; - if (flag) - { - m_mjd2000 = -m_mjd2000; - } - - tp = tp_from_seconds(flag ? -dt.total_seconds() : dt.total_seconds()); - // std::cout << "Posix time: " << posix_time << "\n"; - // std::cout << "Time point : " << epoch::as_utc_string(tp) << "\n"; } - MJD2KClock::time_point epoch::make_tm(const int year, const int month, const int day, - const int hr, const int min, const int sec) + epoch::epoch( kep_clock::time_point&& time_point ) + : tp{ std::move( time_point ) } { - std::tm t{}; - t.tm_year = year - 1900; - t.tm_mon = month - 1; - t.tm_mday = day; - t.tm_hour = hr; - t.tm_min = min; - t.tm_sec = sec; - auto tm{ std::mktime(&t) }; - auto utctm{ std::gmtime(&tm) }; + } - return MJD2KClock::from_time_t(std::mktime(utctm)); + constexpr kep_clock::time_point epoch::make_tp( const int yr, const int mon, const int day, const int hr, const int min, const int s, const int ms, const int us ) + { + return kep_clock::time_point{} + chr::years( yr ) + chr::months( mon ) + + chr::days( day ) + chr::hours( hr ) + chr::minutes( min ) + chr::seconds( s ) + + chr::milliseconds( ms ) + chr::microseconds( us ); } + constexpr kep_clock::time_point epoch::make_tp( const double epoch_in, const julian_type epoch_type ) + { + switch ( epoch_type ) + { + case julian_type::MJD2000: + return epoch::tp_from_days( epoch_in ); + case julian_type::MJD: + return mjd2mjd2000( epoch::tp_from_days( epoch_in ) ); + case julian_type::JD: + return jd2mjd2000( epoch::tp_from_days( epoch_in ) ); + default: + throw; + } + } /// jd getter. /** * Returns the julian date @@ -132,8 +98,10 @@ namespace kep3 * @return double containing the julian date * */ - // double epoch::jd() const { return mjd20002jd(m_mjd2000); } - MJD2KClock::time_point epoch::jd() const { return mjd20002jd(tp); } + kep_clock::time_point epoch::jd() const + { + return mjd20002jd( tp ); + } /// mjd getter. /** @@ -142,14 +110,20 @@ namespace kep3 * @return double containing the modified julian date * */ - MJD2KClock::time_point epoch::mjd() const { return mjd20002mjd(tp); } + kep_clock::time_point epoch::mjd() const + { + return mjd20002mjd( tp ); + } /// mjd2000 getter. /** * Gets the modified julian date 2000 * @return const reference to mjd2000 */ - MJD2KClock::time_point epoch::mjd2000() const { return tp; } + kep_clock::time_point epoch::mjd2000() const + { + return tp; + } /// Extracts the posix time /** @@ -161,126 +135,67 @@ namespace kep3 * @return ptime containing the posix time * */ - ptime epoch::get_posix_time() const - { - long hrs = 0., min = 0., sec = 0., fsec = 0.; - bool flag = false; - double copy = m_mjd2000; - if (copy < 0) - { - copy = -copy; - flag = true; - } - hrs = static_cast(copy * 24); - min = static_cast((copy * 24 - static_cast(hrs)) * 60); - sec = static_cast((((copy * 24 - static_cast(hrs)) * 60) - - static_cast(min)) * 60); - const double dblfsec = ((((copy * 24 - static_cast(hrs)) * 60) - - static_cast(min)) * 60) - - static_cast(sec); - std::ostringstream fsecstr; - fsecstr << std::setiosflags(std::ios::fixed) - << std::setprecision( - -static_cast(std::log10(BOOST_DATE_PRECISION))) - << dblfsec; - fsec = boost::lexical_cast(fsecstr.str().substr( - 2, static_cast(-std::log10(BOOST_DATE_PRECISION) + 1))); - ptime retval; - if (flag) - { - retval = ptime(date(2000, 1, 1), time_duration(-hrs, -min, -sec, -fsec)); - } - else - { - retval = ptime(date(2000, 1, 1), time_duration(hrs, min, sec, fsec)); - } - - ptime temp_pt = boost::posix_time::from_time_t(MJD2KClock::to_time_t(tp)); - - return temp_pt; - } - - /// Sets the epoch from a posix time - /** - * Sets the epoch to a particular posix_time. - * - * \param[in] posix_time containing the posix time - * - */ - void epoch::set(const int year, const int month, const int day, - const int hour, const int minute, const int second) - { - tp = make_tm(year, month, day, hour, minute, second); - } - - MJD2KClock::time_point epoch::tp_from_seconds(const double seconds) const - { - return MJD2KClock::time_point{} + chr::round(chr::duration>(seconds)); - } - MJD2KClock::time_point epoch::tp_from_days(const double days) const - { - return MJD2KClock::time_point{} + day2sec(days); - } - - std::chrono::seconds epoch::day2sec(const double days) const - { - return chr::round(chr::duration>(days)); - } - - void epoch::set_tp_mjd2000(const double days) - { - tp = tp_from_days(days); - std::cout << days << " days in MJD2000: " << epoch::as_utc_string(tp); - } - void epoch::set_tp_mjd(const double days) - { - tp = mjd2mjd2000(tp_from_days(days)); - std::cout << days << " days in MJD: " << epoch::as_utc_string(tp); - } - void epoch::set_tp_jd(const double days) - { - tp = jd2mjd2000(tp_from_days(days)); - std::cout << days << " in JD: " << epoch::as_utc_string(tp); - } + // kep_clock::duration epoch::tp_from_seconds(const double seconds) const { + // return chr::duration_cast(chr::seconds(seconds)); + // } - MJD2KClock::rep epoch::as_sec() + constexpr kep_clock::time_point epoch::tp_from_days( const double days ) { - return tp.time_since_epoch().count(); - } - double epoch::as_days() - { - return std::chrono::duration>(tp.time_since_epoch()).count(); + return kep_clock::time_point{} + + chr::duration_cast( + chr::duration>( days ) ); } - std::time_t epoch::as_gmtime(const MJD2KClock::time_point& tp) - { - auto tt{ MJD2KClock::to_time_t(tp) }; - auto utc = std::gmtime(&tt); - return std::mktime(utc); - } + // void epoch::set_tp_mjd2000( const double days ) + // { + // // tp = tp_from_days( days ); + // // std::cout << days << " days in MJD2000: " << epoch::as_utc_string( tp ); + // } + // void epoch::set_tp_mjd( const double days ) + // { + // // tp = mjd2mjd2000( tp_from_days( days ) ); + // // std::cout << days << " days in MJD: " << epoch::as_utc_string( tp ); + // } + // void epoch::set_tp_jd( const double days ) + // { + // // tp = jd2mjd2000( tp_from_days( days ) ); + // // std::cout << days << " in JD: " << epoch::as_utc_string( tp ); + // } + + // double epoch::as_days() { + // return std::chrono::duration( + // tp.time_since_epoch()) + // .count(); + // } - const char* epoch::as_utc_string(const MJD2KClock::time_point& tp) - { - auto tm = epoch::as_gmtime(tp); - return std::ctime(&tm); - } + // std::time_t epoch::as_gmtime(const kep_clock::time_point &tp) { + // auto tt{kep_clock::to_time_t(tp)}; + // auto utc = std::gmtime(&tt); + // return std::mktime(utc); + // } - template> - epoch& operator+=(epoch& ep, T rhs) + const char* epoch::as_utc_string( const kep_clock::time_point& tp ) { - /* addition of rhs to *this takes place here */ - ep.tp += rhs; - return ep; // return the result by reference + auto t = kep_clock::to_time_t( tp ); + return asctime( gmtime( &t ) ); } - template> - epoch& operator-=(epoch& ep, T rhs) - { - /* addition of rhs to *this takes place here */ - ep.tp -= rhs; - return ep; // return the result by reference - } + // template + // epoch& epoch::operator+=( dur&& rhs ) + // { + // /* addition of rhs to *this takes place here */ + // tp += chr::duration_cast( rhs ); + // return *this; + // } + + // template + // epoch& epoch::operator-=( dur&& rhs ) + // { + // /* addition of rhs to *this takes place here */ + // tp -= chr::duration_cast( rhs ); + // return *this; + // } /// Returns an epoch constructed from a delimited string containing a date /** @@ -293,10 +208,9 @@ namespace kep3 * epoch e(epoch_from_string(ts)) * */ - epoch epoch_from_string(const std::string& date) - { - return epoch(time_from_string(date)); - } + // epoch epoch_from_string(const std::string &date) { + // return epoch(time_from_string(date)); + // } /// Returns an epoch constructed from a non delimited iso string containing a /// date @@ -308,10 +222,9 @@ namespace kep3 * epoch e(epoch_from_iso_string(ts)) * */ - epoch epoch_from_iso_string(const std::string& date) - { - return epoch(from_iso_string(date)); - } + // epoch epoch_from_iso_string(const std::string &date) { + // return epoch(from_iso_string(date)); + // } /// Overload the stream operator for kep_toolbox::epoch /** @@ -323,51 +236,55 @@ namespace kep3 * \return reference to s * */ - std::ostream& operator<<(std::ostream& s, const epoch& ep) + std::ostream& operator<<( std::ostream& s, const epoch& ep ) { - s << epoch::as_utc_string(ep.tp); + s << epoch::as_utc_string( ep.tp ); return s; } - bool operator>(const epoch& c1, const epoch& c2) + + bool operator>( const epoch& c1, const epoch& c2 ) { return c1.tp > c2.tp; } - bool operator<(const epoch& c1, const epoch& c2) + bool operator<( const epoch& c1, const epoch& c2 ) { return c1.tp < c2.tp; } - bool operator>=(const epoch& c1, const epoch& c2) + bool operator>=( const epoch& c1, const epoch& c2 ) { return c1.tp >= c2.tp; } - bool operator<=(const epoch& c1, const epoch& c2) + bool operator<=( const epoch& c1, const epoch& c2 ) { return c1.tp <= c2.tp; } - bool operator==(const epoch& c1, const epoch& c2) + bool operator==( const epoch& c1, const epoch& c2 ) { return c1.tp == c2.tp; } - bool operator!=(const epoch& c1, const epoch& c2) + bool operator!=( const epoch& c1, const epoch& c2 ) { return c1.tp != c2.tp; } - // template> - // epoch operator+(const epoch& lhs, T rhs) - // { - // lhs += rhs; // reuse compound assignment - // return lhs; // return the result by value (uses move constructor) - // } - // template> - // epoch operator-(const epoch& lhs, T rhs) - // { - // lhs -= rhs; // reuse compound assignment - // return lhs; // return the result by value (uses move constructor) - // } - MJD2KClock::rep operator-(const epoch lhs, const epoch rhs) + // template + // epoch operator+( const epoch& lhs, dur&& rhs ) + // { + // lhs.tp += + // chr::duration_cast( rhs ); // reuse compound assignment + // return lhs; // return the result by value (uses move constructor) + // } + // template + // epoch operator-( const epoch& lhs, dur&& rhs ) + // { + // lhs.tp -= + // chr::duration_cast( rhs ); // reuse compound assignment + // return lhs; // return the result by value (uses move constructor) + // } + + kep_clock::duration operator-( const epoch lhs, const epoch rhs ) { - return (lhs - rhs); // return the result by value (uses move constructor) + return lhs.tp - rhs.tp; } } // namespace kep3 diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index acc9544d..4023d77f 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -7,6 +7,7 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +#include #include #include @@ -22,103 +23,94 @@ #include #include -namespace kep3::udpla -{ +namespace kep3::udpla { - keplerian::keplerian(const epoch& ref_epoch, - const std::array, 2>& pos_vel, - double mu_central_body, std::string name, - std::array added_params) +keplerian::keplerian(const epoch &ref_epoch, + const std::array, 2> &pos_vel, + double mu_central_body, std::string name, + std::array added_params) : m_ref_epoch(ref_epoch), m_name(std::move(name)), - m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), - m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), - m_pos_vel_0(pos_vel) - { - double R = + m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), + m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), + m_pos_vel_0(pos_vel) { + double R = std::sqrt(pos_vel[0][0] * pos_vel[0][0] + pos_vel[0][1] * pos_vel[0][1] + pos_vel[0][2] * pos_vel[0][2]); - double en = (pos_vel[1][0] * pos_vel[1][0] + pos_vel[1][1] * pos_vel[1][1] + - pos_vel[1][2] * pos_vel[1][2]) / - 2. - - mu_central_body / R; - (en > 0) ? m_ellipse = false : m_ellipse = true; - } - - keplerian::keplerian(const epoch& ref_epoch, const std::array& par, - double mu_central_body, std::string name, - std::array added_params) + double en = (pos_vel[1][0] * pos_vel[1][0] + pos_vel[1][1] * pos_vel[1][1] + + pos_vel[1][2] * pos_vel[1][2]) / + 2. - + mu_central_body / R; + (en > 0) ? m_ellipse = false : m_ellipse = true; +} + +keplerian::keplerian(const epoch &ref_epoch, const std::array &par, + double mu_central_body, std::string name, + std::array added_params) : m_ref_epoch(ref_epoch), m_name(std::move(name)), - m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), - m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), - m_pos_vel_0() - { - - if (par[0] * (1 - par[1]) <= 0) - { - throw std::domain_error( - "A Keplerian planet constructor was called with with non compatible " - "a,e:" - "The following must hold: a<0 -> e>1 [a>0 -> e<1]."); - } - m_pos_vel_0 = kep3::par2ic(par, mu_central_body); - (par[0] < 0) ? m_ellipse = false : m_ellipse = true; + m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), + m_radius(added_params[1]), m_ellipse(), m_safe_radius(added_params[2]), + m_pos_vel_0() { + + if (par[0] * (1 - par[1]) <= 0) { + throw std::domain_error( + "A Keplerian planet constructor was called with with non compatible " + "a,e:" + "The following must hold: a<0 -> e>1 [a>0 -> e<1]."); } + m_pos_vel_0 = kep3::par2ic(par, mu_central_body); + (par[0] < 0) ? m_ellipse = false : m_ellipse = true; +} - std::array, 2> - keplerian::eph(const kep3::epoch& ep) const - { - // 1 - We compute the dt - auto dt = (ep - m_ref_epoch); - // 2 - We propagate (make a copy as we do not want to change m_pos_vel_0) - auto retval(m_pos_vel_0); - kep3::propagate_lagrangian(retval, dt, m_mu_central_body); - return retval; - } +std::array, 2> +keplerian::eph(const kep3::epoch &ep) const { + // 1 - We compute the dt + auto dt = epoch::as_sec(ep - m_ref_epoch); + // 2 - We propagate (make a copy as we do not want to change m_pos_vel_0) + auto retval(m_pos_vel_0); + kep3::propagate_lagrangian(retval, dt, m_mu_central_body); + return retval; +} + +std::string keplerian::get_name() const { return m_name; } + +double keplerian::get_mu_central_body() const { return m_mu_central_body; } + +double keplerian::get_mu_self() const { return m_mu_self; } - std::string keplerian::get_name() const { return m_name; } - - double keplerian::get_mu_central_body() const { return m_mu_central_body; } - - double keplerian::get_mu_self() const { return m_mu_self; } - - double keplerian::get_radius() const { return m_radius; } - - double keplerian::get_safe_radius() const { return m_safe_radius; } - - kep3::epoch keplerian::get_ref_epoch() const { return m_ref_epoch; } - - std::array keplerian::elements(kep3::elements_type el_type) const - { - std::array retval{}; - switch (el_type) - { - case kep3::elements_type::KEP_F: - retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); - break; - case kep3::elements_type::KEP_M: - if (!m_ellipse) - { - throw std::logic_error("Mean anomaly is only available for ellipses."); - } - retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); - retval[5] = kep3::f2m(retval[5], retval[1]); - break; - case kep3::elements_type::MEQ: - retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body); - break; - case kep3::elements_type::MEQ_R: - retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body, true); - break; - default: - throw std::logic_error("You should not go here!"); +double keplerian::get_radius() const { return m_radius; } + +double keplerian::get_safe_radius() const { return m_safe_radius; } + +kep3::epoch keplerian::get_ref_epoch() const { return m_ref_epoch; } + +std::array keplerian::elements(kep3::elements_type el_type) const { + std::array retval{}; + switch (el_type) { + case kep3::elements_type::KEP_F: + retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); + break; + case kep3::elements_type::KEP_M: + if (!m_ellipse) { + throw std::logic_error("Mean anomaly is only available for ellipses."); } - return retval; + retval = kep3::ic2par(m_pos_vel_0, m_mu_central_body); + retval[5] = kep3::f2m(retval[5], retval[1]); + break; + case kep3::elements_type::MEQ: + retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body); + break; + case kep3::elements_type::MEQ_R: + retval = kep3::ic2eq(m_pos_vel_0, m_mu_central_body, true); + break; + default: + throw std::logic_error("You should not go here!"); } + return retval; +} - std::string keplerian::get_extra_info() const - { - auto par = elements(); - std::string retval = +std::string keplerian::get_extra_info() const { + auto par = elements(); + std::string retval = fmt::format("Keplerian planet elements: \n") + fmt::format("Semi major axis (AU): {}\n", par[0] / kep3::AU) + fmt::format("Eccentricity: {}\n", par[1]) + @@ -126,25 +118,23 @@ namespace kep3::udpla fmt::format("Big Omega (deg.): {}\n", par[3] * kep3::RAD2DEG) + fmt::format("Small omega (deg.): {}\n", par[4] * kep3::RAD2DEG) + fmt::format("True anomly (deg.): {}\n", par[5] * kep3::RAD2DEG); - if (m_ellipse) - { - retval += fmt::format("Mean anomly (deg.): {}\n", - kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); - } - retval += fmt::format("Elements reference epoch (MJD2000): {}\n", - m_ref_epoch.mjd2000().time_since_epoch().count()) + - fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + - fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + - fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); - return retval; - } - - std::ostream& operator<<(std::ostream& os, - const kep3::udpla::keplerian& udpla) - { - os << udpla.get_extra_info() << std::endl; - return os; + if (m_ellipse) { + retval += fmt::format("Mean anomly (deg.): {}\n", + kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); } + retval += fmt::format("Elements reference epoch (MJD2000): {}\n", + m_ref_epoch.mjd2000().time_since_epoch().count()) + + fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + + fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + + fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); + return retval; +} + +std::ostream &operator<<(std::ostream &os, + const kep3::udpla::keplerian &udpla) { + os << udpla.get_extra_info() << std::endl; + return os; +} } // namespace kep3::udpla diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp index 9f04e7c9..53422705 100644 --- a/test/epoch_test_chrono.cpp +++ b/test/epoch_test_chrono.cpp @@ -19,69 +19,90 @@ #include "catch.hpp" using kep3::epoch; +using kep3::kep_clock; // using kep3::epoch_from_iso_string; // using kep3::epoch_from_string; -using boost::gregorian::date; -using boost::posix_time::ptime; - +// using boost::gregorian::date; +// using boost::posix_time::ptime; using namespace std::literals; -TEST_CASE("construct") +TEST_CASE( "construct" ) { - // test syntax - REQUIRE_NOTHROW(epoch()); - REQUIRE_NOTHROW(epoch(123.456)); - REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD2000)); - REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::JD)); - REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::JD)); - REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::MJD)); - REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD)); - REQUIRE_NOTHROW(epoch(2034, 12, 31)); - // // > 2000 - boost::posix_time::ptime posix_time_test(date(2034, 12, 31)); - REQUIRE_NOTHROW(epoch(posix_time_test)); - REQUIRE(epoch(posix_time_test).get_posix_time() == posix_time_test); - std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << "\n"; - std::cout << "Boost1: " << posix_time_test << "\n"; - - // // < 2000 - boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); - REQUIRE_NOTHROW(epoch(posix_time_test2)); - REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); - std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << "\n"; - std::cout << "Boost2: " << posix_time_test2 << "\n"; + // test syntax + // // > 2000 + REQUIRE_NOTHROW( epoch() ); + REQUIRE_NOTHROW( epoch( 123.456 ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD2000 ) ); + REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( 2034, 12, 31, 11, 36, 21, 121, 841 ) ); + // // > 2000 + // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); + // REQUIRE_NOTHROW( epoch( posix_time_test ) ); + // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); + // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << + // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; - // // test conversions - REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); - REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); - std::cout << "Chrono3: " << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << "\n"; - std::cout << "Chrono3-1: " << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << "\n"; - REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); + // // < 2000 + // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); + // REQUIRE_NOTHROW(epoch(posix_time_test2)); + // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); + // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << + // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; + // // test conversions + // REQUIRE(epoch(123.456).mjd2000() == + // epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); + // REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); + // REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); + // std::cout << "Chrono3: " + // << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << + // "\n"; + // std::cout << "Chrono3-1: " + // << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << + // "\n"; + // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } -// TEST_CASE("epoch_operators") -// { -// REQUIRE(epoch(0.) == epoch(0.)); -// REQUIRE(epoch(0.) != epoch(1.)); -// REQUIRE(epoch(1.) > epoch(0.)); -// REQUIRE(epoch(1.) >= epoch(1.)); -// REQUIRE(epoch(1.) >= epoch(0.)); -// REQUIRE(epoch(0.) < epoch(1.)); -// REQUIRE(epoch(1.) <= epoch(1.)); -// epoch today(0.); -// today += 100.; -// REQUIRE(today == epoch(100.)); -// today -= 100.; -// REQUIRE(today == epoch(0.)); -// auto yesterday = today - 1.; -// REQUIRE(yesterday == epoch(-1.)); -// today = yesterday + 1; -// REQUIRE(today == epoch(0.)); -// REQUIRE(today - yesterday == 1.); -// REQUIRE_NOTHROW((std::cout << epoch())); -// } +TEST_CASE( "epoch_operators" ) +{ + REQUIRE( epoch( 2034, 12, 10 ) == epoch( 2034, 12, 10 ) ); + REQUIRE( epoch( 2034, 12, 10 ) != epoch( 2034, 12, 11 ) ); + // Testing us precision + REQUIRE( epoch( 2034, 12, 10 ) != epoch( 2034, 12, 10, 0, 0, 0, 0, 1 ) ); + // Check that ns precision is not supported + REQUIRE( epoch( 0, 12, 10 ) == + epoch( 0, 12, 10, 0, 0, 0, 0, 0 ) + 100ns ); + + // Conversion from double (defaults to days) + REQUIRE( epoch( 1. ) > epoch( 0. ) ); + REQUIRE( epoch( 1. ) >= epoch( 1. ) ); + REQUIRE( epoch( 1. ) >= epoch( 0. ) ); + REQUIRE( epoch( 0. ) < epoch( 1. ) ); + REQUIRE( epoch( 1. ) <= epoch( 1. ) ); + epoch today( 0. ); + today += chr::days( 100 ); + REQUIRE( today == epoch( 0, 0, 100 ) ); + today -= chr::duration_cast( chr::days( 100 ) ); + REQUIRE( today == epoch() ); + auto oneday = chr::days( 1 ); + std::cout << "Type of oneday: " << typeid( oneday ).name() << "\n"; + auto yesterday = today - chr::duration_cast( oneday ); + std::cout << "Type of yesterday: " << typeid( yesterday ).name() << "\n"; + auto yesterday1 = today - oneday; + std::cout << "Type of yesterday1: " << typeid( yesterday1 ).name() << "\n"; + + REQUIRE( yesterday == epoch( 0, 0, -1 ) ); + today = yesterday + chr::duration_cast( chr::days( 1 ) ); + REQUIRE( today == epoch() ); + auto diff{ today - yesterday }; + std::cout << diff << "\n"; + REQUIRE( diff == chr::duration_cast( chr::days( 1 ) ) ); + std::cout << "Type of diff: " << typeid( diff ).name() << "\n"; + REQUIRE_NOTHROW( ( std::cout << epoch() ) ); +} // TEST_CASE("conversions_from_string") { // { diff --git a/test/planet_test.cpp b/test/planet_test.cpp index 8b3348c9..f967d6fc 100644 --- a/test/planet_test.cpp +++ b/test/planet_test.cpp @@ -12,12 +12,12 @@ #include +#include "catch.hpp" +#include #include #include #include -#include "catch.hpp" - using kep3::epoch; using kep3::planet; using kep3::detail::is_udpla; @@ -345,9 +345,9 @@ TEST_CASE("generic_assignment") { TEST_CASE("type_index") { planet p0 = planet{null_udpla{}}; - //REQUIRE(p0.get_type_index() == std::type_index(typeid(null_udpla))); - //p0 = planet{simple_udpla{}}; - //REQUIRE(p0.get_type_index() == std::type_index(typeid(simple_udpla))); + // REQUIRE(p0.get_type_index() == std::type_index(typeid(null_udpla))); + // p0 = planet{simple_udpla{}}; + // REQUIRE(p0.get_type_index() == std::type_index(typeid(simple_udpla))); } TEST_CASE("get_ptr") { From 5b26a0c23af8b4a4f6599e0ae650011d7e2eb34b Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Fri, 29 Sep 2023 14:07:32 +0200 Subject: [PATCH 05/30] Chrono migration - cleanup --- include/kep3/epoch.hpp | 4 ---- test/epoch_test_chrono.cpp | 5 ----- 2 files changed, 9 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 0670a4c0..1b667925 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -97,14 +97,12 @@ namespace kep3 epoch( const dur& duration ) : tp{ kep_clock::time_point{} + duration } { - std::cout << "Constructor const & \n"; } template epoch( dur&& duration ) : tp{ kep_clock::time_point{} + duration } { - std::cout << "Constructor && \n"; } epoch( const kep_clock::time_point& time_point ); @@ -186,7 +184,6 @@ namespace kep3 template kep3_DLL_PUBLIC epoch operator-( dur&& duration ) { - std::cout << "operator-()\n"; return epoch( tp - chr::duration_cast( duration ) ); } @@ -194,7 +191,6 @@ namespace kep3 kep3_DLL_PUBLIC epoch operator=( const epoch& ep ) { - std::cout << "operator=()\n"; return { ep.tp }; } // kep3_DLL_PUBLIC friend epoch& operator=( epoch&& ep ); diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp index 53422705..1b1cbddf 100644 --- a/test/epoch_test_chrono.cpp +++ b/test/epoch_test_chrono.cpp @@ -88,19 +88,14 @@ TEST_CASE( "epoch_operators" ) today -= chr::duration_cast( chr::days( 100 ) ); REQUIRE( today == epoch() ); auto oneday = chr::days( 1 ); - std::cout << "Type of oneday: " << typeid( oneday ).name() << "\n"; auto yesterday = today - chr::duration_cast( oneday ); - std::cout << "Type of yesterday: " << typeid( yesterday ).name() << "\n"; auto yesterday1 = today - oneday; - std::cout << "Type of yesterday1: " << typeid( yesterday1 ).name() << "\n"; REQUIRE( yesterday == epoch( 0, 0, -1 ) ); today = yesterday + chr::duration_cast( chr::days( 1 ) ); REQUIRE( today == epoch() ); auto diff{ today - yesterday }; - std::cout << diff << "\n"; REQUIRE( diff == chr::duration_cast( chr::days( 1 ) ) ); - std::cout << "Type of diff: " << typeid( diff ).name() << "\n"; REQUIRE_NOTHROW( ( std::cout << epoch() ) ); } From ed69a914215505978d8e4fe7956207c4dd50085b Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Fri, 29 Sep 2023 23:46:23 +0200 Subject: [PATCH 06/30] ==[ std::chrono migration ]== class epoch =========== - Added a default constructor and a constructor for microseconds - Added constructor templates to resolve ambiguities - Fixed serialisation issues - Other fixes, cleanup --- include/kep3/detail/s11n.hpp | 1 + include/kep3/epoch.hpp | 378 +++++++++++++++-------------- include/kep3/planets/keplerian.hpp | 2 - src/epoch.cpp | 57 +++-- test/epoch_test_chrono.cpp | 21 +- test/planet_keplerian_test.cpp | 13 +- 6 files changed, 251 insertions(+), 221 deletions(-) diff --git a/include/kep3/detail/s11n.hpp b/include/kep3/detail/s11n.hpp index 5608b07e..6878cc30 100644 --- a/include/kep3/detail/s11n.hpp +++ b/include/kep3/detail/s11n.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index dc6677fa..164eb877 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -10,6 +10,7 @@ #ifndef kep3_EPOCH_HPP #define kep3_EPOCH_HPP +#include #include #include @@ -27,195 +28,206 @@ * that are related to keplerian motions or models. */ -using namespace std::literals; -namespace chr = std::chrono; -using lint = long int; -using llint = long long int; -template -using dur = chr::duration>; -namespace kep3 -{ +namespace kep3 { + using namespace std::literals; + namespace chr = std::chrono; + using lint = long int; + using llint = long long int; + template + using dur = chr::duration>; + + +struct kep_clock : public chr::system_clock { + using rep = int_fast64_t; + using period = std::ratio<1, 1'000'000>; + using duration = chr::duration; + using time_point = chr::time_point; + static constexpr bool is_steady = false; + static constexpr chr::seconds y2k_offset{946684800s}; + + static constexpr time_point ref_epoch{kep_clock::time_point{} + y2k_offset}; + + static std::time_t to_time_t(const time_point &t) noexcept { + return static_cast( + chr::duration_cast(t.time_since_epoch() + y2k_offset) + .count()); + } + + static time_point from_time_t(std::time_t t) noexcept { + return chr::time_point_cast( + time_point(chr::seconds(t) - y2k_offset)); + } + +}; + +/// epoch class. +/** + * This class defines and contains a non-gregorian date (i.e. a date expressed + * in julian form). It also provides the user with an interface to boost + * gregorian dates (see boost documentation at + * http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html) + * using the posix time. + * The date is defined in MJD2000 (double) as a + * private member + * + * @author Dario Izzo (dario.izzo _AT_ googlemail.com) + */ +class kep3_DLL_PUBLIC epoch { +public: + /** Types of non gregorian dates supported. Julian Date (JD) is the number of + * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is + * the number of days passed since November 17, 1858 at 00:00 am. The Modified + * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, + * 2000 at 00:00am. + */ + enum class julian_type { MJD2000, MJD, JD }; + + enum class time_unit { D, H, MIN, S, MS, U }; + + + /** Constructors */ + // Default constructor + epoch(); + + // Constructor for days (as a floating-point value) + template ::value, + FP>::type * = nullptr> + epoch(const FP epoch_in = 0.0, + const julian_type epoch_type = julian_type::MJD2000) + : tp{ make_tp( epoch_in, epoch_type ) } - struct kep_clock : public chr::system_clock { - using rep = int_fast64_t; - using period = std::ratio<1, 1'000'000>; - using duration = chr::duration; - using time_point = chr::time_point; - static constexpr bool is_steady = false; - static constexpr chr::seconds y2k_offset{ 946684800s }; - - static constexpr time_point ref_epoch{ kep_clock::time_point{} + y2k_offset }; - - static std::time_t to_time_t( const time_point& t ) noexcept - { - return static_cast( - chr::duration_cast( t.time_since_epoch() + y2k_offset ) - .count() ); - } - - static time_point from_time_t( std::time_t t ) noexcept - { - return chr::time_point_cast( - time_point( chr::seconds( t ) - y2k_offset ) ); - } - }; - - /// epoch class. - /** - * This class defines and contains a non-gregorian date (i.e. a date expressed - * in julian form). It also provides the user with an interface to boost - * gregorian dates (see boost documentation at - * http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html) - * using the posix time. - * The date is defined in MJD2000 (double) as a - * private member - * - * @author Dario Izzo (dario.izzo _AT_ googlemail.com) - */ - class kep3_DLL_PUBLIC epoch + } + + // Constructor for const duration&) + template + epoch(const dur &duration) + : tp{kep_clock::time_point{} + duration} {} + + // Constructor for duration&&) + template + epoch(dur &&duration) : tp{kep_clock::time_point{} + duration} {} + + // Constructor for a const duration&) + epoch(const kep_clock::time_point &time_point); + epoch(kep_clock::time_point &&time_point); + + // Constructor for microseconds + template ::value, Int>::type * = nullptr> + epoch(const Int us) + : tp{ kep_clock::time_point{chr::microseconds(us)} } { - public: - /** Types of non gregorian dates supported. Julian Date (JD) is the number of - * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is - * the number of days passed since November 17, 1858 at 00:00 am. The Modified - * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, - * 2000 at 00:00am. - */ - enum class julian_type - { - MJD2000, - MJD, - JD - }; - - /** Constructors */ - epoch( const double epoch_in = 0.0, - const julian_type epoch_type = julian_type::MJD2000 ); - - template - epoch( const dur& duration ) - : tp{ kep_clock::time_point{} + duration } - { - } - - template - epoch( dur&& duration ) - : tp{ kep_clock::time_point{} + duration } - { - } - - epoch( const kep_clock::time_point& time_point ); - epoch( kep_clock::time_point&& time_point ); - - epoch( const int yr, const int mon, const int day, const int hr = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0 ); - - /** Computing non-gregorian dates */ - [[nodiscard]] kep_clock::time_point mjd2000() const; - [[nodiscard]] kep_clock::time_point jd() const; - [[nodiscard]] kep_clock::time_point mjd() const; - - /** Interface to boost::posix_time::ptime */ - // [[nodiscard]] boost::posix_time::ptime get_posix_time() const; - - static constexpr kep_clock::time_point make_tp( const int yr, const int mon, const int day, const int hr = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0 ); - static constexpr kep_clock::time_point make_tp( const double epoch_in, const julian_type epoch_type ); - - // Conversions - // double tp_from_seconds(const double seconds) const; - static constexpr kep_clock::time_point tp_from_days( const double days ); - // void set_tp_mjd2000( const double epoch_in ); - // void set_tp_mjd( const double epoch_in ); - // void set_tp_jd( const double epoch_in ); - - // Duration conversions - static constexpr double as_sec( kep_clock::duration d ) - { - return std::chrono::duration( d ) - .count(); - } - // double as_days(); - - // Printing - static const char* as_utc_string( const kep_clock::time_point& ); - // static std::time_t as_gmtime(const kep_clock::time_point &); - - /** operator overloads for sum and diff (epoch-days) and comparison - * operators - * **/ - - // std::chrono::seconds day2sec(const double days) const; - // kep3_DLL_PUBLIC epoch epoch_from_string(const std::string &date); - // kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string &date); - - kep3_DLL_PUBLIC friend std::ostream& operator<<( std::ostream& s, - epoch const& epoch_in ); - template - kep3_DLL_PUBLIC epoch& operator+=( dur&& duration ) - { - /* addition of rhs to *this takes place here */ - tp += chr::duration_cast( duration ); - return *this; - } - template - kep3_DLL_PUBLIC epoch& operator-=( dur&& duration ) - { - /* addition of rhs to *this takes place here */ - tp -= chr::duration_cast( duration ); - return *this; - } - - kep3_DLL_PUBLIC friend bool operator>( const epoch& c1, const epoch& c2 ); - kep3_DLL_PUBLIC friend bool operator<( const epoch& c1, const epoch& c2 ); - kep3_DLL_PUBLIC friend bool operator>=( const epoch& c1, const epoch& c2 ); - kep3_DLL_PUBLIC friend bool operator<=( const epoch& c1, const epoch& c2 ); - kep3_DLL_PUBLIC friend bool operator==( const epoch& c1, const epoch& c2 ); - kep3_DLL_PUBLIC friend bool operator!=( const epoch& c1, const epoch& c2 ); - // template - // kep3_DLL_PUBLIC friend epoch operator+( const epoch& lhs, dur&& rhs ); - // template - // kep3_DLL_PUBLIC friend epoch operator-( const epoch& lhs, dur&& rhs ); - - template - kep3_DLL_PUBLIC epoch operator+( dur&& duration ) - { - return epoch( tp + chr::duration_cast( duration ) ); - } - template - kep3_DLL_PUBLIC epoch operator-( dur&& duration ) - { - return epoch( tp - chr::duration_cast( duration ) ); - } - - kep3_DLL_PUBLIC friend kep_clock::duration operator-( const epoch lhs, const epoch rhs ); - - kep3_DLL_PUBLIC epoch operator=( const epoch& ep ) - { - return { ep.tp }; - } - // kep3_DLL_PUBLIC friend epoch& operator=( epoch&& ep ); - - private: - // Serialization code - friend class boost::serialization::access; - template - void serialize( Archive& ar, const unsigned int ) - { - ar&( *this ); - } - // Serialization code (END) - - /// the modified julian date 2000 stored in a double - // double m_mjd2000; - kep_clock::time_point tp; - }; + } + + // Constructor for microseconds + epoch(const int y,const int d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); + + /** Computing non-gregorian dates */ + [[nodiscard]] kep_clock::time_point mjd2000() const; + [[nodiscard]] kep_clock::time_point jd() const; + [[nodiscard]] kep_clock::time_point mjd() const; + + /** Interface to boost::posix_time::ptime */ + // [[nodiscard]] boost::posix_time::ptime get_posix_time() const; + + static kep_clock::time_point make_tp(const int y, const int d, + const int h = 0, const int min = 0, + const int s = 0, const int ms = 0, const int us = 0); + + static kep_clock::time_point make_tp(const double epoch_in, const julian_type epoch_type); + + // Conversions + // double tp_from_seconds(const double seconds) const; + static constexpr kep_clock::time_point tp_from_days(const double days); + // void set_tp_mjd2000( const double epoch_in ); + // void set_tp_mjd( const double epoch_in ); + // void set_tp_jd( const double epoch_in ); + + // Duration conversions + static constexpr double as_sec(kep_clock::duration d) { + return std::chrono::duration(d) + .count(); + } + // double as_days(); + + // Printing + static auto as_utc_string(const kep_clock::time_point &); + // static std::time_t as_gmtime(const kep_clock::time_point &); + + /** operator overloads for sum and diff (epoch-days) and comparison + * operators + * **/ + + // std::chrono::seconds day2sec(const double days) const; + // kep3_DLL_PUBLIC epoch epoch_from_string(const std::string &date); + // kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string &date); + + kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, + epoch const &epoch_in); + template + kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { + /* addition of rhs to *this takes place here */ + tp += chr::duration_cast(duration); + return *this; + } + template + kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { + /* addition of rhs to *this takes place here */ + tp -= chr::duration_cast(duration); + return *this; + } + + kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); + + template + kep3_DLL_PUBLIC epoch operator+(dur &&duration) { + return epoch(tp + chr::duration_cast(duration)); + } + template + kep3_DLL_PUBLIC epoch operator-(dur &&duration) { + return epoch(tp - chr::duration_cast(duration)); + } + + static constexpr auto days(const double value) { + return chr::duration_cast(chr::duration>(value)); + } + + static constexpr auto sec(const double value) { + return chr::duration_cast(chr::duration>(value)); + } + + kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, + const epoch &rhs); + kep3_DLL_PUBLIC epoch operator=(const epoch &ep) { return {ep.tp}; } + + +private: + // Serialization code + friend class boost::serialization::access; + template + void serialize(Archive &ar, const unsigned int version) { + ar & boost::serialization::make_binary_object(&tp, sizeof(tp)); + } + // Serialization code (END) + + // Time point relative to 1 Jan 2000 (MJD2000) + kep_clock::time_point tp; +}; + + kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, + const epoch &epoch_in); } // end of namespace kep3 -template <> -struct fmt::formatter : fmt::ostream_formatter -{ -}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; + +// Serialization code (END) #endif // kep3_EPOCH_HPP diff --git a/include/kep3/planets/keplerian.hpp b/include/kep3/planets/keplerian.hpp index e56ab29f..c0dd4bf1 100644 --- a/include/kep3/planets/keplerian.hpp +++ b/include/kep3/planets/keplerian.hpp @@ -32,9 +32,7 @@ class kep3_DLL_PUBLIC keplerian { double m_radius; double m_safe_radius; double m_period; - bool m_ellipse; - double m_safe_radius; std::array, 2> m_pos_vel_0; friend class boost::serialization::access; diff --git a/src/epoch.cpp b/src/epoch.cpp index 39305b6e..19f42f61 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "kep3/core_astro/convert_julian_dates.hpp" #include "kep3/epoch.hpp" @@ -23,16 +25,25 @@ namespace kep3 /// Constructor. /** - * Constructs an epoch from a non-gregorian date. - * \param[in] epoch_in A double indicating the non-gregorian date - * \param[in] epoch_type One of [epoch::julian_type::MJD2000, - * \param[in] epoch_type epoch::julian_type::MJD2000 - */ - epoch::epoch( const double epoch_in, const julian_type epoch_type ) - : tp{ make_tp( epoch_in, epoch_type ) } + * Constructs a reference epoch. + */ + epoch::epoch() + : tp{} + {} - { - } + /// Constructor. + /** + * Constructs an epoch from a non-gregorian date. + * \param[in] epoch_in A double indicating the non-gregorian date + * \param[in] epoch_type One of [epoch::julian_type::MJD2000, + * \param[in] epoch_type epoch::julian_type::MJD2000 + */ + // template::value, FP>::type*> + // epoch::epoch( const FP epoch_in, const julian_type epoch_type ) + // : tp{ make_tp( epoch_in, epoch_type ) } + + // { + // } /// Constructor. /** @@ -43,8 +54,8 @@ namespace kep3 * [0-59] \param[in] ms The milliseconds [0-999] \param[in] us The milliseconds * [0-999] */ - epoch::epoch( const int yr, const int mon, const int day, const int hr, const int min, const int s, const int ms, const int us ) - : tp{ make_tp( yr, mon, day, hr, min, s, ms, us ) } + epoch::epoch(const int y, const int d, const int h, const int min, const int s, const int ms, const int us) + : tp{ make_tp( y, d, h, min, s, ms, us ) } { } @@ -70,14 +81,22 @@ namespace kep3 { } - constexpr kep_clock::time_point epoch::make_tp( const int yr, const int mon, const int day, const int hr, const int min, const int s, const int ms, const int us ) + // template::value, Int>::type*> + // epoch::epoch(const Int us) + // : tp{ kep_clock::time_point{chr::microseconds(us)} } + // { + // } + + kep_clock::time_point + epoch::make_tp(const int y, const int d, const int h, const int min, + const int s, const int ms, const int us) + { - return kep_clock::time_point{} + chr::years( yr ) + chr::months( mon ) + - chr::days( day ) + chr::hours( hr ) + chr::minutes( min ) + chr::seconds( s ) + + return kep_clock::time_point{} + chr::years( y ) + chr::days( d ) + chr::hours( h ) + chr::minutes( min ) + chr::seconds( s ) + chr::milliseconds( ms ) + chr::microseconds( us ); } - constexpr kep_clock::time_point epoch::make_tp( const double epoch_in, const julian_type epoch_type ) + kep_clock::time_point epoch::make_tp( const double epoch_in, const julian_type epoch_type ) { switch ( epoch_type ) { @@ -175,10 +194,10 @@ namespace kep3 // return std::mktime(utc); // } - const char* epoch::as_utc_string( const kep_clock::time_point& tp ) + auto epoch::as_utc_string( const kep_clock::time_point& tp ) { auto t = kep_clock::to_time_t( tp ); - return asctime( gmtime( &t ) ); + return std::put_time( gmtime( &t ), "%FT%T"); } // template @@ -238,7 +257,7 @@ namespace kep3 */ std::ostream& operator<<( std::ostream& s, const epoch& ep ) { - s << epoch::as_utc_string( ep.tp ); + s << epoch::as_utc_string(ep.tp); return s; } @@ -282,7 +301,7 @@ namespace kep3 // return lhs; // return the result by value (uses move constructor) // } - kep_clock::duration operator-( const epoch lhs, const epoch rhs ) + kep_clock::duration operator-( const epoch& lhs, const epoch& rhs ) { return lhs.tp - rhs.tp; } diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp index 1b1cbddf..ede81b9c 100644 --- a/test/epoch_test_chrono.cpp +++ b/test/epoch_test_chrono.cpp @@ -20,11 +20,8 @@ using kep3::epoch; using kep3::kep_clock; -// using kep3::epoch_from_iso_string; -// using kep3::epoch_from_string; -// using boost::gregorian::date; -// using boost::posix_time::ptime; using namespace std::literals; +namespace chr = std::chrono; TEST_CASE( "construct" ) { @@ -37,7 +34,7 @@ TEST_CASE( "construct" ) REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::JD ) ); REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::MJD ) ); REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( 2034, 12, 31, 11, 36, 21, 121, 841 ) ); + REQUIRE_NOTHROW( epoch( 34, 364, 11, 36, 21, 121, 841 ) ); // // > 2000 // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); // REQUIRE_NOTHROW( epoch( posix_time_test ) ); @@ -68,13 +65,13 @@ TEST_CASE( "construct" ) TEST_CASE( "epoch_operators" ) { - REQUIRE( epoch( 2034, 12, 10 ) == epoch( 2034, 12, 10 ) ); - REQUIRE( epoch( 2034, 12, 10 ) != epoch( 2034, 12, 11 ) ); + REQUIRE( epoch( 34, 10 ) == epoch( 34, 10 ) ); + REQUIRE( epoch( 34, 10 ) != epoch( 34, 11 ) ); // Testing us precision - REQUIRE( epoch( 2034, 12, 10 ) != epoch( 2034, 12, 10, 0, 0, 0, 0, 1 ) ); + REQUIRE( epoch( 34, 10 ) != epoch( 34, 10, 0, 0, 0, 0, 1 ) ); // Check that ns precision is not supported - REQUIRE( epoch( 0, 12, 10 ) == - epoch( 0, 12, 10, 0, 0, 0, 0, 0 ) + 100ns ); + REQUIRE( epoch( 0, 10 ) == + epoch( 0, 10, 0, 0, 0, 0, 0 ) + 100ns ); // Conversion from double (defaults to days) REQUIRE( epoch( 1. ) > epoch( 0. ) ); @@ -84,14 +81,14 @@ TEST_CASE( "epoch_operators" ) REQUIRE( epoch( 1. ) <= epoch( 1. ) ); epoch today( 0. ); today += chr::days( 100 ); - REQUIRE( today == epoch( 0, 0, 100 ) ); + REQUIRE( today == epoch( 0, 100 ) ); today -= chr::duration_cast( chr::days( 100 ) ); REQUIRE( today == epoch() ); auto oneday = chr::days( 1 ); auto yesterday = today - chr::duration_cast( oneday ); auto yesterday1 = today - oneday; - REQUIRE( yesterday == epoch( 0, 0, -1 ) ); + REQUIRE( yesterday == epoch( 0, -1 ) ); today = yesterday + chr::duration_cast( chr::days( 1 ) ); REQUIRE( today == epoch() ); auto diff{ today - yesterday }; diff --git a/test/planet_keplerian_test.cpp b/test/planet_keplerian_test.cpp index 9d94a045..a63837a6 100644 --- a/test/planet_keplerian_test.cpp +++ b/test/planet_keplerian_test.cpp @@ -18,13 +18,15 @@ #include #include "catch.hpp" +#include "kep3/epoch.hpp" #include "test_helpers.hpp" using kep3::udpla::keplerian; +using kep3::epoch; TEST_CASE("constructor") { REQUIRE_NOTHROW(keplerian{}); - kep3::epoch ref_epoch{12.22, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{12.22, kep3::epoch::julian_type::MJD2000}; // From posvel REQUIRE_NOTHROW( keplerian{ref_epoch, {{{0.3, 1., 0.2}, {0.0, 1.12, 0.}}}, 1., "unknown"}); @@ -124,7 +126,7 @@ TEST_CASE("constructor") { TEST_CASE("eph") { // We use 2000-01-01 as a reference epoch for all these tests - kep3::epoch ref_epoch{0., kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{0., kep3::epoch::julian_type::MJD2000}; // This is a circular orbit at 1 AU. std::array, 2> pos_vel_0{ {{kep3::AU, 0., 0.}, {0., kep3::EARTH_VELOCITY, 0.}}}; @@ -132,13 +134,13 @@ TEST_CASE("eph") { keplerian udpla1{ref_epoch, pos_vel_0, kep3::MU_SUN}; double period_in_days = (2 * kep3::pi * kep3::AU / kep3::EARTH_VELOCITY) * kep3::SEC2DAY; - auto [r, v] = udpla1.eph(ref_epoch + period_in_days); + auto [r, v] = udpla1.eph(ref_epoch + epoch::days(period_in_days)); REQUIRE(kep3_tests::floating_point_error_vector(r, pos_vel_0[0]) < 1e-13); REQUIRE(kep3_tests::floating_point_error_vector(v, pos_vel_0[1]) < 1e-13); } TEST_CASE("elements") { - kep3::epoch ref_epoch{12.22, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{12.22, kep3::epoch::julian_type::MJD2000}; // Non singular elements std::array, 2> pos_vel{ {{1., 0.1, 0.1}, {0.1, 1., 0.1}}}; @@ -181,7 +183,7 @@ TEST_CASE("stream_operator") { TEST_CASE("serialization_test") { // Instantiate a generic udpla - kep3::epoch ref_epoch{2423.4343, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{2423.4343, kep3::epoch::julian_type::MJD2000}; keplerian udpla{ref_epoch, {{{0.33, 1.3, 0.12}, {0.01, 1.123, 0.2}}}, 1.12, @@ -196,6 +198,7 @@ TEST_CASE("serialization_test") { boost::archive::binary_oarchive oarchive(ss); oarchive << udpla; } + // Deserialize // Create a new udpla object keplerian udpla2{}; From 5e0eecfe498bfae1915887b80d6d57390a64c4ab Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Fri, 29 Sep 2023 23:53:12 +0200 Subject: [PATCH 07/30] ==[ Minor fix ]== - Removed missing header included in planet_test.cpp --- test/planet_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/planet_test.cpp b/test/planet_test.cpp index fe1dd074..68035075 100644 --- a/test/planet_test.cpp +++ b/test/planet_test.cpp @@ -15,7 +15,6 @@ #include "catch.hpp" #include -#include #include #include From f458bbcc6e0c794229e8c4a790cf01527e81d338 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 00:04:21 +0200 Subject: [PATCH 08/30] ==[ Minor fix ]== - Added typename to template --- include/kep3/epoch.hpp | 15 +++- src/epoch.cpp | 29 -------- test/CMakeLists.txt | 4 +- test/epoch_test.cpp | 143 ++++++++++++++++++++++--------------- test/epoch_test_chrono.cpp | 110 ---------------------------- 5 files changed, 100 insertions(+), 201 deletions(-) delete mode 100644 test/epoch_test_chrono.cpp diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 164eb877..9fcd8ceb 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -91,7 +91,12 @@ class kep3_DLL_PUBLIC epoch { epoch(); // Constructor for days (as a floating-point value) - template ::value, + /** + * Constructs an epoch from a non-gregorian date. + * \param[in] epoch_in A double indicating the non-gregorian date + * \param[in] epoch_type epoch::julian_type + */ + template ::value, FP>::type * = nullptr> epoch(const FP epoch_in = 0.0, const julian_type epoch_type = julian_type::MJD2000) @@ -101,6 +106,12 @@ class kep3_DLL_PUBLIC epoch { } // Constructor for const duration&) + + /** + * Constructs an epoch from a std::chrono::duration. + * The reference point is assumed to be MJD 0. + * \param[in] time The time as a duration + */ template epoch(const dur &duration) : tp{kep_clock::time_point{} + duration} {} @@ -115,7 +126,7 @@ class kep3_DLL_PUBLIC epoch { // Constructor for microseconds template ::value, Int>::type * = nullptr> + typename std::enable_if::value, Int>::type * = nullptr> epoch(const Int us) : tp{ kep_clock::time_point{chr::microseconds(us)} } { diff --git a/src/epoch.cpp b/src/epoch.cpp index 19f42f61..19ea87f0 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -31,19 +31,7 @@ namespace kep3 : tp{} {} - /// Constructor. - /** - * Constructs an epoch from a non-gregorian date. - * \param[in] epoch_in A double indicating the non-gregorian date - * \param[in] epoch_type One of [epoch::julian_type::MJD2000, - * \param[in] epoch_type epoch::julian_type::MJD2000 - */ - // template::value, FP>::type*> - // epoch::epoch( const FP epoch_in, const julian_type epoch_type ) - // : tp{ make_tp( epoch_in, epoch_type ) } - // { - // } /// Constructor. /** @@ -59,17 +47,6 @@ namespace kep3 { } - /// Constructor. - /** - * Constructs an epoch from a std::chrono::duration. - * The reference point is assumed to be MJD 0. - * \param[in] time The time as a duration - */ - // template - // epoch::epoch( const dur& time ) - // : tp{ kep_clock::time_point( T( time ) ) } - // { - // } epoch::epoch( const kep_clock::time_point& time_point ) : tp{ time_point } @@ -81,12 +58,6 @@ namespace kep3 { } - // template::value, Int>::type*> - // epoch::epoch(const Int us) - // : tp{ kep_clock::time_point{chr::microseconds(us)} } - // { - // } - kep_clock::time_point epoch::make_tp(const int y, const int d, const int h, const int min, const int s, const int ms, const int us) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e201eaab..42d25a51 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,9 +28,7 @@ function(ADD_kep3_TESTCASE arg1) endfunction() ADD_kep3_TESTCASE(convert_anomalies_test) - -# ADD_kep3_TESTCASE(epoch_test) -ADD_kep3_TESTCASE(epoch_test_chrono) +ADD_kep3_TESTCASE(epoch_test) ADD_kep3_TESTCASE(planet_test) ADD_kep3_TESTCASE(planet_keplerian_test) ADD_kep3_TESTCASE(ic2par2ic_test) diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 218ba098..ede81b9c 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -8,74 +8,103 @@ // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include +#include #include #include #include -#include +#include "kep3/epoch.hpp" #include "catch.hpp" using kep3::epoch; -using kep3::epoch_from_iso_string; -using kep3::epoch_from_string; -using boost::gregorian::date; -using boost::posix_time::ptime; +using kep3::kep_clock; +using namespace std::literals; +namespace chr = std::chrono; -TEST_CASE("construct") { - // test syntax - REQUIRE_NOTHROW(epoch()); - REQUIRE_NOTHROW(epoch(123.456)); - REQUIRE_NOTHROW(epoch(123.456, epoch::MJD2000)); - REQUIRE_NOTHROW(epoch(123.456, epoch::JD)); - REQUIRE_NOTHROW(epoch(123.456, epoch::MJD)); - REQUIRE_NOTHROW(epoch(31, 12, 2034)); - // > 2000 - boost::posix_time::ptime posix_time_test(date(2034, 12, 31)); - REQUIRE_NOTHROW(epoch(posix_time_test)); - REQUIRE(epoch(posix_time_test).get_posix_time() == posix_time_test); - // < 2000 - boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); - REQUIRE_NOTHROW(epoch(posix_time_test2)); - REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); +TEST_CASE( "construct" ) +{ + // test syntax + // // > 2000 + REQUIRE_NOTHROW( epoch() ); + REQUIRE_NOTHROW( epoch( 123.456 ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD2000 ) ); + REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( 34, 364, 11, 36, 21, 121, 841 ) ); + // // > 2000 + // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); + // REQUIRE_NOTHROW( epoch( posix_time_test ) ); + // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); + // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << + // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; - // test conversions - REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::MJD2000).mjd2000()); - REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::MJD).mjd()); - REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::JD).jd()); - REQUIRE(epoch(31, 12, 2034).jd() == epoch(posix_time_test).jd()); -} + // // < 2000 + // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); + // REQUIRE_NOTHROW(epoch(posix_time_test2)); + // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); + // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << + // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; -TEST_CASE("epoch_operators") { - REQUIRE(epoch(0.) == epoch(0.)); - REQUIRE(epoch(0.) != epoch(1.)); - REQUIRE(epoch(1.) > epoch(0.)); - REQUIRE(epoch(1.) >= epoch(1.)); - REQUIRE(epoch(1.) >= epoch(0.)); - REQUIRE(epoch(0.) < epoch(1.)); - REQUIRE(epoch(1.) <= epoch(1.)); - epoch today(0.); - today += 100.; - REQUIRE(today == epoch(100.)); - today -= 100.; - REQUIRE(today == epoch(0.)); - auto yesterday = today - 1.; - REQUIRE(yesterday == epoch(-1.)); - today = yesterday + 1; - REQUIRE(today == epoch(0.)); - REQUIRE(today - yesterday == 1.); - REQUIRE_NOTHROW((std::cout << epoch())); + // // test conversions + // REQUIRE(epoch(123.456).mjd2000() == + // epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); + // REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); + // REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); + // std::cout << "Chrono3: " + // << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << + // "\n"; + // std::cout << "Chrono3-1: " + // << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << + // "\n"; + // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } -TEST_CASE("conversions_from_string") { - { - std::string ts("20020131T000000"); - epoch e(epoch_from_iso_string(ts)); - REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 31)))); - } - { - std::string ts("2002-01-20 00:00:00.000"); - epoch e(epoch_from_string(ts)); - REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 20)))); - } +TEST_CASE( "epoch_operators" ) +{ + REQUIRE( epoch( 34, 10 ) == epoch( 34, 10 ) ); + REQUIRE( epoch( 34, 10 ) != epoch( 34, 11 ) ); + // Testing us precision + REQUIRE( epoch( 34, 10 ) != epoch( 34, 10, 0, 0, 0, 0, 1 ) ); + // Check that ns precision is not supported + REQUIRE( epoch( 0, 10 ) == + epoch( 0, 10, 0, 0, 0, 0, 0 ) + 100ns ); + + // Conversion from double (defaults to days) + REQUIRE( epoch( 1. ) > epoch( 0. ) ); + REQUIRE( epoch( 1. ) >= epoch( 1. ) ); + REQUIRE( epoch( 1. ) >= epoch( 0. ) ); + REQUIRE( epoch( 0. ) < epoch( 1. ) ); + REQUIRE( epoch( 1. ) <= epoch( 1. ) ); + epoch today( 0. ); + today += chr::days( 100 ); + REQUIRE( today == epoch( 0, 100 ) ); + today -= chr::duration_cast( chr::days( 100 ) ); + REQUIRE( today == epoch() ); + auto oneday = chr::days( 1 ); + auto yesterday = today - chr::duration_cast( oneday ); + auto yesterday1 = today - oneday; + + REQUIRE( yesterday == epoch( 0, -1 ) ); + today = yesterday + chr::duration_cast( chr::days( 1 ) ); + REQUIRE( today == epoch() ); + auto diff{ today - yesterday }; + REQUIRE( diff == chr::duration_cast( chr::days( 1 ) ) ); + REQUIRE_NOTHROW( ( std::cout << epoch() ) ); } + +// TEST_CASE("conversions_from_string") { +// { +// std::string ts("20020131T000000"); +// epoch e(epoch_from_iso_string(ts)); +// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 31)))); +// } +// { +// std::string ts("2002-01-20 00:00:00.000"); +// epoch e(epoch_from_string(ts)); +// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 20)))); +// } +// } diff --git a/test/epoch_test_chrono.cpp b/test/epoch_test_chrono.cpp deleted file mode 100644 index ede81b9c..00000000 --- a/test/epoch_test_chrono.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani -// (bluescarni@gmail.com) -// -// This file is part of the kep3 library. -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include -#include -#include -#include -#include -#include - -#include "kep3/epoch.hpp" - -#include "catch.hpp" - -using kep3::epoch; -using kep3::kep_clock; -using namespace std::literals; -namespace chr = std::chrono; - -TEST_CASE( "construct" ) -{ - // test syntax - // // > 2000 - REQUIRE_NOTHROW( epoch() ); - REQUIRE_NOTHROW( epoch( 123.456 ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD2000 ) ); - REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( 34, 364, 11, 36, 21, 121, 841 ) ); - // // > 2000 - // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); - // REQUIRE_NOTHROW( epoch( posix_time_test ) ); - // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); - // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << - // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; - - // // < 2000 - // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); - // REQUIRE_NOTHROW(epoch(posix_time_test2)); - // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); - // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << - // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; - - // // test conversions - // REQUIRE(epoch(123.456).mjd2000() == - // epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - // REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); - // REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); - // std::cout << "Chrono3: " - // << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << - // "\n"; - // std::cout << "Chrono3-1: " - // << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << - // "\n"; - // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); -} - -TEST_CASE( "epoch_operators" ) -{ - REQUIRE( epoch( 34, 10 ) == epoch( 34, 10 ) ); - REQUIRE( epoch( 34, 10 ) != epoch( 34, 11 ) ); - // Testing us precision - REQUIRE( epoch( 34, 10 ) != epoch( 34, 10, 0, 0, 0, 0, 1 ) ); - // Check that ns precision is not supported - REQUIRE( epoch( 0, 10 ) == - epoch( 0, 10, 0, 0, 0, 0, 0 ) + 100ns ); - - // Conversion from double (defaults to days) - REQUIRE( epoch( 1. ) > epoch( 0. ) ); - REQUIRE( epoch( 1. ) >= epoch( 1. ) ); - REQUIRE( epoch( 1. ) >= epoch( 0. ) ); - REQUIRE( epoch( 0. ) < epoch( 1. ) ); - REQUIRE( epoch( 1. ) <= epoch( 1. ) ); - epoch today( 0. ); - today += chr::days( 100 ); - REQUIRE( today == epoch( 0, 100 ) ); - today -= chr::duration_cast( chr::days( 100 ) ); - REQUIRE( today == epoch() ); - auto oneday = chr::days( 1 ); - auto yesterday = today - chr::duration_cast( oneday ); - auto yesterday1 = today - oneday; - - REQUIRE( yesterday == epoch( 0, -1 ) ); - today = yesterday + chr::duration_cast( chr::days( 1 ) ); - REQUIRE( today == epoch() ); - auto diff{ today - yesterday }; - REQUIRE( diff == chr::duration_cast( chr::days( 1 ) ) ); - REQUIRE_NOTHROW( ( std::cout << epoch() ) ); -} - -// TEST_CASE("conversions_from_string") { -// { -// std::string ts("20020131T000000"); -// epoch e(epoch_from_iso_string(ts)); -// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 31)))); -// } -// { -// std::string ts("2002-01-20 00:00:00.000"); -// epoch e(epoch_from_string(ts)); -// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 20)))); -// } -// } From bc94f99817326a18cb4b8994349d786d8205cb33 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 00:17:09 +0200 Subject: [PATCH 09/30] ==[ Fixes for Windows and Mac ]== - Reordered initialisation in constructors of keplerian planet - Removed user-defined epoch::operator=() - Removed erroneous #include --- include/kep3/epoch.hpp | 3 +-- src/epoch.cpp | 1 - src/planets/keplerian.cpp | 8 ++++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 9fcd8ceb..a97bb7dc 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -216,14 +216,13 @@ class kep3_DLL_PUBLIC epoch { kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, const epoch &rhs); - kep3_DLL_PUBLIC epoch operator=(const epoch &ep) { return {ep.tp}; } private: // Serialization code friend class boost::serialization::access; template - void serialize(Archive &ar, const unsigned int version) { + void serialize(Archive &ar, const unsigned int) { ar & boost::serialization::make_binary_object(&tp, sizeof(tp)); } // Serialization code (END) diff --git a/src/epoch.cpp b/src/epoch.cpp index 19ea87f0..0914aa33 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -7,7 +7,6 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include #include #include #include diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index eb1bc63d..d453135a 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -34,10 +34,10 @@ keplerian::keplerian(const epoch &ref_epoch, const std::array, 2> &pos_vel, double mu_central_body, std::string name, std::array added_params) - : m_ref_epoch(ref_epoch), m_pos_vel_0(pos_vel), m_name(std::move(name)), + : m_ref_epoch(ref_epoch), m_name(std::move(name)), m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), m_radius(added_params[1]), m_safe_radius(added_params[2]), m_period(), - m_ellipse() { + m_ellipse(), m_pos_vel_0(pos_vel) { double R = std::sqrt(pos_vel[0][0] * pos_vel[0][0] + pos_vel[0][1] * pos_vel[0][1] + pos_vel[0][2] * pos_vel[0][2]); @@ -59,10 +59,10 @@ keplerian::keplerian(const epoch &ref_epoch, double mu_central_body, std::string name, std::array added_params, kep3::elements_type el_type) - : m_ref_epoch(ref_epoch), m_pos_vel_0(), m_name(std::move(name)), + : m_ref_epoch(ref_epoch), m_name(std::move(name)), m_mu_central_body(mu_central_body), m_mu_self(added_params[0]), m_radius(added_params[1]), m_safe_radius(added_params[2]), m_period(), - m_ellipse() { + m_ellipse(), m_pos_vel_0() { // orbital parameters a,e,i,W,w,f will be stored here std::array par(par_in); // we convert according to the chosen input From a63d9786b4a35d7320d43387bb5fd54c9339ddc6 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 10:10:48 +0200 Subject: [PATCH 10/30] - Minor fixes to constructors and template arguments to address fussy OSX and MSVC compilers --- include/kep3/epoch.hpp | 33 +++++++++------------------------ src/epoch.cpp | 10 ++++++++++ test/epoch_test.cpp | 22 ++++++++-------------- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index a97bb7dc..826b604f 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -11,6 +11,7 @@ #define kep3_EPOCH_HPP #include +#include #include #include @@ -33,7 +34,6 @@ namespace kep3 { using namespace std::literals; namespace chr = std::chrono; using lint = long int; - using llint = long long int; template using dur = chr::duration>; @@ -83,27 +83,12 @@ class kep3_DLL_PUBLIC epoch { */ enum class julian_type { MJD2000, MJD, JD }; - enum class time_unit { D, H, MIN, S, MS, U }; - - /** Constructors */ // Default constructor epoch(); // Constructor for days (as a floating-point value) - /** - * Constructs an epoch from a non-gregorian date. - * \param[in] epoch_in A double indicating the non-gregorian date - * \param[in] epoch_type epoch::julian_type - */ - template ::value, - FP>::type * = nullptr> - epoch(const FP epoch_in = 0.0, - const julian_type epoch_type = julian_type::MJD2000) - : tp{ make_tp( epoch_in, epoch_type ) } - - { - } + epoch(const double epoch_in, const julian_type epoch_type = julian_type::MJD2000); // Constructor for const duration&) @@ -124,13 +109,13 @@ class kep3_DLL_PUBLIC epoch { epoch(const kep_clock::time_point &time_point); epoch(kep_clock::time_point &&time_point); - // Constructor for microseconds - template ::value, Int>::type * = nullptr> - epoch(const Int us) - : tp{ kep_clock::time_point{chr::microseconds(us)} } - { - } +// // Constructor for microseconds +// template ::value, Int>::type * = nullptr> +// epoch(const Int us) +// : tp{ kep_clock::time_point{chr::microseconds(us)} } +// { +// } // Constructor for microseconds epoch(const int y,const int d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); diff --git a/src/epoch.cpp b/src/epoch.cpp index 0914aa33..6b8fed39 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -30,7 +30,17 @@ namespace kep3 : tp{} {} + /// Constructor. + /** + * Constructs an epoch from a non-gregorian date. + * \param[in] epoch_in A double indicating the non-gregorian date + * \param[in] epoch_type epoch::julian_type + */ + epoch::epoch(const double epoch_in, const julian_type epoch_type) + : tp{ make_tp( epoch_in, epoch_type ) } + { + } /// Constructor. /** diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index ede81b9c..8919c6b0 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -50,16 +50,10 @@ TEST_CASE( "construct" ) // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; // // test conversions - // REQUIRE(epoch(123.456).mjd2000() == - // epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - // REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); - // REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); - // std::cout << "Chrono3: " - // << kep3::epoch::as_utc_string(epoch(posix_time_test).jd()) << - // "\n"; - // std::cout << "Chrono3-1: " - // << kep3::epoch::as_utc_string(epoch(2034, 12, 31).jd()) << - // "\n"; + REQUIRE(epoch(123.456).mjd2000() == + epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); + REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); + REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } @@ -71,7 +65,7 @@ TEST_CASE( "epoch_operators" ) REQUIRE( epoch( 34, 10 ) != epoch( 34, 10, 0, 0, 0, 0, 1 ) ); // Check that ns precision is not supported REQUIRE( epoch( 0, 10 ) == - epoch( 0, 10, 0, 0, 0, 0, 0 ) + 100ns ); + epoch( 0, 10, 0, 0, 0, 0, 0 ) + chr::nanoseconds(100) ); // Conversion from double (defaults to days) REQUIRE( epoch( 1. ) > epoch( 0. ) ); @@ -84,9 +78,9 @@ TEST_CASE( "epoch_operators" ) REQUIRE( today == epoch( 0, 100 ) ); today -= chr::duration_cast( chr::days( 100 ) ); REQUIRE( today == epoch() ); - auto oneday = chr::days( 1 ); - auto yesterday = today - chr::duration_cast( oneday ); - auto yesterday1 = today - oneday; + auto oneday{chr::days( 1 )}; + auto yesterday{today - chr::duration_cast( oneday )}; + auto yesterday1{today - oneday}; REQUIRE( yesterday == epoch( 0, -1 ) ); today = yesterday + chr::duration_cast( chr::days( 1 ) ); From cafda5f59807a60697bb05229f2d00751c07f78e Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 10:14:02 +0200 Subject: [PATCH 11/30] - Removed included header --- src/planets/keplerian.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index d453135a..b2c47b90 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -8,7 +8,6 @@ // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include "kep3/core_astro/eq2par2eq.hpp" #include #include From d35973c5805f314c92d27473b0b563398801f3a4 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 11:51:29 +0200 Subject: [PATCH 12/30] - Refactored conversion functions to return double NOTE ==== epoch::julian_type is an enum *class* (not a plain enum). This is necessary to avoid implicit conversion from julian_type to an integral type. --- .../kep3/core_astro/convert_julian_dates.hpp | 2 - include/kep3/epoch.hpp | 45 ++++++++++---- src/epoch.cpp | 62 +++++++++---------- src/planets/jpl_lp.cpp | 2 +- src/planets/keplerian.cpp | 2 +- test/planet_jpl_lp_test.cpp | 10 +-- 6 files changed, 72 insertions(+), 51 deletions(-) diff --git a/include/kep3/core_astro/convert_julian_dates.hpp b/include/kep3/core_astro/convert_julian_dates.hpp index 67d97b37..5d3f27ab 100644 --- a/include/kep3/core_astro/convert_julian_dates.hpp +++ b/include/kep3/core_astro/convert_julian_dates.hpp @@ -14,7 +14,6 @@ #include namespace kep3 { - // inline double jd2mjd(double in) { return (in - 2400000.5); } // inline double jd2mjd2000(double in) { return (in - 2451544.5); } // inline double mjd2jd(double in) { return (in + 2400000.5); } @@ -49,7 +48,6 @@ namespace kep3 { return in + 4453401600s; } - } // namespace kep3 #endif // CONVERT_JULIAN_DATES_HPP diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 826b604f..9d4e4616 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -109,21 +109,44 @@ class kep3_DLL_PUBLIC epoch { epoch(const kep_clock::time_point &time_point); epoch(kep_clock::time_point &&time_point); -// // Constructor for microseconds -// template ::value, Int>::type * = nullptr> -// epoch(const Int us) -// : tp{ kep_clock::time_point{chr::microseconds(us)} } -// { -// } - // Constructor for microseconds epoch(const int y,const int d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); /** Computing non-gregorian dates */ - [[nodiscard]] kep_clock::time_point mjd2000() const; - [[nodiscard]] kep_clock::time_point jd() const; - [[nodiscard]] kep_clock::time_point mjd() const; + /// jd getter. + /** + * Returns the julian date + * + * @return double containing the julian date + * + */ + constexpr double jd() const + { + return chr::duration>(tp.time_since_epoch() + 211813444800s).count(); + } + + /// mjd getter. + /** + * Returns the modified julian date + * + * @return double containing the modified julian date + * + */ + constexpr double mjd() const + { + return chr::duration>(tp.time_since_epoch() + 4453401600s).count(); + } + + /// mjd2000 getter. + /** + * Gets the modified julian date 2000 + * @return const reference to mjd2000 + */ + constexpr double mjd2000() const + { + return chr::duration>(tp.time_since_epoch()).count(); + } + /** Interface to boost::posix_time::ptime */ // [[nodiscard]] boost::posix_time::ptime get_posix_time() const; diff --git a/src/epoch.cpp b/src/epoch.cpp index 6b8fed39..43600a0f 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -90,39 +90,39 @@ namespace kep3 throw; } } - /// jd getter. - /** - * Returns the julian date - * - * @return double containing the julian date - * - */ - kep_clock::time_point epoch::jd() const - { - return mjd20002jd( tp ); - } + // /// jd getter. + // /** + // * Returns the julian date + // * + // * @return double containing the julian date + // * + // */ + // constexpr double epoch::jd() const + // { + // return chr::duration>(tp.time_since_epoch() + 211813444800s).count(); + // } - /// mjd getter. - /** - * Returns the modified julian date - * - * @return double containing the modified julian date - * - */ - kep_clock::time_point epoch::mjd() const - { - return mjd20002mjd( tp ); - } + // /// mjd getter. + // /** + // * Returns the modified julian date + // * + // * @return double containing the modified julian date + // * + // */ + // constexpr double epoch::mjd() const + // { + // return chr::duration>(tp.time_since_epoch() + 4453401600s).count(); + // } - /// mjd2000 getter. - /** - * Gets the modified julian date 2000 - * @return const reference to mjd2000 - */ - kep_clock::time_point epoch::mjd2000() const - { - return tp; - } + // /// mjd2000 getter. + // /** + // * Gets the modified julian date 2000 + // * @return const reference to mjd2000 + // */ + // constexpr double epoch::mjd2000() const + // { + // return chr::duration>(tp.time_since_epoch()).count(); + // } /// Extracts the posix time /** diff --git a/src/planets/jpl_lp.cpp b/src/planets/jpl_lp.cpp index 93c04f77..f4f0bd2c 100644 --- a/src/planets/jpl_lp.cpp +++ b/src/planets/jpl_lp.cpp @@ -180,7 +180,7 @@ double jpl_lp::get_radius() const { return m_radius; } double jpl_lp::get_safe_radius() const { return m_safe_radius; } std::string jpl_lp::get_extra_info() const { - kep3::epoch ep{0., kep3::epoch::MJD2000}; + kep3::epoch ep{0., kep3::epoch::julian_type::MJD2000}; auto par = elements(ep); auto pos_vel = eph(ep); diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index 32532b2c..ffa567fe 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -167,7 +167,7 @@ std::string keplerian::get_extra_info() const { kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); } retval += fmt::format("Elements reference epoch (MJD2000): {}\n", - m_ref_epoch.mjd2000().time_since_epoch().count()) + + m_ref_epoch) + fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); diff --git a/test/planet_jpl_lp_test.cpp b/test/planet_jpl_lp_test.cpp index fc2b829d..6869558e 100644 --- a/test/planet_jpl_lp_test.cpp +++ b/test/planet_jpl_lp_test.cpp @@ -24,7 +24,7 @@ using kep3::udpla::jpl_lp; TEST_CASE("constructor") { REQUIRE_NOTHROW(jpl_lp{}); - kep3::epoch ref_epoch{12.22, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{12.22, kep3::epoch::julian_type::MJD2000}; // From name REQUIRE_NOTHROW(jpl_lp{"Mars"}); REQUIRE_NOTHROW(jpl_lp{"mars"}); @@ -39,7 +39,7 @@ TEST_CASE("constructor") { TEST_CASE("eph") { // We use 2030-01-01 as a reference epoch for all these tests - kep3::epoch ref_epoch{2458849.5, kep3::epoch::JD}; + kep3::epoch ref_epoch{2458849.5, kep3::epoch::julian_type::JD}; { // This is Mercury w.r.t. the Sun queried from JPL Horizon at // 2020-01-01 @@ -136,12 +136,12 @@ TEST_CASE("eph") { REQUIRE(kep3_tests::floating_point_error_vector(v, pos_vel_0[1]) < 0.01); } jpl_lp udpla{"uranus"}; - REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534, kep3::epoch::MJD2000)), + REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534, kep3::epoch::julian_type::MJD2000)), std::domain_error); } TEST_CASE("elements") { - kep3::epoch ref_epoch{12.22, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{12.22, kep3::epoch::julian_type::MJD2000}; // We use Neptune jpl_lp udpla{"nePTUne"}; // casing is not important auto pos_vel = udpla.eph(ref_epoch); @@ -192,7 +192,7 @@ TEST_CASE("stream_operator") { TEST_CASE("serialization_test") { // Instantiate a generic jpl_lp - kep3::epoch ref_epoch{2423.4343, kep3::epoch::MJD2000}; + kep3::epoch ref_epoch{2423.4343, kep3::epoch::julian_type::MJD2000}; jpl_lp udpla{"neptune"}; // Store the string representation. From c6bfcf4977908eb2e57d1670e0aa15c97d50b562 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 12:58:44 +0200 Subject: [PATCH 13/30] - More generic duration types in templates --- CMakeLists.txt | 2 +- include/kep3/epoch.hpp | 47 +++++++++++++++++++++++++----------------- src/epoch.cpp | 8 +++---- test/epoch_test.cpp | 7 +++++++ 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9538ea9a..b9b77487 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.18.0) # NOTE: this should be done before the project command since the latter can set # CMAKE_BUILD_TYPE itself (it does so for nmake). if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 9d4e4616..3f256625 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -12,11 +12,9 @@ #include #include -#include - -#include #include #include +#include #include #include @@ -34,8 +32,9 @@ namespace kep3 { using namespace std::literals; namespace chr = std::chrono; using lint = long int; - template - using dur = chr::duration>; + using llint = long long int; + // template + // using dur = chr::duration>; struct kep_clock : public chr::system_clock { @@ -97,13 +96,17 @@ class kep3_DLL_PUBLIC epoch { * The reference point is assumed to be MJD 0. * \param[in] time The time as a duration */ - template - epoch(const dur &duration) +// template +// epoch(const dur &duration) + template > + epoch(const Duration &duration) : tp{kep_clock::time_point{} + duration} {} // Constructor for duration&&) - template - epoch(dur &&duration) : tp{kep_clock::time_point{} + duration} {} +// template +// epoch(dur &&duration) : tp{kep_clock::time_point{} + duration} {} + template > + epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} {} // Constructor for a const duration&) epoch(const kep_clock::time_point &time_point); @@ -185,15 +188,17 @@ class kep3_DLL_PUBLIC epoch { kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, epoch const &epoch_in); - template - kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { - /* addition of rhs to *this takes place here */ +// template +// kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { + template > + kep3_DLL_PUBLIC epoch &operator+=(Duration &&duration) { tp += chr::duration_cast(duration); return *this; } - template - kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { - /* addition of rhs to *this takes place here */ +// template +// kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { + template > + kep3_DLL_PUBLIC epoch &operator-=(Duration &&duration) { tp -= chr::duration_cast(duration); return *this; } @@ -205,12 +210,16 @@ class kep3_DLL_PUBLIC epoch { kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); - template - kep3_DLL_PUBLIC epoch operator+(dur &&duration) { + // template + // kep3_DLL_PUBLIC epoch operator+(dur &&duration) { + template > + kep3_DLL_PUBLIC epoch operator+(Duration &&duration) { return epoch(tp + chr::duration_cast(duration)); } - template - kep3_DLL_PUBLIC epoch operator-(dur &&duration) { +// template +// kep3_DLL_PUBLIC epoch operator-(dur &&duration) { + template > + kep3_DLL_PUBLIC epoch operator-(Duration &&duration) { return epoch(tp - chr::duration_cast(duration)); } diff --git a/src/epoch.cpp b/src/epoch.cpp index 43600a0f..389027ce 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -180,7 +180,7 @@ namespace kep3 return std::put_time( gmtime( &t ), "%FT%T"); } - // template + // template // epoch& epoch::operator+=( dur&& rhs ) // { // /* addition of rhs to *this takes place here */ @@ -188,7 +188,7 @@ namespace kep3 // return *this; // } - // template + // template // epoch& epoch::operator-=( dur&& rhs ) // { // /* addition of rhs to *this takes place here */ @@ -266,14 +266,14 @@ namespace kep3 return c1.tp != c2.tp; } - // template + // template // epoch operator+( const epoch& lhs, dur&& rhs ) // { // lhs.tp += // chr::duration_cast( rhs ); // reuse compound assignment // return lhs; // return the result by value (uses move constructor) // } - // template + // template // epoch operator-( const epoch& lhs, dur&& rhs ) // { // lhs.tp -= diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 8919c6b0..6d7bcfa2 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -43,6 +43,13 @@ TEST_CASE( "construct" ) // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; // // < 2000 + REQUIRE_NOTHROW( epoch( -123.456 ) ); + REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::MJD2000 ) ); + REQUIRE_NOTHROW( epoch( -0.0, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::JD ) ); + REQUIRE_NOTHROW( epoch( -0.0, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::MJD ) ); + REQUIRE_NOTHROW( epoch( -34, 364, 11, 36, 21, 121, 841 ) ); // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); // REQUIRE_NOTHROW(epoch(posix_time_test2)); // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); From dc187f3d51d42b0879f8b9ad8fdfcb4b8bdc00b8 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:08:04 +0200 Subject: [PATCH 14/30] - Custom duration template parameter --- include/kep3/epoch.hpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 3f256625..6777500c 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -36,6 +36,19 @@ namespace kep3 { // template // using dur = chr::duration>; + template + struct is_duration + : std::false_type + { }; + + template + struct is_duration> + : std::true_type + { }; + + template + using enable_if_is_duration = std::enable_if_t::value, T>; + struct kep_clock : public chr::system_clock { using rep = int_fast64_t; @@ -98,14 +111,14 @@ class kep3_DLL_PUBLIC epoch { */ // template // epoch(const dur &duration) - template > + template > epoch(const Duration &duration) : tp{kep_clock::time_point{} + duration} {} // Constructor for duration&&) // template // epoch(dur &&duration) : tp{kep_clock::time_point{} + duration} {} - template > + template > epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} {} // Constructor for a const duration&) @@ -190,14 +203,14 @@ class kep3_DLL_PUBLIC epoch { epoch const &epoch_in); // template // kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { - template > + template > kep3_DLL_PUBLIC epoch &operator+=(Duration &&duration) { tp += chr::duration_cast(duration); return *this; } // template // kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { - template > + template > kep3_DLL_PUBLIC epoch &operator-=(Duration &&duration) { tp -= chr::duration_cast(duration); return *this; @@ -212,13 +225,13 @@ class kep3_DLL_PUBLIC epoch { // template // kep3_DLL_PUBLIC epoch operator+(dur &&duration) { - template > + template > kep3_DLL_PUBLIC epoch operator+(Duration &&duration) { return epoch(tp + chr::duration_cast(duration)); } // template // kep3_DLL_PUBLIC epoch operator-(dur &&duration) { - template > + template > kep3_DLL_PUBLIC epoch operator-(Duration &&duration) { return epoch(tp - chr::duration_cast(duration)); } From b9f8ccf77f45b612077ea8a33bb3b6785cc4c05c Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:13:43 +0200 Subject: [PATCH 15/30] - Minor epoch test fix --- test/epoch_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 6d7bcfa2..8dd8561d 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -88,6 +88,7 @@ TEST_CASE( "epoch_operators" ) auto oneday{chr::days( 1 )}; auto yesterday{today - chr::duration_cast( oneday )}; auto yesterday1{today - oneday}; + REQUIRE(yesterday == yesterday1); REQUIRE( yesterday == epoch( 0, -1 ) ); today = yesterday + chr::duration_cast( chr::days( 1 ) ); From ea33ba7c4e198f84b1922a631b6de7afb17463c7 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:47:52 +0200 Subject: [PATCH 16/30] - Visibility fix for MSVC for templated operators --- include/kep3/epoch.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 6777500c..26d1e75d 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -204,14 +204,14 @@ class kep3_DLL_PUBLIC epoch { // template // kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { template > - kep3_DLL_PUBLIC epoch &operator+=(Duration &&duration) { + epoch &operator+=(Duration &&duration) { tp += chr::duration_cast(duration); return *this; } // template // kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { template > - kep3_DLL_PUBLIC epoch &operator-=(Duration &&duration) { + epoch &operator-=(Duration &&duration) { tp -= chr::duration_cast(duration); return *this; } @@ -226,13 +226,13 @@ class kep3_DLL_PUBLIC epoch { // template // kep3_DLL_PUBLIC epoch operator+(dur &&duration) { template > - kep3_DLL_PUBLIC epoch operator+(Duration &&duration) { + epoch operator+(Duration &&duration) { return epoch(tp + chr::duration_cast(duration)); } // template // kep3_DLL_PUBLIC epoch operator-(dur &&duration) { template > - kep3_DLL_PUBLIC epoch operator-(Duration &&duration) { + epoch operator-(Duration &&duration) { return epoch(tp - chr::duration_cast(duration)); } From b11c72b090490547b1256413d9ae4827c7e83956 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Sat, 30 Sep 2023 18:49:26 +0200 Subject: [PATCH 17/30] ==[ Cleanup ]== - Formatting - Deprecated methods removed - Documentation updated TODO ==== - More verbose documentation - Improve test coverage --- clang-format | 61 ------- include/kep3/epoch.hpp | 390 ++++++++++++++++++++--------------------- src/epoch.cpp | 383 ++++++++++++++-------------------------- test/epoch_test.cpp | 2 +- 4 files changed, 315 insertions(+), 521 deletions(-) delete mode 100644 clang-format diff --git a/clang-format b/clang-format deleted file mode 100644 index aee11add..00000000 --- a/clang-format +++ /dev/null @@ -1,61 +0,0 @@ -Language: Cpp -AccessModifierOffset: -4 -AlignAfterOpenBracket: true -AlignConsecutiveAssignments: false -AlignEscapedNewlinesLeft: false -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: true -BinPackParameters: true -BreakBeforeBinaryOperators: All -BreakBeforeBraces: Linux -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -ColumnLimit: 120 -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -IndentCaseLabels: true -IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 22312 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 2123 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never \ No newline at end of file diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 26d1e75d..8718ec41 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -27,247 +27,229 @@ * that are related to keplerian motions or models. */ - -namespace kep3 { - using namespace std::literals; - namespace chr = std::chrono; - using lint = long int; - using llint = long long int; - // template - // using dur = chr::duration>; - - template - struct is_duration - : std::false_type - { }; - - template - struct is_duration> - : std::true_type - { }; - - template - using enable_if_is_duration = std::enable_if_t::value, T>; - +namespace kep3 +{ +using namespace std::literals; +namespace chr = std::chrono; +using lint = long int; +using llint = long long int; + +template +struct is_duration + : std::false_type +{}; + +template +struct is_duration> + : std::true_type +{}; + +template +using enable_if_is_duration + = std::enable_if_t::value>; struct kep_clock : public chr::system_clock { - using rep = int_fast64_t; - using period = std::ratio<1, 1'000'000>; - using duration = chr::duration; - using time_point = chr::time_point; - static constexpr bool is_steady = false; - static constexpr chr::seconds y2k_offset{946684800s}; - - static constexpr time_point ref_epoch{kep_clock::time_point{} + y2k_offset}; - - static std::time_t to_time_t(const time_point &t) noexcept { - return static_cast( - chr::duration_cast(t.time_since_epoch() + y2k_offset) - .count()); - } - - static time_point from_time_t(std::time_t t) noexcept { - return chr::time_point_cast( - time_point(chr::seconds(t) - y2k_offset)); - } + /** + * @brief Custom clock. + * Used for constructing epochs with a custom reference point. + * In particular, by defining a custom clock, we avoid the overflow + * that std::chrono::system_clock suffers at +/- 292 years. + * To do that, we lower the resolution to 1 us (microsecond), + * which gives the clock a range of +/- 292 thousand years. + * + * NOTE: Adding durations of less than 1 us to an epoch (defined below) + * would not be registered. + * + * NOTE: As of C++20, the standard guarantees that std::chrono::system_clock + * uses the UNIX time reference point, which is midnight on 1 January 1970 (1970-01-01T00:00:00). + * We correct for that here in order to bring the reference point forward to + * midnight on 1 January 2000 (2000-01-01T00:00:00), which is 0 MJD2000. + */ + using rep = int_fast64_t; + // Resolution of (1 / 1'000'000)s = 1 us + using period = std::ratio<1, 1'000'000>; + using duration = chr::duration; + using time_point = chr::time_point; + static constexpr bool is_steady = false; + // Number of seconds from midnight on 1 Jan 1970 to midnight on 1 Jan 2000. + static constexpr chr::seconds y2k_offset{946684800s}; + + static constexpr time_point ref_epoch{kep_clock::time_point{} + y2k_offset}; + + static constexpr std::time_t to_time_t(const time_point &t) noexcept + { + return static_cast(chr::duration_cast(t.time_since_epoch() + y2k_offset).count()); + } + + static constexpr time_point from_time_t(std::time_t t) noexcept + { + return chr::time_point_cast(time_point(chr::seconds(t) - y2k_offset)); + } }; /// epoch class. /** - * This class defines and contains a non-gregorian date (i.e. a date expressed - * in julian form). It also provides the user with an interface to boost - * gregorian dates (see boost documentation at - * http://www.boost.org/doc/libs/1_42_0/doc/html/date_time.html) - * using the posix time. - * The date is defined in MJD2000 (double) as a - * private member - * - * @author Dario Izzo (dario.izzo _AT_ googlemail.com) + * This class defines and contains a non-Gregorian date (i.e., a date expressed in Julian format). + * The date is defined in MJD2000 format as a kep_clock::time_point private member. + * Types of non-Gregorian dates supported: + * - Julian Date (JD): the number of days passed since January 1, 4713 BC at 12:00 (noon). + * - Modified Julian Date (MJD): the number of days passed since November 17, 1858 at 00:00 (midnight). + * - Modified Julian Date 2000 (MJD2000): the number of days passed since Juanuary 1, 2000 at 00:00 (midnight). */ -class kep3_DLL_PUBLIC epoch { +class kep3_DLL_PUBLIC epoch +{ public: - /** Types of non gregorian dates supported. Julian Date (JD) is the number of - * days passed since January 1, 4713 BC at noon. Modified Julian Date (MJD) is - * the number of days passed since November 17, 1858 at 00:00 am. The Modified - * Julian Date 2000 (MJD2000) is the number of days passed since Juanuary 1, - * 2000 at 00:00am. - */ - enum class julian_type { MJD2000, MJD, JD }; - - /** Constructors */ - // Default constructor - epoch(); - - // Constructor for days (as a floating-point value) - epoch(const double epoch_in, const julian_type epoch_type = julian_type::MJD2000); - - // Constructor for const duration&) - - /** - * Constructs an epoch from a std::chrono::duration. - * The reference point is assumed to be MJD 0. - * \param[in] time The time as a duration - */ -// template -// epoch(const dur &duration) - template > - epoch(const Duration &duration) - : tp{kep_clock::time_point{} + duration} {} - - // Constructor for duration&&) -// template -// epoch(dur &&duration) : tp{kep_clock::time_point{} + duration} {} - template > - epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} {} - - // Constructor for a const duration&) - epoch(const kep_clock::time_point &time_point); - epoch(kep_clock::time_point &&time_point); - - // Constructor for microseconds - epoch(const int y,const int d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); - - /** Computing non-gregorian dates */ - /// jd getter. + enum class julian_type { MJD2000, MJD, JD }; + + /** Constructors */ + // Default constructor + epoch(); + + // Constructor for days (as a floating-point value) + explicit epoch( const double epoch_in, const julian_type epoch_type = julian_type::MJD2000); + /** - * Returns the julian date - * - * @return double containing the julian date - * + * Constructs an epoch from a std::chrono::duration. + * The reference point is assumed to be MJD2000. + * \param[in] time The time as a duration. */ + template > + explicit epoch(const Duration &duration) : tp{kep_clock::time_point{} + duration} + { + } + + // Constructor for duration&&) + template > + explicit epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} + { + } + + // Constructor for const time_point&) + epoch(const kep_clock::time_point &time_point); + + // Constructor for const time_point&&) + epoch(kep_clock::time_point &&time_point); + + // Constructor for datetime broken down into its constituents. + epoch(const int y, const int d, const int h = 0, const int min = 0, + const int s = 0, const int ms = 0, const int us = 0); + + /* Computing non-Gregorian dates */ + + /** + * @return Number of days since 0 JD (including fractional days). + */ constexpr double jd() const { return chr::duration>(tp.time_since_epoch() + 211813444800s).count(); } - /// mjd getter. /** - * Returns the modified julian date - * - * @return double containing the modified julian date - * - */ + * @return Number of days since 0 MJD (including fractional days). + */ constexpr double mjd() const { return chr::duration>(tp.time_since_epoch() + 4453401600s).count(); } - /// mjd2000 getter. /** - * Gets the modified julian date 2000 - * @return const reference to mjd2000 - */ + * @return Number of days since 0 MJD2000 (including fractional days). + */ constexpr double mjd2000() const { return chr::duration>(tp.time_since_epoch()).count(); } + /* Helper functions for constructors */ + static kep_clock::time_point make_tp(const int y, const int d, const int h = 0, const int min = 0, + const int s = 0, const int ms = 0, const int us = 0); + + static kep_clock::time_point make_tp(const double epoch_in, const julian_type epoch_type); + + // Conversions + static constexpr kep_clock::time_point tp_from_days(const double days); + + // Duration conversions + static constexpr double as_sec(kep_clock::duration&& d) + { + return std::chrono::duration(d).count(); + } + + // Printing + static auto as_utc_string(const kep_clock::time_point &); + + /** operator overloads for sum and diff (epoch-days) and comparison + * operators + * **/ + + kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, epoch const &epoch_in); - /** Interface to boost::posix_time::ptime */ - // [[nodiscard]] boost::posix_time::ptime get_posix_time() const; - - static kep_clock::time_point make_tp(const int y, const int d, - const int h = 0, const int min = 0, - const int s = 0, const int ms = 0, const int us = 0); - - static kep_clock::time_point make_tp(const double epoch_in, const julian_type epoch_type); - - // Conversions - // double tp_from_seconds(const double seconds) const; - static constexpr kep_clock::time_point tp_from_days(const double days); - // void set_tp_mjd2000( const double epoch_in ); - // void set_tp_mjd( const double epoch_in ); - // void set_tp_jd( const double epoch_in ); - - // Duration conversions - static constexpr double as_sec(kep_clock::duration d) { - return std::chrono::duration(d) - .count(); - } - // double as_days(); - - // Printing - static auto as_utc_string(const kep_clock::time_point &); - // static std::time_t as_gmtime(const kep_clock::time_point &); - - /** operator overloads for sum and diff (epoch-days) and comparison - * operators - * **/ - - // std::chrono::seconds day2sec(const double days) const; - // kep3_DLL_PUBLIC epoch epoch_from_string(const std::string &date); - // kep3_DLL_PUBLIC epoch epoch_from_iso_string(const std::string &date); - - kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, - epoch const &epoch_in); -// template -// kep3_DLL_PUBLIC epoch &operator+=(dur &&duration) { - template > - epoch &operator+=(Duration &&duration) { - tp += chr::duration_cast(duration); - return *this; - } -// template -// kep3_DLL_PUBLIC epoch &operator-=(dur &&duration) { template > - epoch &operator-=(Duration &&duration) { - tp -= chr::duration_cast(duration); - return *this; - } - - kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); - - // template - // kep3_DLL_PUBLIC epoch operator+(dur &&duration) { - template > - epoch operator+(Duration &&duration) { - return epoch(tp + chr::duration_cast(duration)); - } -// template -// kep3_DLL_PUBLIC epoch operator-(dur &&duration) { - template > - epoch operator-(Duration &&duration) { - return epoch(tp - chr::duration_cast(duration)); - } - - static constexpr auto days(const double value) { - return chr::duration_cast(chr::duration>(value)); - } - - static constexpr auto sec(const double value) { - return chr::duration_cast(chr::duration>(value)); - } - - kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, - const epoch &rhs); + epoch &operator+=(Duration &&duration) + { + tp += chr::duration_cast(duration); + return *this; + } + template > + epoch &operator-=(Duration &&duration) + { + tp -= chr::duration_cast(duration); + return *this; + } + + kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); + + template > + epoch operator+(const Duration &duration) + { + return epoch(tp + chr::duration_cast(duration)); + } + + template > + epoch operator-(const Duration &duration) + { + return epoch(tp - chr::duration_cast(duration)); + } + + static constexpr auto days(const double value) + { + return chr::duration_cast(chr::duration>(value)); + } + + static constexpr auto sec(const double value) + { + return chr::duration_cast(chr::duration>(value)); + } + + kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, const epoch &rhs); private: - // Serialization code - friend class boost::serialization::access; - template - void serialize(Archive &ar, const unsigned int) { - ar & boost::serialization::make_binary_object(&tp, sizeof(tp)); - } - // Serialization code (END) - - // Time point relative to 1 Jan 2000 (MJD2000) - kep_clock::time_point tp; + // Serialization code + friend class boost::serialization::access; + template + void serialize(Archive &ar, const unsigned int) + { + ar &boost::serialization::make_binary_object(&tp, sizeof(tp)); + } + // Serialization code (END) + + // Time point relative to 1 Jan 2000 (MJD2000) + kep_clock::time_point tp; }; - kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, - const epoch &epoch_in); +kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, const epoch &epoch_in); } // end of namespace kep3 -template <> struct fmt::formatter : fmt::ostream_formatter {}; - -// Serialization code (END) +template <> +struct fmt::formatter : fmt::ostream_formatter { +}; #endif // kep3_EPOCH_HPP diff --git a/src/epoch.cpp b/src/epoch.cpp index 389027ce..edf47645 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -22,268 +22,141 @@ namespace kep3 { - /// Constructor. - /** - * Constructs a reference epoch. - */ - epoch::epoch() - : tp{} - {} - - /// Constructor. - /** - * Constructs an epoch from a non-gregorian date. - * \param[in] epoch_in A double indicating the non-gregorian date - * \param[in] epoch_type epoch::julian_type - */ - epoch::epoch(const double epoch_in, const julian_type epoch_type) - : tp{ make_tp( epoch_in, epoch_type ) } - - { - } - - /// Constructor. - /** - * Constructs an epoch from a gregorian date. The time of the day is assumed to - * be midnight. \param[in] yr The gregorian year \param[in] mon The month of the - * year [0-11] \param[in] day The day of the month [1-31] \param[in] hr The hour - * of the day [0-23] \param[in] min The minutes [0-59] \param[in] s The seconds - * [0-59] \param[in] ms The milliseconds [0-999] \param[in] us The milliseconds - * [0-999] - */ - epoch::epoch(const int y, const int d, const int h, const int min, const int s, const int ms, const int us) - : tp{ make_tp( y, d, h, min, s, ms, us ) } - { - } - - - epoch::epoch( const kep_clock::time_point& time_point ) - : tp{ time_point } - { - } - - epoch::epoch( kep_clock::time_point&& time_point ) - : tp{ std::move( time_point ) } - { - } - - kep_clock::time_point - epoch::make_tp(const int y, const int d, const int h, const int min, - const int s, const int ms, const int us) - - { - return kep_clock::time_point{} + chr::years( y ) + chr::days( d ) + chr::hours( h ) + chr::minutes( min ) + chr::seconds( s ) + - chr::milliseconds( ms ) + chr::microseconds( us ); - } - - kep_clock::time_point epoch::make_tp( const double epoch_in, const julian_type epoch_type ) - { - switch ( epoch_type ) - { - case julian_type::MJD2000: - return epoch::tp_from_days( epoch_in ); - case julian_type::MJD: - return mjd2mjd2000( epoch::tp_from_days( epoch_in ) ); - case julian_type::JD: - return jd2mjd2000( epoch::tp_from_days( epoch_in ) ); - default: - throw; - } - } - // /// jd getter. - // /** - // * Returns the julian date - // * - // * @return double containing the julian date - // * - // */ - // constexpr double epoch::jd() const - // { - // return chr::duration>(tp.time_since_epoch() + 211813444800s).count(); - // } - - // /// mjd getter. - // /** - // * Returns the modified julian date - // * - // * @return double containing the modified julian date - // * - // */ - // constexpr double epoch::mjd() const - // { - // return chr::duration>(tp.time_since_epoch() + 4453401600s).count(); - // } - - // /// mjd2000 getter. - // /** - // * Gets the modified julian date 2000 - // * @return const reference to mjd2000 - // */ - // constexpr double epoch::mjd2000() const - // { - // return chr::duration>(tp.time_since_epoch()).count(); - // } - - /// Extracts the posix time - /** - * Returns the posix_time representation of the epoch. The method evaluates - * from the mjd2000 the number of days, months, seconds and - * micro/nano seconds passed since the 1st of January 2000 and uses this - * information to build the posix time - * - * @return ptime containing the posix time - * - */ - - // kep_clock::duration epoch::tp_from_seconds(const double seconds) const { - // return chr::duration_cast(chr::seconds(seconds)); - // } - - constexpr kep_clock::time_point epoch::tp_from_days( const double days ) - { - return kep_clock::time_point{} + - chr::duration_cast( - chr::duration>( days ) ); - } - - // void epoch::set_tp_mjd2000( const double days ) - // { - // // tp = tp_from_days( days ); - // // std::cout << days << " days in MJD2000: " << epoch::as_utc_string( tp ); - // } - // void epoch::set_tp_mjd( const double days ) - // { - // // tp = mjd2mjd2000( tp_from_days( days ) ); - // // std::cout << days << " days in MJD: " << epoch::as_utc_string( tp ); - // } - // void epoch::set_tp_jd( const double days ) - // { - // // tp = jd2mjd2000( tp_from_days( days ) ); - // // std::cout << days << " in JD: " << epoch::as_utc_string( tp ); - // } - - // double epoch::as_days() { - // return std::chrono::duration( - // tp.time_since_epoch()) - // .count(); - // } - - // std::time_t epoch::as_gmtime(const kep_clock::time_point &tp) { - // auto tt{kep_clock::to_time_t(tp)}; - // auto utc = std::gmtime(&tt); - // return std::mktime(utc); - // } - - auto epoch::as_utc_string( const kep_clock::time_point& tp ) - { - auto t = kep_clock::to_time_t( tp ); - return std::put_time( gmtime( &t ), "%FT%T"); - } +/** + * @brief Constructs a default epoch . + */ +epoch::epoch() : tp{} {} + +/** + * @brief Constructs an epoch from a non-Gregorian date. + * + * @param[in] epoch_in A double indicating the number of days + since day 0 in the specified calendar. + * @param[in] epoch_type epoch::julian_type + */ +epoch::epoch(const double epoch_in, const julian_type epoch_type) + : tp{make_tp(epoch_in, epoch_type)} {} + +/** + * @brief Constructs an epoch from offsets relative to 0 MJD2000. + * + * @param[in] y The number of years. + * @param[in] d The number of days. + * @param[in] h The number of hours. + * @param[in] min The number of minutes. + * @param[in] s The number of seconds. + * @param[in] ms The number of milliseconds. + * @param[in] us The number of microseconds. + */ +epoch::epoch(const int y, const int d, const int h, const int min, + const int s, const int ms, const int us) + : tp{make_tp(y, d, h, min, s, ms, us)} +{ +} - // template - // epoch& epoch::operator+=( dur&& rhs ) - // { - // /* addition of rhs to *this takes place here */ - // tp += chr::duration_cast( rhs ); - // return *this; - // } +/** + * @brief Constructs an epoch from a const reference to a time point. + * + * @param[in] time_point Self-explanatory. + */ +epoch::epoch(const kep_clock::time_point &time_point) : tp{time_point} {} - // template - // epoch& epoch::operator-=( dur&& rhs ) - // { - // /* addition of rhs to *this takes place here */ - // tp -= chr::duration_cast( rhs ); - // return *this; - // } +/** + * @brief Constructs an epoch from an rvalue reference to a time point. + * + * @param[in] time_point Self-explanatory. + */ +epoch::epoch(kep_clock::time_point &&time_point) : tp{time_point} {} - /// Returns an epoch constructed from a delimited string containing a date - /** - * Builds an epoch from a delimited string. Excess digits in fractional seconds - * will be dropped. Ex: "1:02:03.123456999" => "1:02:03.123456". This behavior - * depends on the precision defined in astro_constant.h used to compile - * - * Example: - * std::string ts("2002-01-20 23:59:54.003"); - * epoch e(epoch_from_string(ts)) - * - */ - // epoch epoch_from_string(const std::string &date) { - // return epoch(time_from_string(date)); - // } - /// Returns an epoch constructed from a non delimited iso string containing a - /// date - /** - * Builds an epoch from a non delimited iso string containing a date. - * - * Example: - * std::string ts("20020131T235959"); - * epoch e(epoch_from_iso_string(ts)) - * - */ - // epoch epoch_from_iso_string(const std::string &date) { - // return epoch(from_iso_string(date)); - // } +kep_clock::time_point epoch::make_tp(const int y, const int d, const int h, const int min, + const int s, const int ms, const int us) - /// Overload the stream operator for kep_toolbox::epoch - /** - * Streams out a date in the format 2000-Jan-01 00:12:30.123457 - * - * \param[in] s stream to which the epoch will be sent - * \param[in] now epoch to be sent to stream - * - * \return reference to s - * - */ - std::ostream& operator<<( std::ostream& s, const epoch& ep ) - { - s << epoch::as_utc_string(ep.tp); - return s; - } +{ + return kep_clock::time_point{} + chr::years(y) + chr::days(d) + chr::hours(h) + chr::minutes(min) + chr::seconds(s) + + chr::milliseconds(ms) + chr::microseconds(us); +} - bool operator>( const epoch& c1, const epoch& c2 ) - { - return c1.tp > c2.tp; - } - bool operator<( const epoch& c1, const epoch& c2 ) - { - return c1.tp < c2.tp; - } - bool operator>=( const epoch& c1, const epoch& c2 ) - { - return c1.tp >= c2.tp; - } - bool operator<=( const epoch& c1, const epoch& c2 ) - { - return c1.tp <= c2.tp; - } - bool operator==( const epoch& c1, const epoch& c2 ) - { - return c1.tp == c2.tp; - } - bool operator!=( const epoch& c1, const epoch& c2 ) - { - return c1.tp != c2.tp; - } +kep_clock::time_point epoch::make_tp(const double epoch_in, const julian_type epoch_type) +{ + switch (epoch_type) { + case julian_type::MJD2000: + return epoch::tp_from_days(epoch_in); + case julian_type::MJD: + return mjd2mjd2000(epoch::tp_from_days(epoch_in)); + case julian_type::JD: + return jd2mjd2000(epoch::tp_from_days(epoch_in)); + default: + throw; + } +} + + +/** + * @brief Creates time point from the number of days since 0 MJD2000. + * + * @return A time point + */ +constexpr kep_clock::time_point epoch::tp_from_days(const double days) +{ + return kep_clock::time_point{} + + chr::duration_cast(chr::duration>(days)); +} + +/** + * @brief Returns a time point formatted as a date/time string + * + * @param tp The time point. + * @return A formatted date/time string. + */ +auto epoch::as_utc_string(const kep_clock::time_point &tp) +{ + auto t = kep_clock::to_time_t(tp); + return std::put_time(gmtime(&t), "%FT%T"); +} + +/** + * @brief Streams out a date in the format 2000-Jan-01 00:12:30 + * + * @param[in] s Stream to which the epoch will be sent. + * @param[in] ep Epoch to be sent to the stream. + * + * @return Reference to s. + */ +std::ostream &operator<<(std::ostream &s, const epoch &ep) +{ + s << epoch::as_utc_string(ep.tp); + return s; +} - // template - // epoch operator+( const epoch& lhs, dur&& rhs ) - // { - // lhs.tp += - // chr::duration_cast( rhs ); // reuse compound assignment - // return lhs; // return the result by value (uses move constructor) - // } - // template - // epoch operator-( const epoch& lhs, dur&& rhs ) - // { - // lhs.tp -= - // chr::duration_cast( rhs ); // reuse compound assignment - // return lhs; // return the result by value (uses move constructor) - // } +bool operator>(const epoch &c1, const epoch &c2) +{ + return c1.tp > c2.tp; +} +bool operator<(const epoch &c1, const epoch &c2) +{ + return c1.tp < c2.tp; +} +bool operator>=(const epoch &c1, const epoch &c2) +{ + return c1.tp >= c2.tp; +} +bool operator<=(const epoch &c1, const epoch &c2) +{ + return c1.tp <= c2.tp; +} +bool operator==(const epoch &c1, const epoch &c2) +{ + return c1.tp == c2.tp; +} +bool operator!=(const epoch &c1, const epoch &c2) +{ + return c1.tp != c2.tp; +} - kep_clock::duration operator-( const epoch& lhs, const epoch& rhs ) - { - return lhs.tp - rhs.tp; - } +kep_clock::duration operator-(const epoch &lhs, const epoch &rhs) +{ + return lhs.tp - rhs.tp; +} } // namespace kep3 diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 8dd8561d..1aee8e3c 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani + // Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani // (bluescarni@gmail.com) // // This file is part of the kep3 library. From aa330585c9bd3c3e210f0ea25a8a03d83103612a Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:11:57 +0200 Subject: [PATCH 18/30] Restore CMakeLists.txt --- CMakeLists.txt | 165 +++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 88 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9b77487..f836f9ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,9 @@ cmake_minimum_required(VERSION 3.18.0) # NOTE: this should be done before the project command since the latter can set # CMAKE_BUILD_TYPE itself (it does so for nmake). if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - FORCE) + set(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." + FORCE) endif() project(kep3 VERSION 0.0.1 LANGUAGES CXX C) @@ -41,97 +41,90 @@ if(UNIX AND NOT APPLE) else() set(_kep3_INSTALL_LIBDIR_DEFAULT "lib") endif() - if(NOT kep3_INSTALL_LIBDIR) set(kep3_INSTALL_LIBDIR "${_kep3_INSTALL_LIBDIR_DEFAULT}" CACHE STRING "Library installation directory." FORCE) endif() - mark_as_advanced(kep3_INSTALL_LIBDIR) message(STATUS "Library installation directory: ${kep3_INSTALL_LIBDIR}") # Assemble the flags. set(kep3_CXX_FLAGS_DEBUG ${YACMA_CXX_FLAGS} ${YACMA_CXX_FLAGS_DEBUG}) set(kep3_CXX_FLAGS_RELEASE ${YACMA_CXX_FLAGS}) - if(YACMA_COMPILER_IS_MSVC) - # On both cl and clang-cl, disable the idiotic minmax macros and enable the bigobj option. - # Also, enable the WIN32_LEAN_AND_MEAN definition: - # https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly - list(APPEND kep3_CXX_FLAGS_DEBUG "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") - list(APPEND kep3_CXX_FLAGS_RELEASE "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") - - if(YACMA_COMPILER_IS_CLANGXX) - # clang-cl emits various warnings, let's just silence them. - # NOTE: at one point in the recent past, MSVC added an options similar to GCC's isystem: - # https://blogs.msdn.microsoft.com/vcblog/2017/12/13/broken-warnings-theory/ - # We probably just need to wait for this to be picked up by CMake/clang-cl. Let's - # revisit the issue in the future. - list(APPEND _kep3_CLANG_CL_DISABLED_WARNINGS - "-Wno-unused-variable" - "-Wno-inconsistent-dllimport" - "-Wno-unknown-pragmas" - "-Wno-unused-parameter" - "-Wno-sign-compare" - "-Wno-deprecated-declarations" - "-Wno-deprecated-dynamic-exception-spec" - "-Wno-old-style-cast" - "-Wno-sign-conversion" - "-Wno-non-virtual-dtor" - "-Wno-deprecated" - "-Wno-shadow" - "-Wno-shorten-64-to-32" - "-Wno-reserved-id-macro" - "-Wno-undef" - "-Wno-c++98-compat-pedantic" - "-Wno-documentation-unknown-command" - "-Wno-zero-as-null-pointer-constant" - "-Wno-language-extension-token" - "-Wno-gnu-anonymous-struct" - "-Wno-nested-anon-types" - "-Wno-documentation" - "-Wno-comma" - "-Wno-nonportable-system-include-path" - "-Wno-global-constructors" - "-Wno-redundant-parens" - "-Wno-exit-time-destructors" - "-Wno-missing-noreturn" - "-Wno-switch-enum" - "-Wno-covered-switch-default" - "-Wno-float-equal" - "-Wno-double-promotion" - "-Wno-microsoft-enum-value" - "-Wno-missing-prototypes" - "-Wno-implicit-fallthrough" - "-Wno-format-nonliteral" - "-Wno-cast-qual" - "-Wno-disabled-macro-expansion" - "-Wno-unused-private-field" - "-Wno-unused-template" - "-Wno-unused-macros" - "-Wno-extra-semi-stmt" - "-Wno-c++98-compat") - list(APPEND kep3_CXX_FLAGS_DEBUG ${_kep3_CLANG_CL_DISABLED_WARNINGS}) - list(APPEND kep3_CXX_FLAGS_RELEASE ${_kep3_CLANG_CL_DISABLED_WARNINGS}) - unset(_kep3_CLANG_CL_DISABLED_WARNINGS) - else() - # Same as above, disable some cl warnings. - list(APPEND kep3_CXX_FLAGS_DEBUG "/wd4459" "/wd4127" "/wd4251") - list(APPEND kep3_CXX_FLAGS_RELEASE "/wd4459" "/wd4127" "/wd4251") - endif() - - # Enable strict conformance mode, if supported. - set(CMAKE_REQUIRED_QUIET TRUE) - check_cxx_compiler_flag("/permissive-" _kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) - unset(CMAKE_REQUIRED_QUIET) - - if(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) - message(STATUS "The '/permissive-' flag is supported, enabling it.") - list(APPEND kep3_CXX_FLAGS_DEBUG "/permissive-") - list(APPEND kep3_CXX_FLAGS_RELEASE "/permissive-") - endif() - - unset(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + # On both cl and clang-cl, disable the idiotic minmax macros and enable the bigobj option. + # Also, enable the WIN32_LEAN_AND_MEAN definition: + # https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly + list(APPEND kep3_CXX_FLAGS_DEBUG "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") + list(APPEND kep3_CXX_FLAGS_RELEASE "-DNOMINMAX" "/bigobj" "-DWIN32_LEAN_AND_MEAN") + if(YACMA_COMPILER_IS_CLANGXX) + # clang-cl emits various warnings, let's just silence them. + # NOTE: at one point in the recent past, MSVC added an options similar to GCC's isystem: + # https://blogs.msdn.microsoft.com/vcblog/2017/12/13/broken-warnings-theory/ + # We probably just need to wait for this to be picked up by CMake/clang-cl. Let's + # revisit the issue in the future. + list(APPEND _kep3_CLANG_CL_DISABLED_WARNINGS + "-Wno-unused-variable" + "-Wno-inconsistent-dllimport" + "-Wno-unknown-pragmas" + "-Wno-unused-parameter" + "-Wno-sign-compare" + "-Wno-deprecated-declarations" + "-Wno-deprecated-dynamic-exception-spec" + "-Wno-old-style-cast" + "-Wno-sign-conversion" + "-Wno-non-virtual-dtor" + "-Wno-deprecated" + "-Wno-shadow" + "-Wno-shorten-64-to-32" + "-Wno-reserved-id-macro" + "-Wno-undef" + "-Wno-c++98-compat-pedantic" + "-Wno-documentation-unknown-command" + "-Wno-zero-as-null-pointer-constant" + "-Wno-language-extension-token" + "-Wno-gnu-anonymous-struct" + "-Wno-nested-anon-types" + "-Wno-documentation" + "-Wno-comma" + "-Wno-nonportable-system-include-path" + "-Wno-global-constructors" + "-Wno-redundant-parens" + "-Wno-exit-time-destructors" + "-Wno-missing-noreturn" + "-Wno-switch-enum" + "-Wno-covered-switch-default" + "-Wno-float-equal" + "-Wno-double-promotion" + "-Wno-microsoft-enum-value" + "-Wno-missing-prototypes" + "-Wno-implicit-fallthrough" + "-Wno-format-nonliteral" + "-Wno-cast-qual" + "-Wno-disabled-macro-expansion" + "-Wno-unused-private-field" + "-Wno-unused-template" + "-Wno-unused-macros" + "-Wno-extra-semi-stmt" + "-Wno-c++98-compat") + list(APPEND kep3_CXX_FLAGS_DEBUG ${_kep3_CLANG_CL_DISABLED_WARNINGS}) + list(APPEND kep3_CXX_FLAGS_RELEASE ${_kep3_CLANG_CL_DISABLED_WARNINGS}) + unset(_kep3_CLANG_CL_DISABLED_WARNINGS) + else() + # Same as above, disable some cl warnings. + list(APPEND kep3_CXX_FLAGS_DEBUG "/wd4459" "/wd4127" "/wd4251") + list(APPEND kep3_CXX_FLAGS_RELEASE "/wd4459" "/wd4127" "/wd4251") + endif() + # Enable strict conformance mode, if supported. + set(CMAKE_REQUIRED_QUIET TRUE) + check_cxx_compiler_flag("/permissive-" _kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + unset(CMAKE_REQUIRED_QUIET) + if(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) + message(STATUS "The '/permissive-' flag is supported, enabling it.") + list(APPEND kep3_CXX_FLAGS_DEBUG "/permissive-") + list(APPEND kep3_CXX_FLAGS_RELEASE "/permissive-") + endif() + unset(_kep3_MSVC_SUPPORTS_STRICT_CONFORMANCE) endif() # List of source files. @@ -164,7 +157,6 @@ target_compile_options(kep3 PRIVATE # Ensure that C++20 is employed when both compiling and consuming kep3. target_compile_features(kep3 PUBLIC cxx_std_20) - # Enforce vanilla C++20 when compiling kep3. set_property(TARGET kep3 PROPERTY CXX_EXTENSIONS NO) @@ -172,7 +164,6 @@ target_include_directories(kep3 PUBLIC $ $ $) - # Boost. # NOTE: need 1.73 for atomic_ref. find_package(Boost 1.73 REQUIRED) @@ -186,7 +177,6 @@ target_link_libraries(kep3 PUBLIC fmt::fmt) find_package(heyoka CONFIG REQUIRED) target_link_libraries(kep3 PUBLIC heyoka::heyoka) message(STATUS "heyoka version: ${heyoka_VERSION}") - if(heyoka_VERSION VERSION_LESS 0.21.0) message(FATAL_ERROR "heyoka>=0.21.0 is required, but heyoka ${heyoka_VERSION} was found instead") endif() @@ -217,7 +207,6 @@ install(TARGETS kep3 ARCHIVE DESTINATION "${kep3_INSTALL_LIBDIR}" RUNTIME DESTINATION bin ) - if(kep3_BUILD_TESTS) enable_testing() add_subdirectory(test) @@ -225,4 +214,4 @@ endif() if(kep3_BUILD_BENCHMARKS) add_subdirectory(benchmark) -endif() +endif() \ No newline at end of file From 1f8ec8cb6eabc5513067a78354080969a6a2b1ee Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:13:45 +0200 Subject: [PATCH 19/30] restore naming of headers in convert_julian_dates --- include/kep3/core_astro/convert_julian_dates.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/kep3/core_astro/convert_julian_dates.hpp b/include/kep3/core_astro/convert_julian_dates.hpp index 5d3f27ab..97822cb9 100644 --- a/include/kep3/core_astro/convert_julian_dates.hpp +++ b/include/kep3/core_astro/convert_julian_dates.hpp @@ -7,8 +7,8 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef CONVERT_JULIAN_DATES_HPP -#define CONVERT_JULIAN_DATES_HPP +#ifndef kep3_CONVERT_JULIAN_DATES_HPP +#define kep3_CONVERT_JULIAN_DATES_HPP #include "kep3/epoch.hpp" #include @@ -50,4 +50,4 @@ namespace kep3 } } // namespace kep3 -#endif // CONVERT_JULIAN_DATES_HPP +#endif // kep3_CONVERT_JULIAN_DATES_HPP From abf82903f0fdfc7fa890952f66cddd0990823540 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:19:15 +0200 Subject: [PATCH 20/30] epoch class sanitized --- include/kep3/epoch.hpp | 394 ++++++++++++++++++++--------------------- src/epoch.cpp | 2 +- 2 files changed, 196 insertions(+), 200 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 8718ec41..cc9a9e7d 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -27,229 +27,225 @@ * that are related to keplerian motions or models. */ -namespace kep3 -{ +namespace kep3 { using namespace std::literals; namespace chr = std::chrono; using lint = long int; using llint = long long int; -template -struct is_duration - : std::false_type -{}; +template struct is_duration : std::false_type {}; template -struct is_duration> - : std::true_type -{}; +struct is_duration> : std::true_type {}; template -using enable_if_is_duration - = std::enable_if_t::value>; +using enable_if_is_duration = std::enable_if_t::value>; struct kep_clock : public chr::system_clock { - /** - * @brief Custom clock. - * Used for constructing epochs with a custom reference point. - * In particular, by defining a custom clock, we avoid the overflow - * that std::chrono::system_clock suffers at +/- 292 years. - * To do that, we lower the resolution to 1 us (microsecond), - * which gives the clock a range of +/- 292 thousand years. - * - * NOTE: Adding durations of less than 1 us to an epoch (defined below) - * would not be registered. - * - * NOTE: As of C++20, the standard guarantees that std::chrono::system_clock - * uses the UNIX time reference point, which is midnight on 1 January 1970 (1970-01-01T00:00:00). - * We correct for that here in order to bring the reference point forward to - * midnight on 1 January 2000 (2000-01-01T00:00:00), which is 0 MJD2000. - */ - using rep = int_fast64_t; - // Resolution of (1 / 1'000'000)s = 1 us - using period = std::ratio<1, 1'000'000>; - using duration = chr::duration; - using time_point = chr::time_point; - static constexpr bool is_steady = false; - // Number of seconds from midnight on 1 Jan 1970 to midnight on 1 Jan 2000. - static constexpr chr::seconds y2k_offset{946684800s}; - - static constexpr time_point ref_epoch{kep_clock::time_point{} + y2k_offset}; - - static constexpr std::time_t to_time_t(const time_point &t) noexcept - { - return static_cast(chr::duration_cast(t.time_since_epoch() + y2k_offset).count()); - } - - static constexpr time_point from_time_t(std::time_t t) noexcept - { - return chr::time_point_cast(time_point(chr::seconds(t) - y2k_offset)); - } + /** + * @brief Custom clock. + * Used for constructing epochs with a custom reference point. + * In particular, by defining a custom clock, we avoid the overflow + * that std::chrono::system_clock suffers at +/- 292 years. + * To do that, we lower the resolution to 1 us (microsecond), + * which gives the clock a range of +/- 292 thousand years. + * + * NOTE: Adding durations of less than 1 us to an epoch (defined below) + * would not be registered. + * + * NOTE: As of C++20, the standard guarantees that std::chrono::system_clock + * uses the UNIX time reference point, which is midnight on 1 January 1970 + * (1970-01-01T00:00:00). We correct for that here in order to bring the + * reference point forward to midnight on 1 January 2000 + * (2000-01-01T00:00:00), which is 0 MJD2000. + */ + using rep = int_fast64_t; + // Resolution of (1 / 1'000'000)s = 1 us + using period = std::ratio<1, 1'000'000>; + using duration = chr::duration; + using time_point = chr::time_point; + static constexpr bool is_steady = false; + // Number of seconds from midnight on 1 Jan 1970 to midnight on 1 Jan 2000. + static constexpr chr::seconds y2k_offset{946684800s}; + + static constexpr time_point ref_epoch{kep_clock::time_point{} + y2k_offset}; + + static constexpr std::time_t to_time_t(const time_point &t) noexcept { + return static_cast( + chr::duration_cast(t.time_since_epoch() + y2k_offset) + .count()); + } + + static constexpr time_point from_time_t(std::time_t t) noexcept { + return chr::time_point_cast( + time_point(chr::seconds(t) - y2k_offset)); + } }; /// epoch class. /** - * This class defines and contains a non-Gregorian date (i.e., a date expressed in Julian format). - * The date is defined in MJD2000 format as a kep_clock::time_point private member. - * Types of non-Gregorian dates supported: - * - Julian Date (JD): the number of days passed since January 1, 4713 BC at 12:00 (noon). - * - Modified Julian Date (MJD): the number of days passed since November 17, 1858 at 00:00 (midnight). - * - Modified Julian Date 2000 (MJD2000): the number of days passed since Juanuary 1, 2000 at 00:00 (midnight). + * This class defines and contains a non-Gregorian date (i.e., a date expressed + * in Julian format). The date is defined in MJD2000 format as a + * kep_clock::time_point private member. Types of non-Gregorian dates supported: + * - Julian Date (JD): the number of days passed since January 1, 4713 BC + * at 12:00 (noon). + * - Modified Julian Date (MJD): the number of days passed since November + * 17, 1858 at 00:00 (midnight). + * - Modified Julian Date 2000 (MJD2000): the number of days passed since + * Juanuary 1, 2000 at 00:00 (midnight). */ -class kep3_DLL_PUBLIC epoch -{ +class kep3_DLL_PUBLIC epoch { public: - enum class julian_type { MJD2000, MJD, JD }; - - /** Constructors */ - // Default constructor - epoch(); - - // Constructor for days (as a floating-point value) - explicit epoch( const double epoch_in, const julian_type epoch_type = julian_type::MJD2000); - - /** - * Constructs an epoch from a std::chrono::duration. - * The reference point is assumed to be MJD2000. - * \param[in] time The time as a duration. - */ - template > - explicit epoch(const Duration &duration) : tp{kep_clock::time_point{} + duration} - { - } - - // Constructor for duration&&) - template > - explicit epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} - { - } - - // Constructor for const time_point&) - epoch(const kep_clock::time_point &time_point); - - // Constructor for const time_point&&) - epoch(kep_clock::time_point &&time_point); - - // Constructor for datetime broken down into its constituents. - epoch(const int y, const int d, const int h = 0, const int min = 0, - const int s = 0, const int ms = 0, const int us = 0); - - /* Computing non-Gregorian dates */ - - /** - * @return Number of days since 0 JD (including fractional days). - */ - constexpr double jd() const - { - return chr::duration>(tp.time_since_epoch() + 211813444800s).count(); - } - - /** - * @return Number of days since 0 MJD (including fractional days). - */ - constexpr double mjd() const - { - return chr::duration>(tp.time_since_epoch() + 4453401600s).count(); - } - - /** - * @return Number of days since 0 MJD2000 (including fractional days). - */ - constexpr double mjd2000() const - { - return chr::duration>(tp.time_since_epoch()).count(); - } - - /* Helper functions for constructors */ - static kep_clock::time_point make_tp(const int y, const int d, const int h = 0, const int min = 0, - const int s = 0, const int ms = 0, const int us = 0); - - static kep_clock::time_point make_tp(const double epoch_in, const julian_type epoch_type); - - // Conversions - static constexpr kep_clock::time_point tp_from_days(const double days); - - // Duration conversions - static constexpr double as_sec(kep_clock::duration&& d) - { - return std::chrono::duration(d).count(); - } - - // Printing - static auto as_utc_string(const kep_clock::time_point &); - - /** operator overloads for sum and diff (epoch-days) and comparison - * operators - * **/ - - kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, epoch const &epoch_in); - - template > - epoch &operator+=(Duration &&duration) - { - tp += chr::duration_cast(duration); - return *this; - } - - template > - epoch &operator-=(Duration &&duration) - { - tp -= chr::duration_cast(duration); - return *this; - } - - kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); - kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); - - template > - epoch operator+(const Duration &duration) - { - return epoch(tp + chr::duration_cast(duration)); - } - - template > - epoch operator-(const Duration &duration) - { - return epoch(tp - chr::duration_cast(duration)); - } - - static constexpr auto days(const double value) - { - return chr::duration_cast(chr::duration>(value)); - } - - static constexpr auto sec(const double value) - { - return chr::duration_cast(chr::duration>(value)); - } - - kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, const epoch &rhs); + enum class julian_type { MJD2000, MJD, JD }; + + /** Constructors */ + // Default constructor + epoch(); + + // Constructor for days (as a floating-point value) + explicit epoch(double epoch_in, + julian_type epoch_type = julian_type::MJD2000); + + /** + * Constructs an epoch from a std::chrono::duration. + * The reference point is assumed to be MJD2000. + * \param[in] time The time as a duration. + */ + template > + explicit epoch(const Duration &duration) + : tp{kep_clock::time_point{} + duration} {} + + // Constructor for duration&&) + template > + explicit epoch(Duration &&duration) + : tp{kep_clock::time_point{} + duration} {} + + // Constructor for const time_point&) + explicit epoch(const kep_clock::time_point &time_point); + + // Constructor for const time_point&&) + explicit epoch(kep_clock::time_point &&time_point); + + // Constructor for datetime broken down into its constituents. + epoch(int y, int d, int h = 0, int min = 0, + int s = 0, int ms = 0, int us = 0); + + /* Computing non-Gregorian dates */ + + /** + * @return Number of days since 0 JD (including fractional days). + */ + [[nodiscard]] constexpr double jd() const { + return chr::duration>(tp.time_since_epoch() + + 211813444800s) + .count(); + } + + /** + * @return Number of days since 0 MJD (including fractional days). + */ + [[nodiscard]] constexpr double mjd() const { + return chr::duration>(tp.time_since_epoch() + + 4453401600s) + .count(); + } + + /** + * @return Number of days since 0 MJD2000 (including fractional days). + */ + [[nodiscard]] constexpr double mjd2000() const { + return chr::duration>(tp.time_since_epoch()) + .count(); + } + + /* Helper functions for constructors */ + static kep_clock::time_point make_tp(int y, int d, + int h = 0, int min = 0, + int s = 0, int ms = 0, + int us = 0); + + static kep_clock::time_point make_tp(double epoch_in, + julian_type epoch_type); + + // Conversions + static constexpr kep_clock::time_point tp_from_days(double days); + + // Duration conversions + static constexpr double as_sec(kep_clock::duration &&d) { + return std::chrono::duration(d) + .count(); + } + + // Printing + static auto as_utc_string(const kep_clock::time_point &); + + /** operator overloads for sum and diff (epoch-days) and comparison + * operators + * **/ + + kep3_DLL_PUBLIC friend std::ostream &operator<<(std::ostream &s, + epoch const &epoch_in); + + template > + epoch &operator+=(Duration &&duration) { + tp += chr::duration_cast(duration); + return *this; + } + + template > + epoch &operator-=(Duration &&duration) { + tp -= chr::duration_cast(duration); + return *this; + } + + kep3_DLL_PUBLIC friend bool operator>(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator>=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator<=(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator==(const epoch &c1, const epoch &c2); + kep3_DLL_PUBLIC friend bool operator!=(const epoch &c1, const epoch &c2); + + template > + epoch operator+(const Duration &duration) { + return epoch(tp + chr::duration_cast(duration)); + } + + template > + epoch operator-(const Duration &duration) { + return epoch(tp - chr::duration_cast(duration)); + } + + static constexpr auto days(const double value) { + return chr::duration_cast( + chr::duration>(value)); + } + + static constexpr auto sec(const double value) { + return chr::duration_cast( + chr::duration>(value)); + } + + kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, + const epoch &rhs); private: - // Serialization code - friend class boost::serialization::access; - template - void serialize(Archive &ar, const unsigned int) - { - ar &boost::serialization::make_binary_object(&tp, sizeof(tp)); - } - // Serialization code (END) - - // Time point relative to 1 Jan 2000 (MJD2000) - kep_clock::time_point tp; + // Serialization code + friend class boost::serialization::access; + template void serialize(Archive &ar, const unsigned int) { + ar &boost::serialization::make_binary_object(&tp, sizeof(tp)); + } + // Serialization code (END) + + // Time point relative to 1 Jan 2000 (MJD2000) + kep_clock::time_point tp; }; -kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, const epoch &epoch_in); +kep3_DLL_PUBLIC std::ostream &operator<<(std::ostream &s, + const epoch &epoch_in); } // end of namespace kep3 -template <> -struct fmt::formatter : fmt::ostream_formatter { -}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; #endif // kep3_EPOCH_HPP diff --git a/src/epoch.cpp b/src/epoch.cpp index edf47645..9985d1bc 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -25,7 +25,7 @@ namespace kep3 /** * @brief Constructs a default epoch . */ -epoch::epoch() : tp{} {} +epoch::epoch() = default; /** * @brief Constructs an epoch from a non-Gregorian date. From fcaddf801b26274c0c696cd1300b201e520f2f0a Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:35:27 +0200 Subject: [PATCH 21/30] enums back one level --- include/kep3/epoch.hpp | 19 ++++++++----------- test/epoch_test.cpp | 4 ++-- test/planet_jpl_lp_test.cpp | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index cc9a9e7d..8c052caa 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -97,7 +97,7 @@ struct kep_clock : public chr::system_clock { */ class kep3_DLL_PUBLIC epoch { public: - enum class julian_type { MJD2000, MJD, JD }; + enum julian_type { MJD2000, MJD, JD }; /** Constructors */ // Default constructor @@ -105,7 +105,7 @@ class kep3_DLL_PUBLIC epoch { // Constructor for days (as a floating-point value) explicit epoch(double epoch_in, - julian_type epoch_type = julian_type::MJD2000); + julian_type epoch_type = MJD2000); /** * Constructs an epoch from a std::chrono::duration. @@ -116,7 +116,7 @@ class kep3_DLL_PUBLIC epoch { explicit epoch(const Duration &duration) : tp{kep_clock::time_point{} + duration} {} - // Constructor for duration&&) + // Constructor from duration&&) template > explicit epoch(Duration &&duration) : tp{kep_clock::time_point{} + duration} {} @@ -128,8 +128,8 @@ class kep3_DLL_PUBLIC epoch { explicit epoch(kep_clock::time_point &&time_point); // Constructor for datetime broken down into its constituents. - epoch(int y, int d, int h = 0, int min = 0, - int s = 0, int ms = 0, int us = 0); + explicit epoch(int y, int d, int h = 0, int min = 0, int s = 0, int ms = 0, + int us = 0); /* Computing non-Gregorian dates */ @@ -160,13 +160,10 @@ class kep3_DLL_PUBLIC epoch { } /* Helper functions for constructors */ - static kep_clock::time_point make_tp(int y, int d, - int h = 0, int min = 0, - int s = 0, int ms = 0, - int us = 0); + static kep_clock::time_point make_tp(int y, int d, int h = 0, int min = 0, + int s = 0, int ms = 0, int us = 0); - static kep_clock::time_point make_tp(double epoch_in, - julian_type epoch_type); + static kep_clock::time_point make_tp(double epoch_in, julian_type epoch_type); // Conversions static constexpr kep_clock::time_point tp_from_days(double days); diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 1aee8e3c..ea0d3ab9 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -59,8 +59,8 @@ TEST_CASE( "construct" ) // // test conversions REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - REQUIRE(epoch(0.).mjd() == epoch(51544, epoch::julian_type::MJD).mjd()); - REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); + REQUIRE(epoch(0.).mjd() == epoch(51544., epoch::MJD).mjd()); + REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::JD).jd()); // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } diff --git a/test/planet_jpl_lp_test.cpp b/test/planet_jpl_lp_test.cpp index 6869558e..946ce37a 100644 --- a/test/planet_jpl_lp_test.cpp +++ b/test/planet_jpl_lp_test.cpp @@ -136,7 +136,7 @@ TEST_CASE("eph") { REQUIRE(kep3_tests::floating_point_error_vector(v, pos_vel_0[1]) < 0.01); } jpl_lp udpla{"uranus"}; - REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534, kep3::epoch::julian_type::MJD2000)), + REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534., kep3::epoch::MJD2000)), std::domain_error); } From ea0acfb558fdfca279d8d515d866e10fdf354d51 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:46:36 +0200 Subject: [PATCH 22/30] restored clang format --- clang-format | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 clang-format diff --git a/clang-format b/clang-format new file mode 100644 index 00000000..aee11add --- /dev/null +++ b/clang-format @@ -0,0 +1,61 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Linux +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 22312 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 2123 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never \ No newline at end of file From 4b6649107808ee338e25ebc3261863d6f9602843 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:49:25 +0200 Subject: [PATCH 23/30] small --- test/epoch_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index ea0d3ab9..48d387f9 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -14,7 +14,7 @@ #include #include -#include "kep3/epoch.hpp" +#include #include "catch.hpp" From f1eb4d4f715be3b8fe769eb8e9e42c569d8c2e26 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sat, 30 Sep 2023 21:55:21 +0200 Subject: [PATCH 24/30] round of clang format --- src/epoch.cpp | 104 ++++++++++++----------------- src/planets/keplerian.cpp | 13 ++-- test/epoch_test.cpp | 133 +++++++++++++++++++------------------- 3 files changed, 111 insertions(+), 139 deletions(-) diff --git a/src/epoch.cpp b/src/epoch.cpp index 9985d1bc..57d8bc50 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -19,8 +19,7 @@ #include "kep3/core_astro/convert_julian_dates.hpp" #include "kep3/epoch.hpp" -namespace kep3 -{ +namespace kep3 { /** * @brief Constructs a default epoch . @@ -48,11 +47,9 @@ epoch::epoch(const double epoch_in, const julian_type epoch_type) * @param[in] ms The number of milliseconds. * @param[in] us The number of microseconds. */ -epoch::epoch(const int y, const int d, const int h, const int min, - const int s, const int ms, const int us) - : tp{make_tp(y, d, h, min, s, ms, us)} -{ -} +epoch::epoch(const int y, const int d, const int h, const int min, const int s, + const int ms, const int us) + : tp{make_tp(y, d, h, min, s, ms, us)} {} /** * @brief Constructs an epoch from a const reference to a time point. @@ -68,39 +65,39 @@ epoch::epoch(const kep_clock::time_point &time_point) : tp{time_point} {} */ epoch::epoch(kep_clock::time_point &&time_point) : tp{time_point} {} - -kep_clock::time_point epoch::make_tp(const int y, const int d, const int h, const int min, - const int s, const int ms, const int us) +kep_clock::time_point epoch::make_tp(const int y, const int d, const int h, + const int min, const int s, const int ms, + const int us) { - return kep_clock::time_point{} + chr::years(y) + chr::days(d) + chr::hours(h) + chr::minutes(min) + chr::seconds(s) - + chr::milliseconds(ms) + chr::microseconds(us); + return kep_clock::time_point{} + chr::years(y) + chr::days(d) + + chr::hours(h) + chr::minutes(min) + chr::seconds(s) + + chr::milliseconds(ms) + chr::microseconds(us); } -kep_clock::time_point epoch::make_tp(const double epoch_in, const julian_type epoch_type) -{ - switch (epoch_type) { - case julian_type::MJD2000: - return epoch::tp_from_days(epoch_in); - case julian_type::MJD: - return mjd2mjd2000(epoch::tp_from_days(epoch_in)); - case julian_type::JD: - return jd2mjd2000(epoch::tp_from_days(epoch_in)); - default: - throw; - } +kep_clock::time_point epoch::make_tp(const double epoch_in, + const julian_type epoch_type) { + switch (epoch_type) { + case julian_type::MJD2000: + return epoch::tp_from_days(epoch_in); + case julian_type::MJD: + return mjd2mjd2000(epoch::tp_from_days(epoch_in)); + case julian_type::JD: + return jd2mjd2000(epoch::tp_from_days(epoch_in)); + default: + throw; + } } - /** * @brief Creates time point from the number of days since 0 MJD2000. * * @return A time point */ -constexpr kep_clock::time_point epoch::tp_from_days(const double days) -{ - return kep_clock::time_point{} - + chr::duration_cast(chr::duration>(days)); +constexpr kep_clock::time_point epoch::tp_from_days(const double days) { + return kep_clock::time_point{} + + chr::duration_cast( + chr::duration>(days)); } /** @@ -109,10 +106,9 @@ constexpr kep_clock::time_point epoch::tp_from_days(const double days) * @param tp The time point. * @return A formatted date/time string. */ -auto epoch::as_utc_string(const kep_clock::time_point &tp) -{ - auto t = kep_clock::to_time_t(tp); - return std::put_time(gmtime(&t), "%FT%T"); +auto epoch::as_utc_string(const kep_clock::time_point &tp) { + auto t = kep_clock::to_time_t(tp); + return std::put_time(gmtime(&t), "%FT%T"); } /** @@ -123,40 +119,20 @@ auto epoch::as_utc_string(const kep_clock::time_point &tp) * * @return Reference to s. */ -std::ostream &operator<<(std::ostream &s, const epoch &ep) -{ - s << epoch::as_utc_string(ep.tp); - return s; +std::ostream &operator<<(std::ostream &s, const epoch &ep) { + s << epoch::as_utc_string(ep.tp); + return s; } -bool operator>(const epoch &c1, const epoch &c2) -{ - return c1.tp > c2.tp; -} -bool operator<(const epoch &c1, const epoch &c2) -{ - return c1.tp < c2.tp; -} -bool operator>=(const epoch &c1, const epoch &c2) -{ - return c1.tp >= c2.tp; -} -bool operator<=(const epoch &c1, const epoch &c2) -{ - return c1.tp <= c2.tp; -} -bool operator==(const epoch &c1, const epoch &c2) -{ - return c1.tp == c2.tp; -} -bool operator!=(const epoch &c1, const epoch &c2) -{ - return c1.tp != c2.tp; -} +bool operator>(const epoch &c1, const epoch &c2) { return c1.tp > c2.tp; } +bool operator<(const epoch &c1, const epoch &c2) { return c1.tp < c2.tp; } +bool operator>=(const epoch &c1, const epoch &c2) { return c1.tp >= c2.tp; } +bool operator<=(const epoch &c1, const epoch &c2) { return c1.tp <= c2.tp; } +bool operator==(const epoch &c1, const epoch &c2) { return c1.tp == c2.tp; } +bool operator!=(const epoch &c1, const epoch &c2) { return c1.tp != c2.tp; } -kep_clock::duration operator-(const epoch &lhs, const epoch &rhs) -{ - return lhs.tp - rhs.tp; +kep_clock::duration operator-(const epoch &lhs, const epoch &rhs) { + return lhs.tp - rhs.tp; } } // namespace kep3 diff --git a/src/planets/keplerian.cpp b/src/planets/keplerian.cpp index ffa567fe..e905923c 100644 --- a/src/planets/keplerian.cpp +++ b/src/planets/keplerian.cpp @@ -7,13 +7,12 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - #include #include +#include #include #include -#include #include #include @@ -166,11 +165,11 @@ std::string keplerian::get_extra_info() const { retval += fmt::format("Mean anomly (deg.): {}\n", kep3::f2m(par[5], par[1]) * kep3::RAD2DEG); } - retval += fmt::format("Elements reference epoch (MJD2000): {}\n", - m_ref_epoch) + - fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + - fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + - fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); + retval += + fmt::format("Elements reference epoch (MJD2000): {}\n", m_ref_epoch) + + fmt::format("Elements reference epoch (date): {}\n", m_ref_epoch) + + fmt::format("r at ref. = {}\n", m_pos_vel_0[0]) + + fmt::format("v at ref. = {}\n", m_pos_vel_0[1]); return retval; } diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 48d387f9..c72a378a 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -1,4 +1,4 @@ - // Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani +// Copyright 2023, 2024 Dario Izzo (dario.izzo@gmail.com), Francesco Biscani // (bluescarni@gmail.com) // // This file is part of the kep3 library. @@ -23,79 +23,76 @@ using kep3::kep_clock; using namespace std::literals; namespace chr = std::chrono; -TEST_CASE( "construct" ) -{ - // test syntax - // // > 2000 - REQUIRE_NOTHROW( epoch() ); - REQUIRE_NOTHROW( epoch( 123.456 ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD2000 ) ); - REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( 0.0, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( 123.456, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( 34, 364, 11, 36, 21, 121, 841 ) ); - // // > 2000 - // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); - // REQUIRE_NOTHROW( epoch( posix_time_test ) ); - // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); - // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << - // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; +TEST_CASE("construct") { + // test syntax + // // > 2000 + REQUIRE_NOTHROW(epoch()); + REQUIRE_NOTHROW(epoch(123.456)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD2000)); + REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(34, 364, 11, 36, 21, 121, 841)); + // // > 2000 + // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); + // REQUIRE_NOTHROW( epoch( posix_time_test ) ); + // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); + // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << + // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; - // // < 2000 - REQUIRE_NOTHROW( epoch( -123.456 ) ); - REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::MJD2000 ) ); - REQUIRE_NOTHROW( epoch( -0.0, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::JD ) ); - REQUIRE_NOTHROW( epoch( -0.0, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( -123.456, epoch::julian_type::MJD ) ); - REQUIRE_NOTHROW( epoch( -34, 364, 11, 36, 21, 121, 841 ) ); - // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); - // REQUIRE_NOTHROW(epoch(posix_time_test2)); - // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); - // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << - // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; + // // < 2000 + REQUIRE_NOTHROW(epoch(-123.456)); + REQUIRE_NOTHROW(epoch(-123.456, epoch::julian_type::MJD2000)); + REQUIRE_NOTHROW(epoch(-0.0, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(-123.456, epoch::julian_type::JD)); + REQUIRE_NOTHROW(epoch(-0.0, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(-123.456, epoch::julian_type::MJD)); + REQUIRE_NOTHROW(epoch(-34, 364, 11, 36, 21, 121, 841)); + // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); + // REQUIRE_NOTHROW(epoch(posix_time_test2)); + // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); + // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << + // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; - // // test conversions - REQUIRE(epoch(123.456).mjd2000() == - epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - REQUIRE(epoch(0.).mjd() == epoch(51544., epoch::MJD).mjd()); - REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::JD).jd()); - // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); + // // test conversions + REQUIRE(epoch(123.456).mjd2000() == + epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); + REQUIRE(epoch(0.).mjd() == epoch(51544., epoch::MJD).mjd()); + REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::JD).jd()); + // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); } -TEST_CASE( "epoch_operators" ) -{ - REQUIRE( epoch( 34, 10 ) == epoch( 34, 10 ) ); - REQUIRE( epoch( 34, 10 ) != epoch( 34, 11 ) ); - // Testing us precision - REQUIRE( epoch( 34, 10 ) != epoch( 34, 10, 0, 0, 0, 0, 1 ) ); - // Check that ns precision is not supported - REQUIRE( epoch( 0, 10 ) == - epoch( 0, 10, 0, 0, 0, 0, 0 ) + chr::nanoseconds(100) ); +TEST_CASE("epoch_operators") { + REQUIRE(epoch(34, 10) == epoch(34, 10)); + REQUIRE(epoch(34, 10) != epoch(34, 11)); + // Testing us precision + REQUIRE(epoch(34, 10) != epoch(34, 10, 0, 0, 0, 0, 1)); + // Check that ns precision is not supported + REQUIRE(epoch(0, 10) == epoch(0, 10, 0, 0, 0, 0, 0) + chr::nanoseconds(100)); - // Conversion from double (defaults to days) - REQUIRE( epoch( 1. ) > epoch( 0. ) ); - REQUIRE( epoch( 1. ) >= epoch( 1. ) ); - REQUIRE( epoch( 1. ) >= epoch( 0. ) ); - REQUIRE( epoch( 0. ) < epoch( 1. ) ); - REQUIRE( epoch( 1. ) <= epoch( 1. ) ); - epoch today( 0. ); - today += chr::days( 100 ); - REQUIRE( today == epoch( 0, 100 ) ); - today -= chr::duration_cast( chr::days( 100 ) ); - REQUIRE( today == epoch() ); - auto oneday{chr::days( 1 )}; - auto yesterday{today - chr::duration_cast( oneday )}; - auto yesterday1{today - oneday}; - REQUIRE(yesterday == yesterday1); + // Conversion from double (defaults to days) + REQUIRE(epoch(1.) > epoch(0.)); + REQUIRE(epoch(1.) >= epoch(1.)); + REQUIRE(epoch(1.) >= epoch(0.)); + REQUIRE(epoch(0.) < epoch(1.)); + REQUIRE(epoch(1.) <= epoch(1.)); + epoch today(0.); + today += chr::days(100); + REQUIRE(today == epoch(0, 100)); + today -= chr::duration_cast(chr::days(100)); + REQUIRE(today == epoch()); + auto oneday{chr::days(1)}; + auto yesterday{today - chr::duration_cast(oneday)}; + auto yesterday1{today - oneday}; + REQUIRE(yesterday == yesterday1); - REQUIRE( yesterday == epoch( 0, -1 ) ); - today = yesterday + chr::duration_cast( chr::days( 1 ) ); - REQUIRE( today == epoch() ); - auto diff{ today - yesterday }; - REQUIRE( diff == chr::duration_cast( chr::days( 1 ) ) ); - REQUIRE_NOTHROW( ( std::cout << epoch() ) ); + REQUIRE(yesterday == epoch(0, -1)); + today = yesterday + chr::duration_cast(chr::days(1)); + REQUIRE(today == epoch()); + auto diff{today - yesterday}; + REQUIRE(diff == chr::duration_cast(chr::days(1))); + REQUIRE_NOTHROW((std::cout << epoch())); } // TEST_CASE("conversions_from_string") { From 2a900fb243d68e0c3ccffc05f0aec5c4559f81dc Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Sun, 1 Oct 2023 09:55:58 +0200 Subject: [PATCH 25/30] rename --- clang-format => .clang-format | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clang-format => .clang-format (100%) diff --git a/clang-format b/.clang-format similarity index 100% rename from clang-format rename to .clang-format From ac4daacb07cf2d4753ff21243fb404984906f2d1 Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:07:06 +0200 Subject: [PATCH 26/30] ==[ Updated epoch class ]== - Epoch now has a constructor epoch(y, mon, d, h, min, s, ms, us) - Improvements in printing (Clang shouldn't complain about thread safety) TODO ==== - Still no conversion from string. That would probably happen at the Python end in a static function, which would parse the string and then use the decoposed datetime object with the new constructor above. --- .../kep3/core_astro/convert_julian_dates.hpp | 42 +++---------- include/kep3/epoch.hpp | 47 ++++++++------- src/epoch.cpp | 52 ++++++++++------ test/epoch_test.cpp | 59 ++++++------------- 4 files changed, 84 insertions(+), 116 deletions(-) diff --git a/include/kep3/core_astro/convert_julian_dates.hpp b/include/kep3/core_astro/convert_julian_dates.hpp index 97822cb9..946dc6d3 100644 --- a/include/kep3/core_astro/convert_julian_dates.hpp +++ b/include/kep3/core_astro/convert_julian_dates.hpp @@ -14,40 +14,14 @@ #include namespace kep3 { - // inline double jd2mjd(double in) { return (in - 2400000.5); } - // inline double jd2mjd2000(double in) { return (in - 2451544.5); } - // inline double mjd2jd(double in) { return (in + 2400000.5); } - // inline double mjd2mjd2000(double in) { return (in - 51544); } - // inline double mjd20002jd(double in) { return (in + 2451544.5); } - // inline double mjd20002mjd(double in) { return (in + 51544); } - inline constexpr kep_clock::time_point jd2mjd( const kep_clock::time_point& in ) - { - return in - 207360043200s; - } - inline constexpr kep_clock::time_point - jd2mjd2000( const kep_clock::time_point& in ) - { - return in - 211813444800s; - } - inline constexpr kep_clock::time_point mjd2jd( const kep_clock::time_point& in ) - { - return in + 207360043200s; - } - inline constexpr kep_clock::time_point - mjd2mjd2000( const kep_clock::time_point& in ) - { - return in - 4453401600s; - } - inline constexpr kep_clock::time_point - mjd20002jd( const kep_clock::time_point& in ) - { - return in + 211813444800s; - } - inline constexpr kep_clock::time_point - mjd20002mjd( const kep_clock::time_point& in ) - { - return in + 4453401600s; - } + inline double jd2mjd(double in) { return (in - 2400000.5); } + inline double jd2mjd2000(double in) { return (in - 2451544.5); } + inline double mjd2jd(double in) { return (in + 2400000.5); } + inline double mjd2mjd2000(double in) { return (in - 51544); } + inline double mjd20002jd(double in) { return (in + 2451544.5); } + inline double mjd20002mjd(double in){ return (in + 51544); } + + } // namespace kep3 #endif // kep3_CONVERT_JULIAN_DATES_HPP diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 8c052caa..11b86aac 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -20,6 +20,7 @@ #include #include #include +#include /// Keplerian Toolbox /** @@ -97,7 +98,7 @@ struct kep_clock : public chr::system_clock { */ class kep3_DLL_PUBLIC epoch { public: - enum julian_type { MJD2000, MJD, JD }; + enum class julian_type { MJD2000, MJD, JD }; /** Constructors */ // Default constructor @@ -105,7 +106,7 @@ class kep3_DLL_PUBLIC epoch { // Constructor for days (as a floating-point value) explicit epoch(double epoch_in, - julian_type epoch_type = MJD2000); + julian_type epoch_type = julian_type::MJD2000); /** * Constructs an epoch from a std::chrono::duration. @@ -119,17 +120,12 @@ class kep3_DLL_PUBLIC epoch { // Constructor from duration&&) template > explicit epoch(Duration &&duration) - : tp{kep_clock::time_point{} + duration} {} - - // Constructor for const time_point&) - explicit epoch(const kep_clock::time_point &time_point); + : tp{kep_clock::time_point{} + std::forward(duration)} {} - // Constructor for const time_point&&) - explicit epoch(kep_clock::time_point &&time_point); // Constructor for datetime broken down into its constituents. - explicit epoch(int y, int d, int h = 0, int min = 0, int s = 0, int ms = 0, - int us = 0); + explicit epoch(const uint y, const uint mon, const uint d, const uint h = 0, + const uint min = 0, const uint s = 0, const uint ms = 0, const uint us = 0); /* Computing non-Gregorian dates */ @@ -137,31 +133,26 @@ class kep3_DLL_PUBLIC epoch { * @return Number of days since 0 JD (including fractional days). */ [[nodiscard]] constexpr double jd() const { - return chr::duration>(tp.time_since_epoch() + - 211813444800s) - .count(); + return chr::duration>(tp.time_since_epoch() - kep_clock::y2k_offset + 211813444800s).count(); } /** * @return Number of days since 0 MJD (including fractional days). */ [[nodiscard]] constexpr double mjd() const { - return chr::duration>(tp.time_since_epoch() + - 4453401600s) - .count(); + return chr::duration>(tp.time_since_epoch() - kep_clock::y2k_offset + 4453401600s).count(); } /** * @return Number of days since 0 MJD2000 (including fractional days). */ [[nodiscard]] constexpr double mjd2000() const { - return chr::duration>(tp.time_since_epoch()) - .count(); + return chr::duration>(tp.time_since_epoch() - kep_clock::y2k_offset).count(); } /* Helper functions for constructors */ - static kep_clock::time_point make_tp(int y, int d, int h = 0, int min = 0, - int s = 0, int ms = 0, int us = 0); + static kep_clock::time_point make_tp(const uint y, const uint mon, const uint d, const uint h = 0, + const uint min = 0, const uint s = 0, const uint ms = 0, const uint us = 0); static kep_clock::time_point make_tp(double epoch_in, julian_type epoch_type); @@ -175,7 +166,8 @@ class kep3_DLL_PUBLIC epoch { } // Printing - static auto as_utc_string(const kep_clock::time_point &); + std::string as_utc_string() const; + static std::string as_utc_string(const kep_clock::time_point& tp); /** operator overloads for sum and diff (epoch-days) and comparison * operators @@ -185,13 +177,13 @@ class kep3_DLL_PUBLIC epoch { epoch const &epoch_in); template > - epoch &operator+=(Duration &&duration) { + epoch &operator+=(const Duration &duration) { tp += chr::duration_cast(duration); return *this; } template > - epoch &operator-=(Duration &&duration) { + epoch &operator-=(const Duration &duration) { tp -= chr::duration_cast(duration); return *this; } @@ -226,7 +218,14 @@ class kep3_DLL_PUBLIC epoch { kep3_DLL_PUBLIC friend kep_clock::duration operator-(const epoch &lhs, const epoch &rhs); -private: + private: + + // Constructor for const time_point&) + explicit epoch(const kep_clock::time_point &time_point); + + // Constructor for const time_point&&) + explicit epoch(kep_clock::time_point &&time_point); + // Serialization code friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int) { diff --git a/src/epoch.cpp b/src/epoch.cpp index 57d8bc50..4dcb41c0 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -10,21 +10,28 @@ #include #include #include +#include +#include #include #include #include +#include #include #include +#include + #include "kep3/core_astro/convert_julian_dates.hpp" #include "kep3/epoch.hpp" -namespace kep3 { +namespace kep3 +{ /** * @brief Constructs a default epoch . */ -epoch::epoch() = default; +epoch::epoch() + : tp{kep_clock::ref_epoch} {} /** * @brief Constructs an epoch from a non-Gregorian date. @@ -47,9 +54,9 @@ epoch::epoch(const double epoch_in, const julian_type epoch_type) * @param[in] ms The number of milliseconds. * @param[in] us The number of microseconds. */ -epoch::epoch(const int y, const int d, const int h, const int min, const int s, - const int ms, const int us) - : tp{make_tp(y, d, h, min, s, ms, us)} {} +epoch::epoch(const uint y, const uint mon, const uint d, const uint h, + const uint min, const uint s, const uint ms, const uint us) + : tp{make_tp(y, mon, d, h, min, s, ms, us)} {} /** * @brief Constructs an epoch from a const reference to a time point. @@ -63,14 +70,13 @@ epoch::epoch(const kep_clock::time_point &time_point) : tp{time_point} {} * * @param[in] time_point Self-explanatory. */ -epoch::epoch(kep_clock::time_point &&time_point) : tp{time_point} {} +epoch::epoch(kep_clock::time_point &&time_point) : tp{std::move(time_point)} {} -kep_clock::time_point epoch::make_tp(const int y, const int d, const int h, - const int min, const int s, const int ms, - const int us) +kep_clock::time_point epoch::make_tp(const uint y, const uint mon, const uint d, const uint h, + const uint min, const uint s, const uint ms, const uint us) { - return kep_clock::time_point{} + chr::years(y) + chr::days(d) + + return kep_clock::time_point{} + chr::sys_days(chr::year_month_day{chr::year(y) / chr::month(mon) / chr::day(d)} + chr::months{0}).time_since_epoch() + chr::hours(h) + chr::minutes(min) + chr::seconds(s) + chr::milliseconds(ms) + chr::microseconds(us); } @@ -81,9 +87,9 @@ kep_clock::time_point epoch::make_tp(const double epoch_in, case julian_type::MJD2000: return epoch::tp_from_days(epoch_in); case julian_type::MJD: - return mjd2mjd2000(epoch::tp_from_days(epoch_in)); + return epoch::tp_from_days(epoch_in) - 4453401600s; case julian_type::JD: - return jd2mjd2000(epoch::tp_from_days(epoch_in)); + return epoch::tp_from_days(epoch_in) - 211813444800s; default: throw; } @@ -95,24 +101,34 @@ kep_clock::time_point epoch::make_tp(const double epoch_in, * @return A time point */ constexpr kep_clock::time_point epoch::tp_from_days(const double days) { - return kep_clock::time_point{} + + return kep_clock::ref_epoch + chr::duration_cast( chr::duration>(days)); } /** * @brief Returns a time point formatted as a date/time string + * in the in the format 2000-12-31T12:34:56.123456. * * @param tp The time point. * @return A formatted date/time string. */ -auto epoch::as_utc_string(const kep_clock::time_point &tp) { - auto t = kep_clock::to_time_t(tp); - return std::put_time(gmtime(&t), "%FT%T"); +std::string epoch::as_utc_string(const kep_clock::time_point& tp) { + std::stringstream iss; + const auto tse{tp.time_since_epoch()}; + const auto dp{std::chrono::duration_cast(tse)}; + const auto hms{std::chrono::duration_cast(tse - dp)}; + const auto us{std::chrono::duration_cast(tse - dp - hms)}; + iss << fmt::format("{:%F}", chr::sys_days(dp)) << "T" << fmt::format("{:%T}", hms) << "." << fmt::format("{:06}", us.count()); + return iss.str(); +} + +std::string epoch::as_utc_string() const { + return epoch::as_utc_string(tp); } /** - * @brief Streams out a date in the format 2000-Jan-01 00:12:30 + * @brief Streams out an epoch as a UTC string. * * @param[in] s Stream to which the epoch will be sent. * @param[in] ep Epoch to be sent to the stream. @@ -120,7 +136,7 @@ auto epoch::as_utc_string(const kep_clock::time_point &tp) { * @return Reference to s. */ std::ostream &operator<<(std::ostream &s, const epoch &ep) { - s << epoch::as_utc_string(ep.tp); + s << ep.as_utc_string(); return s; } diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index c72a378a..2fdc2f0f 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -7,7 +7,6 @@ // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include #include #include #include @@ -25,6 +24,7 @@ namespace chr = std::chrono; TEST_CASE("construct") { // test syntax + // // > 2000 REQUIRE_NOTHROW(epoch()); REQUIRE_NOTHROW(epoch(123.456)); @@ -33,13 +33,8 @@ TEST_CASE("construct") { REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::JD)); REQUIRE_NOTHROW(epoch(0.0, epoch::julian_type::MJD)); REQUIRE_NOTHROW(epoch(123.456, epoch::julian_type::MJD)); - REQUIRE_NOTHROW(epoch(34, 364, 11, 36, 21, 121, 841)); - // // > 2000 - // boost::posix_time::ptime posix_time_test( date( 2034, 12, 31 ) ); - // REQUIRE_NOTHROW( epoch( posix_time_test ) ); - // REQUIRE( epoch( posix_time_test ).get_posix_time() == posix_time_test ); - // std::cout << "Chrono1: " << epoch(posix_time_test).get_posix_time() << - // "\n"; std::cout << "Boost1: " << posix_time_test << "\n"; + REQUIRE_NOTHROW(epoch(2000, 10, 17, 11, 36, 21, 121, 841)); + REQUIRE_NOTHROW(epoch(2064, 10, 17, 11, 36, 21, 121, 841).as_utc_string() == "2064-10-17T11:36:21.121841"); // // < 2000 REQUIRE_NOTHROW(epoch(-123.456)); @@ -48,62 +43,46 @@ TEST_CASE("construct") { REQUIRE_NOTHROW(epoch(-123.456, epoch::julian_type::JD)); REQUIRE_NOTHROW(epoch(-0.0, epoch::julian_type::MJD)); REQUIRE_NOTHROW(epoch(-123.456, epoch::julian_type::MJD)); - REQUIRE_NOTHROW(epoch(-34, 364, 11, 36, 21, 121, 841)); - // boost::posix_time::ptime posix_time_test2(date(1980, 12, 31)); - // REQUIRE_NOTHROW(epoch(posix_time_test2)); - // REQUIRE(epoch(posix_time_test2).get_posix_time() == posix_time_test2); - // std::cout << "Chrono2: " << epoch(posix_time_test2).get_posix_time() << - // "\n"; std::cout << "Boost2: " << posix_time_test2 << "\n"; + REQUIRE_NOTHROW(epoch(1980, 10, 17, 11, 36, 21, 121, 841)); + REQUIRE_NOTHROW(epoch(1980, 10, 17, 11, 36, 21, 121, 841).as_utc_string() == "1980-10-17T11:36:21.121841"); - // // test conversions + // test conversions REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); - REQUIRE(epoch(0.).mjd() == epoch(51544., epoch::MJD).mjd()); - REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::JD).jd()); - // REQUIRE(epoch(2034, 12, 31) == epoch(posix_time_test)); + REQUIRE(epoch(0.).mjd() == epoch(51544., epoch::julian_type::MJD).mjd()); + REQUIRE(epoch(0.).jd() == epoch(2451544.5, epoch::julian_type::JD).jd()); } TEST_CASE("epoch_operators") { - REQUIRE(epoch(34, 10) == epoch(34, 10)); - REQUIRE(epoch(34, 10) != epoch(34, 11)); + REQUIRE(epoch(2034, 10, 17) == epoch(2034, 10, 17)); + REQUIRE(epoch(2034, 10, 17) != epoch(2034, 11, 17)); // Testing us precision - REQUIRE(epoch(34, 10) != epoch(34, 10, 0, 0, 0, 0, 1)); + REQUIRE(epoch(2034, 10, 17) != epoch(2034, 10, 17, 0, 0, 0, 0, 1)); // Check that ns precision is not supported - REQUIRE(epoch(0, 10) == epoch(0, 10, 0, 0, 0, 0, 0) + chr::nanoseconds(100)); + REQUIRE(epoch(2000, 10, 17) == epoch(2000, 10, 17, 0, 0, 0, 0, 0) + chr::nanoseconds(100)); - // Conversion from double (defaults to days) + // Conversion from double (defaults to days) REQUIRE(epoch(1.) > epoch(0.)); REQUIRE(epoch(1.) >= epoch(1.)); REQUIRE(epoch(1.) >= epoch(0.)); REQUIRE(epoch(0.) < epoch(1.)); REQUIRE(epoch(1.) <= epoch(1.)); epoch today(0.); - today += chr::days(100); - REQUIRE(today == epoch(0, 100)); - today -= chr::duration_cast(chr::days(100)); + auto offset{chr::days(10963)}; + today += offset; + std::cout << "TODAY: " << today << "\n"; + REQUIRE(today == epoch(2030, 1, 6)); + today -= chr::duration_cast(offset); REQUIRE(today == epoch()); auto oneday{chr::days(1)}; auto yesterday{today - chr::duration_cast(oneday)}; auto yesterday1{today - oneday}; REQUIRE(yesterday == yesterday1); - REQUIRE(yesterday == epoch(0, -1)); + REQUIRE(yesterday == epoch(1999, 12, 31)); today = yesterday + chr::duration_cast(chr::days(1)); REQUIRE(today == epoch()); auto diff{today - yesterday}; REQUIRE(diff == chr::duration_cast(chr::days(1))); REQUIRE_NOTHROW((std::cout << epoch())); } - -// TEST_CASE("conversions_from_string") { -// { -// std::string ts("20020131T000000"); -// epoch e(epoch_from_iso_string(ts)); -// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 31)))); -// } -// { -// std::string ts("2002-01-20 00:00:00.000"); -// epoch e(epoch_from_string(ts)); -// REQUIRE(e == epoch(boost::posix_time::ptime(date(2002, 01, 20)))); -// } -// } From 99fdabd0f8143acf1f18e361c058dc224cafd3cb Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:22:41 +0200 Subject: [PATCH 27/30] - Minor fix (enum class) --- test/planet_jpl_lp_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/planet_jpl_lp_test.cpp b/test/planet_jpl_lp_test.cpp index 946ce37a..52d71f47 100644 --- a/test/planet_jpl_lp_test.cpp +++ b/test/planet_jpl_lp_test.cpp @@ -136,7 +136,7 @@ TEST_CASE("eph") { REQUIRE(kep3_tests::floating_point_error_vector(v, pos_vel_0[1]) < 0.01); } jpl_lp udpla{"uranus"}; - REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534., kep3::epoch::MJD2000)), + REQUIRE_THROWS_AS(udpla.eph(kep3::epoch(5347534., kep3::epoch::julian_type::MJD2000)), std::domain_error); } From 9cf1755cf2dc7f61679ee7885177a37e34c28cfc Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:34:35 +0200 Subject: [PATCH 28/30] - Added two tests for epoch - Reverted unsigned int arguments to int in one of the epoch constructors and epoch::make_tp() --- include/kep3/epoch.hpp | 8 ++++---- src/epoch.cpp | 8 ++++---- test/epoch_test.cpp | 5 +++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 11b86aac..650f9da3 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -124,8 +124,8 @@ class kep3_DLL_PUBLIC epoch { // Constructor for datetime broken down into its constituents. - explicit epoch(const uint y, const uint mon, const uint d, const uint h = 0, - const uint min = 0, const uint s = 0, const uint ms = 0, const uint us = 0); + explicit epoch(const int y, const int mon, const int d, const int h = 0, + const int min = 0, const int s = 0, const int ms = 0, const int us = 0); /* Computing non-Gregorian dates */ @@ -151,8 +151,8 @@ class kep3_DLL_PUBLIC epoch { } /* Helper functions for constructors */ - static kep_clock::time_point make_tp(const uint y, const uint mon, const uint d, const uint h = 0, - const uint min = 0, const uint s = 0, const uint ms = 0, const uint us = 0); + static kep_clock::time_point make_tp(const int y, const int mon, const int d, const int h = 0, + const int min = 0, const int s = 0, const int ms = 0, const int us = 0); static kep_clock::time_point make_tp(double epoch_in, julian_type epoch_type); diff --git a/src/epoch.cpp b/src/epoch.cpp index 4dcb41c0..e84f0343 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -54,8 +54,8 @@ epoch::epoch(const double epoch_in, const julian_type epoch_type) * @param[in] ms The number of milliseconds. * @param[in] us The number of microseconds. */ -epoch::epoch(const uint y, const uint mon, const uint d, const uint h, - const uint min, const uint s, const uint ms, const uint us) +epoch::epoch(const int y, const int mon, const int d, const int h, + const int min, const int s, const int ms, const int us) : tp{make_tp(y, mon, d, h, min, s, ms, us)} {} /** @@ -72,8 +72,8 @@ epoch::epoch(const kep_clock::time_point &time_point) : tp{time_point} {} */ epoch::epoch(kep_clock::time_point &&time_point) : tp{std::move(time_point)} {} -kep_clock::time_point epoch::make_tp(const uint y, const uint mon, const uint d, const uint h, - const uint min, const uint s, const uint ms, const uint us) +kep_clock::time_point epoch::make_tp(const int y, const int mon, const int d, const int h, + const int min, const int s, const int ms, const int us) { return kep_clock::time_point{} + chr::sys_days(chr::year_month_day{chr::year(y) / chr::month(mon) / chr::day(d)} + chr::months{0}).time_since_epoch() + diff --git a/test/epoch_test.cpp b/test/epoch_test.cpp index 2fdc2f0f..3bac923f 100644 --- a/test/epoch_test.cpp +++ b/test/epoch_test.cpp @@ -46,6 +46,11 @@ TEST_CASE("construct") { REQUIRE_NOTHROW(epoch(1980, 10, 17, 11, 36, 21, 121, 841)); REQUIRE_NOTHROW(epoch(1980, 10, 17, 11, 36, 21, 121, 841).as_utc_string() == "1980-10-17T11:36:21.121841"); + // Epoch from lvalue and rvalue references + epoch ep{2000, 1, 1}; + REQUIRE(epoch(ep) == ep); + REQUIRE(epoch(epoch{2000,1,1}) == ep); + // test conversions REQUIRE(epoch(123.456).mjd2000() == epoch(123.456, epoch::julian_type::MJD2000).mjd2000()); From 6669eb3925f2c19d9678f3da9e3c7f27251665cb Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:44:13 +0200 Subject: [PATCH 29/30] - Fixed signedness issues for Apple Clang --- include/kep3/epoch.hpp | 4 ++-- src/epoch.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 650f9da3..96cde0f9 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -124,7 +124,7 @@ class kep3_DLL_PUBLIC epoch { // Constructor for datetime broken down into its constituents. - explicit epoch(const int y, const int mon, const int d, const int h = 0, + explicit epoch(const int y, const uint mon, const uint d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); /* Computing non-Gregorian dates */ @@ -151,7 +151,7 @@ class kep3_DLL_PUBLIC epoch { } /* Helper functions for constructors */ - static kep_clock::time_point make_tp(const int y, const int mon, const int d, const int h = 0, + static kep_clock::time_point make_tp(const int y, const uint mon, const uint d, const int h = 0, const int min = 0, const int s = 0, const int ms = 0, const int us = 0); static kep_clock::time_point make_tp(double epoch_in, julian_type epoch_type); diff --git a/src/epoch.cpp b/src/epoch.cpp index e84f0343..ab6c7592 100644 --- a/src/epoch.cpp +++ b/src/epoch.cpp @@ -54,7 +54,7 @@ epoch::epoch(const double epoch_in, const julian_type epoch_type) * @param[in] ms The number of milliseconds. * @param[in] us The number of microseconds. */ -epoch::epoch(const int y, const int mon, const int d, const int h, +epoch::epoch(const int y, const uint mon, const uint d, const int h, const int min, const int s, const int ms, const int us) : tp{make_tp(y, mon, d, h, min, s, ms, us)} {} @@ -72,7 +72,7 @@ epoch::epoch(const kep_clock::time_point &time_point) : tp{time_point} {} */ epoch::epoch(kep_clock::time_point &&time_point) : tp{std::move(time_point)} {} -kep_clock::time_point epoch::make_tp(const int y, const int mon, const int d, const int h, +kep_clock::time_point epoch::make_tp(const int y, const uint mon, const uint d, const int h, const int min, const int s, const int ms, const int us) { From 3342849ad5fc8af382aa9cee2c9521d44052498e Mon Sep 17 00:00:00 2001 From: cantordust <43831101+cantordust@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:03:37 +0200 Subject: [PATCH 30/30] - Fixed missing typedef (MSVC) --- include/kep3/epoch.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/kep3/epoch.hpp b/include/kep3/epoch.hpp index 96cde0f9..eaec0fe5 100644 --- a/include/kep3/epoch.hpp +++ b/include/kep3/epoch.hpp @@ -31,8 +31,7 @@ namespace kep3 { using namespace std::literals; namespace chr = std::chrono; -using lint = long int; -using llint = long long int; +using uint = unsigned int; template struct is_duration : std::false_type {}; @@ -46,8 +45,8 @@ struct kep_clock : public chr::system_clock { /** * @brief Custom clock. - * Used for constructing epochs with a custom reference point. - * In particular, by defining a custom clock, we avoid the overflow + * Used for constructing epochs with a custom reference point (1 Jan 2000). + * By defining a custom clock, we avoid the overflow * that std::chrono::system_clock suffers at +/- 292 years. * To do that, we lower the resolution to 1 us (microsecond), * which gives the clock a range of +/- 292 thousand years. @@ -228,7 +227,7 @@ class kep3_DLL_PUBLIC epoch { // Serialization code friend class boost::serialization::access; - template void serialize(Archive &ar, const unsigned int) { + template void serialize(Archive &ar, const uint) { ar &boost::serialization::make_binary_object(&tp, sizeof(tp)); } // Serialization code (END)