|
liblapackwrap 0.1
|
00001 /* 00002 * Wrapper for a variety of LAPACK routines, to provide a unified interface. 00003 00004 Copyright (C) 2010 Joseph Pingenot 00005 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 */ 00020 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 #include <string.h> 00024 #include "liblapackwrap/lapackwrap_complex_double.h" 00025 #include "liblapackwrap/lapackwrap_functions_complex_double.c" 00026 00027 #define ACML 0 00028 #define CELL 1 00029 00030 /*These follow the FORTRAN calling semantics.*/ 00031 #if LAPACK == CELL 00032 #define FCALL 00033 #endif 00034 00035 int llw_complex_double_stegr_a(char jobz, char range, int N, LLW_CONST LLW_complex_double_REAL *D, LLW_CONST LLW_complex_double_REAL *E, LLW_complex_double_REAL VL, LLW_complex_double_REAL VU, int IL, int IU, int *M, LLW_complex_double_REAL** W, LLW_complex_double_COMPLEX** Z, int *LDZ, int** ISUPPZ) { 00036 *W = malloc(sizeof(LLW_complex_double_REAL)*N); 00037 if(*W == NULL) { 00038 return 100; 00039 } 00040 /*Right now, we're just doing N.*/ 00041 *LDZ = N; 00042 *Z = malloc(sizeof(LLW_complex_double_COMPLEX)*(*LDZ)*N); 00043 if(*Z == NULL) { 00044 free(*W); 00045 *W = NULL; 00046 return 100; 00047 } 00048 *ISUPPZ = malloc(sizeof(LLW_complex_double_REAL)*2*N); 00049 if(*ISUPPZ == NULL) { 00050 free(*W); 00051 *W = NULL; 00052 free(*Z); 00053 *Z = NULL; 00054 return 100; 00055 } 00056 int info = llw_complex_double_stegr(jobz, range, N, D, E, VL, VU, IL, IU, M, *W, *Z, *LDZ, *ISUPPZ); 00057 if(info != 0) { 00058 free(*W); 00059 *W = NULL; 00060 free(*Z); 00061 *Z = NULL; 00062 free(*ISUPPZ); 00063 *ISUPPZ = NULL; 00064 } 00065 return info; 00066 } 00067 00068 int llw_complex_double_stegr(char jobz, char range, int N, LLW_CONST LLW_complex_double_REAL *D, LLW_CONST LLW_complex_double_REAL *E, LLW_complex_double_REAL VL, LLW_complex_double_REAL VU, int IL, int IU, int *M, LLW_complex_double_REAL* W, LLW_complex_double_COMPLEX* Z, int LDZ, int* ISUPPZ) { 00069 /* 00070 fprintf(stderr, "llw_complex_double_stegr: %c %c %d %p %p %g %g %d %d %p %p %p %d %p\n", jobz, range, N, (void*)D, (void*)E, VL, VU, IL, IU, (void*)M, (void*)W, (void*)Z, LDZ, (void*)ISUPPZ); 00071 */ 00072 /*Now do our STEGR call*/ 00073 /*NOTE e_in is of length N. We copy only N-1 (since E is N-1 values; it's the first subdiagonal. HOWEVER, e_in[N-1] (i.e., the Nth element) is used internally by LAPACK as a workspace, so we need it in here.*/ 00074 LLW_complex_double_REAL *e_in; 00075 LLW_complex_double_REAL *d_in; 00076 #ifdef LLW_CONST 00077 e_in = malloc(N*sizeof(LLW_complex_double_REAL)); 00078 d_in = malloc(N*sizeof(LLW_complex_double_REAL)); 00079 if((e_in == NULL) || (d_in == NULL)) { 00080 if(e_in != NULL) free(e_in); 00081 if(d_in != NULL) free(d_in); 00082 return 100; 00083 } 00084 memcpy(e_in, E, (N-1)*sizeof(LLW_complex_double_REAL)); 00085 memcpy(d_in, D, N*sizeof(LLW_complex_double_REAL)); 00086 #else 00087 e_in = E; 00088 d_in = D; 00089 #endif 00090 /*Initialize our output storage*/ 00091 /* 00092 *M = 0; 00093 for(int i=0; i<N; i++) { 00094 W[i] = 0; 00095 for(int j=0; j<LDZ; j++) { 00096 Z[j + i*LDZ] = 0; 00097 } 00098 ISUPPZ[2*i] = ISUPPZ[2*i + 1] = 0; 00099 } 00100 for(int i=0; i<N-1; i++) { 00101 fprintf(stderr, "d[%d]=", i); 00102 fprintf(stderr, "%g ", d_in[i]); 00103 fprintf(stderr, "e[%d]=", i); 00104 fprintf(stderr, "=%g\n", e_in[i]); 00105 fprintf(stderr, "D[%d]=", i); 00106 fprintf(stderr, "%g ", D[i]); 00107 fprintf(stderr, "E[%d]=", i); 00108 fprintf(stderr, "=%g\n", E[i]); 00109 } 00110 fprintf(stderr, "D[%d]=%g\n", N, D[N-1]); 00111 fprintf(stderr, "d[%d]=%g\n", N, d_in[N-1]); 00112 */ 00113 /*First, query optimal work size*/ 00114 /* 00115 for(int i=0; i<N; i++) { 00116 fprintf(stderr, "D[%d]=%g d_in=%g E=%g e_in=%g\n", 00117 i, 00118 D[i], 00119 d_in[i], 00120 E[i], 00121 (i == (N-1))?0:e_in[1]); 00122 } 00123 */ 00124 int info; 00125 #if LAPACK == ACML 00126 /*ACML's C interface doesn't require the work and iwork arrays. 00127 *So with ACML, we just dive right in. 00128 */ 00129 STEGR(jobz, range, N, d_in, e_in, VL, VU, IL, IU, 1e-12, M, W, (LAPACK_COMPLEX_TYPENAME*)Z, LDZ, ISUPPZ, &info); 00130 #else 00131 /*The rest of the LAPACK implementations require work and iwork, 00132 * so we'll query the optimal values before making the real call. 00133 */ 00134 LLW_complex_double_REAL opt_lwork; 00135 int opt_liwork; 00136 #ifdef FCALL 00137 /*Look at all the fun in a FORTRAN call. Whee!*/ 00138 LLW_complex_double_REAL EPSILON=1e-12; 00139 int MONE = -1; 00140 STEGR(&jobz, &range, &N, d_in, e_in, &VL, &VU, &IL, &IU, &EPSILON, M, W, (LAPACK_COMPLEX_TYPENAME*)Z, &LDZ, ISUPPZ, &opt_lwork, &MONE, &opt_liwork, &MONE, &info); 00141 #else 00142 STEGR(jobz, range, N, d_in, e_in, VL, VU, IL, IU, 1e-12, M, W, (LAPACK_COMPLEX_TYPENAME*)Z, LDZ, ISUPPZ, &opt_lwork, -1, &opt_liwork, -1, &info); 00143 #endif 00144 if(info != 0) { 00145 #ifdef LLW_CONST 00146 free(e_in); 00147 free(d_in); 00148 #endif 00149 return info; 00150 } 00151 LLW_complex_double_REAL *work = malloc(sizeof(LLW_complex_double_REAL)*((int)opt_lwork)); 00152 int *iwork = malloc(sizeof(int)*opt_liwork); 00153 #ifdef FCALL 00154 int LWORK = opt_lwork; 00155 STEGR(&jobz, &range, &N, d_in, e_in, &VL, &VU, &IL, &IU, &EPSILON, M, W, (LAPACK_COMPLEX_TYPENAME*)Z, &LDZ, ISUPPZ, work, &LWORK, iwork, &opt_liwork, &info); 00156 #else 00157 STEGR(jobz, range, N, d_in, e_in, VL, VU, IL, IU, 1e-12, M, W, (LAPACK_COMPLEX_TYPENAME*)Z, LDZ, ISUPPZ, work, opt_lwork, iwork, opt_liwork, &info); 00158 #endif 00159 free(work); 00160 free(iwork); 00161 #endif 00162 #ifdef LLW_CONST 00163 free(e_in); 00164 free(d_in); 00165 #endif 00166 return info; 00167 } 00168 00169 00170 00171 int llw_complex_double_sbtrd_a(char vect, char uplo, int N, int KD, LLW_CONST LLW_complex_double_COMPLEX* A, int LDAB, LLW_complex_double_REAL** D, LLW_complex_double_REAL **E, LLW_complex_double_COMPLEX** Q) { 00172 *D = (LLW_complex_double_REAL*)malloc(N*sizeof(LLW_complex_double_REAL)); 00173 if(*D == NULL) return 100; 00174 *E = (LLW_complex_double_REAL*)malloc((N-1)*sizeof(LLW_complex_double_REAL)); 00175 if(*E == NULL) { 00176 free(D); 00177 return 100; 00178 } 00179 *Q = (LLW_complex_double_COMPLEX*)malloc(N*N*sizeof(LLW_complex_double_COMPLEX)); 00180 if(*Q == NULL) { 00181 free(D); 00182 free(E); 00183 return 100; 00184 } 00185 return llw_complex_double_sbtrd(vect, uplo, N, KD, A, LDAB, *D, *E, *Q, N); 00186 } 00187 00188 int llw_complex_double_sbtrd(char vect, char uplo, int N, int KD, LLW_CONST LLW_complex_double_COMPLEX* AB, int LDAB, LLW_complex_double_REAL* D, LLW_complex_double_REAL* E, LLW_complex_double_COMPLEX* Q, int LDQ) { 00189 LLW_complex_double_COMPLEX *ab; 00190 #ifdef LLW_CONST 00191 ab = (LLW_complex_double_COMPLEX*)malloc(N*(KD+1)*sizeof(LLW_complex_double_COMPLEX)); 00192 if(ab == NULL) return 100; 00193 memcpy(ab, AB, N*(KD+1)*sizeof(LLW_complex_double_COMPLEX)); 00194 #else 00195 ab = AB; 00196 #endif 00197 int info; 00198 #if LAPACK == ACML 00199 SBTRD(vect, uplo, N, KD, (LAPACK_COMPLEX_TYPENAME*)ab, LDAB, D, E, (LAPACK_COMPLEX_TYPENAME*)Q, LDQ, &info); 00200 #else 00201 LLW_complex_double_COMPLEX *work = (LLW_complex_double_COMPLEX*)malloc(N*sizeof(LLW_complex_double_COMPLEX)); 00202 if(work == NULL) { 00203 #ifdef LLW_CONST 00204 free(ab); 00205 #endif 00206 return 100; 00207 } 00208 #ifdef FCALL 00209 SBTRD(&vect, &uplo, &N, &KD, (LAPACK_COMPLEX_TYPENAME*)ab, &LDAB, D, E, (LAPACK_COMPLEX_TYPENAME*)Q, &LDQ, (LAPACK_COMPLEX_TYPENAME*)work, &info); 00210 #else 00211 SBTRD(vect, uplo, N, KD, (LAPACK_COMPLEX_TYPENAME*)ab, LDAB, D, E, (LAPACK_COMPLEX_TYPENAME*)Q, LDQ, (LAPACK_COMPLEX_TYPENAME*)work, &info); 00212 #endif 00213 free(work); 00214 #endif 00215 return info; 00216 } 00217 00218 00219 00220 /**LAPACK wrapper for DSYTRD. 00221 *\return the resulting INFO 00222 */ 00223 int llw_complex_double_sytrd(char uplo, int N, LLW_CONST LLW_complex_double_COMPLEX* A, LLW_complex_double_REAL* D, LLW_complex_double_REAL* E, LLW_complex_double_COMPLEX* TAU, LLW_complex_double_COMPLEX** a_out) { 00224 LLW_complex_double_COMPLEX **aa; 00225 LLW_complex_double_COMPLEX *a; 00226 if(a_out != NULL) { 00227 a = *a_out; 00228 }else{ 00229 /*Point aa to a LLW_complex_double_COMPLEX pointer on the stack if the user doesn't want it*/ 00230 aa = &a; 00231 } 00232 *aa = malloc(sizeof(LLW_complex_double_COMPLEX)*N*N); 00233 if(a == NULL) return 100; 00234 memcpy(*aa, A, N*N*sizeof(LLW_complex_double_COMPLEX)); 00235 int info; 00236 #if LAPACK == ACML 00237 SYTRD(uplo, N, (LAPACK_COMPLEX_TYPENAME*)*aa, N, D, E, (LAPACK_COMPLEX_TYPENAME*)TAU, &info); 00238 #else 00239 LLW_complex_double_COMPLEX opt_work; 00240 #ifdef FCALL 00241 int MONE = -1; 00242 SYTRD(&uplo, &N, (LAPACK_COMPLEX_TYPENAME*)*aa, &N, D, E, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)&opt_work, &MONE, &info); 00243 #else 00244 SYTRD(uplo, N, (LAPACK_COMPLEX_TYPENAME*)*aa, N, D, E, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)&opt_work, -1, &info); 00245 #endif 00246 if(info != 0) { 00247 if(a_out != NULL) free(a); 00248 return info; 00249 } 00250 int OWORK = (int) 00251 #ifdef LLW_complex_double_IS_COMPLEX 00252 opt_work.re 00253 #else 00254 opt_work 00255 #endif 00256 ; 00257 LLW_complex_double_COMPLEX* work = malloc(sizeof(LLW_complex_double_COMPLEX)*(OWORK)); 00258 #ifdef FCALL 00259 SYTRD(&uplo, &N, (LAPACK_COMPLEX_TYPENAME*)*aa, &N, D, E, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)work, &OWORK, &info); 00260 #else 00261 SYTRD(uplo, N, (LAPACK_COMPLEX_TYPENAME*)*aa, N, D, E, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)work, OWORK, &info); 00262 #endif 00263 #endif 00264 if(a_out != NULL) free(a); 00265 return info; 00266 } 00267 00268 00269 00270 int llw_complex_double_orgtr(char uplo, int N, LLW_complex_double_COMPLEX* A, LLW_complex_double_COMPLEX* TAU) { 00271 int info; 00272 #if LAPACK == ACML 00273 ORGTR(uplo, N, (LAPACK_COMPLEX_TYPENAME*)A, N, (LAPACK_COMPLEX_TYPENAME*)TAU, &info); 00274 #else 00275 LLW_complex_double_COMPLEX opt_work; 00276 #ifdef FCALL 00277 int MONE = -1; 00278 ORGTR(&uplo, &N, (LAPACK_COMPLEX_TYPENAME*)A, &N, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)&opt_work, &MONE, &info); 00279 #else 00280 ORGTR(uplo, N, (LAPACK_COMPLEX_TYPENAME*)A, N, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)&opt_work, -1, &info); 00281 #endif 00282 if(info != 0) { 00283 return info; 00284 } 00285 int OWORK = (int) 00286 #ifdef LLW_complex_double_IS_COMPLEX 00287 opt_work.re 00288 #else 00289 opt_work 00290 #endif 00291 ; 00292 LLW_complex_double_COMPLEX* work = (LLW_complex_double_COMPLEX*)malloc(sizeof(LLW_complex_double_COMPLEX)*OWORK); 00293 #ifdef FCALL 00294 ORGTR(&uplo, &N, (LAPACK_COMPLEX_TYPENAME*)A, &N, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)work, &OWORK, &info); 00295 #else 00296 ORGTR(uplo, N, (LAPACK_COMPLEX_TYPENAME*)A, N, (LAPACK_COMPLEX_TYPENAME*)TAU, (LAPACK_COMPLEX_TYPENAME*)work, OWORK, &info); 00297 #endif 00298 #endif 00299 return info; 00300 } 00301 00302 00303