Mercurial > octave-nkf
comparison libinterp/dldfcn/chol.cc @ 15195:2fc554ffbc28
split libinterp from src
* libinterp: New directory. Move all files from src directory here
except Makefile.am, main.cc, main-cli.cc, mkoctfile.in.cc,
mkoctfilr.in.sh, octave-config.in.cc, octave-config.in.sh.
* libinterp/Makefile.am: New file, extracted from src/Makefile.am.
* src/Makefile.am: Delete everything except targets and definitions
needed to build and link main and utility programs.
* Makefile.am (SUBDIRS): Include libinterp in the list.
* autogen.sh: Run config-module.sh in libinterp/dldfcn directory, not
src/dldfcn directory.
* configure.ac (AC_CONFIG_SRCDIR): Use libinterp/octave.cc, not
src/octave.cc.
(DL_LDFLAGS, LIBOCTINTERP): Use libinterp, not src.
(AC_CONFIG_FILES): Include libinterp/Makefile in the list.
* find-docstring-files.sh: Look in libinterp, not src.
* gui/src/Makefile.am (liboctgui_la_CPPFLAGS): Find header files in
libinterp, not src.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 18 Aug 2012 16:23:39 -0400 |
parents | src/dldfcn/chol.cc@82d51d6e470c |
children | 94cdf82d4a0c |
comparison
equal
deleted
inserted
replaced
15194:0f0b795044c3 | 15195:2fc554ffbc28 |
---|---|
1 /* | |
2 | |
3 Copyright (C) 1996-2012 John W. Eaton | |
4 Copyright (C) 2008-2009 Jaroslav Hajek | |
5 Copyright (C) 2008-2009 VZLU Prague | |
6 | |
7 This file is part of Octave. | |
8 | |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 3 of the License, or (at your | |
12 option) any later version. | |
13 | |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with Octave; see the file COPYING. If not, see | |
21 <http://www.gnu.org/licenses/>. | |
22 | |
23 */ | |
24 | |
25 | |
26 #ifdef HAVE_CONFIG_H | |
27 #include <config.h> | |
28 #endif | |
29 | |
30 #include "CmplxCHOL.h" | |
31 #include "dbleCHOL.h" | |
32 #include "fCmplxCHOL.h" | |
33 #include "floatCHOL.h" | |
34 #include "SparseCmplxCHOL.h" | |
35 #include "SparsedbleCHOL.h" | |
36 #include "oct-spparms.h" | |
37 #include "sparse-util.h" | |
38 | |
39 #include "ov-re-sparse.h" | |
40 #include "ov-cx-sparse.h" | |
41 #include "defun-dld.h" | |
42 #include "error.h" | |
43 #include "gripes.h" | |
44 #include "oct-obj.h" | |
45 #include "utils.h" | |
46 | |
47 template <class CHOLT> | |
48 static octave_value | |
49 get_chol_r (const CHOLT& fact) | |
50 { | |
51 return octave_value (fact.chol_matrix (), | |
52 MatrixType (MatrixType::Upper)); | |
53 } | |
54 | |
55 template <class CHOLT> | |
56 static octave_value | |
57 get_chol_l (const CHOLT& fact) | |
58 { | |
59 return octave_value (fact.chol_matrix ().transpose (), | |
60 MatrixType (MatrixType::Lower)); | |
61 } | |
62 | |
63 DEFUN_DLD (chol, args, nargout, | |
64 "-*- texinfo -*-\n\ | |
65 @deftypefn {Loadable Function} {@var{R} =} chol (@var{A})\n\ | |
66 @deftypefnx {Loadable Function} {[@var{R}, @var{p}] =} chol (@var{A})\n\ | |
67 @deftypefnx {Loadable Function} {[@var{R}, @var{p}, @var{Q}] =} chol (@var{S})\n\ | |
68 @deftypefnx {Loadable Function} {[@var{R}, @var{p}, @var{Q}] =} chol (@var{S}, \"vector\")\n\ | |
69 @deftypefnx {Loadable Function} {[@var{L}, @dots{}] =} chol (@dots{}, \"lower\")\n\ | |
70 @deftypefnx {Loadable Function} {[@var{L}, @dots{}] =} chol (@dots{}, \"upper\")\n\ | |
71 @cindex Cholesky factorization\n\ | |
72 Compute the Cholesky@tie{}factor, @var{R}, of the symmetric positive definite\n\ | |
73 matrix @var{A}, where\n\ | |
74 @tex\n\ | |
75 $ R^T R = A $.\n\ | |
76 @end tex\n\ | |
77 @ifnottex\n\ | |
78 \n\ | |
79 @example\n\ | |
80 @var{R}' * @var{R} = @var{A}.\n\ | |
81 @end example\n\ | |
82 \n\ | |
83 @end ifnottex\n\ | |
84 \n\ | |
85 Called with one output argument @code{chol} fails if @var{A} or @var{S} is\n\ | |
86 not positive definite. With two or more output arguments @var{p} flags\n\ | |
87 whether the matrix was positive definite and @code{chol} does not fail. A\n\ | |
88 zero value indicated that the matrix was positive definite and the @var{R}\n\ | |
89 gives the factorization, and @var{p} will have a positive value otherwise.\n\ | |
90 \n\ | |
91 If called with 3 outputs then a sparsity preserving row/column permutation\n\ | |
92 is applied to @var{A} prior to the factorization. That is @var{R}\n\ | |
93 is the factorization of @code{@var{A}(@var{Q},@var{Q})} such that\n\ | |
94 @tex\n\ | |
95 $ R^T R = Q^T A Q$.\n\ | |
96 @end tex\n\ | |
97 @ifnottex\n\ | |
98 \n\ | |
99 @example\n\ | |
100 @var{R}' * @var{R} = @var{Q}' * @var{A} * @var{Q}.\n\ | |
101 @end example\n\ | |
102 \n\ | |
103 @end ifnottex\n\ | |
104 \n\ | |
105 The sparsity preserving permutation is generally returned as a matrix.\n\ | |
106 However, given the flag \"vector\", @var{Q} will be returned as a vector\n\ | |
107 such that\n\ | |
108 @tex\n\ | |
109 $ R^T R = A (Q, Q)$.\n\ | |
110 @end tex\n\ | |
111 @ifnottex\n\ | |
112 \n\ | |
113 @example\n\ | |
114 @var{R}' * @var{R} = @var{A}(@var{Q}, @var{Q}).\n\ | |
115 @end example\n\ | |
116 \n\ | |
117 @end ifnottex\n\ | |
118 \n\ | |
119 Called with either a sparse or full matrix and using the \"lower\" flag,\n\ | |
120 @code{chol} returns the lower triangular factorization such that\n\ | |
121 @tex\n\ | |
122 $ L L^T = A $.\n\ | |
123 @end tex\n\ | |
124 @ifnottex\n\ | |
125 \n\ | |
126 @example\n\ | |
127 @var{L} * @var{L}' = @var{A}.\n\ | |
128 @end example\n\ | |
129 \n\ | |
130 @end ifnottex\n\ | |
131 \n\ | |
132 For full matrices, if the \"lower\" flag is set only the lower triangular\n\ | |
133 part of the matrix is used for the factorization, otherwise the upper\n\ | |
134 triangular part is used.\n\ | |
135 \n\ | |
136 In general the lower triangular factorization is significantly faster for\n\ | |
137 sparse matrices.\n\ | |
138 @seealso{cholinv, chol2inv}\n\ | |
139 @end deftypefn") | |
140 { | |
141 octave_value_list retval; | |
142 int nargin = args.length (); | |
143 bool LLt = false; | |
144 bool vecout = false; | |
145 | |
146 if (nargin < 1 || nargin > 3 || nargout > 3 | |
147 || (! args(0).is_sparse_type () && nargout > 2)) | |
148 { | |
149 print_usage (); | |
150 return retval; | |
151 } | |
152 | |
153 int n = 1; | |
154 while (n < nargin && ! error_state) | |
155 { | |
156 std::string tmp = args(n++).string_value (); | |
157 | |
158 if (! error_state ) | |
159 { | |
160 if (tmp.compare ("vector") == 0) | |
161 vecout = true; | |
162 else if (tmp.compare ("lower") == 0) | |
163 // FIXME currently the option "lower" is handled by transposing the | |
164 // matrix, factorizing it with the lapack function DPOTRF ('U', ...) | |
165 // and finally transposing the factor. It would be more efficient to use | |
166 // DPOTRF ('L', ...) in this case. | |
167 LLt = true; | |
168 else if (tmp.compare ("upper") == 0) | |
169 LLt = false; | |
170 else | |
171 error ("chol: unexpected second or third input"); | |
172 } | |
173 else | |
174 error ("chol: expecting trailing string arguments"); | |
175 } | |
176 | |
177 if (! error_state) | |
178 { | |
179 octave_value arg = args(0); | |
180 | |
181 octave_idx_type nr = arg.rows (); | |
182 octave_idx_type nc = arg.columns (); | |
183 bool natural = (nargout != 3); | |
184 | |
185 int arg_is_empty = empty_arg ("chol", nr, nc); | |
186 | |
187 if (arg_is_empty < 0) | |
188 return retval; | |
189 if (arg_is_empty > 0) | |
190 return octave_value (Matrix ()); | |
191 | |
192 if (arg.is_sparse_type ()) | |
193 { | |
194 if (arg.is_real_type ()) | |
195 { | |
196 SparseMatrix m = arg.sparse_matrix_value (); | |
197 | |
198 if (! error_state) | |
199 { | |
200 octave_idx_type info = nargout; | |
201 SparseCHOL fact (m, info, natural); | |
202 if (nargout == 3) | |
203 { | |
204 if (vecout) | |
205 retval(2) = fact.perm (); | |
206 else | |
207 retval(2) = fact.Q (); | |
208 } | |
209 | |
210 if (nargout > 1 || info == 0) | |
211 { | |
212 retval(1) = fact.P (); | |
213 if (LLt) | |
214 retval(0) = fact.L (); | |
215 else | |
216 retval(0) = fact.R (); | |
217 } | |
218 else | |
219 error ("chol: input matrix must be positive definite"); | |
220 } | |
221 } | |
222 else if (arg.is_complex_type ()) | |
223 { | |
224 SparseComplexMatrix m = arg.sparse_complex_matrix_value (); | |
225 | |
226 if (! error_state) | |
227 { | |
228 octave_idx_type info = nargout; | |
229 SparseComplexCHOL fact (m, info, natural); | |
230 | |
231 if (nargout == 3) | |
232 { | |
233 if (vecout) | |
234 retval(2) = fact.perm (); | |
235 else | |
236 retval(2) = fact.Q (); | |
237 } | |
238 | |
239 if (nargout > 1 || info == 0) | |
240 { | |
241 retval(1) = fact.P (); | |
242 if (LLt) | |
243 retval(0) = fact.L (); | |
244 else | |
245 retval(0) = fact.R (); | |
246 } | |
247 else | |
248 error ("chol: input matrix must be positive definite"); | |
249 } | |
250 } | |
251 else | |
252 gripe_wrong_type_arg ("chol", arg); | |
253 } | |
254 else if (arg.is_single_type ()) | |
255 { | |
256 if (arg.is_real_type ()) | |
257 { | |
258 FloatMatrix m = arg.float_matrix_value (); | |
259 | |
260 if (! error_state) | |
261 { | |
262 octave_idx_type info; | |
263 | |
264 FloatCHOL fact; | |
265 if (LLt) | |
266 fact = FloatCHOL (m.transpose (), info); | |
267 else | |
268 fact = FloatCHOL (m, info); | |
269 | |
270 if (nargout == 2 || info == 0) | |
271 { | |
272 retval(1) = info; | |
273 if (LLt) | |
274 retval(0) = get_chol_l (fact); | |
275 else | |
276 retval(0) = get_chol_r (fact); | |
277 } | |
278 else | |
279 error ("chol: input matrix must be positive definite"); | |
280 } | |
281 } | |
282 else if (arg.is_complex_type ()) | |
283 { | |
284 FloatComplexMatrix m = arg.float_complex_matrix_value (); | |
285 | |
286 if (! error_state) | |
287 { | |
288 octave_idx_type info; | |
289 | |
290 FloatComplexCHOL fact; | |
291 if (LLt) | |
292 fact = FloatComplexCHOL (m.transpose (), info); | |
293 else | |
294 fact = FloatComplexCHOL (m, info); | |
295 | |
296 if (nargout == 2 || info == 0) | |
297 { | |
298 retval(1) = info; | |
299 if (LLt) | |
300 retval(0) = get_chol_l (fact); | |
301 else | |
302 retval(0) = get_chol_r (fact); | |
303 } | |
304 else | |
305 error ("chol: input matrix must be positive definite"); | |
306 } | |
307 } | |
308 else | |
309 gripe_wrong_type_arg ("chol", arg); | |
310 } | |
311 else | |
312 { | |
313 if (arg.is_real_type ()) | |
314 { | |
315 Matrix m = arg.matrix_value (); | |
316 | |
317 if (! error_state) | |
318 { | |
319 octave_idx_type info; | |
320 | |
321 CHOL fact; | |
322 if (LLt) | |
323 fact = CHOL (m.transpose (), info); | |
324 else | |
325 fact = CHOL (m, info); | |
326 | |
327 if (nargout == 2 || info == 0) | |
328 { | |
329 retval(1) = info; | |
330 if (LLt) | |
331 retval(0) = get_chol_l (fact); | |
332 else | |
333 retval(0) = get_chol_r (fact); | |
334 } | |
335 else | |
336 error ("chol: input matrix must be positive definite"); | |
337 } | |
338 } | |
339 else if (arg.is_complex_type ()) | |
340 { | |
341 ComplexMatrix m = arg.complex_matrix_value (); | |
342 | |
343 if (! error_state) | |
344 { | |
345 octave_idx_type info; | |
346 | |
347 ComplexCHOL fact; | |
348 if (LLt) | |
349 fact = ComplexCHOL (m.transpose (), info); | |
350 else | |
351 fact = ComplexCHOL (m, info); | |
352 | |
353 if (nargout == 2 || info == 0) | |
354 { | |
355 retval(1) = info; | |
356 if (LLt) | |
357 retval(0) = get_chol_l (fact); | |
358 else | |
359 retval(0) = get_chol_r (fact); | |
360 } | |
361 else | |
362 error ("chol: input matrix must be positive definite"); | |
363 } | |
364 } | |
365 else | |
366 gripe_wrong_type_arg ("chol", arg); | |
367 } | |
368 } | |
369 | |
370 return retval; | |
371 } | |
372 | |
373 /* | |
374 %!assert (chol ([2, 1; 1, 1]), [sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)], sqrt (eps)) | |
375 %!assert (chol (single ([2, 1; 1, 1])), single ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)]), sqrt (eps ("single"))) | |
376 | |
377 %!error chol () | |
378 %!error <matrix must be positive definite> chol ([1, 2; 3, 4]) | |
379 %!error <requires square matrix> chol ([1, 2; 3, 4; 5, 6]) | |
380 %!error <unexpected second or third input> chol (1, 2) | |
381 */ | |
382 | |
383 DEFUN_DLD (cholinv, args, , | |
384 "-*- texinfo -*-\n\ | |
385 @deftypefn {Loadable Function} {} cholinv (@var{A})\n\ | |
386 Use the Cholesky@tie{}factorization to compute the inverse of the\n\ | |
387 symmetric positive definite matrix @var{A}.\n\ | |
388 @seealso{chol, chol2inv, inv}\n\ | |
389 @end deftypefn") | |
390 { | |
391 octave_value retval; | |
392 | |
393 int nargin = args.length (); | |
394 | |
395 if (nargin == 1) | |
396 { | |
397 octave_value arg = args(0); | |
398 | |
399 octave_idx_type nr = arg.rows (); | |
400 octave_idx_type nc = arg.columns (); | |
401 | |
402 if (nr == 0 || nc == 0) | |
403 retval = Matrix (); | |
404 else | |
405 { | |
406 if (arg.is_sparse_type ()) | |
407 { | |
408 if (arg.is_real_type ()) | |
409 { | |
410 SparseMatrix m = arg.sparse_matrix_value (); | |
411 | |
412 if (! error_state) | |
413 { | |
414 octave_idx_type info; | |
415 SparseCHOL chol (m, info); | |
416 if (info == 0) | |
417 retval = chol.inverse (); | |
418 else | |
419 error ("cholinv: A must be positive definite"); | |
420 } | |
421 } | |
422 else if (arg.is_complex_type ()) | |
423 { | |
424 SparseComplexMatrix m = arg.sparse_complex_matrix_value (); | |
425 | |
426 if (! error_state) | |
427 { | |
428 octave_idx_type info; | |
429 SparseComplexCHOL chol (m, info); | |
430 if (info == 0) | |
431 retval = chol.inverse (); | |
432 else | |
433 error ("cholinv: A must be positive definite"); | |
434 } | |
435 } | |
436 else | |
437 gripe_wrong_type_arg ("cholinv", arg); | |
438 } | |
439 else if (arg.is_single_type ()) | |
440 { | |
441 if (arg.is_real_type ()) | |
442 { | |
443 FloatMatrix m = arg.float_matrix_value (); | |
444 | |
445 if (! error_state) | |
446 { | |
447 octave_idx_type info; | |
448 FloatCHOL chol (m, info); | |
449 if (info == 0) | |
450 retval = chol.inverse (); | |
451 else | |
452 error ("cholinv: A must be positive definite"); | |
453 } | |
454 } | |
455 else if (arg.is_complex_type ()) | |
456 { | |
457 FloatComplexMatrix m = arg.float_complex_matrix_value (); | |
458 | |
459 if (! error_state) | |
460 { | |
461 octave_idx_type info; | |
462 FloatComplexCHOL chol (m, info); | |
463 if (info == 0) | |
464 retval = chol.inverse (); | |
465 else | |
466 error ("cholinv: A must be positive definite"); | |
467 } | |
468 } | |
469 else | |
470 gripe_wrong_type_arg ("chol", arg); | |
471 } | |
472 else | |
473 { | |
474 if (arg.is_real_type ()) | |
475 { | |
476 Matrix m = arg.matrix_value (); | |
477 | |
478 if (! error_state) | |
479 { | |
480 octave_idx_type info; | |
481 CHOL chol (m, info); | |
482 if (info == 0) | |
483 retval = chol.inverse (); | |
484 else | |
485 error ("cholinv: A must be positive definite"); | |
486 } | |
487 } | |
488 else if (arg.is_complex_type ()) | |
489 { | |
490 ComplexMatrix m = arg.complex_matrix_value (); | |
491 | |
492 if (! error_state) | |
493 { | |
494 octave_idx_type info; | |
495 ComplexCHOL chol (m, info); | |
496 if (info == 0) | |
497 retval = chol.inverse (); | |
498 else | |
499 error ("cholinv: A must be positive definite"); | |
500 } | |
501 } | |
502 else | |
503 gripe_wrong_type_arg ("chol", arg); | |
504 } | |
505 } | |
506 } | |
507 else | |
508 print_usage (); | |
509 | |
510 return retval; | |
511 } | |
512 | |
513 /* | |
514 %!shared A, Ainv | |
515 %! A = [2,0.2;0.2,1]; | |
516 %! Ainv = inv (A); | |
517 %!test | |
518 %! Ainv1 = cholinv (A); | |
519 %! assert (norm (Ainv-Ainv1), 0, 1e-10); | |
520 %!testif HAVE_CHOLMOD | |
521 %! Ainv2 = inv (sparse (A)); | |
522 %! assert (norm (Ainv-Ainv2), 0, 1e-10); | |
523 %!testif HAVE_CHOLMOD | |
524 %! Ainv3 = cholinv (sparse (A)); | |
525 %! assert (norm (Ainv-Ainv3), 0, 1e-10); | |
526 */ | |
527 | |
528 DEFUN_DLD (chol2inv, args, , | |
529 "-*- texinfo -*-\n\ | |
530 @deftypefn {Loadable Function} {} chol2inv (@var{U})\n\ | |
531 Invert a symmetric, positive definite square matrix from its Cholesky\n\ | |
532 decomposition, @var{U}. Note that @var{U} should be an upper-triangular\n\ | |
533 matrix with positive diagonal elements. @code{chol2inv (@var{U})}\n\ | |
534 provides @code{inv (@var{U}'*@var{U})} but it is much faster than\n\ | |
535 using @code{inv}.\n\ | |
536 @seealso{chol, cholinv, inv}\n\ | |
537 @end deftypefn") | |
538 { | |
539 octave_value retval; | |
540 | |
541 int nargin = args.length (); | |
542 | |
543 if (nargin == 1) | |
544 { | |
545 octave_value arg = args(0); | |
546 | |
547 octave_idx_type nr = arg.rows (); | |
548 octave_idx_type nc = arg.columns (); | |
549 | |
550 if (nr == 0 || nc == 0) | |
551 retval = Matrix (); | |
552 else | |
553 { | |
554 if (arg.is_sparse_type ()) | |
555 { | |
556 if (arg.is_real_type ()) | |
557 { | |
558 SparseMatrix r = arg.sparse_matrix_value (); | |
559 | |
560 if (! error_state) | |
561 retval = chol2inv (r); | |
562 } | |
563 else if (arg.is_complex_type ()) | |
564 { | |
565 SparseComplexMatrix r = arg.sparse_complex_matrix_value (); | |
566 | |
567 if (! error_state) | |
568 retval = chol2inv (r); | |
569 } | |
570 else | |
571 gripe_wrong_type_arg ("chol2inv", arg); | |
572 } | |
573 else if (arg.is_single_type ()) | |
574 { | |
575 if (arg.is_real_type ()) | |
576 { | |
577 FloatMatrix r = arg.float_matrix_value (); | |
578 | |
579 if (! error_state) | |
580 retval = chol2inv (r); | |
581 } | |
582 else if (arg.is_complex_type ()) | |
583 { | |
584 FloatComplexMatrix r = arg.float_complex_matrix_value (); | |
585 | |
586 if (! error_state) | |
587 retval = chol2inv (r); | |
588 } | |
589 else | |
590 gripe_wrong_type_arg ("chol2inv", arg); | |
591 | |
592 } | |
593 else | |
594 { | |
595 if (arg.is_real_type ()) | |
596 { | |
597 Matrix r = arg.matrix_value (); | |
598 | |
599 if (! error_state) | |
600 retval = chol2inv (r); | |
601 } | |
602 else if (arg.is_complex_type ()) | |
603 { | |
604 ComplexMatrix r = arg.complex_matrix_value (); | |
605 | |
606 if (! error_state) | |
607 retval = chol2inv (r); | |
608 } | |
609 else | |
610 gripe_wrong_type_arg ("chol2inv", arg); | |
611 } | |
612 } | |
613 } | |
614 else | |
615 print_usage (); | |
616 | |
617 return retval; | |
618 } | |
619 | |
620 DEFUN_DLD (cholupdate, args, nargout, | |
621 "-*- texinfo -*-\n\ | |
622 @deftypefn {Loadable Function} {[@var{R1}, @var{info}] =} cholupdate (@var{R}, @var{u}, @var{op})\n\ | |
623 Update or downdate a Cholesky@tie{}factorization. Given an upper triangular\n\ | |
624 matrix @var{R} and a column vector @var{u}, attempt to determine another\n\ | |
625 upper triangular matrix @var{R1} such that\n\ | |
626 \n\ | |
627 @itemize @bullet\n\ | |
628 @item\n\ | |
629 @var{R1}'*@var{R1} = @var{R}'*@var{R} + @var{u}*@var{u}'\n\ | |
630 if @var{op} is \"+\"\n\ | |
631 \n\ | |
632 @item\n\ | |
633 @var{R1}'*@var{R1} = @var{R}'*@var{R} - @var{u}*@var{u}'\n\ | |
634 if @var{op} is \"-\"\n\ | |
635 @end itemize\n\ | |
636 \n\ | |
637 If @var{op} is \"-\", @var{info} is set to\n\ | |
638 \n\ | |
639 @itemize\n\ | |
640 @item 0 if the downdate was successful,\n\ | |
641 \n\ | |
642 @item 1 if @var{R}'*@var{R} - @var{u}*@var{u}' is not positive definite,\n\ | |
643 \n\ | |
644 @item 2 if @var{R} is singular.\n\ | |
645 @end itemize\n\ | |
646 \n\ | |
647 If @var{info} is not present, an error message is printed in cases 1 and 2.\n\ | |
648 @seealso{chol, qrupdate}\n\ | |
649 @end deftypefn") | |
650 { | |
651 octave_idx_type nargin = args.length (); | |
652 | |
653 octave_value_list retval; | |
654 | |
655 if (nargin > 3 || nargin < 2) | |
656 { | |
657 print_usage (); | |
658 return retval; | |
659 } | |
660 | |
661 octave_value argr = args(0); | |
662 octave_value argu = args(1); | |
663 | |
664 if (argr.is_numeric_type () && argu.is_numeric_type () | |
665 && (nargin < 3 || args(2).is_string ())) | |
666 { | |
667 octave_idx_type n = argr.rows (); | |
668 | |
669 std::string op = (nargin < 3) ? "+" : args(2).string_value (); | |
670 | |
671 bool down = op == "-"; | |
672 | |
673 if (down || op == "+") | |
674 if (argr.columns () == n && argu.rows () == n && argu.columns () == 1) | |
675 { | |
676 int err = 0; | |
677 if (argr.is_single_type () || argu.is_single_type ()) | |
678 { | |
679 if (argr.is_real_type () && argu.is_real_type ()) | |
680 { | |
681 // real case | |
682 FloatMatrix R = argr.float_matrix_value (); | |
683 FloatColumnVector u = argu.float_column_vector_value (); | |
684 | |
685 FloatCHOL fact; | |
686 fact.set (R); | |
687 | |
688 if (down) | |
689 err = fact.downdate (u); | |
690 else | |
691 fact.update (u); | |
692 | |
693 retval(0) = get_chol_r (fact); | |
694 } | |
695 else | |
696 { | |
697 // complex case | |
698 FloatComplexMatrix R = argr.float_complex_matrix_value (); | |
699 FloatComplexColumnVector u = argu.float_complex_column_vector_value (); | |
700 | |
701 FloatComplexCHOL fact; | |
702 fact.set (R); | |
703 | |
704 if (down) | |
705 err = fact.downdate (u); | |
706 else | |
707 fact.update (u); | |
708 | |
709 retval(0) = get_chol_r (fact); | |
710 } | |
711 } | |
712 else | |
713 { | |
714 if (argr.is_real_type () && argu.is_real_type ()) | |
715 { | |
716 // real case | |
717 Matrix R = argr.matrix_value (); | |
718 ColumnVector u = argu.column_vector_value (); | |
719 | |
720 CHOL fact; | |
721 fact.set (R); | |
722 | |
723 if (down) | |
724 err = fact.downdate (u); | |
725 else | |
726 fact.update (u); | |
727 | |
728 retval(0) = get_chol_r (fact); | |
729 } | |
730 else | |
731 { | |
732 // complex case | |
733 ComplexMatrix R = argr.complex_matrix_value (); | |
734 ComplexColumnVector u = argu.complex_column_vector_value (); | |
735 | |
736 ComplexCHOL fact; | |
737 fact.set (R); | |
738 | |
739 if (down) | |
740 err = fact.downdate (u); | |
741 else | |
742 fact.update (u); | |
743 | |
744 retval(0) = get_chol_r (fact); | |
745 } | |
746 } | |
747 | |
748 if (nargout > 1) | |
749 retval(1) = err; | |
750 else if (err == 1) | |
751 error ("cholupdate: downdate violates positiveness"); | |
752 else if (err == 2) | |
753 error ("cholupdate: singular matrix"); | |
754 } | |
755 else | |
756 error ("cholupdate: dimension mismatch between R and U"); | |
757 else | |
758 error ("cholupdate: OP must be \"+\" or \"-\""); | |
759 } | |
760 else | |
761 print_usage (); | |
762 | |
763 return retval; | |
764 } | |
765 | |
766 /* | |
767 %!shared A, u, Ac, uc | |
768 %! A = [ 0.436997 -0.131721 0.124120 -0.061673 ; | |
769 %! -0.131721 0.738529 0.019851 -0.140295 ; | |
770 %! 0.124120 0.019851 0.354879 -0.059472 ; | |
771 %! -0.061673 -0.140295 -0.059472 0.600939 ]; | |
772 %! | |
773 %! u = [ 0.98950 ; | |
774 %! 0.39844 ; | |
775 %! 0.63484 ; | |
776 %! 0.13351 ]; | |
777 %! Ac = [ 0.5585528 + 0.0000000i -0.1662088 - 0.0315341i 0.0107873 + 0.0236411i -0.0276775 - 0.0186073i ; | |
778 %! -0.1662088 + 0.0315341i 0.6760061 + 0.0000000i 0.0011452 - 0.0475528i 0.0145967 + 0.0247641i ; | |
779 %! 0.0107873 - 0.0236411i 0.0011452 + 0.0475528i 0.6263149 - 0.0000000i -0.1585837 - 0.0719763i ; | |
780 %! -0.0276775 + 0.0186073i 0.0145967 - 0.0247641i -0.1585837 + 0.0719763i 0.6034234 - 0.0000000i ]; | |
781 %! | |
782 %! uc = [ 0.54267 + 0.91519i ; | |
783 %! 0.99647 + 0.43141i ; | |
784 %! 0.83760 + 0.68977i ; | |
785 %! 0.39160 + 0.90378i ]; | |
786 | |
787 %!test | |
788 %! R = chol (A); | |
789 %! R1 = cholupdate (R, u); | |
790 %! assert (norm (triu (R1)-R1, Inf), 0); | |
791 %! assert (norm (R1'*R1 - R'*R - u*u', Inf) < 1e1*eps); | |
792 %! | |
793 %! R1 = cholupdate (R1, u, "-"); | |
794 %! assert (norm (triu (R1)-R1, Inf), 0); | |
795 %! assert (norm (R1 - R, Inf) < 1e1*eps); | |
796 | |
797 %!test | |
798 %! R = chol (Ac); | |
799 %! R1 = cholupdate (R, uc); | |
800 %! assert (norm (triu (R1)-R1, Inf), 0); | |
801 %! assert (norm (R1'*R1 - R'*R - uc*uc', Inf) < 1e1*eps); | |
802 %! | |
803 %! R1 = cholupdate (R1, uc, "-"); | |
804 %! assert (norm (triu (R1)-R1, Inf), 0); | |
805 %! assert (norm (R1 - R, Inf) < 1e1*eps); | |
806 | |
807 %!test | |
808 %! R = chol (single (A)); | |
809 %! R1 = cholupdate (R, single (u)); | |
810 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
811 %! assert (norm (R1'*R1 - R'*R - single (u*u'), Inf) < 1e1*eps ("single")); | |
812 %! | |
813 %! R1 = cholupdate (R1, single (u), "-"); | |
814 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
815 %! assert (norm (R1 - R, Inf) < 2e1*eps ("single")); | |
816 | |
817 %!test | |
818 %! R = chol (single (Ac)); | |
819 %! R1 = cholupdate (R, single (uc)); | |
820 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
821 %! assert (norm (R1'*R1 - R'*R - single (uc*uc'), Inf) < 1e1*eps ("single")); | |
822 %! | |
823 %! R1 = cholupdate (R1, single (uc), "-"); | |
824 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
825 %! assert (norm (R1 - R, Inf) < 2e1*eps ("single")); | |
826 */ | |
827 | |
828 DEFUN_DLD (cholinsert, args, nargout, | |
829 "-*- texinfo -*-\n\ | |
830 @deftypefn {Loadable Function} {@var{R1} =} cholinsert (@var{R}, @var{j}, @var{u})\n\ | |
831 @deftypefnx {Loadable Function} {[@var{R1}, @var{info}] =} cholinsert (@var{R}, @var{j}, @var{u})\n\ | |
832 Given a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\n\ | |
833 positive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\n\ | |
834 triangular, return the Cholesky@tie{}factorization of\n\ | |
835 @var{A1}, where @w{A1(p,p) = A}, @w{A1(:,j) = A1(j,:)' = u} and\n\ | |
836 @w{p = [1:j-1,j+1:n+1]}. @w{u(j)} should be positive.\n\ | |
837 On return, @var{info} is set to\n\ | |
838 \n\ | |
839 @itemize\n\ | |
840 @item 0 if the insertion was successful,\n\ | |
841 \n\ | |
842 @item 1 if @var{A1} is not positive definite,\n\ | |
843 \n\ | |
844 @item 2 if @var{R} is singular.\n\ | |
845 @end itemize\n\ | |
846 \n\ | |
847 If @var{info} is not present, an error message is printed in cases 1 and 2.\n\ | |
848 @seealso{chol, cholupdate, choldelete}\n\ | |
849 @end deftypefn") | |
850 { | |
851 octave_idx_type nargin = args.length (); | |
852 | |
853 octave_value_list retval; | |
854 | |
855 if (nargin != 3) | |
856 { | |
857 print_usage (); | |
858 return retval; | |
859 } | |
860 | |
861 octave_value argr = args(0); | |
862 octave_value argj = args(1); | |
863 octave_value argu = args(2); | |
864 | |
865 if (argr.is_numeric_type () && argu.is_numeric_type () | |
866 && argj.is_real_scalar ()) | |
867 { | |
868 octave_idx_type n = argr.rows (); | |
869 octave_idx_type j = argj.scalar_value (); | |
870 | |
871 if (argr.columns () == n && argu.rows () == n+1 && argu.columns () == 1) | |
872 { | |
873 if (j > 0 && j <= n+1) | |
874 { | |
875 int err = 0; | |
876 if (argr.is_single_type () || argu.is_single_type ()) | |
877 { | |
878 if (argr.is_real_type () && argu.is_real_type ()) | |
879 { | |
880 // real case | |
881 FloatMatrix R = argr.float_matrix_value (); | |
882 FloatColumnVector u = argu.float_column_vector_value (); | |
883 | |
884 FloatCHOL fact; | |
885 fact.set (R); | |
886 err = fact.insert_sym (u, j-1); | |
887 | |
888 retval(0) = get_chol_r (fact); | |
889 } | |
890 else | |
891 { | |
892 // complex case | |
893 FloatComplexMatrix R = argr.float_complex_matrix_value (); | |
894 FloatComplexColumnVector u = argu.float_complex_column_vector_value (); | |
895 | |
896 FloatComplexCHOL fact; | |
897 fact.set (R); | |
898 err = fact.insert_sym (u, j-1); | |
899 | |
900 retval(0) = get_chol_r (fact); | |
901 } | |
902 } | |
903 else | |
904 { | |
905 if (argr.is_real_type () && argu.is_real_type ()) | |
906 { | |
907 // real case | |
908 Matrix R = argr.matrix_value (); | |
909 ColumnVector u = argu.column_vector_value (); | |
910 | |
911 CHOL fact; | |
912 fact.set (R); | |
913 err = fact.insert_sym (u, j-1); | |
914 | |
915 retval(0) = get_chol_r (fact); | |
916 } | |
917 else | |
918 { | |
919 // complex case | |
920 ComplexMatrix R = argr.complex_matrix_value (); | |
921 ComplexColumnVector u = argu.complex_column_vector_value (); | |
922 | |
923 ComplexCHOL fact; | |
924 fact.set (R); | |
925 err = fact.insert_sym (u, j-1); | |
926 | |
927 retval(0) = get_chol_r (fact); | |
928 } | |
929 } | |
930 | |
931 if (nargout > 1) | |
932 retval(1) = err; | |
933 else if (err == 1) | |
934 error ("cholinsert: insertion violates positiveness"); | |
935 else if (err == 2) | |
936 error ("cholinsert: singular matrix"); | |
937 else if (err == 3) | |
938 error ("cholinsert: diagonal element must be real"); | |
939 } | |
940 else | |
941 error ("cholinsert: index J out of range"); | |
942 } | |
943 else | |
944 error ("cholinsert: dimension mismatch between R and U"); | |
945 } | |
946 else | |
947 print_usage (); | |
948 | |
949 return retval; | |
950 } | |
951 | |
952 /* | |
953 %!test | |
954 %! u2 = [ 0.35080 ; | |
955 %! 0.63930 ; | |
956 %! 3.31057 ; | |
957 %! -0.13825 ; | |
958 %! 0.45266 ]; | |
959 %! | |
960 %! R = chol (A); | |
961 %! | |
962 %! j = 3; p = [1:j-1, j+1:5]; | |
963 %! R1 = cholinsert (R, j, u2); | |
964 %! A1 = R1'*R1; | |
965 %! | |
966 %! assert (norm (triu (R1)-R1, Inf), 0); | |
967 %! assert (norm (A1(p,p) - A, Inf) < 1e1*eps); | |
968 | |
969 %!test | |
970 %! u2 = [ 0.35080 + 0.04298i; | |
971 %! 0.63930 + 0.23778i; | |
972 %! 3.31057 + 0.00000i; | |
973 %! -0.13825 + 0.19879i; | |
974 %! 0.45266 + 0.50020i]; | |
975 %! | |
976 %! R = chol (Ac); | |
977 %! | |
978 %! j = 3; p = [1:j-1, j+1:5]; | |
979 %! R1 = cholinsert (R, j, u2); | |
980 %! A1 = R1'*R1; | |
981 %! | |
982 %! assert (norm (triu (R1)-R1, Inf), 0); | |
983 %! assert (norm (A1(p,p) - Ac, Inf) < 1e1*eps); | |
984 | |
985 %!test | |
986 %! u2 = single ([ 0.35080 ; | |
987 %! 0.63930 ; | |
988 %! 3.31057 ; | |
989 %! -0.13825 ; | |
990 %! 0.45266 ]); | |
991 %! | |
992 %! R = chol (single (A)); | |
993 %! | |
994 %! j = 3; p = [1:j-1, j+1:5]; | |
995 %! R1 = cholinsert (R, j, u2); | |
996 %! A1 = R1'*R1; | |
997 %! | |
998 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
999 %! assert (norm (A1(p,p) - A, Inf) < 1e1*eps ("single")); | |
1000 | |
1001 %!test | |
1002 %! u2 = single ([ 0.35080 + 0.04298i; | |
1003 %! 0.63930 + 0.23778i; | |
1004 %! 3.31057 + 0.00000i; | |
1005 %! -0.13825 + 0.19879i; | |
1006 %! 0.45266 + 0.50020i]); | |
1007 %! | |
1008 %! R = chol (single (Ac)); | |
1009 %! | |
1010 %! j = 3; p = [1:j-1, j+1:5]; | |
1011 %! R1 = cholinsert (R, j, u2); | |
1012 %! A1 = R1'*R1; | |
1013 %! | |
1014 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
1015 %! assert (norm (A1(p,p) - single (Ac), Inf) < 2e1*eps ("single")); | |
1016 | |
1017 %!test | |
1018 %! cu = chol (triu (A), "upper"); | |
1019 %! cl = chol (tril (A), "lower"); | |
1020 %! assert (cu, cl', eps); | |
1021 | |
1022 %!test | |
1023 %! cca = chol (Ac); | |
1024 %! | |
1025 %! ccal = chol (Ac, "lower"); | |
1026 %! ccal2 = chol (tril (Ac), "lower"); | |
1027 %! | |
1028 %! ccau = chol (Ac, "upper"); | |
1029 %! ccau2 = chol (triu (Ac), "upper"); | |
1030 %! | |
1031 %! assert (cca'*cca, Ac, eps); | |
1032 %! assert (ccau'*ccau, Ac, eps); | |
1033 %! assert (ccau2'*ccau2, Ac, eps); | |
1034 %! | |
1035 %! assert (cca, ccal', eps); | |
1036 %! assert (cca, ccau, eps); | |
1037 %! assert (cca, ccal2', eps); | |
1038 %! assert (cca, ccau2, eps); | |
1039 | |
1040 %!test | |
1041 %! cca = chol (single (Ac)); | |
1042 %! | |
1043 %! ccal = chol (single (Ac), "lower"); | |
1044 %! ccal2 = chol (tril (single (Ac)), "lower"); | |
1045 %! | |
1046 %! ccau = chol (single (Ac), "upper"); | |
1047 %! ccau2 = chol (triu (single (Ac)), "upper"); | |
1048 %! | |
1049 %! assert (cca'*cca, single (Ac), eps ("single")); | |
1050 %! assert (ccau'*ccau, single (Ac), eps ("single")); | |
1051 %! assert (ccau2'*ccau2, single (Ac), eps ("single")); | |
1052 %! | |
1053 %! assert (cca, ccal', eps ("single")); | |
1054 %! assert (cca, ccau, eps ("single")); | |
1055 %! assert (cca, ccal2', eps ("single")); | |
1056 %! assert (cca, ccau2, eps ("single")); | |
1057 | |
1058 %!test | |
1059 %! a = [12, 2, 3, 4; | |
1060 %! 2, 14, 5, 3; | |
1061 %! 3, 5, 16, 6; | |
1062 %! 4, 3, 6, 16]; | |
1063 %! | |
1064 %! b = [0, 1, 2, 3; | |
1065 %! -1, 0, 1, 2; | |
1066 %! -2, -1, 0, 1; | |
1067 %! -3, -2, -1, 0]; | |
1068 %! | |
1069 %! ca = a + i*b; | |
1070 %! | |
1071 %! cca = chol (ca); | |
1072 %! | |
1073 %! ccal = chol (ca, "lower"); | |
1074 %! ccal2 = chol (tril (ca), "lower"); | |
1075 %! | |
1076 %! ccau = chol (ca, "upper"); | |
1077 %! ccau2 = chol (triu (ca), "upper"); | |
1078 %! | |
1079 %! assert (cca'*cca, ca, 16*eps); | |
1080 %! assert (ccau'*ccau, ca, 16*eps); | |
1081 %! assert (ccau2'*ccau2, ca, 16*eps); | |
1082 %! | |
1083 %! assert (cca, ccal', 16*eps); | |
1084 %! assert (cca, ccau, 16*eps); | |
1085 %! assert (cca, ccal2', 16*eps); | |
1086 %! assert (cca, ccau2, 16*eps); | |
1087 */ | |
1088 | |
1089 DEFUN_DLD (choldelete, args, , | |
1090 "-*- texinfo -*-\n\ | |
1091 @deftypefn {Loadable Function} {@var{R1} =} choldelete (@var{R}, @var{j})\n\ | |
1092 Given a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\n\ | |
1093 positive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\n\ | |
1094 triangular, return the Cholesky@tie{}factorization of @w{A(p,p)}, where\n\ | |
1095 @w{p = [1:j-1,j+1:n+1]}.\n\ | |
1096 @seealso{chol, cholupdate, cholinsert}\n\ | |
1097 @end deftypefn") | |
1098 { | |
1099 octave_idx_type nargin = args.length (); | |
1100 | |
1101 octave_value_list retval; | |
1102 | |
1103 if (nargin != 2) | |
1104 { | |
1105 print_usage (); | |
1106 return retval; | |
1107 } | |
1108 | |
1109 octave_value argr = args(0); | |
1110 octave_value argj = args(1); | |
1111 | |
1112 if (argr.is_numeric_type () && argj.is_real_scalar ()) | |
1113 { | |
1114 octave_idx_type n = argr.rows (); | |
1115 octave_idx_type j = argj.scalar_value (); | |
1116 | |
1117 if (argr.columns () == n) | |
1118 { | |
1119 if (j > 0 && j <= n) | |
1120 { | |
1121 if (argr.is_single_type ()) | |
1122 { | |
1123 if (argr.is_real_type ()) | |
1124 { | |
1125 // real case | |
1126 FloatMatrix R = argr.float_matrix_value (); | |
1127 | |
1128 FloatCHOL fact; | |
1129 fact.set (R); | |
1130 fact.delete_sym (j-1); | |
1131 | |
1132 retval(0) = get_chol_r (fact); | |
1133 } | |
1134 else | |
1135 { | |
1136 // complex case | |
1137 FloatComplexMatrix R = argr.float_complex_matrix_value (); | |
1138 | |
1139 FloatComplexCHOL fact; | |
1140 fact.set (R); | |
1141 fact.delete_sym (j-1); | |
1142 | |
1143 retval(0) = get_chol_r (fact); | |
1144 } | |
1145 } | |
1146 else | |
1147 { | |
1148 if (argr.is_real_type ()) | |
1149 { | |
1150 // real case | |
1151 Matrix R = argr.matrix_value (); | |
1152 | |
1153 CHOL fact; | |
1154 fact.set (R); | |
1155 fact.delete_sym (j-1); | |
1156 | |
1157 retval(0) = get_chol_r (fact); | |
1158 } | |
1159 else | |
1160 { | |
1161 // complex case | |
1162 ComplexMatrix R = argr.complex_matrix_value (); | |
1163 | |
1164 ComplexCHOL fact; | |
1165 fact.set (R); | |
1166 fact.delete_sym (j-1); | |
1167 | |
1168 retval(0) = get_chol_r (fact); | |
1169 } | |
1170 } | |
1171 } | |
1172 else | |
1173 error ("choldelete: index J out of range"); | |
1174 } | |
1175 else | |
1176 error ("choldelete: matrix R must be square"); | |
1177 } | |
1178 else | |
1179 print_usage (); | |
1180 | |
1181 return retval; | |
1182 } | |
1183 | |
1184 /* | |
1185 %!test | |
1186 %! R = chol (A); | |
1187 %! | |
1188 %! j = 3; p = [1:j-1,j+1:4]; | |
1189 %! R1 = choldelete (R, j); | |
1190 %! | |
1191 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1192 %! assert (norm (R1'*R1 - A(p,p), Inf) < 1e1*eps); | |
1193 | |
1194 %!test | |
1195 %! R = chol (Ac); | |
1196 %! | |
1197 %! j = 3; p = [1:j-1,j+1:4]; | |
1198 %! R1 = choldelete (R, j); | |
1199 %! | |
1200 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1201 %! assert (norm (R1'*R1 - Ac(p,p), Inf) < 1e1*eps); | |
1202 | |
1203 %!test | |
1204 %! R = chol (single (A)); | |
1205 %! | |
1206 %! j = 3; p = [1:j-1,j+1:4]; | |
1207 %! R1 = choldelete (R, j); | |
1208 %! | |
1209 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
1210 %! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); | |
1211 | |
1212 %!test | |
1213 %! R = chol (single (Ac)); | |
1214 %! | |
1215 %! j = 3; p = [1:j-1,j+1:4]; | |
1216 %! R1 = choldelete (R,j); | |
1217 %! | |
1218 %! assert (norm (triu (R1)-R1, Inf), single (0)); | |
1219 %! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); | |
1220 */ | |
1221 | |
1222 DEFUN_DLD (cholshift, args, , | |
1223 "-*- texinfo -*-\n\ | |
1224 @deftypefn {Loadable Function} {@var{R1} =} cholshift (@var{R}, @var{i}, @var{j})\n\ | |
1225 Given a Cholesky@tie{}factorization of a real symmetric or complex Hermitian\n\ | |
1226 positive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper\n\ | |
1227 triangular, return the Cholesky@tie{}factorization of\n\ | |
1228 @w{@var{A}(p,p)}, where @w{p} is the permutation @*\n\ | |
1229 @code{p = [1:i-1, shift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*\n\ | |
1230 or @*\n\ | |
1231 @code{p = [1:j-1, shift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}. @*\n\ | |
1232 \n\ | |
1233 @seealso{chol, cholinsert, choldelete}\n\ | |
1234 @end deftypefn") | |
1235 { | |
1236 octave_idx_type nargin = args.length (); | |
1237 | |
1238 octave_value_list retval; | |
1239 | |
1240 if (nargin != 3) | |
1241 { | |
1242 print_usage (); | |
1243 return retval; | |
1244 } | |
1245 | |
1246 octave_value argr = args(0); | |
1247 octave_value argi = args(1); | |
1248 octave_value argj = args(2); | |
1249 | |
1250 if (argr.is_numeric_type () && argi.is_real_scalar () && argj.is_real_scalar ()) | |
1251 { | |
1252 octave_idx_type n = argr.rows (); | |
1253 octave_idx_type i = argi.scalar_value (); | |
1254 octave_idx_type j = argj.scalar_value (); | |
1255 | |
1256 if (argr.columns () == n) | |
1257 { | |
1258 if (j > 0 && j <= n+1 && i > 0 && i <= n+1) | |
1259 { | |
1260 | |
1261 if (argr.is_single_type () && argi.is_single_type () && | |
1262 argj.is_single_type ()) | |
1263 { | |
1264 if (argr.is_real_type ()) | |
1265 { | |
1266 // real case | |
1267 FloatMatrix R = argr.float_matrix_value (); | |
1268 | |
1269 FloatCHOL fact; | |
1270 fact.set (R); | |
1271 fact.shift_sym (i-1, j-1); | |
1272 | |
1273 retval(0) = get_chol_r (fact); | |
1274 } | |
1275 else | |
1276 { | |
1277 // complex case | |
1278 FloatComplexMatrix R = argr.float_complex_matrix_value (); | |
1279 | |
1280 FloatComplexCHOL fact; | |
1281 fact.set (R); | |
1282 fact.shift_sym (i-1, j-1); | |
1283 | |
1284 retval(0) = get_chol_r (fact); | |
1285 } | |
1286 } | |
1287 else | |
1288 { | |
1289 if (argr.is_real_type ()) | |
1290 { | |
1291 // real case | |
1292 Matrix R = argr.matrix_value (); | |
1293 | |
1294 CHOL fact; | |
1295 fact.set (R); | |
1296 fact.shift_sym (i-1, j-1); | |
1297 | |
1298 retval(0) = get_chol_r (fact); | |
1299 } | |
1300 else | |
1301 { | |
1302 // complex case | |
1303 ComplexMatrix R = argr.complex_matrix_value (); | |
1304 | |
1305 ComplexCHOL fact; | |
1306 fact.set (R); | |
1307 fact.shift_sym (i-1, j-1); | |
1308 | |
1309 retval(0) = get_chol_r (fact); | |
1310 } | |
1311 } | |
1312 } | |
1313 else | |
1314 error ("cholshift: index I or J is out of range"); | |
1315 } | |
1316 else | |
1317 error ("cholshift: R must be a square matrix"); | |
1318 } | |
1319 else | |
1320 print_usage (); | |
1321 | |
1322 return retval; | |
1323 } | |
1324 | |
1325 /* | |
1326 %!test | |
1327 %! R = chol (A); | |
1328 %! | |
1329 %! i = 1; j = 3; p = [1:i-1, shift(i:j,-1), j+1:4]; | |
1330 %! R1 = cholshift (R, i, j); | |
1331 %! | |
1332 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1333 %! assert (norm (R1'*R1 - A(p,p), Inf) < 1e1*eps); | |
1334 %! | |
1335 %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; | |
1336 %! R1 = cholshift (R, i, j); | |
1337 %! | |
1338 %! assert (norm (triu (R1) - R1, Inf), 0); | |
1339 %! assert (norm (R1'*R1 - A(p,p), Inf) < 1e1*eps); | |
1340 | |
1341 %!test | |
1342 %! R = chol (Ac); | |
1343 %! | |
1344 %! i = 1; j = 3; p = [1:i-1, shift(i:j,-1), j+1:4]; | |
1345 %! R1 = cholshift (R, i, j); | |
1346 %! | |
1347 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1348 %! assert (norm (R1'*R1 - Ac(p,p), Inf) < 1e1*eps); | |
1349 %! | |
1350 %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; | |
1351 %! R1 = cholshift (R, i, j); | |
1352 %! | |
1353 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1354 %! assert (norm (R1'*R1 - Ac(p,p), Inf) < 1e1*eps); | |
1355 | |
1356 %!test | |
1357 %! R = chol (single (A)); | |
1358 %! | |
1359 %! i = 1; j = 3; p = [1:i-1, shift(i:j,-1), j+1:4]; | |
1360 %! R1 = cholshift (R, i, j); | |
1361 %! | |
1362 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1363 %! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); | |
1364 %! | |
1365 %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; | |
1366 %! R1 = cholshift (R, i, j); | |
1367 %! | |
1368 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1369 %! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); | |
1370 | |
1371 %!test | |
1372 %! R = chol (single (Ac)); | |
1373 %! | |
1374 %! i = 1; j = 3; p = [1:i-1, shift(i:j,-1), j+1:4]; | |
1375 %! R1 = cholshift (R, i, j); | |
1376 %! | |
1377 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1378 %! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); | |
1379 %! | |
1380 %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; | |
1381 %! R1 = cholshift (R, i, j); | |
1382 %! | |
1383 %! assert (norm (triu (R1)-R1, Inf), 0); | |
1384 %! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); | |
1385 */ |