| 486 | | ftrmm (F, FflasRight, FflasLower, FflasNoTrans, FflasNonUnit, N1, N2, one, A + N1*(lda+1), lda, A + N1, lda); |
| 487 | | |
| 488 | | ftrmm (F, FflasLeft, FflasUpper, FflasNoTrans, FflasUnit, N2, N1, one, A + N1*(lda+1), lda, A + N1*lda, lda); |
| 489 | | |
| 490 | | ftrtrm (F, N2, A + N1*(lda+1), lda); |
| | 487 | ftrmm (F, FflasRight, FflasLower, FflasNoTrans, (diag == FflasUnit) ? FflasNonUnit : FflasUnit, N1, N2, one, A + N1*(lda+1), lda, A + N1, lda); |
| | 488 | |
| | 489 | ftrmm (F, FflasLeft, FflasUpper, FflasNoTrans, diag, N2, N1, one, A + N1*(lda+1), lda, A + N1*lda, lda); |
| | 490 | |
| | 491 | ftrtrm (F, diag, N2, A + N1*(lda+1), lda); |
| 516 | | r = LUdivine (F, FflasUnit, M, N, A, lda, P, Qt); |
| | 517 | r = LUdivine (F, FflasUnit, FflasNoTrans, M, N, A, lda, P, Qt); |
| | 529 | |
| | 530 | t2.stop(); |
| | 531 | //cerr<<"U^-1 --> "<<t2.usertime()<<endl; |
| | 532 | |
| | 533 | return r; |
| | 534 | } |
| | 535 | |
| | 536 | /** |
| | 537 | * Compute the Row Echelon form of the input matrix in-place. |
| | 538 | * |
| | 539 | * After the computation A = [ L \ M ] such that L A = R is a column echelon |
| | 540 | * decomposition of A, with L = [ L+Ir 0 ] P and R = M |
| | 541 | * [ In-r ] |
| | 542 | * Qt = Q^T |
| | 543 | */ |
| | 544 | template <class Field> |
| | 545 | static size_t |
| | 546 | RowEchelonForm (const Field& F, const size_t M, const size_t N, |
| | 547 | typename Field::Element * A, const size_t lda, |
| | 548 | size_t* P, size_t* Qt){ |
| | 549 | |
| | 550 | typename Field::Element one, mone; |
| | 551 | F.init (one, 1.0); |
| | 552 | F.neg (mone, one); |
| | 553 | size_t r; |
| | 554 | |
| | 555 | Timer t1; |
| | 556 | t1.clear(); |
| | 557 | t1.start(); |
| | 558 | r = LUdivine (F, FflasUnit, FflasTrans, M, N, A, lda, P, Qt); |
| | 559 | t1.stop(); |
| | 560 | //cerr<<"LU --> "<<t1.usertime()<<endl; |
| | 561 | |
| | 562 | Timer t2; |
| | 563 | t2.clear(); |
| | 564 | t2.start(); |
| | 565 | ftrtri (F, FflasLower, FflasUnit, r, A, lda); |
| | 566 | |
| | 567 | |
| | 568 | ftrmm (F, FflasRight, FflasLower, FflasNoTrans, FflasUnit, M-r, r, |
| | 569 | mone, A, lda, A+r*lda, lda); |
| 575 | | ftrtrm (F, r, A, lda); |
| | 617 | ftrtrm (F, FflasUnit, r, A, lda); |
| | 618 | t1.stop(); |
| | 619 | //cerr<<"U^-1L^-1 --> "<<t1.usertime()<<endl; |
| | 620 | |
| | 621 | return r; |
| | 622 | |
| | 623 | } |
| | 624 | |
| | 625 | /** |
| | 626 | * Compute the Reduced Row Echelon form of the input matrix in-place. |
| | 627 | * |
| | 628 | * After the computation A = [ V ] such that L A = R is a reduced row echelon |
| | 629 | * [ M 0 ] |
| | 630 | * decomposition of A, where L = [ V ] P^T and R = [ Ir M ] Q |
| | 631 | * [ 0 In-r ] [ 0 ] |
| | 632 | * Qt = Q^T |
| | 633 | */ |
| | 634 | template <class Field> |
| | 635 | static size_t |
| | 636 | ReducedRowEchelonForm (const Field& F, const size_t M, const size_t N, |
| | 637 | typename Field::Element * A, const size_t lda, |
| | 638 | size_t* P, size_t* Qt){ |
| | 639 | |
| | 640 | typename Field::Element one, mone; |
| | 641 | F.init (one, 1.0); |
| | 642 | F.neg (mone, one); |
| | 643 | size_t r; |
| | 644 | |
| | 645 | r = RowEchelonForm (F, M, N, A, lda, P, Qt); |
| | 646 | |
| | 647 | Timer t1; |
| | 648 | t1.clear(); |
| | 649 | t1.start(); |
| | 650 | // M = M Q^T |
| | 651 | for (int i=0; i<r; ++i){ |
| | 652 | if ( Qt[i]> (size_t) i ){ |
| | 653 | fswap( F, i+1, |
| | 654 | A + Qt[i], lda, |
| | 655 | A + i, lda ); |
| | 656 | } |
| | 657 | } |
| | 658 | |
| | 659 | ftrtri (F, FflasUpper, FflasNonUnit, r, A, lda); |
| | 660 | |
| | 661 | ftrmm (F, FflasLeft, FflasUpper, FflasNoTrans, FflasNonUnit, r, N-r, |
| | 662 | one, A, lda, A+r, lda); |
| | 663 | |
| | 664 | ftrtrm (F, FflasNonUnit, r, A, lda); |
| | 665 | |