2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

constexpr div (#691)

This commit is contained in:
Matt Borland
2021-09-15 21:51:06 +03:00
committed by GitHub
parent e592fae531
commit 3b75b350a4
6 changed files with 156 additions and 3 deletions

View File

@@ -64,6 +64,12 @@ All of the following functions require C++17 or greater.
template <typename Integer>
inline constexpr double ldexp(Integer arg, int exp);
template <typename Integer>
struct div_t {Integer quot; Integer rem;};
template <typename Integer>
inline constexpr div_t<Integer> div(Integer x, Integer y);
} // Namespaces
[endsect] [/section:ccmath Constexpr CMath]

View File

@@ -4,8 +4,8 @@
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_MATH_CCMATH
#define BOOST_MATH_CCMATH
#ifndef BOOST_MATH_CCMATH_HPP
#define BOOST_MATH_CCMATH_HPP
#include <boost/math/ccmath/sqrt.hpp>
#include <boost/math/ccmath/isinf.hpp>
@@ -16,5 +16,6 @@
#include <boost/math/ccmath/isnormal.hpp>
#include <boost/math/ccmath/fpclassify.hpp>
#include <boost/math/ccmath/frexp.hpp>
#include <boost/math/ccmath/div.hpp>
#endif // BOOST_MATH_CCMATH
#endif // BOOST_MATH_CCMATH_HPP

View File

@@ -0,0 +1,84 @@
// (C) Copyright Matt Borland 2021.
// Use, modification and distribution are subject to 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_MATH_CCMATH_DIV_HPP
#define BOOST_MATH_CCMATH_DIV_HPP
#include <cmath>
#include <cstdlib>
#include <cinttypes>
#include <cstdint>
#include <type_traits>
namespace boost::math::ccmath {
namespace detail {
template <typename ReturnType, typename Z>
inline constexpr ReturnType div_impl(const Z x, const Z y) noexcept
{
// std::div_t/ldiv_t/lldiv_t/imaxdiv_t can be defined as either { Z quot; Z rem; }; or { Z rem; Z quot; };
// so don't use braced initialziation to guarantee compatibility
ReturnType ans {0, 0};
ans.quot = x / y;
ans.rem = x % y;
return ans;
}
} // Namespace detail
// Used for types other than built-ins (e.g. boost multiprecision)
template <typename Z>
struct div_t
{
Z quot;
Z rem;
};
template <typename Z>
inline constexpr auto div(Z x, Z y) noexcept
{
if constexpr (std::is_same_v<Z, int>)
{
return detail::div_impl<std::div_t>(x, y);
}
else if constexpr (std::is_same_v<Z, long>)
{
return detail::div_impl<std::ldiv_t>(x, y);
}
else if constexpr (std::is_same_v<Z, long long>)
{
return detail::div_impl<std::lldiv_t>(x, y);
}
else if constexpr (std::is_same_v<Z, std::intmax_t>)
{
return detail::div_impl<std::imaxdiv_t>(x, y);
}
else
{
return detail::div_impl<boost::math::ccmath::div_t<Z>>(x, y);
}
}
inline constexpr std::ldiv_t ldiv(long x, long y) noexcept
{
return detail::div_impl<std::ldiv_t>(x, y);
}
inline constexpr std::lldiv_t lldiv(long long x, long long y) noexcept
{
return detail::div_impl<std::lldiv_t>(x, y);
}
inline constexpr std::imaxdiv_t imaxdiv(std::intmax_t x, std::intmax_t y) noexcept
{
return detail::div_impl<std::imaxdiv_t>(x, y);
}
} // Namespaces
#endif // BOOST_MATH_CCMATH_DIV_HPP

View File

@@ -130,6 +130,7 @@ test-suite special_fun :
[ run ccmath_fpclassify_test.cpp ../../test/build//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] ]
[ run ccmath_frexp_test.cpp ../../test/build//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] ]
[ run ccmath_ldexp_test.cpp ../../test/build//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] ]
[ run ccmath_div_test.cpp ../../test/build//boost_unit_test_framework : : : [ requires cxx17_if_constexpr ] ]
[ run log1p_expm1_test.cpp test_instances//test_instances pch_light ../../test/build//boost_unit_test_framework ]
[ run powm1_sqrtp1m1_test.cpp test_instances//test_instances pch_light ../../test/build//boost_unit_test_framework ]
[ run special_functions_test.cpp ../../test/build//boost_unit_test_framework ]

47
test/ccmath_div_test.cpp Normal file
View File

@@ -0,0 +1,47 @@
// (C) Copyright Matt Borland 2021.
// Use, modification and distribution are subject to 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)
#include <cstdint>
#include <cinttypes>
#include <boost/math/ccmath/div.hpp>
#include <boost/math/tools/is_constant_evaluated.hpp>
#include <boost/multiprecision/cpp_int.hpp>
template <typename Z>
constexpr void test()
{
constexpr auto test_val1 = boost::math::ccmath::div(Z(1), Z(1));
static_assert(test_val1.quot == Z(1));
static_assert(test_val1.rem == Z(0));
constexpr auto test_val2 = boost::math::ccmath::div(Z(1'000'000), Z(3));
static_assert(test_val2.quot == Z(333'333));
static_assert(test_val2.rem == Z(1));
}
#if !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P)
int main()
{
test<int>();
test<long>();
test<long long>();
test<std::intmax_t>();
test<std::int32_t>();
test<std::int64_t>();
test<std::uint32_t>();
test<boost::multiprecision::int128_t>();
test<boost::multiprecision::int256_t>();
test<boost::multiprecision::int512_t>();
return 0;
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,14 @@
// (C) Copyright Matt Borland 2021.
// Use, modification and distribution are subject to 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)
#include <boost/math/ccmath/div.hpp>
#include "test_compile_result.hpp"
void compile_and_link_test()
{
check_result<std::div_t>(boost::math::ccmath::div(1, 1));
check_result<std::ldiv_t>(boost::math::ccmath::div(1l, 1l));
check_result<std::lldiv_t>(boost::math::ccmath::div(1ll, 1ll));
}