fix: math functions (support for inferior C++14 standard)

add C++14 constexpr modifying algorithms
This commit is contained in:
bolero-MURAKAMI 2013-10-25 12:29:16 +09:00
parent 58cff54e0d
commit c58c9cc0fc
106 changed files with 3465 additions and 2144 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

View file

@ -14,9 +14,9 @@ namespace sprout {
//
// 25.3.6 Fill
//
template<typename ForwrdIterator, typename T>
template<typename ForwardIterator, typename T>
inline SPROUT_CXX14_CONSTEXPR void
fill(ForwrdIterator first, ForwrdIterator last, T const& value) {
fill(ForwardIterator first, ForwardIterator last, T const& value) {
while (first != last) {
*first++ = value;
}

View file

@ -14,6 +14,8 @@
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/remove_iterator.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/pit/pit.hpp>
#include <sprout/detail/container_complate.hpp>
@ -93,7 +95,20 @@ namespace sprout {
}
} // namespace fixed
using sprout::fixed::remove_copy;
template<
typename InputIterator, typename Result, typename T,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
remove_copy(InputIterator first, InputIterator last, Result const& result, T const& value) {
return sprout::fixed::remove_copy(first, last, result, value);
}
template<typename Result, typename InputIterator, typename T>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
remove_copy(InputIterator first, InputIterator last, T const& value) {
return sprout::fixed::remove_copy<Result>(first, last, value);
}
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_HPP

View file

@ -14,6 +14,8 @@
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/remove_if_iterator.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/pit/pit.hpp>
#include <sprout/detail/container_complate.hpp>
@ -93,7 +95,20 @@ namespace sprout {
}
} // namespace fixed
using sprout::fixed::remove_copy_if;
template<
typename InputIterator, typename Result, typename Predicate,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
remove_copy_if(InputIterator first, InputIterator last, Result const& result, Predicate pred) {
return sprout::fixed::remove_copy_if(first, last, result, pred);
}
template<typename Result, typename InputIterator, typename Predicate>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
remove_copy_if(InputIterator first, InputIterator last, Predicate pred) {
return sprout::fixed::remove_copy_if<Result>(first, last, pred);
}
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REMOVE_COPY_IF_HPP

View file

@ -137,7 +137,20 @@ namespace sprout {
}
} // namespace fixed
using sprout::fixed::reverse_copy;
template<
typename BidirectionalIterator, typename Result,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
reverse_copy(BidirectionalIterator first, BidirectionalIterator last, Result const& result) {
return sprout::fixed::reverse_copy(first, last, result);
}
template<typename Result, typename BidirectionalIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
reverse_copy(BidirectionalIterator first, BidirectionalIterator last) {
return sprout::fixed::reverse_copy<Result>(first, last);
}
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_FIXED_REVERSE_COPY_HPP

View file

@ -17,6 +17,8 @@
#include <sprout/container/indexes.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/joint_iterator.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/pit/pit.hpp>
#include <sprout/detail/container_complate.hpp>
@ -178,7 +180,20 @@ namespace sprout {
}
} // namespace fixed
using sprout::fixed::rotate_copy;
template<
typename ForwardIterator, typename Result,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Result const& result) {
return sprout::fixed::rotate_copy(first, middle, last, result);
}
template<typename Result, typename ForwardIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last) {
return sprout::fixed::rotate_copy<Result>(first, middle, last);
}
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_FIXED_ROTATE_COPY_HPP

View file

@ -14,6 +14,8 @@
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/unique_iterator.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/pit/pit.hpp>
#include <sprout/detail/container_complate.hpp>
@ -178,7 +180,38 @@ namespace sprout {
}
} // namespace fixed
using sprout::fixed::unique_copy;
template<
typename InputIterator, typename Result,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
unique_copy(InputIterator first, InputIterator last, Result const& result) {
return sprout::fixed::unique_copy(first, last, result);
}
template<typename Result, typename InputIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
unique_copy(InputIterator first, InputIterator last) {
return sprout::fixed::unique_copy<Result>(first, last);
}
template<
typename InputIterator, typename Result, typename BinaryPredicate,
typename sprout::enabler_if<!sprout::is_output_iterator<Result>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
unique_copy(InputIterator first, InputIterator last, Result const& result, BinaryPredicate pred) {
return sprout::fixed::unique_copy(first, last, result, pred);
}
template<
typename Result, typename InputIterator, typename BinaryPredicate,
typename sprout::enabler_if<!sprout::is_output_iterator<BinaryPredicate>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm<Result>::type
unique_copy(InputIterator first, InputIterator last, BinaryPredicate pred) {
return sprout::fixed::unique_copy<Result>(first, last, pred);
}
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_FIXED_UNIQUE_COPY_HPP

View file

