Implements: Integer division function templates proposed in Integer division (P3724R1).
Status: Under development and not yet ready for production use.
beman.integer_division is licensed under the Apache License v2.0 with LLVM Exceptions.
std::div_modeis a family of functions that computes the quotient of an integer division with rounding mode of choicestd::div_rem_modeis a family of functions that computes the quotient and remainder simultaneouslystd::modcomputes the remainder of the division with rounding towards negative infinity
The following demonstrates how these functions may be used:
#include <beman/integer_division/integer_division.hpp>
namespace idiv = beman::integer_division;
int bucket_size = 1000;
int items = 100;
// Compute ceil(100 / 1000), i.e. round the quotient towards positive infinity.
// Using (100 / 1000) would be wrong here because it would mean that
// zero buckets are required to fit 100 elements.
int buckets_required = idiv::div_to_inf(items, bucket_size);
// result.quotient equals 1.
// result.remainder equals 900.
idiv::div_result<int> result = idiv::div_rem_to_inf(items, bucket_size);
// Alternative syntax using structured bindings.
auto [quotient, remainder] = idiv::div_rem_to_inf(items, bucket_size);
// The following examples use the mod function,
// which computes the remainder of an integer division with rounding towards negative infinity.
// This rounding mode is also known as "flooring", and is widely used in other languages.
// For example, Python's "%" operator uses this mode.
// It is particularly useful because the sign of the remainder is the sign of the divisor,
// unlike the builtin C++ "%" operator, which round towards zero,
// so the sign of the remainder is the sign of the dividend.
// Computes (100 mod 1000), which equals 100.
int wrap_100 = idiv::mod( 100, bucket_size);
// Computes (1400 mod 1000), which equals 400.
int wrap_1400 = idiv::mod(1400, bucket_size);
// Computes (-100 mod 1000), which equals 900.
int wrap_minus_100 = idiv::mod( -100, bucket_size);Full runnable examples can be found in examples/.
This project requires at least the following to build:
- A C++ compiler that conforms to the C++17 standard or greater
- CMake 3.25 or later
- (Test Only) GoogleTest
You can disable building tests by setting CMake option
BEMAN_EXEMPLAR_BUILD_TESTS to OFF
when configuring the project.
Even when tests are being built and run, some of them will not be compiled unless the provided compiler supports C++20 ranges.
Tip
The logs indicate examples disabled due to lack of compiler support.
For example:
-- Looking for __cpp_lib_ranges
-- Looking for __cpp_lib_ranges - not found
CMake Warning at examples/CMakeLists.txt:12 (message):
Missing range support! Skip: identity_as_default_projection
Examples to be built: identity_direct_usageThis project officially supports:
- GCC versions 11–15
- LLVM Clang++ (with libstdc++ or libc++) versions 17–21
- AppleClang version 17.0.0 (i.e., the latest version on GitHub-hosted macOS runners)
- MSVC version 19.44.35215.0 (i.e., the latest version on GitHub-hosted Windows runners)
Note
Versions outside of this range would likely work as well, especially if you're using a version above the given range (e.g. HEAD/ nightly). These development environments are verified using our CI configuration.
This project supports GitHub Codespace via Development Containers, which allows rapid development and instant hacking in your browser. We recommend using GitHub codespace to explore this project as it requires minimal setup.
Click the following badge to create a codespace:
For more documentation on GitHub codespaces, please see this doc.
Note
The codespace container may take up to 5 minutes to build and spin-up; this is normal.
For Linux
Beman libraries require recent versions of CMake, we recommend downloading CMake directly from CMake's website or installing it with the Kitware apt library.
A supported compiler should be available from your package manager.
For MacOS
Beman libraries require recent versions of CMake.
Use Homebrew to install the latest version of CMake.
brew install cmakeA supported compiler is also available from brew.
For example, you can install the latest major release of Clang as:
brew install llvmFor Windows
To build Beman libraries, you will need the MSVC compiler. MSVC can be obtained by installing Visual Studio; the free Visual Studio 2022 Community Edition can be downloaded from Microsoft.
After Visual Studio has been installed, you can launch "Developer PowerShell for VS 2022" by typing it into Windows search bar. This shell environment will provide CMake, Ninja, and MSVC, allowing you to build the library and run the tests.
Note that you will need to use FetchContent to build GoogleTest. To do so, please see the instructions in the "Build GoogleTest dependency from github.com" dropdown in the Project specific configure arguments section.
This project recommends using CMake Presets
to configure, build and test the project.
Appropriate presets for major compilers have been included by default.
You can use cmake --list-presets to see all available presets.
Here is an example to invoke the gcc-debug preset.
cmake --workflow --preset gcc-debugGenerally, there are two kinds of presets, debug and release.
The debug presets are designed to aid development, so it has debugging
instrumentation enabled and many sanitizers enabled.
Note
The sanitizers that are enabled vary from compiler to compiler.
See the toolchain files under (cmake) to determine the exact configuration used for each preset.
The release presets are designed for production use, and
consequently have the highest optimization turned on (e.g. O3).
If the presets are not suitable for your use-case, a traditional CMake invocation will provide more configurability.
To configure, build and test the project with extra arguments, you can run this set of commands.
cmake \
-B build \
-S . \
-DCMAKE_CXX_STANDARD=20 \
-DCMAKE_PREFIX_PATH=$PWD/infra/cmake \
# Your extra arguments here.
cmake --build build
ctest --test-dir buildImportant
Beman projects are
passive projects,
therefore,
you will need to specify the C++ version via CMAKE_CXX_STANDARD
when manually configuring the project.
If you do not have GoogleTest installed on your development system, you may optionally configure this project to download a known-compatible release of GoogleTest from source and build it as well.
Example commands:
cmake -B build -S . \
-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake \
-DCMAKE_CXX_STANDARD=20
cmake --build build --target all
cmake --build build --target testThe precise version of GoogleTest that will be used is maintained in
./lockfile.json.
Project-specific options are prefixed with BEMAN_EXEMPLAR.
You can see the list of available options with:
cmake -LH -S . -B build | grep "BEMAN_EXEMPLAR" -C 2Details of CMake arguments.
Enable building tests and test infrastructure. Default: ON.
Values: { ON, OFF }.
You can configure the project to have this option turned off via:
cmake -B build -S . -DCMAKE_CXX_STANDARD=20 -DBEMAN_EXEMPLAR_BUILD_TESTS=OFF[!TIP] Because this project requires GoogleTest for running tests, disabling
BEMAN_EXEMPLAR_BUILD_TESTSavoids the project from cloning GoogleTest from GitHub.
Enable building examples. Default: ON. Values: { ON, OFF }.
Enable installing the CMake config file package. Default: ON. Values: { ON, OFF }.
This is required so that users of beman.exemplar can use
find_package(beman.exemplar) to locate the library.
To use beman.integer_division in your C++ project,
include an appropriate beman.integer_division header from your source code.
#include <beman/integer_division/integer_division.hpp>Note
beman.integer_division headers are to be included with the beman/integer_division/ prefix.
Altering include search paths to spell the include target another way (e.g.
#include <identity.hpp>) is unsupported.
The process for incorporating beman.integer_division into your project depends on the
build system being used. Instructions for CMake are provided in following sections.
For CMake based projects,
you will need to use the beman.integer_division CMake module
to define the beman::integer_division CMake target:
find_package(beman.integer_division REQUIRED)You will also need to add beman::integer_division to the link libraries of
any libraries or executables that include beman.integer_division headers.
target_link_libraries(yourlib PUBLIC beman::integer_division)You can include exemplar's headers locally
by producing a static libbeman.integer_division.a library.
cmake --workflow --preset gcc-release
cmake --install build/gcc-release --prefix /opt/bemanThis will generate the following directory structure at /opt/beman.
/opt/beman
├── include
│ └── beman
│ └── integer_division
│ └── identity.hpp
└── lib
├── cmake
│ └── beman.integer_division
│ ├── beman.integer_division-config-version.cmake
│ ├── beman.integer_division-config.cmake
│ ├── beman.integer_division-targets-debug.cmake
│ └── beman.integer_division-targets.cmake
└── libbeman.integer_division.a