aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2014-12-08 16:26:53 +0100
committerGravatar Gael Guennebaud <g.gael@free.fr>2014-12-08 16:26:53 +0100
commitbea36925dbdd753c861d650623ae2692bb9de812 (patch)
treea89eba4894f0e171e834b598528ed936f3706001 /Eigen
parent7f7a71206267014f33a175322789977047ced24f (diff)
bug #876: implement a portable log1p function
Diffstat (limited to 'Eigen')
-rw-r--r--Eigen/src/Core/MathFunctions.h85
1 files changed, 52 insertions, 33 deletions
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h
index 4c5fc1cae..72d6acfc1 100644
--- a/Eigen/src/Core/MathFunctions.h
+++ b/Eigen/src/Core/MathFunctions.h
@@ -14,7 +14,7 @@ namespace Eigen {
// On WINCE, std::abs is defined for int only, so let's defined our own overloads:
// This issue has been confirmed with MSVC 2008 only, but the issue might exist for more recent versions too.
-#if defined(_WIN32_WCE) && defined(_MSC_VER) && _MSC_VER<=1500
+#if EIGEN_OS_WINCE && EIGEN_COMP_MSVC && EIGEN_COMP_MSVC<=1500
long abs(long x) { return (labs(x)); }
double abs(double x) { return (fabs(x)); }
float abs(float x) { return (fabsf(x)); }
@@ -360,50 +360,31 @@ inline NewType cast(const OldType& x)
}
/****************************************************************************
-* Implementation of atanh2 *
+* Implementation of logp1 *
****************************************************************************/
template<typename Scalar>
-struct atanh2_impl
+struct log1p_impl
{
- static inline Scalar run(const Scalar& x, const Scalar& r)
+ static inline Scalar run(const Scalar& x)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
- #if (__cplusplus >= 201103L) && !defined(__CYGWIN__)
+ // Let's be conservative and enable the default C++11 implementation only if we are sure it exists
+ #if (__cplusplus >= 201103L) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC || EIGEN_COMP_ICC) \
+ && (EIGEN_ARCH_i386_OR_x86_64) && (EIGEN_OS_GNULINUX || EIGEN_OS_WIN_STRICT || EIGEN_OS_MAC)
using std::log1p;
- return log1p(2 * x / (r - x)) / 2;
+ return log1p(x);
#else
- using std::abs;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
using std::log;
- using std::sqrt;
- Scalar z = x / r;
- if (r == 0 || abs(z) > sqrt(NumTraits<Scalar>::epsilon()))
- return log((r + x) / (r - x)) / 2;
- else
- return z + z*z*z / 3;
+ Scalar x1p = RealScalar(1) + x;
+ return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) );
#endif
}
};
-template<typename RealScalar>
-struct atanh2_impl<std::complex<RealScalar> >
-{
- typedef std::complex<RealScalar> Scalar;
- static inline Scalar run(const Scalar& x, const Scalar& r)
- {
- using std::log;
- using std::norm;
- using std::sqrt;
- Scalar z = x / r;
- if (r == Scalar(0) || norm(z) > NumTraits<RealScalar>::epsilon())
- return RealScalar(0.5) * log((r + x) / (r - x));
- else
- return z + z*z*z / RealScalar(3);
- }
-};
-
template<typename Scalar>
-struct atanh2_retval
+struct log1p_retval
{
typedef Scalar type;
};
@@ -680,9 +661,9 @@ inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar&
template<typename Scalar>
EIGEN_DEVICE_FUNC
-inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
+inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x)
{
- return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
+ return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x);
}
template<typename Scalar>
@@ -727,6 +708,44 @@ inline int log2(int x)
} // end namespace numext
+
+namespace internal {
+
+/****************************************************************************
+* Implementation of atanh2 *
+****************************************************************************/
+
+template<typename Scalar>
+struct atanh2_impl
+{
+ static inline Scalar run(const Scalar& x, const Scalar& r)
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ return numext::log1p(RealScalar(2) * x / (r - x)) / RealScalar(2);
+ }
+};
+
+template<typename Scalar>
+struct atanh2_retval
+{
+ typedef Scalar type;
+};
+
+
+} // end namespace internal
+
+namespace numext {
+
+template<typename Scalar>
+EIGEN_DEVICE_FUNC
+inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
+{
+ return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
+}
+
+} // end namespace numext
+
namespace internal {
/****************************************************************************