@ -14,9 +14,9 @@ namespace sprout {
//
// 25.3.7 Generate
//
template<typename ForwrdIterator, typename Generator>
template<typename ForwardIterator, typename Generator>
inline SPROUT_CXX14_CONSTEXPR void
generate(ForwrdIterator first, ForwrdIterator last, Generator gen) {
generate(ForwardIterator first, ForwardIterator last, Generator gen) {
while (first != last) {
*first++ = gen();
}

View file

@ -40,11 +40,12 @@
#include <sprout/algorithm/reverse_copy.hpp>
#include <sprout/algorithm/rotate.hpp>
#include <sprout/algorithm/rotate_copy.hpp>
#include <sprout/algorithm/random_shuffle.hpp>
#include <sprout/algorithm/shuffle.hpp>
#include <sprout/algorithm/shuffle_result.hpp>
#include <sprout/algorithm/partition.hpp>
#include <sprout/algorithm/partition_copy.hpp>
#include <sprout/algorithm/stable_partition.hpp>
#include <sprout/algorithm/partition_copy.hpp>
#include <sprout/algorithm/stable_partition_copy.hpp>
#include <sprout/algorithm/sort.hpp>
#include <sprout/algorithm/stable_sort.hpp>

View file

@ -9,6 +9,28 @@
#define SPROUT_ALGORITHM_PARTITION_HPP
#include <sprout/config.hpp>
#include <sprout/algorithm/iter_swap.hpp>
#include <sprout/algorithm/find_if.hpp>
#include <sprout/algorithm/find_if_not.hpp>
namespace sprout {
//
// 25.3.13 Partitions
//
template<typename ForwardIterator, typename Predicate>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
partition(ForwardIterator first, ForwardIterator last, Predicate pred) {
first = sprout::find_if_not(first, last, pred);
ForwardIterator it = sprout::find_if(first, last, pred);
while (it != last) {
sprout::iter_swap(first, it);
first = sprout::find_if_not(first, last, pred);
it = sprout::find_if(it, last, pred);
}
return first;
}
} // namespace sprout
#include <sprout/algorithm/fixed/partition.hpp>
#include <sprout/algorithm/fit/partition.hpp>

View file

@ -9,6 +9,17 @@
#define SPROUT_ALGORITHM_PARTITION_COPY_HPP
#include <sprout/config.hpp>
#include <sprout/utility/pair.hpp>
namespace sprout {
//
// 25.3.13 Partitions
//
template<typename InputIterator, typename OutputIterator1, typename OutputIterator2, typename Predicate>
inline SPROUT_CXX14_CONSTEXPR sprout::pair<OutputIterator1, OutputIterator2>
partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); // !!!
} // namespace sprout
#include <sprout/algorithm/fixed/partition_copy.hpp>
#include <sprout/algorithm/fit/partition_copy.hpp>

View 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

View file

@ -9,6 +9,25 @@
#define SPROUT_ALGORITHM_REMOVE_HPP
#include <sprout/config.hpp>
#include <sprout/utility/move.hpp>
namespace sprout {
//
// 25.3.8 Remove
//
template<typename ForwardIterator, typename T>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
remove(ForwardIterator first, ForwardIterator last, T const& value) {
ForwardIterator result = first;
for (; first != last; ++first) {
if (!(*first == value)) {
*result++ = sprout::move(*first);
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/remove.hpp>
#include <sprout/algorithm/fit/remove.hpp>

View file

@ -9,6 +9,28 @@
#define SPROUT_ALGORITHM_REMOVE_COPY_HPP
#include <sprout/config.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
//
// 25.3.8 Remove
//
template<
typename InputIterator, typename OutputIterator, typename T,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
remove_copy(InputIterator first, InputIterator last, OutputIterator result, T const& value) {
for (; first != last; ++first) {
if (!(*first == value)) {
*result++ = *first;
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/remove_copy.hpp>
#include <sprout/algorithm/fit/remove_copy.hpp>

View file

@ -9,6 +9,28 @@
#define SPROUT_ALGORITHM_REMOVE_COPY_IF_HPP
#include <sprout/config.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
//
// 25.3.8 Remove
//
template<
typename InputIterator, typename OutputIterator, typename Predicate,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred) {
for (; first != last; ++first) {
if (!pred(*first)) {
*result++ = *first;
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/remove_copy_if.hpp>
#include <sprout/algorithm/fit/remove_copy_if.hpp>

View file

@ -9,6 +9,25 @@
#define SPROUT_ALGORITHM_REMOVE_IF_HPP
#include <sprout/config.hpp>
#include <sprout/utility/move.hpp>
namespace sprout {
//
// 25.3.8 Remove
//
template<typename ForwardIterator, typename Predicate>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
remove_if(ForwardIterator first, ForwardIterator last, Predicate pred) {
ForwardIterator result = first;
for (; first != last; ++first) {
if (!pred(*first)) {
*result++ = sprout::move(*first);
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/remove_if.hpp>
#include <sprout/algorithm/fit/remove_if.hpp>

View file

@ -14,9 +14,9 @@ namespace sprout {
//
// 25.3.5 Replace
//
template<typename ForwrdIterator, typename T>
template<typename ForwardIterator, typename T>
inline SPROUT_CXX14_CONSTEXPR void
replace(ForwrdIterator first, ForwrdIterator last, T const& old_value, T const& new_value) {
replace(ForwardIterator first, ForwardIterator last, T const& old_value, T const& new_value) {
for (; first != last; ++first) {
if (*first == old_value) {
*first = new_value;

View file

@ -14,9 +14,9 @@ namespace sprout {
//
// 25.3.5 Replace
//
template<typename ForwrdIterator, typename Predicate, typename T>
template<typename ForwardIterator, typename Predicate, typename T>
inline SPROUT_CXX14_CONSTEXPR void
replace_if(ForwrdIterator first, ForwrdIterator last, Predicate pred, T const& new_value) {
replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, T const& new_value) {
for (; first != last; ++first) {
if (pred(*first)) {
*first = new_value;

View file

@ -9,6 +9,21 @@
#define SPROUT_ALGORITHM_REVERSE_HPP
#include <sprout/config.hpp>
#include <sprout/algorithm/iter_swap.hpp>
namespace sprout {
//
// 25.3.10 Reverse
//
template<typename BidirectionalIterator>
inline SPROUT_CXX14_CONSTEXPR void
reverse(BidirectionalIterator first, BidirectionalIterator last) {
for (; first != last && first != --last; ++first) {
sprout::iter_swap(first, last);
}
}
} // namespace sprout
#include <sprout/algorithm/fixed/reverse.hpp>
#include <sprout/algorithm/fit/reverse.hpp>

View file

@ -9,6 +9,26 @@
#define SPROUT_ALGORITHM_REVERSE_COPY_HPP
#include <sprout/config.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
//
// 25.3.10 Reverse
//
template<
typename BidirectionalIterator, typename OutputIterator,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result) {
while (first != last) {
*result++ = *--last;
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/reverse_copy.hpp>
#include <sprout/algorithm/fit/reverse_copy.hpp>

View file

@ -8,7 +8,53 @@
#ifndef SPROUT_ALGORITHM_ROTATE_HPP
#define SPROUT_ALGORITHM_ROTATE_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/algorithm/iter_swap.hpp>
namespace sprout {
//
// 25.3.11 Rotate
//
template<typename ForwardIterator>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) {
if (first == middle) {
return last;
} else if (middle == last) {
return first;
}
ForwardIterator first2 = middle;
while (true) {
sprout::iter_swap(first, first2);
++first;
if (++first2 == last) {
break;
}
if (first == middle) {
middle = first2;
}
}
ForwardIterator result = first;
if (first != middle) {
first2 = middle;
while (true) {
sprout::iter_swap(first, first2);
++first;
if (++first2 == last) {
if (first == middle) {
break;
}
first2 = middle;
} else if (first == middle) {
middle = first2;
}
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/rotate.hpp>
#include <sprout/algorithm/fit/rotate.hpp>

View file

@ -9,6 +9,24 @@
#define SPROUT_ALGORITHM_ROTATE_COPY_HPP
#include <sprout/config.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/algorithm/copy.hpp>
namespace sprout {
//
// 25.3.11 Rotate
//
template<
typename ForwardIterator, typename OutputIterator,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) {
return sprout::copy(first, middle, sprout::copy(middle, last, result));
}
} // namespace sprout
#include <sprout/algorithm/fixed/rotate_copy.hpp>
#include <sprout/algorithm/fit/rotate_copy.hpp>

View file

@ -9,6 +9,16 @@
#define SPROUT_ALGORITHM_SHUFFLE_HPP
#include <sprout/config.hpp>
namespace sprout {
//
// 25.3.12 Random shuffle
//
template<typename RandomAccessIterator, typename UniformRandomNumberGenerator>
inline SPROUT_CXX14_CONSTEXPR void
shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& g); // !!!
} // namespace sprout
#include <sprout/algorithm/fixed/shuffle.hpp>
#include <sprout/algorithm/fit/shuffle.hpp>

View file

@ -9,6 +9,17 @@
#define SPROUT_ALGORITHM_STABLE_PARTITION_HPP
#include <sprout/config.hpp>
namespace sprout {
//
// 25.3.13 Partitions
//
template<typename BidirectionalIterator, typename Predicate>
inline SPROUT_CXX14_CONSTEXPR BidirectionalIterator
stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); // !!!
} // namespace sprout
#include <sprout/algorithm/fixed/stable_partition.hpp>
#include <sprout/algorithm/fit/stable_partition.hpp>

View file

@ -8,7 +8,50 @@
#ifndef SPROUT_ALGORITHM_UNIQUE_HPP
#define SPROUT_ALGORITHM_UNIQUE_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/utility/move.hpp>
namespace sprout {
//
// 25.3.9 Unique
//
template<typename ForwardIterator>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
unique(ForwardIterator first, ForwardIterator last) {
if (first == last) {
return first;
}
ForwardIterator result = first;
typename std::iterator_traits<ForwardIterator>::value_type value = sprout::move(*first++);
for (; first != last; ++first) {
if (!(value == *first)) {
*result++ = sprout::move(value);
value = sprout::move(*first);
}
}
*result++ = sprout::move(value);
return result;
}
template<typename ForwardIterator, typename BinaryPredicate>
inline SPROUT_CXX14_CONSTEXPR ForwardIterator
unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) {
if (first == last) {
return first;
}
ForwardIterator result = first;
typename std::iterator_traits<ForwardIterator>::value_type value = sprout::move(*first++);
for (; first != last; ++first) {
if (!pred(value, *first)) {
*result++ = sprout::move(value);
value = sprout::move(*first);
}
}
*result++ = sprout::move(value);
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/unique.hpp>
#include <sprout/algorithm/fit/unique.hpp>

View file

@ -1,14 +1,63 @@
/*=============================================================================
Copyright (c) 2011-2013 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Copyright (c) 2011-2013 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_ALGORITHM_UNIQUE_COPY_HPP
#define SPROUT_ALGORITHM_UNIQUE_COPY_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
//
// 25.3.9 Unique
//
template<
typename InputIterator, typename OutputIterator,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
unique_copy(InputIterator first, InputIterator last, OutputIterator result) {
if (first == last) {
return result;
}
typename std::iterator_traits<InputIterator>::value_type value = *first++;
*result++ = value;
for (; first != last; ++first) {
if (!(value == *first)) {
value = *first;
*result++ = value;
}
}
return result;
}
template<
typename InputIterator, typename OutputIterator, typename BinaryPredicate,
typename sprout::enabler_if<sprout::is_output_iterator<OutputIterator>::value>::type = sprout::enabler
>
inline SPROUT_CXX14_CONSTEXPR OutputIterator
unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred) {
if (first == last) {
return result;
}
typename std::iterator_traits<InputIterator>::value_type value = *first++;
*result++ = value;
for (; first != last; ++first) {
if (!pred(value, *first)) {
value = *first;
*result++ = value;
}
}
return result;
}
} // namespace sprout
#include <sprout/algorithm/fixed/unique_copy.hpp>
#include <sprout/algorithm/fit/unique_copy.hpp>

View file

@ -25,6 +25,15 @@ namespace sprout {
make_array(Types&&... args) {
return sprout::array<T, sizeof...(Types)>{{T(sprout::forward<Types>(args))...}};
}
// template<typename... Types>
// inline SPROUT_CONSTEXPR sprout::array<typename sprout::common_decay<Types&&...>::type, sizeof...(Types)>
// make_array(Types&&... args) {
// typedef sprout::array<
// typename sprout::common_decay<Types&&...>::type,
// sizeof...(Types)
// > type;
// return type{{typename sprout::common_decay<Types&&...>::type(sprout::forward<Types>(args))...}};
// }
//
// make_common_array

View file

@ -16,24 +16,16 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
abs(FloatType x) {
return sprout::math::fabs(x);
}
} // namespace detail
//
// abs
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
abs(FloatType x) {
return NS_SPROUT_MATH_DETAIL::abs(x);
return sprout::math::fabs(x);
}
} // namespace math

View file

@ -22,39 +22,54 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_acos(float x) {
return __builtin_acosf(x);
}
inline SPROUT_CONSTEXPR double
builtin_acos(double x) {
return __builtin_acos(x);
}
inline SPROUT_CONSTEXPR long double
builtin_acos(long double x) {
return __builtin_acosl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
acos_impl(T x) {
return sprout::math::half_pi<T>() - sprout::math::asin(x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
acos(FloatType x) {
return sprout::math::isnan(x) ? x
: sprout::math::fabs(x) > 1 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::acos(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::acos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
acos(IntType x) {
return sprout::math::detail::acos(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::acos;
//
// acos
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
acos(FloatType x) {
return sprout::math::isnan(x) ? x
: sprout::math::fabs(x) > 1 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_acos(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::acos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
acos(IntType x) {
return sprout::math::acos(static_cast<double>(x));
}
} // namespace math
using sprout::math::acos;

View file

@ -21,40 +21,55 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_acosh(float x) {
return __builtin_acoshf(x);
}
inline SPROUT_CONSTEXPR double
builtin_acosh(double x) {
return __builtin_acosh(x);
}
inline SPROUT_CONSTEXPR long double
builtin_acosh(long double x) {
return __builtin_acoshl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
acosh_impl(T x) {
return sprout::math::log(x + sprout::math::sqrt(x * x - 1));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
acosh(FloatType x) {
return sprout::math::isnan(x) ? x
: x < 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::acosh(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::acosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
acosh(IntType x) {
return sprout::math::detail::acosh(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::acosh;
//
// acosh
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
acosh(FloatType x) {
return sprout::math::isnan(x) ? x
: x < 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_acosh(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::acosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
acosh(IntType x) {
return sprout::math::acosh(static_cast<double>(x));
}
} // namespace math
using sprout::math::acosh;

View file

@ -24,6 +24,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_asin(float x) {
return __builtin_asinf(x);
}
inline SPROUT_CONSTEXPR double
builtin_asin(double x) {
return __builtin_asin(x);
}
inline SPROUT_CONSTEXPR long double
builtin_asin(long double x) {
return __builtin_asinl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
asin_impl_center_1(T x, T x2) {
@ -76,37 +91,37 @@ namespace sprout {
: sprout::math::detail::asin_impl_center(x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
asin(FloatType x) {
return sprout::math::isnan(x) ? x
: sprout::math::fabs(x) > 1 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::asin(x)
#else
: x == 0 ? x
: static_cast<FloatType>(
x < 0 ? -sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
: sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
asin(IntType x) {
return sprout::math::detail::asin(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::asin;
//
// asin
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
asin(FloatType x) {
return sprout::math::isnan(x) ? x
: sprout::math::fabs(x) > 1 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_asin(x)
#else
: x == 0 ? x
: static_cast<FloatType>(
x < 0 ? -sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
: sprout::math::detail::asin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
asin(IntType x) {
return sprout::math::asin(static_cast<double>(x));
}
} // namespace math
using sprout::math::asin;

View file

@ -21,40 +21,55 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_asinh(float x) {
return __builtin_asinhf(x);
}
inline SPROUT_CONSTEXPR double
builtin_asinh(double x) {
return __builtin_asinh(x);
}
inline SPROUT_CONSTEXPR long double
builtin_asinh(long double x) {
return __builtin_asinhl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
asinh_impl(T x) {
return sprout::math::log(x + sprout::math::sqrt(x * x + 1));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
asinh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::asinh(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::asinh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
asinh(IntType x) {
return sprout::math::detail::asinh(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::asinh;
//
// asinh
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
asinh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_asinh(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::asinh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
asinh(IntType x) {
return sprout::math::asinh(static_cast<double>(x));
}
} // namespace math
using sprout::math::asinh;

View file

@ -23,6 +23,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_atan(float x) {
return __builtin_atanf(x);
}
inline SPROUT_CONSTEXPR double
builtin_atan(double x) {
return __builtin_atan(x);
}
inline SPROUT_CONSTEXPR long double
builtin_atan(long double x) {
return __builtin_atanl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
atan_impl_1(T x, std::size_t n, std::size_t last) {
@ -43,37 +58,38 @@ namespace sprout {
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atan(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::atan(x)
#else
: x == 0 ? x
: static_cast<FloatType>(
x < 0 ? -sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
: sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
atan(IntType x) {
return sprout::math::detail::atan(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::atan;
//
// atan
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atan(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_atan(x)
#else
: x == 0 ? x
: static_cast<FloatType>(
x < 0 ? -sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(-x))
: sprout::math::detail::atan_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x))
)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
atan(IntType x) {
return sprout::math::atan(static_cast<double>(x));
}
} // namespace math
using sprout::math::atan;

View file

@ -25,6 +25,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_atan2(float y, float x) {
return __builtin_atan2f(y, x);
}
inline SPROUT_CONSTEXPR double
builtin_atan2(double y, double x) {
return __builtin_atan2(y, x);
}
inline SPROUT_CONSTEXPR long double
builtin_atan2(long double y, long double x) {
return __builtin_atan2l(y, x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
atan2_impl(T y, T x) {
@ -35,63 +50,10 @@ namespace sprout {
: sprout::math::atan(y / x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atan2(FloatType y, FloatType x) {
return sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity()
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::three_quarters_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::three_quarters_pi<FloatType>()
: sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: x == sprout::numeric_limits<FloatType>::infinity()
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::quarter_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::quarter_pi<FloatType>()
: FloatType(0) * y
: y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::atan2(y, x)
#else
: y == 0
? x < 0 ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: x > 0 ? FloatType(0) * y
: sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: FloatType(0) * y
: x == 0
? y < 0 ? -sprout::math::half_pi<FloatType>()
: sprout::math::half_pi<FloatType>()
: static_cast<FloatType>(
sprout::math::detail::atan2_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)
)
)
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
atan2(ArithmeticType1 y, ArithmeticType2 x) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::atan2(static_cast<type>(y), static_cast<type>(x));
}
} // namespace detail
//
// atan2
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// atan2(<28>}0, -0) returns <20>}ƒÎ .
@ -101,7 +63,60 @@ namespace sprout {
// atan2(-NaN, -NaN) returns -NaN .
// # returns +NaN . ( same as atan2(+NaN, +NaN) )
//
using sprout::math::detail::atan2;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atan2(FloatType y, FloatType x) {
return sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity()
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::three_quarters_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::three_quarters_pi<FloatType>()
: sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: x == sprout::numeric_limits<FloatType>::infinity()
? y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::quarter_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::quarter_pi<FloatType>()
: FloatType(0) * y
: y == sprout::numeric_limits<FloatType>::infinity() ? sprout::math::half_pi<FloatType>()
: y == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::math::half_pi<FloatType>()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_atan2(y, x)
#else
: y == 0
? x < 0 ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: x > 0 ? FloatType(0) * y
: sprout::math::signbit(x) ? sprout::math::copysign(sprout::math::pi<FloatType>(), y)
: FloatType(0) * y
: x == 0
? y < 0 ? -sprout::math::half_pi<FloatType>()
: sprout::math::half_pi<FloatType>()
: static_cast<FloatType>(
sprout::math::detail::atan2_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)
)
)
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
atan2(ArithmeticType1 y, ArithmeticType2 x) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::atan2(static_cast<type>(y), static_cast<type>(x));
}
} // namespace math
using sprout::math::atan2;

View file

@ -21,41 +21,56 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_atanh(float x) {
return __builtin_atanhf(x);
}
inline SPROUT_CONSTEXPR double
builtin_atanh(double x) {
return __builtin_atanh(x);
}
inline SPROUT_CONSTEXPR long double
builtin_atanh(long double x) {
return __builtin_atanhl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
atanh_impl(T x) {
return sprout::math::log((1 + x) / (1 - x)) / 2;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atanh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 1 ? sprout::numeric_limits<FloatType>::infinity()
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
: sprout::math::fabs(x) > 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::atanh(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::atanh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
atanh(IntType x) {
return sprout::math::detail::atanh(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::atanh;
//
// atanh
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
atanh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 1 ? sprout::numeric_limits<FloatType>::infinity()
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
: sprout::math::fabs(x) > 1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_atanh(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::atanh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
atanh(IntType x) {
return sprout::math::atanh(static_cast<double>(x));
}
} // namespace math
using sprout::math::atanh;

View file

@ -21,6 +21,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_cbrt(float x) {
return __builtin_cbrtf(x);
}
inline SPROUT_CONSTEXPR double
builtin_cbrt(double x) {
return __builtin_cbrt(x);
}
inline SPROUT_CONSTEXPR long double
builtin_cbrt(long double x) {
return __builtin_cbrtl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
cbrt_impl(T x) {
@ -28,36 +43,36 @@ namespace sprout {
: sprout::pow(x, sprout::math::third<T>())
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cbrt(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::cbrt(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::cbrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cbrt(IntType x) {
return sprout::math::detail::cbrt(static_cast<double>(x));
}
} // namespace detail
//
// cbrt
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cbrt(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_cbrt(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::cbrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
using sprout::math::detail::cbrt;
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cbrt(IntType x) {
return sprout::math::cbrt(static_cast<double>(x));
}
} // namespace math
using sprout::math::cbrt;

View file

@ -22,6 +22,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_ceil(float x) {
return __builtin_ceilf(x);
}
inline SPROUT_CONSTEXPR double
builtin_ceil(double x) {
return __builtin_ceil(x);
}
inline SPROUT_CONSTEXPR long double
builtin_ceil(long double x) {
return __builtin_ceill(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
ceil_impl_1(T x, T x0) {
@ -36,37 +51,37 @@ namespace sprout {
: sprout::math::detail::ceil_impl_1(x, static_cast<T>(static_cast<std::uintmax_t>(x)))
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
ceil(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::ceil(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::ceil_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
ceil(IntType x) {
return sprout::math::detail::ceil(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::ceil;
//
// ceil
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
ceil(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_ceil(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ceil: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::ceil_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
ceil(IntType x) {
return sprout::math::ceil(static_cast<double>(x));
}
} // namespace math
using sprout::math::ceil;

View file

@ -20,38 +20,24 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
copysign(FloatType x, FloatType y) {
return x == 0
? y == 0 ? y
: sprout::math::signbit(y) ? -FloatType(0)
: FloatType(0)
: sprout::math::isnan(x)
? sprout::math::isnan(y) ? y
: sprout::math::signbit(y) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::signbit(y) != sprout::math::signbit(x) ? -x
: x
;
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_copysign(float x, float y) {
return __builtin_copysignf(x, y);
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
copysign(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::copysign(static_cast<type>(x), static_cast<type>(y));
inline SPROUT_CONSTEXPR double
builtin_copysign(double x, double y) {
return __builtin_copysign(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_copysign(long double x, long double y) {
return __builtin_copysignl(x, y);
}
#endif
} // namespace detail
//
// copysign
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// copysign(<28>}x, -0) returns -x for |x| is not 0 .
@ -59,7 +45,42 @@ namespace sprout {
// copysign(<28>}x, -NaN) returns -x for |x| is not NaN .
// # returns +x . ( same as copysign(<28>}x, +NaN) )
//
using NS_SPROUT_MATH_DETAIL::copysign;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
copysign(FloatType x, FloatType y) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_copysign(x, y)
#else
x == 0
? y == 0 ? y
: sprout::math::signbit(y) ? -FloatType(0)
: FloatType(0)
: sprout::math::isnan(x)
? sprout::math::isnan(y) ? y
: sprout::math::signbit(y) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::signbit(y) != sprout::math::signbit(x) ? -x
: x
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
copysign(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::copysign(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::copysign;

View file

@ -27,6 +27,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_cos(float x) {
return __builtin_cosf(x);
}
inline SPROUT_CONSTEXPR double
builtin_cos(double x) {
return __builtin_cos(x);
}
inline SPROUT_CONSTEXPR long double
builtin_cos(long double x) {
return __builtin_cosl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
cos_impl_1(T x2, std::size_t n, std::size_t last) {
@ -70,35 +85,35 @@ namespace sprout {
// cos_impl(T x) {
// return sprout::math::detail::cos_impl_1(sprout::math::fmod(sprout::math::fabs(x), sprout::math::two_pi<T>()));
// }
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cos(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::cos(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::cos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cos(IntType x) {
return sprout::math::detail::cos(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::cos;
//
// cos
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cos(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_cos(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::cos_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cos(IntType x) {
return sprout::math::cos(static_cast<double>(x));
}
} // namespace math
using sprout::math::cos;

View file

@ -21,6 +21,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_cosh(float x) {
return __builtin_coshf(x);
}
inline SPROUT_CONSTEXPR double
builtin_cosh(double x) {
return __builtin_cosh(x);
}
inline SPROUT_CONSTEXPR long double
builtin_cosh(long double x) {
return __builtin_coshl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
cosh_impl_1(T t) {
@ -31,35 +46,35 @@ namespace sprout {
cosh_impl(T x) {
return sprout::math::detail::cosh_impl_1(sprout::math::exp(x));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cosh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::cosh(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::cosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cosh(IntType x) {
return sprout::math::detail::cosh(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::cosh;
//
// cosh
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
cosh(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_cosh(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::cosh_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
cosh(IntType x) {
return sprout::math::cosh(static_cast<double>(x));
}
} // namespace math
using sprout::math::cosh;

View file

@ -14,12 +14,6 @@
# include <cmath>
#endif
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# define NS_SPROUT_MATH_DETAIL std
#else // #ifndef SPROUT_USE_BUILTIN_CMATH_FUNCTION
# define NS_SPROUT_MATH_DETAIL sprout::math::detail
#endif // #ifndef SPROUT_USE_BUILTIN_CMATH_FUNCTION
#if (FLT_RADIX == 2)
# define SPROUT_FLT_RADIX_IS_2 1
#else

View file

@ -22,6 +22,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_erf(float x) {
return __builtin_erff(x);
}
inline SPROUT_CONSTEXPR double
builtin_erf(double x) {
return __builtin_erf(x);
}
inline SPROUT_CONSTEXPR long double
builtin_erf(long double x) {
return __builtin_erfl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
erf_impl_3(T x, T y) {
@ -125,35 +140,35 @@ namespace sprout {
erf_impl(T x) {
return sprout::math::detail::erf_impl_1(x, x < 0 ? -x : x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
erf(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(1)
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::erf(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
erf(IntType x) {
return sprout::math::detail::erf(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::erf;
//
// erf
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
erf(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(1)
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_erf(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
erf(IntType x) {
return sprout::math::erf(static_cast<double>(x));
}
} // namespace math
using sprout::math::erf;

View file

@ -19,39 +19,54 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_erfc(float x) {
return __builtin_erfcf(x);
}
inline SPROUT_CONSTEXPR double
builtin_erfc(double x) {
return __builtin_erfc(x);
}
inline SPROUT_CONSTEXPR long double
builtin_erfc(long double x) {
return __builtin_erfcl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
erfc_impl(T x) {
return T(1) - sprout::math::erf(x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
erfc(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(2)
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::erfc(x)
#else
: static_cast<FloatType>(sprout::math::detail::erfc_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
erfc(IntType x) {
return sprout::math::detail::erfc(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::erfc;
//
// erfc
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
erfc(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(2)
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_erfc(x)
#else
: static_cast<FloatType>(sprout::math::detail::erfc_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
erfc(IntType x) {
return sprout::math::erfc(static_cast<double>(x));
}
} // namespace math
using sprout::math::erfc;

View file

@ -22,6 +22,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_exp(float x) {
return __builtin_expf(x);
}
inline SPROUT_CONSTEXPR double
builtin_exp(double x) {
return __builtin_exp(x);
}
inline SPROUT_CONSTEXPR long double
builtin_exp(long double x) {
return __builtin_expl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
exp_impl_1(T x, std::size_t n, std::size_t last) {
@ -38,35 +53,35 @@ namespace sprout {
: T(1) + sprout::math::detail::exp_impl_1(x, 1, sprout::math::factorial_limit<T>() / 2 + 1)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::exp(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp(IntType x) {
return sprout::math::detail::exp(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::exp;
//
// exp
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_exp(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp(IntType x) {
return sprout::math::exp(static_cast<double>(x));
}
} // namespace math
using sprout::math::exp;

View file

@ -26,31 +26,31 @@ namespace sprout {
exp10_impl(T x) {
return sprout::math::exp(x * sprout::math::ln_ten<T>());
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp10(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp10(IntType x) {
return sprout::math::detail::exp10(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::exp10;
//
// exp10
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp10(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp10(IntType x) {
return sprout::math::exp10(static_cast<double>(x));
}
} // namespace math
using sprout::math::exp10;

View file

@ -21,40 +21,56 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_exp2(float x) {
return __builtin_exp2f(x);
}
inline SPROUT_CONSTEXPR double
builtin_exp2(double x) {
return __builtin_exp2(x);
}
inline SPROUT_CONSTEXPR long double
builtin_exp2(long double x) {
return __builtin_exp2l(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
exp2_impl(T x) {
return sprout::math::exp(x * sprout::math::ln_two<T>());
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::exp2(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp2(IntType x) {
return sprout::math::detail::exp2(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::exp2;
//
// exp2
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
exp2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_exp2(x)
#else
: x == 0 ? FloatType(1)
: static_cast<FloatType>(sprout::math::detail::exp2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
exp2(IntType x) {
return sprout::math::exp2(static_cast<double>(x));
}
} // namespace math
using sprout::math::exp2;

View file

@ -22,40 +22,55 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_expm1(float x) {
return __builtin_expm1f(x);
}
inline SPROUT_CONSTEXPR double
builtin_expm1(double x) {
return __builtin_expm1(x);
}
inline SPROUT_CONSTEXPR long double
builtin_expm1(long double x) {
return __builtin_expm1l(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
expm1_impl(T x) {
return sprout::math::exp(x) - T(1);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
expm1(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::expm1(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::expm1_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
expm1(IntType x) {
return sprout::math::detail::expm1(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::expm1;
//
// expm1
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
expm1(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(-1)
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_expm1(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::expm1_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
expm1(IntType x) {
return sprout::math::expm1(static_cast<double>(x));
}
} // namespace math
using sprout::math::expm1;

View file

@ -18,28 +18,48 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fabs(FloatType x) {
return sprout::math::isnan(x) ? sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? FloatType(0)
: sprout::math::copysign(x, FloatType(0))
;
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_fabs(float x) {
return __builtin_fabsf(x);
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
fabs(IntType x) {
return sprout::math::detail::fabs(static_cast<double>(x));
builtin_fabs(double x) {
return __builtin_fabs(x);
}
inline SPROUT_CONSTEXPR long double
builtin_fabs(long double x) {
return __builtin_fabsl(x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::fabs;
//
// fabs
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fabs(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_fabs(x)
#else
sprout::math::isnan(x) ? sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? FloatType(0)
: sprout::math::copysign(x, FloatType(0))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
fabs(IntType x) {
return sprout::math::fabs(static_cast<double>(x));
}
} // namespace math
using sprout::math::fabs;

View file

@ -19,40 +19,55 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fdim(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: y == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: y == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::fdim(x, y)
#else
: x > y ? x - y : FloatType(0)
inline SPROUT_CONSTEXPR float
builtin_fdim(float x, float y) {
return __builtin_fdimf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_fdim(double x, double y) {
return __builtin_fdim(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_fdim(long double x, long double y) {
return __builtin_fdiml(x, y);
}
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fdim(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fdim(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
using sprout::math::detail::fdim;
//
// fdim
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fdim(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: y == sprout::numeric_limits<FloatType>::infinity() ? FloatType(0)
: y == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_fdim(x, y)
#else
: x > y ? x - y : FloatType(0)
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fdim(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::fdim(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::fdim;

View file

@ -18,30 +18,29 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float2_exponent(FloatType x) {
return sprout::math::isnan(x) ? 0
: x == 0 ? 0
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::ilogb2(x) + 1
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float2_exponent(IntType x) {
return sprout::math::detail::float2_exponent(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float2_exponent;
//
// float2_exponent
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float2_exponent(FloatType x) {
return sprout::math::isnan(x) ? 0
: x == 0 ? 0
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::ilogb2(x) + 1
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float2_exponent(IntType x) {
return sprout::math::float2_exponent(static_cast<double>(x));
}
} // namespace math
using sprout::math::float2_exponent;

View file

@ -27,32 +27,32 @@ namespace sprout {
typedef sprout::pair<T, int> type;
return type(x / sprout::detail::pow_n(T(2), exp), exp);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float2_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return sprout::math::isnan(x) ? type(x, 0)
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::infinity(), 0)
: x == 0 ? type(x, 0)
: sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, int>
float2_sig_exp(IntType x) {
return sprout::math::detail::float2_sig_exp(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float2_sig_exp;
//
// float2_sig_exp
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float2_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return sprout::math::isnan(x) ? type(x, 0)
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::infinity(), 0)
: x == 0 ? type(x, 0)
: sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, int>
float2_sig_exp(IntType x) {
return sprout::math::float2_sig_exp(static_cast<double>(x));
}
} // namespace math
using sprout::math::float2_sig_exp;

View file

@ -19,31 +19,30 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
float2_significand(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
float2_significand(IntType x) {
return sprout::math::detail::float_significand(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float2_significand;
//
// float2_significand
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
float2_significand(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
float2_significand(IntType x) {
return sprout::math::float_significand(static_cast<double>(x));
}
} // namespace math
using sprout::math::float2_significand;

View file

@ -18,30 +18,29 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float_exponent(FloatType x) {
return sprout::math::isnan(x) ? 0
: x == 0 ? 0
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::ilogb(x) + 1
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float_exponent(IntType x) {
return sprout::math::detail::float_exponent(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float_exponent;
//
// float_exponent
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float_exponent(FloatType x) {
return sprout::math::isnan(x) ? 0
: x == 0 ? 0
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::ilogb(x) + 1
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
float_exponent(IntType x) {
return sprout::math::float_exponent(static_cast<double>(x));
}
} // namespace math
using sprout::math::float_exponent;

View file

@ -27,32 +27,32 @@ namespace sprout {
typedef sprout::pair<T, int> type;
return type(x / sprout::detail::pow_n(T(sprout::numeric_limits<T>::radix), exp), exp);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return sprout::math::isnan(x) ? type(x, 0)
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::infinity(), 0)
: x == 0 ? type(x, 0)
: sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, int>
float_sig_exp(IntType x) {
return sprout::math::detail::float_sig_exp(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float_sig_exp;
//
// float_sig_exp
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return sprout::math::isnan(x) ? type(x, 0)
: x == sprout::numeric_limits<FloatType>::infinity() ? type(sprout::numeric_limits<FloatType>::infinity(), 0)
: x == -sprout::numeric_limits<FloatType>::infinity() ? type(-sprout::numeric_limits<FloatType>::infinity(), 0)
: x == 0 ? type(x, 0)
: sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, int>
float_sig_exp(IntType x) {
return sprout::math::float_sig_exp(static_cast<double>(x));
}
} // namespace math
using sprout::math::float_sig_exp;

View file

@ -19,31 +19,30 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
float_significand(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(sprout::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
float_significand(IntType x) {
return sprout::math::detail::float_significand(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::float_significand;
//
// float_significand
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
float_significand(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(sprout::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
float_significand(IntType x) {
return sprout::math::float_significand(static_cast<double>(x));
}
} // namespace math
using sprout::math::float_significand;

View file

@ -22,6 +22,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_floor(float x) {
return __builtin_floorf(x);
}
inline SPROUT_CONSTEXPR double
builtin_floor(double x) {
return __builtin_floor(x);
}
inline SPROUT_CONSTEXPR long double
builtin_floor(long double x) {
return __builtin_floorl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
floor_impl_1(T x, T x0) {
@ -36,37 +51,37 @@ namespace sprout {
: static_cast<T>(static_cast<std::uintmax_t>(x))
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
floor(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::floor(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::floor_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
floor(IntType x) {
return sprout::math::detail::floor(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::floor;
//
// floor
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
floor(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_floor(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("floor: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::floor_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
floor(IntType x) {
return sprout::math::floor(static_cast<double>(x));
}
} // namespace math
using sprout::math::floor;

View file

@ -21,48 +21,63 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fma(FloatType x, FloatType y, FloatType z) {
return sprout::math::isnan(x) ? x
: sprout::math::isnan(y) ? y
: sprout::math::isnan(z) ? z
: sprout::math::isinf(x) && y == 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
: (sprout::math::isinf(x) || sprout::math::isinf(y)) && sprout::math::isinf(z) && (sprout::math::signbit(x) ^ sprout::math::signbit(y) ^ sprout::math::signbit(z))
? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::fma(x, y, z)
#else
: x * y + z
inline SPROUT_CONSTEXPR float
builtin_fma(float x, float y, float z) {
return __builtin_fmaf(x, y, z);
}
inline SPROUT_CONSTEXPR double
builtin_fma(double x, double y, double z) {
return __builtin_fma(x, y, z);
}
inline SPROUT_CONSTEXPR long double
builtin_fma(long double x, long double y, long double z) {
return __builtin_fmal(x, y, z);
}
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename ArithmeticType3,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value
&& std::is_arithmetic<ArithmeticType2>::value
&& std::is_arithmetic<ArithmeticType3>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<
ArithmeticType1, ArithmeticType2, ArithmeticType3
>::type
fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) {
typedef typename sprout::float_promote<
ArithmeticType1, ArithmeticType2, ArithmeticType3
>::type type;
return sprout::math::detail::fma(static_cast<type>(x), static_cast<type>(y), static_cast<type>(z));
}
} // namespace detail
using sprout::math::detail::fma;
//
// fma
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fma(FloatType x, FloatType y, FloatType z) {
return sprout::math::isnan(x) ? x
: sprout::math::isnan(y) ? y
: sprout::math::isnan(z) ? z
: sprout::math::isinf(x) && y == 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::isinf(y) && x == 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
: (sprout::math::isinf(x) || sprout::math::isinf(y)) && sprout::math::isinf(z) && (sprout::math::signbit(x) ^ sprout::math::signbit(y) ^ sprout::math::signbit(z))
? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_fma(x, y, z)
#else
: x * y + z
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename ArithmeticType3,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value
&& std::is_arithmetic<ArithmeticType2>::value
&& std::is_arithmetic<ArithmeticType3>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<
ArithmeticType1, ArithmeticType2, ArithmeticType3
>::type
fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) {
typedef typename sprout::float_promote<
ArithmeticType1, ArithmeticType2, ArithmeticType3
>::type type;
return sprout::math::fma(static_cast<type>(x), static_cast<type>(y), static_cast<type>(z));
}
} // namespace math
using sprout::math::fma;

View file

@ -19,41 +19,56 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmax(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? x
: sprout::math::isnan(x) ? y
: y == -sprout::numeric_limits<FloatType>::infinity() ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? y
: y == sprout::numeric_limits<FloatType>::infinity() ? y
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: x == 0 && y == 0 ? x
: std::fmax(x, y)
#else
: x < y ? y : x
inline SPROUT_CONSTEXPR float
builtin_fmax(float x, float y) {
return __builtin_fmaxf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_fmax(double x, double y) {
return __builtin_fmax(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_fmax(long double x, long double y) {
return __builtin_fmaxl(x, y);
}
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmax(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fmax(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
using sprout::math::detail::fmax;
//
// fmax
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmax(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? x
: sprout::math::isnan(x) ? y
: y == -sprout::numeric_limits<FloatType>::infinity() ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? x
: x == -sprout::numeric_limits<FloatType>::infinity() ? y
: y == sprout::numeric_limits<FloatType>::infinity() ? y
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: x == 0 && y == 0 ? x
: sprout::math::detail::builtin_fmax(x, y)
#else
: x < y ? y : x
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmax(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::fmax(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::fmax;

View file

@ -19,41 +19,56 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmin(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? x
: sprout::math::isnan(x) ? y
: x == -sprout::numeric_limits<FloatType>::infinity() ? x
: y == sprout::numeric_limits<FloatType>::infinity() ? x
: y == -sprout::numeric_limits<FloatType>::infinity() ? y
: x == sprout::numeric_limits<FloatType>::infinity() ? y
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: x == 0 && y == 0 ? x
: std::fmin(x, y)
#else
: y < x ? y : x
inline SPROUT_CONSTEXPR float
builtin_fmin(float x, float y) {
return __builtin_fminf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_fmin(double x, double y) {
return __builtin_fmin(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_fmin(long double x, long double y) {
return __builtin_fminl(x, y);
}
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmin(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fmin(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
using sprout::math::detail::fmin;
//
// fmin
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmin(FloatType x, FloatType y) {
return sprout::math::isnan(y) ? x
: sprout::math::isnan(x) ? y
: x == -sprout::numeric_limits<FloatType>::infinity() ? x
: y == sprout::numeric_limits<FloatType>::infinity() ? x
: y == -sprout::numeric_limits<FloatType>::infinity() ? y
: x == sprout::numeric_limits<FloatType>::infinity() ? y
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: x == 0 && y == 0 ? x
: sprout::math::detail::builtin_fmin(x, y)
#else
: y < x ? y : x
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmin(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::fmin(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::fmin;

View file

@ -71,49 +71,49 @@ namespace sprout {
fmod_impl(T x, T y) {
return sprout::math::detail::fmod_impl_1(x, sprout::math::fabs(y), sprout::math::fabs(x));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmod(FloatType x, FloatType y) {
return sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) || sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() || y == 0
? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
: static_cast<FloatType>(sprout::math::detail::fmod_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmod(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fmod(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// fmod
//
// issue:
// fmod(-NaN, -NaN) returns -NaN .
// # returns +NaN . ( same as fmod(+NaN, +NaN) )
//
using sprout::math::detail::fmod;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmod(FloatType x, FloatType y) {
return sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) || sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() || y == 0
? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
: static_cast<FloatType>(sprout::math::detail::fmod_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
fmod(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::fmod(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::fmod;

View file

@ -21,22 +21,45 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR int
fpclassify(FloatType x) {
return sprout::math::isnan(x) ? FP_NAN
: sprout::math::isinf(x) ? FP_INFINITE
: sprout::math::iszero(x) ? FP_ZERO
: sprout::math::detail::issubnormal_or_zero(x) ? FP_SUBNORMAL
: FP_NORMAL
;
builtin_fpclassify(FloatType x) {
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::fpclassify;
//
// fpclassify
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
fpclassify(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_fpclassify(x)
#else
sprout::math::isnan(x) ? FP_NAN
: sprout::math::isinf(x) ? FP_INFINITE
: sprout::math::iszero(x) ? FP_ZERO
: sprout::math::detail::issubnormal_or_zero(x) ? FP_SUBNORMAL
: FP_NORMAL
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
fpclassify(IntType x) {
return x ? FP_NORMAL
: FP_ZERO
;
}
} // namespace math
using sprout::math::fpclassify;

View file

@ -32,26 +32,26 @@ namespace sprout {
: type(sprout::math::copysign(x - ipart, x), ipart)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, FloatType>
frac_int(FloatType x) {
return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x));
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, double>
frac_int(IntType x) {
return sprout::math::detail::frac_int(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::frac_int;
//
// frac_int
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, FloatType>
frac_int(FloatType x) {
return sprout::math::detail::frac_int_impl(x, sprout::integer_part(x));
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<double, double>
frac_int(IntType x) {
return sprout::math::frac_int(static_cast<double>(x));
}
} // namespace math
using sprout::math::frac_int;

View file

@ -27,30 +27,30 @@ namespace sprout {
: sprout::math::copysign(x - ipart, x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fractional_part(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::math::copysign(FloatType(0), x)
: x == 0 ? x
: sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
fractional_part(IntType x) {
return sprout::math::detail::fractional_part(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::fractional_part;
//
// fractional_part
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fractional_part(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::math::copysign(FloatType(0), x)
: x == 0 ? x
: sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
fractional_part(IntType x) {
return sprout::math::fractional_part(static_cast<double>(x));
}
} // namespace math
using sprout::math::fractional_part;

View file

@ -23,6 +23,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_hypot(float x, float y) {
return __builtin_hypotf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_hypot(double x, double y) {
return __builtin_hypot(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_hypot(long double x, long double y) {
return __builtin_hypotl(x, y);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
hypot_impl_2(T t, T w) {
@ -41,47 +56,47 @@ namespace sprout {
hypot_impl(T x, T y) {
return sprout::math::detail::hypot_impl_1(sprout::math::fabs(x), sprout::math::fabs(y));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
hypot(FloatType x, FloatType y) {
return y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::hypot(x, y)
#else
: y == 0 ? sprout::math::fabs(x)
: x == 0 ? sprout::math::fabs(y)
: static_cast<FloatType>(sprout::math::detail::hypot_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
hypot(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::hypot(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// hypot
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
hypot(FloatType x, FloatType y) {
return y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_hypot(x, y)
#else
: y == 0 ? sprout::math::fabs(x)
: x == 0 ? sprout::math::fabs(y)
: static_cast<FloatType>(sprout::math::detail::hypot_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
#endif
;
}
using sprout::math::detail::hypot;
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
hypot(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::hypot(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::hypot;

View file

@ -24,8 +24,8 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
iceil_impl(FloatType x) {
@ -34,18 +34,23 @@ namespace sprout {
: static_cast<To>(x)
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x))
;
}
} // namespace detail
//
// iceil
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x))
;
}
#else
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
iceil_impl(FloatType x, To x0) {
@ -53,33 +58,34 @@ namespace sprout {
: x0 + 1
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast<To>(x))
: sprout::math::detail::iceil_impl(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(IntType x) {
return sprout::math::detail::iceil<To>(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::iceil;
//
// iceil
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iceil: large float rounding."), static_cast<To>(x))
: sprout::math::detail::iceil_impl(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iceil(IntType x) {
return sprout::math::iceil<To>(static_cast<double>(x));
}
} // namespace math
using sprout::math::iceil;

View file

@ -24,8 +24,8 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
ifloor_impl(FloatType x) {
@ -34,18 +34,23 @@ namespace sprout {
: static_cast<To>(x)
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x))
;
}
} // namespace detail
//
// ifloor
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x))
;
}
#else
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
ifloor_impl(FloatType x, To x0) {
@ -53,33 +58,34 @@ namespace sprout {
: x0 - 1
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast<To>(x))
: sprout::math::detail::ifloor_impl(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(IntType x) {
return sprout::math::detail::ifloor<To>(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::ifloor;
//
// ifloor
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("ifloor: large float rounding."), static_cast<To>(x))
: sprout::math::detail::ifloor_impl(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
ifloor(IntType x) {
return sprout::math::ifloor<To>(static_cast<double>(x));
}
} // namespace math
using sprout::math::ifloor;

View file

@ -22,33 +22,48 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb(FloatType x) {
return sprout::math::iszero(x) ? FP_ILOGB0
: sprout::math::isinf(x) ? INT_MAX
: sprout::math::isnan(x) ? FP_ILOGBNAN
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::ilogb(x)
#else
: static_cast<int>(sprout::math::logb(x))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb(IntType x) {
return sprout::math::detail::ilogb(static_cast<double>(x));
builtin_ilogb(float x) {
return __builtin_ilogbf(x);
}
inline SPROUT_CONSTEXPR int
builtin_ilogb(double x) {
return __builtin_ilogb(x);
}
inline SPROUT_CONSTEXPR int
builtin_ilogb(long double x) {
return __builtin_ilogbl(x);
}
#endif
} // namespace detail
using sprout::math::detail::ilogb;
//
// ilogb
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb(FloatType x) {
return sprout::math::iszero(x) ? FP_ILOGB0
: sprout::math::isinf(x) ? INT_MAX
: sprout::math::isnan(x) ? FP_ILOGBNAN
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_ilogb(x)
#else
: static_cast<int>(sprout::math::logb(x))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb(IntType x) {
return sprout::math::ilogb(static_cast<double>(x));
}
} // namespace math
using sprout::math::ilogb;

View file

@ -25,49 +25,45 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_FLT_RADIX_IS_2
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(FloatType x) {
return sprout::math::ilogb(x);
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(IntType x) {
return sprout::math::ilogb(x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(FloatType x) {
return sprout::math::ilogb(x);
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(IntType x) {
return sprout::math::ilogb(x);
}
#else
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(FloatType x) {
return sprout::math::iszero(x) ? FP_ILOGB0
: sprout::math::isinf(x) ? INT_MAX
: sprout::math::isnan(x) ? FP_ILOGBNAN
: static_cast<int>(sprout::math::logb2(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(IntType x) {
return sprout::math::detail::ilogb2(static_cast<double>(x));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(FloatType x) {
return sprout::math::iszero(x) ? FP_ILOGB0
: sprout::math::isinf(x) ? INT_MAX
: sprout::math::isnan(x) ? FP_ILOGBNAN
: static_cast<int>(sprout::math::logb2(x))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int
ilogb2(IntType x) {
return sprout::math::ilogb2(static_cast<double>(x));
}
#endif
} // namespace detail
using sprout::math::detail::ilogb2;
} // namespace math
using sprout::math::ilogb2;

View file

@ -18,31 +18,30 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
integer_part(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: sprout::math::trunc(x)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
integer_part(IntType x) {
return sprout::math::detail::integer_part(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::integer_part;
//
// integer_part
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
integer_part(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: x == 0 ? x
: sprout::math::trunc(x)
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
integer_part(IntType x) {
return sprout::math::integer_part(static_cast<double>(x));
}
} // namespace math
using sprout::math::integer_part;

View file

@ -24,8 +24,8 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
iround_impl(FloatType x) {
@ -34,18 +34,23 @@ namespace sprout {
: static_cast<To>(x)
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::iround_impl<To>(sprout::math::round(x))
;
}
} // namespace detail
//
// iround
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::iround_impl<To>(sprout::math::round(x))
;
}
#else
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
iround_impl_positive(FloatType x, To x0) {
@ -60,34 +65,35 @@ namespace sprout {
: x0 - 1
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iround: large float irounding."), x)
: x < 0 ? sprout::math::detail::iround_impl_nagative(x, static_cast<To>(x))
: sprout::math::detail::iround_impl_positive(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(IntType x) {
return sprout::math::detail::iround(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::iround;
//
// iround
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("iround: large float irounding."), x)
: x < 0 ? sprout::math::detail::iround_impl_nagative(x, static_cast<To>(x))
: sprout::math::detail::iround_impl_positive(x, static_cast<To>(x))
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
iround(IntType x) {
return sprout::math::iround(static_cast<double>(x));
}
} // namespace math
using sprout::math::iround;

View file

@ -22,20 +22,20 @@ namespace sprout {
is_even_unchecked(T x) {
return sprout::math::fmod(x, T(2)) == T(0);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_even(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_even_unchecked(x)
;
}
} // namespace detail
using sprout::math::detail::is_even;
//
// is_even
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_even(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_even_unchecked(x)
;
}
} // namespace math
using sprout::math::is_even;

View file

@ -22,20 +22,20 @@ namespace sprout {
is_integer_unchecked(T x) {
return x == sprout::math::trunc(x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_integer(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_integer_unchecked(x)
;
}
} // namespace detail
using sprout::math::detail::is_integer;
//
// is_integer
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_integer(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_integer_unchecked(x)
;
}
} // namespace math
using sprout::math::is_integer;

View file

@ -22,20 +22,20 @@ namespace sprout {
is_odd_unchecked(T x) {
return sprout::math::fmod(x, T(2)) == T(1);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_odd(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_odd_unchecked(x)
;
}
} // namespace detail
using sprout::math::detail::is_odd;
//
// is_odd
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
is_odd(FloatType x) {
return sprout::math::isfinite(x)
&& sprout::math::detail::is_odd_unchecked(x)
;
}
} // namespace math
using sprout::math::is_odd;

View file

@ -18,19 +18,39 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR bool
isfinite(FloatType x) {
return !sprout::math::isnan(x)
&& !sprout::math::isinf(x)
;
builtin_isfinite(FloatType x) {
return __builtin_isfinite(x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::isfinite;
//
// isfinite
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isfinite(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_isfinite(x)
#else
!(sprout::math::isnan(x) || sprout::math::isinf(x))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isfinite(IntType x) {
return true;
}
} // namespace math
using sprout::math::isfinite;

View file

@ -17,19 +17,40 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR bool
isinf(FloatType x) {
return x == sprout::numeric_limits<FloatType>::infinity()
|| x == -sprout::numeric_limits<FloatType>::infinity()
;
builtin_isinf(FloatType x) {
return __builtin_isinf(x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::isinf;
//
// isinf
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isinf(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_isinf(x)
#else
x == sprout::numeric_limits<FloatType>::infinity()
|| x == -sprout::numeric_limits<FloatType>::infinity()
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isinf(IntType x) {
return false;
}
} // namespace math
using sprout::math::isinf;

View file

@ -16,17 +16,39 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR bool
isnan(FloatType x) {
return !(x == x);
builtin_isnan(FloatType x) {
return __builtin_isnan(x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::isnan;
//
// isnan
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isnan(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_isnan(x)
#else
!(x == x)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isnan(IntType x) {
return false;
}
} // namespace math
using sprout::math::isnan;

View file

@ -19,20 +19,41 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR bool
isnormal(FloatType x) {
return !sprout::math::isnan(x)
&& !sprout::math::isinf(x)
&& !sprout::math::detail::issubnormal_or_zero(x)
;
builtin_isnormal(FloatType x) {
return __builtin_isnormal(x);
}
#endif
} // namespace detail
using NS_SPROUT_MATH_DETAIL::isnormal;
//
// isnormal
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isnormal(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_isnormal(x)
#else
!sprout::math::isnan(x)
&& !sprout::math::isinf(x)
&& !sprout::math::detail::issubnormal_or_zero(x)
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
isnormal(IntType x) {
return x != 0;
}
} // namespace math
using sprout::math::isnormal;

View file

@ -18,6 +18,9 @@
namespace sprout {
namespace math {
namespace detail {
//
// issubnormal_or_zero
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
@ -29,21 +32,21 @@ namespace sprout {
: x > -sprout::numeric_limits<double>::min()
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
issubnormal(FloatType x) {
return !sprout::math::isnan(x)
&& !sprout::math::iszero(x)
&& sprout::math::detail::issubnormal_or_zero(x)
;
}
} // namespace detail
using sprout::math::detail::issubnormal;
//
// issubnormal
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
issubnormal(FloatType x) {
return !sprout::math::isnan(x)
&& !sprout::math::iszero(x)
&& sprout::math::detail::issubnormal_or_zero(x)
;
}
} // namespace math
using sprout::math::issubnormal;

View file

@ -14,18 +14,25 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
iszero(FloatType x) {
return x == 0;
}
} // namespace detail
using sprout::math::detail::iszero;
//
// iszero
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
iszero(FloatType x) {
return x == 0;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
iszero(IntType x) {
return x == 0;
}
} // namespace math
using sprout::math::iszero;

View file

@ -22,8 +22,8 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
namespace detail {
template<typename To, typename FloatType>
inline SPROUT_CONSTEXPR To
itrunc_impl(FloatType x) {
@ -32,45 +32,49 @@ namespace sprout {
: static_cast<To>(x)
;
}
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::itrunc_impl<To>(sprout::math::trunc(x))
;
}
#else
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast<To>(x))
: static_cast<To>(x)
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(IntType x) {
return sprout::math::detail::itrunc<To>(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::itrunc;
//
// itrunc
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: sprout::math::detail::itrunc_impl<To>(sprout::math::trunc(x))
;
}
#else
//
// itrunc
//
template<
typename To = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<To>::min()
: x == 0 ? To(0)
: sprout::numeric_limits<To>::max() < x || sprout::numeric_limits<To>::min() > x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("itrunc: large float rounding."), static_cast<To>(x))
: static_cast<To>(x)
;
}
#endif
template<
typename To = int,
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR To
itrunc(IntType x) {
return sprout::math::itrunc<To>(static_cast<double>(x));
}
} // namespace math
using sprout::math::itrunc;

View file

@ -20,37 +20,57 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_ldexp(float x, int exp) {
return __builtin_ldexpf(x, exp);
}
inline SPROUT_CONSTEXPR double
builtin_ldexp(double x, int exp) {
return __builtin_ldexp(x, exp);
}
inline SPROUT_CONSTEXPR long double
builtin_ldexp(long double x, int exp) {
return __builtin_ldexpl(x, exp);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
ldexp_impl(T x, int exp) {
return x * sprout::detail::pow_n(T(2), exp);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
ldexp(FloatType x, int exp) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::ldexp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
ldexp(IntType x, int exp) {
return sprout::math::detail::ldexp(static_cast<double>(x), exp);
}
} // namespace detail
using NS_SPROUT_MATH_DETAIL::ldexp;
//
// ldexp
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
ldexp(FloatType x, int exp) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_ldexp(x, exp)
#else
sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::ldexp_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
ldexp(IntType x, int exp) {
return sprout::math::ldexp(static_cast<double>(x), exp);
}
} // namespace math
using sprout::math::ldexp;

View file

@ -26,6 +26,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_lgamma(float x) {
return __builtin_lgammaf(x);
}
inline SPROUT_CONSTEXPR double
builtin_lgamma(double x) {
return __builtin_lgamma(x);
}
inline SPROUT_CONSTEXPR long double
builtin_lgamma(long double x) {
return __builtin_lgammal(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
lgamma_impl_3(T x, T y) {
@ -183,38 +198,38 @@ namespace sprout {
lgamma_impl(T x) {
return sprout::math::detail::lgamma_impl_1(x, x < 0 ? -x : x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
lgamma(FloatType x) {
return sprout::math::isnan(x) ? x
: x <= 0 && sprout::math::is_integer(x) ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
// : std::lgamma(x)
//#else
: x == 1 ? FloatType(0)
: x == 2 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
//#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
lgamma(IntType x) {
return sprout::math::detail::lgamma(static_cast<double>(x));
}
} // namespace detail
//
// lgamma
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
lgamma(FloatType x) {
return sprout::math::isnan(x) ? x
: x <= 0 && sprout::math::is_integer(x) ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
//#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
// : sprout::math::detail::builtin_lgamma(x)
//#else
: x == 1 ? FloatType(0)
: x == 2 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
//#endif
;
}
using sprout::math::detail::lgamma;
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
lgamma(IntType x) {
return sprout::math::lgamma(static_cast<double>(x));
}
} // namespace math
using sprout::math::lgamma;

View file

@ -20,35 +20,52 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long long
llround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long long>::min()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::llround(x)
#else
: sprout::math::iround<long long>(x);
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long long
llround(IntType x) {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
return std::llround(x);
#else
return sprout::math::iround<long long>(x);
#endif
builtin_llround(float x) {
return __builtin_llroundf(x);
}
inline SPROUT_CONSTEXPR long long
builtin_llround(double x) {
return __builtin_llround(x);
}
inline SPROUT_CONSTEXPR long long
builtin_llround(long double x) {
return __builtin_llroundl(x);
}
#endif
} // namespace detail
using sprout::math::detail::llround;
//
// llround
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long long
llround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long long>::min()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_llround(x)
#else
: sprout::math::iround<long long>(x);
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long long
llround(IntType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_llround(x)
#else
sprout::math::iround<long long>(x)
#endif
;
}
} // namespace math
using sprout::math::llround;

View file

@ -24,6 +24,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_log(float x) {
return __builtin_logf(x);
}
inline SPROUT_CONSTEXPR double
builtin_log(double x) {
return __builtin_log(x);
}
inline SPROUT_CONSTEXPR long double
builtin_log(long double x) {
return __builtin_logl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
log_impl_2(T x, std::size_t n, std::size_t last) {
@ -48,36 +63,36 @@ namespace sprout {
: sprout::math::detail::log_impl_1(x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::log(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log(IntType x) {
return sprout::math::detail::log(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::log;
//
// log
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_log(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log(IntType x) {
return sprout::math::log(static_cast<double>(x));
}
} // namespace math
using sprout::math::log;

View file

@ -21,41 +21,56 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_log10(float x) {
return __builtin_log10f(x);
}
inline SPROUT_CONSTEXPR double
builtin_log10(double x) {
return __builtin_log10(x);
}
inline SPROUT_CONSTEXPR long double
builtin_log10(long double x) {
return __builtin_log10l(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
log10_impl(T x) {
return sprout::math::log(x) / sprout::math::ln_ten<T>();
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log10(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::log10(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log10(IntType x) {
return sprout::math::detail::log10(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::log10;
//
// log10
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log10(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_log10(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log10_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log10(IntType x) {
return sprout::math::log10(static_cast<double>(x));
}
} // namespace math
using sprout::math::log10;

View file

@ -20,41 +20,56 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_log1p(float x) {
return __builtin_log1pf(x);
}
inline SPROUT_CONSTEXPR double
builtin_log1p(double x) {
return __builtin_log1p(x);
}
inline SPROUT_CONSTEXPR long double
builtin_log1p(long double x) {
return __builtin_log1pl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
log1p_impl(T x) {
return sprout::math::log(T(1) + x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log1p(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < -1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::log1p(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::log1p_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log1p(IntType x) {
return sprout::math::detail::log1p(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::log1p;
//
// log1p
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log1p(FloatType x) {
return sprout::math::isnan(x) ? x
: x == -1 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < -1 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_log1p(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::log1p_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log1p(IntType x) {
return sprout::math::log1p(static_cast<double>(x));
}
} // namespace math
using sprout::math::log1p;

View file

@ -21,41 +21,56 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_log2(float x) {
return __builtin_log2f(x);
}
inline SPROUT_CONSTEXPR double
builtin_log2(double x) {
return __builtin_log2(x);
}
inline SPROUT_CONSTEXPR long double
builtin_log2(long double x) {
return __builtin_log2l(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
log2_impl(T x) {
return sprout::math::log(x) / sprout::math::ln_two<T>();
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::log2(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log2(IntType x) {
return sprout::math::detail::log2(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::log2;
//
// log2
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x < 0 ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_log2(x)
#else
: x == 1 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::log2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
log2(IntType x) {
return sprout::math::log2(static_cast<double>(x));
}
} // namespace math
using sprout::math::log2;

View file

@ -28,34 +28,34 @@ namespace sprout {
: sprout::math::log(y) / sprout::math::log(x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log_a(FloatType x, FloatType y) {
return static_cast<FloatType>(sprout::math::detail::log_a_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
));
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
log_a(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::log_a(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// log_a
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
log_a(FloatType x, FloatType y) {
return static_cast<FloatType>(sprout::math::detail::log_a_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
));
}
using sprout::math::detail::log_a;
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
log_a(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::log_a(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::log_a;

View file

@ -25,6 +25,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_logb(float x) {
return __builtin_logbf(x);
}
inline SPROUT_CONSTEXPR double
builtin_logb(double x) {
return __builtin_logb(x);
}
inline SPROUT_CONSTEXPR long double
builtin_logb(long double x) {
return __builtin_logbl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
logb_impl_3_neg_lo(T x, T x0, T base, T exp) {
@ -100,39 +115,39 @@ namespace sprout {
: sprout::math::detail::logb_impl_1(x, sprout::math::trunc(sprout::math::log_a(T(sprout::numeric_limits<T>::radix), x)))
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
} // namespace detail
//
// logb
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# if defined(__GNUC__)
: x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
# endif
: std::logb(x)
: sprout::math::detail::builtin_logb(x)
#else
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: static_cast<FloatType>(sprout::math::detail::logb_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: static_cast<FloatType>(sprout::math::detail::logb_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb(IntType x) {
return sprout::math::detail::logb(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::logb;
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb(IntType x) {
return sprout::math::logb(static_cast<double>(x));
}
} // namespace math
using sprout::math::logb;

View file

@ -28,25 +28,28 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_FLT_RADIX_IS_2
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb2(FloatType x) {
return sprout::math::logb(x);
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb2(IntType x) {
return sprout::math::logb(x);
}
//
// logb2
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb2(FloatType x) {
return sprout::math::logb(x);
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb2(IntType x) {
return sprout::math::logb(x);
}
#else
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T
logb2_impl_3_neg_lo(T x, T x0, T base, T exp) {
@ -122,32 +125,32 @@ namespace sprout {
: sprout::math::detail::logb2_impl_1(x, sprout::math::trunc(sprout::math::log_a(T(2), x)))
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: static_cast<FloatType>(sprout::math::detail::logb2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb2(IntType x) {
return sprout::math::detail::logb2(static_cast<double>(x));
}
#endif
} // namespace detail
using sprout::math::detail::logb2;
//
// logb2
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
logb2(FloatType x) {
return sprout::math::isnan(x) ? x
: x == 0 ? -sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? sprout::numeric_limits<FloatType>::infinity()
: static_cast<FloatType>(sprout::math::detail::logb2_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
logb2(IntType x) {
return sprout::math::logb2(static_cast<double>(x));
}
#endif
} // namespace math
using sprout::math::logb2;

View file

@ -20,35 +20,52 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long
lround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long>::min()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::lround(x)
#else
: sprout::math::iround<long>(x);
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long
lround(IntType x) {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
return std::lround(x);
#else
return sprout::math::iround<long>(x);
#endif
builtin_lround(float x) {
return __builtin_lroundf(x);
}
inline SPROUT_CONSTEXPR long
builtin_lround(double x) {
return __builtin_lround(x);
}
inline SPROUT_CONSTEXPR long
builtin_lround(long double x) {
return __builtin_lroundl(x);
}
#endif
} // namespace detail
using sprout::math::detail::lround;
//
// lround
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long
lround(FloatType x) {
return sprout::math::isnan(x) || sprout::math::isinf(x) ? sprout::numeric_limits<long>::min()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_lround(x)
#else
: sprout::math::iround<long>(x);
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR long
lround(IntType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_lround(x)
#else
sprout::math::iround<long>(x)
#endif
;
}
} // namespace math
using sprout::math::lround;

View file

@ -26,76 +26,91 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_pow(float x, float y) {
return __builtin_powf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_pow(double x, double y) {
return __builtin_pow(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_pow(long double x, long double y) {
return __builtin_powl(x, y);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
pow_impl(T x, T y) {
return sprout::math::exp(y * sprout::math::log(x));
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
pow(FloatType x, FloatType y) {
return x == 1 ? FloatType(1)
: y == 0 ? FloatType(1)
: sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
: x == 0
? y < 0
? sprout::math::is_odd(y) ? sprout::math::copysign(sprout::numeric_limits<FloatType>::infinity(), x)
: sprout::numeric_limits<FloatType>::infinity()
: sprout::math::is_odd(y) ? x
: FloatType(0)
: x == -1 && (y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()) ? FloatType(1)
: y == -sprout::numeric_limits<FloatType>::infinity()
? sprout::math::fabs(x) < 1 ? sprout::numeric_limits<FloatType>::infinity()
: FloatType(0)
: y == sprout::numeric_limits<FloatType>::infinity()
? sprout::math::fabs(x) < 1 ? FloatType(0)
: sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity()
? y < 0
? sprout::math::is_odd(y) ? -FloatType(0)
: FloatType(0)
: sprout::math::is_odd(y) ? -sprout::numeric_limits<FloatType>::infinity()
: sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity()
? y < 0 ? FloatType(0)
: sprout::numeric_limits<FloatType>::infinity()
: x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::pow(x, y)
#else
: static_cast<FloatType>(sprout::math::detail::pow_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
pow(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::pow(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// pow
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// pow(-0, y) returns -<2D>‡ for y an odd integer < 0.
// # returns +<2B>‡ . ( same as pow(+0, y) )
//
using sprout::math::detail::pow;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
pow(FloatType x, FloatType y) {
return x == 1 ? FloatType(1)
: y == 0 ? FloatType(1)
: sprout::math::isnan(y) ? y
: sprout::math::isnan(x) ? x
: x == 0
? y < 0
? sprout::math::is_odd(y) ? sprout::math::copysign(sprout::numeric_limits<FloatType>::infinity(), x)
: sprout::numeric_limits<FloatType>::infinity()
: sprout::math::is_odd(y) ? x
: FloatType(0)
: x == -1 && (y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity()) ? FloatType(1)
: y == -sprout::numeric_limits<FloatType>::infinity()
? sprout::math::fabs(x) < 1 ? sprout::numeric_limits<FloatType>::infinity()
: FloatType(0)
: y == sprout::numeric_limits<FloatType>::infinity()
? sprout::math::fabs(x) < 1 ? FloatType(0)
: sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity()
? y < 0
? sprout::math::is_odd(y) ? -FloatType(0)
: FloatType(0)
: sprout::math::is_odd(y) ? -sprout::numeric_limits<FloatType>::infinity()
: sprout::numeric_limits<FloatType>::infinity()
: x == sprout::numeric_limits<FloatType>::infinity()
? y < 0 ? FloatType(0)
: sprout::numeric_limits<FloatType>::infinity()
: x < 0 && !sprout::math::is_integer(y) ? sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_pow(x, y)
#else
: static_cast<FloatType>(sprout::math::detail::pow_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
pow(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::pow(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::pow;

View file

@ -20,39 +20,38 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename R = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR R
quotient(FloatType x, FloatType y) {
return y == 0 ? R(0)
: sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0)
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? R(0)
: x == 0 ? R(0)
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? R(0)
: sprout::math::rem_quo<R>(x, y).second
;
}
template<
typename R = int,
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR R
quotient(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::quotient(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
using sprout::math::detail::quotient;
//
// quotient
//
template<
typename R = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR R
quotient(FloatType x, FloatType y) {
return y == 0 ? R(0)
: sprout::math::isnan(y) || sprout::math::isnan(x) ? R(0)
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? R(0)
: x == 0 ? R(0)
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? R(0)
: sprout::math::rem_quo<R>(x, y).second
;
}
template<
typename R = int,
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR R
quotient(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::quotient(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::quotient;

View file

@ -87,55 +87,56 @@ namespace sprout {
rem_quo_impl(T x, T y, R iquo) {
return sprout::math::detail::rem_quo_impl_1(x, sprout::math::fabs(y), (sprout::math::signbit(x) ^ sprout::math::signbit(y) ? -1 : 1), iquo, sprout::math::fabs(x));
}
template<
typename R = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, R>
rem_quo(FloatType x, FloatType y) {
typedef sprout::pair<FloatType, R> type;
return y == 0 ? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: sprout::math::isnan(y)
? sprout::math::isnan(x)
? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN() : sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: type(y, R(0))
: sprout::math::isnan(x) ? type(x, R(0))
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: x == 0 ? type(x, R(0))
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? type(x, R(0))
: sprout::math::detail::rem_quo_ret<R, FloatType>(sprout::math::detail::rem_quo_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
R(0)
))
;
}
template<
typename R = int,
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<
typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type,
R
>
rem_quo(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::rem_quo(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// rem_quo
//
//
// issue:
// rem_quo(-NaN, -NaN) returns {-NaN, _} .
// # returns {+NaN, _} . ( same as rem_quo(+NaN, +NaN) )
//
using sprout::math::detail::rem_quo;
template<
typename R = int,
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<R>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<FloatType, R>
rem_quo(FloatType x, FloatType y) {
typedef sprout::pair<FloatType, R> type;
return y == 0 ? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: sprout::math::isnan(y)
? sprout::math::isnan(x)
? type(sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN() : sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: type(y, R(0))
: sprout::math::isnan(x) ? type(x, R(0))
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? type(-sprout::numeric_limits<FloatType>::quiet_NaN(), R(0))
: x == 0 ? type(x, R(0))
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? type(x, R(0))
: sprout::math::detail::rem_quo_ret<R, FloatType>(sprout::math::detail::rem_quo_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y),
R(0)
))
;
}
template<
typename R = int,
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value && std::is_integral<R>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR sprout::pair<
typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type,
R
>
rem_quo(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::rem_quo(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::rem_quo;

View file

@ -21,49 +21,64 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
remainder(FloatType x, FloatType y) {
return y == 0 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::remainder(x, y)
#else
: sprout::math::rem_quo(x, y).first
inline SPROUT_CONSTEXPR float
builtin_remainder(float x, float y) {
return __builtin_remainderf(x, y);
}
inline SPROUT_CONSTEXPR double
builtin_remainder(double x, double y) {
return __builtin_remainder(x, y);
}
inline SPROUT_CONSTEXPR long double
builtin_remainder(long double x, long double y) {
return __builtin_remainderl(x, y);
}
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
remainder(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::remainder(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
//
// remainder
//
// issue:
// remainder(-NaN, -NaN) returns -NaN .
// # returns +NaN . ( same as remainder(+NaN, +NaN) )
//
using sprout::math::detail::remainder;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
remainder(FloatType x, FloatType y) {
return y == 0 ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::math::isnan(y)
? sprout::math::isnan(x)
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -sprout::numeric_limits<FloatType>::quiet_NaN()
: sprout::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: y == sprout::numeric_limits<FloatType>::infinity() || y == -sprout::numeric_limits<FloatType>::infinity() ? x
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_remainder(x, y)
#else
: sprout::math::rem_quo(x, y).first
#endif
;
}
template<
typename ArithmeticType1,
typename ArithmeticType2,
typename sprout::enabler_if<
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
remainder(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::remainder(static_cast<type>(x), static_cast<type>(y));
}
} // namespace math
using sprout::math::remainder;

View file

@ -21,6 +21,21 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_round(float x) {
return __builtin_roundf(x);
}
inline SPROUT_CONSTEXPR double
builtin_round(double x) {
return __builtin_round(x);
}
inline SPROUT_CONSTEXPR long double
builtin_round(long double x) {
return __builtin_roundl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
round_impl_positive(T x, T x0) {
@ -42,37 +57,37 @@ namespace sprout {
: sprout::math::detail::round_impl_positive(x, static_cast<T>(static_cast<std::uintmax_t>(x)))
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
round(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::round(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::round_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
round(IntType x) {
return sprout::math::detail::round(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::round;
//
// round
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
round(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_round(x)
#else
: x == 0 ? x
: sprout::numeric_limits<std::uintmax_t>::max() < x || sprout::numeric_limits<std::uintmax_t>::max() < -x
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::runtime_error("round: large float rounding."), x)
: static_cast<FloatType>(sprout::math::detail::round_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
round(IntType x) {
return sprout::math::round(static_cast<double>(x));
}
} // namespace math
using sprout::math::round;

View file

@ -20,37 +20,57 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_scalbln(float x, long exp) {
return __builtin_scalblnf(x, exp);
}
inline SPROUT_CONSTEXPR double
builtin_scalbln(double x, long exp) {
return __builtin_scalbln(x, exp);
}
inline SPROUT_CONSTEXPR long double
builtin_scalbln(long double x, long exp) {
return __builtin_scalblnl(x, exp);
}
#endif
template<typename FloatType, typename T>
inline SPROUT_CONSTEXPR T
scalbln_impl(T x, long exp) {
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), exp);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
scalbln(FloatType x, long exp) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::scalbln_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
scalbln(IntType x, long exp) {
return sprout::math::detail::scalbln(static_cast<double>(x), exp);
}
} // namespace detail
using NS_SPROUT_MATH_DETAIL::scalbln;
//
// scalbln
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
scalbln(FloatType x, long exp) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_scalbln(x, exp)
#else
sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::scalbln_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
scalbln(IntType x, long exp) {
return sprout::math::scalbln(static_cast<double>(x), exp);
}
} // namespace math
using sprout::math::scalbln;

View file

@ -20,37 +20,57 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_scalbn(float x, int exp) {
return __builtin_scalbnf(x, exp);
}
inline SPROUT_CONSTEXPR double
builtin_scalbn(double x, int exp) {
return __builtin_scalbn(x, exp);
}
inline SPROUT_CONSTEXPR long double
builtin_scalbn(long double x, int exp) {
return __builtin_scalbnl(x, exp);
}
#endif
template<typename FloatType, typename T>
inline SPROUT_CONSTEXPR T
scalbn_impl(T x, int exp) {
return x * sprout::detail::pow_n(T(sprout::numeric_limits<FloatType>::radix), exp);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
scalbn(FloatType x, int exp) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::scalbn_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
scalbn(IntType x, int exp) {
return sprout::math::detail::scalbn(static_cast<double>(x), exp);
}
} // namespace detail
using NS_SPROUT_MATH_DETAIL::scalbn;
//
// scalbn
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
scalbn(FloatType x, int exp) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_scalbn(x, exp)
#else
sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() ? sprout::numeric_limits<FloatType>::infinity()
: x == -sprout::numeric_limits<FloatType>::infinity() ? -sprout::numeric_limits<FloatType>::infinity()
: exp == 0 ? x
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::scalbn_impl<FloatType>(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x), exp))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
scalbn(IntType x, int exp) {
return sprout::math::scalbn(static_cast<double>(x), exp);
}
} // namespace math
using sprout::math::scalbn;

View file

@ -17,16 +17,17 @@
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
template<typename FloatType>
inline SPROUT_CONSTEXPR bool
signbit(FloatType x) {
return !sprout::math::isnan(x) && x < 0;
builtin_signbit(FloatType x) {
return __builtin_signbit(x);
}
#endif
} // namespace detail
//
// signbit
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// signbit(-0) returns false .
@ -34,7 +35,28 @@ namespace sprout {
// signbit(-NaN) returns false .
// # returns true . ( same as signbit(+NaN) )
//
using NS_SPROUT_MATH_DETAIL::signbit;
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
signbit(FloatType x) {
return
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
sprout::math::detail::builtin_signbit(x)
#else
!sprout::math::isnan(x) && x < 0
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR bool
signbit(IntType x) {
return x < 0;
}
} // namespace math
using sprout::math::signbit;

View file

@ -21,40 +21,55 @@
namespace sprout {
namespace math {
namespace detail {
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
inline SPROUT_CONSTEXPR float
builtin_sin(float x) {
return __builtin_sinf(x);
}
inline SPROUT_CONSTEXPR double
builtin_sin(double x) {
return __builtin_sin(x);
}
inline SPROUT_CONSTEXPR long double
builtin_sin(long double x) {
return __builtin_sinl(x);
}
#endif
template<typename T>
inline SPROUT_CONSTEXPR T
sin_impl(T x) {
return -sprout::math::cos(x + sprout::math::half_pi<T>());
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
sin(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::sin(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::sin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
sin(IntType x) {
return sprout::math::detail::sin(static_cast<double>(x));
}
} // namespace detail
using sprout::math::detail::sin;
//
// sin
//
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
sin(FloatType x) {
return sprout::math::isnan(x) ? x
: x == sprout::numeric_limits<FloatType>::infinity() || x == -sprout::numeric_limits<FloatType>::infinity()
? -sprout::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: sprout::math::detail::builtin_sin(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::sin_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR double
sin(IntType x) {
return sprout::math::sin(static_cast<double>(x));
}
} // namespace math
using sprout::math::sin;

Some files were not shown because too many files have changed in this diff Show more