brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · b52f4f3 Raw
386 lines · plain
1//  Copyright John Maddock 2007.2//  Copyright Matt Borland 2023.3//  Use, modification and distribution are subject to the4//  Boost Software License, Version 1.0. (See accompanying file5//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)6 7#ifndef BOOST_MATH_TRUNC_HPP8#define BOOST_MATH_TRUNC_HPP9 10#ifdef _MSC_VER11#pragma once12#endif13 14#include <boost/math/tools/config.hpp>15#include <boost/math/tools/type_traits.hpp>16#include <boost/math/tools/numeric_limits.hpp>17 18#ifndef BOOST_MATH_HAS_NVRTC19 20#include <type_traits>21#include <boost/math/special_functions/math_fwd.hpp>22#include <boost/math/ccmath/detail/config.hpp>23#include <boost/math/policies/error_handling.hpp>24#include <boost/math/special_functions/fpclassify.hpp>25#include <boost/math/tools/is_constant_evaluated.hpp>26 27#if !defined(BOOST_MATH_NO_CCMATH) && !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION)28#include <boost/math/ccmath/ldexp.hpp>29#    define BOOST_MATH_HAS_CONSTEXPR_LDEXP30#endif31 32namespace boost{ namespace math{ namespace detail{33 34template <class T, class Policy>35BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy& pol, const std::false_type&)36{37   BOOST_MATH_STD_USING38   using result_type = tools::promote_args_t<T>;39   if(!(boost::math::isfinite)(v))40   {41      return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", nullptr, static_cast<result_type>(v), static_cast<result_type>(v), pol);42   }43   return (v >= 0) ? static_cast<result_type>(floor(v)) : static_cast<result_type>(ceil(v));44}45 46template <class T, class Policy>47BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy&, const std::true_type&)48{49   return v;50}51 52} // Namespace detail53 54template <class T, class Policy>55BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy& pol)56{57   return detail::trunc(v, pol, std::integral_constant<bool, detail::is_integer_for_rounding<T>::value>());58}59 60template <class T>61BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v)62{63   return trunc(v, policies::policy<>());64}65 66#else // Special handling for nvrtc67 68namespace boost {69namespace math {70 71namespace detail {72 73template <typename T>74BOOST_MATH_GPU_ENABLED double trunc_impl(T x)75{76   return static_cast<double>(x);77}78 79BOOST_MATH_GPU_ENABLED inline float trunc_impl(float x)80{81   return ::truncf(x);82}83 84BOOST_MATH_GPU_ENABLED inline double trunc_impl(double x)85{86   return ::trunc(x);87}88 89} // Namespace detail90 91template <typename T, typename Policy>92BOOST_MATH_GPU_ENABLED auto trunc(T x, const Policy&)93{94   return detail::trunc_impl(x);95}96 97template <typename T>98BOOST_MATH_GPU_ENABLED auto trunc(T x)99{100   return detail::trunc_impl(x);101}102 103#endif104 105#ifndef BOOST_MATH_HAS_NVRTC106 107//108// The following functions will not compile unless T has an109// implicit conversion to the integer types.  For user-defined110// number types this will likely not be the case.  In that case111// these functions should either be specialized for the UDT in112// question, or else overloads should be placed in the same113// namespace as the UDT: these will then be found via argument114// dependent lookup.  See our concept archetypes for examples.115//116// Non-standard numeric limits syntax "(std::numeric_limits<int>::max)()"117// is to avoid macro substiution from MSVC118// https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax119//120template <class T, class Policy>121BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol)122{123   BOOST_MATH_STD_USING124   using result_type = tools::promote_args_t<T>;125   result_type r = boost::math::trunc(v, pol);126 127   #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)128   if constexpr (std::is_arithmetic_v<result_type>129                 #ifdef BOOST_MATH_FLOAT128_TYPE130                 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>131                 #endif132                )133   {134      constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);135      136      if (r >= max_val || r < -max_val)137      {138         return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));139      }140   }141   else142   {143      static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);144   145      if (r >= max_val || r < -max_val)146      {147         return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));148      }149   }150   #else151   BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);152 153   if (r >= max_val || r < -max_val)154   {155      return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));156   }157   #endif158 159   return static_cast<int>(r);160}161 162template <class T>163BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v)164{165   return itrunc(v, policies::policy<>());166}167 168template <class T, class Policy>169BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol)170{171   BOOST_MATH_STD_USING172   using result_type = tools::promote_args_t<T>;173   result_type r = boost::math::trunc(v, pol);174 175   #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)176   if constexpr (std::is_arithmetic_v<result_type>177                 #ifdef BOOST_MATH_FLOAT128_TYPE178                 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>179                 #endif180                )181   {182      constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);183      184      if (r >= max_val || r < -max_val)185      {186         return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));187      }188   }189   else190   {191      static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);192   193      if (r >= max_val || r < -max_val)194      {195         return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));196      }197   }198   #else199   BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);200 201   if (r >= max_val || r < -max_val)202   {203      return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));204   }205   #endif206 207   return static_cast<long>(r);208}209 210template <class T>211BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v)212{213   return ltrunc(v, policies::policy<>());214}215 216template <class T, class Policy>217BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol)218{219   BOOST_MATH_STD_USING220   using result_type = tools::promote_args_t<T>;221   result_type r = boost::math::trunc(v, pol);222 223   #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)224   if constexpr (std::is_arithmetic_v<result_type>225                 #ifdef BOOST_MATH_FLOAT128_TYPE226                 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>227                 #endif228                )229   {230      constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);231      232      if (r >= max_val || r < -max_val)233      {234         return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));235      }236   }237   else238   {239      static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);240   241      if (r >= max_val || r < -max_val)242      {243         return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));244      }245   }246   #else247   BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);248 249   if (r >= max_val || r < -max_val)250   {251      return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));252   }253   #endif254 255   return static_cast<long long>(r);256}257 258template <class T>259BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v)260{261   return lltrunc(v, policies::policy<>());262}263 264#else // Reduced impl specifically for NVRTC platform265 266namespace detail {267 268template <typename TargetType, typename T>269BOOST_MATH_GPU_ENABLED TargetType integer_trunc_impl(T v)270{271   double r = boost::math::trunc(v);272 273   const double max_val = ldexp(1.0, boost::math::numeric_limits<TargetType>::digits);274 275   if (r >= max_val || r < -max_val)276   {277      r = 0;278   }279 280   return static_cast<TargetType>(r);281}282 283} // Namespace detail284 285template <typename T>286BOOST_MATH_GPU_ENABLED int itrunc(T v)287{288   return detail::integer_trunc_impl<int>(v);289}290 291template <typename T, typename Policy>292BOOST_MATH_GPU_ENABLED int itrunc(T v, const Policy&)293{294   return detail::integer_trunc_impl<int>(v);295}296 297template <typename T>298BOOST_MATH_GPU_ENABLED long ltrunc(T v)299{300   return detail::integer_trunc_impl<long>(v);301}302 303template <typename T, typename Policy>304BOOST_MATH_GPU_ENABLED long ltrunc(T v, const Policy&)305{306   return detail::integer_trunc_impl<long>(v);307}308 309template <typename T>310BOOST_MATH_GPU_ENABLED long long lltrunc(T v)311{312   return detail::integer_trunc_impl<long long>(v);313}314 315template <typename T, typename Policy>316BOOST_MATH_GPU_ENABLED long long lltrunc(T v, const Policy&)317{318   return detail::integer_trunc_impl<long long>(v);319}320 321#endif // BOOST_MATH_HAS_NVRTC322 323template <class T, class Policy>324BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<int, T>, int>325   iconvert(const T& v, const Policy&)326{327   return static_cast<int>(v);328}329 330template <class T, class Policy>331BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<!boost::math::is_constructible_v<int, T>, int>332   iconvert(const T& v, const Policy& pol)333{334   using boost::math::itrunc;335   return itrunc(v, pol);336}337 338template <class T, class Policy>339BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<long, T>, long>340   lconvert(const T& v, const Policy&)341{342   return static_cast<long>(v);343}344 345template <class T, class Policy>346BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<!boost::math::is_constructible_v<long, T>, long>347   lconvert(const T& v, const Policy& pol)348{349   using boost::math::ltrunc;350   return ltrunc(v, pol);351}352 353template <class T, class Policy>354BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<long long, T>, long long>355   llconvert(const T& v, const Policy&)356{357   return static_cast<long long>(v);358}359 360template <class T, class Policy>361BOOST_MATH_GPU_ENABLED inline typename boost::math::enable_if_t<!boost::math::is_constructible_v<long long, T>, long long>362   llconvert(const T& v, const Policy& pol)363{364   using boost::math::lltrunc;365   return lltrunc(v, pol);366}367 368template <class T, class Policy>369BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline boost::math::enable_if_t<boost::math::is_constructible_v<long long, T>, long long>370   llconvertert(const T& v, const Policy&)371{372   return static_cast<long long>(v);373}374 375template <class T, class Policy>376BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline typename boost::math::enable_if_t<!boost::math::is_constructible_v<long long, T>, long long>377   llconvertert(const T& v, const Policy& pol)378{379   using boost::math::lltrunc;380   return lltrunc(v, pol);381}382 383}} // namespaces384 385#endif // BOOST_MATH_TRUNC_HPP386