Skip to content

Commit

Permalink
Merge pull request #303 from bluescarni/pr/cpp20_fixes
Browse files Browse the repository at this point in the history
Fixes for C++20
bluescarni authored Nov 25, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents e8937e5 + 2f509e0 commit 7bf0d70
Showing 23 changed files with 150 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-modernize-use-trailing-return-type,-readability-named-parameter,-hicpp-named-parameter,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-header-guard,-cppcoreguidelines-macro-usage,-google-runtime-references,-readability-isolate-declaration,-fuchsia-default-arguments-calls,-fuchsia-overloaded-operator,-fuchsia-default-arguments-declarations,-readability-else-after-return,-google-runtime-int,-hicpp-signed-bitwise,-cert-dcl21-cpp,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-modernize-use-transparent-functors,-cert-dcl16-c,-cppcoreguidelines-pro-type-union-access,-bugprone-branch-clone,-fuchsia-statically-constructed-objects,-cppcoreguidelines-pro-bounds-constant-array-index,-readability-static-accessed-through-instance,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-llvmlibc-restrict-system-libc-headers,-llvmlibc-callee-namespace,-llvmlibc-implementation-in-namespace,-llvm-else-after-return,-altera-struct-pack-align,-readability-function-cognitive-complexity,-readability-identifier-length,-altera-unroll-loops,-altera-id-dependent-backward-branch'
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-modernize-use-trailing-return-type,-readability-named-parameter,-hicpp-named-parameter,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-header-guard,-cppcoreguidelines-macro-usage,-google-runtime-references,-readability-isolate-declaration,-fuchsia-default-arguments-calls,-fuchsia-overloaded-operator,-fuchsia-default-arguments-declarations,-readability-else-after-return,-google-runtime-int,-hicpp-signed-bitwise,-cert-dcl21-cpp,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-modernize-use-transparent-functors,-cert-dcl16-c,-cppcoreguidelines-pro-type-union-access,-bugprone-branch-clone,-fuchsia-statically-constructed-objects,-cppcoreguidelines-pro-bounds-constant-array-index,-readability-static-accessed-through-instance,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-llvmlibc-restrict-system-libc-headers,-llvmlibc-callee-namespace,-llvmlibc-implementation-in-namespace,-llvm-else-after-return,-altera-struct-pack-align,-readability-function-cognitive-complexity,-readability-identifier-length,-altera-unroll-loops,-altera-id-dependent-backward-branch,-llvmlibc-inline-function-decl'
WarningsAsErrors: '*'
AnalyzeTemporaryDtors: false
FormatStyle: none
22 changes: 22 additions & 0 deletions .github/workflows/gh_actions_ci.yml
Original file line number Diff line number Diff line change
@@ -37,6 +37,28 @@ jobs:
- uses: actions/checkout@v3
- name: Build
run: bash tools/gha_debuggmp.sh
windows_2022:
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- name: Add msbuild to PATH
uses: microsoft/[email protected]
- uses: conda-incubator/setup-miniconda@v2
with:
auto-update-conda: true
python-version: "3.10"
channels: conda-forge
channel-priority: strict
- name: Build
shell: pwsh
run: |
conda install -y cmake mpir mpfr 'libflint<3' arb mpc fmt libboost-devel
mkdir build
cd build
cmake ../ -G "Visual Studio 17 2022" -A x64 -DCMAKE_CXX_STANDARD=20 -DMPPP_GMP_INCLUDE_DIR=C:\Miniconda\envs\test\Library\include -DMPPP_GMP_LIBRARY=C:\Miniconda\envs\test\Library\lib\mpir.lib -DMPPP_BUILD_TESTS=yes -DBoost_NO_BOOST_CMAKE=yes -DMPPP_WITH_BOOST_S11N=yes -DMPPP_WITH_FMT=yes -DMPPP_WITH_MPFR=yes -DMPPP_WITH_MPC=yes -DMPPP_WITH_ARB=yes -DMPPP_ENABLE_IPO=yes
cmake --build . --config Release -j2
copy Release\mp++.dll test\Release\
ctest -j4 -V -C Release
binder_cache:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -9,6 +9,23 @@
[![Anaconda-Server Badge](https://img.shields.io/conda/vn/conda-forge/mppp.svg?style=for-the-badge)](https://anaconda.org/conda-forge/mppp)
<!-- [![DOI](https://zenodo.org/badge/66504757.svg)](https://doi.org/10.5281/zenodo.1043579) -->

<!-- PROJECT LOGO -->
<br />
<p align="center">
<p align="center">
Multiprecision for C++
<br />
<a href="https://bluescarni.github.io/mppp/index.html"><strong>Explore the docs »</strong></a>
<br />
<br />
<a href="https://github.com/bluescarni/mppp/issues/new/choose">Report bug</a>
·
<a href="https://github.com/bluescarni/mppp/issues/new/choose">Request feature</a>
·
<a href="https://github.com/bluescarni/mppp/discussions">Discuss</a>
</p>
</p>

mp++ is a C++11/14/17/20 library for multiprecision arithmetic,
featuring:

@@ -54,6 +71,3 @@ at [this link](https://doi.org/10.5281/zenodo.1043579).

The documentation is available [here](https://bluescarni.github.io/mppp/).

> :warning: mp++ is under active development, and, although we try not to break the API
> gratuitously, backwards-incompatible changes do happen from time to time.
> The API will be stabilised with the upcoming release of version 1.0.
12 changes: 12 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Changelog
=========

1.0.0 (unreleased)
------------------

Fix
~~~

- Fix C++20 deprecations about user-defined literals
(`#303 <https://github.com/bluescarni/mppp/pull/303>`__).
- Fix compilation in C++20 mode with recent versions
of the fmt library
(`#303 <https://github.com/bluescarni/mppp/pull/303>`__).

0.27 (2022-10-21)
-----------------

6 changes: 0 additions & 6 deletions doc/index.rst
Original file line number Diff line number Diff line change
@@ -53,12 +53,6 @@ the repository and/or cite our work. The DOI of the latest version
and other citation resources are available
at `this link <https://doi.org/10.5281/zenodo.1043579>`__.

.. warning::

mp++ is under active development, and, although we try not to break the API
gratuitously, backwards-incompatible changes do happen from time to time.
The API will be stabilised with the upcoming release of version 1.0.

.. note::

This documentation refers to the latest development version of mp++, and it may describe features
14 changes: 4 additions & 10 deletions doc/installation.rst
Original file line number Diff line number Diff line change
@@ -9,12 +9,11 @@ Introduction
mp++ is written in modern C++, and it requires a compiler able to understand
at least C++11 (mp++ will also use features from C++14, C++17 and C++20,
if supported by the compiler). The library is regularly tested on
a comprehensive continuous integration pipeline, which includes:
a continuous integration pipeline which includes:

* various versions of the three major compilers (GCC, Clang and MSVC [#f1]_),
* various versions of the three major operating systems
(Linux, Windows and OSX),
* x86, ARM and PowerPC processors.
* the three major compilers (GCC, Clang and MSVC),
* the three major operating systems (Linux, Windows and OSX),
* x86 and ARM processors.

mp++ has the following dependencies:

@@ -42,11 +41,6 @@ mp++ has the following dependencies:
Additionally, `CMake <https://cmake.org/>`__ is the build system used by mp++ and it must also be available when
installing from source (the minimum required version is 3.8).

.. rubric:: Footnotes

.. [#f1] The Intel compiler is also occasionally tested, but it is not part of the continuous
integration setup.
Installation from source
------------------------

2 changes: 1 addition & 1 deletion include/mp++/complex.hpp
Original file line number Diff line number Diff line change
@@ -3170,7 +3170,7 @@ inline namespace literals

#define MPPP_DECLARE_COMPLEX_UDL(prec) \
template <char... Chars> \
inline complex operator"" _icr##prec() \
inline complex operator""_icr##prec() \
{ \
return complex{real{real_kind::zero, prec}, detail::real_literal_impl<Chars...>(prec)}; \
}
4 changes: 2 additions & 2 deletions include/mp++/complex128.hpp
Original file line number Diff line number Diff line change
@@ -1277,9 +1277,9 @@ inline namespace literals
{

template <char... Chars>
inline complex128 operator"" _icq()
inline complex128 operator""_icq()
{
return complex128{0, operator"" _rq<Chars...>()};
return complex128{0, operator""_rq < Chars... > ()};
}

} // namespace literals
29 changes: 23 additions & 6 deletions include/mp++/detail/fmt.hpp
Original file line number Diff line number Diff line change
@@ -9,10 +9,10 @@
#ifndef MPPP_DETAIL_FMT_HPP
#define MPPP_DETAIL_FMT_HPP

#include <stdexcept>

#include <fmt/core.h>

#include <mp++/config.hpp>

namespace mppp
{

@@ -21,13 +21,30 @@ namespace detail

struct to_string_formatter {
template <typename ParseContext>
auto parse(ParseContext &ctx) -> decltype(ctx.begin())
MPPP_CONSTEXPR_20 auto parse(ParseContext &ctx) -> decltype(ctx.begin())
{
if (ctx.begin() != ctx.end()) {
throw std::invalid_argument("No format strings are currently supported for mp++'s classes");
auto it = ctx.begin();
const auto end = ctx.end();

// Handle the special case for the '{}' format string.
if (it == end) {
return it;
}

// Parse until we get to the end or we find
// the closing bracket '}', ignoring the format
// string.
for (; it != end; ++it) {
if (*it == '}') {
// NOTE: according to the docs, we must return
// an iterator pointing to '}'.
return it;
}
}

return ctx.begin();
// LCOV_EXCL_START
fmt::throw_format_error("Invalid format");
// LCOV_EXCL_STOP
}

template <typename T, typename FormatContext>
2 changes: 1 addition & 1 deletion include/mp++/detail/integer_literals.hpp
Original file line number Diff line number Diff line change
@@ -403,7 +403,7 @@ inline namespace literals

#define MPPP_DECLARE_INTEGRAL_UDL(n) \
template <char... Chars> \
inline integer<n> operator"" _z##n() \
inline integer<n> operator""_z##n() \
{ \
return detail::integer_literal_impl<n, Chars...>(); \
}
2 changes: 1 addition & 1 deletion include/mp++/detail/rational_literals.hpp
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ inline namespace literals

#define MPPP_DECLARE_RATIONAL_UDL(n) \
template <char... Chars> \
inline rational<n> operator"" _q##n() \
inline rational<n> operator""_q##n() \
{ \
return rational<n>{detail::integer_literal_impl<n, Chars...>()}; \
}
2 changes: 1 addition & 1 deletion include/mp++/detail/real128_literal.hpp
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ inline namespace literals
{

template <char... Chars>
inline real128 operator"" _rq()
inline real128 operator""_rq()
{
// Turn the sequence of input chars
// into a null-terminated char array.
2 changes: 1 addition & 1 deletion include/mp++/detail/real_literals.hpp
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ inline namespace literals

#define MPPP_DECLARE_REAL_UDL(prec) \
template <char... Chars> \
inline real operator"" _r##prec() \
inline real operator""_r##prec() \
{ \
return detail::real_literal_impl<Chars...>(prec); \
}
9 changes: 5 additions & 4 deletions test/complex128_io.cpp
Original file line number Diff line number Diff line change
@@ -313,13 +313,14 @@ TEST_CASE("stream output")

TEST_CASE("fmt test")
{
using Catch::Matchers::Message;

REQUIRE(fmt::format("{}", 0_icq) == (0_icq).to_string());
REQUIRE(fmt::format("foo {} bar", 0_icq) == "foo " + (0_icq).to_string() + " bar");
REQUIRE(fmt::format("{}", -1.1_rq + 2.1_icq) == (-1.1_rq + 2.1_icq).to_string());
REQUIRE(fmt::format("foo {} bar", -1.1_rq + 2.1_icq) == "foo " + (-1.1_rq + 2.1_icq).to_string() + " bar");

REQUIRE_THROWS_MATCHES(fmt::format("{:<30}", -1.1_icq), std::invalid_argument,
Message("No format strings are currently supported for mp++'s classes"));
// Check that the string format is ignored.
REQUIRE(fmt::format("foo {:<30} bar", -1.1_rq + 2.1_icq) == "foo " + (-1.1_rq + 2.1_icq).to_string() + " bar");
REQUIRE(fmt::format("foo {:} bar", -1.1_rq + 2.1_icq) == "foo " + (-1.1_rq + 2.1_icq).to_string() + " bar");
}

#endif
14 changes: 9 additions & 5 deletions test/complex_io.cpp
Original file line number Diff line number Diff line change
@@ -319,13 +319,17 @@ TEST_CASE("ostream test")

TEST_CASE("fmt test")
{
using Catch::Matchers::Message;

REQUIRE(fmt::format("{}", 0_icr256) == (0_icr256).to_string());
REQUIRE(fmt::format("foo {} bar", 0_icr256) == "foo " + (0_icr256).to_string() + " bar");
REQUIRE(fmt::format("{}", -1.1_r256 + 2.1_icr256) == (-1.1_r256 + 2.1_icr256).to_string());

REQUIRE_THROWS_MATCHES(fmt::format("{:<30}", 2.1_icr256), std::invalid_argument,
Message("No format strings are currently supported for mp++'s classes"));
REQUIRE(fmt::format("foo {} bar", -1.1_r256 + 2.1_icr256)
== "foo " + (-1.1_r256 + 2.1_icr256).to_string() + " bar");

// Check that format flags are ignored.
REQUIRE(fmt::format("foo {:<30} bar", -1.1_r256 + 2.1_icr256)
== "foo " + (-1.1_r256 + 2.1_icr256).to_string() + " bar");
REQUIRE(fmt::format("foo {:} bar", -1.1_r256 + 2.1_icr256)
== "foo " + (-1.1_r256 + 2.1_icr256).to_string() + " bar");
}

#endif
30 changes: 26 additions & 4 deletions test/integer_arith_ops_01.cpp
Original file line number Diff line number Diff line change
@@ -325,8 +325,19 @@ struct sub_tester {
REQUIRE((std::is_same<decltype(char(4) - n2), integer>::value));
REQUIRE((lex_cast(n1 - static_cast<unsigned char>(4)) == "-3"));
REQUIRE((lex_cast(static_cast<unsigned char>(4) - n2) == "6"));
REQUIRE((lex_cast(n1 - short(4)) == "-3"));
REQUIRE((lex_cast(short(4) - n2) == "6"));
// NOTE: we used to have a test with short rather than
// int here. However, this would result in a bizarre test
// failure on GCC + ARM64 + C++20 + S::value == 3, which looked suspiciously
// similar to the failure referenced in the integer hashing
// test. That is, both failures involved the negation of an integer
// and both failures would randomly vanish by altering the code
// around the test (e.g., by inserting printing statements).
// My suspicion is that there is still some lingering issue
// in GCC perhaps related to all the union shenanigans going
// on in the implementation of the integer class, but pinning
// this down could be a major time sink...
REQUIRE((lex_cast(n1 - 4) == "-3"));
REQUIRE((lex_cast(4 - n2) == "6"));
REQUIRE((lex_cast(n1 - 4) == "-3"));
REQUIRE((lex_cast(4 - n2) == "6"));
REQUIRE((lex_cast(n1 - wchar_t{4}) == "-3"));
@@ -445,9 +456,20 @@ struct sub_tester {
});
}
// In-place with interop on the lhs.
short nl = 1;
// NOTE: we used to have a test with short rather than
// int here. However, this would result in a bizarre test
// failure on GCC + ARM64 + C++20 + S::value == 3, which looked suspiciously
// similar to the failure referenced in the integer hashing
// test. That is, both failures involved the negation of an integer
// and both failures would randomly vanish by altering the code
// around the test (e.g., by inserting printing statements).
// My suspicion is that there is still some lingering issue
// in GCC perhaps related to all the union shenanigans going
// on in the implementation of the integer class, but pinning
// this down could be a major time sink...
int nl = 1;
nl -= integer{1};
REQUIRE((std::is_same<short &, decltype(nl -= integer{1})>::value));
REQUIRE((std::is_same<int &, decltype(nl -= integer{1})>::value));
REQUIRE(nl == 0);
nl -= integer{-3};
REQUIRE(nl == 3);
9 changes: 5 additions & 4 deletions test/integer_stream_format.cpp
Original file line number Diff line number Diff line change
@@ -638,13 +638,14 @@ TEST_CASE("out test")

TEST_CASE("fmt test")
{
using Catch::Matchers::Message;

REQUIRE(fmt::format("{}", 0_z1) == (0_z1).to_string());
REQUIRE(fmt::format("foo {} bar", 0_z1) == "foo 0 bar");
REQUIRE(fmt::format("{}", -123_z2) == (-123_z2).to_string());
REQUIRE(fmt::format("foo {} bar", -123_z2) == "foo -123 bar");

REQUIRE_THROWS_MATCHES(fmt::format("{:<30}", 0_z1), std::invalid_argument,
Message("No format strings are currently supported for mp++'s classes"));
// Check that format strings are ignored.
REQUIRE(fmt::format("foo {:} bar", -123_z2) == "foo -123 bar");
REQUIRE(fmt::format("foo {:<30} bar", -123_z2) == "foo -123 bar");
}

#endif
9 changes: 5 additions & 4 deletions test/rational_stream_format.cpp
Original file line number Diff line number Diff line change
@@ -1188,13 +1188,14 @@ TEST_CASE("out test")

TEST_CASE("fmt test")
{
using Catch::Matchers::Message;

REQUIRE(fmt::format("{}", 0_q1) == (0_q1).to_string());
REQUIRE(fmt::format("foo {} bar", 0_q1) == "foo " + (0_q1).to_string() + " bar");
REQUIRE(fmt::format("{}", -123_q2 / 75) == (-123_q2 / 75).to_string());
REQUIRE(fmt::format("foo {} bar", -123_q2 / 75) == "foo " + (-123_q2 / 75).to_string() + " bar");

REQUIRE_THROWS_MATCHES(fmt::format("{:<30}", 0_q1), std::invalid_argument,
Message("No format strings are currently supported for mp++'s classes"));
// Check that the format string is ignored.
REQUIRE(fmt::format("foo {:<30} bar", -123_q2 / 75) == "foo " + (-123_q2 / 75).to_string() + " bar");
REQUIRE(fmt::format("foo {:} bar", -123_q2 / 75) == "foo " + (-123_q2 / 75).to_string() + " bar");
}

#endif
9 changes: 5 additions & 4 deletions test/real128_io.cpp
Original file line number Diff line number Diff line change
@@ -399,13 +399,14 @@ TEST_CASE("real128 io")

TEST_CASE("fmt test")
{
using Catch::Matchers::Message;

REQUIRE(fmt::format("{}", 0_rq) == (0_rq).to_string());
REQUIRE(fmt::format("foo {} bar", 0_rq) == "foo " + (0_rq).to_string() + " bar");
REQUIRE(fmt::format("{}", -1.1_rq) == (-1.1_rq).to_string());
REQUIRE(fmt::format("foo {} bar", -1.1_rq) == "foo " + (-1.1_rq).to_string() + " bar");

REQUIRE_THROWS_MATCHES(fmt::format("{:<30}", -1.1_rq), std::invalid_argument,
Message("No format strings are currently supported for mp++'s classes"));
// Check that the format string is ignored.
REQUIRE(fmt::format("foo {:<30} bar", -1.1_rq) == "foo " + (-1.1_rq).to_string() + " bar");
REQUIRE(fmt::format("foo {:} bar", -1.1_rq) == "foo " + (-1.1_rq).to_string() + " bar");
}

#endif
Loading

0 comments on commit 7bf0d70

Please sign in to comment.