| | 686 | /** RowRankProfile |
| | 687 | * Computes the row rank profile of A. |
| | 688 | * |
| | 689 | * @param A: input matrix of dimension |
| | 690 | * @param rklprofile: return the rank profile as an array of row indexes, of dimension r=rank(A) |
| | 691 | * |
| | 692 | * rkprofile is allocated during the computation. |
| | 693 | * Returns R |
| | 694 | */ |
| | 695 | template <class Field> |
| | 696 | static size_t RowRankProfile (const Field& F, const size_t M, const size_t N, |
| | 697 | typename Field::Element* A, const size_t lda, size_t* rkprofile){ |
| | 698 | size_t *P = new size_t[N]; |
| | 699 | size_t *Q = new size_t[M]; |
| | 700 | size_t R; |
| | 701 | |
| | 702 | R = LUdivine (F, FflasNonUnit, FflasNoTrans, M, N, A, lda, P, Q); |
| | 703 | rkprofile = new size_t[R]; |
| | 704 | |
| | 705 | for (size_t i=0; i<R; ++i) |
| | 706 | rkprofile[i] = Q[i]; |
| | 707 | delete[] P; |
| | 708 | delete[] Q; |
| | 709 | return R; |
| | 710 | } |
| | 711 | |
| | 712 | /** ColumnRankProfile |
| | 713 | * Computes the column rank profile of A. |
| | 714 | * |
| | 715 | * @param A: input matrix of dimension |
| | 716 | * @param rklprofile: return the rank profile as an array of row indexes, of dimension r=rank(A) |
| | 717 | * |
| | 718 | * A is modified |
| | 719 | * rkprofile is allocated during the computation. |
| | 720 | * Returns R |
| | 721 | */ |
| | 722 | template <class Field> |
| | 723 | static size_t ColumnRankProfile (const Field& F, const size_t M, const size_t N, |
| | 724 | typename Field::Element* A, const size_t lda, size_t* rkprofile){ |
| | 725 | size_t *P = new size_t[N]; |
| | 726 | size_t *Q = new size_t[M]; |
| | 727 | size_t R; |
| | 728 | |
| | 729 | R = LUdivine (F, FflasNonUnit, FflasTrans, M, N, A, lda, P, Q); |
| | 730 | rkprofile = new size_t[R]; |
| | 731 | |
| | 732 | for (size_t i=0; i<R; ++i) |
| | 733 | rkprofile[i] = Q[i]; |
| | 734 | delete[] P; |
| | 735 | delete[] Q; |
| | 736 | return R; |
| | 737 | } |
| | 738 | |
| | 739 | /** RowRankProfileSubmatrixIndices |
| | 740 | * Computes the indices of the submatrix r*r X of A whose rows correspond to |
| | 741 | * the row rank profile of A. |
| | 742 | * |
| | 743 | * @param A: input matrix of dimension |
| | 744 | * @param rowindices: array of the row indices of X in A |
| | 745 | * @param colindices: array of the col indices of X in A |
| | 746 | * |
| | 747 | * rowindices and colindices are allocated during the computation. |
| | 748 | * A is modified |
| | 749 | * Returns R |
| | 750 | */ |
| | 751 | template <class Field> |
| | 752 | static size_t RowRankProfileSubmatrixIndices (const Field& F, |
| | 753 | const size_t M, const size_t N, |
| | 754 | typename Field::Element* A, |
| | 755 | const size_t lda, |
| | 756 | size_t*& rowindices, |
| | 757 | size_t*& colindices, |
| | 758 | size_t& R){ |
| | 759 | size_t *P = new size_t[N]; |
| | 760 | size_t *Q = new size_t[M]; |
| | 761 | |
| | 762 | R = LUdivine (F, FflasNonUnit, FflasNoTrans, M, N, A, lda, P, Q); |
| | 763 | rowindices = new size_t[M]; |
| | 764 | colindices = new size_t[N]; |
| | 765 | for (size_t i=0; i<R; ++i){ |
| | 766 | rowindices [i] = Q [i]; |
| | 767 | } |
| | 768 | for (size_t i=0; i<N; ++i) |
| | 769 | colindices [i] = i; |
| | 770 | size_t tmp; |
| | 771 | for (size_t i=0; i<R; ++i){ |
| | 772 | if (i != P[i]){ |
| | 773 | tmp = colindices[i]; |
| | 774 | colindices[i] = colindices[P[i]]; |
| | 775 | colindices[P[i]] = tmp; |
| | 776 | } |
| | 777 | } |
| | 778 | |
| | 779 | delete[] P; |
| | 780 | delete[] Q; |
| | 781 | |
| | 782 | return R; |
| | 783 | } |
| | 784 | |
| | 785 | /** ColRankProfileSubmatrixIndices |
| | 786 | * Computes the indices of the submatrix r*r X of A whose columns correspond to |
| | 787 | * the column rank profile of A. |
| | 788 | * |
| | 789 | * @param A: input matrix of dimension |
| | 790 | * @param rowindices: array of the row indices of X in A |
| | 791 | * @param colindices: array of the col indices of X in A |
| | 792 | * |
| | 793 | * rowindices and colindices are allocated during the computation. |
| | 794 | * A is modified |
| | 795 | * Returns R |
| | 796 | */ |
| | 797 | template <class Field> |
| | 798 | static size_t ColRankProfileSubmatrixIndices (const Field& F, |
| | 799 | const size_t M, const size_t N, |
| | 800 | typename Field::Element* A, |
| | 801 | const size_t lda, |
| | 802 | size_t*& rowindices, |
| | 803 | size_t*& colindices, |
| | 804 | size_t& R){ |
| | 805 | size_t *P = new size_t[M]; |
| | 806 | size_t *Q = new size_t[N]; |
| | 807 | |
| | 808 | R = LUdivine (F, FflasNonUnit, FflasTrans, M, N, A, lda, P, Q); |
| | 809 | rowindices = new size_t[M]; |
| | 810 | colindices = new size_t[N]; |
| | 811 | for (size_t i=0; i<R; ++i) |
| | 812 | colindices [i] = Q [i]; |
| | 813 | |
| | 814 | for (size_t i=0; i<N; ++i) |
| | 815 | rowindices [i] = i; |
| | 816 | |
| | 817 | size_t tmp; |
| | 818 | for (size_t i=0; i<R; ++i){ |
| | 819 | if (i != P[i]){ |
| | 820 | tmp = rowindices[i]; |
| | 821 | rowindices[i] = rowindices[P[i]]; |
| | 822 | rowindices[P[i]] = tmp; |
| | 823 | } |
| | 824 | } |
| | 825 | delete[] P; |
| | 826 | delete[] Q; |
| | 827 | |
| | 828 | return R; |
| | 829 | } |
| | 830 | |
| | 831 | /** RowRankProfileSubmatrix |
| | 832 | * Compute the r*r submatrix X of A, by picking the row rank profile rows of A |
| | 833 | * |
| | 834 | * @param A: input matrix of dimension M x N |
| | 835 | * @param X: the output matrix |
| | 836 | * |
| | 837 | * A is not modified |
| | 838 | * X is allocated during the computation. |
| | 839 | * Returns R |
| | 840 | */ |
| | 841 | template <class Field> |
| | 842 | static size_t RowRankProfileSubmatrix (const Field& F, |
| | 843 | const size_t M, const size_t N, |
| | 844 | typename Field::Element* A, |
| | 845 | const size_t lda, |
| | 846 | typename Field::Element*& X, size_t& R){ |
| | 847 | |
| | 848 | size_t * rowindices, * colindices; |
| | 849 | |
| | 850 | typename Field::Element * A2 = MatCopy (F, M, N, A, lda); |
| | 851 | |
| | 852 | RowRankProfileSubmatrixIndices (F, M, N, A2, N, rowindices, colindices, R); |
| | 853 | |
| | 854 | X = new typename Field::Element[R*R]; |
| | 855 | for (size_t i=0; i<R; ++i) |
| | 856 | for (size_t j=0; j<R; ++j) |
| | 857 | F.assign (*(X + i*R + j), *(A + rowindices[i]*lda + colindices[j])); |
| | 858 | delete[] A2; |
| | 859 | delete[] rowindices; |
| | 860 | delete[] colindices; |
| | 861 | return R; |
| | 862 | } |
| | 863 | |
| | 864 | |
| | 865 | /** ColRankProfileSubmatrix |
| | 866 | * Compute the r*r submatrix X of A, by picking the row rank profile rows of A |
| | 867 | * |
| | 868 | * @param A: input matrix of dimension M x N |
| | 869 | * @param X: the output matrix |
| | 870 | * |
| | 871 | * A is not modified |
| | 872 | * X is allocated during the computation. |
| | 873 | * Returns R |
| | 874 | */ |
| | 875 | |
| | 876 | template <class Field> |
| | 877 | static size_t ColRankProfileSubmatrix (const Field& F, const size_t M, const size_t N, |
| | 878 | typename Field::Element* A, const size_t lda, |
| | 879 | typename Field::Element*& X, size_t& R){ |
| | 880 | |
| | 881 | size_t * rowindices, * colindices; |
| | 882 | |
| | 883 | typename Field::Element * A2 = MatCopy (F, M, N, A, lda); |
| | 884 | |
| | 885 | ColRankProfileSubmatrixIndices (F, M, N, A2, N, rowindices, colindices, R); |
| | 886 | |
| | 887 | X = new typename Field::Element[R*R]; |
| | 888 | for (size_t i=0; i<R; ++i) |
| | 889 | for (size_t j=0; j<R; ++j) |
| | 890 | F.assign (*(X + i*R + j), *(A + rowindices[i]*lda + colindices[j])); |
| | 891 | delete[] A2; |
| | 892 | delete[] colindices; |
| | 893 | delete[] rowindices; |
| | 894 | return R; |
| | 895 | } |
| | 896 | |
| | 897 | |