add sprout::cbrt, hypot, fmax, fmin, fdim

fix sprout::pow case x==0
This commit is contained in:
bolero-MURAKAMI 2012-05-05 18:50:17 +09:00
parent feba220da4
commit 6ccd6e1cf4
10 changed files with 273 additions and 17 deletions

47
sprout/math/cbrt.hpp Normal file
View file

@ -0,0 +1,47 @@
#ifndef SPROUT_MATH_CBRT_HPP
#define SPROUT_MATH_CBRT_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/utility/enabler_if.hpp>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# include <cmath>
#endif
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
cbrt(FloatType x) {
return x < 0 ? -sprout::math::detail::pow(-x, sprout::math::third<FloatType>())
: sprout::math::detail::pow(x, sprout::math::third<FloatType>())
;
}
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
# if SPROUT_USE_BUILTIN_CMATH_FUNCTION
using std::cbrt;
# else
using sprout::math::detail::cbrt;
# endif
} // namespace math
using sprout::math::cbrt;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_CBRT_HPP

View file

@ -7,35 +7,46 @@ namespace sprout {
namespace math {
//
// pi
// half_pi
// quarter_pi
//
template<typename T>
inline SPROUT_CONSTEXPR T pi() {
return 3.141592653589793238462643383279502884197169399375105820974944L;
}
//
// half_pi
//
template<typename T>
inline SPROUT_CONSTEXPR T half_pi() {
return 1.570796326794896619231321691639751442098584699687552910487472L;
}
//
// quarter_pi
//
template<typename T>
inline SPROUT_CONSTEXPR T quarter_pi() {
return 0.785398163397448309615660845819875721049292349843776455243736L;
}
//
// half
// third
// twothirds
//
template<typename T>
inline SPROUT_CONSTEXPR T half() {
return 0.5L;
}
template<typename T>
inline SPROUT_CONSTEXPR T third() {
return 0.3333333333333333333333333333333333333333333333333333333333333333333333L;
}
template<typename T>
inline SPROUT_CONSTEXPR T twothirds() {
return 0.6666666666666666666666666666666666666666666666666666666666666666666666L;
}
//
// root_two
// half_root_two
//
template<typename T>
inline SPROUT_CONSTEXPR T root_two() {
return 1.414213562373095048801688724209698078569671875376948073L;
}
//
// half_root_two
//
template<typename T>
inline SPROUT_CONSTEXPR T half_root_two() {
return 0.70710678118654752440084436210484903928483593756084L;
@ -49,14 +60,12 @@ namespace sprout {
}
//
// ln_ten
// ln_two
//
template<typename T>
inline SPROUT_CONSTEXPR T ln_ten() {
return 2.302585092994045684017991454684364207601101488628772976L;
}
//
// ln_two
//
template<typename T>
inline SPROUT_CONSTEXPR T ln_two() {
return 0.693147180559945309417232121458176568075500134360255254L;

View file

@ -1,5 +1,5 @@
#ifndef SPROUT_MATH_ABS_HPP
#define SPROUT_MATH_ABS_HPP
#ifndef SPROUT_MATH_FABS_HPP
#define SPROUT_MATH_FABS_HPP
#include <type_traits>
#include <sprout/config.hpp>
@ -64,4 +64,4 @@ namespace sprout {
using sprout::math::fabs;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_ABS_HPP
#endif // #ifndef SPROUT_MATH_FABS_HPP

48
sprout/math/fdim.hpp Normal file
View file

@ -0,0 +1,48 @@
#ifndef SPROUT_MATH_FDIM_HPP
#define SPROUT_MATH_FDIM_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/float_promote.hpp>
#include <sprout/utility/enabler_if.hpp>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# include <cmath>
#endif
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 x > y ? x - y : 0;
}
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::math::float_promote<ArithmeticType1, ArithmeticType2>::type
fdim(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fdim(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
# if SPROUT_USE_BUILTIN_CMATH_FUNCTION
using std::fdim;
# else
using sprout::math::detail::fdim;
# endif
} // namespace math
using sprout::math::fdim;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_FDIM_HPP

48
sprout/math/fmax.hpp Normal file
View file

@ -0,0 +1,48 @@
#ifndef SPROUT_MATH_FMAX_HPP
#define SPROUT_MATH_FMAX_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/float_promote.hpp>
#include <sprout/utility/enabler_if.hpp>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# include <cmath>
#endif
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 x < y ? y : x;
}
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::math::float_promote<ArithmeticType1, ArithmeticType2>::type
fmax(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fmax(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
# if SPROUT_USE_BUILTIN_CMATH_FUNCTION
using std::fmax;
# else
using sprout::math::detail::fmax;
# endif
} // namespace math
using sprout::math::fmax;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_FMAX_HPP

48
sprout/math/fmin.hpp Normal file
View file

@ -0,0 +1,48 @@
#ifndef SPROUT_MATH_FMIN_HPP
#define SPROUT_MATH_FMIN_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/float_promote.hpp>
#include <sprout/utility/enabler_if.hpp>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# include <cmath>
#endif
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 x > y ? y : x;
}
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::math::float_promote<ArithmeticType1, ArithmeticType2>::type
fmin(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::fmin(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
# if SPROUT_USE_BUILTIN_CMATH_FUNCTION
using std::fmin;
# else
using sprout::math::detail::fmin;
# endif
} // namespace math
using sprout::math::fmin;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_FMIN_HPP

49
sprout/math/hypot.hpp Normal file
View file

@ -0,0 +1,49 @@
#ifndef SPROUT_MATH_HYPOT_HPP
#define SPROUT_MATH_HYPOT_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/float_promote.hpp>
#include <sprout/math/sqrt.hpp>
#include <sprout/utility/enabler_if.hpp>
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
# include <cmath>
#endif
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
hypot(FloatType x, FloatType y) {
return sprout::math::detail::sqrt(x * x + y * 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::math::float_promote<ArithmeticType1, ArithmeticType2>::type
hypot(ArithmeticType1 x, ArithmeticType2 y) {
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
return sprout::math::detail::hypot(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
# if SPROUT_USE_BUILTIN_CMATH_FUNCTION
using std::hypot;
# else
using sprout::math::detail::hypot;
# endif
} // namespace math
using sprout::math::hypot;
} // namespace sprout
#endif // #ifndef SPROUT_MATH_HYPOT_HPP

View file

@ -1,6 +1,9 @@
#ifndef SPROUT_MATH_OPERATIONS_HPP
#define SPROUT_MATH_OPERATIONS_HPP
#include <sprout/math/abs.hpp>
#include <sprout/math/fabs.hpp>
#include <sprout/math/fmax.hpp>
#include <sprout/math/fmin.hpp>
#include <sprout/math/fdim.hpp>
#endif // #ifndef SPROUT_MATH_OPERATIONS_HPP

View file

@ -21,7 +21,9 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
pow(FloatType x, FloatType y) {
return sprout::math::detail::exp(y * sprout::math::detail::log(x));
return x == 0 && y > 0 ? FloatType(0)
: sprout::math::detail::exp(y * sprout::math::detail::log(x))
;
}
template<

View file

@ -2,6 +2,8 @@
#define SPROUT_MATH_POWER_HPP
#include <sprout/math/sqrt.hpp>
#include <sprout/math/cbrt.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/math/hypot.hpp>
#endif // #ifndef SPROUT_MATH_POWER_HPP