annotate armadillo-3.900.4/include/armadillo_bits/eop_aux.hpp @ 84:55a047986812 tip

Update library URI so as not to be document-local
author Chris Cannam
date Wed, 22 Apr 2020 14:21:57 +0100
parents 1ec0e2823891
children
rev   line source
Chris@49 1 // Copyright (C) 2010-2013 NICTA (www.nicta.com.au)
Chris@49 2 // Copyright (C) 2010-2013 Conrad Sanderson
Chris@49 3 //
Chris@49 4 // This Source Code Form is subject to the terms of the Mozilla Public
Chris@49 5 // License, v. 2.0. If a copy of the MPL was not distributed with this
Chris@49 6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
Chris@49 7
Chris@49 8
Chris@49 9 //! \addtogroup eop_aux
Chris@49 10 //! @{
Chris@49 11
Chris@49 12
Chris@49 13
Chris@49 14 template<typename eT>
Chris@49 15 struct eop_aux_randu
Chris@49 16 {
Chris@49 17 arma_inline
Chris@49 18 operator eT ()
Chris@49 19 {
Chris@49 20 // make sure we are internally using at least floats
Chris@49 21 typedef typename promote_type<eT,float>::result eTp;
Chris@49 22
Chris@49 23 return eT( eTp(std::rand()) * ( eTp(1) / eTp(RAND_MAX) ) );
Chris@49 24 }
Chris@49 25
Chris@49 26
Chris@49 27 inline
Chris@49 28 static
Chris@49 29 void
Chris@49 30 fill(eT* mem, const uword N)
Chris@49 31 {
Chris@49 32 uword i,j;
Chris@49 33
Chris@49 34 for(i=0, j=1; j < N; i+=2, j+=2)
Chris@49 35 {
Chris@49 36 const eT tmp_i = eT(eop_aux_randu<eT>());
Chris@49 37 const eT tmp_j = eT(eop_aux_randu<eT>());
Chris@49 38
Chris@49 39 mem[i] = tmp_i;
Chris@49 40 mem[j] = tmp_j;
Chris@49 41 }
Chris@49 42
Chris@49 43 if(i < N)
Chris@49 44 {
Chris@49 45 mem[i] = eT(eop_aux_randu<eT>());
Chris@49 46 }
Chris@49 47 }
Chris@49 48 };
Chris@49 49
Chris@49 50
Chris@49 51
Chris@49 52 template<typename T>
Chris@49 53 struct eop_aux_randu< std::complex<T> >
Chris@49 54 {
Chris@49 55 arma_inline
Chris@49 56 operator std::complex<T> ()
Chris@49 57 {
Chris@49 58 return std::complex<T>( T(eop_aux_randu<T>()), T(eop_aux_randu<T>()) );
Chris@49 59 }
Chris@49 60
Chris@49 61
Chris@49 62 inline
Chris@49 63 static
Chris@49 64 void
Chris@49 65 fill(std::complex<T>* mem, const uword N)
Chris@49 66 {
Chris@49 67 for(uword i=0; i < N; ++i)
Chris@49 68 {
Chris@49 69 mem[i] = std::complex<T>( eop_aux_randu< std::complex<T> >() );
Chris@49 70 }
Chris@49 71 }
Chris@49 72 };
Chris@49 73
Chris@49 74
Chris@49 75
Chris@49 76 template<typename eT>
Chris@49 77 struct eop_aux_randn
Chris@49 78 {
Chris@49 79 // rudimentary method, based on the central limit theorem:
Chris@49 80 // http://en.wikipedia.org/wiki/Central_limit_theorem
Chris@49 81
Chris@49 82 // polar form of the Box-Muller transformation:
Chris@49 83 // http://en.wikipedia.org/wiki/Box-Muller_transformation
Chris@49 84 // http://en.wikipedia.org/wiki/Marsaglia_polar_method
Chris@49 85
Chris@49 86 // other methods:
Chris@49 87 // http://en.wikipedia.org/wiki/Ziggurat_algorithm
Chris@49 88 //
Chris@49 89 // Marsaglia and Tsang Ziggurat technique to transform from a uniform to a normal distribution.
Chris@49 90 // G. Marsaglia, W.W. Tsang.
Chris@49 91 // "Ziggurat method for generating random variables",
Chris@49 92 // J. Statistical Software, vol 5, 2000.
Chris@49 93 // http://www.jstatsoft.org/v05/i08/
Chris@49 94
Chris@49 95
Chris@49 96 // currently using polar form of the Box-Muller transformation
Chris@49 97 inline
Chris@49 98 operator eT () const
Chris@49 99 {
Chris@49 100 // make sure we are internally using at least floats
Chris@49 101 typedef typename promote_type<eT,float>::result eTp;
Chris@49 102
Chris@49 103 eTp tmp1;
Chris@49 104 eTp tmp2;
Chris@49 105 eTp w;
Chris@49 106
Chris@49 107 do
Chris@49 108 {
Chris@49 109 tmp1 = eTp(2) * eTp(std::rand()) * (eTp(1) / eTp(RAND_MAX)) - eTp(1);
Chris@49 110 tmp2 = eTp(2) * eTp(std::rand()) * (eTp(1) / eTp(RAND_MAX)) - eTp(1);
Chris@49 111
Chris@49 112 w = tmp1*tmp1 + tmp2*tmp2;
Chris@49 113 }
Chris@49 114 while ( w >= eTp(1) );
Chris@49 115
Chris@49 116 return eT( tmp1 * std::sqrt( (eTp(-2) * std::log(w)) / w) );
Chris@49 117 }
Chris@49 118
Chris@49 119
Chris@49 120
Chris@49 121 inline
Chris@49 122 static
Chris@49 123 void
Chris@49 124 generate(eT& out1, eT& out2)
Chris@49 125 {
Chris@49 126 // make sure we are internally using at least floats
Chris@49 127 typedef typename promote_type<eT,float>::result eTp;
Chris@49 128
Chris@49 129 eTp tmp1;
Chris@49 130 eTp tmp2;
Chris@49 131 eTp w;
Chris@49 132
Chris@49 133 do
Chris@49 134 {
Chris@49 135 tmp1 = eTp(2) * eTp(std::rand()) * (eTp(1) / eTp(RAND_MAX)) - eTp(1);
Chris@49 136 tmp2 = eTp(2) * eTp(std::rand()) * (eTp(1) / eTp(RAND_MAX)) - eTp(1);
Chris@49 137
Chris@49 138 w = tmp1*tmp1 + tmp2*tmp2;
Chris@49 139 }
Chris@49 140 while ( w >= eTp(1) );
Chris@49 141
Chris@49 142 const eTp k = std::sqrt( (eTp(-2) * std::log(w)) / w);
Chris@49 143
Chris@49 144 out1 = eT(tmp1*k);
Chris@49 145 out2 = eT(tmp2*k);
Chris@49 146 }
Chris@49 147
Chris@49 148
Chris@49 149
Chris@49 150 inline
Chris@49 151 static
Chris@49 152 void
Chris@49 153 fill(eT* mem, const uword N)
Chris@49 154 {
Chris@49 155 uword i, j;
Chris@49 156
Chris@49 157 for(i=0, j=1; j < N; i+=2, j+=2)
Chris@49 158 {
Chris@49 159 eop_aux_randn<eT>::generate( mem[i], mem[j] );
Chris@49 160 }
Chris@49 161
Chris@49 162 if(i < N)
Chris@49 163 {
Chris@49 164 mem[i] = eT(eop_aux_randn<eT>());
Chris@49 165 }
Chris@49 166 }
Chris@49 167
Chris@49 168 };
Chris@49 169
Chris@49 170
Chris@49 171
Chris@49 172 template<typename T>
Chris@49 173 struct eop_aux_randn< std::complex<T> >
Chris@49 174 {
Chris@49 175 inline
Chris@49 176 operator std::complex<T> () const
Chris@49 177 {
Chris@49 178 T a, b;
Chris@49 179
Chris@49 180 eop_aux_randn<T>::generate(a, b);
Chris@49 181
Chris@49 182 return std::complex<T>(a, b);
Chris@49 183 }
Chris@49 184
Chris@49 185
Chris@49 186 inline
Chris@49 187 static
Chris@49 188 void
Chris@49 189 fill(std::complex<T>* mem, const uword N)
Chris@49 190 {
Chris@49 191 for(uword i=0; i < N; ++i)
Chris@49 192 {
Chris@49 193 mem[i] = std::complex<T>( eop_aux_randn< std::complex<T> >() );
Chris@49 194 }
Chris@49 195 }
Chris@49 196
Chris@49 197 };
Chris@49 198
Chris@49 199
Chris@49 200
Chris@49 201 //! use of the SFINAE approach to work around compiler limitations
Chris@49 202 //! http://en.wikipedia.org/wiki/SFINAE
Chris@49 203
Chris@49 204 class eop_aux
Chris@49 205 {
Chris@49 206 public:
Chris@49 207
Chris@49 208 template<typename eT> arma_inline static typename arma_integral_only<eT>::result acos (const eT x) { return eT( std::acos(double(x)) ); }
Chris@49 209 template<typename eT> arma_inline static typename arma_integral_only<eT>::result asin (const eT x) { return eT( std::asin(double(x)) ); }
Chris@49 210 template<typename eT> arma_inline static typename arma_integral_only<eT>::result atan (const eT x) { return eT( std::atan(double(x)) ); }
Chris@49 211
Chris@49 212 template<typename eT> arma_inline static typename arma_real_only<eT>::result acos (const eT x) { return std::acos(x); }
Chris@49 213 template<typename eT> arma_inline static typename arma_real_only<eT>::result asin (const eT x) { return std::asin(x); }
Chris@49 214 template<typename eT> arma_inline static typename arma_real_only<eT>::result atan (const eT x) { return std::atan(x); }
Chris@49 215
Chris@49 216 template<typename eT> arma_inline static typename arma_cx_only<eT>::result acos (const eT x) { return arma_acos(x); }
Chris@49 217 template<typename eT> arma_inline static typename arma_cx_only<eT>::result asin (const eT x) { return arma_asin(x); }
Chris@49 218 template<typename eT> arma_inline static typename arma_cx_only<eT>::result atan (const eT x) { return arma_atan(x); }
Chris@49 219
Chris@49 220 template<typename eT> arma_inline static typename arma_integral_only<eT>::result acosh (const eT x) { return eT( arma_acosh(double(x)) ); }
Chris@49 221 template<typename eT> arma_inline static typename arma_integral_only<eT>::result asinh (const eT x) { return eT( arma_asinh(double(x)) ); }
Chris@49 222 template<typename eT> arma_inline static typename arma_integral_only<eT>::result atanh (const eT x) { return eT( arma_atanh(double(x)) ); }
Chris@49 223
Chris@49 224 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result acosh (const eT x) { return arma_acosh(x); }
Chris@49 225 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result asinh (const eT x) { return arma_asinh(x); }
Chris@49 226 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result atanh (const eT x) { return arma_atanh(x); }
Chris@49 227
Chris@49 228 template<typename eT> arma_inline static typename arma_not_cx<eT>::result conj(const eT x) { return x; }
Chris@49 229 template<typename T> arma_inline static std::complex<T> conj(const std::complex<T>& x) { return std::conj(x); }
Chris@49 230
Chris@49 231 template<typename eT> arma_inline static typename arma_integral_only<eT>::result sqrt (const eT x) { return eT( std::sqrt (double(x)) ); }
Chris@49 232 template<typename eT> arma_inline static typename arma_integral_only<eT>::result log10 (const eT x) { return eT( std::log10(double(x)) ); }
Chris@49 233 template<typename eT> arma_inline static typename arma_integral_only<eT>::result log (const eT x) { return eT( std::log (double(x)) ); }
Chris@49 234 template<typename eT> arma_inline static typename arma_integral_only<eT>::result exp (const eT x) { return eT( std::exp (double(x)) ); }
Chris@49 235 template<typename eT> arma_inline static typename arma_integral_only<eT>::result cos (const eT x) { return eT( std::cos (double(x)) ); }
Chris@49 236 template<typename eT> arma_inline static typename arma_integral_only<eT>::result sin (const eT x) { return eT( std::sin (double(x)) ); }
Chris@49 237 template<typename eT> arma_inline static typename arma_integral_only<eT>::result tan (const eT x) { return eT( std::tan (double(x)) ); }
Chris@49 238 template<typename eT> arma_inline static typename arma_integral_only<eT>::result cosh (const eT x) { return eT( std::cosh (double(x)) ); }
Chris@49 239 template<typename eT> arma_inline static typename arma_integral_only<eT>::result sinh (const eT x) { return eT( std::sinh (double(x)) ); }
Chris@49 240 template<typename eT> arma_inline static typename arma_integral_only<eT>::result tanh (const eT x) { return eT( std::tanh (double(x)) ); }
Chris@49 241
Chris@49 242 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result sqrt (const eT x) { return std::sqrt (x); }
Chris@49 243 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result log10 (const eT x) { return std::log10(x); }
Chris@49 244 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result log (const eT x) { return std::log (x); }
Chris@49 245 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result exp (const eT x) { return std::exp (x); }
Chris@49 246 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result cos (const eT x) { return std::cos (x); }
Chris@49 247 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result sin (const eT x) { return std::sin (x); }
Chris@49 248 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result tan (const eT x) { return std::tan (x); }
Chris@49 249 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result cosh (const eT x) { return std::cosh (x); }
Chris@49 250 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result sinh (const eT x) { return std::sinh (x); }
Chris@49 251 template<typename eT> arma_inline static typename arma_real_or_cx_only<eT>::result tanh (const eT x) { return std::tanh (x); }
Chris@49 252
Chris@49 253 template<typename eT> arma_inline static typename arma_unsigned_integral_only<eT>::result neg (const eT x) { return x; }
Chris@49 254 template<typename eT> arma_inline static typename arma_signed_only<eT>::result neg (const eT x) { return -x; }
Chris@49 255
Chris@49 256 template<typename eT> arma_inline static typename arma_integral_only<eT>::result floor(const eT x) { return x; }
Chris@49 257 template<typename eT> arma_inline static typename arma_real_only<eT>::result floor(const eT x) { return std::floor(x); }
Chris@49 258 template<typename eT> arma_inline static typename arma_cx_only<eT>::result floor(const eT& x) { return eT( std::floor(x.real()), std::floor(x.imag()) ); }
Chris@49 259
Chris@49 260 template<typename eT> arma_inline static typename arma_integral_only<eT>::result ceil(const eT x) { return x; }
Chris@49 261 template<typename eT> arma_inline static typename arma_real_only<eT>::result ceil(const eT x) { return std::ceil(x); }
Chris@49 262 template<typename eT> arma_inline static typename arma_cx_only<eT>::result ceil(const eT& x) { return eT( std::ceil(x.real()), std::ceil(x.imag()) ); }
Chris@49 263
Chris@49 264 template<typename eT> arma_inline static typename arma_integral_only<eT>::result round(const eT x) { return x; }
Chris@49 265 template<typename eT> arma_inline static typename arma_real_only<eT>::result round(const eT x) { return (x >= eT(0)) ? std::floor(x+0.5) : std::ceil(x-0.5); }
Chris@49 266 template<typename eT> arma_inline static typename arma_cx_only<eT>::result round(const eT& x) { return eT( eop_aux::round(x.real()), eop_aux::round(x.imag()) ); }
Chris@49 267
Chris@49 268 template<typename eT>
Chris@49 269 arma_inline
Chris@49 270 static
Chris@49 271 typename arma_integral_only<eT>::result
Chris@49 272 log2 (const eT x)
Chris@49 273 {
Chris@49 274 return eT( std::log(double(x))/ double(0.69314718055994530942) );
Chris@49 275 }
Chris@49 276
Chris@49 277
Chris@49 278 template<typename eT>
Chris@49 279 arma_inline
Chris@49 280 static
Chris@49 281 typename arma_real_or_cx_only<eT>::result
Chris@49 282 log2 (const eT x)
Chris@49 283 {
Chris@49 284 typedef typename get_pod_type<eT>::result T;
Chris@49 285 return std::log(x) / T(0.69314718055994530942);
Chris@49 286 }
Chris@49 287
Chris@49 288
Chris@49 289 template<typename eT>
Chris@49 290 arma_inline
Chris@49 291 static
Chris@49 292 typename arma_integral_only<eT>::result
Chris@49 293 exp10 (const eT x)
Chris@49 294 {
Chris@49 295 return eT( std::pow(double(10), double(x)) );
Chris@49 296 }
Chris@49 297
Chris@49 298
Chris@49 299 template<typename eT>
Chris@49 300 arma_inline
Chris@49 301 static
Chris@49 302 typename
Chris@49 303 arma_real_or_cx_only<eT>::result
Chris@49 304 exp10 (const eT x)
Chris@49 305 {
Chris@49 306 typedef typename get_pod_type<eT>::result T;
Chris@49 307 return std::pow( T(10), x);
Chris@49 308 }
Chris@49 309
Chris@49 310
Chris@49 311 template<typename eT>
Chris@49 312 arma_inline
Chris@49 313 static
Chris@49 314 typename arma_integral_only<eT>::result
Chris@49 315 exp2 (const eT x)
Chris@49 316 {
Chris@49 317 return eT( std::pow(double(2), double(x)) );
Chris@49 318 }
Chris@49 319
Chris@49 320
Chris@49 321 template<typename eT>
Chris@49 322 arma_inline
Chris@49 323 static
Chris@49 324 typename arma_real_or_cx_only<eT>::result
Chris@49 325 exp2 (const eT x)
Chris@49 326 {
Chris@49 327 typedef typename get_pod_type<eT>::result T;
Chris@49 328 return std::pow( T(2), x);
Chris@49 329 }
Chris@49 330
Chris@49 331
Chris@49 332 template<typename T1, typename T2>
Chris@49 333 arma_inline
Chris@49 334 static
Chris@49 335 typename arma_real_or_cx_only<T1>::result
Chris@49 336 pow(const T1 base, const T2 exponent)
Chris@49 337 {
Chris@49 338 return std::pow(base, exponent);
Chris@49 339 }
Chris@49 340
Chris@49 341
Chris@49 342
Chris@49 343 template<typename T1, typename T2>
Chris@49 344 arma_inline
Chris@49 345 static
Chris@49 346 typename arma_integral_only<T1>::result
Chris@49 347 pow(const T1 base, const T2 exponent)
Chris@49 348 {
Chris@49 349 return T1( std::pow( double(base), double(exponent) ) );
Chris@49 350 }
Chris@49 351
Chris@49 352
Chris@49 353
Chris@49 354 template<typename eT>
Chris@49 355 arma_inline
Chris@49 356 static
Chris@49 357 typename arma_integral_only<eT>::result
Chris@49 358 direct_eps(const eT)
Chris@49 359 {
Chris@49 360 return eT(0);
Chris@49 361 }
Chris@49 362
Chris@49 363
Chris@49 364
Chris@49 365 template<typename eT>
Chris@49 366 inline
Chris@49 367 static
Chris@49 368 typename arma_real_only<eT>::result
Chris@49 369 direct_eps(const eT x)
Chris@49 370 {
Chris@49 371 //arma_extra_debug_sigprint();
Chris@49 372
Chris@49 373 // acording to IEEE Standard for Floating-Point Arithmetic (IEEE 754)
Chris@49 374 // the mantissa length for double is 53 bits = std::numeric_limits<double>::digits
Chris@49 375 // the mantissa length for float is 24 bits = std::numeric_limits<float >::digits
Chris@49 376
Chris@49 377 //return std::pow( std::numeric_limits<eT>::radix, (std::floor(std::log10(std::abs(x))/std::log10(std::numeric_limits<eT>::radix))-(std::numeric_limits<eT>::digits-1)) );
Chris@49 378
Chris@49 379 const eT radix_eT = eT(std::numeric_limits<eT>::radix);
Chris@49 380 const eT digits_m1_eT = eT(std::numeric_limits<eT>::digits - 1);
Chris@49 381
Chris@49 382 // return std::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) );
Chris@49 383 return eop_aux::pow( radix_eT, eT(std::floor(std::log10(std::abs(x))/std::log10(radix_eT)) - digits_m1_eT) );
Chris@49 384 }
Chris@49 385
Chris@49 386
Chris@49 387
Chris@49 388 template<typename T>
Chris@49 389 inline
Chris@49 390 static
Chris@49 391 typename arma_real_only<T>::result
Chris@49 392 direct_eps(const std::complex<T> x)
Chris@49 393 {
Chris@49 394 //arma_extra_debug_sigprint();
Chris@49 395
Chris@49 396 //return std::pow( std::numeric_limits<T>::radix, (std::floor(std::log10(std::abs(x))/std::log10(std::numeric_limits<T>::radix))-(std::numeric_limits<T>::digits-1)) );
Chris@49 397
Chris@49 398 const T radix_T = T(std::numeric_limits<T>::radix);
Chris@49 399 const T digits_m1_T = T(std::numeric_limits<T>::digits - 1);
Chris@49 400
Chris@49 401 return std::pow( radix_T, T(std::floor(std::log10(std::abs(x))/std::log10(radix_T)) - digits_m1_T) );
Chris@49 402 }
Chris@49 403
Chris@49 404
Chris@49 405
Chris@49 406 //! work around a bug in GCC 4.4
Chris@49 407 template<typename eT> arma_inline static
Chris@49 408 typename arma_unsigned_integral_only<eT>::result arma_abs(const eT x) { return x; }
Chris@49 409
Chris@49 410 template<typename eT> arma_inline static
Chris@49 411 typename arma_signed_integral_only<eT>::result arma_abs(const eT x) { return std::abs(x); }
Chris@49 412
Chris@49 413 template<typename eT> arma_inline static
Chris@49 414 typename arma_real_only<eT>::result arma_abs(const eT x) { return std::abs(x); }
Chris@49 415
Chris@49 416 template<typename T> arma_inline static
Chris@49 417 typename arma_real_only<T>::result arma_abs(const std::complex<T> x) { return std::abs(x); }
Chris@49 418
Chris@49 419 };
Chris@49 420
Chris@49 421
Chris@49 422
Chris@49 423 //! @}
Chris@49 424