From fa4f933c0fe65eda6a051f978db12210f11f5cdb Mon Sep 17 00:00:00 2001 From: Eugene Brevdo Date: Mon, 7 Dec 2015 15:24:49 -0800 Subject: Add special functions to Eigen: lgamma, erf, erfc. Includes CUDA support and unit tests. --- Eigen/Core | 1 + Eigen/src/Core/GenericPacketMath.h | 15 ++++ Eigen/src/Core/GlobalFunctions.h | 3 + Eigen/src/Core/SpecialFunctions.h | 144 ++++++++++++++++++++++++++++++ Eigen/src/Core/arch/CUDA/MathFunctions.h | 37 ++++++++ Eigen/src/Core/arch/CUDA/PacketMath.h | 6 ++ Eigen/src/Core/functors/UnaryFunctors.h | 72 +++++++++++++++ Eigen/src/Core/util/ForwardDeclarations.h | 6 ++ Eigen/src/Core/util/StaticAssert.h | 3 +- Eigen/src/plugins/ArrayCwiseUnaryOps.h | 44 +++++++++ 10 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 Eigen/src/Core/SpecialFunctions.h (limited to 'Eigen') diff --git a/Eigen/Core b/Eigen/Core index 1ec749452..63602f4c3 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -300,6 +300,7 @@ using std::ptrdiff_t; #include "src/Core/NumTraits.h" #include "src/Core/MathFunctions.h" +#include "src/Core/SpecialFunctions.h" #include "src/Core/GenericPacketMath.h" #if defined EIGEN_VECTORIZE_AVX diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h index 5f27d8166..0e7dd29ed 100644 --- a/Eigen/src/Core/GenericPacketMath.h +++ b/Eigen/src/Core/GenericPacketMath.h @@ -74,6 +74,9 @@ struct default_packet_traits HasSinh = 0, HasCosh = 0, HasTanh = 0, + HasLGamma = 0, + HasErf = 0, + HasErfc = 0 HasRound = 0, HasFloor = 0, @@ -432,6 +435,18 @@ Packet pfloor(const Packet& a) { using numext::floor; return floor(a); } template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pceil(const Packet& a) { using numext::ceil; return ceil(a); } +/** \internal \returns the ln(|gamma(\a a)|) (coeff-wise) */ +template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS +Packet plgamma(const Packet& a) { return numext::lgamma(a); } + +/** \internal \returns the erf(\a a) (coeff-wise) */ +template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS +Packet perf(const Packet& a) { return numext::erf(a); } + +/** \internal \returns the erfc(\a a) (coeff-wise) */ +template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS +Packet perfc(const Packet& a) { return numext::erfc(a); } + /*************************************************************************** * The following functions might not have to be overwritten for vectorized types ***************************************************************************/ diff --git a/Eigen/src/Core/GlobalFunctions.h b/Eigen/src/Core/GlobalFunctions.h index 585974809..62fec7008 100644 --- a/Eigen/src/Core/GlobalFunctions.h +++ b/Eigen/src/Core/GlobalFunctions.h @@ -49,6 +49,9 @@ namespace Eigen EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sinh,scalar_sinh_op) EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cosh,scalar_cosh_op) EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tanh,scalar_tanh_op) + EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(lgamma,scalar_lgamma_op) + EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erf,scalar_erf_op) + EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erfc,scalar_erfc_op) EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op) EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op) EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10,scalar_log10_op) diff --git a/Eigen/src/Core/SpecialFunctions.h b/Eigen/src/Core/SpecialFunctions.h new file mode 100644 index 000000000..d481f2e06 --- /dev/null +++ b/Eigen/src/Core/SpecialFunctions.h @@ -0,0 +1,144 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// Copyright (C) 2015 Eugene Brevdo +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPECIAL_FUNCTIONS_H +#define EIGEN_SPECIAL_FUNCTIONS_H + +namespace Eigen { + +namespace internal { + +template +EIGEN_STRONG_INLINE Scalar __lgamma(Scalar x) { + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); +} + +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __lgamma(float x) { return lgammaf(x); } +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __lgamma(double x) { return lgamma(x); } + +template +EIGEN_STRONG_INLINE Scalar __erf(Scalar x) { + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); +} + +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __erf(float x) { return erff(x); } +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __erf(double x) { return erf(x); } + +template +EIGEN_STRONG_INLINE Scalar __erfc(Scalar x) { + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); +} + +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __erfc(float x) { return erfcf(x); } +template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __erfc(double x) { return erfc(x); } + +} // end namespace internal + +/**************************************************************************** + * Implementations * + ****************************************************************************/ + +namespace internal { + +/**************************************************************************** + * Implementation of + * lgamma * + ****************************************************************************/ + +template +struct lgamma_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) + { + return __lgamma(x); + } +}; + +template +struct lgamma_retval +{ + typedef Scalar type; +}; + +/**************************************************************************** + * Implementation of + * erf * + ****************************************************************************/ + +template +struct erf_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) + { + return __erf(x); + } +}; + +template +struct erf_retval +{ + typedef Scalar type; +}; + +/**************************************************************************** +* Implementation of erfc * +****************************************************************************/ + +template +struct erfc_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) + { + return __erfc(x); + } +}; + +template +struct erfc_retval +{ + typedef Scalar type; +}; + +} // end namespace internal + +namespace numext { + +template +EIGEN_DEVICE_FUNC +inline EIGEN_MATHFUNC_RETVAL(lgamma, Scalar) lgamma(const Scalar& x) +{ + return EIGEN_MATHFUNC_IMPL(lgamma, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC +inline EIGEN_MATHFUNC_RETVAL(erf, Scalar) erf(const Scalar& x) +{ + return EIGEN_MATHFUNC_IMPL(erf, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC +inline EIGEN_MATHFUNC_RETVAL(erfc, Scalar) erfc(const Scalar& x) +{ + return EIGEN_MATHFUNC_IMPL(erfc, Scalar)::run(x); +} + +} // end namespace numext + +} // end namespace Eigen + +#endif // EIGEN_SPECIAL_FUNCTIONS_H diff --git a/Eigen/src/Core/arch/CUDA/MathFunctions.h b/Eigen/src/Core/arch/CUDA/MathFunctions.h index 3bea88bea..ecd5c444e 100644 --- a/Eigen/src/Core/arch/CUDA/MathFunctions.h +++ b/Eigen/src/Core/arch/CUDA/MathFunctions.h @@ -66,6 +66,43 @@ double2 prsqrt(const double2& a) return make_double2(rsqrt(a.x), rsqrt(a.y)); } +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +float4 plgamma(const float4& a) +{ + return make_float4(lgammaf(a.x), lgammaf(a.y), lgammaf(a.z), lgammaf(a.w)); +} + +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +double2 plgamma(const double2& a) +{ + return make_double2(lgamma(a.x), lgamma(a.y)); +} + +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +float4 perf(const float4& a) +{ + return make_float4(erf(a.x), erf(a.y), erf(a.z), erf(a.w)); +} + +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +double2 perf(const double2& a) +{ + return make_double2(erf(a.x), erf(a.y)); +} + +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +float4 perfc(const float4& a) +{ + return make_float4(erfc(a.x), erfc(a.y), erfc(a.z), erfc(a.w)); +} + +template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +double2 perfc(const double2& a) +{ + return make_double2(erfc(a.x), erfc(a.y)); +} + + #endif } // end namespace internal diff --git a/Eigen/src/Core/arch/CUDA/PacketMath.h b/Eigen/src/Core/arch/CUDA/PacketMath.h index 0d2c2fef0..cb1b547e0 100644 --- a/Eigen/src/Core/arch/CUDA/PacketMath.h +++ b/Eigen/src/Core/arch/CUDA/PacketMath.h @@ -39,6 +39,9 @@ template<> struct packet_traits : default_packet_traits HasExp = 1, HasSqrt = 1, HasRsqrt = 1, + HasLGamma = 1, + HasErf = 1, + HasErfc = 1, HasBlend = 0, }; @@ -59,6 +62,9 @@ template<> struct packet_traits : default_packet_traits HasExp = 1, HasSqrt = 1, HasRsqrt = 1, + HasLGamma = 1, + HasErf = 1, + HasErfc = 1, HasBlend = 0, }; diff --git a/Eigen/src/Core/functors/UnaryFunctors.h b/Eigen/src/Core/functors/UnaryFunctors.h index e6c665fb6..e16bdd589 100644 --- a/Eigen/src/Core/functors/UnaryFunctors.h +++ b/Eigen/src/Core/functors/UnaryFunctors.h @@ -403,6 +403,77 @@ struct functor_traits > }; }; + +/** \internal + * \brief Template functor to compute the natural log of the absolute + * value of Gamma of a scalar + * \sa class CwiseUnaryOp, Cwise::lgamma() + */ +template struct scalar_lgamma_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_lgamma_op) + EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { + using numext::lgamma; return lgamma(a); + } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::plgamma(a); } +}; +template +struct functor_traits > +{ + enum { + // Guesstimate + Cost = 10 * NumTraits::MulCost + 5 * NumTraits::AddCost, + PacketAccess = packet_traits::HasLGamma + }; +}; + +/** \internal + * \brief Template functor to compute the Gauss error function of a + * scalar + * \sa class CwiseUnaryOp, Cwise::erf() + */ +template struct scalar_erf_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_erf_op) + EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { + using numext::erf; return erf(a); + } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::perf(a); } +}; +template +struct functor_traits > +{ + enum { + // Guesstimate + Cost = 10 * NumTraits::MulCost + 5 * NumTraits::AddCost, + PacketAccess = packet_traits::HasErf + }; +}; + +/** \internal + * \brief Template functor to compute the Complementary Error Function + * of a scalar + * \sa class CwiseUnaryOp, Cwise::erfc() + */ +template struct scalar_erfc_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_erfc_op) + EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { + using numext::erfc; return erfc(a); + } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::perfc(a); } +}; +template +struct functor_traits > +{ + enum { + // Guesstimate + Cost = 10 * NumTraits::MulCost + 5 * NumTraits::AddCost, + PacketAccess = packet_traits::HasErfc + }; +}; + + /** \internal * \brief Template functor to compute the atan of a scalar * \sa class CwiseUnaryOp, ArrayBase::atan() @@ -422,6 +493,7 @@ struct functor_traits > }; }; + /** \internal * \brief Template functor to compute the tanh of a scalar * \sa class CwiseUnaryOp, ArrayBase::tanh() diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 483af876f..27c7907fc 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -294,6 +294,12 @@ struct stem_function }; } +// SpecialFunctions forward declarations +namespace internal { +template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __lgamma(Scalar x); +template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __erf(Scalar x); +template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __erfc(Scalar x); + } // end namespace Eigen #endif // EIGEN_FORWARDDECLARATIONS_H diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 108181419..1fe365aa7 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -96,7 +96,8 @@ STORAGE_LAYOUT_DOES_NOT_MATCH, EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE, THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS, - MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY + MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY, + THIS_TYPE_IS_NOT_SUPPORTED }; }; diff --git a/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/Eigen/src/plugins/ArrayCwiseUnaryOps.h index 45e826b0c..ed9818dd1 100644 --- a/Eigen/src/plugins/ArrayCwiseUnaryOps.h +++ b/Eigen/src/plugins/ArrayCwiseUnaryOps.h @@ -21,6 +21,9 @@ typedef CwiseUnaryOp, const Derived> AtanReturn typedef CwiseUnaryOp, const Derived> TanhReturnType; typedef CwiseUnaryOp, const Derived> SinhReturnType; typedef CwiseUnaryOp, const Derived> CoshReturnType; +typedef CwiseUnaryOp, const Derived> LgammaReturnType; +typedef CwiseUnaryOp, const Derived> ErfReturnType; +typedef CwiseUnaryOp, const Derived> ErfcReturnType; typedef CwiseUnaryOp, const Derived> PowReturnType; typedef CwiseUnaryOp, const Derived> SquareReturnType; typedef CwiseUnaryOp, const Derived> CubeReturnType; @@ -302,6 +305,47 @@ cosh() const return CoshReturnType(derived()); } +/** \returns an expression of the coefficient-wise ln(|gamma(*this)|). + * + * Example: \include Cwise_lgamma.cpp + * Output: \verbinclude Cwise_lgamma.out + * + * \sa cos(), sin(), tan() + */ +inline const CwiseUnaryOp, Derived> +lgamma() const +{ + return LgammaReturnType(derived()); +} + +/** \returns an expression of the coefficient-wise Gauss error + * function of *this. + * + * Example: \include Cwise_erf.cpp + * Output: \verbinclude Cwise_erf.out + * + * \sa cos(), sin(), tan() + */ +inline const CwiseUnaryOp, Derived> +erf() const +{ + return ErfReturnType(derived()); +} + +/** \returns an expression of the coefficient-wise Complementary error + * function of *this. + * + * Example: \include Cwise_erfc.cpp + * Output: \verbinclude Cwise_erfc.out + * + * \sa cos(), sin(), tan() + */ +inline const CwiseUnaryOp, Derived> +erfc() const +{ + return ErfcReturnType(derived()); +} + /** \returns an expression of the coefficient-wise power of *this to the given exponent. * * This function computes the coefficient-wise power. The function MatrixBase::pow() in the -- cgit v1.2.3 From 73b68d4370f761d6422e02e7e515aefdcd652c1e Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Mon, 7 Dec 2015 16:38:48 -0800 Subject: Fixed a couple of typos Cleaned up the code a bit. --- Eigen/src/Core/GenericPacketMath.h | 4 ++-- Eigen/src/Core/SpecialFunctions.h | 13 +++++-------- Eigen/src/Core/util/ForwardDeclarations.h | 6 ------ test/packetmath.cpp | 9 ++++++--- 4 files changed, 13 insertions(+), 19 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h index 0e7dd29ed..6872f5e53 100644 --- a/Eigen/src/Core/GenericPacketMath.h +++ b/Eigen/src/Core/GenericPacketMath.h @@ -43,7 +43,7 @@ struct default_packet_traits { enum { HasHalfPacket = 0, - + HasAdd = 1, HasSub = 1, HasMul = 1, @@ -76,7 +76,7 @@ struct default_packet_traits HasTanh = 0, HasLGamma = 0, HasErf = 0, - HasErfc = 0 + HasErfc = 0, HasRound = 0, HasFloor = 0, diff --git a/Eigen/src/Core/SpecialFunctions.h b/Eigen/src/Core/SpecialFunctions.h index d481f2e06..ae8f0105a 100644 --- a/Eigen/src/Core/SpecialFunctions.h +++ b/Eigen/src/Core/SpecialFunctions.h @@ -1,7 +1,6 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2010 Benoit Jacob // Copyright (C) 2015 Eugene Brevdo // // This Source Code Form is subject to the terms of the Mozilla @@ -45,14 +44,13 @@ template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __erfc(double x } // end namespace internal /**************************************************************************** - * Implementations * + * Implementations * ****************************************************************************/ namespace internal { /**************************************************************************** - * Implementation of - * lgamma * + * Implementation of lgamma * ****************************************************************************/ template @@ -72,8 +70,7 @@ struct lgamma_retval }; /**************************************************************************** - * Implementation of - * erf * + * Implementation of erf * ****************************************************************************/ template @@ -92,8 +89,8 @@ struct erf_retval typedef Scalar type; }; -/**************************************************************************** -* Implementation of erfc * +/*************************************************************************** +* Implementation of erfc * ****************************************************************************/ template diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 27c7907fc..483af876f 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -294,12 +294,6 @@ struct stem_function }; } -// SpecialFunctions forward declarations -namespace internal { -template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __lgamma(Scalar x); -template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __erf(Scalar x); -template EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar __erfc(Scalar x); - } // end namespace Eigen #endif // EIGEN_FORWARDDECLARATIONS_H diff --git a/test/packetmath.cpp b/test/packetmath.cpp index 304fab5de..c34b6f3f1 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -355,19 +355,19 @@ template void packetmath_real() data1[0] = std::numeric_limits::quiet_NaN(); packet_helper::HasLGamma,Packet> h; h.store(data2, internal::plgamma(h.load(data1))); - VERIFY(std::isnan(data2[0])); + VERIFY((numext::isnan)(data2[0])); } { data1[0] = std::numeric_limits::quiet_NaN(); packet_helper::HasErf,Packet> h; h.store(data2, internal::perf(h.load(data1))); - VERIFY(std::isnan(data2[0])); + VERIFY((numext::isnan)(data2[0])); } { data1[0] = std::numeric_limits::quiet_NaN(); packet_helper::HasErfc,Packet> h; h.store(data2, internal::perfc(h.load(data1))); - VERIFY(std::isnan(data2[0])); + VERIFY((numext::isnan)(data2[0])); } for (int i=0; i void packetmath_real() data1[i] = internal::random(0,1) * std::pow(Scalar(10), internal::random(-6,6)); data2[i] = internal::random(0,1) * std::pow(Scalar(10), internal::random(-6,6)); } + +#if __cplusplus > 199711L if(internal::random(0,1)<0.1) data1[internal::random(0, PacketSize)] = 0; CHECK_CWISE1_IF(PacketTraits::HasSqrt, std::sqrt, internal::psqrt); @@ -382,6 +384,7 @@ template void packetmath_real() CHECK_CWISE1_IF(internal::packet_traits::HasLGamma, std::lgamma, internal::plgamma); CHECK_CWISE1_IF(internal::packet_traits::HasErf, std::erf, internal::perf); CHECK_CWISE1_IF(internal::packet_traits::HasErfc, std::erfc, internal::perfc); +#endif if(PacketTraits::HasLog && PacketTraits::size>=2) { -- cgit v1.2.3 From b1ae39794cee2536d28360acd2ea6291806debe1 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Mon, 7 Dec 2015 16:46:35 -0800 Subject: Simplified the code a bit --- Eigen/src/plugins/ArrayCwiseUnaryOps.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/Eigen/src/plugins/ArrayCwiseUnaryOps.h index ed9818dd1..01432e2f3 100644 --- a/Eigen/src/plugins/ArrayCwiseUnaryOps.h +++ b/Eigen/src/plugins/ArrayCwiseUnaryOps.h @@ -312,7 +312,7 @@ cosh() const * * \sa cos(), sin(), tan() */ -inline const CwiseUnaryOp, Derived> +inline const LgammaReturnType lgamma() const { return LgammaReturnType(derived()); @@ -326,7 +326,7 @@ lgamma() const * * \sa cos(), sin(), tan() */ -inline const CwiseUnaryOp, Derived> +inline const ErfReturnType erf() const { return ErfReturnType(derived()); @@ -340,7 +340,7 @@ erf() const * * \sa cos(), sin(), tan() */ -inline const CwiseUnaryOp, Derived> +inline const ErfcReturnType erfc() const { return ErfcReturnType(derived()); -- cgit v1.2.3 From e535450573bf8a15d63cc0dff6090a89f28cf8cb Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Tue, 8 Dec 2015 14:06:39 -0800 Subject: Cleanup --- Eigen/src/Core/GenericPacketMath.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h index 6872f5e53..8ad51bad5 100644 --- a/Eigen/src/Core/GenericPacketMath.h +++ b/Eigen/src/Core/GenericPacketMath.h @@ -437,15 +437,15 @@ Packet pceil(const Packet& a) { using numext::ceil; return ceil(a); } /** \internal \returns the ln(|gamma(\a a)|) (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet plgamma(const Packet& a) { return numext::lgamma(a); } +Packet plgamma(const Packet& a) { using numext::lgamma; return lgamma(a); } /** \internal \returns the erf(\a a) (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet perf(const Packet& a) { return numext::erf(a); } +Packet perf(const Packet& a) { using numext::erf; return erf(a); } /** \internal \returns the erfc(\a a) (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet perfc(const Packet& a) { return numext::erfc(a); } +Packet perfc(const Packet& a) { using numext::erfc; return erfc(a); } /*************************************************************************** * The following functions might not have to be overwritten for vectorized types -- cgit v1.2.3 From 53b196aa5fb503ab3707887eea226eec56943380 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Tue, 8 Dec 2015 14:17:34 -0800 Subject: Simplified the implementation of lgamma, erf, and erfc --- Eigen/src/Core/SpecialFunctions.h | 87 +++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 39 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/SpecialFunctions.h b/Eigen/src/Core/SpecialFunctions.h index ae8f0105a..f90f1b81b 100644 --- a/Eigen/src/Core/SpecialFunctions.h +++ b/Eigen/src/Core/SpecialFunctions.h @@ -11,42 +11,6 @@ #define EIGEN_SPECIAL_FUNCTIONS_H namespace Eigen { - -namespace internal { - -template -EIGEN_STRONG_INLINE Scalar __lgamma(Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); -} - -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __lgamma(float x) { return lgammaf(x); } -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __lgamma(double x) { return lgamma(x); } - -template -EIGEN_STRONG_INLINE Scalar __erf(Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); -} - -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __erf(float x) { return erff(x); } -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __erf(double x) { return erf(x); } - -template -EIGEN_STRONG_INLINE Scalar __erfc(Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); -} - -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float __erfc(float x) { return erfcf(x); } -template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double __erfc(double x) { return erfc(x); } - -} // end namespace internal - -/**************************************************************************** - * Implementations * - ****************************************************************************/ - namespace internal { /**************************************************************************** @@ -59,10 +23,25 @@ struct lgamma_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) { - return __lgamma(x); + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); } }; +template<> +struct lgamma_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE double run(const float& x) { return ::lgammaf(x); } +}; + +template<> +struct lgamma_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE double run(const double& x) { return ::lgamma(x); } +}; + template struct lgamma_retval { @@ -79,10 +58,25 @@ struct erf_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) { - return __erf(x); + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); } }; +template<> +struct erf_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE float run(const float& x) { return ::erff(x); } +}; + +template<> +struct erf_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE double run(const double& x) { return ::erf(x); } +}; + template struct erf_retval { @@ -99,10 +93,25 @@ struct erfc_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Scalar& x) { - return __erfc(x); + EIGEN_STATIC_ASSERT((internal::is_same::value == false), + THIS_TYPE_IS_NOT_SUPPORTED); } }; +template<> +struct erfc_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE float run(const float x) { return ::erfcf(x); } +}; + +template<> +struct erfc_impl +{ + EIGEN_DEVICE_FUNC + static EIGEN_STRONG_INLINE double run(const double x) { return ::erfc(x); } +}; + template struct erfc_retval { -- cgit v1.2.3 From 48877a69334382b8478f5095c5e56500b7de7478 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Thu, 10 Dec 2015 13:09:49 -0800 Subject: Only implement the lgamma, erf, and erfc functions when using a compiler compliant with the C99 specification. --- Eigen/src/Core/SpecialFunctions.h | 43 +++++++++++++++++++++++---------------- test/packetmath.cpp | 4 +++- 2 files changed, 28 insertions(+), 19 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/SpecialFunctions.h b/Eigen/src/Core/SpecialFunctions.h index f90f1b81b..1de3d7f78 100644 --- a/Eigen/src/Core/SpecialFunctions.h +++ b/Eigen/src/Core/SpecialFunctions.h @@ -28,6 +28,13 @@ struct lgamma_impl } }; +template +struct lgamma_retval +{ + typedef Scalar type; +}; + +#ifdef EIGEN_HAS_C99_MATH template<> struct lgamma_impl { @@ -41,12 +48,7 @@ struct lgamma_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE double run(const double& x) { return ::lgamma(x); } }; - -template -struct lgamma_retval -{ - typedef Scalar type; -}; +#endif /**************************************************************************** * Implementation of erf * @@ -63,6 +65,13 @@ struct erf_impl } }; +template +struct erf_retval +{ + typedef Scalar type; +}; + +#ifdef EIGEN_HAS_C99_MATH template<> struct erf_impl { @@ -76,12 +85,7 @@ struct erf_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE double run(const double& x) { return ::erf(x); } }; - -template -struct erf_retval -{ - typedef Scalar type; -}; +#endif // EIGEN_HAS_C99_MATH /*************************************************************************** * Implementation of erfc * @@ -98,6 +102,13 @@ struct erfc_impl } }; +template +struct erfc_retval +{ + typedef Scalar type; +}; + +#ifdef EIGEN_HAS_C99_MATH template<> struct erfc_impl { @@ -111,15 +122,11 @@ struct erfc_impl EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE double run(const double x) { return ::erfc(x); } }; - -template -struct erfc_retval -{ - typedef Scalar type; -}; +#endif // EIGEN_HAS_C99_MATH } // end namespace internal + namespace numext { template diff --git a/test/packetmath.cpp b/test/packetmath.cpp index 758c2fb9d..91bb998d0 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -351,6 +351,7 @@ template void packetmath_real() VERIFY_IS_EQUAL(std::exp(-std::numeric_limits::denorm_min()), data2[1]); } +#ifdef EIGEN_HAS_C99_MATH { data1[0] = std::numeric_limits::quiet_NaN(); packet_helper::HasLGamma,Packet> h; @@ -369,6 +370,7 @@ template void packetmath_real() h.store(data2, internal::perfc(h.load(data1))); VERIFY((numext::isnan)(data2[0])); } +#endif // EIGEN_HAS_C99_MATH for (int i=0; i void packetmath_real() data1[internal::random(0, PacketSize)] = 0; CHECK_CWISE1_IF(PacketTraits::HasSqrt, std::sqrt, internal::psqrt); CHECK_CWISE1_IF(PacketTraits::HasLog, std::log, internal::plog); -#if __cplusplus > 199711L +#if defined(EIGEN_HAS_C99_MATH) && (__cplusplus > 199711L) CHECK_CWISE1_IF(internal::packet_traits::HasLGamma, std::lgamma, internal::plgamma); CHECK_CWISE1_IF(internal::packet_traits::HasErf, std::erf, internal::perf); CHECK_CWISE1_IF(internal::packet_traits::HasErfc, std::erfc, internal::perfc); -- cgit v1.2.3 From 58e06447dec67e265fb0a749e60f67ecd831b32b Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Thu, 10 Dec 2015 13:11:36 -0800 Subject: Silence a compilation warning --- Eigen/src/Core/SpecialFunctions.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Eigen') diff --git a/Eigen/src/Core/SpecialFunctions.h b/Eigen/src/Core/SpecialFunctions.h index 1de3d7f78..05973e372 100644 --- a/Eigen/src/Core/SpecialFunctions.h +++ b/Eigen/src/Core/SpecialFunctions.h @@ -25,6 +25,7 @@ struct lgamma_impl { EIGEN_STATIC_ASSERT((internal::is_same::value == false), THIS_TYPE_IS_NOT_SUPPORTED); + return Scalar(0); } }; @@ -62,6 +63,7 @@ struct erf_impl { EIGEN_STATIC_ASSERT((internal::is_same::value == false), THIS_TYPE_IS_NOT_SUPPORTED); + return Scalar(0); } }; @@ -99,6 +101,7 @@ struct erfc_impl { EIGEN_STATIC_ASSERT((internal::is_same::value == false), THIS_TYPE_IS_NOT_SUPPORTED); + return Scalar(0); } }; -- cgit v1.2.3 From b820b097b870f96538f87862bb3cf22d2b3f4b3b Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Thu, 10 Dec 2015 13:52:05 -0800 Subject: Created EIGEN_HAS_C99_MATH define as Gael suggested. --- Eigen/src/Core/util/Macros.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Eigen') diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index 8def69610..d375c77dd 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -341,6 +341,13 @@ #define EIGEN_HAVE_RVALUE_REFERENCES #endif +// Does the compiler support C99? +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) \ + || (defined(__GNUC__) && defined(_GLIBCXX_USE_C99)) \ + || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) +#define EIGEN_HAS_C99_MATH 1 +#endif + // Does the compiler support result_of? #if (__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L)) #define EIGEN_HAS_STD_RESULT_OF 1 -- cgit v1.2.3