diff options
author | Alberto Ruiz <aruiz@um.es> | 2009-12-28 15:47:26 +0000 |
---|---|---|
committer | Alberto Ruiz <aruiz@um.es> | 2009-12-28 15:47:26 +0000 |
commit | b2715e91d7aef5cee1b64b641b8f173167a7145a (patch) | |
tree | f97b82cfa435441f52153ccdfad5e1fa119f14dc /lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c | |
parent | 107478b2288b0904159599be94089230c7cd3edf (diff) |
additional svd functions
Diffstat (limited to 'lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c')
-rw-r--r-- | lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c | 159 |
1 files changed, 129 insertions, 30 deletions
diff --git a/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c b/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c index f18bbed..db94cc6 100644 --- a/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c +++ b/lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.c | |||
@@ -48,7 +48,27 @@ int svd_l_R(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | |||
48 | integer m = ar; | 48 | integer m = ar; |
49 | integer n = ac; | 49 | integer n = ac; |
50 | integer q = MIN(m,n); | 50 | integer q = MIN(m,n); |
51 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | 51 | REQUIRES(sn==q,BAD_SIZE); |
52 | REQUIRES(up==NULL || ur==m && (uc==m || uc==q),BAD_SIZE); | ||
53 | char* jobu = "A"; | ||
54 | if (up==NULL) { | ||
55 | jobu = "N"; | ||
56 | } else { | ||
57 | if (uc==q) { | ||
58 | jobu = "S"; | ||
59 | } | ||
60 | } | ||
61 | REQUIRES(vp==NULL || vc==n && (vr==n || vr==q),BAD_SIZE); | ||
62 | char* jobvt = "A"; | ||
63 | integer ldvt = n; | ||
64 | if (vp==NULL) { | ||
65 | jobvt = "N"; | ||
66 | } else { | ||
67 | if (vr==q) { | ||
68 | jobvt = "S"; | ||
69 | ldvt = q; | ||
70 | } | ||
71 | } | ||
52 | DEBUGMSG("svd_l_R"); | 72 | DEBUGMSG("svd_l_R"); |
53 | double *B = (double*)malloc(m*n*sizeof(double)); | 73 | double *B = (double*)malloc(m*n*sizeof(double)); |
54 | CHECK(!B,MEM); | 74 | CHECK(!B,MEM); |
@@ -57,25 +77,21 @@ int svd_l_R(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | |||
57 | integer res; | 77 | integer res; |
58 | // ask for optimal lwork | 78 | // ask for optimal lwork |
59 | double ans; | 79 | double ans; |
60 | //printf("ask zgesvd\n"); | 80 | dgesvd_ (jobu,jobvt, |
61 | char* job = "A"; | ||
62 | dgesvd_ (job,job, | ||
63 | &m,&n,B,&m, | 81 | &m,&n,B,&m, |
64 | sp, | 82 | sp, |
65 | up,&m, | 83 | up,&m, |
66 | vp,&n, | 84 | vp,&ldvt, |
67 | &ans, &lwork, | 85 | &ans, &lwork, |
68 | &res); | 86 | &res); |
69 | lwork = ceil(ans); | 87 | lwork = ceil(ans); |
70 | //printf("ans = %d\n",lwork); | ||
71 | double * work = (double*)malloc(lwork*sizeof(double)); | 88 | double * work = (double*)malloc(lwork*sizeof(double)); |
72 | CHECK(!work,MEM); | 89 | CHECK(!work,MEM); |
73 | //printf("dgesdd\n"); | 90 | dgesvd_ (jobu,jobvt, |
74 | dgesvd_ (job,job, | ||
75 | &m,&n,B,&m, | 91 | &m,&n,B,&m, |
76 | sp, | 92 | sp, |
77 | up,&m, | 93 | up,&m, |
78 | vp,&n, | 94 | vp,&ldvt, |
79 | work, &lwork, | 95 | work, &lwork, |
80 | &res); | 96 | &res); |
81 | CHECK(res,res); | 97 | CHECK(res,res); |
@@ -90,25 +106,36 @@ int svd_l_Rdd(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | |||
90 | integer m = ar; | 106 | integer m = ar; |
91 | integer n = ac; | 107 | integer n = ac; |
92 | integer q = MIN(m,n); | 108 | integer q = MIN(m,n); |
93 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | 109 | REQUIRES(sn==q,BAD_SIZE); |
110 | REQUIRES(up == NULL && vp == NULL | ||
111 | || ur==m && vc==n | ||
112 | && (uc == q && vr == q | ||
113 | || uc == m && vc==n),BAD_SIZE); | ||
114 | char* jobz = "A"; | ||
115 | integer ldvt = n; | ||
116 | if (up==NULL) { | ||
117 | jobz = "N"; | ||
118 | } else { | ||
119 | if (uc==q && vr == q) { | ||
120 | jobz = "S"; | ||
121 | ldvt = q; | ||
122 | } | ||
123 | } | ||
94 | DEBUGMSG("svd_l_Rdd"); | 124 | DEBUGMSG("svd_l_Rdd"); |
95 | double *B = (double*)malloc(m*n*sizeof(double)); | 125 | double *B = (double*)malloc(m*n*sizeof(double)); |
96 | CHECK(!B,MEM); | 126 | CHECK(!B,MEM); |
97 | memcpy(B,ap,m*n*sizeof(double)); | 127 | memcpy(B,ap,m*n*sizeof(double)); |
98 | integer* iwk = (integer*) malloc(8*q*sizeof(int)); | 128 | integer* iwk = (integer*) malloc(8*q*sizeof(integer)); |
99 | CHECK(!iwk,MEM); | 129 | CHECK(!iwk,MEM); |
100 | integer lwk = -1; | 130 | integer lwk = -1; |
101 | integer res; | 131 | integer res; |
102 | // ask for optimal lwk | 132 | // ask for optimal lwk |
103 | double ans; | 133 | double ans; |
104 | //printf("ask dgesdd\n"); | 134 | dgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,&ans,&lwk,iwk,&res); |
105 | dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,&ans,&lwk,iwk,&res); | 135 | lwk = ans; |
106 | lwk = 2*ceil(ans); // ????? otherwise 50x100 rejects lwk | ||
107 | //printf("lwk = %d\n",lwk); | ||
108 | double * workv = (double*)malloc(lwk*sizeof(double)); | 136 | double * workv = (double*)malloc(lwk*sizeof(double)); |
109 | CHECK(!workv,MEM); | 137 | CHECK(!workv,MEM); |
110 | //printf("dgesdd\n"); | 138 | dgesdd_ (jobz,&m,&n,B,&m,sp,up,&m,vp,&ldvt,workv,&lwk,iwk,&res); |
111 | dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,workv,&lwk,iwk,&res); | ||
112 | CHECK(res,res); | 139 | CHECK(res,res); |
113 | free(iwk); | 140 | free(iwk); |
114 | free(workv); | 141 | free(workv); |
@@ -120,17 +147,36 @@ int svd_l_Rdd(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) { | |||
120 | 147 | ||
121 | // not in clapack.h | 148 | // not in clapack.h |
122 | 149 | ||
123 | int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n, | 150 | int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n, |
124 | doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, | 151 | doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, |
125 | integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, | 152 | integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, |
126 | integer *lwork, doublereal *rwork, integer *info); | 153 | integer *lwork, doublereal *rwork, integer *info); |
127 | 154 | ||
128 | int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { | 155 | int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { |
129 | integer m = ar; | 156 | integer m = ar; |
130 | integer n = ac; | 157 | integer n = ac; |
131 | integer q = MIN(m,n); | 158 | integer q = MIN(m,n); |
132 | REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE); | 159 | REQUIRES(sn==q,BAD_SIZE); |
133 | DEBUGMSG("svd_l_C"); | 160 | REQUIRES(up==NULL || ur==m && (uc==m || uc==q),BAD_SIZE); |
161 | char* jobu = "A"; | ||
162 | if (up==NULL) { | ||
163 | jobu = "N"; | ||
164 | } else { | ||
165 | if (uc==q) { | ||
166 | jobu = "S"; | ||
167 | } | ||
168 | } | ||
169 | REQUIRES(vp==NULL || vc==n && (vr==n || vr==q),BAD_SIZE); | ||
170 | char* jobvt = "A"; | ||
171 | integer ldvt = n; | ||
172 | if (vp==NULL) { | ||
173 | jobvt = "N"; | ||
174 | } else { | ||
175 | if (vr==q) { | ||
176 | jobvt = "S"; | ||
177 | ldvt = q; | ||
178 | } | ||
179 | }DEBUGMSG("svd_l_C"); | ||
134 | double *B = (double*)malloc(2*m*n*sizeof(double)); | 180 | double *B = (double*)malloc(2*m*n*sizeof(double)); |
135 | CHECK(!B,MEM); | 181 | CHECK(!B,MEM); |
136 | memcpy(B,ap,m*n*2*sizeof(double)); | 182 | memcpy(B,ap,m*n*2*sizeof(double)); |
@@ -141,26 +187,22 @@ int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { | |||
141 | integer res; | 187 | integer res; |
142 | // ask for optimal lwork | 188 | // ask for optimal lwork |
143 | doublecomplex ans; | 189 | doublecomplex ans; |
144 | //printf("ask zgesvd\n"); | 190 | zgesvd_ (jobu,jobvt, |
145 | char* job = "A"; | ||
146 | zgesvd_ (job,job, | ||
147 | &m,&n,(doublecomplex*)B,&m, | 191 | &m,&n,(doublecomplex*)B,&m, |
148 | sp, | 192 | sp, |
149 | (doublecomplex*)up,&m, | 193 | (doublecomplex*)up,&m, |
150 | (doublecomplex*)vp,&n, | 194 | (doublecomplex*)vp,&ldvt, |
151 | &ans, &lwork, | 195 | &ans, &lwork, |
152 | rwork, | 196 | rwork, |
153 | &res); | 197 | &res); |
154 | lwork = ceil(ans.r); | 198 | lwork = ceil(ans.r); |
155 | //printf("ans = %d\n",lwork); | ||
156 | doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double)); | 199 | doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double)); |
157 | CHECK(!work,MEM); | 200 | CHECK(!work,MEM); |
158 | //printf("zgesvd\n"); | 201 | zgesvd_ (jobu,jobvt, |
159 | zgesvd_ (job,job, | ||
160 | &m,&n,(doublecomplex*)B,&m, | 202 | &m,&n,(doublecomplex*)B,&m, |
161 | sp, | 203 | sp, |
162 | (doublecomplex*)up,&m, | 204 | (doublecomplex*)up,&m, |
163 | (doublecomplex*)vp,&n, | 205 | (doublecomplex*)vp,&ldvt, |
164 | work, &lwork, | 206 | work, &lwork, |
165 | rwork, | 207 | rwork, |
166 | &res); | 208 | &res); |
@@ -171,7 +213,64 @@ int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { | |||
171 | OK | 213 | OK |
172 | } | 214 | } |
173 | 215 | ||
216 | int zgesdd_ (char *jobz, integer *m, integer *n, | ||
217 | doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, | ||
218 | integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, | ||
219 | integer *lwork, doublereal *rwork, integer* iwork, integer *info); | ||
174 | 220 | ||
221 | int svd_l_Cdd(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) { | ||
222 | //printf("entro\n"); | ||
223 | integer m = ar; | ||
224 | integer n = ac; | ||
225 | integer q = MIN(m,n); | ||
226 | REQUIRES(sn==q,BAD_SIZE); | ||
227 | REQUIRES(up == NULL && vp == NULL | ||
228 | || ur==m && vc==n | ||
229 | && (uc == q && vr == q | ||
230 | || uc == m && vc==n),BAD_SIZE); | ||
231 | char* jobz = "A"; | ||
232 | integer ldvt = n; | ||
233 | if (up==NULL) { | ||
234 | jobz = "N"; | ||
235 | } else { | ||
236 | if (uc==q && vr == q) { | ||
237 | jobz = "S"; | ||
238 | ldvt = q; | ||
239 | } | ||
240 | } | ||
241 | DEBUGMSG("svd_l_Cdd"); | ||
242 | doublecomplex *B = (doublecomplex*)malloc(m*n*sizeof(doublecomplex)); | ||
243 | CHECK(!B,MEM); | ||
244 | memcpy(B,ap,m*n*sizeof(doublecomplex)); | ||
245 | integer* iwk = (integer*) malloc(8*q*sizeof(integer)); | ||
246 | CHECK(!iwk,MEM); | ||
247 | int lrwk; | ||
248 | if (0 && *jobz == 'N') { | ||
249 | lrwk = 5*q; // does not work, crash at free below | ||
250 | } else { | ||
251 | lrwk = 5*q*q + 7*q; | ||
252 | } | ||
253 | double *rwk = (double*)malloc(lrwk*sizeof(double));; | ||
254 | CHECK(!rwk,MEM); | ||
255 | //printf("%s %ld %d\n",jobz,q,lrwk); | ||
256 | integer lwk = -1; | ||
257 | integer res; | ||
258 | // ask for optimal lwk | ||
259 | doublecomplex ans; | ||
260 | zgesdd_ (jobz,&m,&n,B,&m,sp,(doublecomplex*)up,&m,(doublecomplex*)vp,&ldvt,&ans,&lwk,rwk,iwk,&res); | ||
261 | lwk = ans.r; | ||
262 | //printf("lwk = %ld\n",lwk); | ||
263 | doublecomplex * workv = (doublecomplex*)malloc(lwk*sizeof(doublecomplex)); | ||
264 | CHECK(!workv,MEM); | ||
265 | zgesdd_ (jobz,&m,&n,B,&m,sp,(doublecomplex*)up,&m,(doublecomplex*)vp,&ldvt,workv,&lwk,rwk,iwk,&res); | ||
266 | //printf("res = %ld\n",res); | ||
267 | CHECK(res,res); | ||
268 | free(workv); // printf("freed workv\n"); | ||
269 | free(rwk); // printf("freed rwk\n"); | ||
270 | free(iwk); // printf("freed iwk\n"); | ||
271 | free(B); // printf("freed B, salgo\n"); | ||
272 | OK | ||
273 | } | ||
175 | 274 | ||
176 | //////////////////// general complex eigensystem //////////// | 275 | //////////////////// general complex eigensystem //////////// |
177 | 276 | ||