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
|