diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33f7bc4..ef1356a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: - { compiler: clang-19, cxxstd: "11,14,17,20,23,2c", os: ubuntu-24.04 } - { compiler: clang-20, cxxstd: "11,14,17,20,23,2c", os: ubuntu-latest, container: "ubuntu:25.04" } - { compiler: clang-21, cxxstd: "11,14,17,20,23,2c", os: ubuntu-latest, container: "ubuntu:26.04" } - - { compiler: clang-22, cxxstd: "11,14,17,20,23,2c", os: ubuntu-latest, container: "ubuntu:26.04" } + - { compiler: clang-22, cxxstd: "11,14,17,20,23,2c", os: ubuntu-latest, container: "ubuntu:26.04", self_contained_headers: "yes" } - { compiler: icpx-2025, cxxstd: "11,14,17,20,23,2c", os: ubuntu-latest, container: "intel/oneapi-hpckit:2025.2.2-0-devel-ubuntu24.04" } # libc++ - { name: "Clang w/ sanitizers", sanitize: "yes", stdlib: "libc++", @@ -283,6 +283,7 @@ jobs: ${B2_WRAPPER:-} ./b2 libs/$SELF/test "${ARGS[@]}" env: UBSAN_OPTIONS: print_stacktrace=1,report_error_type=1 + BOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS: ${{ matrix.self_contained_headers }} BDDE_DISTRO: ${{ matrix.distro }} BDDE_EDITION: ${{ matrix.edition }} BDDE_ARCH: ${{ matrix.arch }} @@ -506,7 +507,7 @@ jobs: fail-fast: false matrix: include: - - { os: ubuntu-latest, build_shared: "ON", build_type: Debug, generator: "Unix Makefiles" } + - { os: ubuntu-latest, build_shared: "ON", build_type: Debug, generator: "Unix Makefiles", self_contained_headers: "yes" } - { os: ubuntu-latest, build_shared: "OFF", build_type: Debug, generator: "Unix Makefiles" } - { os: windows-2022, build_shared: "ON", build_type: Debug, generator: "Visual Studio 17 2022" } - { os: windows-2022, build_shared: "OFF", build_type: Debug, generator: "Visual Studio 17 2022" } @@ -574,7 +575,7 @@ jobs: run: | cd "$BOOST_ROOT" mkdir __build_cmake_test__ && cd __build_cmake_test__ - cmake -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{ matrix.build_shared }} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON .. + cmake -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{ matrix.build_shared }} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ${{ matrix.self_contained_headers && '-DBOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS=ON' || '' }} .. cmake --build . --target tests --config ${{ matrix.build_type }} -j3 ctest --output-on-failure --no-tests=error --build-config ${{ matrix.build_type }} diff --git a/include/boost/numeric/interval/compare/certain.hpp b/include/boost/numeric/interval/compare/certain.hpp index 9232d5c..6b9f8a6 100644 --- a/include/boost/numeric/interval/compare/certain.hpp +++ b/include/boost/numeric/interval/compare/certain.hpp @@ -11,6 +11,7 @@ #define BOOST_NUMERIC_INTERVAL_COMPARE_CERTAIN_HPP #include +#include #include namespace boost { diff --git a/include/boost/numeric/interval/compare/lexicographic.hpp b/include/boost/numeric/interval/compare/lexicographic.hpp index 03f6036..4b38101 100644 --- a/include/boost/numeric/interval/compare/lexicographic.hpp +++ b/include/boost/numeric/interval/compare/lexicographic.hpp @@ -11,6 +11,7 @@ #define BOOST_NUMERIC_INTERVAL_COMPARE_LEXICOGRAPHIC_HPP #include +#include #include namespace boost { diff --git a/include/boost/numeric/interval/compare/possible.hpp b/include/boost/numeric/interval/compare/possible.hpp index 59bec31..32b748a 100644 --- a/include/boost/numeric/interval/compare/possible.hpp +++ b/include/boost/numeric/interval/compare/possible.hpp @@ -11,6 +11,7 @@ #define BOOST_NUMERIC_INTERVAL_COMPARE_POSSIBLE_HPP #include +#include #include namespace boost { diff --git a/include/boost/numeric/interval/compare/set.hpp b/include/boost/numeric/interval/compare/set.hpp index 44f4d6e..680fee8 100644 --- a/include/boost/numeric/interval/compare/set.hpp +++ b/include/boost/numeric/interval/compare/set.hpp @@ -11,6 +11,7 @@ #define BOOST_NUMERIC_INTERVAL_COMPARE_SET_HPP #include +#include #include #include diff --git a/include/boost/numeric/interval/compare/tribool.hpp b/include/boost/numeric/interval/compare/tribool.hpp index 6e4a83e..c27308f 100644 --- a/include/boost/numeric/interval/compare/tribool.hpp +++ b/include/boost/numeric/interval/compare/tribool.hpp @@ -11,6 +11,7 @@ #define BOOST_NUMERIC_INTERVAL_COMPARE_TRIBOOL_HPP #include +#include #include #include diff --git a/include/boost/numeric/interval/detail/comparison_error.hpp b/include/boost/numeric/interval/detail/comparison_error.hpp new file mode 100644 index 0000000..2441233 --- /dev/null +++ b/include/boost/numeric/interval/detail/comparison_error.hpp @@ -0,0 +1,34 @@ +/* Boost interval/detail/comparison_error.hpp file + * + * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion + * Copyright 2026 Sayan Samanta + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_NUMERIC_INTERVAL_DETAIL_COMPARISON_ERROR_HPP +#define BOOST_NUMERIC_INTERVAL_DETAIL_COMPARISON_ERROR_HPP + +#include +#include + +namespace boost { +namespace numeric { +namespace interval_lib { + +class BOOST_SYMBOL_VISIBLE comparison_error + : public std::runtime_error +{ +public: + comparison_error() + : std::runtime_error("boost::interval: uncertain comparison") + { } +}; + +} // namespace interval_lib +} // namespace numeric +} // namespace boost + +#endif // BOOST_NUMERIC_INTERVAL_DETAIL_COMPARISON_ERROR_HPP diff --git a/include/boost/numeric/interval/ext/x86_fast_rounding_control.hpp b/include/boost/numeric/interval/ext/x86_fast_rounding_control.hpp index a505ead..204d18a 100644 --- a/include/boost/numeric/interval/ext/x86_fast_rounding_control.hpp +++ b/include/boost/numeric/interval/ext/x86_fast_rounding_control.hpp @@ -17,6 +17,9 @@ #ifndef BOOST_NUMERIC_INTERVAL_EXT_X86_FAST_ROUNDING_CONTROL_HPP #define BOOST_NUMERIC_INTERVAL_EXT_X86_FAST_ROUNDING_CONTROL_HPP +#include +#include + namespace boost { namespace numeric { namespace interval_lib { diff --git a/include/boost/numeric/interval/interval.hpp b/include/boost/numeric/interval/interval.hpp index e89af48..10a6c40 100644 --- a/include/boost/numeric/interval/interval.hpp +++ b/include/boost/numeric/interval/interval.hpp @@ -13,23 +13,11 @@ #include #include #include +#include namespace boost { namespace numeric { -namespace interval_lib { - -class comparison_error - : public std::runtime_error -{ -public: - comparison_error() - : std::runtime_error("boost::interval: uncertain comparison") - { } -}; - -} // namespace interval_lib - /* * interval class */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cae3ff8..bf2f8b8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,6 +26,27 @@ set(BOOST_TEST_LINK_LIBRARIES Boost::numeric_interval Boost::core) boost_test(TYPE compile SOURCES integer.cpp) +# Each public header must compile on its own. These compile-only tests are +# slow and add little per configuration, so they are off by default and CI +# turns them on in one job. +option(BOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS "Test that each public header compiles on its own" OFF) + +if(BOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS) + set(headers_path ${CMAKE_CURRENT_SOURCE_DIR}/../include/boost/numeric) + file(GLOB_RECURSE headers RELATIVE ${headers_path} CONFIGURE_DEPENDS ${headers_path}/*.hpp) + list(FILTER headers EXCLUDE REGEX "/detail/") + # x86 only by design. + if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|amd64|x86|i[3-6]86)$") + list(REMOVE_ITEM headers interval/ext/x86_fast_rounding_control.hpp) + endif() + + foreach(h IN LISTS headers) + string(MAKE_C_IDENTIFIER "${h}" name) + boost_test(TYPE compile NAME self_contained-${name} SOURCES self_contained_header.cpp + COMPILE_DEFINITIONS BOOST_NUMERIC_INTERVAL_TEST_HEADER=${h}) + endforeach() +endif() + foreach(t add det fmod mul overflow pi pow cmp cmp_exp cmp_lex cmp_set test_float) boost_test(TYPE run SOURCES ${t}.cpp) endforeach() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 10cffa4..57b8885 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -22,10 +22,39 @@ project # bring in rules for testing import testing ; +import os ; +import path ; +import regex ; + +# Each public header must compile on its own. These compile-only tests are +# slow and add little per configuration, so they are off by default; set the +# BOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS environment variable to +# run them. +path-constant INTERVAL_INCLUDE_DIR : ../include ; + +local self_contained_tests ; +if [ os.environ BOOST_NUMERIC_INTERVAL_TEST_SELF_CONTAINED_HEADERS ] +{ + local headers_path = [ path.make $(INTERVAL_INCLUDE_DIR)/boost/numeric ] ; + for local file in [ path.glob-tree $(headers_path) : *.hpp : detail ] + { + local h = [ path.relative-to $(headers_path) $(file) ] ; + local requirements = BOOST_NUMERIC_INTERVAL_TEST_HEADER=$(h) $(file) ; + if $(h) = interval/ext/x86_fast_rounding_control.hpp + { + # x86 only by design. + requirements += [ check-target-builds /boost/architecture//x86 : : no ] ; + } + self_contained_tests += [ compile self_contained_header.cpp + : $(requirements) + : [ regex.replace self_contained-$(h) "[/.]" "-" ] ] ; + } +} { test-suite numeric/interval : [ compile integer.cpp ] + $(self_contained_tests) [ run add.cpp ] [ run det.cpp ] diff --git a/test/self_contained_header.cpp b/test/self_contained_header.cpp new file mode 100644 index 0000000..342bc8d --- /dev/null +++ b/test/self_contained_header.cpp @@ -0,0 +1,20 @@ +/* Boost test/self_contained_header.cpp + * test that a public header compiles when included on its own + * + * The header is given relative to boost/numeric by the build system in + * BOOST_NUMERIC_INTERVAL_TEST_HEADER, e.g. interval/compare/certain.hpp. + * + * Copyright 2026 Sayan Samanta + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#define BOOST_NUMERIC_INTERVAL_TEST_INCLUDE_HEADER() + +#include BOOST_NUMERIC_INTERVAL_TEST_INCLUDE_HEADER() + +int main() { + return 0; +}