mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2025-06-07 00:51:32 +00:00
fix: math functions (support for inferior C++14 standard)
add C++14 constexpr modifying algorithms
This commit is contained in:
parent
58cff54e0d
commit
c58c9cc0fc
106 changed files with 3465 additions and 2144 deletions
BIN
example/darkroom/two_spheres-8192x8192.png
Normal file
BIN
example/darkroom/two_spheres-8192x8192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 MiB |
|
@ -14,9 +14,9 @@ namespace sprout {
|
|||
//
|
||||
// 25.3.6 Fill
|
||||
//
|
||||
template<typename ForwrdIterator, typename T>
|
||||
template<typename ForwardIterator, typename T>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <sprout/container/functions.hpp>
|
||||
#include <sprout/iterator/operation.hpp>
|
||||
#include <sprout/iterator/remove_iterator.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/algorithm/fixed/result_of.hpp>
|
||||
#include <sprout/pit/pit.hpp>
|
||||
#include <sprout/detail/container_complate.hpp>
|
||||
|
@ -93,7 +95,20 @@ namespace sprout {
|
|||
}
|
||||
} // namespace fixed
|
||||
|
||||
using sprout::fixed::remove_copy;
|
||||
template<
|
||||
typename InputIterator, typename Result, typename T,
|
||||
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
remove_copy(InputIterator first, InputIterator last, Result const& result, T const& value) {
|
||||
return sprout::fixed::remove_copy(first, last, result, value);
|
||||
}
|
||||
|
||||
template<typename Result, typename InputIterator, typename T>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
remove_copy(InputIterator first, InputIterator last, T const& value) {
|
||||
return sprout::fixed::remove_copy<Result>(first, last, value);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_HPP
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <sprout/container/functions.hpp>
|
||||
#include <sprout/iterator/operation.hpp>
|
||||
#include <sprout/iterator/remove_if_iterator.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/algorithm/fixed/result_of.hpp>
|
||||
#include <sprout/pit/pit.hpp>
|
||||
#include <sprout/detail/container_complate.hpp>
|
||||
|
@ -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<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
remove_copy_if(InputIterator first, InputIterator last, Result const& result, Predicate pred) {
|
||||
return sprout::fixed::remove_copy_if(first, last, result, pred);
|
||||
}
|
||||
|
||||
template<typename Result, typename InputIterator, typename Predicate>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
remove_copy_if(InputIterator first, InputIterator last, Predicate pred) {
|
||||
return sprout::fixed::remove_copy_if<Result>(first, last, pred);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_IF_HPP
|
||||
|
|
|
@ -137,7 +137,20 @@ namespace sprout {
|
|||
}
|
||||
} // namespace fixed
|
||||
|
||||
using sprout::fixed::reverse_copy;
|
||||
template<
|
||||
typename BidirectionalIterator, typename Result,
|
||||
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
reverse_copy(BidirectionalIterator first, BidirectionalIterator last, Result const& result) {
|
||||
return sprout::fixed::reverse_copy(first, last, result);
|
||||
}
|
||||
|
||||
template<typename Result, typename BidirectionalIterator>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
reverse_copy(BidirectionalIterator first, BidirectionalIterator last) {
|
||||
return sprout::fixed::reverse_copy<Result>(first, last);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REVERSE_COPY_HPP
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <sprout/container/indexes.hpp>
|
||||
#include <sprout/iterator/operation.hpp>
|
||||
#include <sprout/iterator/joint_iterator.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/algorithm/fixed/result_of.hpp>
|
||||
#include <sprout/pit/pit.hpp>
|
||||
#include <sprout/detail/container_complate.hpp>
|
||||
|
@ -178,7 +180,20 @@ namespace sprout {
|
|||
}
|
||||
} // namespace fixed
|
||||
|
||||
using sprout::fixed::rotate_copy;
|
||||
template<
|
||||
typename ForwardIterator, typename Result,
|
||||
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Result const& result) {
|
||||
return sprout::fixed::rotate_copy(first, middle, last, result);
|
||||
}
|
||||
|
||||
template<typename Result, typename ForwardIterator>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last) {
|
||||
return sprout::fixed::rotate_copy<Result>(first, middle, last);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_ROTATE_COPY_HPP
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <sprout/container/functions.hpp>
|
||||
#include <sprout/iterator/operation.hpp>
|
||||
#include <sprout/iterator/unique_iterator.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/algorithm/fixed/result_of.hpp>
|
||||
#include <sprout/pit/pit.hpp>
|
||||
#include <sprout/detail/container_complate.hpp>
|
||||
|
@ -178,7 +180,38 @@ namespace sprout {
|
|||
}
|
||||
} // namespace fixed
|
||||
|
||||
using sprout::fixed::unique_copy;
|
||||
template<
|
||||
typename InputIterator, typename Result,
|
||||
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
unique_copy(InputIterator first, InputIterator last, Result const& result) {
|
||||
return sprout::fixed::unique_copy(first, last, result);
|
||||
}
|
||||
|
||||
template<typename Result, typename InputIterator>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
unique_copy(InputIterator first, InputIterator last) {
|
||||
return sprout::fixed::unique_copy<Result>(first, last);
|
||||
}
|
||||
|
||||
template<
|
||||
typename InputIterator, typename Result, typename BinaryPredicate,
|
||||
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::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<!sprout::is_output_iterator<BinaryPredicate>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
|
||||
unique_copy(InputIterator first, InputIterator last, BinaryPredicate pred) {
|
||||
return sprout::fixed::unique_copy<Result>(first, last, pred);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_UNIQUE_COPY_HPP
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
|||
//
|
||||
// 25.3.7 Generate
|
||||
//
|
||||
template<typename ForwrdIterator, typename Generator>
|
||||
template<typename ForwardIterator, typename Generator>
|
||||
inline SPROUT_CXX14_CONSTEXPR void
|
||||
generate(ForwrdIterator first, ForwrdIterator last, Generator gen) {
|
||||
generate(ForwardIterator first, ForwardIterator last, Generator gen) {
|
||||
while (first != last) {
|
||||
*first++ = gen();
|
||||
}
|
||||
|
|
|
@ -40,11 +40,12 @@
|
|||
#include <sprout/algorithm/reverse_copy.hpp>
|
||||
#include <sprout/algorithm/rotate.hpp>
|
||||
#include <sprout/algorithm/rotate_copy.hpp>
|
||||
#include <sprout/algorithm/random_shuffle.hpp>
|
||||
#include <sprout/algorithm/shuffle.hpp>
|
||||
#include <sprout/algorithm/shuffle_result.hpp>
|
||||
#include <sprout/algorithm/partition.hpp>
|
||||
#include <sprout/algorithm/partition_copy.hpp>
|
||||
#include <sprout/algorithm/stable_partition.hpp>
|
||||
#include <sprout/algorithm/partition_copy.hpp>
|
||||
#include <sprout/algorithm/stable_partition_copy.hpp>
|
||||
#include <sprout/algorithm/sort.hpp>
|
||||
#include <sprout/algorithm/stable_sort.hpp>
|
||||
|
|
|
@ -9,6 +9,28 @@
|
|||
#define SPROUT_ALGORITHM_PARTITION_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/algorithm/iter_swap.hpp>
|
||||
#include <sprout/algorithm/find_if.hpp>
|
||||
#include <sprout/algorithm/find_if_not.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.13 Partitions
|
||||
//
|
||||
template<typename ForwardIterator, typename Predicate>
|
||||
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 <sprout/algorithm/fixed/partition.hpp>
|
||||
#include <sprout/algorithm/fit/partition.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,17 @@
|
|||
#define SPROUT_ALGORITHM_PARTITION_COPY_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/utility/pair.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.13 Partitions
|
||||
//
|
||||
template<typename InputIterator, typename OutputIterator1, typename OutputIterator2, typename Predicate>
|
||||
inline SPROUT_CXX14_CONSTEXPR sprout::pair<OutputIterator1, OutputIterator2>
|
||||
partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); // !!!
|
||||
} // namespace sprout
|
||||
|
||||
#include <sprout/algorithm/fixed/partition_copy.hpp>
|
||||
#include <sprout/algorithm/fit/partition_copy.hpp>
|
||||
|
||||
|
|
30
sprout/algorithm/random_shuffle.hpp
Normal file
30
sprout/algorithm/random_shuffle.hpp
Normal file
|
@ -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 <sprout/config.hpp>
|
||||
#include <sprout/algorithm/iter_swap.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.12 Random shuffle
|
||||
//
|
||||
template<typename RandomAccessIterator, typename RandomNumberGenerator>
|
||||
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
|
|
@ -9,6 +9,25 @@
|
|||
#define SPROUT_ALGORITHM_REMOVE_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/utility/move.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.8 Remove
|
||||
//
|
||||
template<typename ForwardIterator, typename T>
|
||||
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 <sprout/algorithm/fixed/remove.hpp>
|
||||
#include <sprout/algorithm/fit/remove.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,28 @@
|
|||
#define SPROUT_ALGORITHM_REMOVE_COPY_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.8 Remove
|
||||
//
|
||||
template<
|
||||
typename InputIterator, typename OutputIterator, typename T,
|
||||
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::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 <sprout/algorithm/fixed/remove_copy.hpp>
|
||||
#include <sprout/algorithm/fit/remove_copy.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,28 @@
|
|||
#define SPROUT_ALGORITHM_REMOVE_COPY_IF_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.8 Remove
|
||||
//
|
||||
template<
|
||||
typename InputIterator, typename OutputIterator, typename Predicate,
|
||||
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::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 <sprout/algorithm/fixed/remove_copy_if.hpp>
|
||||
#include <sprout/algorithm/fit/remove_copy_if.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,25 @@
|
|||
#define SPROUT_ALGORITHM_REMOVE_IF_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/utility/move.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.8 Remove
|
||||
//
|
||||
template<typename ForwardIterator, typename Predicate>
|
||||
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 <sprout/algorithm/fixed/remove_if.hpp>
|
||||
#include <sprout/algorithm/fit/remove_if.hpp>
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
|||
//
|
||||
// 25.3.5 Replace
|
||||
//
|
||||
template<typename ForwrdIterator, typename T>
|
||||
template<typename ForwardIterator, typename T>
|
||||
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;
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
|||
//
|
||||
// 25.3.5 Replace
|
||||
//
|
||||
template<typename ForwrdIterator, typename Predicate, typename T>
|
||||
template<typename ForwardIterator, typename Predicate, typename T>
|
||||
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;
|
||||
|
|
|
@ -9,6 +9,21 @@
|
|||
#define SPROUT_ALGORITHM_REVERSE_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/algorithm/iter_swap.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.10 Reverse
|
||||
//
|
||||
template<typename BidirectionalIterator>
|
||||
inline SPROUT_CXX14_CONSTEXPR void
|
||||
reverse(BidirectionalIterator first, BidirectionalIterator last) {
|
||||
for (; first != last && first != --last; ++first) {
|
||||
sprout::iter_swap(first, last);
|
||||
}
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#include <sprout/algorithm/fixed/reverse.hpp>
|
||||
#include <sprout/algorithm/fit/reverse.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,26 @@
|
|||
#define SPROUT_ALGORITHM_REVERSE_COPY_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.10 Reverse
|
||||
//
|
||||
template<
|
||||
typename BidirectionalIterator, typename OutputIterator,
|
||||
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::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 <sprout/algorithm/fixed/reverse_copy.hpp>
|
||||
#include <sprout/algorithm/fit/reverse_copy.hpp>
|
||||
|
||||
|
|
|
@ -8,7 +8,53 @@
|
|||
#ifndef SPROUT_ALGORITHM_ROTATE_HPP
|
||||
#define SPROUT_ALGORITHM_ROTATE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/algorithm/iter_swap.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.11 Rotate
|
||||
//
|
||||
template<typename ForwardIterator>
|
||||
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 <sprout/algorithm/fixed/rotate.hpp>
|
||||
#include <sprout/algorithm/fit/rotate.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,24 @@
|
|||
#define SPROUT_ALGORITHM_ROTATE_COPY_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/algorithm/copy.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.11 Rotate
|
||||
//
|
||||
template<
|
||||
typename ForwardIterator, typename OutputIterator,
|
||||
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::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 <sprout/algorithm/fixed/rotate_copy.hpp>
|
||||
#include <sprout/algorithm/fit/rotate_copy.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,16 @@
|
|||
#define SPROUT_ALGORITHM_SHUFFLE_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.12 Random shuffle
|
||||
//
|
||||
template<typename RandomAccessIterator, typename UniformRandomNumberGenerator>
|
||||
inline SPROUT_CXX14_CONSTEXPR void
|
||||
shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& g); // !!!
|
||||
} // namespace sprout
|
||||
|
||||
#include <sprout/algorithm/fixed/shuffle.hpp>
|
||||
#include <sprout/algorithm/fit/shuffle.hpp>
|
||||
|
||||
|
|
|
@ -9,6 +9,17 @@
|
|||
#define SPROUT_ALGORITHM_STABLE_PARTITION_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.13 Partitions
|
||||
//
|
||||
template<typename BidirectionalIterator, typename Predicate>
|
||||
inline SPROUT_CXX14_CONSTEXPR BidirectionalIterator
|
||||
stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); // !!!
|
||||
} // namespace sprout
|
||||
|
||||
#include <sprout/algorithm/fixed/stable_partition.hpp>
|
||||
#include <sprout/algorithm/fit/stable_partition.hpp>
|
||||
|
||||
|
|
|
@ -8,7 +8,50 @@
|
|||
#ifndef SPROUT_ALGORITHM_UNIQUE_HPP
|
||||
#define SPROUT_ALGORITHM_UNIQUE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/utility/move.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.9 Unique
|
||||
//
|
||||
template<typename ForwardIterator>
|
||||
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
|
||||
unique(ForwardIterator first, ForwardIterator last) {
|
||||
if (first == last) {
|
||||
return first;
|
||||
}
|
||||
ForwardIterator result = first;
|
||||
typename std::iterator_traits<ForwardIterator>::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<typename ForwardIterator, typename BinaryPredicate>
|
||||
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
|
||||
unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) {
|
||||
if (first == last) {
|
||||
return first;
|
||||
}
|
||||
ForwardIterator result = first;
|
||||
typename std::iterator_traits<ForwardIterator>::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 <sprout/algorithm/fixed/unique.hpp>
|
||||
#include <sprout/algorithm/fit/unique.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 <iterator>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// 25.3.9 Unique
|
||||
//
|
||||
template<
|
||||
typename InputIterator, typename OutputIterator,
|
||||
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::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<InputIterator>::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<sprout::is_output_iterator<OutputIterator>::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<InputIterator>::value_type value = *first++;
|
||||
*result++ = value;
|
||||
for (; first != last; ++first) {
|
||||
if (!pred(value, *first)) {
|
||||
value = *first;
|
||||
*result++ = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
#include <sprout/algorithm/fixed/unique_copy.hpp>
|
||||
#include <sprout/algorithm/fit/unique_copy.hpp>
|
||||
|
||||
|
|
|
@ -25,6 +25,15 @@ namespace sprout {
|
|||
make_array(Types&&... args) {
|
||||
return sprout::array<T, sizeof...(Types)>{{T(sprout::forward<Types>(args))...}};
|
||||
}
|
||||
// template<typename... Types>
|
||||
// inline SPROUT_CONSTEXPR sprout::array<typename sprout::common_decay<Types&&...>::type, sizeof...(Types)>
|
||||
// make_array(Types&&... args) {
|
||||
// typedef sprout::array<
|
||||
// typename sprout::common_decay<Types&&...>::type,
|
||||
// sizeof...(Types)
|
||||
// > type;
|
||||
// return type{{typename sprout::common_decay<Types&&...>::type(sprout::forward<Types>(args))...}};
|
||||
// }
|
||||
|
||||
//
|
||||
// make_common_array
|
||||
|
|
|
@ -16,24 +16,16 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::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
|
||||
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
acos_impl(T x) {
|
||||
return sprout::math::half_pi<T>() - sprout::math::asin(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::acos(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::acos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
acos(IntType x) {
|
||||
return sprout::math::detail::acos(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::acos;
|
||||
//
|
||||
// acos
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_acos(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::acos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
acos(IntType x) {
|
||||
return sprout::math::acos(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::acos;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
acosh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x < 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::acosh(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::acosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
acosh(IntType x) {
|
||||
return sprout::math::detail::acosh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::acosh;
|
||||
//
|
||||
// acosh
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
acosh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x < 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_acosh(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::acosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
acosh(IntType x) {
|
||||
return sprout::math::acosh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::acosh;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::asin(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(
|
||||
x < 0 ? -sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
|
||||
: sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
asin(IntType x) {
|
||||
return sprout::math::detail::asin(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::asin;
|
||||
//
|
||||
// asin
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_asin(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(
|
||||
x < 0 ? -sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
|
||||
: sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
asin(IntType x) {
|
||||
return sprout::math::asin(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::asin;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
asinh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::asinh(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::asinh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
asinh(IntType x) {
|
||||
return sprout::math::detail::asinh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::asinh;
|
||||
//
|
||||
// asinh
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
asinh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_asinh(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::asinh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
asinh(IntType x) {
|
||||
return sprout::math::asinh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::asinh;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
atan(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::atan(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(
|
||||
x < 0 ? -sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
|
||||
: sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
atan(IntType x) {
|
||||
return sprout::math::detail::atan(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::atan;
|
||||
//
|
||||
// atan
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
atan(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_atan(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(
|
||||
x < 0 ? -sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
|
||||
: sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
atan(IntType x) {
|
||||
return sprout::math::atan(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::atan;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::three_quarters_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::three_quarters_pi<FloatType>()
|
||||
: sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity()
|
||||
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::quarter_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::quarter_pi<FloatType>()
|
||||
: FloatType(0) * y
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::atan2(y, x)
|
||||
#else
|
||||
: y == 0
|
||||
? x < 0 ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: x > 0 ? FloatType(0) * y
|
||||
: sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: FloatType(0) * y
|
||||
: x == 0
|
||||
? y < 0 ? -sprout::math::half_pi<FloatType>()
|
||||
: sprout::math::half_pi<FloatType>()
|
||||
: static_cast<FloatType>(
|
||||
sprout::math::detail::atan2_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)
|
||||
)
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
atan2(ArithmeticType1 y, ArithmeticType2 x) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::atan2(static_cast<type>(y), static_cast<type>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// atan2
|
||||
//
|
||||
// issue:
|
||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||
// atan2(<28>}0, -0) returns <20>}ƒÎ .
|
||||
|
@ -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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::three_quarters_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::three_quarters_pi<FloatType>()
|
||||
: sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity()
|
||||
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::quarter_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::quarter_pi<FloatType>()
|
||||
: FloatType(0) * y
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_atan2(y, x)
|
||||
#else
|
||||
: y == 0
|
||||
? x < 0 ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: x > 0 ? FloatType(0) * y
|
||||
: sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
|
||||
: FloatType(0) * y
|
||||
: x == 0
|
||||
? y < 0 ? -sprout::math::half_pi<FloatType>()
|
||||
: sprout::math::half_pi<FloatType>()
|
||||
: static_cast<FloatType>(
|
||||
sprout::math::detail::atan2_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)
|
||||
)
|
||||
)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
atan2(ArithmeticType1 y, ArithmeticType2 x) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::atan2(static_cast<type>(y), static_cast<type>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::atan2;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
atanh_impl(T x) {
|
||||
return sprout::math::log((1 + x) / (1 - x)) / 2;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
atanh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 1 ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::math::fabs(x) > 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::atanh(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::atanh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
atanh(IntType x) {
|
||||
return sprout::math::detail::atanh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::atanh;
|
||||
//
|
||||
// atanh
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
atanh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 1 ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::math::fabs(x) > 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_atanh(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::atanh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
atanh(IntType x) {
|
||||
return sprout::math::atanh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::atanh;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
cbrt_impl(T x) {
|
||||
|
@ -28,36 +43,36 @@ namespace sprout {
|
|||
: sprout::pow(x, sprout::math::third<T>())
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cbrt(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::cbrt(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::cbrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cbrt(IntType x) {
|
||||
return sprout::math::detail::cbrt(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// cbrt
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cbrt(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_cbrt(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::cbrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
using sprout::math::detail::cbrt;
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cbrt(IntType x) {
|
||||
return sprout::math::cbrt(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::cbrt;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<T>(static_cast<std::uintmax_t>(x)))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
ceil(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::ceil(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::ceil_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
ceil(IntType x) {
|
||||
return sprout::math::detail::ceil(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::ceil;
|
||||
//
|
||||
// ceil
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
ceil(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_ceil(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::ceil_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
ceil(IntType x) {
|
||||
return sprout::math::ceil(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ceil;
|
||||
|
|
|
@ -20,38 +20,24 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
copysign(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::copysign(static_cast<type>(x), static_cast<type>(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(<28>}x, -0) returns -x for |x| is not 0 .
|
||||
|
@ -59,7 +45,42 @@ namespace sprout {
|
|||
// copysign(<28>}x, -NaN) returns -x for |x| is not NaN .
|
||||
// # returns +x . ( same as copysign(<28>}x, +NaN) )
|
||||
//
|
||||
using NS_SPROUT_MATH_DETAIL::copysign;
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
copysign(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::copysign(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::copysign;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<T>()));
|
||||
// }
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cos(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::cos(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::cos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cos(IntType x) {
|
||||
return sprout::math::detail::cos(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::cos;
|
||||
//
|
||||
// cos
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cos(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_cos(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::cos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cos(IntType x) {
|
||||
return sprout::math::cos(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::cos;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cosh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::cosh(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::cosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cosh(IntType x) {
|
||||
return sprout::math::detail::cosh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::cosh;
|
||||
//
|
||||
// cosh
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
cosh(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_cosh(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::cosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
cosh(IntType x) {
|
||||
return sprout::math::cosh(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::cosh;
|
||||
|
|
|
@ -14,12 +14,6 @@
|
|||
# include <cmath>
|
||||
#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
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
erf(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(1)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::erf(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
erf(IntType x) {
|
||||
return sprout::math::detail::erf(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::erf;
|
||||
//
|
||||
// erf
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
erf(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(1)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_erf(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
erf(IntType x) {
|
||||
return sprout::math::erf(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::erf;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
erfc_impl(T x) {
|
||||
return T(1) - sprout::math::erf(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
erfc(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(2)
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::erfc(x)
|
||||
#else
|
||||
: static_cast<FloatType>(sprout::math::detail::erfc_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
erfc(IntType x) {
|
||||
return sprout::math::detail::erfc(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::erfc;
|
||||
//
|
||||
// erfc
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
erfc(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(2)
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_erfc(x)
|
||||
#else
|
||||
: static_cast<FloatType>(sprout::math::detail::erfc_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
erfc(IntType x) {
|
||||
return sprout::math::erfc(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::erfc;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<T>() / 2 + 1)
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::exp(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp(IntType x) {
|
||||
return sprout::math::detail::exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::exp;
|
||||
//
|
||||
// exp
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_exp(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp(IntType x) {
|
||||
return sprout::math::exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::exp;
|
||||
|
|
|
@ -26,31 +26,31 @@ namespace sprout {
|
|||
exp10_impl(T x) {
|
||||
return sprout::math::exp(x * sprout::math::ln_ten<T>());
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp10(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp10(IntType x) {
|
||||
return sprout::math::detail::exp10(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::exp10;
|
||||
//
|
||||
// exp10
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp10(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp10(IntType x) {
|
||||
return sprout::math::exp10(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::exp10;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
exp2_impl(T x) {
|
||||
return sprout::math::exp(x * sprout::math::ln_two<T>());
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::exp2(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp2(IntType x) {
|
||||
return sprout::math::detail::exp2(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::exp2;
|
||||
//
|
||||
// exp2
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
exp2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_exp2(x)
|
||||
#else
|
||||
: x == 0 ? FloatType(1)
|
||||
: static_cast<FloatType>(sprout::math::detail::exp2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
exp2(IntType x) {
|
||||
return sprout::math::exp2(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::exp2;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
expm1_impl(T x) {
|
||||
return sprout::math::exp(x) - T(1);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
expm1(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::expm1(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::expm1_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
expm1(IntType x) {
|
||||
return sprout::math::detail::expm1(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::expm1;
|
||||
//
|
||||
// expm1
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
expm1(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_expm1(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::expm1_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
expm1(IntType x) {
|
||||
return sprout::math::expm1(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::expm1;
|
||||
|
|
|
@ -18,28 +18,48 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
fabs(FloatType x) {
|
||||
return sprout::math::isnan(x) ? sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
fabs(IntType x) {
|
||||
return sprout::math::detail::fabs(static_cast<double>(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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: x == 0 ? FloatType(0)
|
||||
: sprout::math::copysign(x, FloatType(0))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
fabs(IntType x) {
|
||||
return sprout::math::fabs(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fabs;
|
||||
|
|
|
@ -19,40 +19,55 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fdim(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fdim(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::fdim;
|
||||
//
|
||||
// fdim
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fdim(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::fdim(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fdim;
|
||||
|
|
|
@ -18,30 +18,29 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
||||
: sprout::math::ilogb2(x) + 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float2_exponent(IntType x) {
|
||||
return sprout::math::detail::float2_exponent(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_exponent;
|
||||
//
|
||||
// float2_exponent
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
||||
: sprout::math::ilogb2(x) + 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float2_exponent(IntType x) {
|
||||
return sprout::math::float2_exponent(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_exponent;
|
||||
|
|
|
@ -27,32 +27,32 @@ namespace sprout {
|
|||
typedef sprout::pair<T, int> type;
|
||||
return type(x / sprout::detail::pow_n(T(2), exp), exp);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float2_sig_exp(FloatType x) {
|
||||
typedef sprout::pair<FloatType, int> type;
|
||||
return sprout::math::isnan(x) ? type(x, 0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float2_sig_exp(IntType x) {
|
||||
return sprout::math::detail::float2_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_sig_exp;
|
||||
//
|
||||
// float2_sig_exp
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float2_sig_exp(FloatType x) {
|
||||
typedef sprout::pair<FloatType, int> type;
|
||||
return sprout::math::isnan(x) ? type(x, 0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float2_sig_exp(IntType x) {
|
||||
return sprout::math::float2_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_sig_exp;
|
||||
|
|
|
@ -19,31 +19,30 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float2_significand(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float2_significand(IntType x) {
|
||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_significand;
|
||||
//
|
||||
// float2_significand
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float2_significand(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float2_significand(IntType x) {
|
||||
return sprout::math::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_significand;
|
||||
|
|
|
@ -18,30 +18,29 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
||||
: sprout::math::ilogb(x) + 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float_exponent(IntType x) {
|
||||
return sprout::math::detail::float_exponent(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_exponent;
|
||||
//
|
||||
// float_exponent
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
||||
: sprout::math::ilogb(x) + 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float_exponent(IntType x) {
|
||||
return sprout::math::float_exponent(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_exponent;
|
||||
|
|
|
@ -27,32 +27,32 @@ namespace sprout {
|
|||
typedef sprout::pair<T, int> type;
|
||||
return type(x / sprout::detail::pow_n(T(sprout::numeric_limits<T>::radix), exp), exp);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float_sig_exp(FloatType x) {
|
||||
typedef sprout::pair<FloatType, int> type;
|
||||
return sprout::math::isnan(x) ? type(x, 0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float_sig_exp(IntType x) {
|
||||
return sprout::math::detail::float_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_sig_exp;
|
||||
//
|
||||
// float_sig_exp
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float_sig_exp(FloatType x) {
|
||||
typedef sprout::pair<FloatType, int> type;
|
||||
return sprout::math::isnan(x) ? type(x, 0)
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float_sig_exp(IntType x) {
|
||||
return sprout::math::float_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_sig_exp;
|
||||
|
|
|
@ -19,31 +19,30 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float_significand(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: x / sprout::detail::pow_n(FloatType(sprout::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float_significand(IntType x) {
|
||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_significand;
|
||||
//
|
||||
// float_significand
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float_significand(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: x / sprout::detail::pow_n(FloatType(sprout::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float_significand(IntType x) {
|
||||
return sprout::math::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_significand;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
floor_impl_1(T x, T x0) {
|
||||
|
@ -36,37 +51,37 @@ namespace sprout {
|
|||
: static_cast<T>(static_cast<std::uintmax_t>(x))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
floor(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::floor(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::floor_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
floor(IntType x) {
|
||||
return sprout::math::detail::floor(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::floor;
|
||||
//
|
||||
// floor
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
floor(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_floor(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::floor_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
floor(IntType x) {
|
||||
return sprout::math::floor(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::floor;
|
||||
|
|
|
@ -21,48 +21,63 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits<FloatType>::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<FloatType>::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<ArithmeticType1>::value
|
||||
&& std::is_arithmetic<ArithmeticType2>::value
|
||||
&& std::is_arithmetic<ArithmeticType3>::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<type>(x), static_cast<type>(y), static_cast<type>(z));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::fma;
|
||||
//
|
||||
// fma
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits<FloatType>::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<FloatType>::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<ArithmeticType1>::value
|
||||
&& std::is_arithmetic<ArithmeticType2>::value
|
||||
&& std::is_arithmetic<ArithmeticType3>::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<type>(x), static_cast<type>(y), static_cast<type>(z));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fma;
|
||||
|
|
|
@ -19,41 +19,56 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? y
|
||||
: y == sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmax(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fmax(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::fmax;
|
||||
//
|
||||
// fmax
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? y
|
||||
: y == sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmax(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::fmax(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fmax;
|
||||
|
|
|
@ -19,41 +19,56 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? y
|
||||
: x == sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmin(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fmin(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::fmin;
|
||||
//
|
||||
// fmin
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity() ? y
|
||||
: x == sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmin(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::fmin(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fmin;
|
||||
|
|
|
@ -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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() || y == 0
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == 0 ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::fmod_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmod(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fmod(static_cast<type>(x), static_cast<type>(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<std::is_floating_point<FloatType>::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<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() || y == 0
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == 0 ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::fmod_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmod(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::fmod(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fmod;
|
||||
|
|
|
@ -21,22 +21,45 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
fpclassify(IntType x) {
|
||||
return x ? FP_NORMAL
|
||||
: FP_ZERO
|
||||
;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fpclassify;
|
||||
|
|
|
@ -32,26 +32,26 @@ namespace sprout {
|
|||
: type(sprout::math::copysign(x - ipart, x), ipart)
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, FloatType>
|
||||
frac_int(FloatType x) {
|
||||
return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x));
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, double>
|
||||
frac_int(IntType x) {
|
||||
return sprout::math::detail::frac_int(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::frac_int;
|
||||
//
|
||||
// frac_int
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, FloatType>
|
||||
frac_int(FloatType x) {
|
||||
return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x));
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, double>
|
||||
frac_int(IntType x) {
|
||||
return sprout::math::frac_int(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::frac_int;
|
||||
|
|
|
@ -27,30 +27,30 @@ namespace sprout {
|
|||
: sprout::math::copysign(x - ipart, x)
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
fractional_part(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
fractional_part(IntType x) {
|
||||
return sprout::math::detail::fractional_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::fractional_part;
|
||||
//
|
||||
// fractional_part
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
fractional_part(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
fractional_part(IntType x) {
|
||||
return sprout::math::fractional_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::fractional_part;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
hypot(FloatType x, FloatType y) {
|
||||
return y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::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<FloatType>(sprout::math::detail::hypot_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
hypot(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::hypot(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// hypot
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
hypot(FloatType x, FloatType y) {
|
||||
return y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::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<FloatType>(sprout::math::detail::hypot_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
using sprout::math::detail::hypot;
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
hypot(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::hypot(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::hypot;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil_impl(FloatType x) {
|
||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
|||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x))
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// iceil
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x))
|
||||
;
|
||||
}
|
||||
#else
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::iceil_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(IntType x) {
|
||||
return sprout::math::detail::iceil<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::iceil;
|
||||
//
|
||||
// iceil
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::iceil_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(IntType x) {
|
||||
return sprout::math::iceil<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::iceil;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor_impl(FloatType x) {
|
||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
|||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x))
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// ifloor
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x))
|
||||
;
|
||||
}
|
||||
#else
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::ifloor_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(IntType x) {
|
||||
return sprout::math::detail::ifloor<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::ifloor;
|
||||
//
|
||||
// ifloor
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::ifloor_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(IntType x) {
|
||||
return sprout::math::ifloor<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ifloor;
|
||||
|
|
|
@ -22,33 +22,48 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<int>(sprout::math::logb(x))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb(IntType x) {
|
||||
return sprout::math::detail::ilogb(static_cast<double>(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<std::is_floating_point<FloatType>::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<int>(sprout::math::logb(x))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb(IntType x) {
|
||||
return sprout::math::ilogb(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ilogb;
|
||||
|
|
|
@ -25,49 +25,45 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(FloatType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(FloatType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
#else
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<int>(sprout::math::logb2(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::detail::ilogb2(static_cast<double>(x));
|
||||
}
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<int>(sprout::math::logb2(x))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::ilogb2(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::ilogb2;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ilogb2;
|
||||
|
|
|
@ -18,31 +18,30 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
integer_part(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: sprout::math::trunc(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
integer_part(IntType x) {
|
||||
return sprout::math::detail::integer_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::integer_part;
|
||||
//
|
||||
// integer_part
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
integer_part(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == 0 ? x
|
||||
: sprout::math::trunc(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
integer_part(IntType x) {
|
||||
return sprout::math::integer_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::integer_part;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround_impl(FloatType x) {
|
||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
|||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::iround_impl<To>(sprout::math::round(x))
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// iround
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::iround_impl<To>(sprout::math::round(x))
|
||||
;
|
||||
}
|
||||
#else
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::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<To>(x))
|
||||
: sprout::math::detail::iround_impl_positive(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(IntType x) {
|
||||
return sprout::math::detail::iround(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::iround;
|
||||
//
|
||||
// iround
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::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<To>(x))
|
||||
: sprout::math::detail::iround_impl_positive(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(IntType x) {
|
||||
return sprout::math::iround(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::iround;
|
||||
|
|
|
@ -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<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::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;
|
||||
|
|
|
@ -22,20 +22,20 @@ namespace sprout {
|
|||
is_integer_unchecked(T x) {
|
||||
return x == sprout::math::trunc(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::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;
|
||||
|
|
|
@ -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<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::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;
|
||||
|
|
|
@ -18,19 +18,39 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
isfinite(IntType x) {
|
||||
return true;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::isfinite;
|
||||
|
|
|
@ -17,19 +17,40 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
isinf(FloatType x) {
|
||||
return x == sprout::numeric_limits<FloatType>::infinity()
|
||||
|| x == -sprout::numeric_limits<FloatType>::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<std::is_floating_point<FloatType>::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<FloatType>::infinity()
|
||||
|| x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
isinf(IntType x) {
|
||||
return false;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::isinf;
|
||||
|
|
|
@ -16,17 +16,39 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
isnan(IntType x) {
|
||||
return false;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::isnan;
|
||||
|
|
|
@ -19,20 +19,41 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
isnormal(IntType x) {
|
||||
return x != 0;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::isnormal;
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
//
|
||||
// issubnormal_or_zero
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
|
@ -29,21 +32,21 @@ namespace sprout {
|
|||
: x > -sprout::numeric_limits<double>::min()
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::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;
|
||||
|
|
|
@ -14,18 +14,25 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
iszero(FloatType x) {
|
||||
return x == 0;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
iszero(IntType x) {
|
||||
return x == 0;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::iszero;
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
namespace detail {
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc_impl(FloatType x) {
|
||||
|
@ -32,45 +32,49 @@ namespace sprout {
|
|||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::itrunc_impl<To>(sprout::math::trunc(x))
|
||||
;
|
||||
}
|
||||
#else
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(IntType x) {
|
||||
return sprout::math::detail::itrunc<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::itrunc;
|
||||
//
|
||||
// itrunc
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: sprout::math::detail::itrunc_impl<To>(sprout::math::trunc(x))
|
||||
;
|
||||
}
|
||||
#else
|
||||
//
|
||||
// itrunc
|
||||
//
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
||||
: x == 0 ? To(0)
|
||||
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(IntType x) {
|
||||
return sprout::math::itrunc<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::itrunc;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
ldexp(FloatType x, int exp) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::ldexp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
ldexp(IntType x, int exp) {
|
||||
return sprout::math::detail::ldexp(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using NS_SPROUT_MATH_DETAIL::ldexp;
|
||||
//
|
||||
// ldexp
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::ldexp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
ldexp(IntType x, int exp) {
|
||||
return sprout::math::ldexp(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ldexp;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::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<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
// : std::lgamma(x)
|
||||
//#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: x == 2 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
//#endif
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
lgamma(IntType x) {
|
||||
return sprout::math::detail::lgamma(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// lgamma
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
// : sprout::math::detail::builtin_lgamma(x)
|
||||
//#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: x == 2 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
//#endif
|
||||
;
|
||||
}
|
||||
|
||||
using sprout::math::detail::lgamma;
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
lgamma(IntType x) {
|
||||
return sprout::math::lgamma(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::lgamma;
|
||||
|
|
|
@ -20,35 +20,52 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long long>::min()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::llround(x)
|
||||
#else
|
||||
: sprout::math::iround<long long>(x);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::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<long long>(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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long long>::min()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_llround(x)
|
||||
#else
|
||||
: sprout::math::iround<long long>(x);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::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<long long>(x)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::llround;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::log(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log(IntType x) {
|
||||
return sprout::math::detail::log(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::log;
|
||||
//
|
||||
// log
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_log(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log(IntType x) {
|
||||
return sprout::math::log(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::log;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
log10_impl(T x) {
|
||||
return sprout::math::log(x) / sprout::math::ln_ten<T>();
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log10(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::log10(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log10(IntType x) {
|
||||
return sprout::math::detail::log10(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::log10;
|
||||
//
|
||||
// log10
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log10(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_log10(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log10(IntType x) {
|
||||
return sprout::math::log10(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::log10;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
log1p_impl(T x) {
|
||||
return sprout::math::log(T(1) + x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log1p(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < -1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::log1p(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::log1p_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log1p(IntType x) {
|
||||
return sprout::math::detail::log1p(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::log1p;
|
||||
//
|
||||
// log1p
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log1p(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < -1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_log1p(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::log1p_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log1p(IntType x) {
|
||||
return sprout::math::log1p(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::log1p;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
log2_impl(T x) {
|
||||
return sprout::math::log(x) / sprout::math::ln_two<T>();
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::log2(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log2(IntType x) {
|
||||
return sprout::math::detail::log2(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::log2;
|
||||
//
|
||||
// log2
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_log2(x)
|
||||
#else
|
||||
: x == 1 ? FloatType(0)
|
||||
: static_cast<FloatType>(sprout::math::detail::log2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
log2(IntType x) {
|
||||
return sprout::math::log2(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::log2;
|
||||
|
|
|
@ -28,34 +28,34 @@ namespace sprout {
|
|||
: sprout::math::log(y) / sprout::math::log(x)
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log_a(FloatType x, FloatType y) {
|
||||
return static_cast<FloatType>(sprout::math::detail::log_a_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
));
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
log_a(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::log_a(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// log_a
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
log_a(FloatType x, FloatType y) {
|
||||
return static_cast<FloatType>(sprout::math::detail::log_a_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
));
|
||||
}
|
||||
|
||||
using sprout::math::detail::log_a;
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
log_a(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::log_a(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::log_a;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<T>::radix), x)))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
} // namespace detail
|
||||
//
|
||||
// logb
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# if defined(__GNUC__)
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
# endif
|
||||
: std::logb(x)
|
||||
: sprout::math::detail::builtin_logb(x)
|
||||
#else
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: static_cast<FloatType>(sprout::math::detail::logb_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: static_cast<FloatType>(sprout::math::detail::logb_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb(IntType x) {
|
||||
return sprout::math::detail::logb(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::logb;
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb(IntType x) {
|
||||
return sprout::math::logb(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::logb;
|
||||
|
|
|
@ -28,25 +28,28 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
//
|
||||
// logb2
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
#else
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: static_cast<FloatType>(sprout::math::detail::logb2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::detail::logb2(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::logb2;
|
||||
//
|
||||
// logb2
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::numeric_limits<FloatType>::infinity()
|
||||
: static_cast<FloatType>(sprout::math::detail::logb2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::logb2(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::logb2;
|
||||
|
|
|
@ -20,35 +20,52 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long>::min()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::lround(x)
|
||||
#else
|
||||
: sprout::math::iround<long>(x);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::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<long>(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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround(FloatType x) {
|
||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long>::min()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_lround(x)
|
||||
#else
|
||||
: sprout::math::iround<long>(x);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::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<long>(x)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::lround;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<std::is_floating_point<FloatType>::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<FloatType>::infinity(), x)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::math::is_odd(y) ? x
|
||||
: FloatType(0)
|
||||
: x == -1 && (y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()) ? FloatType(1)
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::math::fabs(x) < 1 ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: FloatType(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::math::fabs(x) < 1 ? FloatType(0)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? y < 0
|
||||
? sprout::math::is_odd(y) ? -FloatType(0)
|
||||
: FloatType(0)
|
||||
: sprout::math::is_odd(y) ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity()
|
||||
? y < 0 ? FloatType(0)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::pow(x, y)
|
||||
#else
|
||||
: static_cast<FloatType>(sprout::math::detail::pow_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
pow(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::pow(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// pow
|
||||
//
|
||||
// issue:
|
||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||
// pow(-0, y) returns -<2D>‡ for y an odd integer < 0.
|
||||
// # returns +<2B>‡ . ( same as pow(+0, y) )
|
||||
//
|
||||
using sprout::math::detail::pow;
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity(), x)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::math::is_odd(y) ? x
|
||||
: FloatType(0)
|
||||
: x == -1 && (y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()) ? FloatType(1)
|
||||
: y == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::math::fabs(x) < 1 ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: FloatType(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity()
|
||||
? sprout::math::fabs(x) < 1 ? FloatType(0)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? y < 0
|
||||
? sprout::math::is_odd(y) ? -FloatType(0)
|
||||
: FloatType(0)
|
||||
: sprout::math::is_odd(y) ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == sprout::numeric_limits<FloatType>::infinity()
|
||||
? y < 0 ? FloatType(0)
|
||||
: sprout::numeric_limits<FloatType>::infinity()
|
||||
: x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_pow(x, y)
|
||||
#else
|
||||
: static_cast<FloatType>(sprout::math::detail::pow_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
|
||||
))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
pow(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::pow(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::pow;
|
||||
|
|
|
@ -20,39 +20,38 @@
|
|||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename R = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? R(0)
|
||||
: x == 0 ? R(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? R(0)
|
||||
: sprout::math::rem_quo<R>(x, y).second
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename R = int,
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR R
|
||||
quotient(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::quotient(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::quotient;
|
||||
//
|
||||
// quotient
|
||||
//
|
||||
template<
|
||||
typename R = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::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<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? R(0)
|
||||
: x == 0 ? R(0)
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? R(0)
|
||||
: sprout::math::rem_quo<R>(x, y).second
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename R = int,
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR R
|
||||
quotient(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::quotient(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::quotient;
|
||||
|
|
|
@ -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<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, R>
|
||||
rem_quo(FloatType x, FloatType y) {
|
||||
typedef sprout::pair<FloatType, R> type;
|
||||
return y == 0 ? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: sprout::math::isnan(y)
|
||||
? sprout::math::isnan(x)
|
||||
? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN() : sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: type(y, R(0))
|
||||
: sprout::math::isnan(x) ? type(x, R(0))
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: x == 0 ? type(x, R(0))
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? type(x, R(0))
|
||||
: sprout::math::detail::rem_quo_ret<R, FloatType>(sprout::math::detail::rem_quo_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
|
||||
R(0)
|
||||
))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename R = int,
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<
|
||||
typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type,
|
||||
R
|
||||
>
|
||||
rem_quo(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::rem_quo(static_cast<type>(x), static_cast<type>(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<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, R>
|
||||
rem_quo(FloatType x, FloatType y) {
|
||||
typedef sprout::pair<FloatType, R> type;
|
||||
return y == 0 ? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: sprout::math::isnan(y)
|
||||
? sprout::math::isnan(x)
|
||||
? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN() : sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: type(y, R(0))
|
||||
: sprout::math::isnan(x) ? type(x, R(0))
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
|
||||
: x == 0 ? type(x, R(0))
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? type(x, R(0))
|
||||
: sprout::math::detail::rem_quo_ret<R, FloatType>(sprout::math::detail::rem_quo_impl(
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
|
||||
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
|
||||
R(0)
|
||||
))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename R = int,
|
||||
typename ArithmeticType1,
|
||||
typename ArithmeticType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<
|
||||
typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type,
|
||||
R
|
||||
>
|
||||
rem_quo(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::rem_quo(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::rem_quo;
|
||||
|
|
|
@ -21,49 +21,64 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
remainder(FloatType x, FloatType y) {
|
||||
return y == 0 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: sprout::math::isnan(y)
|
||||
? sprout::math::isnan(x)
|
||||
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == 0 ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
remainder(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::remainder(static_cast<type>(x), static_cast<type>(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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
remainder(FloatType x, FloatType y) {
|
||||
return y == 0 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: sprout::math::isnan(y)
|
||||
? sprout::math::isnan(x)
|
||||
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: y
|
||||
: sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
: x == 0 ? x
|
||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::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<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
remainder(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::remainder(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::remainder;
|
||||
|
|
|
@ -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<typename T>
|
||||
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<T>(static_cast<std::uintmax_t>(x)))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
round(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::round(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::round_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
round(IntType x) {
|
||||
return sprout::math::detail::round(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::round;
|
||||
//
|
||||
// round
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
round(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_round(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x)
|
||||
: static_cast<FloatType>(sprout::math::detail::round_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
round(IntType x) {
|
||||
return sprout::math::round(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::round;
|
||||
|
|
|
@ -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<typename FloatType, typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
scalbln_impl(T x, long exp) {
|
||||
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), exp);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
scalbln(FloatType x, long exp) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::scalbln_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
scalbln(IntType x, long exp) {
|
||||
return sprout::math::detail::scalbln(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using NS_SPROUT_MATH_DETAIL::scalbln;
|
||||
//
|
||||
// scalbln
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::scalbln_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
scalbln(IntType x, long exp) {
|
||||
return sprout::math::scalbln(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::scalbln;
|
||||
|
|
|
@ -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<typename FloatType, typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
scalbn_impl(T x, int exp) {
|
||||
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), exp);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
scalbn(FloatType x, int exp) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::scalbn_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
scalbn(IntType x, int exp) {
|
||||
return sprout::math::detail::scalbn(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using NS_SPROUT_MATH_DETAIL::scalbn;
|
||||
//
|
||||
// scalbn
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
||||
: exp == 0 ? x
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::scalbn_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
scalbn(IntType x, int exp) {
|
||||
return sprout::math::scalbn(static_cast<double>(x), exp);
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::scalbn;
|
||||
|
|
|
@ -17,16 +17,17 @@
|
|||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename FloatType>
|
||||
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<std::is_floating_point<FloatType>::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<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
signbit(IntType x) {
|
||||
return x < 0;
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::signbit;
|
||||
|
|
|
@ -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<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
sin_impl(T x) {
|
||||
return -sprout::math::cos(x + sprout::math::half_pi<T>());
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
sin(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: std::sin(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::sin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
sin(IntType x) {
|
||||
return sprout::math::detail::sin(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::sin;
|
||||
//
|
||||
// sin
|
||||
//
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
sin(FloatType x) {
|
||||
return sprout::math::isnan(x) ? x
|
||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||
? -sprout::numeric_limits<FloatType>::quiet_NaN()
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
: sprout::math::detail::builtin_sin(x)
|
||||
#else
|
||||
: x == 0 ? x
|
||||
: static_cast<FloatType>(sprout::math::detail::sin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
sin(IntType x) {
|
||||
return sprout::math::sin(static_cast<double>(x));
|
||||
}
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::sin;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue