Loading CMakeLists.txt +2 −2 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ if (CPPDUALS_TESTING) # build the thirdparty message ("***************************************************************") message ("********** Building '${PROJECT_BINARY_DIR}/thirdparty'...") message ("** Building '${PROJECT_BINARY_DIR}/thirdparty'...") message ("***************************************************************") execute_process ( WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty" Loading @@ -133,6 +133,7 @@ if (CPPDUALS_TESTING) if (DEPS_BUILD_RESULT) message ("***************************************************************") message (FATAL_ERROR "Building dependencies failed: ${DEPS_BUILD_RESULT}") message ("***************************************************************") endif () add_subdirectory (thirdparty) Loading Loading @@ -220,4 +221,3 @@ if (ETAGS) COMMAND ${ETAGS} --language=c++ --append `find ${PROJECT_BINARY_DIR}/thirdparty/eigenX/src/eigenX -type f` ) endif (ETAGS) README.md +23 −8 Original line number Diff line number Diff line Loading @@ -103,15 +103,11 @@ family of commands and modifying the global preprocessor search path: include(ExternalProject) # Have CMake download the library set (CPPDUALS_VER 0.1.2) set (CPPDUALS_MD5 48d9276482e5f07a768875ef692d14cd) set (CPPDUALS_MD5 2c4049fa5738ba82bb6c4ba13a77ff43) ExternalProject_Add (cppduals URL https://gitlab.com/tesch1/cppduals/-/archive/v${CPPDUALS_VER}/cppduals-v${CPPDUALS_VER}.tar.bz2 URL https://gitlab.com/tesch1/cppduals/uploads/f2e1f3490fcbe862124c89394097eae3/cppduals-0.2.0.tgz URL_HASH MD5=${CPPDUALS_MD5} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) # Make include directory globally visible ExternalProject_Get_Property (cppduals source_dir) Loading Loading @@ -155,7 +151,7 @@ The benchmark compares cppduals against a local BLAS implementation, by default OpenBLAS (whose development package is required; RedHat-flavor: `openblas-devel`, Debian-flavor: `openblas-dev`). If you wish to build the benchmarks against a different installation of BLAS, the following CMake variables can be used at configuration: BLAS, the following CMake variables can be set at configuration time: - [BLA_VENDOR](https://cmake.org/cmake/help/latest/module/FindBLAS.html) - BLAS_DIR Loading Loading @@ -295,6 +291,25 @@ derived from the [Eigen project](http://eigen.tuxfamily.org/index.php?title=Main_Page), and thus licensed under [MPL-2](http://www.mozilla.org/MPL/2.0/FAQ.html) . ChangeLog ========= v0.3.0 ====== - vastly improved cmake support, thanks to [Jeff](https://gitlab.com/flying-tiger). The improvements required changing some CMake target names. - Added basic optional [libfmt](https://github.com/fmtlib/fmt) support for duals::dual<> and std::complex<>, enabled with `#define`\ s v0.2.0 ====== - fixed build on VS2017 - save and restore signam and errno in {t,l}gamma - fixes from Nestor D. for https://gitlab.com/tesch1/cppduals/issues/5 (spurious nan) Todo ==== Loading duals/dual +146 −4 Original line number Diff line number Diff line Loading @@ -1071,12 +1071,20 @@ operator>>(std::basic_istream<CharT, Traits> & is, dual<T> & x) T r; is >> r; if (!is.fail()) { ws(is); CharT c = is.peek(); if (c == CharT('+') || c == CharT('-')) { if (c != CharT('_')) { ws(is); c = is.peek(); } if (c == CharT('+') || c == CharT('-') || c == CharT('_')) { if (c == CharT('+')) is.get(); T d; if (c == CharT('_')) { d = r; r = 0; } else is >> d; if (!is.fail()) { ws(is); Loading Loading @@ -1136,7 +1144,6 @@ operator>>(std::basic_istream<CharT, Traits> & is, dual<T> & x) return is; } #if __cpp_user_defined_literals >= 200809 /// Dual number literals in namespace duals::literals inline namespace literals Loading Loading @@ -1181,6 +1188,141 @@ typedef std::complex<dualld> cdualld; } // namespace duals #ifdef CPPDUALS_LIBFMT #include <fmt/format.h> /// duals::dual<> Formatter for libfmt https://github.com/fmtlib/fmt /// /// Formats a dual number (r,d) as (r+d_e), offering the same /// formatting options as the underlying type - with the addition of /// three optional format options, only one of which may appear /// directly after the ':' in the format spec: '$', '*', and ',". The /// '*' flag changes the separating _ to a *, producing (r+d*e), where /// r and d are the formatted value_type values. The ',' flag simply /// prints the real and dual parts separated by a comma. As a /// concrete exmple, this formatter can produce either (3+5.4_e) or /// (3+5.4*e) or (3,5.4) for a dual<double> using the specs {:g}, /// {:*g}, or {:,g}, respectively. When the '*' is NOT specified, the /// output should be compatible with the input operator>> and the dual /// literals below. (this implementation is a bit hacky - glad for /// cleanups). template <typename T, typename Char> struct fmt::formatter<duals::dual<T>,Char> : public fmt::formatter<T,Char> { typedef fmt::formatter<T,Char> base; enum style { expr, star, pair } style_ = expr; internal::dynamic_format_specs<Char> specs_; constexpr auto parse(format_parse_context & ctx) -> decltype(ctx.begin()) { using handler_type = internal::dynamic_specs_handler<format_parse_context>; auto type = internal::type_constant<T, Char>::value; internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), type); auto it = ctx.begin(); switch (*it) { case '$': style_ = style::expr; ctx.advance_to(++it); break; case '*': style_ = style::star; ctx.advance_to(++it); break; case ',': style_ = style::pair; ctx.advance_to(++it); break; default: break; } parse_format_specs(ctx.begin(), ctx.end(), handler); return base::parse(ctx); } template <typename FormatCtx> auto format(const duals::dual<T> & x, FormatCtx & ctx) -> decltype(ctx.out()) { format_to(ctx.out(), "("); if (x.rpart() || !x.dpart()) base::format(x.rpart(), ctx); if (x.dpart()) { if (style_ == style::pair) format_to(ctx.out(), ","); else if (x.rpart() && x.dpart() >= 0 && specs_.sign != sign::plus) format_to(ctx.out(), "+"); base::format(x.dpart(), ctx); if (style_ != style::pair) { if (style_ == style::star) format_to(ctx.out(), "*e"); else format_to(ctx.out(), "_e"); if (std::is_same<typename std::decay<T>::type,float>::value) format_to(ctx.out(), "f"); if (std::is_same<typename std::decay<T>::type,long double>::value) format_to(ctx.out(), "l"); } } return format_to(ctx.out(), ")"); } }; #endif #ifdef CPPDUALS_LIBFMT_COMPLEX #ifndef CPPDUALS_LIBFMT #include <fmt/format.h> #endif /// std::complex<> Formatter for libfmt https://github.com/fmtlib/fmt /// /// libfmt does not provide a formatter for std::complex<>, although /// one is proposed for c++20. Anyway, at the expense of a k or two, /// you can define CPPDUALS_LIBFMT_COMPLEX and get this one. /// /// The standard iostreams formatting of complex numbers is (a,b), /// where a and b are the real and imaginary parts. This formats a /// complex number (a+bi) as (a+bi), offering the same formatting /// options as the underlying type - with the addition of three /// optional format options, only one of which may appear directly /// after the ':' in the format spec (before any fill or align): '$' /// (the default if no flag is specified), '*', and ',". The '*' flag /// adds a * before the 'i', producing (a+b*i), where a and b are the /// formatted value_type values. The ',' flag simply prints the real /// and complex parts separated by a comma (same as iostreams' format). /// As a concrete exmple, this formatter can produce either (3+5.4i) /// or (3+5.4*i) or (3,5.4) for a complex<double> using the specs {:g} /// | {:$g}, {:*g}, or {:,g}, respectively. (this implementation is a /// bit hacky - glad for cleanups). /// template <typename T, typename Char> struct fmt::formatter<std::complex<T>,Char> : public fmt::formatter<T,Char> { typedef fmt::formatter<T,Char> base; enum style { expr, star, pair } style_ = expr; internal::dynamic_format_specs<Char> specs_; constexpr auto parse(format_parse_context & ctx) -> decltype(ctx.begin()) { using handler_type = internal::dynamic_specs_handler<format_parse_context>; auto type = internal::type_constant<T, Char>::value; internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), type); auto it = ctx.begin(); switch (*it) { case '$': style_ = style::expr; ctx.advance_to(++it); break; case '*': style_ = style::star; ctx.advance_to(++it); break; case ',': style_ = style::pair; ctx.advance_to(++it); break; default: break; } parse_format_specs(ctx.begin(), ctx.end(), handler); //todo: fixup alignment return base::parse(ctx); } template <typename FormatCtx> auto format(const std::complex<T> & x, FormatCtx & ctx) -> decltype(ctx.out()) { format_to(ctx.out(), "("); if (x.real() || !x.imag()) base::format(x.real(), ctx); if (x.imag()) { if (style_ == style::pair) format_to(ctx.out(), ","); else if (x.real() && x.imag() >= 0 && specs_.sign != sign::plus) format_to(ctx.out(), "+"); base::format(x.imag(), ctx); if (style_ != style::pair) { if (style_ == style::star) format_to(ctx.out(), "*i"); else format_to(ctx.out(), "i"); if (std::is_same<typename std::decay<T>::type,float>::value) format_to(ctx.out(), "f"); if (std::is_same<typename std::decay<T>::type,long double>::value) format_to(ctx.out(), "l"); } } return format_to(ctx.out(), ")"); } }; #endif #ifdef _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD #else Loading tests/CMakeLists.txt +3 −2 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_VECTORIZE_CDUAL") set (ALL_TESTS test_dual test_funcs test_eigen test_packets test_vectorize test_solve test_expm test_1 test_vectorize test_solve test_expm test_1 test_fmt example ) set (ALL_TEST_BINS ) Loading @@ -73,7 +73,7 @@ foreach (TEST_ ${ALL_TESTS}) string (REPLACE ";" ", " L2 "${CMAKE_CXX_FLAGS}") target_compile_options (${TEST} PUBLIC ${PHASE_FLAGS}) target_compile_definitions (${TEST} PRIVATE "OPT_FLAGS=${L2}") target_link_libraries (${TEST} gtest_main cppduals_coverage_config ) target_link_libraries (${TEST} gtest_main cppduals_coverage_config fmt::fmt) #target_link_libraries (${TEST} -lasan) add_dependencies (${TEST} eigenX expokitX) gtest_discover_tests (${TEST} TEST_LIST ${TEST}_targets) Loading @@ -82,6 +82,7 @@ foreach (TEST_ ${ALL_TESTS}) endforeach (PHASE) endforeach (TEST_) target_compile_features (test_fmt_1 PUBLIC cxx_std_14) if (CPPDUALS_BENCHMARK) # Loading tests/test_dual.cpp +42 −2 Original line number Diff line number Diff line Loading @@ -642,18 +642,28 @@ TEST(non_class, putto) { s << 2 + 3_ef; EXPECT_EQ(s.str(), "(2+3_ef)"); } //#ifndef _MSC_VER // hoping for a patch to fix this { std::stringstream s; s << 2 + 3_e; EXPECT_EQ(s.str(), "(2+3_e)"); } //#endif { std::stringstream s; s << 2 + 3_el; EXPECT_EQ(s.str(), "(2+3_el)"); } #if 0 // seems reasonable { std::stringstream s; s << 3_e; EXPECT_EQ(s.str(), "(3_e)"); } #endif { std::stringstream s; s << std::fixed << std::setprecision(10) << 10 + 2_e; EXPECT_EQ(s.str(), "(10.0000000000+2.0000000000_e)"); } { std::stringstream s; s << cdualf(2 + 3_ef, 4 + 5_ef); Loading Loading @@ -702,6 +712,22 @@ TEST(non_class, getfro) { EXPECT_EQ(x.rpart(), 2); EXPECT_EQ(x.dpart(), 0); } { std::stringstream s("(2_e) "); duald x(1,8); s >> x; EXPECT_TRUE(s); EXPECT_EQ(x.rpart(), 0); EXPECT_EQ(x.dpart(), 2); } { std::stringstream s("(3_e ) "); duald x(1,8); s >> x; EXPECT_TRUE(s); EXPECT_EQ(x.rpart(), 0); EXPECT_EQ(x.dpart(), 3); } { std::stringstream s(" (2.3+ 3_el)"); dualld x; Loading Loading @@ -855,6 +881,20 @@ TEST(non_class, getfro) { EXPECT_FALSE(s); EXPECT_EQ(x, cdualf()); } { std::stringstream s("(1_) "); cdualf x; s >> x; EXPECT_FALSE(s); EXPECT_EQ(x, cdualf()); } { std::stringstream s("(1.3 _e) "); cduald x; s >> x; EXPECT_FALSE(s); EXPECT_EQ(x, cduald()); } } Loading Loading
CMakeLists.txt +2 −2 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ if (CPPDUALS_TESTING) # build the thirdparty message ("***************************************************************") message ("********** Building '${PROJECT_BINARY_DIR}/thirdparty'...") message ("** Building '${PROJECT_BINARY_DIR}/thirdparty'...") message ("***************************************************************") execute_process ( WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty" Loading @@ -133,6 +133,7 @@ if (CPPDUALS_TESTING) if (DEPS_BUILD_RESULT) message ("***************************************************************") message (FATAL_ERROR "Building dependencies failed: ${DEPS_BUILD_RESULT}") message ("***************************************************************") endif () add_subdirectory (thirdparty) Loading Loading @@ -220,4 +221,3 @@ if (ETAGS) COMMAND ${ETAGS} --language=c++ --append `find ${PROJECT_BINARY_DIR}/thirdparty/eigenX/src/eigenX -type f` ) endif (ETAGS)
README.md +23 −8 Original line number Diff line number Diff line Loading @@ -103,15 +103,11 @@ family of commands and modifying the global preprocessor search path: include(ExternalProject) # Have CMake download the library set (CPPDUALS_VER 0.1.2) set (CPPDUALS_MD5 48d9276482e5f07a768875ef692d14cd) set (CPPDUALS_MD5 2c4049fa5738ba82bb6c4ba13a77ff43) ExternalProject_Add (cppduals URL https://gitlab.com/tesch1/cppduals/-/archive/v${CPPDUALS_VER}/cppduals-v${CPPDUALS_VER}.tar.bz2 URL https://gitlab.com/tesch1/cppduals/uploads/f2e1f3490fcbe862124c89394097eae3/cppduals-0.2.0.tgz URL_HASH MD5=${CPPDUALS_MD5} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) # Make include directory globally visible ExternalProject_Get_Property (cppduals source_dir) Loading Loading @@ -155,7 +151,7 @@ The benchmark compares cppduals against a local BLAS implementation, by default OpenBLAS (whose development package is required; RedHat-flavor: `openblas-devel`, Debian-flavor: `openblas-dev`). If you wish to build the benchmarks against a different installation of BLAS, the following CMake variables can be used at configuration: BLAS, the following CMake variables can be set at configuration time: - [BLA_VENDOR](https://cmake.org/cmake/help/latest/module/FindBLAS.html) - BLAS_DIR Loading Loading @@ -295,6 +291,25 @@ derived from the [Eigen project](http://eigen.tuxfamily.org/index.php?title=Main_Page), and thus licensed under [MPL-2](http://www.mozilla.org/MPL/2.0/FAQ.html) . ChangeLog ========= v0.3.0 ====== - vastly improved cmake support, thanks to [Jeff](https://gitlab.com/flying-tiger). The improvements required changing some CMake target names. - Added basic optional [libfmt](https://github.com/fmtlib/fmt) support for duals::dual<> and std::complex<>, enabled with `#define`\ s v0.2.0 ====== - fixed build on VS2017 - save and restore signam and errno in {t,l}gamma - fixes from Nestor D. for https://gitlab.com/tesch1/cppduals/issues/5 (spurious nan) Todo ==== Loading
duals/dual +146 −4 Original line number Diff line number Diff line Loading @@ -1071,12 +1071,20 @@ operator>>(std::basic_istream<CharT, Traits> & is, dual<T> & x) T r; is >> r; if (!is.fail()) { ws(is); CharT c = is.peek(); if (c == CharT('+') || c == CharT('-')) { if (c != CharT('_')) { ws(is); c = is.peek(); } if (c == CharT('+') || c == CharT('-') || c == CharT('_')) { if (c == CharT('+')) is.get(); T d; if (c == CharT('_')) { d = r; r = 0; } else is >> d; if (!is.fail()) { ws(is); Loading Loading @@ -1136,7 +1144,6 @@ operator>>(std::basic_istream<CharT, Traits> & is, dual<T> & x) return is; } #if __cpp_user_defined_literals >= 200809 /// Dual number literals in namespace duals::literals inline namespace literals Loading Loading @@ -1181,6 +1188,141 @@ typedef std::complex<dualld> cdualld; } // namespace duals #ifdef CPPDUALS_LIBFMT #include <fmt/format.h> /// duals::dual<> Formatter for libfmt https://github.com/fmtlib/fmt /// /// Formats a dual number (r,d) as (r+d_e), offering the same /// formatting options as the underlying type - with the addition of /// three optional format options, only one of which may appear /// directly after the ':' in the format spec: '$', '*', and ',". The /// '*' flag changes the separating _ to a *, producing (r+d*e), where /// r and d are the formatted value_type values. The ',' flag simply /// prints the real and dual parts separated by a comma. As a /// concrete exmple, this formatter can produce either (3+5.4_e) or /// (3+5.4*e) or (3,5.4) for a dual<double> using the specs {:g}, /// {:*g}, or {:,g}, respectively. When the '*' is NOT specified, the /// output should be compatible with the input operator>> and the dual /// literals below. (this implementation is a bit hacky - glad for /// cleanups). template <typename T, typename Char> struct fmt::formatter<duals::dual<T>,Char> : public fmt::formatter<T,Char> { typedef fmt::formatter<T,Char> base; enum style { expr, star, pair } style_ = expr; internal::dynamic_format_specs<Char> specs_; constexpr auto parse(format_parse_context & ctx) -> decltype(ctx.begin()) { using handler_type = internal::dynamic_specs_handler<format_parse_context>; auto type = internal::type_constant<T, Char>::value; internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), type); auto it = ctx.begin(); switch (*it) { case '$': style_ = style::expr; ctx.advance_to(++it); break; case '*': style_ = style::star; ctx.advance_to(++it); break; case ',': style_ = style::pair; ctx.advance_to(++it); break; default: break; } parse_format_specs(ctx.begin(), ctx.end(), handler); return base::parse(ctx); } template <typename FormatCtx> auto format(const duals::dual<T> & x, FormatCtx & ctx) -> decltype(ctx.out()) { format_to(ctx.out(), "("); if (x.rpart() || !x.dpart()) base::format(x.rpart(), ctx); if (x.dpart()) { if (style_ == style::pair) format_to(ctx.out(), ","); else if (x.rpart() && x.dpart() >= 0 && specs_.sign != sign::plus) format_to(ctx.out(), "+"); base::format(x.dpart(), ctx); if (style_ != style::pair) { if (style_ == style::star) format_to(ctx.out(), "*e"); else format_to(ctx.out(), "_e"); if (std::is_same<typename std::decay<T>::type,float>::value) format_to(ctx.out(), "f"); if (std::is_same<typename std::decay<T>::type,long double>::value) format_to(ctx.out(), "l"); } } return format_to(ctx.out(), ")"); } }; #endif #ifdef CPPDUALS_LIBFMT_COMPLEX #ifndef CPPDUALS_LIBFMT #include <fmt/format.h> #endif /// std::complex<> Formatter for libfmt https://github.com/fmtlib/fmt /// /// libfmt does not provide a formatter for std::complex<>, although /// one is proposed for c++20. Anyway, at the expense of a k or two, /// you can define CPPDUALS_LIBFMT_COMPLEX and get this one. /// /// The standard iostreams formatting of complex numbers is (a,b), /// where a and b are the real and imaginary parts. This formats a /// complex number (a+bi) as (a+bi), offering the same formatting /// options as the underlying type - with the addition of three /// optional format options, only one of which may appear directly /// after the ':' in the format spec (before any fill or align): '$' /// (the default if no flag is specified), '*', and ',". The '*' flag /// adds a * before the 'i', producing (a+b*i), where a and b are the /// formatted value_type values. The ',' flag simply prints the real /// and complex parts separated by a comma (same as iostreams' format). /// As a concrete exmple, this formatter can produce either (3+5.4i) /// or (3+5.4*i) or (3,5.4) for a complex<double> using the specs {:g} /// | {:$g}, {:*g}, or {:,g}, respectively. (this implementation is a /// bit hacky - glad for cleanups). /// template <typename T, typename Char> struct fmt::formatter<std::complex<T>,Char> : public fmt::formatter<T,Char> { typedef fmt::formatter<T,Char> base; enum style { expr, star, pair } style_ = expr; internal::dynamic_format_specs<Char> specs_; constexpr auto parse(format_parse_context & ctx) -> decltype(ctx.begin()) { using handler_type = internal::dynamic_specs_handler<format_parse_context>; auto type = internal::type_constant<T, Char>::value; internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), type); auto it = ctx.begin(); switch (*it) { case '$': style_ = style::expr; ctx.advance_to(++it); break; case '*': style_ = style::star; ctx.advance_to(++it); break; case ',': style_ = style::pair; ctx.advance_to(++it); break; default: break; } parse_format_specs(ctx.begin(), ctx.end(), handler); //todo: fixup alignment return base::parse(ctx); } template <typename FormatCtx> auto format(const std::complex<T> & x, FormatCtx & ctx) -> decltype(ctx.out()) { format_to(ctx.out(), "("); if (x.real() || !x.imag()) base::format(x.real(), ctx); if (x.imag()) { if (style_ == style::pair) format_to(ctx.out(), ","); else if (x.real() && x.imag() >= 0 && specs_.sign != sign::plus) format_to(ctx.out(), "+"); base::format(x.imag(), ctx); if (style_ != style::pair) { if (style_ == style::star) format_to(ctx.out(), "*i"); else format_to(ctx.out(), "i"); if (std::is_same<typename std::decay<T>::type,float>::value) format_to(ctx.out(), "f"); if (std::is_same<typename std::decay<T>::type,long double>::value) format_to(ctx.out(), "l"); } } return format_to(ctx.out(), ")"); } }; #endif #ifdef _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD #else Loading
tests/CMakeLists.txt +3 −2 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_VECTORIZE_CDUAL") set (ALL_TESTS test_dual test_funcs test_eigen test_packets test_vectorize test_solve test_expm test_1 test_vectorize test_solve test_expm test_1 test_fmt example ) set (ALL_TEST_BINS ) Loading @@ -73,7 +73,7 @@ foreach (TEST_ ${ALL_TESTS}) string (REPLACE ";" ", " L2 "${CMAKE_CXX_FLAGS}") target_compile_options (${TEST} PUBLIC ${PHASE_FLAGS}) target_compile_definitions (${TEST} PRIVATE "OPT_FLAGS=${L2}") target_link_libraries (${TEST} gtest_main cppduals_coverage_config ) target_link_libraries (${TEST} gtest_main cppduals_coverage_config fmt::fmt) #target_link_libraries (${TEST} -lasan) add_dependencies (${TEST} eigenX expokitX) gtest_discover_tests (${TEST} TEST_LIST ${TEST}_targets) Loading @@ -82,6 +82,7 @@ foreach (TEST_ ${ALL_TESTS}) endforeach (PHASE) endforeach (TEST_) target_compile_features (test_fmt_1 PUBLIC cxx_std_14) if (CPPDUALS_BENCHMARK) # Loading
tests/test_dual.cpp +42 −2 Original line number Diff line number Diff line Loading @@ -642,18 +642,28 @@ TEST(non_class, putto) { s << 2 + 3_ef; EXPECT_EQ(s.str(), "(2+3_ef)"); } //#ifndef _MSC_VER // hoping for a patch to fix this { std::stringstream s; s << 2 + 3_e; EXPECT_EQ(s.str(), "(2+3_e)"); } //#endif { std::stringstream s; s << 2 + 3_el; EXPECT_EQ(s.str(), "(2+3_el)"); } #if 0 // seems reasonable { std::stringstream s; s << 3_e; EXPECT_EQ(s.str(), "(3_e)"); } #endif { std::stringstream s; s << std::fixed << std::setprecision(10) << 10 + 2_e; EXPECT_EQ(s.str(), "(10.0000000000+2.0000000000_e)"); } { std::stringstream s; s << cdualf(2 + 3_ef, 4 + 5_ef); Loading Loading @@ -702,6 +712,22 @@ TEST(non_class, getfro) { EXPECT_EQ(x.rpart(), 2); EXPECT_EQ(x.dpart(), 0); } { std::stringstream s("(2_e) "); duald x(1,8); s >> x; EXPECT_TRUE(s); EXPECT_EQ(x.rpart(), 0); EXPECT_EQ(x.dpart(), 2); } { std::stringstream s("(3_e ) "); duald x(1,8); s >> x; EXPECT_TRUE(s); EXPECT_EQ(x.rpart(), 0); EXPECT_EQ(x.dpart(), 3); } { std::stringstream s(" (2.3+ 3_el)"); dualld x; Loading Loading @@ -855,6 +881,20 @@ TEST(non_class, getfro) { EXPECT_FALSE(s); EXPECT_EQ(x, cdualf()); } { std::stringstream s("(1_) "); cdualf x; s >> x; EXPECT_FALSE(s); EXPECT_EQ(x, cdualf()); } { std::stringstream s("(1.3 _e) "); cduald x; s >> x; EXPECT_FALSE(s); EXPECT_EQ(x, cduald()); } } Loading