comparison liboctave/fCmplxQR.cc @ 8562:a6edd5c23cb5

use replacement methods if qrupdate is not available
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 22 Jan 2009 11:10:47 +0100
parents d66c9b6e506a
children c86718093c1b
comparison
equal deleted inserted replaced
8561:66165de2cc42 8562:a6edd5c23cb5
166 } 166 }
167 } 167 }
168 168
169 FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& q_arg, const FloatComplexMatrix& r_arg) 169 FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& q_arg, const FloatComplexMatrix& r_arg)
170 { 170 {
171 if (q_arg.columns () != r_arg.rows ()) 171 octave_idx_type qr = q_arg.rows (), qc = q_arg.columns ();
172 { 172 octave_idx_type rr = r_arg.rows (), rc = r_arg.columns ();
173 (*current_liboctave_error_handler) ("QR dimensions mismatch"); 173 if (qc == rr && (qr == qc || (qr > qc && rr == rc)))
174 return; 174 {
175 } 175 q = q_arg;
176 176 r = r_arg;
177 this->q = q_arg; 177 }
178 this->r = r_arg; 178 else
179 (*current_liboctave_error_handler) ("QR dimensions mismatch");
180 }
181
182 QR::type
183 FloatComplexQR::get_type (void) const
184 {
185 QR::type retval;
186 if (!q.is_empty () && q.is_square ())
187 retval = QR::std;
188 else if (q.rows () > q.columns () && r.is_square ())
189 retval = QR::economy;
190 else
191 retval = QR::raw;
192 return retval;
179 } 193 }
180 194
181 #ifdef HAVE_QRUPDATE 195 #ifdef HAVE_QRUPDATE
182 196
183 void 197 void
194 OCTAVE_LOCAL_BUFFER (float, rw, k); 208 OCTAVE_LOCAL_BUFFER (float, rw, k);
195 F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, 209 F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
196 utmp.fortran_vec (), vtmp.fortran_vec (), w, rw)); 210 utmp.fortran_vec (), vtmp.fortran_vec (), w, rw));
197 } 211 }
198 else 212 else
199 (*current_liboctave_error_handler) ("QR update dimensions mismatch"); 213 (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
200 } 214 }
201 215
202 void 216 void
203 FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v) 217 FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v)
204 { 218 {
428 r.fortran_vec (), r.rows (), 442 r.fortran_vec (), r.rows (),
429 i + 1, j + 1, w, rw)); 443 i + 1, j + 1, w, rw));
430 } 444 }
431 } 445 }
432 446
447 #else
448
449 // Replacement update methods.
450
451 void
452 FloatComplexQR::update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v)
453 {
454 warn_qrupdate_once ();
455
456 octave_idx_type m = q.rows ();
457 octave_idx_type n = r.columns ();
458
459 if (u.length () == m && v.length () == n)
460 {
461 init(q*r + FloatComplexMatrix (u) * FloatComplexMatrix (v).hermitian (), get_type ());
462 }
463 else
464 (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
465 }
466
467 void
468 FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v)
469 {
470 warn_qrupdate_once ();
471
472 octave_idx_type m = q.rows ();
473 octave_idx_type n = r.columns ();
474
475 if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
476 {
477 init(q*r + u * v.hermitian (), get_type ());
478 }
479 else
480 (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
481 }
482
483 static
484 FloatComplexMatrix insert_col (const FloatComplexMatrix& a, octave_idx_type i,
485 const FloatComplexColumnVector& x)
486 {
487 FloatComplexMatrix retval (a.rows (), a.columns () + 1);
488 retval.assign (idx_vector::colon, idx_vector (0, i),
489 a.index (idx_vector::colon, idx_vector (0, i)));
490 retval.assign (idx_vector::colon, idx_vector (i), x);
491 retval.assign (idx_vector::colon, idx_vector (i+1, retval.columns ()),
492 a.index (idx_vector::colon, idx_vector (i, a.columns ())));
493 return retval;
494 }
495
496 static
497 FloatComplexMatrix insert_row (const FloatComplexMatrix& a, octave_idx_type i,
498 const FloatComplexRowVector& x)
499 {
500 FloatComplexMatrix retval (a.rows () + 1, a.columns ());
501 retval.assign (idx_vector (0, i), idx_vector::colon,
502 a.index (idx_vector (0, i), idx_vector::colon));
503 retval.assign (idx_vector (i), idx_vector::colon, x);
504 retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon,
505 a.index (idx_vector (i, a.rows ()), idx_vector::colon));
506 return retval;
507 }
508
509 static
510 FloatComplexMatrix delete_col (const FloatComplexMatrix& a, octave_idx_type i)
511 {
512 FloatComplexMatrix retval = a;
513 retval.delete_elements (1, idx_vector (i));
514 return retval;
515 }
516
517 static
518 FloatComplexMatrix delete_row (const FloatComplexMatrix& a, octave_idx_type i)
519 {
520 FloatComplexMatrix retval = a;
521 retval.delete_elements (0, idx_vector (i));
522 return retval;
523 }
524
525 static
526 FloatComplexMatrix shift_cols (const FloatComplexMatrix& a,
527 octave_idx_type i, octave_idx_type j)
528 {
529 octave_idx_type n = a.columns ();
530 Array<octave_idx_type> p (n);
531 for (octave_idx_type k = 0; k < n; k++) p(k) = k;
532 if (i < j)
533 {
534 for (octave_idx_type k = i; k < j; k++) p(k) = k+1;
535 p(j) = i;
536 }
537 else if (j < i)
538 {
539 p(j) = i;
540 for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;
541 }
542
543 return a.index (idx_vector::colon, idx_vector (p));
544 }
545
546 void
547 FloatComplexQR::insert_col (const FloatComplexColumnVector& u, octave_idx_type j)
548 {
549 warn_qrupdate_once ();
550
551 octave_idx_type m = q.rows ();
552 octave_idx_type n = r.columns ();
553
554 if (u.length () != m)
555 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
556 else if (j < 0 || j > n)
557 (*current_liboctave_error_handler) ("qrinsert: index out of range");
558 else
559 {
560 init (::insert_col (q*r, j, u), get_type ());
561 }
562 }
563
564 void
565 FloatComplexQR::insert_col (const FloatComplexMatrix& u, const Array<octave_idx_type>& j)
566 {
567 warn_qrupdate_once ();
568
569 octave_idx_type m = q.rows ();
570 octave_idx_type n = r.columns ();
571
572 Array<octave_idx_type> jsi;
573 Array<octave_idx_type> js = j.sort (jsi, ASCENDING);
574 octave_idx_type nj = js.length ();
575 bool dups = false;
576 for (octave_idx_type i = 0; i < nj - 1; i++)
577 dups = dups && js(i) == js(i+1);
578
579 if (dups)
580 (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
581 else if (u.length () != m || u.columns () != nj)
582 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
583 else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
584 (*current_liboctave_error_handler) ("qrinsert: index out of range");
585 else if (nj > 0)
586 {
587 FloatComplexMatrix a = q*r;
588 for (octave_idx_type i = 0; i < js.length (); i++)
589 a = ::insert_col (a, js(i), u.column (i));
590 init (a, get_type ());
591 }
592 }
593
594 void
595 FloatComplexQR::delete_col (octave_idx_type j)
596 {
597 warn_qrupdate_once ();
598
599 octave_idx_type m = q.rows ();
600 octave_idx_type n = r.columns ();
601
602 if (j < 0 || j > n-1)
603 (*current_liboctave_error_handler) ("qrdelete: index out of range");
604 else
605 {
606 init (::delete_col (q*r, j), get_type ());
607 }
608 }
609
610 void
611 FloatComplexQR::delete_col (const Array<octave_idx_type>& j)
612 {
613 warn_qrupdate_once ();
614
615 octave_idx_type m = q.rows ();
616 octave_idx_type n = r.columns ();
617
618 Array<octave_idx_type> jsi;
619 Array<octave_idx_type> js = j.sort (jsi, DESCENDING);
620 octave_idx_type nj = js.length ();
621 bool dups = false;
622 for (octave_idx_type i = 0; i < nj - 1; i++)
623 dups = dups && js(i) == js(i+1);
624
625 if (dups)
626 (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
627 else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
628 (*current_liboctave_error_handler) ("qrinsert: index out of range");
629 else if (nj > 0)
630 {
631 FloatComplexMatrix a = q*r;
632 for (octave_idx_type i = 0; i < js.length (); i++)
633 a = ::delete_col (a, js(i));
634 init (a, get_type ());
635 }
636 }
637
638 void
639 FloatComplexQR::insert_row (const FloatComplexRowVector& u, octave_idx_type j)
640 {
641 warn_qrupdate_once ();
642
643 octave_idx_type m = r.rows ();
644 octave_idx_type n = r.columns ();
645
646 if (! q.is_square () || u.length () != n)
647 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
648 else if (j < 0 || j > m)
649 (*current_liboctave_error_handler) ("qrinsert: index out of range");
650 else
651 {
652 init (::insert_row (q*r, j, u), get_type ());
653 }
654 }
655
656 void
657 FloatComplexQR::delete_row (octave_idx_type j)
658 {
659 warn_qrupdate_once ();
660
661 octave_idx_type m = r.rows ();
662 octave_idx_type n = r.columns ();
663
664 if (! q.is_square ())
665 (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
666 else if (j < 0 || j > m-1)
667 (*current_liboctave_error_handler) ("qrdelete: index out of range");
668 else
669 {
670 init (::delete_row (q*r, j), get_type ());
671 }
672 }
673
674 void
675 FloatComplexQR::shift_cols (octave_idx_type i, octave_idx_type j)
676 {
677 warn_qrupdate_once ();
678
679 octave_idx_type m = q.rows ();
680 octave_idx_type n = r.columns ();
681
682 if (i < 0 || i > n-1 || j < 0 || j > n-1)
683 (*current_liboctave_error_handler) ("qrshift: index out of range");
684 else
685 {
686 init (::shift_cols (q*r, i, j), get_type ());
687 }
688 }
689
433 #endif 690 #endif
434 691
435 /* 692 /*
436 ;;; Local Variables: *** 693 ;;; Local Variables: ***
437 ;;; mode: C++ *** 694 ;;; mode: C++ ***