max@0: // Copyright (C) 2010-2011 NICTA (www.nicta.com.au) max@0: // Copyright (C) 2010-2011 Conrad Sanderson max@0: // max@0: // This file is part of the Armadillo C++ library. max@0: // It is provided without any warranty of fitness max@0: // for any purpose. You can redistribute this file max@0: // and/or modify it under the terms of the GNU max@0: // Lesser General Public License (LGPL) as published max@0: // by the Free Software Foundation, either version 3 max@0: // of the License or (at your option) any later version. max@0: // (see http://www.opensource.org/licenses for more info) max@0: max@0: max@0: //! \addtogroup eop_aux max@0: //! @{ max@0: max@0: max@0: max@0: template max@0: struct eop_aux_randu max@0: { max@0: arma_inline max@0: operator eT () max@0: { max@0: return eT(std::rand()) / eT(RAND_MAX); max@0: } max@0: }; max@0: max@0: max@0: max@0: template max@0: struct eop_aux_randu< std::complex > max@0: { max@0: arma_inline max@0: operator std::complex () max@0: { max@0: return std::complex( T(eop_aux_randu()), T(eop_aux_randu()) ); max@0: } max@0: }; max@0: max@0: max@0: max@0: template max@0: struct eop_aux_randn max@0: { max@0: // // rudimentary method, based on the central limit theorem max@0: // // http://en.wikipedia.org/wiki/Central_limit_theorem max@0: // inline max@0: // operator eT () const max@0: // { max@0: // const uword N = 12; // N must be >= 12 and an even number max@0: // const uword N2 = N/2; max@0: // max@0: // eT acc = eT(0); max@0: // max@0: // for(uword i=0; i::result eTp; max@0: max@0: eTp tmp1; max@0: eTp tmp2; max@0: eTp w; max@0: max@0: do max@0: { max@0: tmp1 = eTp(2) * eTp(std::rand()) / eTp(RAND_MAX) - eTp(1); max@0: tmp2 = eTp(2) * eTp(std::rand()) / eTp(RAND_MAX) - eTp(1); max@0: w = tmp1*tmp1 + tmp2*tmp2; max@0: } max@0: while ( w >= eTp(1) ); max@0: max@0: return eT( tmp1 * std::sqrt( (eTp(-2) * std::log(w)) / w) ); max@0: } max@0: max@0: max@0: // other methods: max@0: // http://en.wikipedia.org/wiki/Ziggurat_algorithm max@0: // max@0: // Marsaglia and Tsang Ziggurat technique to transform from a uniform to a normal distribution. max@0: // G. Marsaglia, W.W. Tsang. max@0: // "Ziggurat method for generating random variables", max@0: // J. Statistical Software, vol 5, 2000. max@0: // http://www.jstatsoft.org/v05/i08/ max@0: }; max@0: max@0: max@0: max@0: template max@0: struct eop_aux_randn< std::complex > max@0: { max@0: arma_inline max@0: operator std::complex () const max@0: { max@0: return std::complex( T(eop_aux_randn()), T(eop_aux_randn()) ); max@0: } max@0: max@0: }; max@0: max@0: max@0: //! use of the SFINAE approach to work around compiler limitations max@0: //! http://en.wikipedia.org/wiki/SFINAE max@0: max@0: class eop_aux max@0: { max@0: public: max@0: max@0: template arma_inline static typename arma_integral_only::result acos (const eT x) { return eT( std::acos(double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result asin (const eT x) { return eT( std::asin(double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result atan (const eT x) { return eT( std::atan(double(x)) ); } max@0: max@0: template arma_inline static typename arma_float_only::result acos (const eT x) { return std::acos(x); } max@0: template arma_inline static typename arma_float_only::result asin (const eT x) { return std::asin(x); } max@0: template arma_inline static typename arma_float_only::result atan (const eT x) { return std::atan(x); } max@0: max@0: template arma_inline static typename arma_cx_only::result acos (const eT x) { return arma_acos(x); } max@0: template arma_inline static typename arma_cx_only::result asin (const eT x) { return arma_asin(x); } max@0: template arma_inline static typename arma_cx_only::result atan (const eT x) { return arma_atan(x); } max@0: max@0: template arma_inline static typename arma_integral_only::result acosh (const eT x) { return eT( arma_acosh(double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result asinh (const eT x) { return eT( arma_asinh(double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result atanh (const eT x) { return eT( arma_atanh(double(x)) ); } max@0: max@0: template arma_inline static typename arma_float_or_cx_only::result acosh (const eT x) { return arma_acosh(x); } max@0: template arma_inline static typename arma_float_or_cx_only::result asinh (const eT x) { return arma_asinh(x); } max@0: template arma_inline static typename arma_float_or_cx_only::result atanh (const eT x) { return arma_atanh(x); } max@0: max@0: template arma_inline static typename arma_not_cx::result conj(const eT x) { return x; } max@0: template arma_inline static std::complex conj(const std::complex& x) { return std::conj(x); } max@0: max@0: template arma_inline static typename arma_integral_only::result sqrt (const eT x) { return eT( std::sqrt (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result log10 (const eT x) { return eT( std::log10(double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result log (const eT x) { return eT( std::log (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result exp (const eT x) { return eT( std::exp (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result cos (const eT x) { return eT( std::cos (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result sin (const eT x) { return eT( std::sin (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result tan (const eT x) { return eT( std::tan (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result cosh (const eT x) { return eT( std::cosh (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result sinh (const eT x) { return eT( std::sinh (double(x)) ); } max@0: template arma_inline static typename arma_integral_only::result tanh (const eT x) { return eT( std::tanh (double(x)) ); } max@0: max@0: template arma_inline static typename arma_float_or_cx_only::result sqrt (const eT x) { return std::sqrt (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result log10 (const eT x) { return std::log10(x); } max@0: template arma_inline static typename arma_float_or_cx_only::result log (const eT x) { return std::log (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result exp (const eT x) { return std::exp (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result cos (const eT x) { return std::cos (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result sin (const eT x) { return std::sin (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result tan (const eT x) { return std::tan (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result cosh (const eT x) { return std::cosh (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result sinh (const eT x) { return std::sinh (x); } max@0: template arma_inline static typename arma_float_or_cx_only::result tanh (const eT x) { return std::tanh (x); } max@0: max@0: template arma_inline static typename arma_unsigned_integral_only::result neg (const eT x) { return x; } max@0: template arma_inline static typename arma_signed_only::result neg (const eT x) { return -x; } max@0: max@0: template arma_inline static typename arma_integral_only::result floor(const eT x) { return x; } max@0: template arma_inline static typename arma_float_only::result floor(const eT x) { return std::floor(x); } max@0: template arma_inline static typename arma_cx_only::result floor(const eT& x) { return eT( std::floor(x.real()), std::floor(x.imag()) ); } max@0: max@0: template arma_inline static typename arma_integral_only::result ceil(const eT x) { return x; } max@0: template arma_inline static typename arma_float_only::result ceil(const eT x) { return std::ceil(x); } max@0: template arma_inline static typename arma_cx_only::result ceil(const eT& x) { return eT( std::ceil(x.real()), std::ceil(x.imag()) ); } max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_integral_only::result max@0: log2 (const eT x) max@0: { max@0: return eT( std::log(double(x))/ double(0.69314718055994530942) ); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_float_or_cx_only::result max@0: log2 (const eT x) max@0: { max@0: typedef typename get_pod_type::result T; max@0: return std::log(x) / T(0.69314718055994530942); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_integral_only::result max@0: exp10 (const eT x) max@0: { max@0: return eT( std::pow(double(10), double(x)) ); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename max@0: arma_float_or_cx_only::result max@0: exp10 (const eT x) max@0: { max@0: typedef typename get_pod_type::result T; max@0: return std::pow( T(10), x); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_integral_only::result max@0: exp2 (const eT x) max@0: { max@0: return eT( std::pow(double(2), double(x)) ); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_float_or_cx_only::result max@0: exp2 (const eT x) max@0: { max@0: typedef typename get_pod_type::result T; max@0: return std::pow( T(2), x); max@0: } max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_float_or_cx_only::result max@0: pow(const T1 base, const T2 exponent) max@0: { max@0: return std::pow(base, exponent); max@0: } max@0: max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_integral_only::result max@0: pow(const T1 base, const T2 exponent) max@0: { max@0: return T1( std::pow( double(base), double(exponent) ) ); max@0: } max@0: max@0: max@0: max@0: template max@0: arma_inline max@0: static max@0: typename arma_integral_only::result max@0: direct_eps(const eT) max@0: { max@0: return eT(0); max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: static max@0: typename arma_float_only::result max@0: direct_eps(const eT x) max@0: { max@0: //arma_extra_debug_sigprint(); max@0: max@0: // acording to IEEE Standard for Floating-Point Arithmetic (IEEE 754) max@0: // the mantissa length for double is 53 bits = std::numeric_limits::digits max@0: // the mantissa length for float is 24 bits = std::numeric_limits::digits max@0: max@0: //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)) ); max@0: max@0: const eT radix_eT = eT(std::numeric_limits::radix); max@0: const eT digits_m1_eT = eT(std::numeric_limits::digits - 1); max@0: max@0: // return std::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) ); max@0: return eop_aux::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) ); max@0: } max@0: max@0: max@0: max@0: template max@0: inline max@0: static max@0: typename arma_float_only::result max@0: direct_eps(const std::complex x) max@0: { max@0: //arma_extra_debug_sigprint(); max@0: max@0: //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)) ); max@0: max@0: const T radix_T = T(std::numeric_limits::radix); max@0: const T digits_m1_T = T(std::numeric_limits::digits - 1); max@0: max@0: return std::pow( radix_T, T(std::floor(std::log10(std::abs(x))/std::log10(radix_T)) - digits_m1_T) ); max@0: } max@0: max@0: max@0: max@0: //! work around a bug in GCC 4.4 max@0: template arma_inline static max@0: typename arma_unsigned_integral_only::result arma_abs(const eT x) { return x; } max@0: max@0: template arma_inline static max@0: typename arma_signed_integral_only::result arma_abs(const eT x) { return std::abs(x); } max@0: max@0: template arma_inline static max@0: typename arma_float_only::result arma_abs(const eT x) { return std::abs(x); } max@0: max@0: template arma_inline static max@0: typename arma_float_only::result arma_abs(const std::complex x) { return std::abs(x); } max@0: max@0: }; max@0: max@0: max@0: max@0: //! @} max@0: