Chris@49
|
1 // Copyright (C) 2008-2012 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2008-2012 Conrad Sanderson
|
Chris@49
|
3 // Copyright (C) 2009 Edmund Highcock
|
Chris@49
|
4 // Copyright (C) 2011 James Sanders
|
Chris@49
|
5 // Copyright (C) 2012 Eric Jon Sundstrom
|
Chris@49
|
6 //
|
Chris@49
|
7 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
8 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
9 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
10
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13 #ifdef ARMA_USE_LAPACK
|
Chris@49
|
14
|
Chris@49
|
15
|
Chris@49
|
16 //! \namespace lapack namespace for LAPACK functions
|
Chris@49
|
17 namespace lapack
|
Chris@49
|
18 {
|
Chris@49
|
19
|
Chris@49
|
20
|
Chris@49
|
21 template<typename eT>
|
Chris@49
|
22 inline
|
Chris@49
|
23 void
|
Chris@49
|
24 getrf(blas_int* m, blas_int* n, eT* a, blas_int* lda, blas_int* ipiv, blas_int* info)
|
Chris@49
|
25 {
|
Chris@49
|
26 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
27
|
Chris@49
|
28 if(is_float<eT>::value == true)
|
Chris@49
|
29 {
|
Chris@49
|
30 typedef float T;
|
Chris@49
|
31 arma_fortran(arma_sgetrf)(m, n, (T*)a, lda, ipiv, info);
|
Chris@49
|
32 }
|
Chris@49
|
33 else
|
Chris@49
|
34 if(is_double<eT>::value == true)
|
Chris@49
|
35 {
|
Chris@49
|
36 typedef double T;
|
Chris@49
|
37 arma_fortran(arma_dgetrf)(m, n, (T*)a, lda, ipiv, info);
|
Chris@49
|
38 }
|
Chris@49
|
39 else
|
Chris@49
|
40 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
41 {
|
Chris@49
|
42 typedef std::complex<float> T;
|
Chris@49
|
43 arma_fortran(arma_cgetrf)(m, n, (T*)a, lda, ipiv, info);
|
Chris@49
|
44 }
|
Chris@49
|
45 else
|
Chris@49
|
46 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
47 {
|
Chris@49
|
48 typedef std::complex<double> T;
|
Chris@49
|
49 arma_fortran(arma_zgetrf)(m, n, (T*)a, lda, ipiv, info);
|
Chris@49
|
50 }
|
Chris@49
|
51 }
|
Chris@49
|
52
|
Chris@49
|
53
|
Chris@49
|
54
|
Chris@49
|
55 template<typename eT>
|
Chris@49
|
56 inline
|
Chris@49
|
57 void
|
Chris@49
|
58 getri(blas_int* n, eT* a, blas_int* lda, blas_int* ipiv, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
59 {
|
Chris@49
|
60 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
61
|
Chris@49
|
62 if(is_float<eT>::value == true)
|
Chris@49
|
63 {
|
Chris@49
|
64 typedef float T;
|
Chris@49
|
65 arma_fortran(arma_sgetri)(n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
66 }
|
Chris@49
|
67 else
|
Chris@49
|
68 if(is_double<eT>::value == true)
|
Chris@49
|
69 {
|
Chris@49
|
70 typedef double T;
|
Chris@49
|
71 arma_fortran(arma_dgetri)(n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
72 }
|
Chris@49
|
73 else
|
Chris@49
|
74 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
75 {
|
Chris@49
|
76 typedef std::complex<float> T;
|
Chris@49
|
77 arma_fortran(arma_cgetri)(n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
78 }
|
Chris@49
|
79 else
|
Chris@49
|
80 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
81 {
|
Chris@49
|
82 typedef std::complex<double> T;
|
Chris@49
|
83 arma_fortran(arma_zgetri)(n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
84 }
|
Chris@49
|
85 }
|
Chris@49
|
86
|
Chris@49
|
87
|
Chris@49
|
88
|
Chris@49
|
89 template<typename eT>
|
Chris@49
|
90 inline
|
Chris@49
|
91 void
|
Chris@49
|
92 trtri(char* uplo, char* diag, blas_int* n, eT* a, blas_int* lda, blas_int* info)
|
Chris@49
|
93 {
|
Chris@49
|
94 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
95
|
Chris@49
|
96 if(is_float<eT>::value == true)
|
Chris@49
|
97 {
|
Chris@49
|
98 typedef float T;
|
Chris@49
|
99 arma_fortran(arma_strtri)(uplo, diag, n, (T*)a, lda, info);
|
Chris@49
|
100 }
|
Chris@49
|
101 else
|
Chris@49
|
102 if(is_double<eT>::value == true)
|
Chris@49
|
103 {
|
Chris@49
|
104 typedef double T;
|
Chris@49
|
105 arma_fortran(arma_dtrtri)(uplo, diag, n, (T*)a, lda, info);
|
Chris@49
|
106 }
|
Chris@49
|
107 else
|
Chris@49
|
108 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
109 {
|
Chris@49
|
110 typedef std::complex<float> T;
|
Chris@49
|
111 arma_fortran(arma_ctrtri)(uplo, diag, n, (T*)a, lda, info);
|
Chris@49
|
112 }
|
Chris@49
|
113 else
|
Chris@49
|
114 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
115 {
|
Chris@49
|
116 typedef std::complex<double> T;
|
Chris@49
|
117 arma_fortran(arma_ztrtri)(uplo, diag, n, (T*)a, lda, info);
|
Chris@49
|
118 }
|
Chris@49
|
119 }
|
Chris@49
|
120
|
Chris@49
|
121
|
Chris@49
|
122
|
Chris@49
|
123 template<typename eT>
|
Chris@49
|
124 inline
|
Chris@49
|
125 void
|
Chris@49
|
126 syev(char* jobz, char* uplo, blas_int* n, eT* a, blas_int* lda, eT* w, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
127 {
|
Chris@49
|
128 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
129
|
Chris@49
|
130 if(is_float<eT>::value == true)
|
Chris@49
|
131 {
|
Chris@49
|
132 typedef float T;
|
Chris@49
|
133 arma_fortran(arma_ssyev)(jobz, uplo, n, (T*)a, lda, (T*)w, (T*)work, lwork, info);
|
Chris@49
|
134 }
|
Chris@49
|
135 else
|
Chris@49
|
136 if(is_double<eT>::value == true)
|
Chris@49
|
137 {
|
Chris@49
|
138 typedef double T;
|
Chris@49
|
139 arma_fortran(arma_dsyev)(jobz, uplo, n, (T*)a, lda, (T*)w, (T*)work, lwork, info);
|
Chris@49
|
140 }
|
Chris@49
|
141 }
|
Chris@49
|
142
|
Chris@49
|
143
|
Chris@49
|
144
|
Chris@49
|
145 template<typename eT>
|
Chris@49
|
146 inline
|
Chris@49
|
147 void
|
Chris@49
|
148 syevd(char* jobz, char* uplo, blas_int* n, eT* a, blas_int* lda, eT* w, eT* work, blas_int* lwork, blas_int* iwork, blas_int* liwork, blas_int* info)
|
Chris@49
|
149 {
|
Chris@49
|
150 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
151
|
Chris@49
|
152 if(is_float<eT>::value == true)
|
Chris@49
|
153 {
|
Chris@49
|
154 typedef float T;
|
Chris@49
|
155 arma_fortran(arma_ssyevd)(jobz, uplo, n, (T*)a, lda, (T*)w, (T*)work, lwork, iwork, liwork, info);
|
Chris@49
|
156 }
|
Chris@49
|
157 else
|
Chris@49
|
158 if(is_double<eT>::value == true)
|
Chris@49
|
159 {
|
Chris@49
|
160 typedef double T;
|
Chris@49
|
161 arma_fortran(arma_dsyevd)(jobz, uplo, n, (T*)a, lda, (T*)w, (T*)work, lwork, iwork, liwork, info);
|
Chris@49
|
162 }
|
Chris@49
|
163 }
|
Chris@49
|
164
|
Chris@49
|
165
|
Chris@49
|
166
|
Chris@49
|
167 template<typename eT>
|
Chris@49
|
168 inline
|
Chris@49
|
169 void
|
Chris@49
|
170 heev
|
Chris@49
|
171 (
|
Chris@49
|
172 char* jobz, char* uplo, blas_int* n,
|
Chris@49
|
173 eT* a, blas_int* lda, typename eT::value_type* w,
|
Chris@49
|
174 eT* work, blas_int* lwork, typename eT::value_type* rwork,
|
Chris@49
|
175 blas_int* info
|
Chris@49
|
176 )
|
Chris@49
|
177 {
|
Chris@49
|
178 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
179
|
Chris@49
|
180 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
181 {
|
Chris@49
|
182 typedef float T;
|
Chris@49
|
183 typedef typename std::complex<T> cx_T;
|
Chris@49
|
184 arma_fortran(arma_cheev)(jobz, uplo, n, (cx_T*)a, lda, (T*)w, (cx_T*)work, lwork, (T*)rwork, info);
|
Chris@49
|
185 }
|
Chris@49
|
186 else
|
Chris@49
|
187 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
188 {
|
Chris@49
|
189 typedef double T;
|
Chris@49
|
190 typedef typename std::complex<T> cx_T;
|
Chris@49
|
191 arma_fortran(arma_zheev)(jobz, uplo, n, (cx_T*)a, lda, (T*)w, (cx_T*)work, lwork, (T*)rwork, info);
|
Chris@49
|
192 }
|
Chris@49
|
193 }
|
Chris@49
|
194
|
Chris@49
|
195
|
Chris@49
|
196
|
Chris@49
|
197 template<typename eT>
|
Chris@49
|
198 inline
|
Chris@49
|
199 void
|
Chris@49
|
200 heevd
|
Chris@49
|
201 (
|
Chris@49
|
202 char* jobz, char* uplo, blas_int* n,
|
Chris@49
|
203 eT* a, blas_int* lda, typename eT::value_type* w,
|
Chris@49
|
204 eT* work, blas_int* lwork, typename eT::value_type* rwork,
|
Chris@49
|
205 blas_int* lrwork, blas_int* iwork, blas_int* liwork,
|
Chris@49
|
206 blas_int* info
|
Chris@49
|
207 )
|
Chris@49
|
208 {
|
Chris@49
|
209 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
210
|
Chris@49
|
211 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
212 {
|
Chris@49
|
213 typedef float T;
|
Chris@49
|
214 typedef typename std::complex<T> cx_T;
|
Chris@49
|
215 arma_fortran(arma_cheevd)(jobz, uplo, n, (cx_T*)a, lda, (T*)w, (cx_T*)work, lwork, (T*)rwork, lrwork, iwork, liwork, info);
|
Chris@49
|
216 }
|
Chris@49
|
217 else
|
Chris@49
|
218 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
219 {
|
Chris@49
|
220 typedef double T;
|
Chris@49
|
221 typedef typename std::complex<T> cx_T;
|
Chris@49
|
222 arma_fortran(arma_zheevd)(jobz, uplo, n, (cx_T*)a, lda, (T*)w, (cx_T*)work, lwork, (T*)rwork, lrwork, iwork, liwork, info);
|
Chris@49
|
223 }
|
Chris@49
|
224 }
|
Chris@49
|
225
|
Chris@49
|
226
|
Chris@49
|
227
|
Chris@49
|
228 template<typename eT>
|
Chris@49
|
229 inline
|
Chris@49
|
230 void
|
Chris@49
|
231 geev
|
Chris@49
|
232 (
|
Chris@49
|
233 char* jobvl, char* jobvr, blas_int* n,
|
Chris@49
|
234 eT* a, blas_int* lda, eT* wr, eT* wi, eT* vl,
|
Chris@49
|
235 blas_int* ldvl, eT* vr, blas_int* ldvr,
|
Chris@49
|
236 eT* work, blas_int* lwork,
|
Chris@49
|
237 blas_int* info
|
Chris@49
|
238 )
|
Chris@49
|
239 {
|
Chris@49
|
240 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
241
|
Chris@49
|
242 if(is_float<eT>::value == true)
|
Chris@49
|
243 {
|
Chris@49
|
244 typedef float T;
|
Chris@49
|
245 arma_fortran(arma_sgeev)(jobvl, jobvr, n, (T*)a, lda, (T*)wr, (T*)wi, (T*)vl, ldvl, (T*)vr, ldvr, (T*)work, lwork, info);
|
Chris@49
|
246 }
|
Chris@49
|
247 else
|
Chris@49
|
248 if(is_double<eT>::value == true)
|
Chris@49
|
249 {
|
Chris@49
|
250 typedef double T;
|
Chris@49
|
251 arma_fortran(arma_dgeev)(jobvl, jobvr, n, (T*)a, lda, (T*)wr, (T*)wi, (T*)vl, ldvl, (T*)vr, ldvr, (T*)work, lwork, info);
|
Chris@49
|
252 }
|
Chris@49
|
253 }
|
Chris@49
|
254
|
Chris@49
|
255
|
Chris@49
|
256 template<typename eT>
|
Chris@49
|
257 inline
|
Chris@49
|
258 void
|
Chris@49
|
259 cx_geev
|
Chris@49
|
260 (
|
Chris@49
|
261 char* jobvl, char* jobvr, blas_int* n,
|
Chris@49
|
262 eT* a, blas_int* lda, eT* w,
|
Chris@49
|
263 eT* vl, blas_int* ldvl,
|
Chris@49
|
264 eT* vr, blas_int* ldvr,
|
Chris@49
|
265 eT* work, blas_int* lwork, typename eT::value_type* rwork,
|
Chris@49
|
266 blas_int* info
|
Chris@49
|
267 )
|
Chris@49
|
268 {
|
Chris@49
|
269 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
270
|
Chris@49
|
271 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
272 {
|
Chris@49
|
273 typedef float T;
|
Chris@49
|
274 typedef typename std::complex<T> cx_T;
|
Chris@49
|
275 arma_fortran(arma_cgeev)(jobvl, jobvr, n, (cx_T*)a, lda, (cx_T*)w, (cx_T*)vl, ldvl, (cx_T*)vr, ldvr, (cx_T*)work, lwork, (T*)rwork, info);
|
Chris@49
|
276 }
|
Chris@49
|
277 else
|
Chris@49
|
278 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
279 {
|
Chris@49
|
280 typedef double T;
|
Chris@49
|
281 typedef typename std::complex<T> cx_T;
|
Chris@49
|
282 arma_fortran(arma_zgeev)(jobvl, jobvr, n, (cx_T*)a, lda, (cx_T*)w, (cx_T*)vl, ldvl, (cx_T*)vr, ldvr, (cx_T*)work, lwork, (T*)rwork, info);
|
Chris@49
|
283 }
|
Chris@49
|
284 }
|
Chris@49
|
285
|
Chris@49
|
286
|
Chris@49
|
287
|
Chris@49
|
288
|
Chris@49
|
289 template<typename eT>
|
Chris@49
|
290 inline
|
Chris@49
|
291 void
|
Chris@49
|
292 potrf(char* uplo, blas_int* n, eT* a, blas_int* lda, blas_int* info)
|
Chris@49
|
293 {
|
Chris@49
|
294 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
295
|
Chris@49
|
296 if(is_float<eT>::value == true)
|
Chris@49
|
297 {
|
Chris@49
|
298 typedef float T;
|
Chris@49
|
299 arma_fortran(arma_spotrf)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
300 }
|
Chris@49
|
301 else
|
Chris@49
|
302 if(is_double<eT>::value == true)
|
Chris@49
|
303 {
|
Chris@49
|
304 typedef double T;
|
Chris@49
|
305 arma_fortran(arma_dpotrf)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
306 }
|
Chris@49
|
307 else
|
Chris@49
|
308 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
309 {
|
Chris@49
|
310 typedef std::complex<float> T;
|
Chris@49
|
311 arma_fortran(arma_cpotrf)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
312 }
|
Chris@49
|
313 else
|
Chris@49
|
314 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
315 {
|
Chris@49
|
316 typedef std::complex<double> T;
|
Chris@49
|
317 arma_fortran(arma_zpotrf)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
318 }
|
Chris@49
|
319
|
Chris@49
|
320 }
|
Chris@49
|
321
|
Chris@49
|
322
|
Chris@49
|
323
|
Chris@49
|
324 template<typename eT>
|
Chris@49
|
325 inline
|
Chris@49
|
326 void
|
Chris@49
|
327 potri(char* uplo, blas_int* n, eT* a, blas_int* lda, blas_int* info)
|
Chris@49
|
328 {
|
Chris@49
|
329 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
330
|
Chris@49
|
331 if(is_float<eT>::value == true)
|
Chris@49
|
332 {
|
Chris@49
|
333 typedef float T;
|
Chris@49
|
334 arma_fortran(arma_spotri)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
335 }
|
Chris@49
|
336 else
|
Chris@49
|
337 if(is_double<eT>::value == true)
|
Chris@49
|
338 {
|
Chris@49
|
339 typedef double T;
|
Chris@49
|
340 arma_fortran(arma_dpotri)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
341 }
|
Chris@49
|
342 else
|
Chris@49
|
343 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
344 {
|
Chris@49
|
345 typedef std::complex<float> T;
|
Chris@49
|
346 arma_fortran(arma_cpotri)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
347 }
|
Chris@49
|
348 else
|
Chris@49
|
349 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
350 {
|
Chris@49
|
351 typedef std::complex<double> T;
|
Chris@49
|
352 arma_fortran(arma_zpotri)(uplo, n, (T*)a, lda, info);
|
Chris@49
|
353 }
|
Chris@49
|
354
|
Chris@49
|
355 }
|
Chris@49
|
356
|
Chris@49
|
357
|
Chris@49
|
358
|
Chris@49
|
359 template<typename eT>
|
Chris@49
|
360 inline
|
Chris@49
|
361 void
|
Chris@49
|
362 geqrf(blas_int* m, blas_int* n, eT* a, blas_int* lda, eT* tau, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
363 {
|
Chris@49
|
364 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
365
|
Chris@49
|
366 if(is_float<eT>::value == true)
|
Chris@49
|
367 {
|
Chris@49
|
368 typedef float T;
|
Chris@49
|
369 arma_fortran(arma_sgeqrf)(m, n, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
370 }
|
Chris@49
|
371 else
|
Chris@49
|
372 if(is_double<eT>::value == true)
|
Chris@49
|
373 {
|
Chris@49
|
374 typedef double T;
|
Chris@49
|
375 arma_fortran(arma_dgeqrf)(m, n, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
376 }
|
Chris@49
|
377 else
|
Chris@49
|
378 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
379 {
|
Chris@49
|
380 typedef std::complex<float> T;
|
Chris@49
|
381 arma_fortran(arma_cgeqrf)(m, n, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
382 }
|
Chris@49
|
383 else
|
Chris@49
|
384 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
385 {
|
Chris@49
|
386 typedef std::complex<double> T;
|
Chris@49
|
387 arma_fortran(arma_zgeqrf)(m, n, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
388 }
|
Chris@49
|
389
|
Chris@49
|
390 }
|
Chris@49
|
391
|
Chris@49
|
392
|
Chris@49
|
393
|
Chris@49
|
394 template<typename eT>
|
Chris@49
|
395 inline
|
Chris@49
|
396 void
|
Chris@49
|
397 orgqr(blas_int* m, blas_int* n, blas_int* k, eT* a, blas_int* lda, eT* tau, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
398 {
|
Chris@49
|
399 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
400
|
Chris@49
|
401 if(is_float<eT>::value == true)
|
Chris@49
|
402 {
|
Chris@49
|
403 typedef float T;
|
Chris@49
|
404 arma_fortran(arma_sorgqr)(m, n, k, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
405 }
|
Chris@49
|
406 else
|
Chris@49
|
407 if(is_double<eT>::value == true)
|
Chris@49
|
408 {
|
Chris@49
|
409 typedef double T;
|
Chris@49
|
410 arma_fortran(arma_dorgqr)(m, n, k, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
411 }
|
Chris@49
|
412 }
|
Chris@49
|
413
|
Chris@49
|
414
|
Chris@49
|
415
|
Chris@49
|
416 template<typename eT>
|
Chris@49
|
417 inline
|
Chris@49
|
418 void
|
Chris@49
|
419 ungqr(blas_int* m, blas_int* n, blas_int* k, eT* a, blas_int* lda, eT* tau, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
420 {
|
Chris@49
|
421 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
422
|
Chris@49
|
423 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
424 {
|
Chris@49
|
425 typedef float T;
|
Chris@49
|
426 arma_fortran(arma_cungqr)(m, n, k, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
427 }
|
Chris@49
|
428 else
|
Chris@49
|
429 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
430 {
|
Chris@49
|
431 typedef double T;
|
Chris@49
|
432 arma_fortran(arma_zungqr)(m, n, k, (T*)a, lda, (T*)tau, (T*)work, lwork, info);
|
Chris@49
|
433 }
|
Chris@49
|
434 }
|
Chris@49
|
435
|
Chris@49
|
436
|
Chris@49
|
437 template<typename eT>
|
Chris@49
|
438 inline
|
Chris@49
|
439 void
|
Chris@49
|
440 gesvd
|
Chris@49
|
441 (
|
Chris@49
|
442 char* jobu, char* jobvt, blas_int* m, blas_int* n, eT* a, blas_int* lda,
|
Chris@49
|
443 eT* s, eT* u, blas_int* ldu, eT* vt, blas_int* ldvt,
|
Chris@49
|
444 eT* work, blas_int* lwork, blas_int* info
|
Chris@49
|
445 )
|
Chris@49
|
446 {
|
Chris@49
|
447 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
448
|
Chris@49
|
449 if(is_float<eT>::value == true)
|
Chris@49
|
450 {
|
Chris@49
|
451 typedef float T;
|
Chris@49
|
452 arma_fortran(arma_sgesvd)(jobu, jobvt, m, n, (T*)a, lda, (T*)s, (T*)u, ldu, (T*)vt, ldvt, (T*)work, lwork, info);
|
Chris@49
|
453 }
|
Chris@49
|
454 else
|
Chris@49
|
455 if(is_double<eT>::value == true)
|
Chris@49
|
456 {
|
Chris@49
|
457 typedef double T;
|
Chris@49
|
458 arma_fortran(arma_dgesvd)(jobu, jobvt, m, n, (T*)a, lda, (T*)s, (T*)u, ldu, (T*)vt, ldvt, (T*)work, lwork, info);
|
Chris@49
|
459 }
|
Chris@49
|
460 }
|
Chris@49
|
461
|
Chris@49
|
462
|
Chris@49
|
463
|
Chris@49
|
464 template<typename T>
|
Chris@49
|
465 inline
|
Chris@49
|
466 void
|
Chris@49
|
467 cx_gesvd
|
Chris@49
|
468 (
|
Chris@49
|
469 char* jobu, char* jobvt, blas_int* m, blas_int* n, std::complex<T>* a, blas_int* lda,
|
Chris@49
|
470 T* s, std::complex<T>* u, blas_int* ldu, std::complex<T>* vt, blas_int* ldvt,
|
Chris@49
|
471 std::complex<T>* work, blas_int* lwork, T* rwork, blas_int* info
|
Chris@49
|
472 )
|
Chris@49
|
473 {
|
Chris@49
|
474 arma_type_check(( is_supported_blas_type<T>::value == false ));
|
Chris@49
|
475 arma_type_check(( is_supported_blas_type< std::complex<T> >::value == false ));
|
Chris@49
|
476
|
Chris@49
|
477 if(is_float<T>::value == true)
|
Chris@49
|
478 {
|
Chris@49
|
479 typedef float bT;
|
Chris@49
|
480 arma_fortran(arma_cgesvd)
|
Chris@49
|
481 (
|
Chris@49
|
482 jobu, jobvt, m, n, (std::complex<bT>*)a, lda,
|
Chris@49
|
483 (bT*)s, (std::complex<bT>*)u, ldu, (std::complex<bT>*)vt, ldvt,
|
Chris@49
|
484 (std::complex<bT>*)work, lwork, (bT*)rwork, info
|
Chris@49
|
485 );
|
Chris@49
|
486 }
|
Chris@49
|
487 else
|
Chris@49
|
488 if(is_double<T>::value == true)
|
Chris@49
|
489 {
|
Chris@49
|
490 typedef double bT;
|
Chris@49
|
491 arma_fortran(arma_zgesvd)
|
Chris@49
|
492 (
|
Chris@49
|
493 jobu, jobvt, m, n, (std::complex<bT>*)a, lda,
|
Chris@49
|
494 (bT*)s, (std::complex<bT>*)u, ldu, (std::complex<bT>*)vt, ldvt,
|
Chris@49
|
495 (std::complex<bT>*)work, lwork, (bT*)rwork, info
|
Chris@49
|
496 );
|
Chris@49
|
497 }
|
Chris@49
|
498 }
|
Chris@49
|
499
|
Chris@49
|
500
|
Chris@49
|
501
|
Chris@49
|
502 template<typename eT>
|
Chris@49
|
503 inline
|
Chris@49
|
504 void
|
Chris@49
|
505 gesdd
|
Chris@49
|
506 (
|
Chris@49
|
507 char* jobz, blas_int* m, blas_int* n,
|
Chris@49
|
508 eT* a, blas_int* lda, eT* s, eT* u, blas_int* ldu, eT* vt, blas_int* ldvt,
|
Chris@49
|
509 eT* work, blas_int* lwork, blas_int* iwork, blas_int* info
|
Chris@49
|
510 )
|
Chris@49
|
511 {
|
Chris@49
|
512 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
513
|
Chris@49
|
514 if(is_float<eT>::value == true)
|
Chris@49
|
515 {
|
Chris@49
|
516 typedef float T;
|
Chris@49
|
517 arma_fortran(arma_sgesdd)(jobz, m, n, (T*)a, lda, (T*)s, (T*)u, ldu, (T*)vt, ldvt, (T*)work, lwork, iwork, info);
|
Chris@49
|
518 }
|
Chris@49
|
519 else
|
Chris@49
|
520 if(is_double<eT>::value == true)
|
Chris@49
|
521 {
|
Chris@49
|
522 typedef double T;
|
Chris@49
|
523 arma_fortran(arma_dgesdd)(jobz, m, n, (T*)a, lda, (T*)s, (T*)u, ldu, (T*)vt, ldvt, (T*)work, lwork, iwork, info);
|
Chris@49
|
524 }
|
Chris@49
|
525 }
|
Chris@49
|
526
|
Chris@49
|
527
|
Chris@49
|
528
|
Chris@49
|
529 template<typename T>
|
Chris@49
|
530 inline
|
Chris@49
|
531 void
|
Chris@49
|
532 cx_gesdd
|
Chris@49
|
533 (
|
Chris@49
|
534 char* jobz, blas_int* m, blas_int* n,
|
Chris@49
|
535 std::complex<T>* a, blas_int* lda, T* s, std::complex<T>* u, blas_int* ldu, std::complex<T>* vt, blas_int* ldvt,
|
Chris@49
|
536 std::complex<T>* work, blas_int* lwork, T* rwork, blas_int* iwork, blas_int* info
|
Chris@49
|
537 )
|
Chris@49
|
538 {
|
Chris@49
|
539 arma_type_check(( is_supported_blas_type<T>::value == false ));
|
Chris@49
|
540 arma_type_check(( is_supported_blas_type< std::complex<T> >::value == false ));
|
Chris@49
|
541
|
Chris@49
|
542 if(is_float<T>::value == true)
|
Chris@49
|
543 {
|
Chris@49
|
544 typedef float bT;
|
Chris@49
|
545 arma_fortran(arma_cgesdd)
|
Chris@49
|
546 (
|
Chris@49
|
547 jobz, m, n,
|
Chris@49
|
548 (std::complex<bT>*)a, lda, (bT*)s, (std::complex<bT>*)u, ldu, (std::complex<bT>*)vt, ldvt,
|
Chris@49
|
549 (std::complex<bT>*)work, lwork, (bT*)rwork, iwork, info
|
Chris@49
|
550 );
|
Chris@49
|
551 }
|
Chris@49
|
552 else
|
Chris@49
|
553 if(is_double<T>::value == true)
|
Chris@49
|
554 {
|
Chris@49
|
555 typedef double bT;
|
Chris@49
|
556 arma_fortran(arma_zgesdd)
|
Chris@49
|
557 (
|
Chris@49
|
558 jobz, m, n,
|
Chris@49
|
559 (std::complex<bT>*)a, lda, (bT*)s, (std::complex<bT>*)u, ldu, (std::complex<bT>*)vt, ldvt,
|
Chris@49
|
560 (std::complex<bT>*)work, lwork, (bT*)rwork, iwork, info
|
Chris@49
|
561 );
|
Chris@49
|
562 }
|
Chris@49
|
563 }
|
Chris@49
|
564
|
Chris@49
|
565
|
Chris@49
|
566
|
Chris@49
|
567 template<typename eT>
|
Chris@49
|
568 inline
|
Chris@49
|
569 void
|
Chris@49
|
570 gesv(blas_int* n, blas_int* nrhs, eT* a, blas_int* lda, blas_int* ipiv, eT* b, blas_int* ldb, blas_int* info)
|
Chris@49
|
571 {
|
Chris@49
|
572 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
573
|
Chris@49
|
574 if(is_float<eT>::value == true)
|
Chris@49
|
575 {
|
Chris@49
|
576 typedef float T;
|
Chris@49
|
577 arma_fortran(arma_sgesv)(n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info);
|
Chris@49
|
578 }
|
Chris@49
|
579 else
|
Chris@49
|
580 if(is_double<eT>::value == true)
|
Chris@49
|
581 {
|
Chris@49
|
582 typedef double T;
|
Chris@49
|
583 arma_fortran(arma_dgesv)(n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info);
|
Chris@49
|
584 }
|
Chris@49
|
585 else
|
Chris@49
|
586 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
587 {
|
Chris@49
|
588 typedef std::complex<float> T;
|
Chris@49
|
589 arma_fortran(arma_cgesv)(n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info);
|
Chris@49
|
590 }
|
Chris@49
|
591 else
|
Chris@49
|
592 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
593 {
|
Chris@49
|
594 typedef std::complex<double> T;
|
Chris@49
|
595 arma_fortran(arma_zgesv)(n, nrhs, (T*)a, lda, ipiv, (T*)b, ldb, info);
|
Chris@49
|
596 }
|
Chris@49
|
597 }
|
Chris@49
|
598
|
Chris@49
|
599
|
Chris@49
|
600
|
Chris@49
|
601 template<typename eT>
|
Chris@49
|
602 inline
|
Chris@49
|
603 void
|
Chris@49
|
604 gels(char* trans, blas_int* m, blas_int* n, blas_int* nrhs, eT* a, blas_int* lda, eT* b, blas_int* ldb, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
605 {
|
Chris@49
|
606 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
607
|
Chris@49
|
608 if(is_float<eT>::value == true)
|
Chris@49
|
609 {
|
Chris@49
|
610 typedef float T;
|
Chris@49
|
611 arma_fortran(arma_sgels)(trans, m, n, nrhs, (T*)a, lda, (T*)b, ldb, (T*)work, lwork, info);
|
Chris@49
|
612 }
|
Chris@49
|
613 else
|
Chris@49
|
614 if(is_double<eT>::value == true)
|
Chris@49
|
615 {
|
Chris@49
|
616 typedef double T;
|
Chris@49
|
617 arma_fortran(arma_dgels)(trans, m, n, nrhs, (T*)a, lda, (T*)b, ldb, (T*)work, lwork, info);
|
Chris@49
|
618 }
|
Chris@49
|
619 else
|
Chris@49
|
620 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
621 {
|
Chris@49
|
622 typedef std::complex<float> T;
|
Chris@49
|
623 arma_fortran(arma_cgels)(trans, m, n, nrhs, (T*)a, lda, (T*)b, ldb, (T*)work, lwork, info);
|
Chris@49
|
624 }
|
Chris@49
|
625 else
|
Chris@49
|
626 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
627 {
|
Chris@49
|
628 typedef std::complex<double> T;
|
Chris@49
|
629 arma_fortran(arma_zgels)(trans, m, n, nrhs, (T*)a, lda, (T*)b, ldb, (T*)work, lwork, info);
|
Chris@49
|
630 }
|
Chris@49
|
631 }
|
Chris@49
|
632
|
Chris@49
|
633
|
Chris@49
|
634
|
Chris@49
|
635 template<typename eT>
|
Chris@49
|
636 inline
|
Chris@49
|
637 void
|
Chris@49
|
638 trtrs(char* uplo, char* trans, char* diag, blas_int* n, blas_int* nrhs, const eT* a, blas_int* lda, eT* b, blas_int* ldb, blas_int* info)
|
Chris@49
|
639 {
|
Chris@49
|
640 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
641
|
Chris@49
|
642 if(is_float<eT>::value == true)
|
Chris@49
|
643 {
|
Chris@49
|
644 typedef float T;
|
Chris@49
|
645 arma_fortran(arma_strtrs)(uplo, trans, diag, n, nrhs, (T*)a, lda, (T*)b, ldb, info);
|
Chris@49
|
646 }
|
Chris@49
|
647 else
|
Chris@49
|
648 if(is_double<eT>::value == true)
|
Chris@49
|
649 {
|
Chris@49
|
650 typedef double T;
|
Chris@49
|
651 arma_fortran(arma_dtrtrs)(uplo, trans, diag, n, nrhs, (T*)a, lda, (T*)b, ldb, info);
|
Chris@49
|
652 }
|
Chris@49
|
653 else
|
Chris@49
|
654 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
655 {
|
Chris@49
|
656 typedef std::complex<float> T;
|
Chris@49
|
657 arma_fortran(arma_ctrtrs)(uplo, trans, diag, n, nrhs, (T*)a, lda, (T*)b, ldb, info);
|
Chris@49
|
658 }
|
Chris@49
|
659 else
|
Chris@49
|
660 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
661 {
|
Chris@49
|
662 typedef std::complex<double> T;
|
Chris@49
|
663 arma_fortran(arma_ztrtrs)(uplo, trans, diag, n, nrhs, (T*)a, lda, (T*)b, ldb, info);
|
Chris@49
|
664 }
|
Chris@49
|
665 }
|
Chris@49
|
666
|
Chris@49
|
667
|
Chris@49
|
668
|
Chris@49
|
669 template<typename eT>
|
Chris@49
|
670 inline
|
Chris@49
|
671 void
|
Chris@49
|
672 gees(char* jobvs, char* sort, blas_int* select, blas_int* n, eT* a, blas_int* lda, blas_int* sdim, eT* wr, eT* wi, eT* vs, blas_int* ldvs, eT* work, blas_int* lwork, blas_int* bwork, blas_int* info)
|
Chris@49
|
673 {
|
Chris@49
|
674 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
675
|
Chris@49
|
676 if(is_float<eT>::value == true)
|
Chris@49
|
677 {
|
Chris@49
|
678 typedef float T;
|
Chris@49
|
679 arma_fortran(arma_sgees)(jobvs, sort, select, n, (T*)a, lda, sdim, (T*)wr, (T*)wi, (T*)vs, ldvs, (T*)work, lwork, bwork, info);
|
Chris@49
|
680 }
|
Chris@49
|
681 else
|
Chris@49
|
682 if(is_double<eT>::value == true)
|
Chris@49
|
683 {
|
Chris@49
|
684 typedef double T;
|
Chris@49
|
685 arma_fortran(arma_dgees)(jobvs, sort, select, n, (T*)a, lda, sdim, (T*)wr, (T*)wi, (T*)vs, ldvs, (T*)work, lwork, bwork, info);
|
Chris@49
|
686 }
|
Chris@49
|
687 }
|
Chris@49
|
688
|
Chris@49
|
689
|
Chris@49
|
690
|
Chris@49
|
691 template<typename T>
|
Chris@49
|
692 inline
|
Chris@49
|
693 void
|
Chris@49
|
694 cx_gees(char* jobvs, char* sort, blas_int* select, blas_int* n, std::complex<T>* a, blas_int* lda, blas_int* sdim, std::complex<T>* w, std::complex<T>* vs, blas_int* ldvs, std::complex<T>* work, blas_int* lwork, T* rwork, blas_int* bwork, blas_int* info)
|
Chris@49
|
695 {
|
Chris@49
|
696 arma_type_check(( is_supported_blas_type<T>::value == false ));
|
Chris@49
|
697 arma_type_check(( is_supported_blas_type< std::complex<T> >::value == false ));
|
Chris@49
|
698
|
Chris@49
|
699 if(is_float<T>::value == true)
|
Chris@49
|
700 {
|
Chris@49
|
701 typedef float bT;
|
Chris@49
|
702 typedef std::complex<bT> cT;
|
Chris@49
|
703 arma_fortran(arma_cgees)(jobvs, sort, select, n, (cT*)a, lda, sdim, (cT*)w, (cT*)vs, ldvs, (cT*)work, lwork, (bT*)rwork, bwork, info);
|
Chris@49
|
704 }
|
Chris@49
|
705 else
|
Chris@49
|
706 if(is_double<T>::value == true)
|
Chris@49
|
707 {
|
Chris@49
|
708 typedef double bT;
|
Chris@49
|
709 typedef std::complex<bT> cT;
|
Chris@49
|
710 arma_fortran(arma_zgees)(jobvs, sort, select, n, (cT*)a, lda, sdim, (cT*)w, (cT*)vs, ldvs, (cT*)work, lwork, (bT*)rwork, bwork, info);
|
Chris@49
|
711 }
|
Chris@49
|
712 }
|
Chris@49
|
713
|
Chris@49
|
714
|
Chris@49
|
715
|
Chris@49
|
716 template<typename eT>
|
Chris@49
|
717 inline
|
Chris@49
|
718 void
|
Chris@49
|
719 trsyl(char* transa, char* transb, blas_int* isgn, blas_int* m, blas_int* n, const eT* a, blas_int* lda, const eT* b, blas_int* ldb, eT* c, blas_int* ldc, eT* scale, blas_int* info)
|
Chris@49
|
720 {
|
Chris@49
|
721 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
722
|
Chris@49
|
723 if(is_float<eT>::value == true)
|
Chris@49
|
724 {
|
Chris@49
|
725 typedef float T;
|
Chris@49
|
726 arma_fortran(arma_strsyl)(transa, transb, isgn, m, n, (T*)a, lda, (T*)b, ldb, (T*)c, ldc, (T*)scale, info);
|
Chris@49
|
727 }
|
Chris@49
|
728 else
|
Chris@49
|
729 if(is_double<eT>::value == true)
|
Chris@49
|
730 {
|
Chris@49
|
731 typedef double T;
|
Chris@49
|
732 arma_fortran(arma_dtrsyl)(transa, transb, isgn, m, n, (T*)a, lda, (T*)b, ldb, (T*)c, ldc, (T*)scale, info);
|
Chris@49
|
733 }
|
Chris@49
|
734 else
|
Chris@49
|
735 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
736 {
|
Chris@49
|
737 typedef std::complex<float> T;
|
Chris@49
|
738 arma_fortran(arma_ctrsyl)(transa, transb, isgn, m, n, (T*)a, lda, (T*)b, ldb, (T*)c, ldc, (float*)scale, info);
|
Chris@49
|
739 }
|
Chris@49
|
740 else
|
Chris@49
|
741 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
742 {
|
Chris@49
|
743 typedef std::complex<double> T;
|
Chris@49
|
744 arma_fortran(arma_ztrsyl)(transa, transb, isgn, m, n, (T*)a, lda, (T*)b, ldb, (T*)c, ldc, (double*)scale, info);
|
Chris@49
|
745 }
|
Chris@49
|
746 }
|
Chris@49
|
747
|
Chris@49
|
748
|
Chris@49
|
749 template<typename eT>
|
Chris@49
|
750 inline
|
Chris@49
|
751 void
|
Chris@49
|
752 sytrf(char* uplo, blas_int* n, eT* a, blas_int* lda, blas_int* ipiv, eT* work, blas_int* lwork, blas_int* info)
|
Chris@49
|
753 {
|
Chris@49
|
754 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
755
|
Chris@49
|
756 if(is_float<eT>::value == true)
|
Chris@49
|
757 {
|
Chris@49
|
758 typedef float T;
|
Chris@49
|
759 arma_fortran(arma_ssytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
760 }
|
Chris@49
|
761 else
|
Chris@49
|
762 if(is_double<eT>::value == true)
|
Chris@49
|
763 {
|
Chris@49
|
764 typedef double T;
|
Chris@49
|
765 arma_fortran(arma_dsytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
766 }
|
Chris@49
|
767 else
|
Chris@49
|
768 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
769 {
|
Chris@49
|
770 typedef std::complex<float> T;
|
Chris@49
|
771 arma_fortran(arma_csytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
772 }
|
Chris@49
|
773 else
|
Chris@49
|
774 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
775 {
|
Chris@49
|
776 typedef std::complex<double> T;
|
Chris@49
|
777 arma_fortran(arma_zsytrf)(uplo, n, (T*)a, lda, ipiv, (T*)work, lwork, info);
|
Chris@49
|
778 }
|
Chris@49
|
779 }
|
Chris@49
|
780
|
Chris@49
|
781
|
Chris@49
|
782 template<typename eT>
|
Chris@49
|
783 inline
|
Chris@49
|
784 void
|
Chris@49
|
785 sytri(char* uplo, blas_int* n, eT* a, blas_int* lda, blas_int* ipiv, eT* work, blas_int* info)
|
Chris@49
|
786 {
|
Chris@49
|
787 arma_type_check(( is_supported_blas_type<eT>::value == false ));
|
Chris@49
|
788
|
Chris@49
|
789 if(is_float<eT>::value == true)
|
Chris@49
|
790 {
|
Chris@49
|
791 typedef float T;
|
Chris@49
|
792 arma_fortran(arma_ssytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info);
|
Chris@49
|
793 }
|
Chris@49
|
794 else
|
Chris@49
|
795 if(is_double<eT>::value == true)
|
Chris@49
|
796 {
|
Chris@49
|
797 typedef double T;
|
Chris@49
|
798 arma_fortran(arma_dsytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info);
|
Chris@49
|
799 }
|
Chris@49
|
800 else
|
Chris@49
|
801 if(is_supported_complex_float<eT>::value == true)
|
Chris@49
|
802 {
|
Chris@49
|
803 typedef std::complex<float> T;
|
Chris@49
|
804 arma_fortran(arma_csytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info);
|
Chris@49
|
805 }
|
Chris@49
|
806 else
|
Chris@49
|
807 if(is_supported_complex_double<eT>::value == true)
|
Chris@49
|
808 {
|
Chris@49
|
809 typedef std::complex<double> T;
|
Chris@49
|
810 arma_fortran(arma_zsytri)(uplo, n, (T*)a, lda, ipiv, (T*)work, info);
|
Chris@49
|
811 }
|
Chris@49
|
812 }
|
Chris@49
|
813
|
Chris@49
|
814
|
Chris@49
|
815 }
|
Chris@49
|
816
|
Chris@49
|
817
|
Chris@49
|
818 #endif
|