diff options
Diffstat (limited to 'lib/LAPACK/lapack-aux.c')
-rw-r--r-- | lib/LAPACK/lapack-aux.c | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/lib/LAPACK/lapack-aux.c b/lib/LAPACK/lapack-aux.c new file mode 100644 index 0000000..3e8c015 --- /dev/null +++ b/lib/LAPACK/lapack-aux.c | |||
@@ -0,0 +1,579 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include <math.h> | ||
5 | #include <time.h> | ||
6 | #include "lapack-aux.h" | ||
7 | |||
8 | #define MACRO(B) do {B} while (0) | ||
9 | #define ERROR(CODE) MACRO(return CODE;) | ||
10 | #define REQUIRES(COND, CODE) MACRO(if(!(COND)) {ERROR(CODE);}) | ||
11 | |||
12 | #define MIN(A,B) ((A)<(B)?(A):(B)) | ||
13 | #define MAX(A,B) ((A)>(B)?(A):(B)) | ||
14 | |||
15 | #ifdef DBGL | ||
16 | #define DEBUGMSG(M) printf("LAPACK Wrapper "M"\n: "); size_t t0 = time(NULL); | ||
17 | #define OK MACRO(printf("%ld s\n",time(0)-t0); return 0;); | ||
18 | #else | ||
19 | #define DEBUGMSG(M) | ||
20 | #define OK return 0; | ||
21 | #endif | ||
22 | |||
23 | #define CHECK(RES,CODE) MACRO(if(RES) return CODE;) | ||
24 | |||
25 | #define BAD_SIZE 1000 | ||
26 | #define BAD_CODE 1001 | ||
27 | #define MEM 1002 | ||
28 | #define BAD_FILE 1003 | ||
29 | #define SINGULAR 1004 | ||
30 | #define NOCONVER 1005 | ||
31 | |||
32 | //////////////////// real svd //////////////////////////////////// | ||
33 | |||
34 | int svd_l_R(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | ||
35 | integer m = ar; | ||
36 | integer n = ac; | ||
37 | integer q = MIN(m,n); | ||
38 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | ||
39 | DEBUGMSG("svd_l_R"); | ||
40 | double *B = (double*)malloc(m*n*sizeof(double)); | ||
41 | CHECK(!B,MEM); | ||
42 | memcpy(B,ap,m*n*sizeof(double)); | ||
43 | integer lwork = -1; | ||
44 | integer res; | ||
45 | // ask for optimal lwork | ||
46 | double ans; | ||
47 | //printf("ask zgesvd\n"); | ||
48 | char* job = "A"; | ||
49 | dgesvd_ (job,job, | ||
50 | &m,&n,B,&m, | ||
51 | sp, | ||
52 | up,&m, | ||
53 | vp,&n, | ||
54 | &ans, &lwork, | ||
55 | &res); | ||
56 | lwork = ceil(ans); | ||
57 | //printf("ans = %d\n",lwork); | ||
58 | double * work = (double*)malloc(lwork*sizeof(double)); | ||
59 | CHECK(!work,MEM); | ||
60 | //printf("dgesdd\n"); | ||
61 | dgesvd_ (job,job, | ||
62 | &m,&n,B,&m, | ||
63 | sp, | ||
64 | up,&m, | ||
65 | vp,&n, | ||
66 | work, &lwork, | ||
67 | &res); | ||
68 | CHECK(res,res); | ||
69 | free(work); | ||
70 | free(B); | ||
71 | OK | ||
72 | } | ||
73 | |||
74 | // (alternative version) | ||
75 | |||
76 | int svd_l_Rdd(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | ||
77 | integer m = ar; | ||
78 | integer n = ac; | ||
79 | integer q = MIN(m,n); | ||
80 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | ||
81 | DEBUGMSG("svd_l_Rdd"); | ||
82 | double *B = (double*)malloc(m*n*sizeof(double)); | ||
83 | CHECK(!B,MEM); | ||
84 | memcpy(B,ap,m*n*sizeof(double)); | ||
85 | integer* iwk = (integer*) malloc(8*q*sizeof(int)); | ||
86 | CHECK(!iwk,MEM); | ||
87 | integer lwk = -1; | ||
88 | integer res; | ||
89 | // ask for optimal lwk | ||
90 | double ans; | ||
91 | //printf("ask dgesdd\n"); | ||
92 | dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,&ans,&lwk,iwk,&res); | ||
93 | lwk = 2*ceil(ans); // ????? otherwise 50x100 rejects lwk | ||
94 | //printf("lwk = %d\n",lwk); | ||
95 | double * workv = (double*)malloc(lwk*sizeof(double)); | ||
96 | CHECK(!workv,MEM); | ||
97 | //printf("dgesdd\n"); | ||
98 | dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,workv,&lwk,iwk,&res); | ||
99 | CHECK(res,res); | ||
100 | free(iwk); | ||
101 | free(workv); | ||
102 | free(B); | ||
103 | OK | ||
104 | } | ||
105 | |||
106 | //////////////////// complex svd //////////////////////////////////// | ||
107 | |||
108 | // not in clapack.h | ||
109 | |||
110 | int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n, | ||
111 | doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, | ||
112 | integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, | ||
113 | integer *lwork, doublereal *rwork, integer *info); | ||
114 | |||
115 | int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { | ||
116 | integer m = ar; | ||
117 | integer n = ac; | ||
118 | integer q = MIN(m,n); | ||
119 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | ||
120 | DEBUGMSG("svd_l_C"); | ||
121 | double *B = (double*)malloc(2*m*n*sizeof(double)); | ||
122 | CHECK(!B,MEM); | ||
123 | memcpy(B,ap,m*n*2*sizeof(double)); | ||
124 | |||
125 | double *rwork = (double*) malloc(5*q*sizeof(double)); | ||
126 | CHECK(!rwork,MEM); | ||
127 | integer lwork = -1; | ||
128 | integer res; | ||
129 | // ask for optimal lwork | ||
130 | doublecomplex ans; | ||
131 | //printf("ask zgesvd\n"); | ||
132 | char* job = "A"; | ||
133 | zgesvd_ (job,job, | ||
134 | &m,&n,(doublecomplex*)B,&m, | ||
135 | sp, | ||
136 | (doublecomplex*)up,&m, | ||
137 | (doublecomplex*)vp,&n, | ||
138 | &ans, &lwork, | ||
139 | rwork, | ||
140 | &res); | ||
141 | lwork = ceil(ans.r); | ||
142 | //printf("ans = %d\n",lwork); | ||
143 | doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double)); | ||
144 | CHECK(!work,MEM); | ||
145 | //printf("zgesvd\n"); | ||
146 | zgesvd_ (job,job, | ||
147 | &m,&n,(doublecomplex*)B,&m, | ||
148 | sp, | ||
149 | (doublecomplex*)up,&m, | ||
150 | (doublecomplex*)vp,&n, | ||
151 | work, &lwork, | ||
152 | rwork, | ||
153 | &res); | ||
154 | CHECK(res,res); | ||
155 | free(work); | ||
156 | free(rwork); | ||
157 | free(B); | ||
158 | OK | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | //////////////////// general complex eigensystem //////////// | ||
164 | |||
165 | int eig_l_C(KCMAT(a),CMAT(u), CVEC(s),CMAT(v)) { | ||
166 | integer n = ar; | ||
167 | REQUIRES(n>=2 && (ur==1 || (ur==n && uc==n)) && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE); | ||
168 | DEBUGMSG("eig_l_C"); | ||
169 | double *B = (double*)malloc(2*n*n*sizeof(double)); | ||
170 | CHECK(!B,MEM); | ||
171 | memcpy(B,ap,n*n*2*sizeof(double)); | ||
172 | |||
173 | double *rwork = (double*) malloc(2*n*sizeof(double)); | ||
174 | CHECK(!rwork,MEM); | ||
175 | integer lwork = -1; | ||
176 | char jobvl = ur==1?'N':'V'; | ||
177 | char jobvr = vr==1?'N':'V'; | ||
178 | integer res; | ||
179 | // ask for optimal lwork | ||
180 | doublecomplex ans; | ||
181 | //printf("ask zgeev\n"); | ||
182 | zgeev_ (&jobvl,&jobvr, | ||
183 | &n,(doublecomplex*)B,&n, | ||
184 | (doublecomplex*)sp, | ||
185 | (doublecomplex*)up,&n, | ||
186 | (doublecomplex*)vp,&n, | ||
187 | &ans, &lwork, | ||
188 | rwork, | ||
189 | &res); | ||
190 | lwork = ceil(ans.r); | ||
191 | //printf("ans = %d\n",lwork); | ||
192 | doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double)); | ||
193 | CHECK(!work,MEM); | ||
194 | //printf("zgeev\n"); | ||
195 | zgeev_ (&jobvl,&jobvr, | ||
196 | &n,(doublecomplex*)B,&n, | ||
197 | (doublecomplex*)sp, | ||
198 | (doublecomplex*)up,&n, | ||
199 | (doublecomplex*)vp,&n, | ||
200 | work, &lwork, | ||
201 | rwork, | ||
202 | &res); | ||
203 | CHECK(res,res); | ||
204 | free(work); | ||
205 | free(rwork); | ||
206 | free(B); | ||
207 | OK | ||
208 | } | ||
209 | |||
210 | |||
211 | |||
212 | //////////////////// general real eigensystem //////////// | ||
213 | |||
214 | int eig_l_R(KDMAT(a),DMAT(u), CVEC(s),DMAT(v)) { | ||
215 | integer n = ar; | ||
216 | REQUIRES(n>=2 && (ur==1 || (ur==n && uc==n)) && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE); | ||
217 | DEBUGMSG("eig_l_R"); | ||
218 | double *B = (double*)malloc(n*n*sizeof(double)); | ||
219 | CHECK(!B,MEM); | ||
220 | memcpy(B,ap,n*n*sizeof(double)); | ||
221 | integer lwork = -1; | ||
222 | char jobvl = ur==1?'N':'V'; | ||
223 | char jobvr = vr==1?'N':'V'; | ||
224 | integer res; | ||
225 | // ask for optimal lwork | ||
226 | double ans; | ||
227 | //printf("ask dgeev\n"); | ||
228 | dgeev_ (&jobvl,&jobvr, | ||
229 | &n,B,&n, | ||
230 | sp, sp+n, | ||
231 | up,&n, | ||
232 | vp,&n, | ||
233 | &ans, &lwork, | ||
234 | &res); | ||
235 | lwork = ceil(ans); | ||
236 | //printf("ans = %d\n",lwork); | ||
237 | double * work = (double*)malloc(lwork*sizeof(double)); | ||
238 | CHECK(!work,MEM); | ||
239 | //printf("dgeev\n"); | ||
240 | dgeev_ (&jobvl,&jobvr, | ||
241 | &n,B,&n, | ||
242 | sp, sp+n, | ||
243 | up,&n, | ||
244 | vp,&n, | ||
245 | work, &lwork, | ||
246 | &res); | ||
247 | CHECK(res,res); | ||
248 | free(work); | ||
249 | free(B); | ||
250 | OK | ||
251 | } | ||
252 | |||
253 | |||
254 | //////////////////// symmetric real eigensystem //////////// | ||
255 | |||
256 | |||
257 | int eig_l_S(KDMAT(a),DVEC(s),DMAT(v)) { | ||
258 | integer n = ar; | ||
259 | REQUIRES(n>=2 && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE); | ||
260 | DEBUGMSG("eig_l_S"); | ||
261 | memcpy(vp,ap,n*n*sizeof(double)); | ||
262 | integer lwork = -1; | ||
263 | char jobz = vr==1?'N':'V'; | ||
264 | char uplo = 'U'; | ||
265 | integer res; | ||
266 | // ask for optimal lwork | ||
267 | double ans; | ||
268 | //printf("ask dsyev\n"); | ||
269 | dsyev_ (&jobz,&uplo, | ||
270 | &n,vp,&n, | ||
271 | sp, | ||
272 | &ans, &lwork, | ||
273 | &res); | ||
274 | lwork = ceil(ans); | ||
275 | //printf("ans = %d\n",lwork); | ||
276 | double * work = (double*)malloc(lwork*sizeof(double)); | ||
277 | CHECK(!work,MEM); | ||
278 | dsyev_ (&jobz,&uplo, | ||
279 | &n,vp,&n, | ||
280 | sp, | ||
281 | work, &lwork, | ||
282 | &res); | ||
283 | CHECK(res,res); | ||
284 | free(work); | ||
285 | OK | ||
286 | } | ||
287 | |||
288 | //////////////////// hermitian complex eigensystem //////////// | ||
289 | |||
290 | int eig_l_H(KCMAT(a),DVEC(s),CMAT(v)) { | ||
291 | integer n = ar; | ||
292 | REQUIRES(n>=2 && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE); | ||
293 | DEBUGMSG("eig_l_H"); | ||
294 | memcpy(vp,ap,2*n*n*sizeof(double)); | ||
295 | double *rwork = (double*) malloc((3*n-2)*sizeof(double)); | ||
296 | CHECK(!rwork,MEM); | ||
297 | integer lwork = -1; | ||
298 | char jobz = vr==1?'N':'V'; | ||
299 | char uplo = 'U'; | ||
300 | integer res; | ||
301 | // ask for optimal lwork | ||
302 | doublecomplex ans; | ||
303 | //printf("ask zheev\n"); | ||
304 | zheev_ (&jobz,&uplo, | ||
305 | &n,(doublecomplex*)vp,&n, | ||
306 | sp, | ||
307 | &ans, &lwork, | ||
308 | rwork, | ||
309 | &res); | ||
310 | lwork = ceil(ans.r); | ||
311 | //printf("ans = %d\n",lwork); | ||
312 | doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double)); | ||
313 | CHECK(!work,MEM); | ||
314 | zheev_ (&jobz,&uplo, | ||
315 | &n,(doublecomplex*)vp,&n, | ||
316 | sp, | ||
317 | work, &lwork, | ||
318 | rwork, | ||
319 | &res); | ||
320 | CHECK(res,res); | ||
321 | free(work); | ||
322 | free(rwork); | ||
323 | OK | ||
324 | } | ||
325 | |||
326 | //////////////////// general real linear system //////////// | ||
327 | |||
328 | int linearSolveR_l(KDMAT(a),KDMAT(b),DMAT(x)) { | ||
329 | integer n = ar; | ||
330 | integer nhrs = bc; | ||
331 | REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE); | ||
332 | DEBUGMSG("linearSolveR_l"); | ||
333 | double*AC = (double*)malloc(n*n*sizeof(double)); | ||
334 | memcpy(AC,ap,n*n*sizeof(double)); | ||
335 | memcpy(xp,bp,n*nhrs*sizeof(double)); | ||
336 | integer * ipiv = (integer*)malloc(n*sizeof(integer)); | ||
337 | integer res; | ||
338 | dgesv_ (&n,&nhrs, | ||
339 | AC, &n, | ||
340 | ipiv, | ||
341 | xp, &n, | ||
342 | &res); | ||
343 | if(res>0) { | ||
344 | return SINGULAR; | ||
345 | } | ||
346 | CHECK(res,res); | ||
347 | free(ipiv); | ||
348 | free(AC); | ||
349 | OK | ||
350 | } | ||
351 | |||
352 | //////////////////// general complex linear system //////////// | ||
353 | |||
354 | int linearSolveC_l(KCMAT(a),KCMAT(b),CMAT(x)) { | ||
355 | integer n = ar; | ||
356 | integer nhrs = bc; | ||
357 | REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE); | ||
358 | DEBUGMSG("linearSolveC_l"); | ||
359 | double*AC = (double*)malloc(2*n*n*sizeof(double)); | ||
360 | memcpy(AC,ap,2*n*n*sizeof(double)); | ||
361 | memcpy(xp,bp,2*n*nhrs*sizeof(double)); | ||
362 | integer * ipiv = (integer*)malloc(n*sizeof(integer)); | ||
363 | integer res; | ||
364 | zgesv_ (&n,&nhrs, | ||
365 | (doublecomplex*)AC, &n, | ||
366 | ipiv, | ||
367 | (doublecomplex*)xp, &n, | ||
368 | &res); | ||
369 | if(res>0) { | ||
370 | return SINGULAR; | ||
371 | } | ||
372 | CHECK(res,res); | ||
373 | free(ipiv); | ||
374 | free(AC); | ||
375 | OK | ||
376 | } | ||
377 | |||
378 | //////////////////// least squares real linear system //////////// | ||
379 | |||
380 | int linearSolveLSR_l(KDMAT(a),KDMAT(b),DMAT(x)) { | ||
381 | integer m = ar; | ||
382 | integer n = ac; | ||
383 | integer nrhs = bc; | ||
384 | integer ldb = xr; | ||
385 | REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE); | ||
386 | DEBUGMSG("linearSolveLSR_l"); | ||
387 | double*AC = (double*)malloc(m*n*sizeof(double)); | ||
388 | memcpy(AC,ap,m*n*sizeof(double)); | ||
389 | if (m>=n) { | ||
390 | memcpy(xp,bp,m*nrhs*sizeof(double)); | ||
391 | } else { | ||
392 | int k; | ||
393 | for(k = 0; k<nrhs; k++) { | ||
394 | memcpy(xp+ldb*k,bp+m*k,m*sizeof(double)); | ||
395 | } | ||
396 | } | ||
397 | integer res; | ||
398 | integer lwork = -1; | ||
399 | double ans; | ||
400 | dgels_ ("N",&m,&n,&nrhs, | ||
401 | AC,&m, | ||
402 | xp,&ldb, | ||
403 | &ans,&lwork, | ||
404 | &res); | ||
405 | lwork = ceil(ans); | ||
406 | //printf("ans = %d\n",lwork); | ||
407 | double * work = (double*)malloc(lwork*sizeof(double)); | ||
408 | dgels_ ("N",&m,&n,&nrhs, | ||
409 | AC,&m, | ||
410 | xp,&ldb, | ||
411 | work,&lwork, | ||
412 | &res); | ||
413 | if(res>0) { | ||
414 | return SINGULAR; | ||
415 | } | ||
416 | CHECK(res,res); | ||
417 | free(work); | ||
418 | free(AC); | ||
419 | OK | ||
420 | } | ||
421 | |||
422 | //////////////////// least squares complex linear system //////////// | ||
423 | |||
424 | int linearSolveLSC_l(KCMAT(a),KCMAT(b),CMAT(x)) { | ||
425 | integer m = ar; | ||
426 | integer n = ac; | ||
427 | integer nrhs = bc; | ||
428 | integer ldb = xr; | ||
429 | REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE); | ||
430 | DEBUGMSG("linearSolveLSC_l"); | ||
431 | double*AC = (double*)malloc(2*m*n*sizeof(double)); | ||
432 | memcpy(AC,ap,2*m*n*sizeof(double)); | ||
433 | memcpy(AC,ap,2*m*n*sizeof(double)); | ||
434 | if (m>=n) { | ||
435 | memcpy(xp,bp,2*m*nrhs*sizeof(double)); | ||
436 | } else { | ||
437 | int k; | ||
438 | for(k = 0; k<nrhs; k++) { | ||
439 | memcpy(xp+2*ldb*k,bp+2*m*k,m*2*sizeof(double)); | ||
440 | } | ||
441 | } | ||
442 | integer res; | ||
443 | integer lwork = -1; | ||
444 | doublecomplex ans; | ||
445 | zgels_ ("N",&m,&n,&nrhs, | ||
446 | (doublecomplex*)AC,&m, | ||
447 | (doublecomplex*)xp,&ldb, | ||
448 | &ans,&lwork, | ||
449 | &res); | ||
450 | lwork = ceil(ans.r); | ||
451 | //printf("ans = %d\n",lwork); | ||
452 | doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex)); | ||
453 | zgels_ ("N",&m,&n,&nrhs, | ||
454 | (doublecomplex*)AC,&m, | ||
455 | (doublecomplex*)xp,&ldb, | ||
456 | work,&lwork, | ||
457 | &res); | ||
458 | if(res>0) { | ||
459 | return SINGULAR; | ||
460 | } | ||
461 | CHECK(res,res); | ||
462 | free(work); | ||
463 | free(AC); | ||
464 | OK | ||
465 | } | ||
466 | |||
467 | //////////////////// least squares real linear system using SVD //////////// | ||
468 | |||
469 | int linearSolveSVDR_l(double rcond,KDMAT(a),KDMAT(b),DMAT(x)) { | ||
470 | integer m = ar; | ||
471 | integer n = ac; | ||
472 | integer nrhs = bc; | ||
473 | integer ldb = xr; | ||
474 | REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE); | ||
475 | DEBUGMSG("linearSolveSVDR_l"); | ||
476 | double*AC = (double*)malloc(m*n*sizeof(double)); | ||
477 | double*S = (double*)malloc(MIN(m,n)*sizeof(double)); | ||
478 | memcpy(AC,ap,m*n*sizeof(double)); | ||
479 | if (m>=n) { | ||
480 | memcpy(xp,bp,m*nrhs*sizeof(double)); | ||
481 | } else { | ||
482 | int k; | ||
483 | for(k = 0; k<nrhs; k++) { | ||
484 | memcpy(xp+ldb*k,bp+m*k,m*sizeof(double)); | ||
485 | } | ||
486 | } | ||
487 | integer res; | ||
488 | integer lwork = -1; | ||
489 | integer rank; | ||
490 | double ans; | ||
491 | dgelss_ (&m,&n,&nrhs, | ||
492 | AC,&m, | ||
493 | xp,&ldb, | ||
494 | S, | ||
495 | &rcond,&rank, | ||
496 | &ans,&lwork, | ||
497 | &res); | ||
498 | lwork = ceil(ans); | ||
499 | //printf("ans = %d\n",lwork); | ||
500 | double * work = (double*)malloc(lwork*sizeof(double)); | ||
501 | dgelss_ (&m,&n,&nrhs, | ||
502 | AC,&m, | ||
503 | xp,&ldb, | ||
504 | S, | ||
505 | &rcond,&rank, | ||
506 | work,&lwork, | ||
507 | &res); | ||
508 | if(res>0) { | ||
509 | return NOCONVER; | ||
510 | } | ||
511 | CHECK(res,res); | ||
512 | free(work); | ||
513 | free(S); | ||
514 | free(AC); | ||
515 | OK | ||
516 | } | ||
517 | |||
518 | //////////////////// least squares complex linear system using SVD //////////// | ||
519 | |||
520 | // not in clapack.h | ||
521 | |||
522 | int zgelss_(integer *m, integer *n, integer *nhrs, | ||
523 | doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, doublereal *s, | ||
524 | doublereal *rcond, integer* rank, | ||
525 | doublecomplex *work, integer* lwork, doublereal* rwork, | ||
526 | integer *info); | ||
527 | |||
528 | int linearSolveSVDC_l(double rcond, KCMAT(a),KCMAT(b),CMAT(x)) { | ||
529 | integer m = ar; | ||
530 | integer n = ac; | ||
531 | integer nrhs = bc; | ||
532 | integer ldb = xr; | ||
533 | REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE); | ||
534 | DEBUGMSG("linearSolveSVDC_l"); | ||
535 | double*AC = (double*)malloc(2*m*n*sizeof(double)); | ||
536 | double*S = (double*)malloc(MIN(m,n)*sizeof(double)); | ||
537 | double*RWORK = (double*)malloc(5*MIN(m,n)*sizeof(double)); | ||
538 | memcpy(AC,ap,2*m*n*sizeof(double)); | ||
539 | if (m>=n) { | ||
540 | memcpy(xp,bp,2*m*nrhs*sizeof(double)); | ||
541 | } else { | ||
542 | int k; | ||
543 | for(k = 0; k<nrhs; k++) { | ||
544 | memcpy(xp+2*ldb*k,bp+2*m*k,m*2*sizeof(double)); | ||
545 | } | ||
546 | } | ||
547 | integer res; | ||
548 | integer lwork = -1; | ||
549 | integer rank; | ||
550 | doublecomplex ans; | ||
551 | zgelss_ (&m,&n,&nrhs, | ||
552 | (doublecomplex*)AC,&m, | ||
553 | (doublecomplex*)xp,&ldb, | ||
554 | S, | ||
555 | &rcond,&rank, | ||
556 | &ans,&lwork, | ||
557 | RWORK, | ||
558 | &res); | ||
559 | lwork = ceil(ans.r); | ||
560 | //printf("ans = %d\n",lwork); | ||
561 | doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex)); | ||
562 | zgelss_ (&m,&n,&nrhs, | ||
563 | (doublecomplex*)AC,&m, | ||
564 | (doublecomplex*)xp,&ldb, | ||
565 | S, | ||
566 | &rcond,&rank, | ||
567 | work,&lwork, | ||
568 | RWORK, | ||
569 | &res); | ||
570 | if(res>0) { | ||
571 | return NOCONVER; | ||
572 | } | ||
573 | CHECK(res,res); | ||
574 | free(work); | ||
575 | free(RWORK); | ||
576 | free(S); | ||
577 | free(AC); | ||
578 | OK | ||
579 | } | ||