00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <shogun/mathematics/arpack.h>
00012 #ifdef HAVE_ARPACK
00013 #ifdef HAVE_LAPACK
00014 #include <shogun/lib/config.h>
00015 #include <cblas.h>
00016 #include <shogun/mathematics/lapack.h>
00017 #include <shogun/lib/common.h>
00018 #include <shogun/io/SGIO.h>
00019 #include <string.h>
00020
00021 using namespace shogun;
00022
00023 namespace shogun
00024 {
00025
00026 void arpack_dsaeupd_wrap(double* matrix, double* rhs_diag, int n, int nev, const char* which,
00027 int mode, bool pos, double shift, double tolerance, double* eigenvalues,
00028 double* eigenvectors, int& status)
00029 {
00030
00031 int i,j;
00032
00033
00034 if (nev>n)
00035 SG_SERROR("Number of required eigenpairs is greater than order of the matrix");
00036
00037
00038 if (mode!=1 && mode!=3)
00039 SG_SERROR("Mode not supported yet");
00040
00041
00042
00043 int ido = 0;
00044
00045
00046
00047 char bmat[2] = "I";
00048 if (rhs_diag)
00049 bmat[0] = 'G';
00050
00051
00052 double tol = tolerance;
00053
00054
00055 double* resid = SG_MALLOC(double, n);
00056
00057 for (i=0; i<n; i++)
00058 resid[i] = 1.0;
00059
00060
00061
00062 int ncv = nev*4>n ? n : nev*4;
00063
00064
00065 int ldv = n;
00066 double* v = SG_MALLOC(double, ldv*ncv);
00067
00068
00069 int* iparam = SG_MALLOC(int, 11);
00070
00071 iparam[0] = 1;
00072
00073 iparam[2] = 3*n;
00074
00075 iparam[6] = mode;
00076
00077
00078 int* ipntr = SG_CALLOC(int, 11);
00079
00080
00081 double* workd = SG_MALLOC(double, 3*n);
00082 int lworkl = ncv*(ncv+8);
00083 double* workl = SG_MALLOC(double, lworkl);
00084
00085
00086 int info = 1;
00087
00088
00089 char* which_ = strdup(which);
00090
00091 char* all_ = strdup("A");
00092
00093
00094 int* ipiv = NULL;
00095
00096 if (mode==3)
00097 {
00098
00099 if (shift!=0.0)
00100 {
00101 SG_SDEBUG("ARPACK: Subtracting shift\n");
00102
00103 if (rhs_diag)
00104
00105 for (i=0; i<n; i++)
00106 matrix[i*n+i] -= shift*rhs_diag[i];
00107 else
00108
00109 for (i=0; i<n; i++)
00110 matrix[i*n+i] -= shift;
00111 }
00112
00113
00114 if (pos)
00115 {
00116
00117 SG_SDEBUG("ARPACK: Using Cholesky factorization.\n");
00118 clapack_dpotrf(CblasColMajor,CblasUpper,n,matrix,n);
00119 }
00120 else
00121 {
00122
00123 SG_SDEBUG("ARPACK: Using LUP factorization.\n");
00124 ipiv = SG_CALLOC(int, n);
00125 clapack_dgetrf(CblasColMajor,n,n,matrix,n,ipiv);
00126 }
00127 }
00128
00129 SG_SDEBUG("ARPACK: Starting main computation DSAUPD loop.\n");
00130 do
00131 {
00132 dsaupd_(&ido, bmat, &n, which_, &nev, &tol, resid,
00133 &ncv, v, &ldv, iparam, ipntr, workd, workl,
00134 &lworkl, &info);
00135
00136 if ((ido==1)||(ido==-1)||(ido==2))
00137 {
00138 if (mode==1)
00139 {
00140
00141 cblas_dsymv(CblasColMajor,CblasUpper,
00142 n,1.0,matrix,n,
00143 (workd+ipntr[0]-1),1,
00144 0.0,(workd+ipntr[1]-1),1);
00145 }
00146 if (mode==3)
00147 {
00148 if (!rhs_diag)
00149 {
00150 for (i=0; i<n; i++)
00151 (workd+ipntr[1]-1)[i] = (workd+ipntr[0]-1)[i];
00152
00153 if (pos)
00154 clapack_dpotrs(CblasColMajor,CblasUpper,n,1,matrix,n,(workd+ipntr[1]-1),n);
00155 else
00156 clapack_dgetrs(CblasColMajor,CblasNoTrans,n,1,matrix,n,ipiv,(workd+ipntr[1]-1),n);
00157 }
00158 else
00159 {
00160 if (ido==-1)
00161 {
00162 for (i=0; i<n; i++)
00163 (workd+ipntr[1]-1)[i] = rhs_diag[i]*(workd+ipntr[0]-1)[i];
00164
00165 if (pos)
00166 clapack_dpotrs(CblasColMajor,CblasUpper,n,1,matrix,n,(workd+ipntr[1]-1),n);
00167 else
00168 clapack_dgetrs(CblasColMajor,CblasNoTrans,n,1,matrix,n,ipiv,(workd+ipntr[1]-1),n);
00169 }
00170 if (ido==1)
00171 {
00172 for (i=0; i<n; i++)
00173 (workd+ipntr[1]-1)[i] = (workd+ipntr[2]-1)[i];
00174
00175 if (pos)
00176 clapack_dpotrs(CblasColMajor,CblasUpper,n,1,matrix,n,(workd+ipntr[1]-1),n);
00177 else
00178 clapack_dgetrs(CblasColMajor,CblasNoTrans,n,1,matrix,n,ipiv,(workd+ipntr[1]-1),n);
00179 }
00180 if (ido==2)
00181 {
00182 for (i=0; i<n; i++)
00183 (workd+ipntr[1]-1)[i] = rhs_diag[i]*(workd+ipntr[0]-1)[i];
00184 }
00185 }
00186 }
00187 }
00188 } while ((ido==1)||(ido==-1)||(ido==2));
00189
00190 if (!pos && mode==3) SG_FREE(ipiv);
00191
00192
00193 if (info<0)
00194 {
00195 if ((info<=-1)&&(info>=-6))
00196 SG_SWARNING("ARPACK: DSAUPD failed. Wrong parameter passed.\n");
00197 else if (info==-7)
00198 SG_SWARNING("ARPACK: DSAUPD failed. Workaround array size is not sufficient.\n");
00199 else
00200 SG_SWARNING("ARPACK: DSAUPD failed. Error code: %d.\n", info);
00201
00202 status = -1;
00203 }
00204 else
00205 {
00206 if (info==1)
00207 SG_SWARNING("ARPACK: Maximum number of iterations reached.\n");
00208
00209
00210 int* select = SG_MALLOC(int, ncv);
00211
00212 double* d = SG_MALLOC(double, 2*ncv);
00213
00214 double sigma = shift;
00215
00216
00217 int ierr = 0;
00218
00219
00220 int rvec = 1;
00221
00222 SG_SDEBUG("APRACK: Starting DSEUPD.\n");
00223
00224
00225 dseupd_(&rvec, all_, select, d, v, &ldv, &sigma, bmat,
00226 &n, which_, &nev, &tol, resid, &ncv, v, &ldv,
00227 iparam, ipntr, workd, workl, &lworkl, &ierr);
00228
00229
00230 if (ierr!=0)
00231 {
00232 SG_SWARNING("ARPACK: DSEUPD failed with status %d.\n", ierr);
00233 status = -1;
00234 }
00235 else
00236 {
00237 SG_SDEBUG("ARPACK: Storing eigenpairs.\n");
00238
00239
00240 for (i=0; i<nev; i++)
00241 {
00242 eigenvalues[i] = d[i];
00243
00244 for (j=0; j<n; j++)
00245 eigenvectors[j*nev+i] = v[i*n+j];
00246 }
00247 }
00248
00249
00250 SG_FREE(select);
00251 SG_FREE(d);
00252 }
00253
00254
00255 SG_FREE(all_);
00256 SG_FREE(which_);
00257 SG_FREE(resid);
00258 SG_FREE(v);
00259 SG_FREE(iparam);
00260 SG_FREE(ipntr);
00261 SG_FREE(workd);
00262 SG_FREE(workl);
00263 };
00264
00265 }
00266 #endif
00267 #endif