brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · 5afed7d Raw
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