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
|
// 25.3.6 Fill
|
||||||
//
|
//
|
||||||
template<typename ForwrdIterator, typename T>
|
template<typename ForwardIterator, typename T>
|
||||||
inline SPROUT_CXX14_CONSTEXPR void
|
inline SPROUT_CXX14_CONSTEXPR void
|
||||||
fill(ForwrdIterator first, ForwrdIterator last, T const& value) {
|
fill(ForwardIterator first, ForwardIterator last, T const& value) {
|
||||||
while (first != last) {
|
while (first != last) {
|
||||||
*first++ = value;
|
*first++ = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <sprout/container/functions.hpp>
|
#include <sprout/container/functions.hpp>
|
||||||
#include <sprout/iterator/operation.hpp>
|
#include <sprout/iterator/operation.hpp>
|
||||||
#include <sprout/iterator/remove_iterator.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/algorithm/fixed/result_of.hpp>
|
||||||
#include <sprout/pit/pit.hpp>
|
#include <sprout/pit/pit.hpp>
|
||||||
#include <sprout/detail/container_complate.hpp>
|
#include <sprout/detail/container_complate.hpp>
|
||||||
|
@ -93,7 +95,20 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
} // namespace fixed
|
} // 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_HPP
|
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_HPP
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <sprout/container/functions.hpp>
|
#include <sprout/container/functions.hpp>
|
||||||
#include <sprout/iterator/operation.hpp>
|
#include <sprout/iterator/operation.hpp>
|
||||||
#include <sprout/iterator/remove_if_iterator.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/algorithm/fixed/result_of.hpp>
|
||||||
#include <sprout/pit/pit.hpp>
|
#include <sprout/pit/pit.hpp>
|
||||||
#include <sprout/detail/container_complate.hpp>
|
#include <sprout/detail/container_complate.hpp>
|
||||||
|
@ -93,7 +95,20 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
} // namespace fixed
|
} // 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_IF_HPP
|
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_IF_HPP
|
||||||
|
|
|
@ -137,7 +137,20 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
} // namespace fixed
|
} // 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REVERSE_COPY_HPP
|
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REVERSE_COPY_HPP
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <sprout/container/indexes.hpp>
|
#include <sprout/container/indexes.hpp>
|
||||||
#include <sprout/iterator/operation.hpp>
|
#include <sprout/iterator/operation.hpp>
|
||||||
#include <sprout/iterator/joint_iterator.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/algorithm/fixed/result_of.hpp>
|
||||||
#include <sprout/pit/pit.hpp>
|
#include <sprout/pit/pit.hpp>
|
||||||
#include <sprout/detail/container_complate.hpp>
|
#include <sprout/detail/container_complate.hpp>
|
||||||
|
@ -178,7 +180,20 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
} // namespace fixed
|
} // 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_ROTATE_COPY_HPP
|
#endif // #ifndef SPROUT_ALGORITHM_FIXED_ROTATE_COPY_HPP
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <sprout/container/functions.hpp>
|
#include <sprout/container/functions.hpp>
|
||||||
#include <sprout/iterator/operation.hpp>
|
#include <sprout/iterator/operation.hpp>
|
||||||
#include <sprout/iterator/unique_iterator.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/algorithm/fixed/result_of.hpp>
|
||||||
#include <sprout/pit/pit.hpp>
|
#include <sprout/pit/pit.hpp>
|
||||||
#include <sprout/detail/container_complate.hpp>
|
#include <sprout/detail/container_complate.hpp>
|
||||||
|
@ -178,7 +180,38 @@ namespace sprout {
|
||||||
}
|
}
|
||||||
} // namespace fixed
|
} // 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_ALGORITHM_FIXED_UNIQUE_COPY_HPP
|
#endif // #ifndef SPROUT_ALGORITHM_FIXED_UNIQUE_COPY_HPP
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
||||||
//
|
//
|
||||||
// 25.3.7 Generate
|
// 25.3.7 Generate
|
||||||
//
|
//
|
||||||
template<typename ForwrdIterator, typename Generator>
|
template<typename ForwardIterator, typename Generator>
|
||||||
inline SPROUT_CXX14_CONSTEXPR void
|
inline SPROUT_CXX14_CONSTEXPR void
|
||||||
generate(ForwrdIterator first, ForwrdIterator last, Generator gen) {
|
generate(ForwardIterator first, ForwardIterator last, Generator gen) {
|
||||||
while (first != last) {
|
while (first != last) {
|
||||||
*first++ = gen();
|
*first++ = gen();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,12 @@
|
||||||
#include <sprout/algorithm/reverse_copy.hpp>
|
#include <sprout/algorithm/reverse_copy.hpp>
|
||||||
#include <sprout/algorithm/rotate.hpp>
|
#include <sprout/algorithm/rotate.hpp>
|
||||||
#include <sprout/algorithm/rotate_copy.hpp>
|
#include <sprout/algorithm/rotate_copy.hpp>
|
||||||
|
#include <sprout/algorithm/random_shuffle.hpp>
|
||||||
#include <sprout/algorithm/shuffle.hpp>
|
#include <sprout/algorithm/shuffle.hpp>
|
||||||
#include <sprout/algorithm/shuffle_result.hpp>
|
#include <sprout/algorithm/shuffle_result.hpp>
|
||||||
#include <sprout/algorithm/partition.hpp>
|
#include <sprout/algorithm/partition.hpp>
|
||||||
#include <sprout/algorithm/partition_copy.hpp>
|
|
||||||
#include <sprout/algorithm/stable_partition.hpp>
|
#include <sprout/algorithm/stable_partition.hpp>
|
||||||
|
#include <sprout/algorithm/partition_copy.hpp>
|
||||||
#include <sprout/algorithm/stable_partition_copy.hpp>
|
#include <sprout/algorithm/stable_partition_copy.hpp>
|
||||||
#include <sprout/algorithm/sort.hpp>
|
#include <sprout/algorithm/sort.hpp>
|
||||||
#include <sprout/algorithm/stable_sort.hpp>
|
#include <sprout/algorithm/stable_sort.hpp>
|
||||||
|
|
|
@ -9,6 +9,28 @@
|
||||||
#define SPROUT_ALGORITHM_PARTITION_HPP
|
#define SPROUT_ALGORITHM_PARTITION_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/partition.hpp>
|
||||||
#include <sprout/algorithm/fit/partition.hpp>
|
#include <sprout/algorithm/fit/partition.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
#define SPROUT_ALGORITHM_PARTITION_COPY_HPP
|
#define SPROUT_ALGORITHM_PARTITION_COPY_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/partition_copy.hpp>
|
||||||
#include <sprout/algorithm/fit/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
|
#define SPROUT_ALGORITHM_REMOVE_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/remove.hpp>
|
||||||
#include <sprout/algorithm/fit/remove.hpp>
|
#include <sprout/algorithm/fit/remove.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,28 @@
|
||||||
#define SPROUT_ALGORITHM_REMOVE_COPY_HPP
|
#define SPROUT_ALGORITHM_REMOVE_COPY_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/remove_copy.hpp>
|
||||||
#include <sprout/algorithm/fit/remove_copy.hpp>
|
#include <sprout/algorithm/fit/remove_copy.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,28 @@
|
||||||
#define SPROUT_ALGORITHM_REMOVE_COPY_IF_HPP
|
#define SPROUT_ALGORITHM_REMOVE_COPY_IF_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/remove_copy_if.hpp>
|
||||||
#include <sprout/algorithm/fit/remove_copy_if.hpp>
|
#include <sprout/algorithm/fit/remove_copy_if.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,25 @@
|
||||||
#define SPROUT_ALGORITHM_REMOVE_IF_HPP
|
#define SPROUT_ALGORITHM_REMOVE_IF_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/remove_if.hpp>
|
||||||
#include <sprout/algorithm/fit/remove_if.hpp>
|
#include <sprout/algorithm/fit/remove_if.hpp>
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
||||||
//
|
//
|
||||||
// 25.3.5 Replace
|
// 25.3.5 Replace
|
||||||
//
|
//
|
||||||
template<typename ForwrdIterator, typename T>
|
template<typename ForwardIterator, typename T>
|
||||||
inline SPROUT_CXX14_CONSTEXPR void
|
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) {
|
for (; first != last; ++first) {
|
||||||
if (*first == old_value) {
|
if (*first == old_value) {
|
||||||
*first = new_value;
|
*first = new_value;
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace sprout {
|
||||||
//
|
//
|
||||||
// 25.3.5 Replace
|
// 25.3.5 Replace
|
||||||
//
|
//
|
||||||
template<typename ForwrdIterator, typename Predicate, typename T>
|
template<typename ForwardIterator, typename Predicate, typename T>
|
||||||
inline SPROUT_CXX14_CONSTEXPR void
|
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) {
|
for (; first != last; ++first) {
|
||||||
if (pred(*first)) {
|
if (pred(*first)) {
|
||||||
*first = new_value;
|
*first = new_value;
|
||||||
|
|
|
@ -9,6 +9,21 @@
|
||||||
#define SPROUT_ALGORITHM_REVERSE_HPP
|
#define SPROUT_ALGORITHM_REVERSE_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/reverse.hpp>
|
||||||
#include <sprout/algorithm/fit/reverse.hpp>
|
#include <sprout/algorithm/fit/reverse.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,26 @@
|
||||||
#define SPROUT_ALGORITHM_REVERSE_COPY_HPP
|
#define SPROUT_ALGORITHM_REVERSE_COPY_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/reverse_copy.hpp>
|
||||||
#include <sprout/algorithm/fit/reverse_copy.hpp>
|
#include <sprout/algorithm/fit/reverse_copy.hpp>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,53 @@
|
||||||
#ifndef SPROUT_ALGORITHM_ROTATE_HPP
|
#ifndef SPROUT_ALGORITHM_ROTATE_HPP
|
||||||
#define SPROUT_ALGORITHM_ROTATE_HPP
|
#define SPROUT_ALGORITHM_ROTATE_HPP
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#include <sprout/config.hpp>
|
#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/fixed/rotate.hpp>
|
||||||
#include <sprout/algorithm/fit/rotate.hpp>
|
#include <sprout/algorithm/fit/rotate.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,24 @@
|
||||||
#define SPROUT_ALGORITHM_ROTATE_COPY_HPP
|
#define SPROUT_ALGORITHM_ROTATE_COPY_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/rotate_copy.hpp>
|
||||||
#include <sprout/algorithm/fit/rotate_copy.hpp>
|
#include <sprout/algorithm/fit/rotate_copy.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,16 @@
|
||||||
#define SPROUT_ALGORITHM_SHUFFLE_HPP
|
#define SPROUT_ALGORITHM_SHUFFLE_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/shuffle.hpp>
|
||||||
#include <sprout/algorithm/fit/shuffle.hpp>
|
#include <sprout/algorithm/fit/shuffle.hpp>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
#define SPROUT_ALGORITHM_STABLE_PARTITION_HPP
|
#define SPROUT_ALGORITHM_STABLE_PARTITION_HPP
|
||||||
|
|
||||||
#include <sprout/config.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/fixed/stable_partition.hpp>
|
||||||
#include <sprout/algorithm/fit/stable_partition.hpp>
|
#include <sprout/algorithm/fit/stable_partition.hpp>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,50 @@
|
||||||
#ifndef SPROUT_ALGORITHM_UNIQUE_HPP
|
#ifndef SPROUT_ALGORITHM_UNIQUE_HPP
|
||||||
#define SPROUT_ALGORITHM_UNIQUE_HPP
|
#define SPROUT_ALGORITHM_UNIQUE_HPP
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#include <sprout/config.hpp>
|
#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/fixed/unique.hpp>
|
||||||
#include <sprout/algorithm/fit/unique.hpp>
|
#include <sprout/algorithm/fit/unique.hpp>
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,63 @@
|
||||||
/*=============================================================================
|
/*=============================================================================
|
||||||
Copyright (c) 2011-2013 Bolero MURAKAMI
|
Copyright (c) 2011-2013 Bolero MURAKAMI
|
||||||
https://github.com/bolero-MURAKAMI/Sprout
|
https://github.com/bolero-MURAKAMI/Sprout
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
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)
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
#ifndef SPROUT_ALGORITHM_UNIQUE_COPY_HPP
|
#ifndef SPROUT_ALGORITHM_UNIQUE_COPY_HPP
|
||||||
#define SPROUT_ALGORITHM_UNIQUE_COPY_HPP
|
#define SPROUT_ALGORITHM_UNIQUE_COPY_HPP
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#include <sprout/config.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.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/fixed/unique_copy.hpp>
|
||||||
#include <sprout/algorithm/fit/unique_copy.hpp>
|
#include <sprout/algorithm/fit/unique_copy.hpp>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,15 @@ namespace sprout {
|
||||||
make_array(Types&&... args) {
|
make_array(Types&&... args) {
|
||||||
return sprout::array<T, sizeof...(Types)>{{T(sprout::forward<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
|
// make_common_array
|
||||||
|
|
|
@ -16,24 +16,16 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// abs
|
||||||
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
|
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
inline SPROUT_CONSTEXPR FloatType
|
||||||
abs(FloatType x) {
|
abs(FloatType x) {
|
||||||
return NS_SPROUT_MATH_DETAIL::abs(x);
|
return sprout::math::fabs(x);
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
|
|
|
@ -22,39 +22,54 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
acos_impl(T x) {
|
acos_impl(T x) {
|
||||||
return sprout::math::half_pi<T>() - sprout::math::asin(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::acos;
|
using sprout::math::acos;
|
||||||
|
|
|
@ -21,40 +21,55 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
acosh_impl(T x) {
|
acosh_impl(T x) {
|
||||||
return sprout::math::log(x + sprout::math::sqrt(x * x - 1));
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::acosh;
|
using sprout::math::acosh;
|
||||||
|
|
|
@ -24,6 +24,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
asin_impl_center_1(T x, T x2) {
|
asin_impl_center_1(T x, T x2) {
|
||||||
|
@ -76,37 +91,37 @@ namespace sprout {
|
||||||
: sprout::math::detail::asin_impl_center(x)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::asin;
|
using sprout::math::asin;
|
||||||
|
|
|
@ -21,40 +21,55 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
asinh_impl(T x) {
|
asinh_impl(T x) {
|
||||||
return sprout::math::log(x + sprout::math::sqrt(x * x + 1));
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::asinh;
|
using sprout::math::asinh;
|
||||||
|
|
|
@ -23,6 +23,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
atan_impl_1(T x, std::size_t n, std::size_t last) {
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::atan;
|
using sprout::math::atan;
|
||||||
|
|
|
@ -25,6 +25,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
atan2_impl(T y, T x) {
|
atan2_impl(T y, T x) {
|
||||||
|
@ -35,63 +50,10 @@ namespace sprout {
|
||||||
: sprout::math::atan(y / x)
|
: 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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// atan2
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||||
// atan2(<28>}0, -0) returns <20>}ƒÎ .
|
// atan2(<28>}0, -0) returns <20>}ƒÎ .
|
||||||
|
@ -101,7 +63,60 @@ namespace sprout {
|
||||||
// atan2(-NaN, -NaN) returns -NaN .
|
// atan2(-NaN, -NaN) returns -NaN .
|
||||||
// # returns +NaN . ( same as atan2(+NaN, +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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::atan2;
|
using sprout::math::atan2;
|
||||||
|
|
|
@ -21,41 +21,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
atanh_impl(T x) {
|
atanh_impl(T x) {
|
||||||
return sprout::math::log((1 + x) / (1 - x)) / 2;
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::atanh;
|
using sprout::math::atanh;
|
||||||
|
|
|
@ -21,6 +21,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
cbrt_impl(T x) {
|
cbrt_impl(T x) {
|
||||||
|
@ -28,36 +43,36 @@ namespace sprout {
|
||||||
: sprout::pow(x, sprout::math::third<T>())
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::cbrt;
|
using sprout::math::cbrt;
|
||||||
|
|
|
@ -22,6 +22,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
ceil_impl_1(T x, T x0) {
|
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)))
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::ceil;
|
using sprout::math::ceil;
|
||||||
|
|
|
@ -20,38 +20,24 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
inline SPROUT_CONSTEXPR float
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
builtin_copysign(float x, float y) {
|
||||||
>
|
return __builtin_copysignf(x, y);
|
||||||
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
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
template<
|
inline SPROUT_CONSTEXPR double
|
||||||
typename ArithmeticType1,
|
builtin_copysign(double x, double y) {
|
||||||
typename ArithmeticType2,
|
return __builtin_copysign(x, y);
|
||||||
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 long double
|
||||||
|
builtin_copysign(long double x, long double y) {
|
||||||
|
return __builtin_copysignl(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// copysign
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||||
// copysign(<28>}x, -0) returns -x for |x| is not 0 .
|
// 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 .
|
// copysign(<28>}x, -NaN) returns -x for |x| is not NaN .
|
||||||
// # returns +x . ( same as copysign(<28>}x, +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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::copysign;
|
using sprout::math::copysign;
|
||||||
|
|
|
@ -27,6 +27,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
cos_impl_1(T x2, std::size_t n, std::size_t last) {
|
cos_impl_1(T x2, std::size_t n, std::size_t last) {
|
||||||
|
@ -70,35 +85,35 @@ namespace sprout {
|
||||||
// cos_impl(T x) {
|
// cos_impl(T x) {
|
||||||
// return sprout::math::detail::cos_impl_1(sprout::math::fmod(sprout::math::fabs(x), sprout::math::two_pi<T>()));
|
// 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::cos;
|
using sprout::math::cos;
|
||||||
|
|
|
@ -21,6 +21,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
cosh_impl_1(T t) {
|
cosh_impl_1(T t) {
|
||||||
|
@ -31,35 +46,35 @@ namespace sprout {
|
||||||
cosh_impl(T x) {
|
cosh_impl(T x) {
|
||||||
return sprout::math::detail::cosh_impl_1(sprout::math::exp(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::cosh;
|
using sprout::math::cosh;
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
# include <cmath>
|
# include <cmath>
|
||||||
#endif
|
#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)
|
#if (FLT_RADIX == 2)
|
||||||
# define SPROUT_FLT_RADIX_IS_2 1
|
# define SPROUT_FLT_RADIX_IS_2 1
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -22,6 +22,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
erf_impl_3(T x, T y) {
|
erf_impl_3(T x, T y) {
|
||||||
|
@ -125,35 +140,35 @@ namespace sprout {
|
||||||
erf_impl(T x) {
|
erf_impl(T x) {
|
||||||
return sprout::math::detail::erf_impl_1(x, x < 0 ? -x : 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::erf;
|
using sprout::math::erf;
|
||||||
|
|
|
@ -19,39 +19,54 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
erfc_impl(T x) {
|
erfc_impl(T x) {
|
||||||
return T(1) - sprout::math::erf(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::erfc;
|
using sprout::math::erfc;
|
||||||
|
|
|
@ -22,6 +22,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
exp_impl_1(T x, std::size_t n, std::size_t last) {
|
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)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::exp;
|
using sprout::math::exp;
|
||||||
|
|
|
@ -26,31 +26,31 @@ namespace sprout {
|
||||||
exp10_impl(T x) {
|
exp10_impl(T x) {
|
||||||
return sprout::math::exp(x * sprout::math::ln_ten<T>());
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::exp10;
|
using sprout::math::exp10;
|
||||||
|
|
|
@ -21,40 +21,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
exp2_impl(T x) {
|
exp2_impl(T x) {
|
||||||
return sprout::math::exp(x * sprout::math::ln_two<T>());
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::exp2;
|
using sprout::math::exp2;
|
||||||
|
|
|
@ -22,40 +22,55 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
expm1_impl(T x) {
|
expm1_impl(T x) {
|
||||||
return sprout::math::exp(x) - T(1);
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::expm1;
|
using sprout::math::expm1;
|
||||||
|
|
|
@ -18,28 +18,48 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
inline SPROUT_CONSTEXPR float
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
builtin_fabs(float x) {
|
||||||
>
|
return __builtin_fabsf(x);
|
||||||
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))
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
template<
|
|
||||||
typename IntType,
|
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR double
|
inline SPROUT_CONSTEXPR double
|
||||||
fabs(IntType x) {
|
builtin_fabs(double x) {
|
||||||
return sprout::math::detail::fabs(static_cast<double>(x));
|
return __builtin_fabs(x);
|
||||||
}
|
}
|
||||||
|
inline SPROUT_CONSTEXPR long double
|
||||||
|
builtin_fabs(long double x) {
|
||||||
|
return __builtin_fabsl(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fabs;
|
using sprout::math::fabs;
|
||||||
|
|
|
@ -19,40 +19,55 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
: std::fdim(x, y)
|
inline SPROUT_CONSTEXPR float
|
||||||
#else
|
builtin_fdim(float x, float y) {
|
||||||
: x > y ? x - y : FloatType(0)
|
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
|
#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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fdim;
|
using sprout::math::fdim;
|
||||||
|
|
|
@ -18,30 +18,29 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// float2_exponent
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR int
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
float2_exponent(FloatType x) {
|
>
|
||||||
return sprout::math::isnan(x) ? 0
|
inline SPROUT_CONSTEXPR int
|
||||||
: x == 0 ? 0
|
float2_exponent(FloatType x) {
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
return sprout::math::isnan(x) ? 0
|
||||||
: sprout::math::ilogb2(x) + 1
|
: 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
|
template<
|
||||||
>
|
typename IntType,
|
||||||
inline SPROUT_CONSTEXPR int
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
float2_exponent(IntType x) {
|
>
|
||||||
return sprout::math::detail::float2_exponent(static_cast<double>(x));
|
inline SPROUT_CONSTEXPR int
|
||||||
}
|
float2_exponent(IntType x) {
|
||||||
} // namespace detail
|
return sprout::math::float2_exponent(static_cast<double>(x));
|
||||||
|
}
|
||||||
using sprout::math::detail::float2_exponent;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float2_exponent;
|
using sprout::math::float2_exponent;
|
||||||
|
|
|
@ -27,32 +27,32 @@ namespace sprout {
|
||||||
typedef sprout::pair<T, int> type;
|
typedef sprout::pair<T, int> type;
|
||||||
return type(x / sprout::detail::pow_n(T(2), exp), exp);
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float2_sig_exp;
|
using sprout::math::float2_sig_exp;
|
||||||
|
|
|
@ -19,31 +19,30 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// float2_significand
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
float2_significand(FloatType x) {
|
>
|
||||||
return sprout::math::isnan(x) ? x
|
inline SPROUT_CONSTEXPR FloatType
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
float2_significand(FloatType x) {
|
||||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
return sprout::math::isnan(x) ? x
|
||||||
: x == 0 ? x
|
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||||
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
|
: 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
|
template<
|
||||||
>
|
typename IntType,
|
||||||
inline SPROUT_CONSTEXPR double
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
float2_significand(IntType x) {
|
>
|
||||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
inline SPROUT_CONSTEXPR double
|
||||||
}
|
float2_significand(IntType x) {
|
||||||
} // namespace detail
|
return sprout::math::float_significand(static_cast<double>(x));
|
||||||
|
}
|
||||||
using sprout::math::detail::float2_significand;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float2_significand;
|
using sprout::math::float2_significand;
|
||||||
|
|
|
@ -18,30 +18,29 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// float_exponent
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR int
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
float_exponent(FloatType x) {
|
>
|
||||||
return sprout::math::isnan(x) ? 0
|
inline SPROUT_CONSTEXPR int
|
||||||
: x == 0 ? 0
|
float_exponent(FloatType x) {
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
|
return sprout::math::isnan(x) ? 0
|
||||||
: sprout::math::ilogb(x) + 1
|
: 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
|
template<
|
||||||
>
|
typename IntType,
|
||||||
inline SPROUT_CONSTEXPR int
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
float_exponent(IntType x) {
|
>
|
||||||
return sprout::math::detail::float_exponent(static_cast<double>(x));
|
inline SPROUT_CONSTEXPR int
|
||||||
}
|
float_exponent(IntType x) {
|
||||||
} // namespace detail
|
return sprout::math::float_exponent(static_cast<double>(x));
|
||||||
|
}
|
||||||
using sprout::math::detail::float_exponent;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float_exponent;
|
using sprout::math::float_exponent;
|
||||||
|
|
|
@ -27,32 +27,32 @@ namespace sprout {
|
||||||
typedef sprout::pair<T, int> type;
|
typedef sprout::pair<T, int> type;
|
||||||
return type(x / sprout::detail::pow_n(T(sprout::numeric_limits<T>::radix), exp), exp);
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float_sig_exp;
|
using sprout::math::float_sig_exp;
|
||||||
|
|
|
@ -19,31 +19,30 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// float_significand
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
float_significand(FloatType x) {
|
>
|
||||||
return sprout::math::isnan(x) ? x
|
inline SPROUT_CONSTEXPR FloatType
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
float_significand(FloatType x) {
|
||||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
return sprout::math::isnan(x) ? x
|
||||||
: x == 0 ? x
|
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||||
: x / sprout::detail::pow_n(FloatType(sprout::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
|
: 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
|
template<
|
||||||
>
|
typename IntType,
|
||||||
inline SPROUT_CONSTEXPR double
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
float_significand(IntType x) {
|
>
|
||||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
inline SPROUT_CONSTEXPR double
|
||||||
}
|
float_significand(IntType x) {
|
||||||
} // namespace detail
|
return sprout::math::float_significand(static_cast<double>(x));
|
||||||
|
}
|
||||||
using sprout::math::detail::float_significand;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::float_significand;
|
using sprout::math::float_significand;
|
||||||
|
|
|
@ -22,6 +22,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
floor_impl_1(T x, T x0) {
|
floor_impl_1(T x, T x0) {
|
||||||
|
@ -36,37 +51,37 @@ namespace sprout {
|
||||||
: static_cast<T>(static_cast<std::uintmax_t>(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
|
|
||||||
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::floor;
|
using sprout::math::floor;
|
||||||
|
|
|
@ -21,48 +21,63 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
: std::fma(x, y, z)
|
inline SPROUT_CONSTEXPR float
|
||||||
#else
|
builtin_fma(float x, float y, float z) {
|
||||||
: x * y + 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
|
#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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fma;
|
using sprout::math::fma;
|
||||||
|
|
|
@ -19,41 +19,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
: x == 0 && y == 0 ? x
|
inline SPROUT_CONSTEXPR float
|
||||||
: std::fmax(x, y)
|
builtin_fmax(float x, float y) {
|
||||||
#else
|
return __builtin_fmaxf(x, y);
|
||||||
: x < y ? y : x
|
}
|
||||||
|
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
|
#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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fmax;
|
using sprout::math::fmax;
|
||||||
|
|
|
@ -19,41 +19,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
: x == 0 && y == 0 ? x
|
inline SPROUT_CONSTEXPR float
|
||||||
: std::fmin(x, y)
|
builtin_fmin(float x, float y) {
|
||||||
#else
|
return __builtin_fminf(x, y);
|
||||||
: y < x ? y : x
|
}
|
||||||
|
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
|
#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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fmin;
|
using sprout::math::fmin;
|
||||||
|
|
|
@ -71,49 +71,49 @@ namespace sprout {
|
||||||
fmod_impl(T x, T y) {
|
fmod_impl(T x, T y) {
|
||||||
return sprout::math::detail::fmod_impl_1(x, sprout::math::fabs(y), sprout::math::fabs(x));
|
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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// fmod
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// fmod(-NaN, -NaN) returns -NaN .
|
// fmod(-NaN, -NaN) returns -NaN .
|
||||||
// # returns +NaN . ( same as fmod(+NaN, +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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fmod;
|
using sprout::math::fmod;
|
||||||
|
|
|
@ -21,22 +21,45 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
fpclassify(FloatType x) {
|
builtin_fpclassify(FloatType x) {
|
||||||
return sprout::math::isnan(x) ? FP_NAN
|
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x);
|
||||||
: sprout::math::isinf(x) ? FP_INFINITE
|
|
||||||
: sprout::math::iszero(x) ? FP_ZERO
|
|
||||||
: sprout::math::detail::issubnormal_or_zero(x) ? FP_SUBNORMAL
|
|
||||||
: FP_NORMAL
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fpclassify;
|
using sprout::math::fpclassify;
|
||||||
|
|
|
@ -32,26 +32,26 @@ namespace sprout {
|
||||||
: type(sprout::math::copysign(x - ipart, x), ipart)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::frac_int;
|
using sprout::math::frac_int;
|
||||||
|
|
|
@ -27,30 +27,30 @@ namespace sprout {
|
||||||
: sprout::math::copysign(x - ipart, x)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::fractional_part;
|
using sprout::math::fractional_part;
|
||||||
|
|
|
@ -23,6 +23,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
hypot_impl_2(T t, T w) {
|
hypot_impl_2(T t, T w) {
|
||||||
|
@ -41,47 +56,47 @@ namespace sprout {
|
||||||
hypot_impl(T x, T y) {
|
hypot_impl(T x, T y) {
|
||||||
return sprout::math::detail::hypot_impl_1(sprout::math::fabs(x), sprout::math::fabs(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::hypot;
|
using sprout::math::hypot;
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
iceil_impl(FloatType x) {
|
iceil_impl(FloatType x) {
|
||||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
||||||
: static_cast<To>(x)
|
: static_cast<To>(x)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<
|
} // namespace detail
|
||||||
typename To = int,
|
//
|
||||||
typename FloatType,
|
// iceil
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
//
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR To
|
typename To = int,
|
||||||
iceil(FloatType x) {
|
typename FloatType,
|
||||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||||
: sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x))
|
>
|
||||||
;
|
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
|
#else
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
iceil_impl(FloatType x, To x0) {
|
iceil_impl(FloatType x, To x0) {
|
||||||
|
@ -53,33 +58,34 @@ namespace sprout {
|
||||||
: x0 + 1
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::iceil;
|
using sprout::math::iceil;
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
ifloor_impl(FloatType x) {
|
ifloor_impl(FloatType x) {
|
||||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
||||||
: static_cast<To>(x)
|
: static_cast<To>(x)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<
|
} // namespace detail
|
||||||
typename To = int,
|
//
|
||||||
typename FloatType,
|
// ifloor
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
//
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR To
|
typename To = int,
|
||||||
ifloor(FloatType x) {
|
typename FloatType,
|
||||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||||
: sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x))
|
>
|
||||||
;
|
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
|
#else
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
ifloor_impl(FloatType x, To x0) {
|
ifloor_impl(FloatType x, To x0) {
|
||||||
|
@ -53,33 +58,34 @@ namespace sprout {
|
||||||
: x0 - 1
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::ifloor;
|
using sprout::math::ifloor;
|
||||||
|
|
|
@ -22,33 +22,48 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#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
|
inline SPROUT_CONSTEXPR int
|
||||||
ilogb(IntType x) {
|
builtin_ilogb(float x) {
|
||||||
return sprout::math::detail::ilogb(static_cast<double>(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::ilogb;
|
using sprout::math::ilogb;
|
||||||
|
|
|
@ -25,49 +25,45 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_FLT_RADIX_IS_2
|
#if SPROUT_FLT_RADIX_IS_2
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
ilogb2(FloatType x) {
|
ilogb2(FloatType x) {
|
||||||
return sprout::math::ilogb(x);
|
return sprout::math::ilogb(x);
|
||||||
}
|
}
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
ilogb2(IntType x) {
|
ilogb2(IntType x) {
|
||||||
return sprout::math::ilogb(x);
|
return sprout::math::ilogb(x);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
ilogb2(FloatType x) {
|
ilogb2(FloatType x) {
|
||||||
return sprout::math::iszero(x) ? FP_ILOGB0
|
return sprout::math::iszero(x) ? FP_ILOGB0
|
||||||
: sprout::math::isinf(x) ? INT_MAX
|
: sprout::math::isinf(x) ? INT_MAX
|
||||||
: sprout::math::isnan(x) ? FP_ILOGBNAN
|
: sprout::math::isnan(x) ? FP_ILOGBNAN
|
||||||
: static_cast<int>(sprout::math::logb2(x))
|
: static_cast<int>(sprout::math::logb2(x))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
ilogb2(IntType x) {
|
ilogb2(IntType x) {
|
||||||
return sprout::math::detail::ilogb2(static_cast<double>(x));
|
return sprout::math::ilogb2(static_cast<double>(x));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
using sprout::math::detail::ilogb2;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::ilogb2;
|
using sprout::math::ilogb2;
|
||||||
|
|
|
@ -18,31 +18,30 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// integer_part
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
integer_part(FloatType x) {
|
>
|
||||||
return sprout::math::isnan(x) ? x
|
inline SPROUT_CONSTEXPR FloatType
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
integer_part(FloatType x) {
|
||||||
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
|
return sprout::math::isnan(x) ? x
|
||||||
: x == 0 ? x
|
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
|
||||||
: sprout::math::trunc(x)
|
: 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
|
template<
|
||||||
>
|
typename IntType,
|
||||||
inline SPROUT_CONSTEXPR double
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
integer_part(IntType x) {
|
>
|
||||||
return sprout::math::detail::integer_part(static_cast<double>(x));
|
inline SPROUT_CONSTEXPR double
|
||||||
}
|
integer_part(IntType x) {
|
||||||
} // namespace detail
|
return sprout::math::integer_part(static_cast<double>(x));
|
||||||
|
}
|
||||||
using sprout::math::detail::integer_part;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::integer_part;
|
using sprout::math::integer_part;
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
iround_impl(FloatType x) {
|
iround_impl(FloatType x) {
|
||||||
|
@ -34,18 +34,23 @@ namespace sprout {
|
||||||
: static_cast<To>(x)
|
: static_cast<To>(x)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<
|
} // namespace detail
|
||||||
typename To = int,
|
//
|
||||||
typename FloatType,
|
// iround
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
//
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR To
|
typename To = int,
|
||||||
iround(FloatType x) {
|
typename FloatType,
|
||||||
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||||
: sprout::math::detail::iround_impl<To>(sprout::math::round(x))
|
>
|
||||||
;
|
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
|
#else
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
iround_impl_positive(FloatType x, To x0) {
|
iround_impl_positive(FloatType x, To x0) {
|
||||||
|
@ -60,34 +65,35 @@ namespace sprout {
|
||||||
: x0 - 1
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::iround;
|
using sprout::math::iround;
|
||||||
|
|
|
@ -22,20 +22,20 @@ namespace sprout {
|
||||||
is_even_unchecked(T x) {
|
is_even_unchecked(T x) {
|
||||||
return sprout::math::fmod(x, T(2)) == T(0);
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::is_even;
|
using sprout::math::is_even;
|
||||||
|
|
|
@ -22,20 +22,20 @@ namespace sprout {
|
||||||
is_integer_unchecked(T x) {
|
is_integer_unchecked(T x) {
|
||||||
return x == sprout::math::trunc(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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::is_integer;
|
using sprout::math::is_integer;
|
||||||
|
|
|
@ -22,20 +22,20 @@ namespace sprout {
|
||||||
is_odd_unchecked(T x) {
|
is_odd_unchecked(T x) {
|
||||||
return sprout::math::fmod(x, T(2)) == T(1);
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::is_odd;
|
using sprout::math::is_odd;
|
||||||
|
|
|
@ -18,19 +18,39 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
isfinite(FloatType x) {
|
builtin_isfinite(FloatType x) {
|
||||||
return !sprout::math::isnan(x)
|
return __builtin_isfinite(x);
|
||||||
&& !sprout::math::isinf(x)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::isfinite;
|
using sprout::math::isfinite;
|
||||||
|
|
|
@ -17,19 +17,40 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
isinf(FloatType x) {
|
builtin_isinf(FloatType x) {
|
||||||
return x == sprout::numeric_limits<FloatType>::infinity()
|
return __builtin_isinf(x);
|
||||||
|| x == -sprout::numeric_limits<FloatType>::infinity()
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::isinf;
|
using sprout::math::isinf;
|
||||||
|
|
|
@ -16,17 +16,39 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
isnan(FloatType x) {
|
builtin_isnan(FloatType x) {
|
||||||
return !(x == x);
|
return __builtin_isnan(x);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::isnan;
|
using sprout::math::isnan;
|
||||||
|
|
|
@ -19,20 +19,41 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
isnormal(FloatType x) {
|
builtin_isnormal(FloatType x) {
|
||||||
return !sprout::math::isnan(x)
|
return __builtin_isnormal(x);
|
||||||
&& !sprout::math::isinf(x)
|
|
||||||
&& !sprout::math::detail::issubnormal_or_zero(x)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::isnormal;
|
using sprout::math::isnormal;
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
//
|
||||||
|
// issubnormal_or_zero
|
||||||
|
//
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
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()
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::issubnormal;
|
using sprout::math::issubnormal;
|
||||||
|
|
|
@ -14,18 +14,25 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// iszero
|
||||||
typename FloatType,
|
//
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
template<
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR bool
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
iszero(FloatType x) {
|
>
|
||||||
return x == 0;
|
inline SPROUT_CONSTEXPR bool
|
||||||
}
|
iszero(FloatType x) {
|
||||||
} // namespace detail
|
return x == 0;
|
||||||
|
}
|
||||||
using sprout::math::detail::iszero;
|
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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::iszero;
|
using sprout::math::iszero;
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
|
namespace detail {
|
||||||
template<typename To, typename FloatType>
|
template<typename To, typename FloatType>
|
||||||
inline SPROUT_CONSTEXPR To
|
inline SPROUT_CONSTEXPR To
|
||||||
itrunc_impl(FloatType x) {
|
itrunc_impl(FloatType x) {
|
||||||
|
@ -32,45 +32,49 @@ namespace sprout {
|
||||||
: static_cast<To>(x)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::itrunc;
|
using sprout::math::itrunc;
|
||||||
|
|
|
@ -20,37 +20,57 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
ldexp_impl(T x, int exp) {
|
ldexp_impl(T x, int exp) {
|
||||||
return x * sprout::detail::pow_n(T(2), 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::ldexp;
|
using sprout::math::ldexp;
|
||||||
|
|
|
@ -26,6 +26,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
lgamma_impl_3(T x, T y) {
|
lgamma_impl_3(T x, T y) {
|
||||||
|
@ -183,38 +198,38 @@ namespace sprout {
|
||||||
lgamma_impl(T x) {
|
lgamma_impl(T x) {
|
||||||
return sprout::math::detail::lgamma_impl_1(x, x < 0 ? -x : 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::lgamma;
|
using sprout::math::lgamma;
|
||||||
|
|
|
@ -20,35 +20,52 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#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
|
inline SPROUT_CONSTEXPR long long
|
||||||
llround(IntType x) {
|
builtin_llround(float x) {
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
return __builtin_llroundf(x);
|
||||||
return std::llround(x);
|
|
||||||
#else
|
|
||||||
return sprout::math::iround<long long>(x);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::llround;
|
using sprout::math::llround;
|
||||||
|
|
|
@ -24,6 +24,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
log_impl_2(T x, std::size_t n, std::size_t last) {
|
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)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::log;
|
using sprout::math::log;
|
||||||
|
|
|
@ -21,41 +21,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
log10_impl(T x) {
|
log10_impl(T x) {
|
||||||
return sprout::math::log(x) / sprout::math::ln_ten<T>();
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::log10;
|
using sprout::math::log10;
|
||||||
|
|
|
@ -20,41 +20,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
log1p_impl(T x) {
|
log1p_impl(T x) {
|
||||||
return sprout::math::log(T(1) + 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::log1p;
|
using sprout::math::log1p;
|
||||||
|
|
|
@ -21,41 +21,56 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
log2_impl(T x) {
|
log2_impl(T x) {
|
||||||
return sprout::math::log(x) / sprout::math::ln_two<T>();
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::log2;
|
using sprout::math::log2;
|
||||||
|
|
|
@ -28,34 +28,34 @@ namespace sprout {
|
||||||
: sprout::math::log(y) / sprout::math::log(x)
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::log_a;
|
using sprout::math::log_a;
|
||||||
|
|
|
@ -25,6 +25,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
logb_impl_3_neg_lo(T x, T x0, T base, T exp) {
|
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)))
|
: sprout::math::detail::logb_impl_1(x, sprout::math::trunc(sprout::math::log_a(T(sprout::numeric_limits<T>::radix), x)))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
} // namespace detail
|
||||||
template<
|
//
|
||||||
typename FloatType,
|
// logb
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
//
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
typename FloatType,
|
||||||
logb(FloatType x) {
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
return sprout::math::isnan(x) ? x
|
>
|
||||||
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
|
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 SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
# if defined(__GNUC__)
|
# if defined(__GNUC__)
|
||||||
: x == -sprout::numeric_limits<FloatType>::infinity()
|
: x == -sprout::numeric_limits<FloatType>::infinity()
|
||||||
? sprout::numeric_limits<FloatType>::infinity()
|
? sprout::numeric_limits<FloatType>::infinity()
|
||||||
# endif
|
# endif
|
||||||
: std::logb(x)
|
: sprout::math::detail::builtin_logb(x)
|
||||||
#else
|
#else
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||||
? 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)))
|
: static_cast<FloatType>(sprout::math::detail::logb_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR double
|
inline SPROUT_CONSTEXPR double
|
||||||
logb(IntType x) {
|
logb(IntType x) {
|
||||||
return sprout::math::detail::logb(static_cast<double>(x));
|
return sprout::math::logb(static_cast<double>(x));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
using sprout::math::detail::logb;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::logb;
|
using sprout::math::logb;
|
||||||
|
|
|
@ -28,25 +28,28 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
|
||||||
#if SPROUT_FLT_RADIX_IS_2
|
#if SPROUT_FLT_RADIX_IS_2
|
||||||
template<
|
//
|
||||||
typename FloatType,
|
// logb2
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
//
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR FloatType
|
typename FloatType,
|
||||||
logb2(FloatType x) {
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||||
return sprout::math::logb(x);
|
>
|
||||||
}
|
inline SPROUT_CONSTEXPR FloatType
|
||||||
template<
|
logb2(FloatType x) {
|
||||||
typename IntType,
|
return sprout::math::logb(x);
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
}
|
||||||
>
|
template<
|
||||||
inline SPROUT_CONSTEXPR double
|
typename IntType,
|
||||||
logb2(IntType x) {
|
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||||
return sprout::math::logb(x);
|
>
|
||||||
}
|
inline SPROUT_CONSTEXPR double
|
||||||
|
logb2(IntType x) {
|
||||||
|
return sprout::math::logb(x);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
logb2_impl_3_neg_lo(T x, T x0, T base, T exp) {
|
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)))
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::logb2;
|
using sprout::math::logb2;
|
||||||
|
|
|
@ -20,35 +20,52 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#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
|
inline SPROUT_CONSTEXPR long
|
||||||
lround(IntType x) {
|
builtin_lround(float x) {
|
||||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
return __builtin_lroundf(x);
|
||||||
return std::lround(x);
|
|
||||||
#else
|
|
||||||
return sprout::math::iround<long>(x);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::lround;
|
using sprout::math::lround;
|
||||||
|
|
|
@ -26,76 +26,91 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
pow_impl(T x, T y) {
|
pow_impl(T x, T y) {
|
||||||
return sprout::math::exp(y * sprout::math::log(x));
|
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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// pow
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||||
// pow(-0, y) returns -<2D>‡ for y an odd integer < 0.
|
// pow(-0, y) returns -<2D>‡ for y an odd integer < 0.
|
||||||
// # returns +<2B>‡ . ( same as pow(+0, y) )
|
// # 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::pow;
|
using sprout::math::pow;
|
||||||
|
|
|
@ -20,39 +20,38 @@
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
//
|
||||||
template<
|
// quotient
|
||||||
typename R = int,
|
//
|
||||||
typename FloatType,
|
template<
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
|
typename R = int,
|
||||||
>
|
typename FloatType,
|
||||||
inline SPROUT_CONSTEXPR R
|
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
|
||||||
quotient(FloatType x, FloatType y) {
|
>
|
||||||
return y == 0 ? R(0)
|
inline SPROUT_CONSTEXPR R
|
||||||
: sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0)
|
quotient(FloatType x, FloatType y) {
|
||||||
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
return y == 0 ? R(0)
|
||||||
? R(0)
|
: sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0)
|
||||||
: x == 0 ? R(0)
|
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
|
||||||
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? R(0)
|
? R(0)
|
||||||
: sprout::math::rem_quo<R>(x, y).second
|
: 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,
|
template<
|
||||||
typename ArithmeticType2,
|
typename R = int,
|
||||||
typename sprout::enabler_if<
|
typename ArithmeticType1,
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
typename ArithmeticType2,
|
||||||
>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
>
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
|
||||||
inline SPROUT_CONSTEXPR R
|
>::type = sprout::enabler
|
||||||
quotient(ArithmeticType1 x, ArithmeticType2 y) {
|
>
|
||||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
inline SPROUT_CONSTEXPR R
|
||||||
return sprout::math::detail::quotient(static_cast<type>(x), static_cast<type>(y));
|
quotient(ArithmeticType1 x, ArithmeticType2 y) {
|
||||||
}
|
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||||
} // namespace detail
|
return sprout::math::quotient(static_cast<type>(x), static_cast<type>(y));
|
||||||
|
}
|
||||||
using sprout::math::detail::quotient;
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::quotient;
|
using sprout::math::quotient;
|
||||||
|
|
|
@ -87,55 +87,56 @@ namespace sprout {
|
||||||
rem_quo_impl(T x, T y, R iquo) {
|
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));
|
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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// rem_quo
|
||||||
|
//
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// rem_quo(-NaN, -NaN) returns {-NaN, _} .
|
// rem_quo(-NaN, -NaN) returns {-NaN, _} .
|
||||||
// # returns {+NaN, _} . ( same as rem_quo(+NaN, +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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::rem_quo;
|
using sprout::math::rem_quo;
|
||||||
|
|
|
@ -21,49 +21,64 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
: std::remainder(x, y)
|
inline SPROUT_CONSTEXPR float
|
||||||
#else
|
builtin_remainder(float x, float y) {
|
||||||
: sprout::math::rem_quo(x, y).first
|
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
|
#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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// remainder
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// remainder(-NaN, -NaN) returns -NaN .
|
// remainder(-NaN, -NaN) returns -NaN .
|
||||||
// # returns +NaN . ( same as remainder(+NaN, +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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::remainder;
|
using sprout::math::remainder;
|
||||||
|
|
|
@ -21,6 +21,21 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
round_impl_positive(T x, T x0) {
|
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)))
|
: 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::round;
|
using sprout::math::round;
|
||||||
|
|
|
@ -20,37 +20,57 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename FloatType, typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
scalbln_impl(T x, long exp) {
|
scalbln_impl(T x, long exp) {
|
||||||
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::scalbln;
|
using sprout::math::scalbln;
|
||||||
|
|
|
@ -20,37 +20,57 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename FloatType, typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
scalbn_impl(T x, int exp) {
|
scalbn_impl(T x, int exp) {
|
||||||
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), 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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::scalbn;
|
using sprout::math::scalbn;
|
||||||
|
|
|
@ -17,16 +17,17 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||||
typename FloatType,
|
template<typename FloatType>
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
signbit(FloatType x) {
|
builtin_signbit(FloatType x) {
|
||||||
return !sprout::math::isnan(x) && x < 0;
|
return __builtin_signbit(x);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
//
|
//
|
||||||
|
// signbit
|
||||||
|
//
|
||||||
// issue:
|
// issue:
|
||||||
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
|
||||||
// signbit(-0) returns false .
|
// signbit(-0) returns false .
|
||||||
|
@ -34,7 +35,28 @@ namespace sprout {
|
||||||
// signbit(-NaN) returns false .
|
// signbit(-NaN) returns false .
|
||||||
// # returns true . ( same as signbit(+NaN) )
|
// # 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::signbit;
|
using sprout::math::signbit;
|
||||||
|
|
|
@ -21,40 +21,55 @@
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
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>
|
template<typename T>
|
||||||
inline SPROUT_CONSTEXPR T
|
inline SPROUT_CONSTEXPR T
|
||||||
sin_impl(T x) {
|
sin_impl(T x) {
|
||||||
return -sprout::math::cos(x + sprout::math::half_pi<T>());
|
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
|
} // 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
|
} // namespace math
|
||||||
|
|
||||||
using sprout::math::sin;
|
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