132 lines · plain
1// (C) Copyright Matt Borland 2021.2// Use, modification and distribution are subject to the3// Boost Software License, Version 1.0. (See accompanying file4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)5 6#ifndef BOOST_MATH_CCMATH_FLOOR_HPP7#define BOOST_MATH_CCMATH_FLOOR_HPP8 9#include <boost/math/ccmath/detail/config.hpp>10 11#ifdef BOOST_MATH_NO_CCMATH12#error "The header <boost/math/floor.hpp> can only be used in C++17 and later."13#endif14 15#include <boost/math/ccmath/abs.hpp>16#include <boost/math/ccmath/isinf.hpp>17#include <boost/math/ccmath/isnan.hpp>18#include <limits>19 20namespace boost::math::ccmath {21 22namespace detail {23 24template <typename T>25inline constexpr T floor_pos_impl(T arg) noexcept26{27 constexpr auto max_comp_val = T(1) / std::numeric_limits<T>::epsilon();28 29 if (arg >= max_comp_val)30 {31 return arg;32 }33 34 T result = 1;35 36 if(result <= arg)37 {38 while(result < arg)39 {40 result *= 2;41 }42 while(result > arg)43 {44 --result;45 }46 47 return result;48 }49 else50 {51 return T(0);52 }53}54 55template <typename T>56inline constexpr T floor_neg_impl(T arg) noexcept57{58 T result = -1;59 60 if(result > arg)61 {62 while(result > arg)63 {64 result *= 2;65 }66 while(result < arg)67 {68 ++result;69 }70 if(result != arg)71 {72 --result;73 }74 }75 76 return result;77}78 79template <typename T>80inline constexpr T floor_impl(T arg) noexcept81{82 if(arg > 0)83 {84 return floor_pos_impl(arg);85 }86 else87 {88 return floor_neg_impl(arg);89 }90}91 92} // Namespace detail93 94template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>95inline constexpr Real floor(Real arg) noexcept96{97 if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg))98 {99 return boost::math::ccmath::abs(arg) == Real(0) ? arg :100 boost::math::ccmath::isinf(arg) ? arg :101 boost::math::ccmath::isnan(arg) ? arg :102 boost::math::ccmath::detail::floor_impl(arg);103 }104 else105 {106 using std::floor;107 return floor(arg);108 }109}110 111template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>112inline constexpr double floor(Z arg) noexcept113{114 return boost::math::ccmath::floor(static_cast<double>(arg));115}116 117inline constexpr float floorf(float arg) noexcept118{119 return boost::math::ccmath::floor(arg);120}121 122#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS123inline constexpr long double floorl(long double arg) noexcept124{125 return boost::math::ccmath::floor(arg);126}127#endif128 129} // Namespaces130 131#endif // BOOST_MATH_CCMATH_FLOOR_HPP132