00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef IMAGE_LINEARALGEBRA_C_DEFINED
00039 #define IMAGE_LINEARALGEBRA_C_DEFINED
00040
00041 #include "Image/LinearAlgebra.H"
00042
00043 #include "Image/Image.H"
00044 #include "Image/MatrixOps.H"
00045 #include "Image/gsl.H"
00046 #include "Image/lapack.H"
00047 #include "rutz/trace.h"
00048
00049 namespace
00050 {
00051
00052 template <class T>
00053 Image<T> invdiag(const Image<T>& x,
00054 const T tolfactor,
00055 int* const rank)
00056 {
00057 ASSERT(x.getWidth() == x.getHeight());
00058
00059 Image<T> result(x.getDims(), ZEROS);
00060 if (rank != NULL) *rank = 0;
00061
00062 const T thresh = tolfactor*x[0];
00063
00064 const T eigtot = trace(x);
00065 T eigsum = 0.0;
00066 T eigkept = 0.0;
00067
00068 for (int i = 0; i < x.getWidth(); ++i)
00069 {
00070 const T xval = x[Point2D<int>(i,i)];
00071
00072 eigsum += xval;
00073
00074
00075
00076
00077
00078
00079 const bool discard =
00080 tolfactor < 1.0
00081 ? (xval < thresh)
00082 : (i >= int(tolfactor));
00083
00084 LINFO("x[%d]=%g %s %5.2f%% (thresh=%g)",
00085 i, double(xval),
00086 discard ? "discarded" : "kept",
00087 eigtot > 0.0 ? double(100.0 * eigsum) / eigtot : 0.0,
00088 double(thresh));
00089
00090 if (discard)
00091 result[Point2D<int>(i,i)] = 0.0;
00092 else
00093 {
00094 result[Point2D<int>(i,i)] = 1.0 / xval;
00095 if (rank != NULL) ++*rank;
00096 eigkept = eigsum;
00097 }
00098 }
00099
00100 LINFO("retained eigenvalues account for %5.2f%% of total",
00101 eigtot > 0.0 ? double(100.0 * eigkept) / eigtot : 0.0);
00102 return result;
00103 }
00104
00105 }
00106
00107
00108 void svd(const Image<double>& A,
00109 Image<double>& U, Image<double>& S, Image<double>& V,
00110 SvdAlgo algo, SvdFlag flags)
00111 {
00112 GVX_TRACE(__PRETTY_FUNCTION__);
00113
00114 #ifndef HAVE_LAPACK
00115 if (algo == SVD_LAPACK)
00116 {
00117 LINFO("SVD_LAPACK not available, using SVD_GSL instead");
00118 algo = SVD_GSL;
00119 flags |= SVD_TALL;
00120 }
00121 #endif
00122
00123 switch (algo)
00124 {
00125 #ifdef HAVE_LAPACK
00126 case SVD_LAPACK:
00127 lapack::svd(A, U, S, V, flags);
00128 break;
00129 #endif
00130
00131 case SVD_GSL:
00132 gsl::svd(A, U, S, V, flags);
00133 break;
00134
00135 default:
00136 LFATAL("unknown SvdAlgo enumerant '%d'", int(algo));
00137 }
00138 }
00139
00140
00141 void svdf(const Image<float>& A,
00142 Image<float>& U, Image<float>& S, Image<float>& V,
00143 SvdAlgo algo, SvdFlag flags)
00144 {
00145 GVX_TRACE(__PRETTY_FUNCTION__);
00146
00147 #ifndef HAVE_LAPACK
00148 if (algo == SVD_LAPACK)
00149 {
00150 LINFO("SVD_LAPACK not available, using SVD_GSL instead");
00151 algo = SVD_GSL;
00152 flags |= SVD_TALL;
00153 }
00154 #endif
00155
00156 switch (algo)
00157 {
00158 #ifdef HAVE_LAPACK
00159 case SVD_LAPACK:
00160 lapack::svdf(A, U, S, V, flags);
00161 break;
00162 #endif
00163
00164 case SVD_GSL:
00165 gsl::svdf(A, U, S, V, flags);
00166 break;
00167
00168 default:
00169 LFATAL("unknown SvdAlgo enumerant '%d'", int(algo));
00170 }
00171 }
00172
00173
00174 Image<double> svdPseudoInv(const Image<double>& x,
00175 const SvdAlgo algo,
00176 int* const rank,
00177 const double tolfactor)
00178 {
00179 GVX_TRACE(__PRETTY_FUNCTION__);
00180
00181 Image<double> U, S, V;
00182 svd(x, U, S, V, algo);
00183
00184 LINFO("U is %dx%d", U.getHeight(), U.getWidth());
00185 LINFO("S is %dx%d", S.getHeight(), S.getWidth());
00186 LINFO("V is %dx%d", V.getHeight(), V.getWidth());
00187
00188
00189
00190
00191 return matrixMult(V, matrixMult(invdiag(S, tolfactor, rank),
00192 transpose(U)));
00193 }
00194
00195
00196 Image<float> svdPseudoInvf(const Image<float>& x,
00197 const SvdAlgo algo,
00198 int* const rank,
00199 const float tolfactor)
00200 {
00201 GVX_TRACE(__PRETTY_FUNCTION__);
00202
00203 Image<float> U, S, V;
00204 svdf(x, U, S, V, algo);
00205
00206 LINFO("U is %dx%d", U.getHeight(), U.getWidth());
00207 LINFO("S is %dx%d", S.getHeight(), S.getWidth());
00208 LINFO("V is %dx%d", V.getHeight(), V.getWidth());
00209
00210 return matrixMult(V, matrixMult(invdiag(S, tolfactor, rank),
00211 transpose(U)));
00212 }
00213
00214
00215 template <class T>
00216 Image<typename promote_trait<T, float>::TP>
00217 naiveUnstablePseudoInv(const Image<T>& M)
00218 {
00219 GVX_TRACE(__PRETTY_FUNCTION__);
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 typedef typename promote_trait<T, float>::TP TF;
00232
00233 const Image<TF> m(M);
00234 const Image<TF> mt(transpose(M));
00235 const Image<TF> mtm = matrixMult(mt, m);
00236 const Image<TF> invmtm = matrixInv(mtm);
00237
00238 return matrixMult(invmtm, mt);
00239 }
00240
00241
00242 #include "inst/Image/LinearAlgebra.I"
00243
00244 template Image<promote_trait<double, float>::TP> naiveUnstablePseudoInv(const Image<double>&);
00245
00246
00247
00248
00249
00250
00251
00252 #endif // IMAGE_LINEARALGEBRA_C_DEFINED