/*! * Copyright 2015 by Contributors * \file math.h * \brief additional math utils * \author Tianqi Chen */ #ifndef XGBOOST_COMMON_MATH_H_ #define XGBOOST_COMMON_MATH_H_ #include #include #include #include #include #include namespace xgboost { namespace common { /*! * \brief calculate the sigmoid of the input. * \param x input parameter * \return the transformed value. */ XGBOOST_DEVICE inline float Sigmoid(float x) { return 1.0f / (1.0f + expf(-x)); } /*! * \brief Equality test for both integer and floating point. */ template XGBOOST_DEVICE constexpr bool CloseTo(T a, U b) { using Casted = typename std::conditional< std::is_floating_point::value || std::is_floating_point::value, double, typename std::conditional< std::is_signed::value || std::is_signed::value, int64_t, uint64_t>::type>::type; return std::is_floating_point::value ? std::abs(static_cast(a) -static_cast(b)) < 1e-6 : a == b; } /*! * \brief Do inplace softmax transformaton on start to end * * \tparam Iterator Input iterator type * * \param start Start iterator of input * \param end end iterator of input */ template XGBOOST_DEVICE inline void Softmax(Iterator start, Iterator end) { static_assert(std::is_same().operator*())>::type >::value, "Values should be of type bst_float"); bst_float wmax = *start; for (Iterator i = start+1; i != end; ++i) { wmax = fmaxf(*i, wmax); } double wsum = 0.0f; for (Iterator i = start; i != end; ++i) { *i = expf(*i - wmax); wsum += *i; } for (Iterator i = start; i != end; ++i) { *i /= static_cast(wsum); } } /*! * \brief Find the maximum iterator within the iterators * \param begin The begining iterator. * \param end The end iterator. * \return the iterator point to the maximum value. * \tparam Iterator The type of the iterator. */ template XGBOOST_DEVICE inline Iterator FindMaxIndex(Iterator begin, Iterator end) { Iterator maxit = begin; for (Iterator it = begin; it != end; ++it) { if (*it > *maxit) maxit = it; } return maxit; } /*! * \brief perform numerically safe logsum * \param x left input operand * \param y right input operand * \return log(exp(x) + exp(y)) */ inline float LogSum(float x, float y) { if (x < y) { return y + std::log(std::exp(x - y) + 1.0f); } else { return x + std::log(std::exp(y - x) + 1.0f); } } /*! * \brief perform numerically safe logsum * \param begin The begining iterator. * \param end The end iterator. * \return the iterator point to the maximum value. * \tparam Iterator The type of the iterator. */ template inline float LogSum(Iterator begin, Iterator end) { float mx = *begin; for (Iterator it = begin; it != end; ++it) { mx = std::max(mx, *it); } float sum = 0.0f; for (Iterator it = begin; it != end; ++it) { sum += std::exp(*it - mx); } return mx + std::log(sum); } // comparator functions for sorting pairs in descending order inline static bool CmpFirst(const std::pair &a, const std::pair &b) { return a.first > b.first; } inline static bool CmpSecond(const std::pair &a, const std::pair &b) { return a.second > b.second; } // Redefined here to workaround a VC bug that doesn't support overloadng for integer // types. template XGBOOST_DEVICE typename std::enable_if< std::numeric_limits::is_integer, bool>::type CheckNAN(T) { return false; } #if XGBOOST_STRICT_R_MODE && !defined(__CUDA_ARCH__) bool CheckNAN(double v); #else XGBOOST_DEVICE bool inline CheckNAN(float x) { #if defined(__CUDA_ARCH__) return isnan(x); #else return std::isnan(x); #endif // defined(__CUDA_ARCH__) } XGBOOST_DEVICE bool inline CheckNAN(double x) { #if defined(__CUDA_ARCH__) return isnan(x); #else return std::isnan(x); #endif // defined(__CUDA_ARCH__) } #endif // XGBOOST_STRICT_R_MODE && !defined(__CUDA_ARCH__) // GPU version is not uploaded in CRAN anyway. // Specialize only when using R with CPU. #if XGBOOST_STRICT_R_MODE && !defined(XGBOOST_USE_CUDA) double LogGamma(double v); #else // Not R or R with GPU. template XGBOOST_DEVICE inline T LogGamma(T v) { #ifdef _MSC_VER #if _MSC_VER >= 1800 return lgamma(v); #else #pragma message("Warning: lgamma function was not available until VS2013"\ ", poisson regression will be disabled") utils::Error("lgamma function was not available until VS2013"); return static_cast(1.0); #endif // _MSC_VER >= 1800 #else return lgamma(v); #endif // _MSC_VER } #endif // XGBOOST_STRICT_R_MODE && !defined(XGBOOST_USE_CUDA) } // namespace common } // namespace xgboost #endif // XGBOOST_COMMON_MATH_H_