00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vnl_sparse_symmetric_eigensystem.h"
00009 #include <vcl_cassert.h>
00010 #include <vcl_cstring.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_vector.h>
00013
00014 #include <vnl/algo/vnl_netlib.h>
00015
00016 static vnl_sparse_symmetric_eigensystem * current_system = 0;
00017
00018 #ifdef VCL_SUNPRO_CC
00019 # define FUNCTION extern "C"
00020 #else
00021 # define FUNCTION static
00022 #endif
00023
00024
00025
00026
00027
00028 FUNCTION
00029 void sse_op_callback(const long* n,
00030 const long* m,
00031 const double* p,
00032 double* q)
00033 {
00034 assert(current_system != 0);
00035
00036 current_system->CalculateProduct(*n,*m,p,q);
00037 }
00038
00039
00040
00041
00042
00043
00044 FUNCTION
00045 void sse_iovect_callback(const long* n,
00046 const long* m,
00047 double* q,
00048 const long* j,
00049 const long* k)
00050 {
00051 assert(current_system != 0);
00052
00053 if (*k==0)
00054 current_system->SaveVectors(*n,*m,q,*j-*m);
00055 else if (*k==1)
00056 current_system->RestoreVectors(*n,*m,q,*j-*m);
00057 }
00058
00059 vnl_sparse_symmetric_eigensystem::vnl_sparse_symmetric_eigensystem()
00060 : nvalues(0), vectors(0), values(0)
00061 {
00062 }
00063
00064 vnl_sparse_symmetric_eigensystem::~vnl_sparse_symmetric_eigensystem()
00065 {
00066 delete[] vectors; vectors = 0;
00067 delete[] values; values = 0;
00068 for (unsigned i=0; i<temp_store.size(); ++i)
00069 delete temp_store[i];
00070 temp_store.clear();
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080 int vnl_sparse_symmetric_eigensystem::CalculateNPairs(vnl_sparse_matrix<double>& M,
00081 int n,
00082 bool smallest,
00083 long nfigures)
00084 {
00085 mat = &M;
00086
00087
00088 if (vectors) {
00089 delete[] vectors; vectors = 0;
00090 delete[] values; values = 0;
00091 }
00092 nvalues = 0;
00093
00094 current_system = this;
00095
00096 long dim = mat->columns();
00097 long nvals = (smallest)?-n:n;
00098 long nperm = 0;
00099 long nmval = n;
00100 long nmvec = dim;
00101 vcl_vector<double> temp_vals(n*4);
00102 vcl_vector<double> temp_vecs(n*dim);
00103
00104
00105 long nblock = (dim<60) ? dim/6 : 10;
00106
00107
00108 long maxop = dim*10;
00109
00110
00111 long maxj = maxop*nblock;
00112 long t1 = 6*nblock+1;
00113 if (maxj < t1) maxj = t1;
00114 if (maxj < 40) maxj = 40;
00115
00116
00117
00118 int work_size = dim*nblock;
00119 int t2 = maxj*(2*nblock+3) + 2*n + 6 + (2*nblock+2)*(nblock+1);
00120 if (work_size < t2) work_size = t2;
00121 work_size += 2*dim*nblock + maxj*(nblock + n + 2) + 2*nblock*nblock + 3*n;
00122 vcl_vector<double> work(work_size+10);
00123
00124
00125 for (int i=0; i<dim*nblock; ++i)
00126 work[i] = 0.0;
00127
00128 vcl_vector<long> ind(n);
00129
00130 long ierr = 0;
00131
00132 v3p_netlib_dnlaso_(sse_op_callback, sse_iovect_callback,
00133 &dim, &nvals, &nfigures, &nperm,
00134 &nmval, &temp_vals[0],
00135 &nmvec, &temp_vecs[0],
00136 &nblock,
00137 &maxop,
00138 &maxj,
00139 &work[0],
00140 &ind[0],
00141 &ierr);
00142 if (ierr > 0)
00143 {
00144 if (ierr & 0x1)
00145 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: N < 6*NBLOCK\n";
00146 if (ierr & 0x2)
00147 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NFIG < 0\n";
00148 if (ierr & 0x4)
00149 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NMVEC < N\n";
00150 if (ierr & 0x8)
00151 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NPERM < 0\n";
00152 if (ierr & 0x10)
00153 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: MAXJ < 6*NBLOCK\n";
00154 if (ierr & 0x20)
00155 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NVAL < max(1,NPERM)\n";
00156 if (ierr & 0x40)
00157 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NVAL > NMVAL\n";
00158 if (ierr & 0x80)
00159 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NVAL > MAXOP\n";
00160 if (ierr & 0x100)
00161 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NVAL > MAXJ/2\n";
00162 if (ierr & 0x200)
00163 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem: NBLOCK < 1\n";
00164 }
00165 else if (ierr < 0)
00166 {
00167 if (ierr == -1)
00168 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem:\n"
00169 << " poor initial vectors chosen\n";
00170 else if (ierr == -2)
00171 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem:\n"
00172 << " reached maximum operations " << maxop
00173 << " without finding all eigenvalues,\n"
00174 << " found " << nperm << " eigenvalues\n";
00175 else if (ierr == -8)
00176 vcl_cerr << "Error: vnl_sparse_symmetric_eigensystem:\n"
00177 << " disastrous loss of orthogonality - internal error\n";
00178 }
00179
00180
00181 nvalues = n;
00182 vectors = new vnl_vector<double>[n];
00183 values = new double[n];
00184 for (int i=0; i<n; ++i) {
00185 values[i] = temp_vals[i];
00186 #if 0
00187 vcl_cout << "value " << temp_vals[i]
00188 << " accuracy " << temp_vals[i+n*2] << vcl_endl;
00189 #endif
00190 vnl_vector<double> vec(dim,0.0);
00191 for (int j=0; j<dim; ++j)
00192 vec[j] = temp_vecs[j + dim*i];
00193 vectors[i] = vec;
00194 }
00195
00196
00197 for (unsigned i=0; i<temp_store.size(); ++i)
00198 delete [] temp_store[i];
00199 temp_store.clear();
00200
00201 return ierr;
00202 }
00203
00204
00205
00206 int vnl_sparse_symmetric_eigensystem::CalculateProduct(int n, int m,
00207 const double* p,
00208 double* q)
00209 {
00210
00211 mat->mult(n,m,p,q);
00212
00213 return 0;
00214 }
00215
00216
00217
00218 int vnl_sparse_symmetric_eigensystem::SaveVectors(int n, int m,
00219 const double* q,
00220 int base)
00221 {
00222
00223
00224 if (base == 0) {
00225 for (unsigned i=0; i<temp_store.size(); ++i)
00226 delete temp_store[i];
00227 temp_store.clear();
00228 }
00229
00230 double* temp = new double[n*m];
00231 vcl_memcpy(temp,q,n*m*sizeof(double));
00232 #ifdef DEBUG
00233 vcl_cout << "Save vectors " << base << ' ' << temp << '\n';
00234 #endif
00235
00236 temp_store.push_back(temp);
00237
00238 return 0;
00239 }
00240
00241
00242
00243 int vnl_sparse_symmetric_eigensystem::RestoreVectors(int n, int m,
00244 double* q,
00245 int base)
00246 {
00247
00248
00249 static int read_idx = 0;
00250 if (base == 0)
00251 read_idx = 0;
00252
00253 double* temp = temp_store[read_idx];
00254 vcl_memcpy(q,temp,n*m*sizeof(double));
00255 #ifdef DEBUG
00256 vcl_cout << "Restore vectors " << base << ' ' << temp << '\n';
00257 #endif
00258
00259 read_idx++;
00260 return 0;
00261 }
00262
00263
00264
00265 vnl_vector<double> vnl_sparse_symmetric_eigensystem::get_eigenvector(int i) const
00266 {
00267 assert(i>=0 && i<nvalues);
00268 return vectors[i];
00269 }
00270
00271 double vnl_sparse_symmetric_eigensystem::get_eigenvalue(int i) const
00272 {
00273 assert(i>=0 && i<nvalues);
00274 return values[i];
00275 }