00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "CmplxSVD.h"
00028 #include "dbleSVD.h"
00029 #include "fCmplxSVD.h"
00030 #include "floatSVD.h"
00031
00032 #include "defun-dld.h"
00033 #include "error.h"
00034 #include "gripes.h"
00035 #include "oct-obj.h"
00036 #include "pr-output.h"
00037 #include "utils.h"
00038 #include "variables.h"
00039
00040 static int Vsvd_driver = SVD::GESVD;
00041
00042 DEFUN_DLD (svd, args, nargout,
00043 "-*- texinfo -*-\n\
00044 @deftypefn {Loadable Function} {@var{s} =} svd (@var{A})\n\
00045 @deftypefnx {Loadable Function} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A})\n\
00046 @deftypefnx {Loadable Function} {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}, @var{econ})\n\
00047 @cindex singular value decomposition\n\
00048 Compute the singular value decomposition of @var{A}\n\
00049 @tex\n\
00050 $$\n\
00051 A = U S V^{\\dagger}\n\
00052 $$\n\
00053 @end tex\n\
00054 @ifnottex\n\
00055 \n\
00056 @example\n\
00057 A = U*S*V'\n\
00058 @end example\n\
00059 \n\
00060 @end ifnottex\n\
00061 \n\
00062 The function @code{svd} normally returns only the vector of singular values.\n\
00063 When called with three return values, it computes\n\
00064 @tex\n\
00065 $U$, $S$, and $V$.\n\
00066 @end tex\n\
00067 @ifnottex\n\
00068 @var{U}, @var{S}, and @var{V}.\n\
00069 @end ifnottex\n\
00070 For example,\n\
00071 \n\
00072 @example\n\
00073 svd (hilb (3))\n\
00074 @end example\n\
00075 \n\
00076 @noindent\n\
00077 returns\n\
00078 \n\
00079 @example\n\
00080 @group\n\
00081 ans =\n\
00082 \n\
00083 1.4083189\n\
00084 0.1223271\n\
00085 0.0026873\n\
00086 @end group\n\
00087 @end example\n\
00088 \n\
00089 @noindent\n\
00090 and\n\
00091 \n\
00092 @example\n\
00093 [u, s, v] = svd (hilb (3))\n\
00094 @end example\n\
00095 \n\
00096 @noindent\n\
00097 returns\n\
00098 \n\
00099 @example\n\
00100 @group\n\
00101 u =\n\
00102 \n\
00103 -0.82704 0.54745 0.12766\n\
00104 -0.45986 -0.52829 -0.71375\n\
00105 -0.32330 -0.64901 0.68867\n\
00106 \n\
00107 s =\n\
00108 \n\
00109 1.40832 0.00000 0.00000\n\
00110 0.00000 0.12233 0.00000\n\
00111 0.00000 0.00000 0.00269\n\
00112 \n\
00113 v =\n\
00114 \n\
00115 -0.82704 0.54745 0.12766\n\
00116 -0.45986 -0.52829 -0.71375\n\
00117 -0.32330 -0.64901 0.68867\n\
00118 @end group\n\
00119 @end example\n\
00120 \n\
00121 If given a second argument, @code{svd} returns an economy-sized\n\
00122 decomposition, eliminating the unnecessary rows or columns of @var{U} or\n\
00123 @var{V}.\n\
00124 @seealso{svd_driver, svds, eig}\n\
00125 @end deftypefn")
00126 {
00127 octave_value_list retval;
00128
00129 int nargin = args.length ();
00130
00131 if (nargin < 1 || nargin > 2 || nargout == 2 || nargout > 3)
00132 {
00133 print_usage ();
00134 return retval;
00135 }
00136
00137 octave_value arg = args(0);
00138
00139 octave_idx_type nr = arg.rows ();
00140 octave_idx_type nc = arg.columns ();
00141
00142 if (arg.ndims () != 2)
00143 {
00144 error ("svd: A must be a 2-D matrix");
00145 return retval;
00146 }
00147
00148 bool isfloat = arg.is_single_type ();
00149
00150 SVD::type type = ((nargout == 0 || nargout == 1)
00151 ? SVD::sigma_only
00152 : (nargin == 2) ? SVD::economy : SVD::std);
00153
00154 SVD::driver driver = static_cast<SVD::driver> (Vsvd_driver);
00155
00156 if (nr == 0 || nc == 0)
00157 {
00158 if (isfloat)
00159 {
00160 switch (type)
00161 {
00162 case SVD::std:
00163 retval(2) = FloatDiagMatrix (nc, nc, 1.0f);
00164 retval(1) = FloatMatrix (nr, nc);
00165 retval(0) = FloatDiagMatrix (nr, nr, 1.0f);
00166 break;
00167 case SVD::economy:
00168 retval(2) = FloatDiagMatrix (0, nc, 1.0f);
00169 retval(1) = FloatMatrix (0, 0);
00170 retval(0) = FloatDiagMatrix (nr, 0, 1.0f);
00171 break;
00172 case SVD::sigma_only: default:
00173 retval(0) = FloatMatrix (0, 1);
00174 break;
00175 }
00176 }
00177 else
00178 {
00179 switch (type)
00180 {
00181 case SVD::std:
00182 retval(2) = DiagMatrix (nc, nc, 1.0);
00183 retval(1) = Matrix (nr, nc);
00184 retval(0) = DiagMatrix (nr, nr, 1.0);
00185 break;
00186 case SVD::economy:
00187 retval(2) = DiagMatrix (0, nc, 1.0);
00188 retval(1) = Matrix (0, 0);
00189 retval(0) = DiagMatrix (nr, 0, 1.0);
00190 break;
00191 case SVD::sigma_only: default:
00192 retval(0) = Matrix (0, 1);
00193 break;
00194 }
00195 }
00196 }
00197 else
00198 {
00199 if (isfloat)
00200 {
00201 if (arg.is_real_type ())
00202 {
00203 FloatMatrix tmp = arg.float_matrix_value ();
00204
00205 if (! error_state)
00206 {
00207 if (tmp.any_element_is_inf_or_nan ())
00208 {
00209 error ("svd: cannot take SVD of matrix containing Inf or NaN values");
00210 return retval;
00211 }
00212
00213 FloatSVD result (tmp, type, driver);
00214
00215 FloatDiagMatrix sigma = result.singular_values ();
00216
00217 if (nargout == 0 || nargout == 1)
00218 {
00219 retval(0) = sigma.diag ();
00220 }
00221 else
00222 {
00223 retval(2) = result.right_singular_matrix ();
00224 retval(1) = sigma;
00225 retval(0) = result.left_singular_matrix ();
00226 }
00227 }
00228 }
00229 else if (arg.is_complex_type ())
00230 {
00231 FloatComplexMatrix ctmp = arg.float_complex_matrix_value ();
00232
00233 if (! error_state)
00234 {
00235 if (ctmp.any_element_is_inf_or_nan ())
00236 {
00237 error ("svd: cannot take SVD of matrix containing Inf or NaN values");
00238 return retval;
00239 }
00240
00241 FloatComplexSVD result (ctmp, type, driver);
00242
00243 FloatDiagMatrix sigma = result.singular_values ();
00244
00245 if (nargout == 0 || nargout == 1)
00246 {
00247 retval(0) = sigma.diag ();
00248 }
00249 else
00250 {
00251 retval(2) = result.right_singular_matrix ();
00252 retval(1) = sigma;
00253 retval(0) = result.left_singular_matrix ();
00254 }
00255 }
00256 }
00257 }
00258 else
00259 {
00260 if (arg.is_real_type ())
00261 {
00262 Matrix tmp = arg.matrix_value ();
00263
00264 if (! error_state)
00265 {
00266 if (tmp.any_element_is_inf_or_nan ())
00267 {
00268 error ("svd: cannot take SVD of matrix containing Inf or NaN values");
00269 return retval;
00270 }
00271
00272 SVD result (tmp, type, driver);
00273
00274 DiagMatrix sigma = result.singular_values ();
00275
00276 if (nargout == 0 || nargout == 1)
00277 {
00278 retval(0) = sigma.diag ();
00279 }
00280 else
00281 {
00282 retval(2) = result.right_singular_matrix ();
00283 retval(1) = sigma;
00284 retval(0) = result.left_singular_matrix ();
00285 }
00286 }
00287 }
00288 else if (arg.is_complex_type ())
00289 {
00290 ComplexMatrix ctmp = arg.complex_matrix_value ();
00291
00292 if (! error_state)
00293 {
00294 if (ctmp.any_element_is_inf_or_nan ())
00295 {
00296 error ("svd: cannot take SVD of matrix containing Inf or NaN values");
00297 return retval;
00298 }
00299
00300 ComplexSVD result (ctmp, type, driver);
00301
00302 DiagMatrix sigma = result.singular_values ();
00303
00304 if (nargout == 0 || nargout == 1)
00305 {
00306 retval(0) = sigma.diag ();
00307 }
00308 else
00309 {
00310 retval(2) = result.right_singular_matrix ();
00311 retval(1) = sigma;
00312 retval(0) = result.left_singular_matrix ();
00313 }
00314 }
00315 }
00316 else
00317 {
00318 gripe_wrong_type_arg ("svd", arg);
00319 return retval;
00320 }
00321 }
00322 }
00323
00324 return retval;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 DEFUN_DLD (svd_driver, args, nargout,
00408 "-*- texinfo -*-\n\
00409 @deftypefn {Loadable Function} {@var{val} =} svd_driver ()\n\
00410 @deftypefnx {Loadable Function} {@var{old_val} =} svd_driver (@var{new_val})\n\
00411 @deftypefnx {Loadable Function} {} svd_driver (@var{new_val}, \"local\")\n\
00412 Query or set the underlying @sc{lapack} driver used by @code{svd}.\n\
00413 Currently recognized values are \"gesvd\" and \"gesdd\". The default\n\
00414 is \"gesvd\".\n\
00415 \n\
00416 When called from inside a function with the \"local\" option, the variable is\n\
00417 changed locally for the function and any subroutines it calls. The original\n\
00418 variable value is restored when exiting the function.\n\
00419 @seealso{svd}\n\
00420 @end deftypefn")
00421 {
00422 static const char *driver_names[] = { "gesvd", "gesdd", 0 };
00423
00424 return SET_INTERNAL_VARIABLE_CHOICES (svd_driver, driver_names);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438