diff --git a/example/darkroom/two_spheres-8192x8192.png b/example/darkroom/two_spheres-8192x8192.png new file mode 100644 index 00000000..19634c52 Binary files /dev/null and b/example/darkroom/two_spheres-8192x8192.png differ diff --git a/sprout/algorithm/fill.hpp b/sprout/algorithm/fill.hpp index 8f193716..b67982ff 100644 --- a/sprout/algorithm/fill.hpp +++ b/sprout/algorithm/fill.hpp @@ -14,9 +14,9 @@ namespace sprout { // // 25.3.6 Fill // - template + template inline SPROUT_CXX14_CONSTEXPR void - fill(ForwrdIterator first, ForwrdIterator last, T const& value) { + fill(ForwardIterator first, ForwardIterator last, T const& value) { while (first != last) { *first++ = value; } diff --git a/sprout/algorithm/fixed/remove_copy.hpp b/sprout/algorithm/fixed/remove_copy.hpp index 856c8fe6..80b6f869 100644 --- a/sprout/algorithm/fixed/remove_copy.hpp +++ b/sprout/algorithm/fixed/remove_copy.hpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -93,7 +95,20 @@ namespace sprout { } } // namespace fixed - using sprout::fixed::remove_copy; + template< + typename InputIterator, typename Result, typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + remove_copy(InputIterator first, InputIterator last, Result const& result, T const& value) { + return sprout::fixed::remove_copy(first, last, result, value); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + remove_copy(InputIterator first, InputIterator last, T const& value) { + return sprout::fixed::remove_copy(first, last, value); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_HPP diff --git a/sprout/algorithm/fixed/remove_copy_if.hpp b/sprout/algorithm/fixed/remove_copy_if.hpp index 8c64b4c2..42be802c 100644 --- a/sprout/algorithm/fixed/remove_copy_if.hpp +++ b/sprout/algorithm/fixed/remove_copy_if.hpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -93,7 +95,20 @@ namespace sprout { } } // namespace fixed - using sprout::fixed::remove_copy_if; + template< + typename InputIterator, typename Result, typename Predicate, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + remove_copy_if(InputIterator first, InputIterator last, Result const& result, Predicate pred) { + return sprout::fixed::remove_copy_if(first, last, result, pred); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + remove_copy_if(InputIterator first, InputIterator last, Predicate pred) { + return sprout::fixed::remove_copy_if(first, last, pred); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_IF_HPP diff --git a/sprout/algorithm/fixed/reverse_copy.hpp b/sprout/algorithm/fixed/reverse_copy.hpp index 0d4a3be7..7d7715e9 100644 --- a/sprout/algorithm/fixed/reverse_copy.hpp +++ b/sprout/algorithm/fixed/reverse_copy.hpp @@ -137,7 +137,20 @@ namespace sprout { } } // namespace fixed - using sprout::fixed::reverse_copy; + template< + typename BidirectionalIterator, typename Result, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + reverse_copy(BidirectionalIterator first, BidirectionalIterator last, Result const& result) { + return sprout::fixed::reverse_copy(first, last, result); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + reverse_copy(BidirectionalIterator first, BidirectionalIterator last) { + return sprout::fixed::reverse_copy(first, last); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_REVERSE_COPY_HPP diff --git a/sprout/algorithm/fixed/rotate_copy.hpp b/sprout/algorithm/fixed/rotate_copy.hpp index 2a514778..d00654c9 100644 --- a/sprout/algorithm/fixed/rotate_copy.hpp +++ b/sprout/algorithm/fixed/rotate_copy.hpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,7 +180,20 @@ namespace sprout { } } // namespace fixed - using sprout::fixed::rotate_copy; + template< + typename ForwardIterator, typename Result, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Result const& result) { + return sprout::fixed::rotate_copy(first, middle, last, result); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last) { + return sprout::fixed::rotate_copy(first, middle, last); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_ROTATE_COPY_HPP diff --git a/sprout/algorithm/fixed/unique_copy.hpp b/sprout/algorithm/fixed/unique_copy.hpp index 833d0615..5412f888 100644 --- a/sprout/algorithm/fixed/unique_copy.hpp +++ b/sprout/algorithm/fixed/unique_copy.hpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -178,7 +180,38 @@ namespace sprout { } } // namespace fixed - using sprout::fixed::unique_copy; + template< + typename InputIterator, typename Result, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + unique_copy(InputIterator first, InputIterator last, Result const& result) { + return sprout::fixed::unique_copy(first, last, result); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + unique_copy(InputIterator first, InputIterator last) { + return sprout::fixed::unique_copy(first, last); + } + + template< + typename InputIterator, typename Result, typename BinaryPredicate, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + unique_copy(InputIterator first, InputIterator last, Result const& result, BinaryPredicate pred) { + return sprout::fixed::unique_copy(first, last, result, pred); + } + + template< + typename Result, typename InputIterator, typename BinaryPredicate, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type + unique_copy(InputIterator first, InputIterator last, BinaryPredicate pred) { + return sprout::fixed::unique_copy(first, last, pred); + } } // namespace sprout #endif // #ifndef SPROUT_ALGORITHM_FIXED_UNIQUE_COPY_HPP diff --git a/sprout/algorithm/generate.hpp b/sprout/algorithm/generate.hpp index 38fc1721..d579ec00 100644 --- a/sprout/algorithm/generate.hpp +++ b/sprout/algorithm/generate.hpp @@ -14,9 +14,9 @@ namespace sprout { // // 25.3.7 Generate // - template + template inline SPROUT_CXX14_CONSTEXPR void - generate(ForwrdIterator first, ForwrdIterator last, Generator gen) { + generate(ForwardIterator first, ForwardIterator last, Generator gen) { while (first != last) { *first++ = gen(); } diff --git a/sprout/algorithm/modifying.hpp b/sprout/algorithm/modifying.hpp index 552c952d..8ecc6681 100644 --- a/sprout/algorithm/modifying.hpp +++ b/sprout/algorithm/modifying.hpp @@ -40,11 +40,12 @@ #include #include #include +#include #include #include #include -#include #include +#include #include #include #include diff --git a/sprout/algorithm/partition.hpp b/sprout/algorithm/partition.hpp index db0308a6..3275454d 100644 --- a/sprout/algorithm/partition.hpp +++ b/sprout/algorithm/partition.hpp @@ -9,6 +9,28 @@ #define SPROUT_ALGORITHM_PARTITION_HPP #include +#include +#include +#include + +namespace sprout { + // + // 25.3.13 Partitions + // + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + partition(ForwardIterator first, ForwardIterator last, Predicate pred) { + first = sprout::find_if_not(first, last, pred); + ForwardIterator it = sprout::find_if(first, last, pred); + while (it != last) { + sprout::iter_swap(first, it); + first = sprout::find_if_not(first, last, pred); + it = sprout::find_if(it, last, pred); + } + return first; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/partition_copy.hpp b/sprout/algorithm/partition_copy.hpp index fae72760..0a89b5a7 100644 --- a/sprout/algorithm/partition_copy.hpp +++ b/sprout/algorithm/partition_copy.hpp @@ -9,6 +9,17 @@ #define SPROUT_ALGORITHM_PARTITION_COPY_HPP #include +#include + +namespace sprout { + // + // 25.3.13 Partitions + // + template + inline SPROUT_CXX14_CONSTEXPR sprout::pair + partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); // !!! +} // namespace sprout + #include #include diff --git a/sprout/algorithm/random_shuffle.hpp b/sprout/algorithm/random_shuffle.hpp new file mode 100644 index 00000000..7c9ad98e --- /dev/null +++ b/sprout/algorithm/random_shuffle.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2011-2013 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under 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 SPROUT_ALGORITHM_RANDOM_SHUFFLE_HPP +#define SPROUT_ALGORITHM_RANDOM_SHUFFLE_HPP + +#include +#include + +namespace sprout { + // + // 25.3.12 Random shuffle + // + template + inline SPROUT_CXX14_CONSTEXPR void + random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rand) { + if (first == last) { + return; + } + for (auto it = first + 1; it != last; ++it) { + sprout::iter_swap(it, first + rand(it - first + 1)); + } + } +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_RANDOM_SHUFFLE_HPP diff --git a/sprout/algorithm/remove.hpp b/sprout/algorithm/remove.hpp index f429bf50..48e5c884 100644 --- a/sprout/algorithm/remove.hpp +++ b/sprout/algorithm/remove.hpp @@ -9,6 +9,25 @@ #define SPROUT_ALGORITHM_REMOVE_HPP #include +#include + +namespace sprout { + // + // 25.3.8 Remove + // + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + remove(ForwardIterator first, ForwardIterator last, T const& value) { + ForwardIterator result = first; + for (; first != last; ++first) { + if (!(*first == value)) { + *result++ = sprout::move(*first); + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/remove_copy.hpp b/sprout/algorithm/remove_copy.hpp index 11385026..e84e627e 100644 --- a/sprout/algorithm/remove_copy.hpp +++ b/sprout/algorithm/remove_copy.hpp @@ -9,6 +9,28 @@ #define SPROUT_ALGORITHM_REMOVE_COPY_HPP #include +#include +#include + +namespace sprout { + // + // 25.3.8 Remove + // + template< + typename InputIterator, typename OutputIterator, typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + remove_copy(InputIterator first, InputIterator last, OutputIterator result, T const& value) { + for (; first != last; ++first) { + if (!(*first == value)) { + *result++ = *first; + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/remove_copy_if.hpp b/sprout/algorithm/remove_copy_if.hpp index 9b218ba2..b1f3e124 100644 --- a/sprout/algorithm/remove_copy_if.hpp +++ b/sprout/algorithm/remove_copy_if.hpp @@ -9,6 +9,28 @@ #define SPROUT_ALGORITHM_REMOVE_COPY_IF_HPP #include +#include +#include + +namespace sprout { + // + // 25.3.8 Remove + // + template< + typename InputIterator, typename OutputIterator, typename Predicate, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred) { + for (; first != last; ++first) { + if (!pred(*first)) { + *result++ = *first; + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/remove_if.hpp b/sprout/algorithm/remove_if.hpp index 6c398756..e7570548 100644 --- a/sprout/algorithm/remove_if.hpp +++ b/sprout/algorithm/remove_if.hpp @@ -9,6 +9,25 @@ #define SPROUT_ALGORITHM_REMOVE_IF_HPP #include +#include + +namespace sprout { + // + // 25.3.8 Remove + // + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + remove_if(ForwardIterator first, ForwardIterator last, Predicate pred) { + ForwardIterator result = first; + for (; first != last; ++first) { + if (!pred(*first)) { + *result++ = sprout::move(*first); + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/replace.hpp b/sprout/algorithm/replace.hpp index ca196c25..b918a9d1 100644 --- a/sprout/algorithm/replace.hpp +++ b/sprout/algorithm/replace.hpp @@ -14,9 +14,9 @@ namespace sprout { // // 25.3.5 Replace // - template + template inline SPROUT_CXX14_CONSTEXPR void - replace(ForwrdIterator first, ForwrdIterator last, T const& old_value, T const& new_value) { + replace(ForwardIterator first, ForwardIterator last, T const& old_value, T const& new_value) { for (; first != last; ++first) { if (*first == old_value) { *first = new_value; diff --git a/sprout/algorithm/replace_if.hpp b/sprout/algorithm/replace_if.hpp index 75689137..53e772c5 100644 --- a/sprout/algorithm/replace_if.hpp +++ b/sprout/algorithm/replace_if.hpp @@ -14,9 +14,9 @@ namespace sprout { // // 25.3.5 Replace // - template + template inline SPROUT_CXX14_CONSTEXPR void - replace_if(ForwrdIterator first, ForwrdIterator last, Predicate pred, T const& new_value) { + replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, T const& new_value) { for (; first != last; ++first) { if (pred(*first)) { *first = new_value; diff --git a/sprout/algorithm/reverse.hpp b/sprout/algorithm/reverse.hpp index 0c923438..899731aa 100644 --- a/sprout/algorithm/reverse.hpp +++ b/sprout/algorithm/reverse.hpp @@ -9,6 +9,21 @@ #define SPROUT_ALGORITHM_REVERSE_HPP #include +#include + +namespace sprout { + // + // 25.3.10 Reverse + // + template + inline SPROUT_CXX14_CONSTEXPR void + reverse(BidirectionalIterator first, BidirectionalIterator last) { + for (; first != last && first != --last; ++first) { + sprout::iter_swap(first, last); + } + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/reverse_copy.hpp b/sprout/algorithm/reverse_copy.hpp index bd66d098..c45f0d3d 100644 --- a/sprout/algorithm/reverse_copy.hpp +++ b/sprout/algorithm/reverse_copy.hpp @@ -9,6 +9,26 @@ #define SPROUT_ALGORITHM_REVERSE_COPY_HPP #include +#include +#include + +namespace sprout { + // + // 25.3.10 Reverse + // + template< + typename BidirectionalIterator, typename OutputIterator, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result) { + while (first != last) { + *result++ = *--last; + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/rotate.hpp b/sprout/algorithm/rotate.hpp index 1180a9ce..4023e05f 100644 --- a/sprout/algorithm/rotate.hpp +++ b/sprout/algorithm/rotate.hpp @@ -8,7 +8,53 @@ #ifndef SPROUT_ALGORITHM_ROTATE_HPP #define SPROUT_ALGORITHM_ROTATE_HPP +#include #include +#include + +namespace sprout { + // + // 25.3.11 Rotate + // + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) { + if (first == middle) { + return last; + } else if (middle == last) { + return first; + } + ForwardIterator first2 = middle; + while (true) { + sprout::iter_swap(first, first2); + ++first; + if (++first2 == last) { + break; + } + if (first == middle) { + middle = first2; + } + } + ForwardIterator result = first; + if (first != middle) { + first2 = middle; + while (true) { + sprout::iter_swap(first, first2); + ++first; + if (++first2 == last) { + if (first == middle) { + break; + } + first2 = middle; + } else if (first == middle) { + middle = first2; + } + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/rotate_copy.hpp b/sprout/algorithm/rotate_copy.hpp index e268f5cb..dac4f483 100644 --- a/sprout/algorithm/rotate_copy.hpp +++ b/sprout/algorithm/rotate_copy.hpp @@ -9,6 +9,24 @@ #define SPROUT_ALGORITHM_ROTATE_COPY_HPP #include +#include +#include +#include + +namespace sprout { + // + // 25.3.11 Rotate + // + template< + typename ForwardIterator, typename OutputIterator, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) { + return sprout::copy(first, middle, sprout::copy(middle, last, result)); + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/shuffle.hpp b/sprout/algorithm/shuffle.hpp index 2cc943e3..41bb628e 100644 --- a/sprout/algorithm/shuffle.hpp +++ b/sprout/algorithm/shuffle.hpp @@ -9,6 +9,16 @@ #define SPROUT_ALGORITHM_SHUFFLE_HPP #include + +namespace sprout { + // + // 25.3.12 Random shuffle + // + template + inline SPROUT_CXX14_CONSTEXPR void + shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& g); // !!! +} // namespace sprout + #include #include diff --git a/sprout/algorithm/stable_partition.hpp b/sprout/algorithm/stable_partition.hpp index 86e95b3e..b2a03b7e 100644 --- a/sprout/algorithm/stable_partition.hpp +++ b/sprout/algorithm/stable_partition.hpp @@ -9,6 +9,17 @@ #define SPROUT_ALGORITHM_STABLE_PARTITION_HPP #include + + +namespace sprout { + // + // 25.3.13 Partitions + // + template + inline SPROUT_CXX14_CONSTEXPR BidirectionalIterator + stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); // !!! +} // namespace sprout + #include #include diff --git a/sprout/algorithm/unique.hpp b/sprout/algorithm/unique.hpp index 0ba1ff2d..38c88ec9 100644 --- a/sprout/algorithm/unique.hpp +++ b/sprout/algorithm/unique.hpp @@ -8,7 +8,50 @@ #ifndef SPROUT_ALGORITHM_UNIQUE_HPP #define SPROUT_ALGORITHM_UNIQUE_HPP +#include #include +#include + +namespace sprout { + // + // 25.3.9 Unique + // + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + unique(ForwardIterator first, ForwardIterator last) { + if (first == last) { + return first; + } + ForwardIterator result = first; + typename std::iterator_traits::value_type value = sprout::move(*first++); + for (; first != last; ++first) { + if (!(value == *first)) { + *result++ = sprout::move(value); + value = sprout::move(*first); + } + } + *result++ = sprout::move(value); + return result; + } + template + inline SPROUT_CXX14_CONSTEXPR ForwardIterator + unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { + if (first == last) { + return first; + } + ForwardIterator result = first; + typename std::iterator_traits::value_type value = sprout::move(*first++); + for (; first != last; ++first) { + if (!pred(value, *first)) { + *result++ = sprout::move(value); + value = sprout::move(*first); + } + } + *result++ = sprout::move(value); + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/algorithm/unique_copy.hpp b/sprout/algorithm/unique_copy.hpp index d6c0b4dd..57e79532 100644 --- a/sprout/algorithm/unique_copy.hpp +++ b/sprout/algorithm/unique_copy.hpp @@ -1,14 +1,63 @@ /*============================================================================= - Copyright (c) 2011-2013 Bolero MURAKAMI - https://github.com/bolero-MURAKAMI/Sprout + Copyright (c) 2011-2013 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout - Distributed under 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) + Distributed under 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 SPROUT_ALGORITHM_UNIQUE_COPY_HPP #define SPROUT_ALGORITHM_UNIQUE_COPY_HPP +#include #include +#include +#include + +namespace sprout { + // + // 25.3.9 Unique + // + template< + typename InputIterator, typename OutputIterator, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + unique_copy(InputIterator first, InputIterator last, OutputIterator result) { + if (first == last) { + return result; + } + typename std::iterator_traits::value_type value = *first++; + *result++ = value; + for (; first != last; ++first) { + if (!(value == *first)) { + value = *first; + *result++ = value; + } + } + return result; + } + + template< + typename InputIterator, typename OutputIterator, typename BinaryPredicate, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CXX14_CONSTEXPR OutputIterator + unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred) { + if (first == last) { + return result; + } + typename std::iterator_traits::value_type value = *first++; + *result++ = value; + for (; first != last; ++first) { + if (!pred(value, *first)) { + value = *first; + *result++ = value; + } + } + return result; + } +} // namespace sprout + #include #include diff --git a/sprout/array/make_array.hpp b/sprout/array/make_array.hpp index a443f250..51f06664 100644 --- a/sprout/array/make_array.hpp +++ b/sprout/array/make_array.hpp @@ -25,6 +25,15 @@ namespace sprout { make_array(Types&&... args) { return sprout::array{{T(sprout::forward(args))...}}; } +// template +// inline SPROUT_CONSTEXPR sprout::array::type, sizeof...(Types)> +// make_array(Types&&... args) { +// typedef sprout::array< +// typename sprout::common_decay::type, +// sizeof...(Types) +// > type; +// return type{{typename sprout::common_decay::type(sprout::forward(args))...}}; +// } // // make_common_array diff --git a/sprout/math/abs.hpp b/sprout/math/abs.hpp index 72f3311c..90062e21 100644 --- a/sprout/math/abs.hpp +++ b/sprout/math/abs.hpp @@ -16,24 +16,16 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - abs(FloatType x) { - return sprout::math::fabs(x); - } - } // namespace detail - + // + // abs + // template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType abs(FloatType x) { - return NS_SPROUT_MATH_DETAIL::abs(x); + return sprout::math::fabs(x); } } // namespace math diff --git a/sprout/math/acos.hpp b/sprout/math/acos.hpp index b3ab5cdf..0b87ab51 100644 --- a/sprout/math/acos.hpp +++ b/sprout/math/acos.hpp @@ -22,39 +22,54 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_acos(float x) { + return __builtin_acosf(x); + } + inline SPROUT_CONSTEXPR double + builtin_acos(double x) { + return __builtin_acos(x); + } + inline SPROUT_CONSTEXPR long double + builtin_acos(long double x) { + return __builtin_acosl(x); + } +#endif + template inline SPROUT_CONSTEXPR T acos_impl(T x) { return sprout::math::half_pi() - sprout::math::asin(x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - acos(FloatType x) { - return sprout::math::isnan(x) ? x - : sprout::math::fabs(x) > 1 ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::acos(x) -#else - : x == 1 ? FloatType(0) - : static_cast(sprout::math::detail::acos_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - acos(IntType x) { - return sprout::math::detail::acos(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::acos; + // + // acos + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + acos(FloatType x) { + return sprout::math::isnan(x) ? x + : sprout::math::fabs(x) > 1 ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_acos(x) +#else + : x == 1 ? FloatType(0) + : static_cast(sprout::math::detail::acos_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + acos(IntType x) { + return sprout::math::acos(static_cast(x)); + } } // namespace math using sprout::math::acos; diff --git a/sprout/math/acosh.hpp b/sprout/math/acosh.hpp index ac62f4e6..b66e9fed 100644 --- a/sprout/math/acosh.hpp +++ b/sprout/math/acosh.hpp @@ -21,40 +21,55 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_acosh(float x) { + return __builtin_acoshf(x); + } + inline SPROUT_CONSTEXPR double + builtin_acosh(double x) { + return __builtin_acosh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_acosh(long double x) { + return __builtin_acoshl(x); + } +#endif + template inline SPROUT_CONSTEXPR T acosh_impl(T x) { return sprout::math::log(x + sprout::math::sqrt(x * x - 1)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - acosh(FloatType x) { - return sprout::math::isnan(x) ? x - : x < 1 ? -sprout::numeric_limits::quiet_NaN() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::acosh(x) -#else - : x == 1 ? FloatType(0) - : static_cast(sprout::math::detail::acosh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - acosh(IntType x) { - return sprout::math::detail::acosh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::acosh; + // + // acosh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + acosh(FloatType x) { + return sprout::math::isnan(x) ? x + : x < 1 ? -sprout::numeric_limits::quiet_NaN() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_acosh(x) +#else + : x == 1 ? FloatType(0) + : static_cast(sprout::math::detail::acosh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + acosh(IntType x) { + return sprout::math::acosh(static_cast(x)); + } } // namespace math using sprout::math::acosh; diff --git a/sprout/math/asin.hpp b/sprout/math/asin.hpp index fcd45c87..6afd3d13 100644 --- a/sprout/math/asin.hpp +++ b/sprout/math/asin.hpp @@ -24,6 +24,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_asin(float x) { + return __builtin_asinf(x); + } + inline SPROUT_CONSTEXPR double + builtin_asin(double x) { + return __builtin_asin(x); + } + inline SPROUT_CONSTEXPR long double + builtin_asin(long double x) { + return __builtin_asinl(x); + } +#endif + template inline SPROUT_CONSTEXPR T asin_impl_center_1(T x, T x2) { @@ -76,37 +91,37 @@ namespace sprout { : sprout::math::detail::asin_impl_center(x) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - asin(FloatType x) { - return sprout::math::isnan(x) ? x - : sprout::math::fabs(x) > 1 ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::asin(x) -#else - : x == 0 ? x - : static_cast( - x < 0 ? -sprout::math::detail::asin_impl(static_cast::type>(-x)) - : sprout::math::detail::asin_impl(static_cast::type>(x)) - ) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - asin(IntType x) { - return sprout::math::detail::asin(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::asin; + // + // asin + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + asin(FloatType x) { + return sprout::math::isnan(x) ? x + : sprout::math::fabs(x) > 1 ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_asin(x) +#else + : x == 0 ? x + : static_cast( + x < 0 ? -sprout::math::detail::asin_impl(static_cast::type>(-x)) + : sprout::math::detail::asin_impl(static_cast::type>(x)) + ) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + asin(IntType x) { + return sprout::math::asin(static_cast(x)); + } } // namespace math using sprout::math::asin; diff --git a/sprout/math/asinh.hpp b/sprout/math/asinh.hpp index 890ea664..d23df972 100644 --- a/sprout/math/asinh.hpp +++ b/sprout/math/asinh.hpp @@ -21,40 +21,55 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_asinh(float x) { + return __builtin_asinhf(x); + } + inline SPROUT_CONSTEXPR double + builtin_asinh(double x) { + return __builtin_asinh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_asinh(long double x) { + return __builtin_asinhl(x); + } +#endif + template inline SPROUT_CONSTEXPR T asinh_impl(T x) { return sprout::math::log(x + sprout::math::sqrt(x * x + 1)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - asinh(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::asinh(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::asinh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - asinh(IntType x) { - return sprout::math::detail::asinh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::asinh; + // + // asinh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + asinh(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_asinh(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::asinh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + asinh(IntType x) { + return sprout::math::asinh(static_cast(x)); + } } // namespace math using sprout::math::asinh; diff --git a/sprout/math/atan.hpp b/sprout/math/atan.hpp index 399e3e03..c910c6d8 100644 --- a/sprout/math/atan.hpp +++ b/sprout/math/atan.hpp @@ -23,6 +23,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_atan(float x) { + return __builtin_atanf(x); + } + inline SPROUT_CONSTEXPR double + builtin_atan(double x) { + return __builtin_atan(x); + } + inline SPROUT_CONSTEXPR long double + builtin_atan(long double x) { + return __builtin_atanl(x); + } +#endif + template inline SPROUT_CONSTEXPR T atan_impl_1(T x, std::size_t n, std::size_t last) { @@ -43,37 +58,38 @@ namespace sprout { ; } - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - atan(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::math::half_pi() - : x == -sprout::numeric_limits::infinity() ? -sprout::math::half_pi() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::atan(x) -#else - : x == 0 ? x - : static_cast( - x < 0 ? -sprout::math::detail::atan_impl(static_cast::type>(-x)) - : sprout::math::detail::atan_impl(static_cast::type>(x)) - ) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - atan(IntType x) { - return sprout::math::detail::atan(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::atan; + // + // atan + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + atan(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::math::half_pi() + : x == -sprout::numeric_limits::infinity() ? -sprout::math::half_pi() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_atan(x) +#else + : x == 0 ? x + : static_cast( + x < 0 ? -sprout::math::detail::atan_impl(static_cast::type>(-x)) + : sprout::math::detail::atan_impl(static_cast::type>(x)) + ) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + atan(IntType x) { + return sprout::math::atan(static_cast(x)); + } } // namespace math using sprout::math::atan; diff --git a/sprout/math/atan2.hpp b/sprout/math/atan2.hpp index a6595b5a..8953cb8c 100644 --- a/sprout/math/atan2.hpp +++ b/sprout/math/atan2.hpp @@ -25,6 +25,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_atan2(float y, float x) { + return __builtin_atan2f(y, x); + } + inline SPROUT_CONSTEXPR double + builtin_atan2(double y, double x) { + return __builtin_atan2(y, x); + } + inline SPROUT_CONSTEXPR long double + builtin_atan2(long double y, long double x) { + return __builtin_atan2l(y, x); + } +#endif + template inline SPROUT_CONSTEXPR T atan2_impl(T y, T x) { @@ -35,63 +50,10 @@ namespace sprout { : sprout::math::atan(y / x) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - atan2(FloatType y, FloatType x) { - return sprout::math::isnan(y) - ? sprout::math::isnan(x) - ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() - : sprout::numeric_limits::quiet_NaN() - : y - : sprout::math::isnan(x) ? x - : x == -sprout::numeric_limits::infinity() - ? y == sprout::numeric_limits::infinity() ? sprout::math::three_quarters_pi() - : y == -sprout::numeric_limits::infinity() ? -sprout::math::three_quarters_pi() - : sprout::math::copysign(sprout::math::pi(), y) - : x == sprout::numeric_limits::infinity() - ? y == sprout::numeric_limits::infinity() ? sprout::math::quarter_pi() - : y == -sprout::numeric_limits::infinity() ? -sprout::math::quarter_pi() - : FloatType(0) * y - : y == sprout::numeric_limits::infinity() ? sprout::math::half_pi() - : y == -sprout::numeric_limits::infinity() ? -sprout::math::half_pi() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::atan2(y, x) -#else - : y == 0 - ? x < 0 ? sprout::math::copysign(sprout::math::pi(), y) - : x > 0 ? FloatType(0) * y - : sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi(), y) - : FloatType(0) * y - : x == 0 - ? y < 0 ? -sprout::math::half_pi() - : sprout::math::half_pi() - : static_cast( - sprout::math::detail::atan2_impl( - static_cast::type>(y), - static_cast::type>(x) - ) - ) -#endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - atan2(ArithmeticType1 y, ArithmeticType2 x) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::atan2(static_cast(y), static_cast(x)); - } } // namespace detail // + // atan2 + // // issue: // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] // atan2(}0, -0) returns } . @@ -101,7 +63,60 @@ namespace sprout { // atan2(-NaN, -NaN) returns -NaN . // # returns +NaN . ( same as atan2(+NaN, +NaN) ) // - using sprout::math::detail::atan2; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + atan2(FloatType y, FloatType x) { + return sprout::math::isnan(y) + ? sprout::math::isnan(x) + ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() + : sprout::numeric_limits::quiet_NaN() + : y + : sprout::math::isnan(x) ? x + : x == -sprout::numeric_limits::infinity() + ? y == sprout::numeric_limits::infinity() ? sprout::math::three_quarters_pi() + : y == -sprout::numeric_limits::infinity() ? -sprout::math::three_quarters_pi() + : sprout::math::copysign(sprout::math::pi(), y) + : x == sprout::numeric_limits::infinity() + ? y == sprout::numeric_limits::infinity() ? sprout::math::quarter_pi() + : y == -sprout::numeric_limits::infinity() ? -sprout::math::quarter_pi() + : FloatType(0) * y + : y == sprout::numeric_limits::infinity() ? sprout::math::half_pi() + : y == -sprout::numeric_limits::infinity() ? -sprout::math::half_pi() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_atan2(y, x) +#else + : y == 0 + ? x < 0 ? sprout::math::copysign(sprout::math::pi(), y) + : x > 0 ? FloatType(0) * y + : sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi(), y) + : FloatType(0) * y + : x == 0 + ? y < 0 ? -sprout::math::half_pi() + : sprout::math::half_pi() + : static_cast( + sprout::math::detail::atan2_impl( + static_cast::type>(y), + static_cast::type>(x) + ) + ) +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + atan2(ArithmeticType1 y, ArithmeticType2 x) { + typedef typename sprout::float_promote::type type; + return sprout::math::atan2(static_cast(y), static_cast(x)); + } } // namespace math using sprout::math::atan2; diff --git a/sprout/math/atanh.hpp b/sprout/math/atanh.hpp index bae28cae..fba2f50d 100644 --- a/sprout/math/atanh.hpp +++ b/sprout/math/atanh.hpp @@ -21,41 +21,56 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_atanh(float x) { + return __builtin_atanhf(x); + } + inline SPROUT_CONSTEXPR double + builtin_atanh(double x) { + return __builtin_atanh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_atanh(long double x) { + return __builtin_atanhl(x); + } +#endif + template inline SPROUT_CONSTEXPR T atanh_impl(T x) { return sprout::math::log((1 + x) / (1 - x)) / 2; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - atanh(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 1 ? sprout::numeric_limits::infinity() - : x == -1 ? -sprout::numeric_limits::infinity() - : sprout::math::fabs(x) > 1 ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::atanh(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::atanh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - atanh(IntType x) { - return sprout::math::detail::atanh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::atanh; + // + // atanh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + atanh(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 1 ? sprout::numeric_limits::infinity() + : x == -1 ? -sprout::numeric_limits::infinity() + : sprout::math::fabs(x) > 1 ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_atanh(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::atanh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + atanh(IntType x) { + return sprout::math::atanh(static_cast(x)); + } } // namespace math using sprout::math::atanh; diff --git a/sprout/math/cbrt.hpp b/sprout/math/cbrt.hpp index 2f639f30..b8fd360c 100644 --- a/sprout/math/cbrt.hpp +++ b/sprout/math/cbrt.hpp @@ -21,6 +21,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_cbrt(float x) { + return __builtin_cbrtf(x); + } + inline SPROUT_CONSTEXPR double + builtin_cbrt(double x) { + return __builtin_cbrt(x); + } + inline SPROUT_CONSTEXPR long double + builtin_cbrt(long double x) { + return __builtin_cbrtl(x); + } +#endif + template inline SPROUT_CONSTEXPR T cbrt_impl(T x) { @@ -28,36 +43,36 @@ namespace sprout { : sprout::pow(x, sprout::math::third()) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - cbrt(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::cbrt(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::cbrt_impl(static_cast::type>(x))) -#endif - ; - } - - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - cbrt(IntType x) { - return sprout::math::detail::cbrt(static_cast(x)); - } } // namespace detail + // + // cbrt + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + cbrt(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_cbrt(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::cbrt_impl(static_cast::type>(x))) +#endif + ; + } - using sprout::math::detail::cbrt; + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + cbrt(IntType x) { + return sprout::math::cbrt(static_cast(x)); + } } // namespace math using sprout::math::cbrt; diff --git a/sprout/math/ceil.hpp b/sprout/math/ceil.hpp index a8384fbc..1a457d5e 100644 --- a/sprout/math/ceil.hpp +++ b/sprout/math/ceil.hpp @@ -22,6 +22,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_ceil(float x) { + return __builtin_ceilf(x); + } + inline SPROUT_CONSTEXPR double + builtin_ceil(double x) { + return __builtin_ceil(x); + } + inline SPROUT_CONSTEXPR long double + builtin_ceil(long double x) { + return __builtin_ceill(x); + } +#endif + template inline SPROUT_CONSTEXPR T ceil_impl_1(T x, T x0) { @@ -36,37 +51,37 @@ namespace sprout { : sprout::math::detail::ceil_impl_1(x, static_cast(static_cast(x))) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - ceil(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::ceil(x) -#else - : x == 0 ? x - : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x) - : static_cast(sprout::math::detail::ceil_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - ceil(IntType x) { - return sprout::math::detail::ceil(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::ceil; + // + // ceil + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + ceil(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_ceil(x) +#else + : x == 0 ? x + : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x) + : static_cast(sprout::math::detail::ceil_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + ceil(IntType x) { + return sprout::math::ceil(static_cast(x)); + } } // namespace math using sprout::math::ceil; diff --git a/sprout/math/copysign.hpp b/sprout/math/copysign.hpp index 497cf9d7..311b69bf 100644 --- a/sprout/math/copysign.hpp +++ b/sprout/math/copysign.hpp @@ -20,38 +20,24 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - copysign(FloatType x, FloatType y) { - return x == 0 - ? y == 0 ? y - : sprout::math::signbit(y) ? -FloatType(0) - : FloatType(0) - : sprout::math::isnan(x) - ? sprout::math::isnan(y) ? y - : sprout::math::signbit(y) ? -sprout::numeric_limits::quiet_NaN() - : sprout::numeric_limits::quiet_NaN() - : sprout::math::signbit(y) != sprout::math::signbit(x) ? -x - : x - ; +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_copysign(float x, float y) { + return __builtin_copysignf(x, y); } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - copysign(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::copysign(static_cast(x), static_cast(y)); + inline SPROUT_CONSTEXPR double + builtin_copysign(double x, double y) { + return __builtin_copysign(x, y); } + inline SPROUT_CONSTEXPR long double + builtin_copysign(long double x, long double y) { + return __builtin_copysignl(x, y); + } +#endif } // namespace detail // + // copysign + // // issue: // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] // copysign(}x, -0) returns -x for |x| is not 0 . @@ -59,7 +45,42 @@ namespace sprout { // copysign(}x, -NaN) returns -x for |x| is not NaN . // # returns +x . ( same as copysign(}x, +NaN) ) // - using NS_SPROUT_MATH_DETAIL::copysign; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + copysign(FloatType x, FloatType y) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_copysign(x, y) +#else + x == 0 + ? y == 0 ? y + : sprout::math::signbit(y) ? -FloatType(0) + : FloatType(0) + : sprout::math::isnan(x) + ? sprout::math::isnan(y) ? y + : sprout::math::signbit(y) ? -sprout::numeric_limits::quiet_NaN() + : sprout::numeric_limits::quiet_NaN() + : sprout::math::signbit(y) != sprout::math::signbit(x) ? -x + : x +#endif + ; + } + + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + copysign(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::copysign(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::copysign; diff --git a/sprout/math/cos.hpp b/sprout/math/cos.hpp index c27e58a7..5cf528dd 100644 --- a/sprout/math/cos.hpp +++ b/sprout/math/cos.hpp @@ -27,6 +27,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_cos(float x) { + return __builtin_cosf(x); + } + inline SPROUT_CONSTEXPR double + builtin_cos(double x) { + return __builtin_cos(x); + } + inline SPROUT_CONSTEXPR long double + builtin_cos(long double x) { + return __builtin_cosl(x); + } +#endif + template inline SPROUT_CONSTEXPR T cos_impl_1(T x2, std::size_t n, std::size_t last) { @@ -70,35 +85,35 @@ namespace sprout { // cos_impl(T x) { // return sprout::math::detail::cos_impl_1(sprout::math::fmod(sprout::math::fabs(x), sprout::math::two_pi())); // } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - cos(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::cos(x) -#else - : x == 0 ? FloatType(1) - : static_cast(sprout::math::detail::cos_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - cos(IntType x) { - return sprout::math::detail::cos(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::cos; + // + // cos + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + cos(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_cos(x) +#else + : x == 0 ? FloatType(1) + : static_cast(sprout::math::detail::cos_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + cos(IntType x) { + return sprout::math::cos(static_cast(x)); + } } // namespace math using sprout::math::cos; diff --git a/sprout/math/cosh.hpp b/sprout/math/cosh.hpp index f9f1516a..ef98e2ac 100644 --- a/sprout/math/cosh.hpp +++ b/sprout/math/cosh.hpp @@ -21,6 +21,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_cosh(float x) { + return __builtin_coshf(x); + } + inline SPROUT_CONSTEXPR double + builtin_cosh(double x) { + return __builtin_cosh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_cosh(long double x) { + return __builtin_coshl(x); + } +#endif + template inline SPROUT_CONSTEXPR T cosh_impl_1(T t) { @@ -31,35 +46,35 @@ namespace sprout { cosh_impl(T x) { return sprout::math::detail::cosh_impl_1(sprout::math::exp(x)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - cosh(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::cosh(x) -#else - : x == 0 ? FloatType(1) - : static_cast(sprout::math::detail::cosh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - cosh(IntType x) { - return sprout::math::detail::cosh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::cosh; + // + // cosh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + cosh(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_cosh(x) +#else + : x == 0 ? FloatType(1) + : static_cast(sprout::math::detail::cosh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + cosh(IntType x) { + return sprout::math::cosh(static_cast(x)); + } } // namespace math using sprout::math::cosh; diff --git a/sprout/math/detail/config.hpp b/sprout/math/detail/config.hpp index d15f0f2c..46f5bb19 100644 --- a/sprout/math/detail/config.hpp +++ b/sprout/math/detail/config.hpp @@ -14,12 +14,6 @@ # include #endif -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION -# define NS_SPROUT_MATH_DETAIL std -#else // #ifndef SPROUT_USE_BUILTIN_CMATH_FUNCTION -# define NS_SPROUT_MATH_DETAIL sprout::math::detail -#endif // #ifndef SPROUT_USE_BUILTIN_CMATH_FUNCTION - #if (FLT_RADIX == 2) # define SPROUT_FLT_RADIX_IS_2 1 #else diff --git a/sprout/math/erf.hpp b/sprout/math/erf.hpp index 7620a66a..2d3a08e2 100644 --- a/sprout/math/erf.hpp +++ b/sprout/math/erf.hpp @@ -22,6 +22,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_erf(float x) { + return __builtin_erff(x); + } + inline SPROUT_CONSTEXPR double + builtin_erf(double x) { + return __builtin_erf(x); + } + inline SPROUT_CONSTEXPR long double + builtin_erf(long double x) { + return __builtin_erfl(x); + } +#endif + template inline SPROUT_CONSTEXPR T erf_impl_3(T x, T y) { @@ -125,35 +140,35 @@ namespace sprout { erf_impl(T x) { return sprout::math::detail::erf_impl_1(x, x < 0 ? -x : x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - erf(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? FloatType(1) - : x == -sprout::numeric_limits::infinity() ? FloatType(-1) -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::erf(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::erf_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - erf(IntType x) { - return sprout::math::detail::erf(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::erf; + // + // erf + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + erf(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? FloatType(1) + : x == -sprout::numeric_limits::infinity() ? FloatType(-1) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_erf(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::erf_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + erf(IntType x) { + return sprout::math::erf(static_cast(x)); + } } // namespace math using sprout::math::erf; diff --git a/sprout/math/erfc.hpp b/sprout/math/erfc.hpp index f09165e9..44cdd3a9 100644 --- a/sprout/math/erfc.hpp +++ b/sprout/math/erfc.hpp @@ -19,39 +19,54 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_erfc(float x) { + return __builtin_erfcf(x); + } + inline SPROUT_CONSTEXPR double + builtin_erfc(double x) { + return __builtin_erfc(x); + } + inline SPROUT_CONSTEXPR long double + builtin_erfc(long double x) { + return __builtin_erfcl(x); + } +#endif + template inline SPROUT_CONSTEXPR T erfc_impl(T x) { return T(1) - sprout::math::erf(x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - erfc(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? FloatType(0) - : x == -sprout::numeric_limits::infinity() ? FloatType(2) -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::erfc(x) -#else - : static_cast(sprout::math::detail::erfc_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - erfc(IntType x) { - return sprout::math::detail::erfc(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::erfc; + // + // erfc + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + erfc(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? FloatType(0) + : x == -sprout::numeric_limits::infinity() ? FloatType(2) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_erfc(x) +#else + : static_cast(sprout::math::detail::erfc_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + erfc(IntType x) { + return sprout::math::erfc(static_cast(x)); + } } // namespace math using sprout::math::erfc; diff --git a/sprout/math/exp.hpp b/sprout/math/exp.hpp index 8d8d6286..0546734d 100644 --- a/sprout/math/exp.hpp +++ b/sprout/math/exp.hpp @@ -22,6 +22,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_exp(float x) { + return __builtin_expf(x); + } + inline SPROUT_CONSTEXPR double + builtin_exp(double x) { + return __builtin_exp(x); + } + inline SPROUT_CONSTEXPR long double + builtin_exp(long double x) { + return __builtin_expl(x); + } +#endif + template inline SPROUT_CONSTEXPR T exp_impl_1(T x, std::size_t n, std::size_t last) { @@ -38,35 +53,35 @@ namespace sprout { : T(1) + sprout::math::detail::exp_impl_1(x, 1, sprout::math::factorial_limit() / 2 + 1) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - exp(FloatType x) { - return sprout::math::isnan(x) ? x - : x == -sprout::numeric_limits::infinity() ? FloatType(0) - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::exp(x) -#else - : x == 0 ? FloatType(1) - : static_cast(sprout::math::detail::exp_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - exp(IntType x) { - return sprout::math::detail::exp(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::exp; + // + // exp + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + exp(FloatType x) { + return sprout::math::isnan(x) ? x + : x == -sprout::numeric_limits::infinity() ? FloatType(0) + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_exp(x) +#else + : x == 0 ? FloatType(1) + : static_cast(sprout::math::detail::exp_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + exp(IntType x) { + return sprout::math::exp(static_cast(x)); + } } // namespace math using sprout::math::exp; diff --git a/sprout/math/exp10.hpp b/sprout/math/exp10.hpp index 93a1ab59..805567df 100644 --- a/sprout/math/exp10.hpp +++ b/sprout/math/exp10.hpp @@ -26,31 +26,31 @@ namespace sprout { exp10_impl(T x) { return sprout::math::exp(x * sprout::math::ln_ten()); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - exp10(FloatType x) { - return sprout::math::isnan(x) ? x - : x == -sprout::numeric_limits::infinity() ? FloatType(0) - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == 0 ? FloatType(1) - : static_cast(sprout::math::detail::exp10_impl(static_cast::type>(x))) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - exp10(IntType x) { - return sprout::math::detail::exp10(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::exp10; + // + // exp10 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + exp10(FloatType x) { + return sprout::math::isnan(x) ? x + : x == -sprout::numeric_limits::infinity() ? FloatType(0) + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == 0 ? FloatType(1) + : static_cast(sprout::math::detail::exp10_impl(static_cast::type>(x))) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + exp10(IntType x) { + return sprout::math::exp10(static_cast(x)); + } } // namespace math using sprout::math::exp10; diff --git a/sprout/math/exp2.hpp b/sprout/math/exp2.hpp index c02196d8..008b0aaf 100644 --- a/sprout/math/exp2.hpp +++ b/sprout/math/exp2.hpp @@ -21,40 +21,56 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_exp2(float x) { + return __builtin_exp2f(x); + } + inline SPROUT_CONSTEXPR double + builtin_exp2(double x) { + return __builtin_exp2(x); + } + inline SPROUT_CONSTEXPR long double + builtin_exp2(long double x) { + return __builtin_exp2l(x); + } +#endif + template inline SPROUT_CONSTEXPR T exp2_impl(T x) { return sprout::math::exp(x * sprout::math::ln_two()); } - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - exp2(FloatType x) { - return sprout::math::isnan(x) ? x - : x == -sprout::numeric_limits::infinity() ? FloatType(0) - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::exp2(x) -#else - : x == 0 ? FloatType(1) - : static_cast(sprout::math::detail::exp2_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - exp2(IntType x) { - return sprout::math::detail::exp2(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::exp2; + // + // exp2 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + exp2(FloatType x) { + return sprout::math::isnan(x) ? x + : x == -sprout::numeric_limits::infinity() ? FloatType(0) + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_exp2(x) +#else + : x == 0 ? FloatType(1) + : static_cast(sprout::math::detail::exp2_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + exp2(IntType x) { + return sprout::math::exp2(static_cast(x)); + } } // namespace math using sprout::math::exp2; diff --git a/sprout/math/expm1.hpp b/sprout/math/expm1.hpp index 86446a12..a610e62a 100644 --- a/sprout/math/expm1.hpp +++ b/sprout/math/expm1.hpp @@ -22,40 +22,55 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_expm1(float x) { + return __builtin_expm1f(x); + } + inline SPROUT_CONSTEXPR double + builtin_expm1(double x) { + return __builtin_expm1(x); + } + inline SPROUT_CONSTEXPR long double + builtin_expm1(long double x) { + return __builtin_expm1l(x); + } +#endif + template inline SPROUT_CONSTEXPR T expm1_impl(T x) { return sprout::math::exp(x) - T(1); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - expm1(FloatType x) { - return sprout::math::isnan(x) ? x - : x == -sprout::numeric_limits::infinity() ? FloatType(-1) - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::expm1(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::expm1_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - expm1(IntType x) { - return sprout::math::detail::expm1(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::expm1; + // + // expm1 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + expm1(FloatType x) { + return sprout::math::isnan(x) ? x + : x == -sprout::numeric_limits::infinity() ? FloatType(-1) + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_expm1(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::expm1_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + expm1(IntType x) { + return sprout::math::expm1(static_cast(x)); + } } // namespace math using sprout::math::expm1; diff --git a/sprout/math/fabs.hpp b/sprout/math/fabs.hpp index c7da5eee..de6d42e2 100644 --- a/sprout/math/fabs.hpp +++ b/sprout/math/fabs.hpp @@ -18,28 +18,48 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fabs(FloatType x) { - return sprout::math::isnan(x) ? sprout::numeric_limits::quiet_NaN() - : x == 0 ? FloatType(0) - : sprout::math::copysign(x, FloatType(0)) - ; +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_fabs(float x) { + return __builtin_fabsf(x); } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > inline SPROUT_CONSTEXPR double - fabs(IntType x) { - return sprout::math::detail::fabs(static_cast(x)); + builtin_fabs(double x) { + return __builtin_fabs(x); } + inline SPROUT_CONSTEXPR long double + builtin_fabs(long double x) { + return __builtin_fabsl(x); + } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::fabs; + // + // fabs + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fabs(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_fabs(x) +#else + sprout::math::isnan(x) ? sprout::numeric_limits::quiet_NaN() + : x == 0 ? FloatType(0) + : sprout::math::copysign(x, FloatType(0)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + fabs(IntType x) { + return sprout::math::fabs(static_cast(x)); + } } // namespace math using sprout::math::fabs; diff --git a/sprout/math/fdim.hpp b/sprout/math/fdim.hpp index 018a8607..babd7c5e 100644 --- a/sprout/math/fdim.hpp +++ b/sprout/math/fdim.hpp @@ -19,40 +19,55 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fdim(FloatType x, FloatType y) { - return sprout::math::isnan(y) ? y - : sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? FloatType(0) - : y == sprout::numeric_limits::infinity() ? FloatType(0) - : y == -sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::fdim(x, y) -#else - : x > y ? x - y : FloatType(0) + inline SPROUT_CONSTEXPR float + builtin_fdim(float x, float y) { + return __builtin_fdimf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_fdim(double x, double y) { + return __builtin_fdim(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_fdim(long double x, long double y) { + return __builtin_fdiml(x, y); + } #endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - fdim(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::fdim(static_cast(x), static_cast(y)); - } } // namespace detail - - using sprout::math::detail::fdim; + // + // fdim + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fdim(FloatType x, FloatType y) { + return sprout::math::isnan(y) ? y + : sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? FloatType(0) + : y == sprout::numeric_limits::infinity() ? FloatType(0) + : y == -sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_fdim(x, y) +#else + : x > y ? x - y : FloatType(0) +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + fdim(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::fdim(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::fdim; diff --git a/sprout/math/float2_exponent.hpp b/sprout/math/float2_exponent.hpp index a21d88ce..46b8d035 100644 --- a/sprout/math/float2_exponent.hpp +++ b/sprout/math/float2_exponent.hpp @@ -18,30 +18,29 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - float2_exponent(FloatType x) { - return sprout::math::isnan(x) ? 0 - : x == 0 ? 0 - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? 0 - : sprout::math::ilogb2(x) + 1 - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - float2_exponent(IntType x) { - return sprout::math::detail::float2_exponent(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::float2_exponent; + // + // float2_exponent + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + float2_exponent(FloatType x) { + return sprout::math::isnan(x) ? 0 + : x == 0 ? 0 + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? 0 + : sprout::math::ilogb2(x) + 1 + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + float2_exponent(IntType x) { + return sprout::math::float2_exponent(static_cast(x)); + } } // namespace math using sprout::math::float2_exponent; diff --git a/sprout/math/float2_sig_exp.hpp b/sprout/math/float2_sig_exp.hpp index 4529fd01..5628f791 100644 --- a/sprout/math/float2_sig_exp.hpp +++ b/sprout/math/float2_sig_exp.hpp @@ -27,32 +27,32 @@ namespace sprout { typedef sprout::pair type; return type(x / sprout::detail::pow_n(T(2), exp), exp); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - float2_sig_exp(FloatType x) { - typedef sprout::pair type; - return sprout::math::isnan(x) ? type(x, 0) - : x == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), 0) - : x == -sprout::numeric_limits::infinity() ? type(-sprout::numeric_limits::infinity(), 0) - : x == 0 ? type(x, 0) - : sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - float2_sig_exp(IntType x) { - return sprout::math::detail::float2_sig_exp(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::float2_sig_exp; + // + // float2_sig_exp + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + float2_sig_exp(FloatType x) { + typedef sprout::pair type; + return sprout::math::isnan(x) ? type(x, 0) + : x == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), 0) + : x == -sprout::numeric_limits::infinity() ? type(-sprout::numeric_limits::infinity(), 0) + : x == 0 ? type(x, 0) + : sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + float2_sig_exp(IntType x) { + return sprout::math::float2_sig_exp(static_cast(x)); + } } // namespace math using sprout::math::float2_sig_exp; diff --git a/sprout/math/float2_significand.hpp b/sprout/math/float2_significand.hpp index 462d99f4..38ac9250 100644 --- a/sprout/math/float2_significand.hpp +++ b/sprout/math/float2_significand.hpp @@ -19,31 +19,30 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - float2_significand(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : x == 0 ? x - : x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - float2_significand(IntType x) { - return sprout::math::detail::float_significand(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::float2_significand; + // + // float2_significand + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + float2_significand(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : x == 0 ? x + : x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x)) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + float2_significand(IntType x) { + return sprout::math::float_significand(static_cast(x)); + } } // namespace math using sprout::math::float2_significand; diff --git a/sprout/math/float_exponent.hpp b/sprout/math/float_exponent.hpp index b36cbf2c..0c8392ea 100644 --- a/sprout/math/float_exponent.hpp +++ b/sprout/math/float_exponent.hpp @@ -18,30 +18,29 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - float_exponent(FloatType x) { - return sprout::math::isnan(x) ? 0 - : x == 0 ? 0 - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? 0 - : sprout::math::ilogb(x) + 1 - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - float_exponent(IntType x) { - return sprout::math::detail::float_exponent(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::float_exponent; + // + // float_exponent + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + float_exponent(FloatType x) { + return sprout::math::isnan(x) ? 0 + : x == 0 ? 0 + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? 0 + : sprout::math::ilogb(x) + 1 + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + float_exponent(IntType x) { + return sprout::math::float_exponent(static_cast(x)); + } } // namespace math using sprout::math::float_exponent; diff --git a/sprout/math/float_sig_exp.hpp b/sprout/math/float_sig_exp.hpp index 20be698c..833a12ff 100644 --- a/sprout/math/float_sig_exp.hpp +++ b/sprout/math/float_sig_exp.hpp @@ -27,32 +27,32 @@ namespace sprout { typedef sprout::pair type; return type(x / sprout::detail::pow_n(T(sprout::numeric_limits::radix), exp), exp); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - float_sig_exp(FloatType x) { - typedef sprout::pair type; - return sprout::math::isnan(x) ? type(x, 0) - : x == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), 0) - : x == -sprout::numeric_limits::infinity() ? type(-sprout::numeric_limits::infinity(), 0) - : x == 0 ? type(x, 0) - : sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - float_sig_exp(IntType x) { - return sprout::math::detail::float_sig_exp(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::float_sig_exp; + // + // float_sig_exp + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + float_sig_exp(FloatType x) { + typedef sprout::pair type; + return sprout::math::isnan(x) ? type(x, 0) + : x == sprout::numeric_limits::infinity() ? type(sprout::numeric_limits::infinity(), 0) + : x == -sprout::numeric_limits::infinity() ? type(-sprout::numeric_limits::infinity(), 0) + : x == 0 ? type(x, 0) + : sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + float_sig_exp(IntType x) { + return sprout::math::float_sig_exp(static_cast(x)); + } } // namespace math using sprout::math::float_sig_exp; diff --git a/sprout/math/float_significand.hpp b/sprout/math/float_significand.hpp index 677d8c00..61dfda06 100644 --- a/sprout/math/float_significand.hpp +++ b/sprout/math/float_significand.hpp @@ -19,31 +19,30 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - float_significand(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : x == 0 ? x - : x / sprout::detail::pow_n(FloatType(sprout::numeric_limits::radix), sprout::float_exponent(x)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - float_significand(IntType x) { - return sprout::math::detail::float_significand(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::float_significand; + // + // float_significand + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + float_significand(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : x == 0 ? x + : x / sprout::detail::pow_n(FloatType(sprout::numeric_limits::radix), sprout::float_exponent(x)) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + float_significand(IntType x) { + return sprout::math::float_significand(static_cast(x)); + } } // namespace math using sprout::math::float_significand; diff --git a/sprout/math/floor.hpp b/sprout/math/floor.hpp index fe6969cc..47738ad5 100644 --- a/sprout/math/floor.hpp +++ b/sprout/math/floor.hpp @@ -22,6 +22,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_floor(float x) { + return __builtin_floorf(x); + } + inline SPROUT_CONSTEXPR double + builtin_floor(double x) { + return __builtin_floor(x); + } + inline SPROUT_CONSTEXPR long double + builtin_floor(long double x) { + return __builtin_floorl(x); + } +#endif + template inline SPROUT_CONSTEXPR T floor_impl_1(T x, T x0) { @@ -36,37 +51,37 @@ namespace sprout { : static_cast(static_cast(x)) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - floor(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::floor(x) -#else - : x == 0 ? x - : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x) - : static_cast(sprout::math::detail::floor_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - floor(IntType x) { - return sprout::math::detail::floor(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::floor; + // + // floor + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + floor(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_floor(x) +#else + : x == 0 ? x + : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x) + : static_cast(sprout::math::detail::floor_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + floor(IntType x) { + return sprout::math::floor(static_cast(x)); + } } // namespace math using sprout::math::floor; diff --git a/sprout/math/fma.hpp b/sprout/math/fma.hpp index d693aa90..39da79dc 100644 --- a/sprout/math/fma.hpp +++ b/sprout/math/fma.hpp @@ -21,48 +21,63 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fma(FloatType x, FloatType y, FloatType z) { - return sprout::math::isnan(x) ? x - : sprout::math::isnan(y) ? y - : sprout::math::isnan(z) ? z - : sprout::math::isinf(x) && y == 0 ? sprout::numeric_limits::quiet_NaN() - : sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits::quiet_NaN() - : (sprout::math::isinf(x) || sprout::math::isinf(y)) && sprout::math::isinf(z) && (sprout::math::signbit(x) ^ sprout::math::signbit(y) ^ sprout::math::signbit(z)) - ? sprout::numeric_limits::quiet_NaN() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::fma(x, y, z) -#else - : x * y + z + inline SPROUT_CONSTEXPR float + builtin_fma(float x, float y, float z) { + return __builtin_fmaf(x, y, z); + } + inline SPROUT_CONSTEXPR double + builtin_fma(double x, double y, double z) { + return __builtin_fma(x, y, z); + } + inline SPROUT_CONSTEXPR long double + builtin_fma(long double x, long double y, long double z) { + return __builtin_fmal(x, y, z); + } #endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename ArithmeticType3, - typename sprout::enabler_if< - std::is_arithmetic::value - && std::is_arithmetic::value - && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote< - ArithmeticType1, ArithmeticType2, ArithmeticType3 - >::type - fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) { - typedef typename sprout::float_promote< - ArithmeticType1, ArithmeticType2, ArithmeticType3 - >::type type; - return sprout::math::detail::fma(static_cast(x), static_cast(y), static_cast(z)); - } } // namespace detail - - using sprout::math::detail::fma; + // + // fma + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fma(FloatType x, FloatType y, FloatType z) { + return sprout::math::isnan(x) ? x + : sprout::math::isnan(y) ? y + : sprout::math::isnan(z) ? z + : sprout::math::isinf(x) && y == 0 ? sprout::numeric_limits::quiet_NaN() + : sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits::quiet_NaN() + : (sprout::math::isinf(x) || sprout::math::isinf(y)) && sprout::math::isinf(z) && (sprout::math::signbit(x) ^ sprout::math::signbit(y) ^ sprout::math::signbit(z)) + ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_fma(x, y, z) +#else + : x * y + z +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename ArithmeticType3, + typename sprout::enabler_if< + std::is_arithmetic::value + && std::is_arithmetic::value + && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote< + ArithmeticType1, ArithmeticType2, ArithmeticType3 + >::type + fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) { + typedef typename sprout::float_promote< + ArithmeticType1, ArithmeticType2, ArithmeticType3 + >::type type; + return sprout::math::fma(static_cast(x), static_cast(y), static_cast(z)); + } } // namespace math using sprout::math::fma; diff --git a/sprout/math/fmax.hpp b/sprout/math/fmax.hpp index bfe68780..b6dc5831 100644 --- a/sprout/math/fmax.hpp +++ b/sprout/math/fmax.hpp @@ -19,41 +19,56 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fmax(FloatType x, FloatType y) { - return sprout::math::isnan(y) ? x - : sprout::math::isnan(x) ? y - : y == -sprout::numeric_limits::infinity() ? x - : x == sprout::numeric_limits::infinity() ? x - : x == -sprout::numeric_limits::infinity() ? y - : y == sprout::numeric_limits::infinity() ? y #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : x == 0 && y == 0 ? x - : std::fmax(x, y) -#else - : x < y ? y : x + inline SPROUT_CONSTEXPR float + builtin_fmax(float x, float y) { + return __builtin_fmaxf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_fmax(double x, double y) { + return __builtin_fmax(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_fmax(long double x, long double y) { + return __builtin_fmaxl(x, y); + } #endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - fmax(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::fmax(static_cast(x), static_cast(y)); - } } // namespace detail - - using sprout::math::detail::fmax; + // + // fmax + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fmax(FloatType x, FloatType y) { + return sprout::math::isnan(y) ? x + : sprout::math::isnan(x) ? y + : y == -sprout::numeric_limits::infinity() ? x + : x == sprout::numeric_limits::infinity() ? x + : x == -sprout::numeric_limits::infinity() ? y + : y == sprout::numeric_limits::infinity() ? y +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : x == 0 && y == 0 ? x + : sprout::math::detail::builtin_fmax(x, y) +#else + : x < y ? y : x +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + fmax(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::fmax(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::fmax; diff --git a/sprout/math/fmin.hpp b/sprout/math/fmin.hpp index 1c529505..7eeb6bf9 100644 --- a/sprout/math/fmin.hpp +++ b/sprout/math/fmin.hpp @@ -19,41 +19,56 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fmin(FloatType x, FloatType y) { - return sprout::math::isnan(y) ? x - : sprout::math::isnan(x) ? y - : x == -sprout::numeric_limits::infinity() ? x - : y == sprout::numeric_limits::infinity() ? x - : y == -sprout::numeric_limits::infinity() ? y - : x == sprout::numeric_limits::infinity() ? y #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : x == 0 && y == 0 ? x - : std::fmin(x, y) -#else - : y < x ? y : x + inline SPROUT_CONSTEXPR float + builtin_fmin(float x, float y) { + return __builtin_fminf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_fmin(double x, double y) { + return __builtin_fmin(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_fmin(long double x, long double y) { + return __builtin_fminl(x, y); + } #endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - fmin(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::fmin(static_cast(x), static_cast(y)); - } } // namespace detail - - using sprout::math::detail::fmin; + // + // fmin + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fmin(FloatType x, FloatType y) { + return sprout::math::isnan(y) ? x + : sprout::math::isnan(x) ? y + : x == -sprout::numeric_limits::infinity() ? x + : y == sprout::numeric_limits::infinity() ? x + : y == -sprout::numeric_limits::infinity() ? y + : x == sprout::numeric_limits::infinity() ? y +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : x == 0 && y == 0 ? x + : sprout::math::detail::builtin_fmin(x, y) +#else + : y < x ? y : x +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + fmin(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::fmin(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::fmin; diff --git a/sprout/math/fmod.hpp b/sprout/math/fmod.hpp index 5c4b2b1b..bb406fc6 100644 --- a/sprout/math/fmod.hpp +++ b/sprout/math/fmod.hpp @@ -71,49 +71,49 @@ namespace sprout { fmod_impl(T x, T y) { return sprout::math::detail::fmod_impl_1(x, sprout::math::fabs(y), sprout::math::fabs(x)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fmod(FloatType x, FloatType y) { - return sprout::math::isnan(y) - ? sprout::math::isnan(x) - ? sprout::math::signbit(y) || sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() - : sprout::numeric_limits::quiet_NaN() - : y - : sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() || y == 0 - ? -sprout::numeric_limits::quiet_NaN() - : x == 0 ? x - : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? x - : static_cast(sprout::math::detail::fmod_impl( - static_cast::type>(x), - static_cast::type>(y) - )) - ; - } - - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - fmod(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::fmod(static_cast(x), static_cast(y)); - } } // namespace detail // + // fmod + // // issue: // fmod(-NaN, -NaN) returns -NaN . // # returns +NaN . ( same as fmod(+NaN, +NaN) ) // - using sprout::math::detail::fmod; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fmod(FloatType x, FloatType y) { + return sprout::math::isnan(y) + ? sprout::math::isnan(x) + ? sprout::math::signbit(y) || sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() + : sprout::numeric_limits::quiet_NaN() + : y + : sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() || y == 0 + ? -sprout::numeric_limits::quiet_NaN() + : x == 0 ? x + : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? x + : static_cast(sprout::math::detail::fmod_impl( + static_cast::type>(x), + static_cast::type>(y) + )) + ; + } + + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + fmod(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::fmod(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::fmod; diff --git a/sprout/math/fpclassify.hpp b/sprout/math/fpclassify.hpp index 9303ca82..537a0a79 100644 --- a/sprout/math/fpclassify.hpp +++ b/sprout/math/fpclassify.hpp @@ -21,22 +21,45 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR int - fpclassify(FloatType x) { - return sprout::math::isnan(x) ? FP_NAN - : sprout::math::isinf(x) ? FP_INFINITE - : sprout::math::iszero(x) ? FP_ZERO - : sprout::math::detail::issubnormal_or_zero(x) ? FP_SUBNORMAL - : FP_NORMAL - ; + builtin_fpclassify(FloatType x) { + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x); } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::fpclassify; + // + // fpclassify + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + fpclassify(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_fpclassify(x) +#else + sprout::math::isnan(x) ? FP_NAN + : sprout::math::isinf(x) ? FP_INFINITE + : sprout::math::iszero(x) ? FP_ZERO + : sprout::math::detail::issubnormal_or_zero(x) ? FP_SUBNORMAL + : FP_NORMAL +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + fpclassify(IntType x) { + return x ? FP_NORMAL + : FP_ZERO + ; + } } // namespace math using sprout::math::fpclassify; diff --git a/sprout/math/frac_int.hpp b/sprout/math/frac_int.hpp index 8f6e71ce..09fe90ca 100644 --- a/sprout/math/frac_int.hpp +++ b/sprout/math/frac_int.hpp @@ -32,26 +32,26 @@ namespace sprout { : type(sprout::math::copysign(x - ipart, x), ipart) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - frac_int(FloatType x) { - return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x)); - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - frac_int(IntType x) { - return sprout::math::detail::frac_int(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::frac_int; + // + // frac_int + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + frac_int(FloatType x) { + return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x)); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + frac_int(IntType x) { + return sprout::math::frac_int(static_cast(x)); + } } // namespace math using sprout::math::frac_int; diff --git a/sprout/math/fractional_part.hpp b/sprout/math/fractional_part.hpp index e8e7e898..4f4382fb 100644 --- a/sprout/math/fractional_part.hpp +++ b/sprout/math/fractional_part.hpp @@ -27,30 +27,30 @@ namespace sprout { : sprout::math::copysign(x - ipart, x) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - fractional_part(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? sprout::math::copysign(FloatType(0), x) - : x == 0 ? x - : sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - fractional_part(IntType x) { - return sprout::math::detail::fractional_part(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::fractional_part; + // + // fractional_part + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + fractional_part(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() ? sprout::math::copysign(FloatType(0), x) + : x == 0 ? x + : sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x)) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + fractional_part(IntType x) { + return sprout::math::fractional_part(static_cast(x)); + } } // namespace math using sprout::math::fractional_part; diff --git a/sprout/math/hypot.hpp b/sprout/math/hypot.hpp index a1aa7c9e..93e0d064 100644 --- a/sprout/math/hypot.hpp +++ b/sprout/math/hypot.hpp @@ -23,6 +23,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_hypot(float x, float y) { + return __builtin_hypotf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_hypot(double x, double y) { + return __builtin_hypot(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_hypot(long double x, long double y) { + return __builtin_hypotl(x, y); + } +#endif + template inline SPROUT_CONSTEXPR T hypot_impl_2(T t, T w) { @@ -41,47 +56,47 @@ namespace sprout { hypot_impl(T x, T y) { return sprout::math::detail::hypot_impl_1(sprout::math::fabs(x), sprout::math::fabs(y)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - hypot(FloatType x, FloatType y) { - return y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() - : sprout::math::isnan(y) ? y - : sprout::math::isnan(x) ? x -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::hypot(x, y) -#else - : y == 0 ? sprout::math::fabs(x) - : x == 0 ? sprout::math::fabs(y) - : static_cast(sprout::math::detail::hypot_impl( - static_cast::type>(x), - static_cast::type>(y) - )) -#endif - ; - } - - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - hypot(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::hypot(static_cast(x), static_cast(y)); - } } // namespace detail + // + // hypot + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + hypot(FloatType x, FloatType y) { + return y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() + : sprout::math::isnan(y) ? y + : sprout::math::isnan(x) ? x +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_hypot(x, y) +#else + : y == 0 ? sprout::math::fabs(x) + : x == 0 ? sprout::math::fabs(y) + : static_cast(sprout::math::detail::hypot_impl( + static_cast::type>(x), + static_cast::type>(y) + )) +#endif + ; + } - using sprout::math::detail::hypot; + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + hypot(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::hypot(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::hypot; diff --git a/sprout/math/iceil.hpp b/sprout/math/iceil.hpp index 2e0bc73a..e0c96d5f 100644 --- a/sprout/math/iceil.hpp +++ b/sprout/math/iceil.hpp @@ -24,8 +24,8 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_USE_BUILTIN_CMATH_FUNCTION + namespace detail { template inline SPROUT_CONSTEXPR To iceil_impl(FloatType x) { @@ -34,18 +34,23 @@ namespace sprout { : static_cast(x) ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iceil(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : sprout::math::detail::iceil_impl(sprout::math::ceil(x)) - ; - } + } // namespace detail + // + // iceil + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iceil(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : sprout::math::detail::iceil_impl(sprout::math::ceil(x)) + ; + } #else + namespace detail { template inline SPROUT_CONSTEXPR To iceil_impl(FloatType x, To x0) { @@ -53,33 +58,34 @@ namespace sprout { : x0 + 1 ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iceil(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : x == 0 ? To(0) - : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast(x)) - : sprout::math::detail::iceil_impl(x, static_cast(x)) - ; - } -#endif - template< - typename To = int, - typename IntType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iceil(IntType x) { - return sprout::math::detail::iceil(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::iceil; + // + // iceil + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iceil(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : x == 0 ? To(0) + : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast(x)) + : sprout::math::detail::iceil_impl(x, static_cast(x)) + ; + } +#endif + template< + typename To = int, + typename IntType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iceil(IntType x) { + return sprout::math::iceil(static_cast(x)); + } } // namespace math using sprout::math::iceil; diff --git a/sprout/math/ifloor.hpp b/sprout/math/ifloor.hpp index d994d19b..71d93bd9 100644 --- a/sprout/math/ifloor.hpp +++ b/sprout/math/ifloor.hpp @@ -24,8 +24,8 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_USE_BUILTIN_CMATH_FUNCTION + namespace detail { template inline SPROUT_CONSTEXPR To ifloor_impl(FloatType x) { @@ -34,18 +34,23 @@ namespace sprout { : static_cast(x) ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - ifloor(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : sprout::math::detail::ifloor_impl(sprout::math::floor(x)) - ; - } + } // namespace detail + // + // ifloor + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + ifloor(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : sprout::math::detail::ifloor_impl(sprout::math::floor(x)) + ; + } #else + namespace detail { template inline SPROUT_CONSTEXPR To ifloor_impl(FloatType x, To x0) { @@ -53,33 +58,34 @@ namespace sprout { : x0 - 1 ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - ifloor(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : x == 0 ? To(0) - : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast(x)) - : sprout::math::detail::ifloor_impl(x, static_cast(x)) - ; - } -#endif - template< - typename To = int, - typename IntType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - ifloor(IntType x) { - return sprout::math::detail::ifloor(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::ifloor; + // + // ifloor + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + ifloor(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : x == 0 ? To(0) + : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast(x)) + : sprout::math::detail::ifloor_impl(x, static_cast(x)) + ; + } +#endif + template< + typename To = int, + typename IntType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + ifloor(IntType x) { + return sprout::math::ifloor(static_cast(x)); + } } // namespace math using sprout::math::ifloor; diff --git a/sprout/math/ilogb.hpp b/sprout/math/ilogb.hpp index 7073f49b..6d47fa00 100644 --- a/sprout/math/ilogb.hpp +++ b/sprout/math/ilogb.hpp @@ -22,33 +22,48 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - ilogb(FloatType x) { - return sprout::math::iszero(x) ? FP_ILOGB0 - : sprout::math::isinf(x) ? INT_MAX - : sprout::math::isnan(x) ? FP_ILOGBNAN #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::ilogb(x) -#else - : static_cast(sprout::math::logb(x)) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > inline SPROUT_CONSTEXPR int - ilogb(IntType x) { - return sprout::math::detail::ilogb(static_cast(x)); + builtin_ilogb(float x) { + return __builtin_ilogbf(x); } + inline SPROUT_CONSTEXPR int + builtin_ilogb(double x) { + return __builtin_ilogb(x); + } + inline SPROUT_CONSTEXPR int + builtin_ilogb(long double x) { + return __builtin_ilogbl(x); + } +#endif } // namespace detail - - using sprout::math::detail::ilogb; + // + // ilogb + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb(FloatType x) { + return sprout::math::iszero(x) ? FP_ILOGB0 + : sprout::math::isinf(x) ? INT_MAX + : sprout::math::isnan(x) ? FP_ILOGBNAN +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_ilogb(x) +#else + : static_cast(sprout::math::logb(x)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb(IntType x) { + return sprout::math::ilogb(static_cast(x)); + } } // namespace math using sprout::math::ilogb; diff --git a/sprout/math/ilogb2.hpp b/sprout/math/ilogb2.hpp index 8132d25e..b7c591ec 100644 --- a/sprout/math/ilogb2.hpp +++ b/sprout/math/ilogb2.hpp @@ -25,49 +25,45 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_FLT_RADIX_IS_2 - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - ilogb2(FloatType x) { - return sprout::math::ilogb(x); - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - ilogb2(IntType x) { - return sprout::math::ilogb(x); - } + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb2(FloatType x) { + return sprout::math::ilogb(x); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb2(IntType x) { + return sprout::math::ilogb(x); + } #else - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - ilogb2(FloatType x) { - return sprout::math::iszero(x) ? FP_ILOGB0 - : sprout::math::isinf(x) ? INT_MAX - : sprout::math::isnan(x) ? FP_ILOGBNAN - : static_cast(sprout::math::logb2(x)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR int - ilogb2(IntType x) { - return sprout::math::detail::ilogb2(static_cast(x)); - } + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb2(FloatType x) { + return sprout::math::iszero(x) ? FP_ILOGB0 + : sprout::math::isinf(x) ? INT_MAX + : sprout::math::isnan(x) ? FP_ILOGBNAN + : static_cast(sprout::math::logb2(x)) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR int + ilogb2(IntType x) { + return sprout::math::ilogb2(static_cast(x)); + } #endif - } // namespace detail - - using sprout::math::detail::ilogb2; } // namespace math using sprout::math::ilogb2; diff --git a/sprout/math/integer_part.hpp b/sprout/math/integer_part.hpp index 36c69784..f5a0c583 100644 --- a/sprout/math/integer_part.hpp +++ b/sprout/math/integer_part.hpp @@ -18,31 +18,30 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - integer_part(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : x == 0 ? x - : sprout::math::trunc(x) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - integer_part(IntType x) { - return sprout::math::detail::integer_part(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::integer_part; + // + // integer_part + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + integer_part(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : x == 0 ? x + : sprout::math::trunc(x) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + integer_part(IntType x) { + return sprout::math::integer_part(static_cast(x)); + } } // namespace math using sprout::math::integer_part; diff --git a/sprout/math/iround.hpp b/sprout/math/iround.hpp index be294ec4..4ecc035e 100644 --- a/sprout/math/iround.hpp +++ b/sprout/math/iround.hpp @@ -24,8 +24,8 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_USE_BUILTIN_CMATH_FUNCTION + namespace detail { template inline SPROUT_CONSTEXPR To iround_impl(FloatType x) { @@ -34,18 +34,23 @@ namespace sprout { : static_cast(x) ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iround(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : sprout::math::detail::iround_impl(sprout::math::round(x)) - ; - } + } // namespace detail + // + // iround + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iround(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : sprout::math::detail::iround_impl(sprout::math::round(x)) + ; + } #else + namespace detail { template inline SPROUT_CONSTEXPR To iround_impl_positive(FloatType x, To x0) { @@ -60,34 +65,35 @@ namespace sprout { : x0 - 1 ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iround(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : x == 0 ? To(0) - : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iround: large float irounding."), x) - : x < 0 ? sprout::math::detail::iround_impl_nagative(x, static_cast(x)) - : sprout::math::detail::iround_impl_positive(x, static_cast(x)) - ; - } -#endif - template< - typename To = int, - typename IntType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - iround(IntType x) { - return sprout::math::detail::iround(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::iround; + // + // iround + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iround(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : x == 0 ? To(0) + : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iround: large float irounding."), x) + : x < 0 ? sprout::math::detail::iround_impl_nagative(x, static_cast(x)) + : sprout::math::detail::iround_impl_positive(x, static_cast(x)) + ; + } +#endif + template< + typename To = int, + typename IntType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + iround(IntType x) { + return sprout::math::iround(static_cast(x)); + } } // namespace math using sprout::math::iround; diff --git a/sprout/math/is_even.hpp b/sprout/math/is_even.hpp index c80ff08d..d4bc5d14 100644 --- a/sprout/math/is_even.hpp +++ b/sprout/math/is_even.hpp @@ -22,20 +22,20 @@ namespace sprout { is_even_unchecked(T x) { return sprout::math::fmod(x, T(2)) == T(0); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR bool - is_even(FloatType x) { - return sprout::math::isfinite(x) - && sprout::math::detail::is_even_unchecked(x) - ; - } } // namespace detail - - using sprout::math::detail::is_even; + // + // is_even + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_even(FloatType x) { + return sprout::math::isfinite(x) + && sprout::math::detail::is_even_unchecked(x) + ; + } } // namespace math using sprout::math::is_even; diff --git a/sprout/math/is_integer.hpp b/sprout/math/is_integer.hpp index ac8b1c54..8a37349c 100644 --- a/sprout/math/is_integer.hpp +++ b/sprout/math/is_integer.hpp @@ -22,20 +22,20 @@ namespace sprout { is_integer_unchecked(T x) { return x == sprout::math::trunc(x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR bool - is_integer(FloatType x) { - return sprout::math::isfinite(x) - && sprout::math::detail::is_integer_unchecked(x) - ; - } } // namespace detail - - using sprout::math::detail::is_integer; + // + // is_integer + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_integer(FloatType x) { + return sprout::math::isfinite(x) + && sprout::math::detail::is_integer_unchecked(x) + ; + } } // namespace math using sprout::math::is_integer; diff --git a/sprout/math/is_odd.hpp b/sprout/math/is_odd.hpp index c790907d..3a03c772 100644 --- a/sprout/math/is_odd.hpp +++ b/sprout/math/is_odd.hpp @@ -22,20 +22,20 @@ namespace sprout { is_odd_unchecked(T x) { return sprout::math::fmod(x, T(2)) == T(1); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR bool - is_odd(FloatType x) { - return sprout::math::isfinite(x) - && sprout::math::detail::is_odd_unchecked(x) - ; - } } // namespace detail - - using sprout::math::detail::is_odd; + // + // is_odd + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_odd(FloatType x) { + return sprout::math::isfinite(x) + && sprout::math::detail::is_odd_unchecked(x) + ; + } } // namespace math using sprout::math::is_odd; diff --git a/sprout/math/isfinite.hpp b/sprout/math/isfinite.hpp index 4f5dcf5f..8f70cf46 100644 --- a/sprout/math/isfinite.hpp +++ b/sprout/math/isfinite.hpp @@ -18,19 +18,39 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR bool - isfinite(FloatType x) { - return !sprout::math::isnan(x) - && !sprout::math::isinf(x) - ; + builtin_isfinite(FloatType x) { + return __builtin_isfinite(x); } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::isfinite; + // + // isfinite + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isfinite(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_isfinite(x) +#else + !(sprout::math::isnan(x) || sprout::math::isinf(x)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isfinite(IntType x) { + return true; + } } // namespace math using sprout::math::isfinite; diff --git a/sprout/math/isinf.hpp b/sprout/math/isinf.hpp index 66ebce95..39092966 100644 --- a/sprout/math/isinf.hpp +++ b/sprout/math/isinf.hpp @@ -17,19 +17,40 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR bool - isinf(FloatType x) { - return x == sprout::numeric_limits::infinity() - || x == -sprout::numeric_limits::infinity() - ; + builtin_isinf(FloatType x) { + return __builtin_isinf(x); } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::isinf; + // + // isinf + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isinf(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_isinf(x) +#else + x == sprout::numeric_limits::infinity() + || x == -sprout::numeric_limits::infinity() +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isinf(IntType x) { + return false; + } } // namespace math using sprout::math::isinf; diff --git a/sprout/math/isnan.hpp b/sprout/math/isnan.hpp index 185107e0..e58ab5ae 100644 --- a/sprout/math/isnan.hpp +++ b/sprout/math/isnan.hpp @@ -16,17 +16,39 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR bool - isnan(FloatType x) { - return !(x == x); + builtin_isnan(FloatType x) { + return __builtin_isnan(x); } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::isnan; + // + // isnan + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isnan(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_isnan(x) +#else + !(x == x) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isnan(IntType x) { + return false; + } } // namespace math using sprout::math::isnan; diff --git a/sprout/math/isnormal.hpp b/sprout/math/isnormal.hpp index 106f1f55..bbe001de 100644 --- a/sprout/math/isnormal.hpp +++ b/sprout/math/isnormal.hpp @@ -19,20 +19,41 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR bool - isnormal(FloatType x) { - return !sprout::math::isnan(x) - && !sprout::math::isinf(x) - && !sprout::math::detail::issubnormal_or_zero(x) - ; + builtin_isnormal(FloatType x) { + return __builtin_isnormal(x); } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::isnormal; + // + // isnormal + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isnormal(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_isnormal(x) +#else + !sprout::math::isnan(x) + && !sprout::math::isinf(x) + && !sprout::math::detail::issubnormal_or_zero(x) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + isnormal(IntType x) { + return x != 0; + } } // namespace math using sprout::math::isnormal; diff --git a/sprout/math/issubnormal.hpp b/sprout/math/issubnormal.hpp index b3476f7b..3b26026b 100644 --- a/sprout/math/issubnormal.hpp +++ b/sprout/math/issubnormal.hpp @@ -18,6 +18,9 @@ namespace sprout { namespace math { namespace detail { + // + // issubnormal_or_zero + // template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler @@ -29,21 +32,21 @@ namespace sprout { : x > -sprout::numeric_limits::min() ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR bool - issubnormal(FloatType x) { - return !sprout::math::isnan(x) - && !sprout::math::iszero(x) - && sprout::math::detail::issubnormal_or_zero(x) - ; - } } // namespace detail - - using sprout::math::detail::issubnormal; + // + // issubnormal + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + issubnormal(FloatType x) { + return !sprout::math::isnan(x) + && !sprout::math::iszero(x) + && sprout::math::detail::issubnormal_or_zero(x) + ; + } } // namespace math using sprout::math::issubnormal; diff --git a/sprout/math/iszero.hpp b/sprout/math/iszero.hpp index cc401b94..96efc3ac 100644 --- a/sprout/math/iszero.hpp +++ b/sprout/math/iszero.hpp @@ -14,18 +14,25 @@ namespace sprout { namespace math { - namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR bool - iszero(FloatType x) { - return x == 0; - } - } // namespace detail - - using sprout::math::detail::iszero; + // + // iszero + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + iszero(FloatType x) { + return x == 0; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + iszero(IntType x) { + return x == 0; + } } // namespace math using sprout::math::iszero; diff --git a/sprout/math/itrunc.hpp b/sprout/math/itrunc.hpp index 009e9bc3..f5a8d1d7 100644 --- a/sprout/math/itrunc.hpp +++ b/sprout/math/itrunc.hpp @@ -22,8 +22,8 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_USE_BUILTIN_CMATH_FUNCTION + namespace detail { template inline SPROUT_CONSTEXPR To itrunc_impl(FloatType x) { @@ -32,45 +32,49 @@ namespace sprout { : static_cast(x) ; } - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - itrunc(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : sprout::math::detail::itrunc_impl(sprout::math::trunc(x)) - ; - } -#else - template< - typename To = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - itrunc(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() - : x == 0 ? To(0) - : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast(x)) - : static_cast(x) - ; - } -#endif - template< - typename To = int, - typename IntType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR To - itrunc(IntType x) { - return sprout::math::detail::itrunc(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::itrunc; + // + // itrunc + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + itrunc(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : sprout::math::detail::itrunc_impl(sprout::math::trunc(x)) + ; + } +#else + // + // itrunc + // + template< + typename To = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + itrunc(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() + : x == 0 ? To(0) + : sprout::numeric_limits::max() < x || sprout::numeric_limits::min() > x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast(x)) + : static_cast(x) + ; + } +#endif + template< + typename To = int, + typename IntType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR To + itrunc(IntType x) { + return sprout::math::itrunc(static_cast(x)); + } } // namespace math using sprout::math::itrunc; diff --git a/sprout/math/ldexp.hpp b/sprout/math/ldexp.hpp index 51507f31..be73d7c7 100644 --- a/sprout/math/ldexp.hpp +++ b/sprout/math/ldexp.hpp @@ -20,37 +20,57 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_ldexp(float x, int exp) { + return __builtin_ldexpf(x, exp); + } + inline SPROUT_CONSTEXPR double + builtin_ldexp(double x, int exp) { + return __builtin_ldexp(x, exp); + } + inline SPROUT_CONSTEXPR long double + builtin_ldexp(long double x, int exp) { + return __builtin_ldexpl(x, exp); + } +#endif + template inline SPROUT_CONSTEXPR T ldexp_impl(T x, int exp) { return x * sprout::detail::pow_n(T(2), exp); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - ldexp(FloatType x, int exp) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : exp == 0 ? x - : x == 0 ? x - : static_cast(sprout::math::detail::ldexp_impl(static_cast::type>(x), exp)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - ldexp(IntType x, int exp) { - return sprout::math::detail::ldexp(static_cast(x), exp); - } } // namespace detail - - using NS_SPROUT_MATH_DETAIL::ldexp; + // + // ldexp + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + ldexp(FloatType x, int exp) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_ldexp(x, exp) +#else + sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : exp == 0 ? x + : x == 0 ? x + : static_cast(sprout::math::detail::ldexp_impl(static_cast::type>(x), exp)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + ldexp(IntType x, int exp) { + return sprout::math::ldexp(static_cast(x), exp); + } } // namespace math using sprout::math::ldexp; diff --git a/sprout/math/lgamma.hpp b/sprout/math/lgamma.hpp index 1d1bc17b..c4d53069 100644 --- a/sprout/math/lgamma.hpp +++ b/sprout/math/lgamma.hpp @@ -26,6 +26,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_lgamma(float x) { + return __builtin_lgammaf(x); + } + inline SPROUT_CONSTEXPR double + builtin_lgamma(double x) { + return __builtin_lgamma(x); + } + inline SPROUT_CONSTEXPR long double + builtin_lgamma(long double x) { + return __builtin_lgammal(x); + } +#endif + template inline SPROUT_CONSTEXPR T lgamma_impl_3(T x, T y) { @@ -183,38 +198,38 @@ namespace sprout { lgamma_impl(T x) { return sprout::math::detail::lgamma_impl_1(x, x < 0 ? -x : x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - lgamma(FloatType x) { - return sprout::math::isnan(x) ? x - : x <= 0 && sprout::math::is_integer(x) ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() -//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION -// : std::lgamma(x) -//#else - : x == 1 ? FloatType(0) - : x == 2 ? FloatType(0) - : static_cast(sprout::math::detail::lgamma_impl(static_cast::type>(x))) -//#endif - ; - } - - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - lgamma(IntType x) { - return sprout::math::detail::lgamma(static_cast(x)); - } } // namespace detail + // + // lgamma + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + lgamma(FloatType x) { + return sprout::math::isnan(x) ? x + : x <= 0 && sprout::math::is_integer(x) ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() +//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION +// : sprout::math::detail::builtin_lgamma(x) +//#else + : x == 1 ? FloatType(0) + : x == 2 ? FloatType(0) + : static_cast(sprout::math::detail::lgamma_impl(static_cast::type>(x))) +//#endif + ; + } - using sprout::math::detail::lgamma; + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + lgamma(IntType x) { + return sprout::math::lgamma(static_cast(x)); + } } // namespace math using sprout::math::lgamma; diff --git a/sprout/math/llround.hpp b/sprout/math/llround.hpp index cf41abb8..4b8e762a 100644 --- a/sprout/math/llround.hpp +++ b/sprout/math/llround.hpp @@ -20,35 +20,52 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR long long - llround(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::llround(x) -#else - : sprout::math::iround(x); -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > inline SPROUT_CONSTEXPR long long - llround(IntType x) { -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - return std::llround(x); -#else - return sprout::math::iround(x); -#endif + builtin_llround(float x) { + return __builtin_llroundf(x); } + inline SPROUT_CONSTEXPR long long + builtin_llround(double x) { + return __builtin_llround(x); + } + inline SPROUT_CONSTEXPR long long + builtin_llround(long double x) { + return __builtin_llroundl(x); + } +#endif } // namespace detail - - using sprout::math::detail::llround; + // + // llround + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR long long + llround(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_llround(x) +#else + : sprout::math::iround(x); +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR long long + llround(IntType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_llround(x) +#else + sprout::math::iround(x) +#endif + ; + } } // namespace math using sprout::math::llround; diff --git a/sprout/math/log.hpp b/sprout/math/log.hpp index 5ee55d0f..3dc1c158 100644 --- a/sprout/math/log.hpp +++ b/sprout/math/log.hpp @@ -24,6 +24,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_log(float x) { + return __builtin_logf(x); + } + inline SPROUT_CONSTEXPR double + builtin_log(double x) { + return __builtin_log(x); + } + inline SPROUT_CONSTEXPR long double + builtin_log(long double x) { + return __builtin_logl(x); + } +#endif + template inline SPROUT_CONSTEXPR T log_impl_2(T x, std::size_t n, std::size_t last) { @@ -48,36 +63,36 @@ namespace sprout { : sprout::math::detail::log_impl_1(x) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - log(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? -sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < 0 ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::log(x) -#else - : x == 1 ? FloatType(0) - : static_cast(sprout::math::detail::log_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - log(IntType x) { - return sprout::math::detail::log(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::log; + // + // log + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + log(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? -sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < 0 ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_log(x) +#else + : x == 1 ? FloatType(0) + : static_cast(sprout::math::detail::log_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + log(IntType x) { + return sprout::math::log(static_cast(x)); + } } // namespace math using sprout::math::log; diff --git a/sprout/math/log10.hpp b/sprout/math/log10.hpp index 4fddd7bf..d4795f18 100644 --- a/sprout/math/log10.hpp +++ b/sprout/math/log10.hpp @@ -21,41 +21,56 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_log10(float x) { + return __builtin_log10f(x); + } + inline SPROUT_CONSTEXPR double + builtin_log10(double x) { + return __builtin_log10(x); + } + inline SPROUT_CONSTEXPR long double + builtin_log10(long double x) { + return __builtin_log10l(x); + } +#endif + template inline SPROUT_CONSTEXPR T log10_impl(T x) { return sprout::math::log(x) / sprout::math::ln_ten(); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - log10(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? -sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < 0 ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::log10(x) -#else - : x == 1 ? FloatType(0) - : static_cast(sprout::math::detail::log10_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - log10(IntType x) { - return sprout::math::detail::log10(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::log10; + // + // log10 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + log10(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? -sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < 0 ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_log10(x) +#else + : x == 1 ? FloatType(0) + : static_cast(sprout::math::detail::log10_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + log10(IntType x) { + return sprout::math::log10(static_cast(x)); + } } // namespace math using sprout::math::log10; diff --git a/sprout/math/log1p.hpp b/sprout/math/log1p.hpp index ad52caf4..3684f3b6 100644 --- a/sprout/math/log1p.hpp +++ b/sprout/math/log1p.hpp @@ -20,41 +20,56 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_log1p(float x) { + return __builtin_log1pf(x); + } + inline SPROUT_CONSTEXPR double + builtin_log1p(double x) { + return __builtin_log1p(x); + } + inline SPROUT_CONSTEXPR long double + builtin_log1p(long double x) { + return __builtin_log1pl(x); + } +#endif + template inline SPROUT_CONSTEXPR T log1p_impl(T x) { return sprout::math::log(T(1) + x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - log1p(FloatType x) { - return sprout::math::isnan(x) ? x - : x == -1 ? -sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < -1 ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::log1p(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::log1p_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - log1p(IntType x) { - return sprout::math::detail::log1p(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::log1p; + // + // log1p + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + log1p(FloatType x) { + return sprout::math::isnan(x) ? x + : x == -1 ? -sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < -1 ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_log1p(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::log1p_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + log1p(IntType x) { + return sprout::math::log1p(static_cast(x)); + } } // namespace math using sprout::math::log1p; diff --git a/sprout/math/log2.hpp b/sprout/math/log2.hpp index 61fcd999..1f155c5c 100644 --- a/sprout/math/log2.hpp +++ b/sprout/math/log2.hpp @@ -21,41 +21,56 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_log2(float x) { + return __builtin_log2f(x); + } + inline SPROUT_CONSTEXPR double + builtin_log2(double x) { + return __builtin_log2(x); + } + inline SPROUT_CONSTEXPR long double + builtin_log2(long double x) { + return __builtin_log2l(x); + } +#endif + template inline SPROUT_CONSTEXPR T log2_impl(T x) { return sprout::math::log(x) / sprout::math::ln_two(); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - log2(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? -sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < 0 ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::log2(x) -#else - : x == 1 ? FloatType(0) - : static_cast(sprout::math::detail::log2_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - log2(IntType x) { - return sprout::math::detail::log2(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::log2; + // + // log2 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + log2(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? -sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < 0 ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_log2(x) +#else + : x == 1 ? FloatType(0) + : static_cast(sprout::math::detail::log2_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + log2(IntType x) { + return sprout::math::log2(static_cast(x)); + } } // namespace math using sprout::math::log2; diff --git a/sprout/math/log_a.hpp b/sprout/math/log_a.hpp index c0c9f5f0..240bb2b4 100644 --- a/sprout/math/log_a.hpp +++ b/sprout/math/log_a.hpp @@ -28,34 +28,34 @@ namespace sprout { : sprout::math::log(y) / sprout::math::log(x) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - log_a(FloatType x, FloatType y) { - return static_cast(sprout::math::detail::log_a_impl( - static_cast::type>(x), - static_cast::type>(y) - )); - } - - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - log_a(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::log_a(static_cast(x), static_cast(y)); - } } // namespace detail + // + // log_a + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + log_a(FloatType x, FloatType y) { + return static_cast(sprout::math::detail::log_a_impl( + static_cast::type>(x), + static_cast::type>(y) + )); + } - using sprout::math::detail::log_a; + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + log_a(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::log_a(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::log_a; diff --git a/sprout/math/logb.hpp b/sprout/math/logb.hpp index 20ce7c72..508fab38 100644 --- a/sprout/math/logb.hpp +++ b/sprout/math/logb.hpp @@ -25,6 +25,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_logb(float x) { + return __builtin_logbf(x); + } + inline SPROUT_CONSTEXPR double + builtin_logb(double x) { + return __builtin_logb(x); + } + inline SPROUT_CONSTEXPR long double + builtin_logb(long double x) { + return __builtin_logbl(x); + } +#endif + template inline SPROUT_CONSTEXPR T logb_impl_3_neg_lo(T x, T x0, T base, T exp) { @@ -100,39 +115,39 @@ namespace sprout { : sprout::math::detail::logb_impl_1(x, sprout::math::trunc(sprout::math::log_a(T(sprout::numeric_limits::radix), x))) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - logb(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? -sprout::numeric_limits::infinity() + } // namespace detail + // + // logb + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + logb(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? -sprout::numeric_limits::infinity() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION # if defined(__GNUC__) - : x == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() # endif - : std::logb(x) + : sprout::math::detail::builtin_logb(x) #else - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() - : static_cast(sprout::math::detail::logb_impl(static_cast::type>(x))) + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() + : static_cast(sprout::math::detail::logb_impl(static_cast::type>(x))) #endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - logb(IntType x) { - return sprout::math::detail::logb(static_cast(x)); - } - } // namespace detail - - using sprout::math::detail::logb; + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + logb(IntType x) { + return sprout::math::logb(static_cast(x)); + } } // namespace math using sprout::math::logb; diff --git a/sprout/math/logb2.hpp b/sprout/math/logb2.hpp index 5c14a189..3b239dcd 100644 --- a/sprout/math/logb2.hpp +++ b/sprout/math/logb2.hpp @@ -28,25 +28,28 @@ namespace sprout { namespace math { - namespace detail { #if SPROUT_FLT_RADIX_IS_2 - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - logb2(FloatType x) { - return sprout::math::logb(x); - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - logb2(IntType x) { - return sprout::math::logb(x); - } + // + // logb2 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + logb2(FloatType x) { + return sprout::math::logb(x); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + logb2(IntType x) { + return sprout::math::logb(x); + } #else + namespace detail { template inline SPROUT_CONSTEXPR T logb2_impl_3_neg_lo(T x, T x0, T base, T exp) { @@ -122,32 +125,32 @@ namespace sprout { : sprout::math::detail::logb2_impl_1(x, sprout::math::trunc(sprout::math::log_a(T(2), x))) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - logb2(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? -sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? sprout::numeric_limits::infinity() - : static_cast(sprout::math::detail::logb2_impl(static_cast::type>(x))) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - logb2(IntType x) { - return sprout::math::detail::logb2(static_cast(x)); - } -#endif } // namespace detail - - using sprout::math::detail::logb2; + // + // logb2 + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + logb2(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? -sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? sprout::numeric_limits::infinity() + : static_cast(sprout::math::detail::logb2_impl(static_cast::type>(x))) + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + logb2(IntType x) { + return sprout::math::logb2(static_cast(x)); + } +#endif } // namespace math using sprout::math::logb2; diff --git a/sprout/math/lround.hpp b/sprout/math/lround.hpp index c128c7d7..89c21761 100644 --- a/sprout/math/lround.hpp +++ b/sprout/math/lround.hpp @@ -20,35 +20,52 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR long - lround(FloatType x) { - return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::lround(x) -#else - : sprout::math::iround(x); -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > inline SPROUT_CONSTEXPR long - lround(IntType x) { -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - return std::lround(x); -#else - return sprout::math::iround(x); -#endif + builtin_lround(float x) { + return __builtin_lroundf(x); } + inline SPROUT_CONSTEXPR long + builtin_lround(double x) { + return __builtin_lround(x); + } + inline SPROUT_CONSTEXPR long + builtin_lround(long double x) { + return __builtin_lroundl(x); + } +#endif } // namespace detail - - using sprout::math::detail::lround; + // + // lround + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR long + lround(FloatType x) { + return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits::min() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_lround(x) +#else + : sprout::math::iround(x); +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR long + lround(IntType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_lround(x) +#else + sprout::math::iround(x) +#endif + ; + } } // namespace math using sprout::math::lround; diff --git a/sprout/math/pow.hpp b/sprout/math/pow.hpp index b61efef6..977718bf 100644 --- a/sprout/math/pow.hpp +++ b/sprout/math/pow.hpp @@ -26,76 +26,91 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_pow(float x, float y) { + return __builtin_powf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_pow(double x, double y) { + return __builtin_pow(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_pow(long double x, long double y) { + return __builtin_powl(x, y); + } +#endif + template inline SPROUT_CONSTEXPR T pow_impl(T x, T y) { return sprout::math::exp(y * sprout::math::log(x)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - pow(FloatType x, FloatType y) { - return x == 1 ? FloatType(1) - : y == 0 ? FloatType(1) - : sprout::math::isnan(y) ? y - : sprout::math::isnan(x) ? x - : x == 0 - ? y < 0 - ? sprout::math::is_odd(y) ? sprout::math::copysign(sprout::numeric_limits::infinity(), x) - : sprout::numeric_limits::infinity() - : sprout::math::is_odd(y) ? x - : FloatType(0) - : x == -1 && (y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity()) ? FloatType(1) - : y == -sprout::numeric_limits::infinity() - ? sprout::math::fabs(x) < 1 ? sprout::numeric_limits::infinity() - : FloatType(0) - : y == sprout::numeric_limits::infinity() - ? sprout::math::fabs(x) < 1 ? FloatType(0) - : sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() - ? y < 0 - ? sprout::math::is_odd(y) ? -FloatType(0) - : FloatType(0) - : sprout::math::is_odd(y) ? -sprout::numeric_limits::infinity() - : sprout::numeric_limits::infinity() - : x == sprout::numeric_limits::infinity() - ? y < 0 ? FloatType(0) - : sprout::numeric_limits::infinity() - : x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::pow(x, y) -#else - : static_cast(sprout::math::detail::pow_impl( - static_cast::type>(x), - static_cast::type>(y) - )) -#endif - ; - } - - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - pow(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::pow(static_cast(x), static_cast(y)); - } } // namespace detail // + // pow + // // issue: // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] // pow(-0, y) returns - for y an odd integer < 0. // # returns + . ( same as pow(+0, y) ) // - using sprout::math::detail::pow; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + pow(FloatType x, FloatType y) { + return x == 1 ? FloatType(1) + : y == 0 ? FloatType(1) + : sprout::math::isnan(y) ? y + : sprout::math::isnan(x) ? x + : x == 0 + ? y < 0 + ? sprout::math::is_odd(y) ? sprout::math::copysign(sprout::numeric_limits::infinity(), x) + : sprout::numeric_limits::infinity() + : sprout::math::is_odd(y) ? x + : FloatType(0) + : x == -1 && (y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity()) ? FloatType(1) + : y == -sprout::numeric_limits::infinity() + ? sprout::math::fabs(x) < 1 ? sprout::numeric_limits::infinity() + : FloatType(0) + : y == sprout::numeric_limits::infinity() + ? sprout::math::fabs(x) < 1 ? FloatType(0) + : sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() + ? y < 0 + ? sprout::math::is_odd(y) ? -FloatType(0) + : FloatType(0) + : sprout::math::is_odd(y) ? -sprout::numeric_limits::infinity() + : sprout::numeric_limits::infinity() + : x == sprout::numeric_limits::infinity() + ? y < 0 ? FloatType(0) + : sprout::numeric_limits::infinity() + : x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_pow(x, y) +#else + : static_cast(sprout::math::detail::pow_impl( + static_cast::type>(x), + static_cast::type>(y) + )) +#endif + ; + } + + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + pow(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::pow(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::pow; diff --git a/sprout/math/quotient.hpp b/sprout/math/quotient.hpp index 2d0ab884..89fa3c17 100644 --- a/sprout/math/quotient.hpp +++ b/sprout/math/quotient.hpp @@ -20,39 +20,38 @@ namespace sprout { namespace math { - namespace detail { - template< - typename R = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR R - quotient(FloatType x, FloatType y) { - return y == 0 ? R(0) - : sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0) - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? R(0) - : x == 0 ? R(0) - : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? R(0) - : sprout::math::rem_quo(x, y).second - ; - } - template< - typename R = int, - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value && std::is_integral::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR R - quotient(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::quotient(static_cast(x), static_cast(y)); - } - } // namespace detail - - using sprout::math::detail::quotient; + // + // quotient + // + template< + typename R = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR R + quotient(FloatType x, FloatType y) { + return y == 0 ? R(0) + : sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0) + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? R(0) + : x == 0 ? R(0) + : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? R(0) + : sprout::math::rem_quo(x, y).second + ; + } + template< + typename R = int, + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value && std::is_integral::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR R + quotient(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::quotient(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::quotient; diff --git a/sprout/math/rem_quo.hpp b/sprout/math/rem_quo.hpp index a4f0e2f6..44fc0c56 100644 --- a/sprout/math/rem_quo.hpp +++ b/sprout/math/rem_quo.hpp @@ -87,55 +87,56 @@ namespace sprout { rem_quo_impl(T x, T y, R iquo) { return sprout::math::detail::rem_quo_impl_1(x, sprout::math::fabs(y), (sprout::math::signbit(x) ^ sprout::math::signbit(y) ? -1 : 1), iquo, sprout::math::fabs(x)); } - - template< - typename R = int, - typename FloatType, - typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair - rem_quo(FloatType x, FloatType y) { - typedef sprout::pair type; - return y == 0 ? type(-sprout::numeric_limits::quiet_NaN(), R(0)) - : sprout::math::isnan(y) - ? sprout::math::isnan(x) - ? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() : sprout::numeric_limits::quiet_NaN(), R(0)) - : type(y, R(0)) - : sprout::math::isnan(x) ? type(x, R(0)) - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? type(-sprout::numeric_limits::quiet_NaN(), R(0)) - : x == 0 ? type(x, R(0)) - : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? type(x, R(0)) - : sprout::math::detail::rem_quo_ret(sprout::math::detail::rem_quo_impl( - static_cast::type>(x), - static_cast::type>(y), - R(0) - )) - ; - } - template< - typename R = int, - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value && std::is_integral::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR sprout::pair< - typename sprout::float_promote::type, - R - > - rem_quo(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::rem_quo(static_cast(x), static_cast(y)); - } } // namespace detail // + // rem_quo + // + // // issue: // rem_quo(-NaN, -NaN) returns {-NaN, _} . // # returns {+NaN, _} . ( same as rem_quo(+NaN, +NaN) ) // - using sprout::math::detail::rem_quo; + template< + typename R = int, + typename FloatType, + typename sprout::enabler_if::value && std::is_integral::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair + rem_quo(FloatType x, FloatType y) { + typedef sprout::pair type; + return y == 0 ? type(-sprout::numeric_limits::quiet_NaN(), R(0)) + : sprout::math::isnan(y) + ? sprout::math::isnan(x) + ? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() : sprout::numeric_limits::quiet_NaN(), R(0)) + : type(y, R(0)) + : sprout::math::isnan(x) ? type(x, R(0)) + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? type(-sprout::numeric_limits::quiet_NaN(), R(0)) + : x == 0 ? type(x, R(0)) + : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? type(x, R(0)) + : sprout::math::detail::rem_quo_ret(sprout::math::detail::rem_quo_impl( + static_cast::type>(x), + static_cast::type>(y), + R(0) + )) + ; + } + template< + typename R = int, + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value && std::is_integral::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR sprout::pair< + typename sprout::float_promote::type, + R + > + rem_quo(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::rem_quo(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::rem_quo; diff --git a/sprout/math/remainder.hpp b/sprout/math/remainder.hpp index 3d34ec8c..7b00300d 100644 --- a/sprout/math/remainder.hpp +++ b/sprout/math/remainder.hpp @@ -21,49 +21,64 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - remainder(FloatType x, FloatType y) { - return y == 0 ? -sprout::numeric_limits::quiet_NaN() - : sprout::math::isnan(y) - ? sprout::math::isnan(x) - ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() - : sprout::numeric_limits::quiet_NaN() - : y - : sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? -sprout::numeric_limits::quiet_NaN() - : x == 0 ? x - : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? x #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::remainder(x, y) -#else - : sprout::math::rem_quo(x, y).first + inline SPROUT_CONSTEXPR float + builtin_remainder(float x, float y) { + return __builtin_remainderf(x, y); + } + inline SPROUT_CONSTEXPR double + builtin_remainder(double x, double y) { + return __builtin_remainder(x, y); + } + inline SPROUT_CONSTEXPR long double + builtin_remainder(long double x, long double y) { + return __builtin_remainderl(x, y); + } #endif - ; - } - template< - typename ArithmeticType1, - typename ArithmeticType2, - typename sprout::enabler_if< - std::is_arithmetic::value && std::is_arithmetic::value - >::type = sprout::enabler - > - inline SPROUT_CONSTEXPR typename sprout::float_promote::type - remainder(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::float_promote::type type; - return sprout::math::detail::remainder(static_cast(x), static_cast(y)); - } } // namespace detail // + // remainder + // // issue: // remainder(-NaN, -NaN) returns -NaN . // # returns +NaN . ( same as remainder(+NaN, +NaN) ) // - using sprout::math::detail::remainder; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + remainder(FloatType x, FloatType y) { + return y == 0 ? -sprout::numeric_limits::quiet_NaN() + : sprout::math::isnan(y) + ? sprout::math::isnan(x) + ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits::quiet_NaN() + : sprout::numeric_limits::quiet_NaN() + : y + : sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? -sprout::numeric_limits::quiet_NaN() + : x == 0 ? x + : y == sprout::numeric_limits::infinity() || y == -sprout::numeric_limits::infinity() ? x +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_remainder(x, y) +#else + : sprout::math::rem_quo(x, y).first +#endif + ; + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + remainder(ArithmeticType1 x, ArithmeticType2 y) { + typedef typename sprout::float_promote::type type; + return sprout::math::remainder(static_cast(x), static_cast(y)); + } } // namespace math using sprout::math::remainder; diff --git a/sprout/math/round.hpp b/sprout/math/round.hpp index 21882cc5..8e496a7e 100644 --- a/sprout/math/round.hpp +++ b/sprout/math/round.hpp @@ -21,6 +21,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_round(float x) { + return __builtin_roundf(x); + } + inline SPROUT_CONSTEXPR double + builtin_round(double x) { + return __builtin_round(x); + } + inline SPROUT_CONSTEXPR long double + builtin_round(long double x) { + return __builtin_roundl(x); + } +#endif + template inline SPROUT_CONSTEXPR T round_impl_positive(T x, T x0) { @@ -42,37 +57,37 @@ namespace sprout { : sprout::math::detail::round_impl_positive(x, static_cast(static_cast(x))) ; } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - round(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::round(x) -#else - : x == 0 ? x - : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x) - : static_cast(sprout::math::detail::round_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - round(IntType x) { - return sprout::math::detail::round(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::round; + // + // round + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + round(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_round(x) +#else + : x == 0 ? x + : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x) + : static_cast(sprout::math::detail::round_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + round(IntType x) { + return sprout::math::round(static_cast(x)); + } } // namespace math using sprout::math::round; diff --git a/sprout/math/scalbln.hpp b/sprout/math/scalbln.hpp index b05ffce2..0ebd07b9 100644 --- a/sprout/math/scalbln.hpp +++ b/sprout/math/scalbln.hpp @@ -20,37 +20,57 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_scalbln(float x, long exp) { + return __builtin_scalblnf(x, exp); + } + inline SPROUT_CONSTEXPR double + builtin_scalbln(double x, long exp) { + return __builtin_scalbln(x, exp); + } + inline SPROUT_CONSTEXPR long double + builtin_scalbln(long double x, long exp) { + return __builtin_scalblnl(x, exp); + } +#endif + template inline SPROUT_CONSTEXPR T scalbln_impl(T x, long exp) { return x * sprout::detail::pow_n(T(sprout::numeric_limits::radix), exp); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - scalbln(FloatType x, long exp) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : exp == 0 ? x - : x == 0 ? x - : static_cast(sprout::math::detail::scalbln_impl(static_cast::type>(x), exp)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - scalbln(IntType x, long exp) { - return sprout::math::detail::scalbln(static_cast(x), exp); - } } // namespace detail - - using NS_SPROUT_MATH_DETAIL::scalbln; + // + // scalbln + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + scalbln(FloatType x, long exp) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_scalbln(x, exp) +#else + sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : exp == 0 ? x + : x == 0 ? x + : static_cast(sprout::math::detail::scalbln_impl(static_cast::type>(x), exp)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + scalbln(IntType x, long exp) { + return sprout::math::scalbln(static_cast(x), exp); + } } // namespace math using sprout::math::scalbln; diff --git a/sprout/math/scalbn.hpp b/sprout/math/scalbn.hpp index 2b1a3fe3..fd80993b 100644 --- a/sprout/math/scalbn.hpp +++ b/sprout/math/scalbn.hpp @@ -20,37 +20,57 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_scalbn(float x, int exp) { + return __builtin_scalbnf(x, exp); + } + inline SPROUT_CONSTEXPR double + builtin_scalbn(double x, int exp) { + return __builtin_scalbn(x, exp); + } + inline SPROUT_CONSTEXPR long double + builtin_scalbn(long double x, int exp) { + return __builtin_scalbnl(x, exp); + } +#endif + template inline SPROUT_CONSTEXPR T scalbn_impl(T x, int exp) { return x * sprout::detail::pow_n(T(sprout::numeric_limits::radix), exp); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - scalbn(FloatType x, int exp) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() - : exp == 0 ? x - : x == 0 ? x - : static_cast(sprout::math::detail::scalbn_impl(static_cast::type>(x), exp)) - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - scalbn(IntType x, int exp) { - return sprout::math::detail::scalbn(static_cast(x), exp); - } } // namespace detail - - using NS_SPROUT_MATH_DETAIL::scalbn; + // + // scalbn + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + scalbn(FloatType x, int exp) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_scalbn(x, exp) +#else + sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() + : exp == 0 ? x + : x == 0 ? x + : static_cast(sprout::math::detail::scalbn_impl(static_cast::type>(x), exp)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + scalbn(IntType x, int exp) { + return sprout::math::scalbn(static_cast(x), exp); + } } // namespace math using sprout::math::scalbn; diff --git a/sprout/math/signbit.hpp b/sprout/math/signbit.hpp index f5557e5d..0bf20fd0 100644 --- a/sprout/math/signbit.hpp +++ b/sprout/math/signbit.hpp @@ -17,16 +17,17 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + template inline SPROUT_CONSTEXPR bool - signbit(FloatType x) { - return !sprout::math::isnan(x) && x < 0; + builtin_signbit(FloatType x) { + return __builtin_signbit(x); } +#endif } // namespace detail // + // signbit + // // issue: // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] // signbit(-0) returns false . @@ -34,7 +35,28 @@ namespace sprout { // signbit(-NaN) returns false . // # returns true . ( same as signbit(+NaN) ) // - using NS_SPROUT_MATH_DETAIL::signbit; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + signbit(FloatType x) { + return +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + sprout::math::detail::builtin_signbit(x) +#else + !sprout::math::isnan(x) && x < 0 +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + signbit(IntType x) { + return x < 0; + } } // namespace math using sprout::math::signbit; diff --git a/sprout/math/sin.hpp b/sprout/math/sin.hpp index 38179d77..c34ac2e1 100644 --- a/sprout/math/sin.hpp +++ b/sprout/math/sin.hpp @@ -21,40 +21,55 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_sin(float x) { + return __builtin_sinf(x); + } + inline SPROUT_CONSTEXPR double + builtin_sin(double x) { + return __builtin_sin(x); + } + inline SPROUT_CONSTEXPR long double + builtin_sin(long double x) { + return __builtin_sinl(x); + } +#endif + template inline SPROUT_CONSTEXPR T sin_impl(T x) { return -sprout::math::cos(x + sprout::math::half_pi()); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - sin(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::sin(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::sin_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - sin(IntType x) { - return sprout::math::detail::sin(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::sin; + // + // sin + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + sin(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_sin(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::sin_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + sin(IntType x) { + return sprout::math::sin(static_cast(x)); + } } // namespace math using sprout::math::sin; diff --git a/sprout/math/sinh.hpp b/sprout/math/sinh.hpp index 00d56039..fe462fee 100644 --- a/sprout/math/sinh.hpp +++ b/sprout/math/sinh.hpp @@ -21,6 +21,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_sinh(float x) { + return __builtin_sinhf(x); + } + inline SPROUT_CONSTEXPR double + builtin_sinh(double x) { + return __builtin_sinh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_sinh(long double x) { + return __builtin_sinhl(x); + } +#endif + template inline SPROUT_CONSTEXPR T sinh_impl_1(T t) { @@ -31,35 +46,35 @@ namespace sprout { sinh_impl(T x) { return sprout::math::detail::sinh_impl_1(sprout::math::exp(x)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - sinh(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::sinh(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::sinh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - sinh(IntType x) { - return sprout::math::detail::sinh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::sinh; + // + // sinh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + sinh(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_sinh(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::sinh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + sinh(IntType x) { + return sprout::math::sinh(static_cast(x)); + } } // namespace math using sprout::math::sinh; diff --git a/sprout/math/sqrt.hpp b/sprout/math/sqrt.hpp index 12b7a4b1..ea88f4fc 100644 --- a/sprout/math/sqrt.hpp +++ b/sprout/math/sqrt.hpp @@ -19,6 +19,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_sqrt(float x) { + return __builtin_sqrtf(x); + } + inline SPROUT_CONSTEXPR double + builtin_sqrt(double x) { + return __builtin_sqrt(x); + } + inline SPROUT_CONSTEXPR long double + builtin_sqrt(long double x) { + return __builtin_sqrtl(x); + } +#endif + template inline SPROUT_CONSTEXPR T sqrt_impl_2(T x, T s, T s2) { @@ -36,35 +51,35 @@ namespace sprout { sqrt_impl(T x) { return sprout::math::detail::sqrt_impl_1(x, x > 1 ? x : T(1)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - sqrt(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < 0 ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::sqrt(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::sqrt_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - sqrt(IntType x) { - return sprout::math::detail::sqrt(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::sqrt; + // + // sqrt + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + sqrt(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < 0 ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_sqrt(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::sqrt_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + sqrt(IntType x) { + return sprout::math::sqrt(static_cast(x)); + } } // namespace math using sprout::math::sqrt; diff --git a/sprout/math/tan.hpp b/sprout/math/tan.hpp index 6027b7ca..a7b19e6d 100644 --- a/sprout/math/tan.hpp +++ b/sprout/math/tan.hpp @@ -21,40 +21,55 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_tan(float x) { + return __builtin_tanf(x); + } + inline SPROUT_CONSTEXPR double + builtin_tan(double x) { + return __builtin_tan(x); + } + inline SPROUT_CONSTEXPR long double + builtin_tan(long double x) { + return __builtin_tanl(x); + } +#endif + template inline SPROUT_CONSTEXPR T tan_impl(T x) { return sprout::math::sin(x) / sprout::math::cos(x); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - tan(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() - ? -sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::tan(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::tan_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - tan(IntType x) { - return sprout::math::detail::tan(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::tan; + // + // tan + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + tan(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() || x == -sprout::numeric_limits::infinity() + ? -sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_tan(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::tan_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + tan(IntType x) { + return sprout::math::tan(static_cast(x)); + } } // namespace math using sprout::math::tan; diff --git a/sprout/math/tanh.hpp b/sprout/math/tanh.hpp index 6714222c..99640a23 100644 --- a/sprout/math/tanh.hpp +++ b/sprout/math/tanh.hpp @@ -20,6 +20,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_tanh(float x) { + return __builtin_tanhf(x); + } + inline SPROUT_CONSTEXPR double + builtin_tanh(double x) { + return __builtin_tanh(x); + } + inline SPROUT_CONSTEXPR long double + builtin_tanh(long double x) { + return __builtin_tanhl(x); + } +#endif + template inline SPROUT_CONSTEXPR T tanh_impl_2(T t, T u) { @@ -35,35 +50,35 @@ namespace sprout { tanh_impl(T x) { return sprout::math::detail::tanh_impl_1(sprout::math::exp(x)); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - tanh(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? FloatType(1) - : x == -sprout::numeric_limits::infinity() ? FloatType(-1) -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::tanh(x) -#else - : x == 0 ? x - : static_cast(sprout::math::detail::tanh_impl(static_cast::type>(x))) -#endif - ; - } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - tanh(IntType x) { - return sprout::math::detail::tanh(static_cast(x)); - } } // namespace detail - - using sprout::math::detail::tanh; + // + // tanh + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + tanh(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? FloatType(1) + : x == -sprout::numeric_limits::infinity() ? FloatType(-1) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_tanh(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::tanh_impl(static_cast::type>(x))) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + tanh(IntType x) { + return sprout::math::tanh(static_cast(x)); + } } // namespace math using sprout::math::tanh; diff --git a/sprout/math/tgamma.hpp b/sprout/math/tgamma.hpp index b9996ff1..e3e54f28 100644 --- a/sprout/math/tgamma.hpp +++ b/sprout/math/tgamma.hpp @@ -26,6 +26,21 @@ namespace sprout { namespace math { namespace detail { +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + inline SPROUT_CONSTEXPR float + builtin_tgamma(float x) { + return __builtin_tgammaf(x); + } + inline SPROUT_CONSTEXPR double + builtin_tgamma(double x) { + return __builtin_tgamma(x); + } + inline SPROUT_CONSTEXPR long double + builtin_tgamma(long double x) { + return __builtin_tgammal(x); + } +#endif + template inline SPROUT_CONSTEXPR T tgamma_impl_y(T w) { @@ -107,42 +122,42 @@ namespace sprout { ) ); } - - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - tgamma(FloatType x) { - return sprout::math::isnan(x) ? x - : x == 0 ? sprout::math::copysign(sprout::numeric_limits::infinity(), x) - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::quiet_NaN() - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x < 0 && sprout::math::is_integer(x) ? sprout::numeric_limits::quiet_NaN() -#if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::tgamma(x) -#else - : static_cast(sprout::math::detail::tgamma_impl(static_cast::type>(x))) -#endif - ; - } - - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR double - tgamma(IntType x) { - return sprout::math::detail::tgamma(static_cast(x)); - } } // namespace detail // + // tgamma + // // issue: // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] // tgamma(-0) returns - . // # returns + . ( same as tgamma(+0) ) // - using sprout::math::detail::tgamma; + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + tgamma(FloatType x) { + return sprout::math::isnan(x) ? x + : x == 0 ? sprout::math::copysign(sprout::numeric_limits::infinity(), x) + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::quiet_NaN() + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x < 0 && sprout::math::is_integer(x) ? sprout::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_tgamma(x) +#else + : static_cast(sprout::math::detail::tgamma_impl(static_cast::type>(x))) +#endif + ; + } + + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + tgamma(IntType x) { + return sprout::math::tgamma(static_cast(x)); + } } // namespace math using sprout::math::tgamma; diff --git a/sprout/math/trunc.hpp b/sprout/math/trunc.hpp index 575ce720..a7545a8f 100644 --- a/sprout/math/trunc.hpp +++ b/sprout/math/trunc.hpp @@ -20,37 +20,52 @@ namespace sprout { namespace math { namespace detail { - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > - inline SPROUT_CONSTEXPR FloatType - trunc(FloatType x) { - return sprout::math::isnan(x) ? x - : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() - : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() #if SPROUT_USE_BUILTIN_CMATH_FUNCTION - : std::trunc(x) -#else - : x == 0 ? x - : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x - ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("trunc: large float rounding."), x) - : x < 0 ? -static_cast(static_cast(-x)) - : static_cast(static_cast(x)) -#endif - ; + inline SPROUT_CONSTEXPR float + builtin_trunc(float x) { + return __builtin_truncf(x); } - template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler - > inline SPROUT_CONSTEXPR double - trunc(IntType x) { - return sprout::math::detail::trunc(static_cast(x)); + builtin_trunc(double x) { + return __builtin_trunc(x); } + inline SPROUT_CONSTEXPR long double + builtin_trunc(long double x) { + return __builtin_truncl(x); + } +#endif } // namespace detail - - using NS_SPROUT_MATH_DETAIL::trunc; + // + // trunc + // + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + trunc(FloatType x) { + return sprout::math::isnan(x) ? x + : x == sprout::numeric_limits::infinity() ? sprout::numeric_limits::infinity() + : x == -sprout::numeric_limits::infinity() ? -sprout::numeric_limits::infinity() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : sprout::math::detail::builtin_trunc(x) +#else + : x == 0 ? x + : sprout::numeric_limits::max() < x || sprout::numeric_limits::max() < -x + ? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("trunc: large float rounding."), x) + : x < 0 ? -static_cast(static_cast(-x)) + : static_cast(static_cast(x)) +#endif + ; + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + trunc(IntType x) { + return sprout::math::trunc(static_cast(x)); + } } // namespace math using sprout::math::trunc;