// Copyright (C) 2010-2016 National ICT Australia (NICTA) // // 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/. // ------------------------------------------------------------------- // // Written by Conrad Sanderson - http://conradsanderson.id.au //! \addtogroup eop_aux //! @{ //! use of the SFINAE approach to work around compiler limitations //! http://en.wikipedia.org/wiki/SFINAE class eop_aux { public: template arma_inline static typename arma_integral_only::result acos (const eT x) { return eT( std::acos(double(x)) ); } template arma_inline static typename arma_integral_only::result asin (const eT x) { return eT( std::asin(double(x)) ); } template arma_inline static typename arma_integral_only::result atan (const eT x) { return eT( std::atan(double(x)) ); } template arma_inline static typename arma_real_only::result acos (const eT x) { return std::acos(x); } template arma_inline static typename arma_real_only::result asin (const eT x) { return std::asin(x); } template arma_inline static typename arma_real_only::result atan (const eT x) { return std::atan(x); } template arma_inline static typename arma_cx_only::result acos (const eT x) { return arma_acos(x); } template arma_inline static typename arma_cx_only::result asin (const eT x) { return arma_asin(x); } template arma_inline static typename arma_cx_only::result atan (const eT x) { return arma_atan(x); } template arma_inline static typename arma_integral_only::result acosh (const eT x) { return eT( arma_acosh(double(x)) ); } template arma_inline static typename arma_integral_only::result asinh (const eT x) { return eT( arma_asinh(double(x)) ); } template arma_inline static typename arma_integral_only::result atanh (const eT x) { return eT( arma_atanh(double(x)) ); } template arma_inline static typename arma_real_or_cx_only::result acosh (const eT x) { return arma_acosh(x); } template arma_inline static typename arma_real_or_cx_only::result asinh (const eT x) { return arma_asinh(x); } template arma_inline static typename arma_real_or_cx_only::result atanh (const eT x) { return arma_atanh(x); } template arma_inline static typename arma_not_cx::result conj(const eT x) { return x; } template arma_inline static std::complex conj(const std::complex& x) { return std::conj(x); } template arma_inline static typename arma_integral_only::result sqrt (const eT x) { return eT( std::sqrt (double(x)) ); } template arma_inline static typename arma_integral_only::result log10 (const eT x) { return eT( std::log10(double(x)) ); } template arma_inline static typename arma_integral_only::result log (const eT x) { return eT( std::log (double(x)) ); } template arma_inline static typename arma_integral_only::result exp (const eT x) { return eT( std::exp (double(x)) ); } template arma_inline static typename arma_integral_only::result cos (const eT x) { return eT( std::cos (double(x)) ); } template arma_inline static typename arma_integral_only::result sin (const eT x) { return eT( std::sin (double(x)) ); } template arma_inline static typename arma_integral_only::result tan (const eT x) { return eT( std::tan (double(x)) ); } template arma_inline static typename arma_integral_only::result cosh (const eT x) { return eT( std::cosh (double(x)) ); } template arma_inline static typename arma_integral_only::result sinh (const eT x) { return eT( std::sinh (double(x)) ); } template arma_inline static typename arma_integral_only::result tanh (const eT x) { return eT( std::tanh (double(x)) ); } template arma_inline static typename arma_real_or_cx_only::result sqrt (const eT x) { return std::sqrt (x); } template arma_inline static typename arma_real_or_cx_only::result log10 (const eT x) { return std::log10(x); } template arma_inline static typename arma_real_or_cx_only::result log (const eT x) { return std::log (x); } template arma_inline static typename arma_real_or_cx_only::result exp (const eT x) { return std::exp (x); } template arma_inline static typename arma_real_or_cx_only::result cos (const eT x) { return std::cos (x); } template arma_inline static typename arma_real_or_cx_only::result sin (const eT x) { return std::sin (x); } template arma_inline static typename arma_real_or_cx_only::result tan (const eT x) { return std::tan (x); } template arma_inline static typename arma_real_or_cx_only::result cosh (const eT x) { return std::cosh (x); } template arma_inline static typename arma_real_or_cx_only::result sinh (const eT x) { return std::sinh (x); } template arma_inline static typename arma_real_or_cx_only::result tanh (const eT x) { return std::tanh (x); } template arma_inline static typename arma_unsigned_integral_only::result neg (const eT x) { return x; } template arma_inline static typename arma_signed_only::result neg (const eT x) { return -x; } template arma_inline static typename arma_integral_only::result floor (const eT x) { return x; } template arma_inline static typename arma_real_only::result floor (const eT x) { return std::floor(x); } template arma_inline static typename arma_cx_only::result floor (const eT& x) { return eT( std::floor(x.real()), std::floor(x.imag()) ); } template arma_inline static typename arma_integral_only::result ceil (const eT x) { return x; } template arma_inline static typename arma_real_only::result ceil (const eT x) { return std::ceil(x); } template arma_inline static typename arma_cx_only::result ceil (const eT& x) { return eT( std::ceil(x.real()), std::ceil(x.imag()) ); } #if defined(ARMA_USE_CXX11) template arma_inline static typename arma_integral_only::result round (const eT x) { return x; } template arma_inline static typename arma_real_only::result round (const eT x) { return std::round(x); } template arma_inline static typename arma_cx_only::result round (const eT& x) { return eT( std::round(x.real()), std::round(x.imag()) ); } #else template arma_inline static typename arma_integral_only::result round (const eT x) { return x; } template arma_inline static typename arma_real_only::result round (const eT x) { return (x >= eT(0)) ? std::floor(x+0.5) : std::ceil(x-0.5); } template arma_inline static typename arma_cx_only::result round (const eT& x) { return eT( eop_aux::round(x.real()), eop_aux::round(x.imag()) ); } #endif #if defined(ARMA_USE_CXX11) template arma_inline static typename arma_integral_only::result trunc (const eT x) { return x; } template arma_inline static typename arma_real_only::result trunc (const eT x) { return std::trunc(x); } template arma_inline static typename arma_cx_only::result trunc (const eT& x) { return eT( std::trunc(x.real()), std::trunc(x.imag()) ); } #else template arma_inline static typename arma_integral_only::result trunc (const eT x) { return x; } template arma_inline static typename arma_real_only::result trunc (const eT x) { return (x >= eT(0)) ? std::floor(x) : std::ceil(x); } template arma_inline static typename arma_cx_only::result trunc (const eT& x) { return eT( eop_aux::trunc(x.real()), eop_aux::trunc(x.imag()) ); } #endif #if defined(ARMA_USE_CXX11) template arma_inline static typename arma_integral_only::result log2 (const eT x) { return eT( std::log(double(x))/ double(0.69314718055994530942) ); } template arma_inline static typename arma_real_only::result log2 (const eT x) { return std::log2(x); } template arma_inline static typename arma_cx_only::result log2 (const eT& x) { typedef typename get_pod_type::result T; return std::log(x) / T(0.69314718055994530942); } #else template arma_inline static typename arma_integral_only::result log2 (const eT x) { return eT( std::log(double(x))/ double(0.69314718055994530942) ); } template arma_inline static typename arma_real_or_cx_only::result log2 (const eT x) { typedef typename get_pod_type::result T; return std::log(x) / T(0.69314718055994530942); } #endif #if defined(ARMA_USE_CXX11) template arma_inline static typename arma_integral_only::result exp2 (const eT x) { return eT( std::pow(double(2), double(x)) ); } template arma_inline static typename arma_real_only::result exp2 (const eT x) { return std::exp2(x); } template arma_inline static typename arma_cx_only::result exp2 (const eT& x) { typedef typename get_pod_type::result T; return std::pow( T(2), x); } #else template arma_inline static typename arma_integral_only::result exp2 (const eT x) { return eT( std::pow(double(2), double(x)) ); } template arma_inline static typename arma_real_or_cx_only::result exp2 (const eT x) { typedef typename get_pod_type::result T; return std::pow( T(2), x); } #endif template arma_inline static typename arma_integral_only::result exp10 (const eT x) { return eT( std::pow(double(10), double(x)) ); } template arma_inline static typename arma_real_or_cx_only::result exp10 (const eT x) { typedef typename get_pod_type::result T; return std::pow( T(10), x); } template arma_inline static typename arma_unsigned_integral_only::result arma_abs (const eT x) { return x; } template arma_inline static typename arma_signed_integral_only::result arma_abs (const eT x) { return std::abs(x); } template arma_inline static typename arma_real_only::result arma_abs (const eT x) { return std::abs(x); } template arma_inline static typename arma_real_only< T>::result arma_abs (const std::complex& x) { return std::abs(x); } template arma_inline static typename arma_unsigned_integral_only::result sign (const eT x) { return (x > eT(0)) ? eT(+1) : eT(0); } template arma_inline static typename arma_signed_integral_only::result sign (const eT x) { return (x > eT(0)) ? eT(+1) : ( (x < eT(0)) ? eT(-1) : eT(0) ); } template arma_inline static typename arma_real_only::result sign (const eT x) { return (x > eT(0)) ? eT(+1) : ( (x < eT(0)) ? eT(-1) : eT(0) ); } template arma_inline static typename arma_cx_only::result sign (const eT& x) { typedef typename eT::value_type T; return (x.real() != T(0) && x.imag() != T(0)) ? (x / std::abs(x)) : x; } template arma_inline static typename arma_integral_only::result pow (const T1 base, const T2 exponent) { return T1( std::pow( double(base), double(exponent) ) ); } template arma_inline static typename arma_real_or_cx_only::result pow (const T1 base, const T2 exponent) { return std::pow(base, exponent); } template arma_inline static typename arma_integral_only::result direct_eps(const eT) { return eT(0); } template inline static typename arma_real_only::result direct_eps(const eT x) { //arma_extra_debug_sigprint(); // acording to IEEE Standard for Floating-Point Arithmetic (IEEE 754) // the mantissa length for double is 53 bits = std::numeric_limits::digits // the mantissa length for float is 24 bits = std::numeric_limits::digits //return std::pow( std::numeric_limits::radix, (std::floor(std::log10(std::abs(x))/std::log10(std::numeric_limits::radix))-(std::numeric_limits::digits-1)) ); const eT radix_eT = eT(std::numeric_limits::radix); const eT digits_m1_eT = eT(std::numeric_limits::digits - 1); // return std::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) ); return eop_aux::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) ); } template inline static typename arma_real_only::result direct_eps(const std::complex x) { //arma_extra_debug_sigprint(); //return std::pow( std::numeric_limits::radix, (std::floor(std::log10(std::abs(x))/std::log10(std::numeric_limits::radix))-(std::numeric_limits::digits-1)) ); const T radix_T = T(std::numeric_limits::radix); const T digits_m1_T = T(std::numeric_limits::digits - 1); return std::pow( radix_T, T(std::floor(std::log10(std::abs(x))/std::log10(radix_T)) - digits_m1_T) ); } }; //! @}