Mercurial > jwe > octave
comparison liboctave/array/dSparse.cc @ 21136:7cac4e7458f2
maint: clean up code around calls to current_liboctave_error_handler.
Remove statements after call to handler that are no longer reachable.
Place input validation first and immediately call handler if necessary.
Change if/error_handler/else to if/error_handler and re-indent code.
* Array-util.cc, Array.cc, CColVector.cc, CDiagMatrix.cc, CMatrix.cc,
CNDArray.cc, CRowVector.cc, CSparse.cc, DiagArray2.cc, MArray.cc,
PermMatrix.cc, Sparse.cc, Sparse.h, chMatrix.cc, chNDArray.cc, dColVector.cc,
dDiagMatrix.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc, dSparse.cc,
fCColVector.cc, fCDiagMatrix.cc, fCMatrix.cc, fCNDArray.cc, fCRowVector.cc,
fColVector.cc, fDiagMatrix.cc, fMatrix.cc, fNDArray.cc, fRowVector.cc,
idx-vector.cc, CmplxAEPBAL.cc, CmplxCHOL.cc, CmplxGEPBAL.cc, CmplxHESS.cc,
CmplxLU.cc, CmplxQR.cc, CmplxSCHUR.cc, CmplxSVD.cc, DASPK.cc, EIG.cc, LSODE.cc,
Quad.cc, SparseCmplxCHOL.cc, SparseCmplxLU.cc, SparseCmplxQR.cc, SparseQR.cc,
SparsedbleCHOL.cc, SparsedbleLU.cc, base-lu.cc, bsxfun-defs.cc, dbleAEPBAL.cc,
dbleCHOL.cc, dbleGEPBAL.cc, dbleHESS.cc, dbleLU.cc, dbleQR.cc, dbleSCHUR.cc,
dbleSVD.cc, eigs-base.cc, fCmplxAEPBAL.cc, fCmplxCHOL.cc, fCmplxLU.cc,
fCmplxQR.cc, fCmplxSCHUR.cc, fEIG.cc, floatAEPBAL.cc, floatCHOL.cc,
floatGEPBAL.cc, floatHESS.cc, floatLU.cc, floatQR.cc, floatSCHUR.cc,
floatSVD.cc, lo-specfun.cc, oct-fftw.cc, oct-rand.cc, oct-spparms.cc,
sparse-base-chol.cc, sparse-dmsolve.cc, file-ops.cc, lo-sysdep.cc,
mach-info.cc, oct-env.cc, oct-syscalls.cc, cmd-edit.cc, cmd-hist.cc,
data-conv.cc, lo-ieee.cc, lo-regexp.cc, oct-base64.cc, oct-shlib.cc,
pathsearch.cc, singleton-cleanup.cc, sparse-util.cc, unwind-prot.cc:
Remove statements after call to handler that are no longer reachable.
Place input validation first and immediately call handler if necessary.
Change if/error_handler/else to if/error_handler and re-indent code.
author | Rik <rik@octave.org> |
---|---|
date | Sat, 23 Jan 2016 13:52:03 -0800 |
parents | 499b851fbfae |
children | 623fc7d08cc6 |
comparison
equal
deleted
inserted
replaced
21135:95da3bc8a281 | 21136:7cac4e7458f2 |
---|---|
749 } | 749 } |
750 | 750 |
751 SparseMatrix | 751 SparseMatrix |
752 atan2 (const SparseMatrix& x, const SparseMatrix& y) | 752 atan2 (const SparseMatrix& x, const SparseMatrix& y) |
753 { | 753 { |
754 if ((x.rows () != y.rows ()) || (x.cols () != y.cols ())) | |
755 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
756 | |
757 octave_idx_type x_nr = x.rows (); | |
758 octave_idx_type x_nc = x.cols (); | |
759 | |
760 octave_idx_type y_nr = y.rows (); | |
761 octave_idx_type y_nc = y.cols (); | |
762 | |
763 if (x_nr != y_nr || x_nc != y_nc) | |
764 err_nonconformant ("atan2", x_nr, x_nc, y_nr, y_nc); | |
765 | |
754 SparseMatrix r; | 766 SparseMatrix r; |
755 | 767 |
756 if ((x.rows () == y.rows ()) && (x.cols () == y.cols ())) | 768 r = SparseMatrix (x_nr, x_nc, (x.nnz () + y.nnz ())); |
769 | |
770 octave_idx_type jx = 0; | |
771 r.cidx (0) = 0; | |
772 for (octave_idx_type i = 0 ; i < x_nc ; i++) | |
757 { | 773 { |
758 octave_idx_type x_nr = x.rows (); | 774 octave_idx_type ja = x.cidx (i); |
759 octave_idx_type x_nc = x.cols (); | 775 octave_idx_type ja_max = x.cidx (i+1); |
760 | 776 bool ja_lt_max= ja < ja_max; |
761 octave_idx_type y_nr = y.rows (); | 777 |
762 octave_idx_type y_nc = y.cols (); | 778 octave_idx_type jb = y.cidx (i); |
763 | 779 octave_idx_type jb_max = y.cidx (i+1); |
764 if (x_nr != y_nr || x_nc != y_nc) | 780 bool jb_lt_max = jb < jb_max; |
765 err_nonconformant ("atan2", x_nr, x_nc, y_nr, y_nc); | 781 |
766 | 782 while (ja_lt_max || jb_lt_max) |
767 r = SparseMatrix (x_nr, x_nc, (x.nnz () + y.nnz ())); | 783 { |
768 | 784 octave_quit (); |
769 octave_idx_type jx = 0; | 785 if ((! jb_lt_max) |
770 r.cidx (0) = 0; | 786 || (ja_lt_max && (x.ridx (ja) < y.ridx (jb)))) |
771 for (octave_idx_type i = 0 ; i < x_nc ; i++) | 787 { |
772 { | 788 r.ridx (jx) = x.ridx (ja); |
773 octave_idx_type ja = x.cidx (i); | 789 r.data (jx) = atan2 (x.data (ja), 0.); |
774 octave_idx_type ja_max = x.cidx (i+1); | 790 jx++; |
775 bool ja_lt_max= ja < ja_max; | 791 ja++; |
776 | 792 ja_lt_max= ja < ja_max; |
777 octave_idx_type jb = y.cidx (i); | 793 } |
778 octave_idx_type jb_max = y.cidx (i+1); | 794 else if ((! ja_lt_max) |
779 bool jb_lt_max = jb < jb_max; | 795 || (jb_lt_max && (y.ridx (jb) < x.ridx (ja)))) |
780 | 796 { |
781 while (ja_lt_max || jb_lt_max) | 797 jb++; |
782 { | 798 jb_lt_max= jb < jb_max; |
783 octave_quit (); | 799 } |
784 if ((! jb_lt_max) | 800 else |
785 || (ja_lt_max && (x.ridx (ja) < y.ridx (jb)))) | 801 { |
786 { | 802 double tmp = atan2 (x.data (ja), y.data (jb)); |
803 if (tmp != 0.) | |
804 { | |
805 r.data (jx) = tmp; | |
787 r.ridx (jx) = x.ridx (ja); | 806 r.ridx (jx) = x.ridx (ja); |
788 r.data (jx) = atan2 (x.data (ja), 0.); | |
789 jx++; | 807 jx++; |
790 ja++; | 808 } |
791 ja_lt_max= ja < ja_max; | 809 ja++; |
792 } | 810 ja_lt_max= ja < ja_max; |
793 else if ((! ja_lt_max) | 811 jb++; |
794 || (jb_lt_max && (y.ridx (jb) < x.ridx (ja)))) | 812 jb_lt_max= jb < jb_max; |
795 { | 813 } |
796 jb++; | 814 } |
797 jb_lt_max= jb < jb_max; | 815 r.cidx (i+1) = jx; |
798 } | |
799 else | |
800 { | |
801 double tmp = atan2 (x.data (ja), y.data (jb)); | |
802 if (tmp != 0.) | |
803 { | |
804 r.data (jx) = tmp; | |
805 r.ridx (jx) = x.ridx (ja); | |
806 jx++; | |
807 } | |
808 ja++; | |
809 ja_lt_max= ja < ja_max; | |
810 jb++; | |
811 jb_lt_max= jb < jb_max; | |
812 } | |
813 } | |
814 r.cidx (i+1) = jx; | |
815 } | |
816 | |
817 r.maybe_compress (); | |
818 } | 816 } |
819 else | 817 |
820 (*current_liboctave_error_handler) ("matrix size mismatch"); | 818 r.maybe_compress (); |
821 | 819 |
822 return r; | 820 return r; |
823 } | 821 } |
824 | 822 |
825 SparseMatrix | 823 SparseMatrix |
857 octave_idx_type nc = cols (); | 855 octave_idx_type nc = cols (); |
858 info = 0; | 856 info = 0; |
859 | 857 |
860 if (nr == 0 || nc == 0 || nr != nc) | 858 if (nr == 0 || nc == 0 || nr != nc) |
861 (*current_liboctave_error_handler) ("inverse requires square matrix"); | 859 (*current_liboctave_error_handler) ("inverse requires square matrix"); |
860 | |
861 // Print spparms("spumoni") info if requested | |
862 int typ = mattyp.type (); | |
863 mattyp.info (); | |
864 | |
865 if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal) | |
866 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
867 | |
868 if (typ == MatrixType::Permuted_Diagonal) | |
869 retval = transpose (); | |
862 else | 870 else |
871 retval = *this; | |
872 | |
873 // Force make_unique to be called | |
874 double *v = retval.data (); | |
875 | |
876 if (calccond) | |
863 { | 877 { |
864 // Print spparms("spumoni") info if requested | 878 double dmax = 0.; |
865 int typ = mattyp.type (); | 879 double dmin = octave_Inf; |
866 mattyp.info (); | 880 for (octave_idx_type i = 0; i < nr; i++) |
867 | 881 { |
868 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) | 882 double tmp = fabs (v[i]); |
869 { | 883 if (tmp > dmax) |
870 if (typ == MatrixType::Permuted_Diagonal) | 884 dmax = tmp; |
871 retval = transpose (); | 885 if (tmp < dmin) |
872 else | 886 dmin = tmp; |
873 retval = *this; | 887 } |
874 | 888 rcond = dmin / dmax; |
875 // Force make_unique to be called | |
876 double *v = retval.data (); | |
877 | |
878 if (calccond) | |
879 { | |
880 double dmax = 0.; | |
881 double dmin = octave_Inf; | |
882 for (octave_idx_type i = 0; i < nr; i++) | |
883 { | |
884 double tmp = fabs (v[i]); | |
885 if (tmp > dmax) | |
886 dmax = tmp; | |
887 if (tmp < dmin) | |
888 dmin = tmp; | |
889 } | |
890 rcond = dmin / dmax; | |
891 } | |
892 | |
893 for (octave_idx_type i = 0; i < nr; i++) | |
894 v[i] = 1.0 / v[i]; | |
895 } | |
896 else | |
897 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
898 } | 889 } |
890 | |
891 for (octave_idx_type i = 0; i < nr; i++) | |
892 v[i] = 1.0 / v[i]; | |
899 | 893 |
900 return retval; | 894 return retval; |
901 } | 895 } |
902 | 896 |
903 SparseMatrix | 897 SparseMatrix |
911 octave_idx_type nc = cols (); | 905 octave_idx_type nc = cols (); |
912 info = 0; | 906 info = 0; |
913 | 907 |
914 if (nr == 0 || nc == 0 || nr != nc) | 908 if (nr == 0 || nc == 0 || nr != nc) |
915 (*current_liboctave_error_handler) ("inverse requires square matrix"); | 909 (*current_liboctave_error_handler) ("inverse requires square matrix"); |
910 | |
911 // Print spparms("spumoni") info if requested | |
912 int typ = mattyp.type (); | |
913 mattyp.info (); | |
914 | |
915 if (typ != MatrixType::Upper && typ != MatrixType::Permuted_Upper | |
916 && typ != MatrixType::Lower && typ != MatrixType::Permuted_Lower) | |
917 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
918 | |
919 double anorm = 0.; | |
920 double ainvnorm = 0.; | |
921 | |
922 if (calccond) | |
923 { | |
924 // Calculate the 1-norm of matrix for rcond calculation | |
925 for (octave_idx_type j = 0; j < nr; j++) | |
926 { | |
927 double atmp = 0.; | |
928 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
929 atmp += fabs (data (i)); | |
930 if (atmp > anorm) | |
931 anorm = atmp; | |
932 } | |
933 } | |
934 | |
935 if (typ == MatrixType::Upper || typ == MatrixType::Lower) | |
936 { | |
937 octave_idx_type nz = nnz (); | |
938 octave_idx_type cx = 0; | |
939 octave_idx_type nz2 = nz; | |
940 retval = SparseMatrix (nr, nc, nz2); | |
941 | |
942 for (octave_idx_type i = 0; i < nr; i++) | |
943 { | |
944 octave_quit (); | |
945 // place the 1 in the identity position | |
946 octave_idx_type cx_colstart = cx; | |
947 | |
948 if (cx == nz2) | |
949 { | |
950 nz2 *= 2; | |
951 retval.change_capacity (nz2); | |
952 } | |
953 | |
954 retval.xcidx (i) = cx; | |
955 retval.xridx (cx) = i; | |
956 retval.xdata (cx) = 1.0; | |
957 cx++; | |
958 | |
959 // iterate accross columns of input matrix | |
960 for (octave_idx_type j = i+1; j < nr; j++) | |
961 { | |
962 double v = 0.; | |
963 // iterate to calculate sum | |
964 octave_idx_type colXp = retval.xcidx (i); | |
965 octave_idx_type colUp = cidx (j); | |
966 octave_idx_type rpX, rpU; | |
967 | |
968 if (cidx (j) == cidx (j+1)) | |
969 (*current_liboctave_error_handler) ("division by zero"); | |
970 | |
971 do | |
972 { | |
973 octave_quit (); | |
974 rpX = retval.xridx (colXp); | |
975 rpU = ridx (colUp); | |
976 | |
977 if (rpX < rpU) | |
978 colXp++; | |
979 else if (rpX > rpU) | |
980 colUp++; | |
981 else | |
982 { | |
983 v -= retval.xdata (colXp) * data (colUp); | |
984 colXp++; | |
985 colUp++; | |
986 } | |
987 } | |
988 while (rpX < j && rpU < j && colXp < cx && colUp < nz); | |
989 | |
990 // get A(m,m) | |
991 if (typ == MatrixType::Upper) | |
992 colUp = cidx (j+1) - 1; | |
993 else | |
994 colUp = cidx (j); | |
995 double pivot = data (colUp); | |
996 if (pivot == 0. || ridx (colUp) != j) | |
997 (*current_liboctave_error_handler) ("division by zero"); | |
998 | |
999 if (v != 0.) | |
1000 { | |
1001 if (cx == nz2) | |
1002 { | |
1003 nz2 *= 2; | |
1004 retval.change_capacity (nz2); | |
1005 } | |
1006 | |
1007 retval.xridx (cx) = j; | |
1008 retval.xdata (cx) = v / pivot; | |
1009 cx++; | |
1010 } | |
1011 } | |
1012 | |
1013 // get A(m,m) | |
1014 octave_idx_type colUp; | |
1015 if (typ == MatrixType::Upper) | |
1016 colUp = cidx (i+1) - 1; | |
1017 else | |
1018 colUp = cidx (i); | |
1019 double pivot = data (colUp); | |
1020 if (pivot == 0. || ridx (colUp) != i) | |
1021 (*current_liboctave_error_handler) ("division by zero"); | |
1022 | |
1023 if (pivot != 1.0) | |
1024 for (octave_idx_type j = cx_colstart; j < cx; j++) | |
1025 retval.xdata (j) /= pivot; | |
1026 } | |
1027 retval.xcidx (nr) = cx; | |
1028 retval.maybe_compress (); | |
1029 } | |
916 else | 1030 else |
917 { | 1031 { |
918 // Print spparms("spumoni") info if requested | 1032 octave_idx_type nz = nnz (); |
919 int typ = mattyp.type (); | 1033 octave_idx_type cx = 0; |
920 mattyp.info (); | 1034 octave_idx_type nz2 = nz; |
921 | 1035 retval = SparseMatrix (nr, nc, nz2); |
922 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper | 1036 |
923 || typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) | 1037 OCTAVE_LOCAL_BUFFER (double, work, nr); |
924 { | 1038 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr); |
925 double anorm = 0.; | 1039 |
926 double ainvnorm = 0.; | 1040 octave_idx_type *perm = mattyp.triangular_perm (); |
927 | 1041 if (typ == MatrixType::Permuted_Upper) |
928 if (calccond) | 1042 { |
929 { | 1043 for (octave_idx_type i = 0; i < nr; i++) |
930 // Calculate the 1-norm of matrix for rcond calculation | 1044 rperm[perm[i]] = i; |
931 for (octave_idx_type j = 0; j < nr; j++) | 1045 } |
932 { | 1046 else |
933 double atmp = 0.; | 1047 { |
934 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 1048 for (octave_idx_type i = 0; i < nr; i++) |
935 atmp += fabs (data (i)); | 1049 rperm[i] = perm[i]; |
936 if (atmp > anorm) | 1050 for (octave_idx_type i = 0; i < nr; i++) |
937 anorm = atmp; | 1051 perm[rperm[i]] = i; |
938 } | 1052 } |
939 } | 1053 |
940 | 1054 for (octave_idx_type i = 0; i < nr; i++) |
941 if (typ == MatrixType::Upper || typ == MatrixType::Lower) | 1055 { |
942 { | 1056 octave_quit (); |
943 octave_idx_type nz = nnz (); | 1057 octave_idx_type iidx = rperm[i]; |
944 octave_idx_type cx = 0; | 1058 |
945 octave_idx_type nz2 = nz; | 1059 for (octave_idx_type j = 0; j < nr; j++) |
946 retval = SparseMatrix (nr, nc, nz2); | 1060 work[j] = 0.; |
947 | 1061 |
948 for (octave_idx_type i = 0; i < nr; i++) | 1062 // place the 1 in the identity position |
1063 work[iidx] = 1.0; | |
1064 | |
1065 // iterate accross columns of input matrix | |
1066 for (octave_idx_type j = iidx+1; j < nr; j++) | |
1067 { | |
1068 double v = 0.; | |
1069 octave_idx_type jidx = perm[j]; | |
1070 // iterate to calculate sum | |
1071 for (octave_idx_type k = cidx (jidx); | |
1072 k < cidx (jidx+1); k++) | |
949 { | 1073 { |
950 octave_quit (); | 1074 octave_quit (); |
951 // place the 1 in the identity position | 1075 v -= work[ridx (k)] * data (k); |
952 octave_idx_type cx_colstart = cx; | 1076 } |
953 | 1077 |
954 if (cx == nz2) | 1078 // get A(m,m) |
955 { | 1079 double pivot; |
956 nz2 *= 2; | 1080 if (typ == MatrixType::Permuted_Upper) |
957 retval.change_capacity (nz2); | 1081 pivot = data (cidx (jidx+1) - 1); |
958 } | 1082 else |
959 | 1083 pivot = data (cidx (jidx)); |
960 retval.xcidx (i) = cx; | 1084 if (pivot == 0.) |
961 retval.xridx (cx) = i; | 1085 (*current_liboctave_error_handler) ("division by zero"); |
962 retval.xdata (cx) = 1.0; | 1086 |
963 cx++; | 1087 work[j] = v / pivot; |
964 | 1088 } |
965 // iterate accross columns of input matrix | 1089 |
966 for (octave_idx_type j = i+1; j < nr; j++) | 1090 // get A(m,m) |
967 { | 1091 octave_idx_type colUp; |
968 double v = 0.; | 1092 if (typ == MatrixType::Permuted_Upper) |
969 // iterate to calculate sum | 1093 colUp = cidx (perm[iidx]+1) - 1; |
970 octave_idx_type colXp = retval.xcidx (i); | |
971 octave_idx_type colUp = cidx (j); | |
972 octave_idx_type rpX, rpU; | |
973 | |
974 if (cidx (j) == cidx (j+1)) | |
975 { | |
976 (*current_liboctave_error_handler) | |
977 ("division by zero"); | |
978 goto inverse_singular; | |
979 } | |
980 | |
981 do | |
982 { | |
983 octave_quit (); | |
984 rpX = retval.xridx (colXp); | |
985 rpU = ridx (colUp); | |
986 | |
987 if (rpX < rpU) | |
988 colXp++; | |
989 else if (rpX > rpU) | |
990 colUp++; | |
991 else | |
992 { | |
993 v -= retval.xdata (colXp) * data (colUp); | |
994 colXp++; | |
995 colUp++; | |
996 } | |
997 } | |
998 while (rpX < j && rpU < j && colXp < cx && colUp < nz); | |
999 | |
1000 // get A(m,m) | |
1001 if (typ == MatrixType::Upper) | |
1002 colUp = cidx (j+1) - 1; | |
1003 else | |
1004 colUp = cidx (j); | |
1005 double pivot = data (colUp); | |
1006 if (pivot == 0. || ridx (colUp) != j) | |
1007 { | |
1008 (*current_liboctave_error_handler) | |
1009 ("division by zero"); | |
1010 goto inverse_singular; | |
1011 } | |
1012 | |
1013 if (v != 0.) | |
1014 { | |
1015 if (cx == nz2) | |
1016 { | |
1017 nz2 *= 2; | |
1018 retval.change_capacity (nz2); | |
1019 } | |
1020 | |
1021 retval.xridx (cx) = j; | |
1022 retval.xdata (cx) = v / pivot; | |
1023 cx++; | |
1024 } | |
1025 } | |
1026 | |
1027 // get A(m,m) | |
1028 octave_idx_type colUp; | |
1029 if (typ == MatrixType::Upper) | |
1030 colUp = cidx (i+1) - 1; | |
1031 else | |
1032 colUp = cidx (i); | |
1033 double pivot = data (colUp); | |
1034 if (pivot == 0. || ridx (colUp) != i) | |
1035 { | |
1036 (*current_liboctave_error_handler) ("division by zero"); | |
1037 goto inverse_singular; | |
1038 } | |
1039 | |
1040 if (pivot != 1.0) | |
1041 for (octave_idx_type j = cx_colstart; j < cx; j++) | |
1042 retval.xdata (j) /= pivot; | |
1043 } | |
1044 retval.xcidx (nr) = cx; | |
1045 retval.maybe_compress (); | |
1046 } | |
1047 else | 1094 else |
1048 { | 1095 colUp = cidx (perm[iidx]); |
1049 octave_idx_type nz = nnz (); | 1096 |
1050 octave_idx_type cx = 0; | 1097 double pivot = data (colUp); |
1051 octave_idx_type nz2 = nz; | 1098 if (pivot == 0.) |
1052 retval = SparseMatrix (nr, nc, nz2); | 1099 (*current_liboctave_error_handler) ("division by zero"); |
1053 | 1100 |
1054 OCTAVE_LOCAL_BUFFER (double, work, nr); | 1101 octave_idx_type new_cx = cx; |
1055 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr); | 1102 for (octave_idx_type j = iidx; j < nr; j++) |
1056 | 1103 if (work[j] != 0.0) |
1057 octave_idx_type *perm = mattyp.triangular_perm (); | 1104 { |
1058 if (typ == MatrixType::Permuted_Upper) | 1105 new_cx++; |
1059 { | 1106 if (pivot != 1.0) |
1060 for (octave_idx_type i = 0; i < nr; i++) | 1107 work[j] /= pivot; |
1061 rperm[perm[i]] = i; | 1108 } |
1062 } | 1109 |
1063 else | 1110 if (cx < new_cx) |
1064 { | 1111 { |
1065 for (octave_idx_type i = 0; i < nr; i++) | 1112 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2); |
1066 rperm[i] = perm[i]; | 1113 retval.change_capacity (nz2); |
1067 for (octave_idx_type i = 0; i < nr; i++) | 1114 } |
1068 perm[rperm[i]] = i; | 1115 |
1069 } | 1116 retval.xcidx (i) = cx; |
1070 | 1117 for (octave_idx_type j = iidx; j < nr; j++) |
1071 for (octave_idx_type i = 0; i < nr; i++) | 1118 if (work[j] != 0.) |
1072 { | 1119 { |
1073 octave_quit (); | 1120 retval.xridx (cx) = j; |
1074 octave_idx_type iidx = rperm[i]; | 1121 retval.xdata (cx++) = work[j]; |
1075 | 1122 } |
1076 for (octave_idx_type j = 0; j < nr; j++) | 1123 } |
1077 work[j] = 0.; | 1124 |
1078 | 1125 retval.xcidx (nr) = cx; |
1079 // place the 1 in the identity position | 1126 retval.maybe_compress (); |
1080 work[iidx] = 1.0; | 1127 } |
1081 | 1128 |
1082 // iterate accross columns of input matrix | 1129 if (calccond) |
1083 for (octave_idx_type j = iidx+1; j < nr; j++) | 1130 { |
1084 { | 1131 // Calculate the 1-norm of inverse matrix for rcond calculation |
1085 double v = 0.; | 1132 for (octave_idx_type j = 0; j < nr; j++) |
1086 octave_idx_type jidx = perm[j]; | 1133 { |
1087 // iterate to calculate sum | 1134 double atmp = 0.; |
1088 for (octave_idx_type k = cidx (jidx); | 1135 for (octave_idx_type i = retval.cidx (j); |
1089 k < cidx (jidx+1); k++) | 1136 i < retval.cidx (j+1); i++) |
1090 { | 1137 atmp += fabs (retval.data (i)); |
1091 octave_quit (); | 1138 if (atmp > ainvnorm) |
1092 v -= work[ridx (k)] * data (k); | 1139 ainvnorm = atmp; |
1093 } | 1140 } |
1094 | 1141 |
1095 // get A(m,m) | 1142 rcond = 1. / ainvnorm / anorm; |
1096 double pivot; | |
1097 if (typ == MatrixType::Permuted_Upper) | |
1098 pivot = data (cidx (jidx+1) - 1); | |
1099 else | |
1100 pivot = data (cidx (jidx)); | |
1101 if (pivot == 0.) | |
1102 { | |
1103 (*current_liboctave_error_handler) | |
1104 ("division by zero"); | |
1105 goto inverse_singular; | |
1106 } | |
1107 | |
1108 work[j] = v / pivot; | |
1109 } | |
1110 | |
1111 // get A(m,m) | |
1112 octave_idx_type colUp; | |
1113 if (typ == MatrixType::Permuted_Upper) | |
1114 colUp = cidx (perm[iidx]+1) - 1; | |
1115 else | |
1116 colUp = cidx (perm[iidx]); | |
1117 | |
1118 double pivot = data (colUp); | |
1119 if (pivot == 0.) | |
1120 { | |
1121 (*current_liboctave_error_handler) | |
1122 ("division by zero"); | |
1123 goto inverse_singular; | |
1124 } | |
1125 | |
1126 octave_idx_type new_cx = cx; | |
1127 for (octave_idx_type j = iidx; j < nr; j++) | |
1128 if (work[j] != 0.0) | |
1129 { | |
1130 new_cx++; | |
1131 if (pivot != 1.0) | |
1132 work[j] /= pivot; | |
1133 } | |
1134 | |
1135 if (cx < new_cx) | |
1136 { | |
1137 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2); | |
1138 retval.change_capacity (nz2); | |
1139 } | |
1140 | |
1141 retval.xcidx (i) = cx; | |
1142 for (octave_idx_type j = iidx; j < nr; j++) | |
1143 if (work[j] != 0.) | |
1144 { | |
1145 retval.xridx (cx) = j; | |
1146 retval.xdata (cx++) = work[j]; | |
1147 } | |
1148 } | |
1149 | |
1150 retval.xcidx (nr) = cx; | |
1151 retval.maybe_compress (); | |
1152 } | |
1153 | |
1154 if (calccond) | |
1155 { | |
1156 // Calculate the 1-norm of inverse matrix for rcond calculation | |
1157 for (octave_idx_type j = 0; j < nr; j++) | |
1158 { | |
1159 double atmp = 0.; | |
1160 for (octave_idx_type i = retval.cidx (j); | |
1161 i < retval.cidx (j+1); i++) | |
1162 atmp += fabs (retval.data (i)); | |
1163 if (atmp > ainvnorm) | |
1164 ainvnorm = atmp; | |
1165 } | |
1166 | |
1167 rcond = 1. / ainvnorm / anorm; | |
1168 } | |
1169 } | |
1170 else | |
1171 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1172 } | 1143 } |
1173 | 1144 |
1174 return retval; | 1145 return retval; |
1175 | 1146 |
1176 inverse_singular: | 1147 inverse_singular: |
1310 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, | 1281 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, |
1311 Ax, 0, &Symbolic, control, info); | 1282 Ax, 0, &Symbolic, control, info); |
1312 | 1283 |
1313 if (status < 0) | 1284 if (status < 0) |
1314 { | 1285 { |
1286 UMFPACK_DNAME (report_status) (control, status); | |
1287 UMFPACK_DNAME (report_info) (control, info); | |
1288 | |
1289 UMFPACK_DNAME (free_symbolic) (&Symbolic); | |
1290 | |
1315 (*current_liboctave_error_handler) | 1291 (*current_liboctave_error_handler) |
1316 ("SparseMatrix::determinant symbolic factorization failed"); | 1292 ("SparseMatrix::determinant symbolic factorization failed"); |
1317 | |
1318 UMFPACK_DNAME (report_status) (control, status); | |
1319 UMFPACK_DNAME (report_info) (control, info); | |
1320 | |
1321 UMFPACK_DNAME (free_symbolic) (&Symbolic); | |
1322 } | 1293 } |
1323 else | 1294 else |
1324 { | 1295 { |
1325 UMFPACK_DNAME (report_symbolic) (Symbolic, control); | 1296 UMFPACK_DNAME (report_symbolic) (Symbolic, control); |
1326 | 1297 |
1331 | 1302 |
1332 rcond = Info (UMFPACK_RCOND); | 1303 rcond = Info (UMFPACK_RCOND); |
1333 | 1304 |
1334 if (status < 0) | 1305 if (status < 0) |
1335 { | 1306 { |
1307 UMFPACK_DNAME (report_status) (control, status); | |
1308 UMFPACK_DNAME (report_info) (control, info); | |
1309 | |
1310 UMFPACK_DNAME (free_numeric) (&Numeric); | |
1336 (*current_liboctave_error_handler) | 1311 (*current_liboctave_error_handler) |
1337 ("SparseMatrix::determinant numeric factorization failed"); | 1312 ("SparseMatrix::determinant numeric factorization failed"); |
1338 | |
1339 UMFPACK_DNAME (report_status) (control, status); | |
1340 UMFPACK_DNAME (report_info) (control, info); | |
1341 | |
1342 UMFPACK_DNAME (free_numeric) (&Numeric); | |
1343 } | 1313 } |
1344 else | 1314 else |
1345 { | 1315 { |
1346 UMFPACK_DNAME (report_numeric) (Numeric, control); | 1316 UMFPACK_DNAME (report_numeric) (Numeric, control); |
1347 | 1317 |
1350 status = UMFPACK_DNAME (get_determinant) (&c10, &e10, Numeric, | 1320 status = UMFPACK_DNAME (get_determinant) (&c10, &e10, Numeric, |
1351 info); | 1321 info); |
1352 | 1322 |
1353 if (status < 0) | 1323 if (status < 0) |
1354 { | 1324 { |
1325 UMFPACK_DNAME (report_status) (control, status); | |
1326 UMFPACK_DNAME (report_info) (control, info); | |
1327 | |
1355 (*current_liboctave_error_handler) | 1328 (*current_liboctave_error_handler) |
1356 ("SparseMatrix::determinant error calculating determinant"); | 1329 ("SparseMatrix::determinant error calculating determinant"); |
1357 | |
1358 UMFPACK_DNAME (report_status) (control, status); | |
1359 UMFPACK_DNAME (report_info) (control, info); | |
1360 } | 1330 } |
1361 else | 1331 else |
1362 retval = DET (c10, e10, 10); | 1332 retval = DET (c10, e10, 10); |
1363 | 1333 |
1364 UMFPACK_DNAME (free_numeric) (&Numeric); | 1334 UMFPACK_DNAME (free_numeric) (&Numeric); |
1389 err = 0; | 1359 err = 0; |
1390 | 1360 |
1391 if (nr != b.rows ()) | 1361 if (nr != b.rows ()) |
1392 (*current_liboctave_error_handler) | 1362 (*current_liboctave_error_handler) |
1393 ("matrix dimension mismatch solution of linear equations"); | 1363 ("matrix dimension mismatch solution of linear equations"); |
1394 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1364 |
1365 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1395 retval = Matrix (nc, b.cols (), 0.0); | 1366 retval = Matrix (nc, b.cols (), 0.0); |
1396 else | 1367 else |
1397 { | 1368 { |
1398 // Print spparms("spumoni") info if requested | 1369 // Print spparms("spumoni") info if requested |
1399 int typ = mattype.type (); | 1370 int typ = mattype.type (); |
1400 mattype.info (); | 1371 mattype.info (); |
1401 | 1372 |
1402 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) | 1373 if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal) |
1403 { | 1374 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1404 retval.resize (nc, b.cols (), 0.); | 1375 |
1405 if (typ == MatrixType::Diagonal) | 1376 retval.resize (nc, b.cols (), 0.); |
1406 for (octave_idx_type j = 0; j < b.cols (); j++) | 1377 if (typ == MatrixType::Diagonal) |
1407 for (octave_idx_type i = 0; i < nm; i++) | 1378 for (octave_idx_type j = 0; j < b.cols (); j++) |
1408 retval(i,j) = b(i,j) / data (i); | 1379 for (octave_idx_type i = 0; i < nm; i++) |
1409 else | 1380 retval(i,j) = b(i,j) / data (i); |
1410 for (octave_idx_type j = 0; j < b.cols (); j++) | |
1411 for (octave_idx_type k = 0; k < nc; k++) | |
1412 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
1413 retval(k,j) = b(ridx (i),j) / data (i); | |
1414 | |
1415 if (calc_cond) | |
1416 { | |
1417 double dmax = 0.; | |
1418 double dmin = octave_Inf; | |
1419 for (octave_idx_type i = 0; i < nm; i++) | |
1420 { | |
1421 double tmp = fabs (data (i)); | |
1422 if (tmp > dmax) | |
1423 dmax = tmp; | |
1424 if (tmp < dmin) | |
1425 dmin = tmp; | |
1426 } | |
1427 rcond = dmin / dmax; | |
1428 } | |
1429 else | |
1430 rcond = 1.; | |
1431 } | |
1432 else | 1381 else |
1433 (*current_liboctave_error_handler) ("incorrect matrix type"); | 1382 for (octave_idx_type j = 0; j < b.cols (); j++) |
1383 for (octave_idx_type k = 0; k < nc; k++) | |
1384 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
1385 retval(k,j) = b(ridx (i),j) / data (i); | |
1386 | |
1387 if (calc_cond) | |
1388 { | |
1389 double dmax = 0.; | |
1390 double dmin = octave_Inf; | |
1391 for (octave_idx_type i = 0; i < nm; i++) | |
1392 { | |
1393 double tmp = fabs (data (i)); | |
1394 if (tmp > dmax) | |
1395 dmax = tmp; | |
1396 if (tmp < dmin) | |
1397 dmin = tmp; | |
1398 } | |
1399 rcond = dmin / dmax; | |
1400 } | |
1401 else | |
1402 rcond = 1.; | |
1434 } | 1403 } |
1435 | 1404 |
1436 return retval; | 1405 return retval; |
1437 } | 1406 } |
1438 | 1407 |
1449 err = 0; | 1418 err = 0; |
1450 | 1419 |
1451 if (nr != b.rows ()) | 1420 if (nr != b.rows ()) |
1452 (*current_liboctave_error_handler) | 1421 (*current_liboctave_error_handler) |
1453 ("matrix dimension mismatch solution of linear equations"); | 1422 ("matrix dimension mismatch solution of linear equations"); |
1454 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1423 |
1424 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1455 retval = SparseMatrix (nc, b.cols ()); | 1425 retval = SparseMatrix (nc, b.cols ()); |
1456 else | 1426 else |
1457 { | 1427 { |
1458 // Print spparms("spumoni") info if requested | 1428 // Print spparms("spumoni") info if requested |
1459 int typ = mattype.type (); | 1429 int typ = mattype.type (); |
1460 mattype.info (); | 1430 mattype.info (); |
1461 | 1431 |
1462 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) | 1432 if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal) |
1463 { | 1433 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1464 octave_idx_type b_nc = b.cols (); | 1434 |
1465 octave_idx_type b_nz = b.nnz (); | 1435 octave_idx_type b_nc = b.cols (); |
1466 retval = SparseMatrix (nc, b_nc, b_nz); | 1436 octave_idx_type b_nz = b.nnz (); |
1467 | 1437 retval = SparseMatrix (nc, b_nc, b_nz); |
1468 retval.xcidx (0) = 0; | 1438 |
1469 octave_idx_type ii = 0; | 1439 retval.xcidx (0) = 0; |
1470 if (typ == MatrixType::Diagonal) | 1440 octave_idx_type ii = 0; |
1471 for (octave_idx_type j = 0; j < b_nc; j++) | 1441 if (typ == MatrixType::Diagonal) |
1442 for (octave_idx_type j = 0; j < b_nc; j++) | |
1443 { | |
1444 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
1472 { | 1445 { |
1473 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 1446 if (b.ridx (i) >= nm) |
1474 { | 1447 break; |
1475 if (b.ridx (i) >= nm) | 1448 retval.xridx (ii) = b.ridx (i); |
1476 break; | 1449 retval.xdata (ii++) = b.data (i) / data (b.ridx (i)); |
1477 retval.xridx (ii) = b.ridx (i); | |
1478 retval.xdata (ii++) = b.data (i) / data (b.ridx (i)); | |
1479 } | |
1480 retval.xcidx (j+1) = ii; | |
1481 } | 1450 } |
1482 else | 1451 retval.xcidx (j+1) = ii; |
1483 for (octave_idx_type j = 0; j < b_nc; j++) | 1452 } |
1484 { | |
1485 for (octave_idx_type l = 0; l < nc; l++) | |
1486 for (octave_idx_type i = cidx (l); i < cidx (l+1); i++) | |
1487 { | |
1488 bool found = false; | |
1489 octave_idx_type k; | |
1490 for (k = b.cidx (j); k < b.cidx (j+1); k++) | |
1491 if (ridx (i) == b.ridx (k)) | |
1492 { | |
1493 found = true; | |
1494 break; | |
1495 } | |
1496 if (found) | |
1497 { | |
1498 retval.xridx (ii) = l; | |
1499 retval.xdata (ii++) = b.data (k) / data (i); | |
1500 } | |
1501 } | |
1502 retval.xcidx (j+1) = ii; | |
1503 } | |
1504 | |
1505 if (calc_cond) | |
1506 { | |
1507 double dmax = 0.; | |
1508 double dmin = octave_Inf; | |
1509 for (octave_idx_type i = 0; i < nm; i++) | |
1510 { | |
1511 double tmp = fabs (data (i)); | |
1512 if (tmp > dmax) | |
1513 dmax = tmp; | |
1514 if (tmp < dmin) | |
1515 dmin = tmp; | |
1516 } | |
1517 rcond = dmin / dmax; | |
1518 } | |
1519 else | |
1520 rcond = 1.; | |
1521 } | |
1522 else | 1453 else |
1523 (*current_liboctave_error_handler) ("incorrect matrix type"); | 1454 for (octave_idx_type j = 0; j < b_nc; j++) |
1455 { | |
1456 for (octave_idx_type l = 0; l < nc; l++) | |
1457 for (octave_idx_type i = cidx (l); i < cidx (l+1); i++) | |
1458 { | |
1459 bool found = false; | |
1460 octave_idx_type k; | |
1461 for (k = b.cidx (j); k < b.cidx (j+1); k++) | |
1462 if (ridx (i) == b.ridx (k)) | |
1463 { | |
1464 found = true; | |
1465 break; | |
1466 } | |
1467 if (found) | |
1468 { | |
1469 retval.xridx (ii) = l; | |
1470 retval.xdata (ii++) = b.data (k) / data (i); | |
1471 } | |
1472 } | |
1473 retval.xcidx (j+1) = ii; | |
1474 } | |
1475 | |
1476 if (calc_cond) | |
1477 { | |
1478 double dmax = 0.; | |
1479 double dmin = octave_Inf; | |
1480 for (octave_idx_type i = 0; i < nm; i++) | |
1481 { | |
1482 double tmp = fabs (data (i)); | |
1483 if (tmp > dmax) | |
1484 dmax = tmp; | |
1485 if (tmp < dmin) | |
1486 dmin = tmp; | |
1487 } | |
1488 rcond = dmin / dmax; | |
1489 } | |
1490 else | |
1491 rcond = 1.; | |
1524 } | 1492 } |
1525 | 1493 |
1526 return retval; | 1494 return retval; |
1527 } | 1495 } |
1528 | 1496 |
1539 err = 0; | 1507 err = 0; |
1540 | 1508 |
1541 if (nr != b.rows ()) | 1509 if (nr != b.rows ()) |
1542 (*current_liboctave_error_handler) | 1510 (*current_liboctave_error_handler) |
1543 ("matrix dimension mismatch solution of linear equations"); | 1511 ("matrix dimension mismatch solution of linear equations"); |
1544 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1512 |
1513 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1545 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 1514 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
1546 else | 1515 else |
1547 { | 1516 { |
1548 // Print spparms("spumoni") info if requested | 1517 // Print spparms("spumoni") info if requested |
1549 int typ = mattype.type (); | 1518 int typ = mattype.type (); |
1550 mattype.info (); | 1519 mattype.info (); |
1551 | 1520 |
1552 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) | 1521 if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal) |
1553 { | 1522 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1554 retval.resize (nc, b.cols (), 0); | 1523 |
1555 if (typ == MatrixType::Diagonal) | 1524 retval.resize (nc, b.cols (), 0); |
1556 for (octave_idx_type j = 0; j < b.cols (); j++) | 1525 if (typ == MatrixType::Diagonal) |
1557 for (octave_idx_type i = 0; i < nm; i++) | 1526 for (octave_idx_type j = 0; j < b.cols (); j++) |
1558 retval(i,j) = b(i,j) / data (i); | 1527 for (octave_idx_type i = 0; i < nm; i++) |
1559 else | 1528 retval(i,j) = b(i,j) / data (i); |
1560 for (octave_idx_type j = 0; j < b.cols (); j++) | |
1561 for (octave_idx_type k = 0; k < nc; k++) | |
1562 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
1563 retval(k,j) = b(ridx (i),j) / data (i); | |
1564 | |
1565 if (calc_cond) | |
1566 { | |
1567 double dmax = 0.; | |
1568 double dmin = octave_Inf; | |
1569 for (octave_idx_type i = 0; i < nm; i++) | |
1570 { | |
1571 double tmp = fabs (data (i)); | |
1572 if (tmp > dmax) | |
1573 dmax = tmp; | |
1574 if (tmp < dmin) | |
1575 dmin = tmp; | |
1576 } | |
1577 rcond = dmin / dmax; | |
1578 } | |
1579 else | |
1580 rcond = 1.; | |
1581 } | |
1582 else | 1529 else |
1583 (*current_liboctave_error_handler) ("incorrect matrix type"); | 1530 for (octave_idx_type j = 0; j < b.cols (); j++) |
1531 for (octave_idx_type k = 0; k < nc; k++) | |
1532 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
1533 retval(k,j) = b(ridx (i),j) / data (i); | |
1534 | |
1535 if (calc_cond) | |
1536 { | |
1537 double dmax = 0.; | |
1538 double dmin = octave_Inf; | |
1539 for (octave_idx_type i = 0; i < nm; i++) | |
1540 { | |
1541 double tmp = fabs (data (i)); | |
1542 if (tmp > dmax) | |
1543 dmax = tmp; | |
1544 if (tmp < dmin) | |
1545 dmin = tmp; | |
1546 } | |
1547 rcond = dmin / dmax; | |
1548 } | |
1549 else | |
1550 rcond = 1.; | |
1584 } | 1551 } |
1585 | 1552 |
1586 return retval; | 1553 return retval; |
1587 } | 1554 } |
1588 | 1555 |
1599 err = 0; | 1566 err = 0; |
1600 | 1567 |
1601 if (nr != b.rows ()) | 1568 if (nr != b.rows ()) |
1602 (*current_liboctave_error_handler) | 1569 (*current_liboctave_error_handler) |
1603 ("matrix dimension mismatch solution of linear equations"); | 1570 ("matrix dimension mismatch solution of linear equations"); |
1604 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1571 |
1572 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1605 retval = SparseComplexMatrix (nc, b.cols ()); | 1573 retval = SparseComplexMatrix (nc, b.cols ()); |
1606 else | 1574 else |
1607 { | 1575 { |
1608 // Print spparms("spumoni") info if requested | 1576 // Print spparms("spumoni") info if requested |
1609 int typ = mattype.type (); | 1577 int typ = mattype.type (); |
1610 mattype.info (); | 1578 mattype.info (); |
1611 | 1579 |
1612 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) | 1580 if (typ != MatrixType::Diagonal && typ != MatrixType::Permuted_Diagonal) |
1613 { | 1581 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1614 octave_idx_type b_nc = b.cols (); | 1582 |
1615 octave_idx_type b_nz = b.nnz (); | 1583 octave_idx_type b_nc = b.cols (); |
1616 retval = SparseComplexMatrix (nc, b_nc, b_nz); | 1584 octave_idx_type b_nz = b.nnz (); |
1617 | 1585 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
1618 retval.xcidx (0) = 0; | 1586 |
1619 octave_idx_type ii = 0; | 1587 retval.xcidx (0) = 0; |
1620 if (typ == MatrixType::Diagonal) | 1588 octave_idx_type ii = 0; |
1621 for (octave_idx_type j = 0; j < b.cols (); j++) | 1589 if (typ == MatrixType::Diagonal) |
1590 for (octave_idx_type j = 0; j < b.cols (); j++) | |
1591 { | |
1592 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
1622 { | 1593 { |
1623 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 1594 if (b.ridx (i) >= nm) |
1624 { | 1595 break; |
1625 if (b.ridx (i) >= nm) | 1596 retval.xridx (ii) = b.ridx (i); |
1626 break; | 1597 retval.xdata (ii++) = b.data (i) / data (b.ridx (i)); |
1627 retval.xridx (ii) = b.ridx (i); | |
1628 retval.xdata (ii++) = b.data (i) / data (b.ridx (i)); | |
1629 } | |
1630 retval.xcidx (j+1) = ii; | |
1631 } | 1598 } |
1632 else | 1599 retval.xcidx (j+1) = ii; |
1633 for (octave_idx_type j = 0; j < b.cols (); j++) | 1600 } |
1634 { | |
1635 for (octave_idx_type l = 0; l < nc; l++) | |
1636 for (octave_idx_type i = cidx (l); i < cidx (l+1); i++) | |
1637 { | |
1638 bool found = false; | |
1639 octave_idx_type k; | |
1640 for (k = b.cidx (j); k < b.cidx (j+1); k++) | |
1641 if (ridx (i) == b.ridx (k)) | |
1642 { | |
1643 found = true; | |
1644 break; | |
1645 } | |
1646 if (found) | |
1647 { | |
1648 retval.xridx (ii) = l; | |
1649 retval.xdata (ii++) = b.data (k) / data (i); | |
1650 } | |
1651 } | |
1652 retval.xcidx (j+1) = ii; | |
1653 } | |
1654 | |
1655 if (calc_cond) | |
1656 { | |
1657 double dmax = 0.; | |
1658 double dmin = octave_Inf; | |
1659 for (octave_idx_type i = 0; i < nm; i++) | |
1660 { | |
1661 double tmp = fabs (data (i)); | |
1662 if (tmp > dmax) | |
1663 dmax = tmp; | |
1664 if (tmp < dmin) | |
1665 dmin = tmp; | |
1666 } | |
1667 rcond = dmin / dmax; | |
1668 } | |
1669 else | |
1670 rcond = 1.; | |
1671 } | |
1672 else | 1601 else |
1673 (*current_liboctave_error_handler) ("incorrect matrix type"); | 1602 for (octave_idx_type j = 0; j < b.cols (); j++) |
1603 { | |
1604 for (octave_idx_type l = 0; l < nc; l++) | |
1605 for (octave_idx_type i = cidx (l); i < cidx (l+1); i++) | |
1606 { | |
1607 bool found = false; | |
1608 octave_idx_type k; | |
1609 for (k = b.cidx (j); k < b.cidx (j+1); k++) | |
1610 if (ridx (i) == b.ridx (k)) | |
1611 { | |
1612 found = true; | |
1613 break; | |
1614 } | |
1615 if (found) | |
1616 { | |
1617 retval.xridx (ii) = l; | |
1618 retval.xdata (ii++) = b.data (k) / data (i); | |
1619 } | |
1620 } | |
1621 retval.xcidx (j+1) = ii; | |
1622 } | |
1623 | |
1624 if (calc_cond) | |
1625 { | |
1626 double dmax = 0.; | |
1627 double dmin = octave_Inf; | |
1628 for (octave_idx_type i = 0; i < nm; i++) | |
1629 { | |
1630 double tmp = fabs (data (i)); | |
1631 if (tmp > dmax) | |
1632 dmax = tmp; | |
1633 if (tmp < dmin) | |
1634 dmin = tmp; | |
1635 } | |
1636 rcond = dmin / dmax; | |
1637 } | |
1638 else | |
1639 rcond = 1.; | |
1674 } | 1640 } |
1675 | 1641 |
1676 return retval; | 1642 return retval; |
1677 } | 1643 } |
1678 | 1644 |
1690 err = 0; | 1656 err = 0; |
1691 | 1657 |
1692 if (nr != b.rows ()) | 1658 if (nr != b.rows ()) |
1693 (*current_liboctave_error_handler) | 1659 (*current_liboctave_error_handler) |
1694 ("matrix dimension mismatch solution of linear equations"); | 1660 ("matrix dimension mismatch solution of linear equations"); |
1695 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1661 |
1662 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1696 retval = Matrix (nc, b.cols (), 0.0); | 1663 retval = Matrix (nc, b.cols (), 0.0); |
1697 else | 1664 else |
1698 { | 1665 { |
1699 // Print spparms("spumoni") info if requested | 1666 // Print spparms("spumoni") info if requested |
1700 int typ = mattype.type (); | 1667 int typ = mattype.type (); |
1701 mattype.info (); | 1668 mattype.info (); |
1702 | 1669 |
1703 if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper) | 1670 if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper) |
1704 { | 1671 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1705 double anorm = 0.; | 1672 |
1706 double ainvnorm = 0.; | 1673 double anorm = 0.; |
1707 octave_idx_type b_nc = b.cols (); | 1674 double ainvnorm = 0.; |
1708 rcond = 1.; | 1675 octave_idx_type b_nc = b.cols (); |
1676 rcond = 1.; | |
1677 | |
1678 if (calc_cond) | |
1679 { | |
1680 // Calculate the 1-norm of matrix for rcond calculation | |
1681 for (octave_idx_type j = 0; j < nc; j++) | |
1682 { | |
1683 double atmp = 0.; | |
1684 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
1685 atmp += fabs (data (i)); | |
1686 if (atmp > anorm) | |
1687 anorm = atmp; | |
1688 } | |
1689 } | |
1690 | |
1691 if (typ == MatrixType::Permuted_Upper) | |
1692 { | |
1693 retval.resize (nc, b_nc); | |
1694 octave_idx_type *perm = mattype.triangular_perm (); | |
1695 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
1696 | |
1697 for (octave_idx_type j = 0; j < b_nc; j++) | |
1698 { | |
1699 for (octave_idx_type i = 0; i < nr; i++) | |
1700 work[i] = b(i,j); | |
1701 for (octave_idx_type i = nr; i < nc; i++) | |
1702 work[i] = 0.; | |
1703 | |
1704 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1705 { | |
1706 octave_idx_type kidx = perm[k]; | |
1707 | |
1708 if (work[k] != 0.) | |
1709 { | |
1710 if (ridx (cidx (kidx+1)-1) != k | |
1711 || data (cidx (kidx+1)-1) == 0.) | |
1712 { | |
1713 err = -2; | |
1714 goto triangular_error; | |
1715 } | |
1716 | |
1717 double tmp = work[k] / data (cidx (kidx+1)-1); | |
1718 work[k] = tmp; | |
1719 for (octave_idx_type i = cidx (kidx); | |
1720 i < cidx (kidx+1)-1; i++) | |
1721 { | |
1722 octave_idx_type iidx = ridx (i); | |
1723 work[iidx] = work[iidx] - tmp * data (i); | |
1724 } | |
1725 } | |
1726 } | |
1727 | |
1728 for (octave_idx_type i = 0; i < nc; i++) | |
1729 retval.xelem (perm[i], j) = work[i]; | |
1730 } | |
1709 | 1731 |
1710 if (calc_cond) | 1732 if (calc_cond) |
1711 { | 1733 { |
1712 // Calculate the 1-norm of matrix for rcond calculation | 1734 // Calculation of 1-norm of inv(*this) |
1713 for (octave_idx_type j = 0; j < nc; j++) | 1735 for (octave_idx_type i = 0; i < nm; i++) |
1714 { | 1736 work[i] = 0.; |
1715 double atmp = 0.; | 1737 |
1716 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 1738 for (octave_idx_type j = 0; j < nr; j++) |
1717 atmp += fabs (data (i)); | 1739 { |
1718 if (atmp > anorm) | 1740 work[j] = 1.; |
1719 anorm = atmp; | 1741 |
1720 } | 1742 for (octave_idx_type k = j; k >= 0; k--) |
1721 } | 1743 { |
1722 | 1744 octave_idx_type iidx = perm[k]; |
1723 if (typ == MatrixType::Permuted_Upper) | |
1724 { | |
1725 retval.resize (nc, b_nc); | |
1726 octave_idx_type *perm = mattype.triangular_perm (); | |
1727 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
1728 | |
1729 for (octave_idx_type j = 0; j < b_nc; j++) | |
1730 { | |
1731 for (octave_idx_type i = 0; i < nr; i++) | |
1732 work[i] = b(i,j); | |
1733 for (octave_idx_type i = nr; i < nc; i++) | |
1734 work[i] = 0.; | |
1735 | |
1736 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1737 { | |
1738 octave_idx_type kidx = perm[k]; | |
1739 | 1745 |
1740 if (work[k] != 0.) | 1746 if (work[k] != 0.) |
1741 { | 1747 { |
1742 if (ridx (cidx (kidx+1)-1) != k | 1748 double tmp = work[k] / data (cidx (iidx+1)-1); |
1743 || data (cidx (kidx+1)-1) == 0.) | 1749 work[k] = tmp; |
1750 for (octave_idx_type i = cidx (iidx); | |
1751 i < cidx (iidx+1)-1; i++) | |
1744 { | 1752 { |
1745 err = -2; | 1753 octave_idx_type idx2 = ridx (i); |
1746 goto triangular_error; | 1754 work[idx2] = work[idx2] - tmp * data (i); |
1747 } | |
1748 | |
1749 double tmp = work[k] / data (cidx (kidx+1)-1); | |
1750 work[k] = tmp; | |
1751 for (octave_idx_type i = cidx (kidx); | |
1752 i < cidx (kidx+1)-1; i++) | |
1753 { | |
1754 octave_idx_type iidx = ridx (i); | |
1755 work[iidx] = work[iidx] - tmp * data (i); | |
1756 } | 1755 } |
1757 } | 1756 } |
1758 } | 1757 } |
1759 | 1758 double atmp = 0; |
1760 for (octave_idx_type i = 0; i < nc; i++) | 1759 for (octave_idx_type i = 0; i < j+1; i++) |
1761 retval.xelem (perm[i], j) = work[i]; | 1760 { |
1762 } | 1761 atmp += fabs (work[i]); |
1763 | 1762 work[i] = 0.; |
1764 if (calc_cond) | 1763 } |
1765 { | 1764 if (atmp > ainvnorm) |
1766 // Calculation of 1-norm of inv(*this) | 1765 ainvnorm = atmp; |
1767 for (octave_idx_type i = 0; i < nm; i++) | 1766 } |
1768 work[i] = 0.; | 1767 rcond = 1. / ainvnorm / anorm; |
1769 | 1768 } |
1770 for (octave_idx_type j = 0; j < nr; j++) | 1769 } |
1771 { | 1770 else |
1772 work[j] = 1.; | 1771 { |
1773 | 1772 OCTAVE_LOCAL_BUFFER (double, work, nm); |
1774 for (octave_idx_type k = j; k >= 0; k--) | 1773 retval.resize (nc, b_nc); |
1774 | |
1775 for (octave_idx_type j = 0; j < b_nc; j++) | |
1776 { | |
1777 for (octave_idx_type i = 0; i < nr; i++) | |
1778 work[i] = b(i,j); | |
1779 for (octave_idx_type i = nr; i < nc; i++) | |
1780 work[i] = 0.; | |
1781 | |
1782 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1783 { | |
1784 if (work[k] != 0.) | |
1785 { | |
1786 if (ridx (cidx (k+1)-1) != k | |
1787 || data (cidx (k+1)-1) == 0.) | |
1775 { | 1788 { |
1776 octave_idx_type iidx = perm[k]; | 1789 err = -2; |
1777 | 1790 goto triangular_error; |
1778 if (work[k] != 0.) | |
1779 { | |
1780 double tmp = work[k] / data (cidx (iidx+1)-1); | |
1781 work[k] = tmp; | |
1782 for (octave_idx_type i = cidx (iidx); | |
1783 i < cidx (iidx+1)-1; i++) | |
1784 { | |
1785 octave_idx_type idx2 = ridx (i); | |
1786 work[idx2] = work[idx2] - tmp * data (i); | |
1787 } | |
1788 } | |
1789 } | 1791 } |
1790 double atmp = 0; | 1792 |
1791 for (octave_idx_type i = 0; i < j+1; i++) | 1793 double tmp = work[k] / data (cidx (k+1)-1); |
1794 work[k] = tmp; | |
1795 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
1792 { | 1796 { |
1793 atmp += fabs (work[i]); | 1797 octave_idx_type iidx = ridx (i); |
1794 work[i] = 0.; | 1798 work[iidx] = work[iidx] - tmp * data (i); |
1795 } | 1799 } |
1796 if (atmp > ainvnorm) | 1800 } |
1797 ainvnorm = atmp; | 1801 } |
1798 } | 1802 |
1799 rcond = 1. / ainvnorm / anorm; | 1803 for (octave_idx_type i = 0; i < nc; i++) |
1800 } | 1804 retval.xelem (i, j) = work[i]; |
1801 } | 1805 } |
1802 else | 1806 |
1803 { | 1807 if (calc_cond) |
1804 OCTAVE_LOCAL_BUFFER (double, work, nm); | 1808 { |
1805 retval.resize (nc, b_nc); | 1809 // Calculation of 1-norm of inv(*this) |
1806 | 1810 for (octave_idx_type i = 0; i < nm; i++) |
1807 for (octave_idx_type j = 0; j < b_nc; j++) | 1811 work[i] = 0.; |
1808 { | 1812 |
1809 for (octave_idx_type i = 0; i < nr; i++) | 1813 for (octave_idx_type j = 0; j < nr; j++) |
1810 work[i] = b(i,j); | 1814 { |
1811 for (octave_idx_type i = nr; i < nc; i++) | 1815 work[j] = 1.; |
1812 work[i] = 0.; | 1816 |
1813 | 1817 for (octave_idx_type k = j; k >= 0; k--) |
1814 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1815 { | 1818 { |
1816 if (work[k] != 0.) | 1819 if (work[k] != 0.) |
1817 { | 1820 { |
1818 if (ridx (cidx (k+1)-1) != k | |
1819 || data (cidx (k+1)-1) == 0.) | |
1820 { | |
1821 err = -2; | |
1822 goto triangular_error; | |
1823 } | |
1824 | |
1825 double tmp = work[k] / data (cidx (k+1)-1); | 1821 double tmp = work[k] / data (cidx (k+1)-1); |
1826 work[k] = tmp; | 1822 work[k] = tmp; |
1827 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | 1823 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) |
1828 { | 1824 { |
1829 octave_idx_type iidx = ridx (i); | 1825 octave_idx_type iidx = ridx (i); |
1830 work[iidx] = work[iidx] - tmp * data (i); | 1826 work[iidx] = work[iidx] - tmp * data (i); |
1831 } | 1827 } |
1832 } | 1828 } |
1833 } | 1829 } |
1834 | 1830 double atmp = 0; |
1835 for (octave_idx_type i = 0; i < nc; i++) | 1831 for (octave_idx_type i = 0; i < j+1; i++) |
1836 retval.xelem (i, j) = work[i]; | 1832 { |
1837 } | 1833 atmp += fabs (work[i]); |
1838 | 1834 work[i] = 0.; |
1839 if (calc_cond) | 1835 } |
1840 { | 1836 if (atmp > ainvnorm) |
1841 // Calculation of 1-norm of inv(*this) | 1837 ainvnorm = atmp; |
1842 for (octave_idx_type i = 0; i < nm; i++) | 1838 } |
1843 work[i] = 0.; | 1839 rcond = 1. / ainvnorm / anorm; |
1844 | 1840 } |
1845 for (octave_idx_type j = 0; j < nr; j++) | 1841 } |
1846 { | 1842 |
1847 work[j] = 1.; | 1843 triangular_error: |
1848 | 1844 if (err != 0) |
1849 for (octave_idx_type k = j; k >= 0; k--) | 1845 { |
1850 { | 1846 if (sing_handler) |
1851 if (work[k] != 0.) | 1847 { |
1852 { | 1848 sing_handler (rcond); |
1853 double tmp = work[k] / data (cidx (k+1)-1); | 1849 mattype.mark_as_rectangular (); |
1854 work[k] = tmp; | 1850 } |
1855 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | 1851 else |
1856 { | 1852 warn_singular_matrix (rcond); |
1857 octave_idx_type iidx = ridx (i); | 1853 } |
1858 work[iidx] = work[iidx] - tmp * data (i); | 1854 |
1859 } | 1855 volatile double rcond_plus_one = rcond + 1.0; |
1860 } | 1856 |
1861 } | 1857 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
1862 double atmp = 0; | 1858 { |
1863 for (octave_idx_type i = 0; i < j+1; i++) | 1859 err = -2; |
1864 { | 1860 |
1865 atmp += fabs (work[i]); | 1861 if (sing_handler) |
1866 work[i] = 0.; | 1862 { |
1867 } | 1863 sing_handler (rcond); |
1868 if (atmp > ainvnorm) | 1864 mattype.mark_as_rectangular (); |
1869 ainvnorm = atmp; | 1865 } |
1870 } | 1866 else |
1871 rcond = 1. / ainvnorm / anorm; | 1867 warn_singular_matrix (rcond); |
1872 } | 1868 } |
1873 } | |
1874 | |
1875 triangular_error: | |
1876 if (err != 0) | |
1877 { | |
1878 if (sing_handler) | |
1879 { | |
1880 sing_handler (rcond); | |
1881 mattype.mark_as_rectangular (); | |
1882 } | |
1883 else | |
1884 warn_singular_matrix (rcond); | |
1885 } | |
1886 | |
1887 volatile double rcond_plus_one = rcond + 1.0; | |
1888 | |
1889 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
1890 { | |
1891 err = -2; | |
1892 | |
1893 if (sing_handler) | |
1894 { | |
1895 sing_handler (rcond); | |
1896 mattype.mark_as_rectangular (); | |
1897 } | |
1898 else | |
1899 warn_singular_matrix (rcond); | |
1900 } | |
1901 } | |
1902 else | |
1903 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1904 } | 1869 } |
1905 | 1870 |
1906 return retval; | 1871 return retval; |
1907 } | 1872 } |
1908 | 1873 |
1920 err = 0; | 1885 err = 0; |
1921 | 1886 |
1922 if (nr != b.rows ()) | 1887 if (nr != b.rows ()) |
1923 (*current_liboctave_error_handler) | 1888 (*current_liboctave_error_handler) |
1924 ("matrix dimension mismatch solution of linear equations"); | 1889 ("matrix dimension mismatch solution of linear equations"); |
1925 else if (nr == 0 || nc == 0 || b.cols () == 0) | 1890 |
1891 if (nr == 0 || nc == 0 || b.cols () == 0) | |
1926 retval = SparseMatrix (nc, b.cols ()); | 1892 retval = SparseMatrix (nc, b.cols ()); |
1927 else | 1893 else |
1928 { | 1894 { |
1929 // Print spparms("spumoni") info if requested | 1895 // Print spparms("spumoni") info if requested |
1930 int typ = mattype.type (); | 1896 int typ = mattype.type (); |
1931 mattype.info (); | 1897 mattype.info (); |
1932 | 1898 |
1933 if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper) | 1899 if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper) |
1934 { | 1900 (*current_liboctave_error_handler) ("incorrect matrix type"); |
1935 double anorm = 0.; | 1901 |
1936 double ainvnorm = 0.; | 1902 double anorm = 0.; |
1937 rcond = 1.; | 1903 double ainvnorm = 0.; |
1904 rcond = 1.; | |
1905 | |
1906 if (calc_cond) | |
1907 { | |
1908 // Calculate the 1-norm of matrix for rcond calculation | |
1909 for (octave_idx_type j = 0; j < nc; j++) | |
1910 { | |
1911 double atmp = 0.; | |
1912 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
1913 atmp += fabs (data (i)); | |
1914 if (atmp > anorm) | |
1915 anorm = atmp; | |
1916 } | |
1917 } | |
1918 | |
1919 octave_idx_type b_nc = b.cols (); | |
1920 octave_idx_type b_nz = b.nnz (); | |
1921 retval = SparseMatrix (nc, b_nc, b_nz); | |
1922 retval.xcidx (0) = 0; | |
1923 octave_idx_type ii = 0; | |
1924 octave_idx_type x_nz = b_nz; | |
1925 | |
1926 if (typ == MatrixType::Permuted_Upper) | |
1927 { | |
1928 octave_idx_type *perm = mattype.triangular_perm (); | |
1929 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
1930 | |
1931 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
1932 for (octave_idx_type i = 0; i < nc; i++) | |
1933 rperm[perm[i]] = i; | |
1934 | |
1935 for (octave_idx_type j = 0; j < b_nc; j++) | |
1936 { | |
1937 for (octave_idx_type i = 0; i < nm; i++) | |
1938 work[i] = 0.; | |
1939 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
1940 work[b.ridx (i)] = b.data (i); | |
1941 | |
1942 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1943 { | |
1944 octave_idx_type kidx = perm[k]; | |
1945 | |
1946 if (work[k] != 0.) | |
1947 { | |
1948 if (ridx (cidx (kidx+1)-1) != k | |
1949 || data (cidx (kidx+1)-1) == 0.) | |
1950 { | |
1951 err = -2; | |
1952 goto triangular_error; | |
1953 } | |
1954 | |
1955 double tmp = work[k] / data (cidx (kidx+1)-1); | |
1956 work[k] = tmp; | |
1957 for (octave_idx_type i = cidx (kidx); | |
1958 i < cidx (kidx+1)-1; i++) | |
1959 { | |
1960 octave_idx_type iidx = ridx (i); | |
1961 work[iidx] = work[iidx] - tmp * data (i); | |
1962 } | |
1963 } | |
1964 } | |
1965 | |
1966 // Count nonzeros in work vector and adjust space in | |
1967 // retval if needed | |
1968 octave_idx_type new_nnz = 0; | |
1969 for (octave_idx_type i = 0; i < nc; i++) | |
1970 if (work[i] != 0.) | |
1971 new_nnz++; | |
1972 | |
1973 if (ii + new_nnz > x_nz) | |
1974 { | |
1975 // Resize the sparse matrix | |
1976 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
1977 retval.change_capacity (sz); | |
1978 x_nz = sz; | |
1979 } | |
1980 | |
1981 for (octave_idx_type i = 0; i < nc; i++) | |
1982 if (work[rperm[i]] != 0.) | |
1983 { | |
1984 retval.xridx (ii) = i; | |
1985 retval.xdata (ii++) = work[rperm[i]]; | |
1986 } | |
1987 retval.xcidx (j+1) = ii; | |
1988 } | |
1989 | |
1990 retval.maybe_compress (); | |
1938 | 1991 |
1939 if (calc_cond) | 1992 if (calc_cond) |
1940 { | 1993 { |
1941 // Calculate the 1-norm of matrix for rcond calculation | 1994 // Calculation of 1-norm of inv(*this) |
1942 for (octave_idx_type j = 0; j < nc; j++) | 1995 for (octave_idx_type i = 0; i < nm; i++) |
1943 { | 1996 work[i] = 0.; |
1944 double atmp = 0.; | 1997 |
1945 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 1998 for (octave_idx_type j = 0; j < nr; j++) |
1946 atmp += fabs (data (i)); | 1999 { |
1947 if (atmp > anorm) | 2000 work[j] = 1.; |
1948 anorm = atmp; | 2001 |
1949 } | 2002 for (octave_idx_type k = j; k >= 0; k--) |
1950 } | 2003 { |
1951 | 2004 octave_idx_type iidx = perm[k]; |
1952 octave_idx_type b_nc = b.cols (); | |
1953 octave_idx_type b_nz = b.nnz (); | |
1954 retval = SparseMatrix (nc, b_nc, b_nz); | |
1955 retval.xcidx (0) = 0; | |
1956 octave_idx_type ii = 0; | |
1957 octave_idx_type x_nz = b_nz; | |
1958 | |
1959 if (typ == MatrixType::Permuted_Upper) | |
1960 { | |
1961 octave_idx_type *perm = mattype.triangular_perm (); | |
1962 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
1963 | |
1964 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
1965 for (octave_idx_type i = 0; i < nc; i++) | |
1966 rperm[perm[i]] = i; | |
1967 | |
1968 for (octave_idx_type j = 0; j < b_nc; j++) | |
1969 { | |
1970 for (octave_idx_type i = 0; i < nm; i++) | |
1971 work[i] = 0.; | |
1972 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
1973 work[b.ridx (i)] = b.data (i); | |
1974 | |
1975 for (octave_idx_type k = nc-1; k >= 0; k--) | |
1976 { | |
1977 octave_idx_type kidx = perm[k]; | |
1978 | 2005 |
1979 if (work[k] != 0.) | 2006 if (work[k] != 0.) |
1980 { | 2007 { |
1981 if (ridx (cidx (kidx+1)-1) != k | 2008 double tmp = work[k] / data (cidx (iidx+1)-1); |
1982 || data (cidx (kidx+1)-1) == 0.) | 2009 work[k] = tmp; |
2010 for (octave_idx_type i = cidx (iidx); | |
2011 i < cidx (iidx+1)-1; i++) | |
1983 { | 2012 { |
1984 err = -2; | 2013 octave_idx_type idx2 = ridx (i); |
1985 goto triangular_error; | 2014 work[idx2] = work[idx2] - tmp * data (i); |
1986 } | 2015 } |
1987 | 2016 } |
1988 double tmp = work[k] / data (cidx (kidx+1)-1); | 2017 } |
2018 double atmp = 0; | |
2019 for (octave_idx_type i = 0; i < j+1; i++) | |
2020 { | |
2021 atmp += fabs (work[i]); | |
2022 work[i] = 0.; | |
2023 } | |
2024 if (atmp > ainvnorm) | |
2025 ainvnorm = atmp; | |
2026 } | |
2027 rcond = 1. / ainvnorm / anorm; | |
2028 } | |
2029 } | |
2030 else | |
2031 { | |
2032 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2033 | |
2034 for (octave_idx_type j = 0; j < b_nc; j++) | |
2035 { | |
2036 for (octave_idx_type i = 0; i < nm; i++) | |
2037 work[i] = 0.; | |
2038 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
2039 work[b.ridx (i)] = b.data (i); | |
2040 | |
2041 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2042 { | |
2043 if (work[k] != 0.) | |
2044 { | |
2045 if (ridx (cidx (k+1)-1) != k | |
2046 || data (cidx (k+1)-1) == 0.) | |
2047 { | |
2048 err = -2; | |
2049 goto triangular_error; | |
2050 } | |
2051 | |
2052 double tmp = work[k] / data (cidx (k+1)-1); | |
2053 work[k] = tmp; | |
2054 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2055 { | |
2056 octave_idx_type iidx = ridx (i); | |
2057 work[iidx] = work[iidx] - tmp * data (i); | |
2058 } | |
2059 } | |
2060 } | |
2061 | |
2062 // Count nonzeros in work vector and adjust space in | |
2063 // retval if needed | |
2064 octave_idx_type new_nnz = 0; | |
2065 for (octave_idx_type i = 0; i < nc; i++) | |
2066 if (work[i] != 0.) | |
2067 new_nnz++; | |
2068 | |
2069 if (ii + new_nnz > x_nz) | |
2070 { | |
2071 // Resize the sparse matrix | |
2072 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
2073 retval.change_capacity (sz); | |
2074 x_nz = sz; | |
2075 } | |
2076 | |
2077 for (octave_idx_type i = 0; i < nc; i++) | |
2078 if (work[i] != 0.) | |
2079 { | |
2080 retval.xridx (ii) = i; | |
2081 retval.xdata (ii++) = work[i]; | |
2082 } | |
2083 retval.xcidx (j+1) = ii; | |
2084 } | |
2085 | |
2086 retval.maybe_compress (); | |
2087 | |
2088 if (calc_cond) | |
2089 { | |
2090 // Calculation of 1-norm of inv(*this) | |
2091 for (octave_idx_type i = 0; i < nm; i++) | |
2092 work[i] = 0.; | |
2093 | |
2094 for (octave_idx_type j = 0; j < nr; j++) | |
2095 { | |
2096 work[j] = 1.; | |
2097 | |
2098 for (octave_idx_type k = j; k >= 0; k--) | |
2099 { | |
2100 if (work[k] != 0.) | |
2101 { | |
2102 double tmp = work[k] / data (cidx (k+1)-1); | |
1989 work[k] = tmp; | 2103 work[k] = tmp; |
1990 for (octave_idx_type i = cidx (kidx); | 2104 for (octave_idx_type i = cidx (k); |
1991 i < cidx (kidx+1)-1; i++) | 2105 i < cidx (k+1)-1; i++) |
1992 { | 2106 { |
1993 octave_idx_type iidx = ridx (i); | 2107 octave_idx_type iidx = ridx (i); |
1994 work[iidx] = work[iidx] - tmp * data (i); | 2108 work[iidx] = work[iidx] - tmp * data (i); |
1995 } | 2109 } |
1996 } | 2110 } |
1997 } | 2111 } |
1998 | 2112 double atmp = 0; |
1999 // Count nonzeros in work vector and adjust space in | 2113 for (octave_idx_type i = 0; i < j+1; i++) |
2000 // retval if needed | 2114 { |
2001 octave_idx_type new_nnz = 0; | 2115 atmp += fabs (work[i]); |
2002 for (octave_idx_type i = 0; i < nc; i++) | 2116 work[i] = 0.; |
2003 if (work[i] != 0.) | 2117 } |
2004 new_nnz++; | 2118 if (atmp > ainvnorm) |
2005 | 2119 ainvnorm = atmp; |
2006 if (ii + new_nnz > x_nz) | 2120 } |
2007 { | 2121 rcond = 1. / ainvnorm / anorm; |
2008 // Resize the sparse matrix | 2122 } |
2009 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | 2123 } |
2010 retval.change_capacity (sz); | 2124 |
2011 x_nz = sz; | 2125 triangular_error: |
2012 } | 2126 if (err != 0) |
2013 | 2127 { |
2014 for (octave_idx_type i = 0; i < nc; i++) | 2128 if (sing_handler) |
2015 if (work[rperm[i]] != 0.) | 2129 { |
2016 { | 2130 sing_handler (rcond); |
2017 retval.xridx (ii) = i; | 2131 mattype.mark_as_rectangular (); |
2018 retval.xdata (ii++) = work[rperm[i]]; | |
2019 } | |
2020 retval.xcidx (j+1) = ii; | |
2021 } | |
2022 | |
2023 retval.maybe_compress (); | |
2024 | |
2025 if (calc_cond) | |
2026 { | |
2027 // Calculation of 1-norm of inv(*this) | |
2028 for (octave_idx_type i = 0; i < nm; i++) | |
2029 work[i] = 0.; | |
2030 | |
2031 for (octave_idx_type j = 0; j < nr; j++) | |
2032 { | |
2033 work[j] = 1.; | |
2034 | |
2035 for (octave_idx_type k = j; k >= 0; k--) | |
2036 { | |
2037 octave_idx_type iidx = perm[k]; | |
2038 | |
2039 if (work[k] != 0.) | |
2040 { | |
2041 double tmp = work[k] / data (cidx (iidx+1)-1); | |
2042 work[k] = tmp; | |
2043 for (octave_idx_type i = cidx (iidx); | |
2044 i < cidx (iidx+1)-1; i++) | |
2045 { | |
2046 octave_idx_type idx2 = ridx (i); | |
2047 work[idx2] = work[idx2] - tmp * data (i); | |
2048 } | |
2049 } | |
2050 } | |
2051 double atmp = 0; | |
2052 for (octave_idx_type i = 0; i < j+1; i++) | |
2053 { | |
2054 atmp += fabs (work[i]); | |
2055 work[i] = 0.; | |
2056 } | |
2057 if (atmp > ainvnorm) | |
2058 ainvnorm = atmp; | |
2059 } | |
2060 rcond = 1. / ainvnorm / anorm; | |
2061 } | |
2062 } | 2132 } |
2063 else | 2133 else |
2064 { | 2134 warn_singular_matrix (rcond); |
2065 OCTAVE_LOCAL_BUFFER (double, work, nm); | 2135 } |
2066 | 2136 |
2067 for (octave_idx_type j = 0; j < b_nc; j++) | 2137 volatile double rcond_plus_one = rcond + 1.0; |
2068 { | 2138 |
2069 for (octave_idx_type i = 0; i < nm; i++) | 2139 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
2070 work[i] = 0.; | 2140 { |
2071 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 2141 err = -2; |
2072 work[b.ridx (i)] = b.data (i); | 2142 |
2073 | 2143 if (sing_handler) |
2074 for (octave_idx_type k = nc-1; k >= 0; k--) | 2144 { |
2075 { | 2145 sing_handler (rcond); |
2076 if (work[k] != 0.) | 2146 mattype.mark_as_rectangular (); |
2077 { | 2147 } |
2078 if (ridx (cidx (k+1)-1) != k | 2148 else |
2079 || data (cidx (k+1)-1) == 0.) | 2149 warn_singular_matrix (rcond); |
2080 { | 2150 } |
2081 err = -2; | |
2082 goto triangular_error; | |
2083 } | |
2084 | |
2085 double tmp = work[k] / data (cidx (k+1)-1); | |
2086 work[k] = tmp; | |
2087 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2088 { | |
2089 octave_idx_type iidx = ridx (i); | |
2090 work[iidx] = work[iidx] - tmp * data (i); | |
2091 } | |
2092 } | |
2093 } | |
2094 | |
2095 // Count nonzeros in work vector and adjust space in | |
2096 // retval if needed | |
2097 octave_idx_type new_nnz = 0; | |
2098 for (octave_idx_type i = 0; i < nc; i++) | |
2099 if (work[i] != 0.) | |
2100 new_nnz++; | |
2101 | |
2102 if (ii + new_nnz > x_nz) | |
2103 { | |
2104 // Resize the sparse matrix | |
2105 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
2106 retval.change_capacity (sz); | |
2107 x_nz = sz; | |
2108 } | |
2109 | |
2110 for (octave_idx_type i = 0; i < nc; i++) | |
2111 if (work[i] != 0.) | |
2112 { | |
2113 retval.xridx (ii) = i; | |
2114 retval.xdata (ii++) = work[i]; | |
2115 } | |
2116 retval.xcidx (j+1) = ii; | |
2117 } | |
2118 | |
2119 retval.maybe_compress (); | |
2120 | |
2121 if (calc_cond) | |
2122 { | |
2123 // Calculation of 1-norm of inv(*this) | |
2124 for (octave_idx_type i = 0; i < nm; i++) | |
2125 work[i] = 0.; | |
2126 | |
2127 for (octave_idx_type j = 0; j < nr; j++) | |
2128 { | |
2129 work[j] = 1.; | |
2130 | |
2131 for (octave_idx_type k = j; k >= 0; k--) | |
2132 { | |
2133 if (work[k] != 0.) | |
2134 { | |
2135 double tmp = work[k] / data (cidx (k+1)-1); | |
2136 work[k] = tmp; | |
2137 for (octave_idx_type i = cidx (k); | |
2138 i < cidx (k+1)-1; i++) | |
2139 { | |
2140 octave_idx_type iidx = ridx (i); | |
2141 work[iidx] = work[iidx] - tmp * data (i); | |
2142 } | |
2143 } | |
2144 } | |
2145 double atmp = 0; | |
2146 for (octave_idx_type i = 0; i < j+1; i++) | |
2147 { | |
2148 atmp += fabs (work[i]); | |
2149 work[i] = 0.; | |
2150 } | |
2151 if (atmp > ainvnorm) | |
2152 ainvnorm = atmp; | |
2153 } | |
2154 rcond = 1. / ainvnorm / anorm; | |
2155 } | |
2156 } | |
2157 | |
2158 triangular_error: | |
2159 if (err != 0) | |
2160 { | |
2161 if (sing_handler) | |
2162 { | |
2163 sing_handler (rcond); | |
2164 mattype.mark_as_rectangular (); | |
2165 } | |
2166 else | |
2167 warn_singular_matrix (rcond); | |
2168 } | |
2169 | |
2170 volatile double rcond_plus_one = rcond + 1.0; | |
2171 | |
2172 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2173 { | |
2174 err = -2; | |
2175 | |
2176 if (sing_handler) | |
2177 { | |
2178 sing_handler (rcond); | |
2179 mattype.mark_as_rectangular (); | |
2180 } | |
2181 else | |
2182 warn_singular_matrix (rcond); | |
2183 } | |
2184 } | |
2185 else | |
2186 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2187 } | 2151 } |
2188 return retval; | 2152 return retval; |
2189 } | 2153 } |
2190 | 2154 |
2191 ComplexMatrix | 2155 ComplexMatrix |
2202 err = 0; | 2166 err = 0; |
2203 | 2167 |
2204 if (nr != b.rows ()) | 2168 if (nr != b.rows ()) |
2205 (*current_liboctave_error_handler) | 2169 (*current_liboctave_error_handler) |
2206 ("matrix dimension mismatch solution of linear equations"); | 2170 ("matrix dimension mismatch solution of linear equations"); |
2207 else if (nr == 0 || nc == 0 || b.cols () == 0) | 2171 |
2172 if (nr == 0 || nc == 0 || b.cols () == 0) | |
2208 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 2173 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
2209 else | 2174 else |
2210 { | 2175 { |
2211 // Print spparms("spumoni") info if requested | 2176 // Print spparms("spumoni") info if requested |
2212 int typ = mattype.type (); | 2177 int typ = mattype.type (); |
2213 mattype.info (); | 2178 mattype.info (); |
2214 | 2179 |
2215 if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper) | 2180 if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper) |
2216 { | 2181 (*current_liboctave_error_handler) ("incorrect matrix type"); |
2217 double anorm = 0.; | 2182 |
2218 double ainvnorm = 0.; | 2183 double anorm = 0.; |
2219 octave_idx_type b_nc = b.cols (); | 2184 double ainvnorm = 0.; |
2220 rcond = 1.; | 2185 octave_idx_type b_nc = b.cols (); |
2186 rcond = 1.; | |
2187 | |
2188 if (calc_cond) | |
2189 { | |
2190 // Calculate the 1-norm of matrix for rcond calculation | |
2191 for (octave_idx_type j = 0; j < nc; j++) | |
2192 { | |
2193 double atmp = 0.; | |
2194 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
2195 atmp += fabs (data (i)); | |
2196 if (atmp > anorm) | |
2197 anorm = atmp; | |
2198 } | |
2199 } | |
2200 | |
2201 if (typ == MatrixType::Permuted_Upper) | |
2202 { | |
2203 retval.resize (nc, b_nc); | |
2204 octave_idx_type *perm = mattype.triangular_perm (); | |
2205 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
2206 | |
2207 for (octave_idx_type j = 0; j < b_nc; j++) | |
2208 { | |
2209 for (octave_idx_type i = 0; i < nr; i++) | |
2210 cwork[i] = b(i,j); | |
2211 for (octave_idx_type i = nr; i < nc; i++) | |
2212 cwork[i] = 0.; | |
2213 | |
2214 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2215 { | |
2216 octave_idx_type kidx = perm[k]; | |
2217 | |
2218 if (cwork[k] != 0.) | |
2219 { | |
2220 if (ridx (cidx (kidx+1)-1) != k | |
2221 || data (cidx (kidx+1)-1) == 0.) | |
2222 { | |
2223 err = -2; | |
2224 goto triangular_error; | |
2225 } | |
2226 | |
2227 Complex tmp = cwork[k] / data (cidx (kidx+1)-1); | |
2228 cwork[k] = tmp; | |
2229 for (octave_idx_type i = cidx (kidx); | |
2230 i < cidx (kidx+1)-1; i++) | |
2231 { | |
2232 octave_idx_type iidx = ridx (i); | |
2233 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2234 } | |
2235 } | |
2236 } | |
2237 | |
2238 for (octave_idx_type i = 0; i < nc; i++) | |
2239 retval.xelem (perm[i], j) = cwork[i]; | |
2240 } | |
2221 | 2241 |
2222 if (calc_cond) | 2242 if (calc_cond) |
2223 { | 2243 { |
2224 // Calculate the 1-norm of matrix for rcond calculation | 2244 // Calculation of 1-norm of inv(*this) |
2225 for (octave_idx_type j = 0; j < nc; j++) | 2245 OCTAVE_LOCAL_BUFFER (double, work, nm); |
2226 { | 2246 for (octave_idx_type i = 0; i < nm; i++) |
2227 double atmp = 0.; | 2247 work[i] = 0.; |
2228 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 2248 |
2229 atmp += fabs (data (i)); | 2249 for (octave_idx_type j = 0; j < nr; j++) |
2230 if (atmp > anorm) | 2250 { |
2231 anorm = atmp; | 2251 work[j] = 1.; |
2232 } | 2252 |
2233 } | 2253 for (octave_idx_type k = j; k >= 0; k--) |
2234 | 2254 { |
2235 if (typ == MatrixType::Permuted_Upper) | 2255 octave_idx_type iidx = perm[k]; |
2236 { | 2256 |
2237 retval.resize (nc, b_nc); | 2257 if (work[k] != 0.) |
2238 octave_idx_type *perm = mattype.triangular_perm (); | |
2239 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
2240 | |
2241 for (octave_idx_type j = 0; j < b_nc; j++) | |
2242 { | |
2243 for (octave_idx_type i = 0; i < nr; i++) | |
2244 cwork[i] = b(i,j); | |
2245 for (octave_idx_type i = nr; i < nc; i++) | |
2246 cwork[i] = 0.; | |
2247 | |
2248 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2249 { | |
2250 octave_idx_type kidx = perm[k]; | |
2251 | |
2252 if (cwork[k] != 0.) | |
2253 { | 2258 { |
2254 if (ridx (cidx (kidx+1)-1) != k | 2259 double tmp = work[k] / data (cidx (iidx+1)-1); |
2255 || data (cidx (kidx+1)-1) == 0.) | 2260 work[k] = tmp; |
2261 for (octave_idx_type i = cidx (iidx); | |
2262 i < cidx (iidx+1)-1; i++) | |
2256 { | 2263 { |
2257 err = -2; | 2264 octave_idx_type idx2 = ridx (i); |
2258 goto triangular_error; | 2265 work[idx2] = work[idx2] - tmp * data (i); |
2259 } | 2266 } |
2260 | 2267 } |
2261 Complex tmp = cwork[k] / data (cidx (kidx+1)-1); | 2268 } |
2262 cwork[k] = tmp; | 2269 double atmp = 0; |
2263 for (octave_idx_type i = cidx (kidx); | 2270 for (octave_idx_type i = 0; i < j+1; i++) |
2264 i < cidx (kidx+1)-1; i++) | 2271 { |
2272 atmp += fabs (work[i]); | |
2273 work[i] = 0.; | |
2274 } | |
2275 if (atmp > ainvnorm) | |
2276 ainvnorm = atmp; | |
2277 } | |
2278 rcond = 1. / ainvnorm / anorm; | |
2279 } | |
2280 } | |
2281 else | |
2282 { | |
2283 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
2284 retval.resize (nc, b_nc); | |
2285 | |
2286 for (octave_idx_type j = 0; j < b_nc; j++) | |
2287 { | |
2288 for (octave_idx_type i = 0; i < nr; i++) | |
2289 cwork[i] = b(i,j); | |
2290 for (octave_idx_type i = nr; i < nc; i++) | |
2291 cwork[i] = 0.; | |
2292 | |
2293 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2294 { | |
2295 if (cwork[k] != 0.) | |
2296 { | |
2297 if (ridx (cidx (k+1)-1) != k | |
2298 || data (cidx (k+1)-1) == 0.) | |
2299 { | |
2300 err = -2; | |
2301 goto triangular_error; | |
2302 } | |
2303 | |
2304 Complex tmp = cwork[k] / data (cidx (k+1)-1); | |
2305 cwork[k] = tmp; | |
2306 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2307 { | |
2308 octave_idx_type iidx = ridx (i); | |
2309 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2310 } | |
2311 } | |
2312 } | |
2313 | |
2314 for (octave_idx_type i = 0; i < nc; i++) | |
2315 retval.xelem (i, j) = cwork[i]; | |
2316 } | |
2317 | |
2318 if (calc_cond) | |
2319 { | |
2320 // Calculation of 1-norm of inv(*this) | |
2321 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2322 for (octave_idx_type i = 0; i < nm; i++) | |
2323 work[i] = 0.; | |
2324 | |
2325 for (octave_idx_type j = 0; j < nr; j++) | |
2326 { | |
2327 work[j] = 1.; | |
2328 | |
2329 for (octave_idx_type k = j; k >= 0; k--) | |
2330 { | |
2331 if (work[k] != 0.) | |
2332 { | |
2333 double tmp = work[k] / data (cidx (k+1)-1); | |
2334 work[k] = tmp; | |
2335 for (octave_idx_type i = cidx (k); | |
2336 i < cidx (k+1)-1; i++) | |
2265 { | 2337 { |
2266 octave_idx_type iidx = ridx (i); | 2338 octave_idx_type iidx = ridx (i); |
2267 cwork[iidx] = cwork[iidx] - tmp * data (i); | 2339 work[iidx] = work[iidx] - tmp * data (i); |
2268 } | 2340 } |
2269 } | 2341 } |
2270 } | 2342 } |
2271 | 2343 double atmp = 0; |
2272 for (octave_idx_type i = 0; i < nc; i++) | 2344 for (octave_idx_type i = 0; i < j+1; i++) |
2273 retval.xelem (perm[i], j) = cwork[i]; | 2345 { |
2274 } | 2346 atmp += fabs (work[i]); |
2275 | 2347 work[i] = 0.; |
2276 if (calc_cond) | 2348 } |
2277 { | 2349 if (atmp > ainvnorm) |
2278 // Calculation of 1-norm of inv(*this) | 2350 ainvnorm = atmp; |
2279 OCTAVE_LOCAL_BUFFER (double, work, nm); | 2351 } |
2280 for (octave_idx_type i = 0; i < nm; i++) | 2352 rcond = 1. / ainvnorm / anorm; |
2281 work[i] = 0.; | 2353 } |
2282 | 2354 } |
2283 for (octave_idx_type j = 0; j < nr; j++) | 2355 |
2284 { | 2356 triangular_error: |
2285 work[j] = 1.; | 2357 if (err != 0) |
2286 | 2358 { |
2287 for (octave_idx_type k = j; k >= 0; k--) | 2359 if (sing_handler) |
2288 { | 2360 { |
2289 octave_idx_type iidx = perm[k]; | 2361 sing_handler (rcond); |
2290 | 2362 mattype.mark_as_rectangular (); |
2291 if (work[k] != 0.) | |
2292 { | |
2293 double tmp = work[k] / data (cidx (iidx+1)-1); | |
2294 work[k] = tmp; | |
2295 for (octave_idx_type i = cidx (iidx); | |
2296 i < cidx (iidx+1)-1; i++) | |
2297 { | |
2298 octave_idx_type idx2 = ridx (i); | |
2299 work[idx2] = work[idx2] - tmp * data (i); | |
2300 } | |
2301 } | |
2302 } | |
2303 double atmp = 0; | |
2304 for (octave_idx_type i = 0; i < j+1; i++) | |
2305 { | |
2306 atmp += fabs (work[i]); | |
2307 work[i] = 0.; | |
2308 } | |
2309 if (atmp > ainvnorm) | |
2310 ainvnorm = atmp; | |
2311 } | |
2312 rcond = 1. / ainvnorm / anorm; | |
2313 } | |
2314 } | 2363 } |
2315 else | 2364 else |
2316 { | 2365 warn_singular_matrix (rcond); |
2317 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | 2366 } |
2318 retval.resize (nc, b_nc); | 2367 |
2319 | 2368 volatile double rcond_plus_one = rcond + 1.0; |
2320 for (octave_idx_type j = 0; j < b_nc; j++) | 2369 |
2321 { | 2370 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
2322 for (octave_idx_type i = 0; i < nr; i++) | 2371 { |
2323 cwork[i] = b(i,j); | 2372 err = -2; |
2324 for (octave_idx_type i = nr; i < nc; i++) | 2373 |
2325 cwork[i] = 0.; | 2374 if (sing_handler) |
2326 | 2375 { |
2327 for (octave_idx_type k = nc-1; k >= 0; k--) | 2376 sing_handler (rcond); |
2328 { | 2377 mattype.mark_as_rectangular (); |
2329 if (cwork[k] != 0.) | 2378 } |
2330 { | 2379 else |
2331 if (ridx (cidx (k+1)-1) != k | 2380 warn_singular_matrix (rcond); |
2332 || data (cidx (k+1)-1) == 0.) | 2381 } |
2333 { | |
2334 err = -2; | |
2335 goto triangular_error; | |
2336 } | |
2337 | |
2338 Complex tmp = cwork[k] / data (cidx (k+1)-1); | |
2339 cwork[k] = tmp; | |
2340 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2341 { | |
2342 octave_idx_type iidx = ridx (i); | |
2343 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2344 } | |
2345 } | |
2346 } | |
2347 | |
2348 for (octave_idx_type i = 0; i < nc; i++) | |
2349 retval.xelem (i, j) = cwork[i]; | |
2350 } | |
2351 | |
2352 if (calc_cond) | |
2353 { | |
2354 // Calculation of 1-norm of inv(*this) | |
2355 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2356 for (octave_idx_type i = 0; i < nm; i++) | |
2357 work[i] = 0.; | |
2358 | |
2359 for (octave_idx_type j = 0; j < nr; j++) | |
2360 { | |
2361 work[j] = 1.; | |
2362 | |
2363 for (octave_idx_type k = j; k >= 0; k--) | |
2364 { | |
2365 if (work[k] != 0.) | |
2366 { | |
2367 double tmp = work[k] / data (cidx (k+1)-1); | |
2368 work[k] = tmp; | |
2369 for (octave_idx_type i = cidx (k); | |
2370 i < cidx (k+1)-1; i++) | |
2371 { | |
2372 octave_idx_type iidx = ridx (i); | |
2373 work[iidx] = work[iidx] - tmp * data (i); | |
2374 } | |
2375 } | |
2376 } | |
2377 double atmp = 0; | |
2378 for (octave_idx_type i = 0; i < j+1; i++) | |
2379 { | |
2380 atmp += fabs (work[i]); | |
2381 work[i] = 0.; | |
2382 } | |
2383 if (atmp > ainvnorm) | |
2384 ainvnorm = atmp; | |
2385 } | |
2386 rcond = 1. / ainvnorm / anorm; | |
2387 } | |
2388 } | |
2389 | |
2390 triangular_error: | |
2391 if (err != 0) | |
2392 { | |
2393 if (sing_handler) | |
2394 { | |
2395 sing_handler (rcond); | |
2396 mattype.mark_as_rectangular (); | |
2397 } | |
2398 else | |
2399 warn_singular_matrix (rcond); | |
2400 } | |
2401 | |
2402 volatile double rcond_plus_one = rcond + 1.0; | |
2403 | |
2404 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2405 { | |
2406 err = -2; | |
2407 | |
2408 if (sing_handler) | |
2409 { | |
2410 sing_handler (rcond); | |
2411 mattype.mark_as_rectangular (); | |
2412 } | |
2413 else | |
2414 warn_singular_matrix (rcond); | |
2415 } | |
2416 } | |
2417 else | |
2418 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2419 } | 2382 } |
2420 | 2383 |
2421 return retval; | 2384 return retval; |
2422 } | 2385 } |
2423 | 2386 |
2435 err = 0; | 2398 err = 0; |
2436 | 2399 |
2437 if (nr != b.rows ()) | 2400 if (nr != b.rows ()) |
2438 (*current_liboctave_error_handler) | 2401 (*current_liboctave_error_handler) |
2439 ("matrix dimension mismatch solution of linear equations"); | 2402 ("matrix dimension mismatch solution of linear equations"); |
2440 else if (nr == 0 || nc == 0 || b.cols () == 0) | 2403 |
2404 if (nr == 0 || nc == 0 || b.cols () == 0) | |
2441 retval = SparseComplexMatrix (nc, b.cols ()); | 2405 retval = SparseComplexMatrix (nc, b.cols ()); |
2442 else | 2406 else |
2443 { | 2407 { |
2444 // Print spparms("spumoni") info if requested | 2408 // Print spparms("spumoni") info if requested |
2445 int typ = mattype.type (); | 2409 int typ = mattype.type (); |
2446 mattype.info (); | 2410 mattype.info (); |
2447 | 2411 |
2448 if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper) | 2412 if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper) |
2449 { | 2413 (*current_liboctave_error_handler) ("incorrect matrix type"); |
2450 double anorm = 0.; | 2414 |
2451 double ainvnorm = 0.; | 2415 double anorm = 0.; |
2452 rcond = 1.; | 2416 double ainvnorm = 0.; |
2417 rcond = 1.; | |
2418 | |
2419 if (calc_cond) | |
2420 { | |
2421 // Calculate the 1-norm of matrix for rcond calculation | |
2422 for (octave_idx_type j = 0; j < nc; j++) | |
2423 { | |
2424 double atmp = 0.; | |
2425 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
2426 atmp += fabs (data (i)); | |
2427 if (atmp > anorm) | |
2428 anorm = atmp; | |
2429 } | |
2430 } | |
2431 | |
2432 octave_idx_type b_nc = b.cols (); | |
2433 octave_idx_type b_nz = b.nnz (); | |
2434 retval = SparseComplexMatrix (nc, b_nc, b_nz); | |
2435 retval.xcidx (0) = 0; | |
2436 octave_idx_type ii = 0; | |
2437 octave_idx_type x_nz = b_nz; | |
2438 | |
2439 if (typ == MatrixType::Permuted_Upper) | |
2440 { | |
2441 octave_idx_type *perm = mattype.triangular_perm (); | |
2442 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
2443 | |
2444 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
2445 for (octave_idx_type i = 0; i < nc; i++) | |
2446 rperm[perm[i]] = i; | |
2447 | |
2448 for (octave_idx_type j = 0; j < b_nc; j++) | |
2449 { | |
2450 for (octave_idx_type i = 0; i < nm; i++) | |
2451 cwork[i] = 0.; | |
2452 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
2453 cwork[b.ridx (i)] = b.data (i); | |
2454 | |
2455 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2456 { | |
2457 octave_idx_type kidx = perm[k]; | |
2458 | |
2459 if (cwork[k] != 0.) | |
2460 { | |
2461 if (ridx (cidx (kidx+1)-1) != k | |
2462 || data (cidx (kidx+1)-1) == 0.) | |
2463 { | |
2464 err = -2; | |
2465 goto triangular_error; | |
2466 } | |
2467 | |
2468 Complex tmp = cwork[k] / data (cidx (kidx+1)-1); | |
2469 cwork[k] = tmp; | |
2470 for (octave_idx_type i = cidx (kidx); | |
2471 i < cidx (kidx+1)-1; i++) | |
2472 { | |
2473 octave_idx_type iidx = ridx (i); | |
2474 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2475 } | |
2476 } | |
2477 } | |
2478 | |
2479 // Count nonzeros in work vector and adjust space in | |
2480 // retval if needed | |
2481 octave_idx_type new_nnz = 0; | |
2482 for (octave_idx_type i = 0; i < nc; i++) | |
2483 if (cwork[i] != 0.) | |
2484 new_nnz++; | |
2485 | |
2486 if (ii + new_nnz > x_nz) | |
2487 { | |
2488 // Resize the sparse matrix | |
2489 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
2490 retval.change_capacity (sz); | |
2491 x_nz = sz; | |
2492 } | |
2493 | |
2494 for (octave_idx_type i = 0; i < nc; i++) | |
2495 if (cwork[rperm[i]] != 0.) | |
2496 { | |
2497 retval.xridx (ii) = i; | |
2498 retval.xdata (ii++) = cwork[rperm[i]]; | |
2499 } | |
2500 retval.xcidx (j+1) = ii; | |
2501 } | |
2502 | |
2503 retval.maybe_compress (); | |
2453 | 2504 |
2454 if (calc_cond) | 2505 if (calc_cond) |
2455 { | 2506 { |
2456 // Calculate the 1-norm of matrix for rcond calculation | 2507 // Calculation of 1-norm of inv(*this) |
2457 for (octave_idx_type j = 0; j < nc; j++) | 2508 OCTAVE_LOCAL_BUFFER (double, work, nm); |
2458 { | 2509 for (octave_idx_type i = 0; i < nm; i++) |
2459 double atmp = 0.; | 2510 work[i] = 0.; |
2460 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 2511 |
2461 atmp += fabs (data (i)); | 2512 for (octave_idx_type j = 0; j < nr; j++) |
2462 if (atmp > anorm) | 2513 { |
2463 anorm = atmp; | 2514 work[j] = 1.; |
2464 } | 2515 |
2465 } | 2516 for (octave_idx_type k = j; k >= 0; k--) |
2466 | 2517 { |
2467 octave_idx_type b_nc = b.cols (); | 2518 octave_idx_type iidx = perm[k]; |
2468 octave_idx_type b_nz = b.nnz (); | 2519 |
2469 retval = SparseComplexMatrix (nc, b_nc, b_nz); | 2520 if (work[k] != 0.) |
2470 retval.xcidx (0) = 0; | 2521 { |
2471 octave_idx_type ii = 0; | 2522 double tmp = work[k] / data (cidx (iidx+1)-1); |
2472 octave_idx_type x_nz = b_nz; | 2523 work[k] = tmp; |
2473 | 2524 for (octave_idx_type i = cidx (iidx); |
2474 if (typ == MatrixType::Permuted_Upper) | 2525 i < cidx (iidx+1)-1; i++) |
2475 { | 2526 { |
2476 octave_idx_type *perm = mattype.triangular_perm (); | 2527 octave_idx_type idx2 = ridx (i); |
2477 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | 2528 work[idx2] = work[idx2] - tmp * data (i); |
2478 | 2529 } |
2479 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | 2530 } |
2531 } | |
2532 double atmp = 0; | |
2533 for (octave_idx_type i = 0; i < j+1; i++) | |
2534 { | |
2535 atmp += fabs (work[i]); | |
2536 work[i] = 0.; | |
2537 } | |
2538 if (atmp > ainvnorm) | |
2539 ainvnorm = atmp; | |
2540 } | |
2541 rcond = 1. / ainvnorm / anorm; | |
2542 } | |
2543 } | |
2544 else | |
2545 { | |
2546 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
2547 | |
2548 for (octave_idx_type j = 0; j < b_nc; j++) | |
2549 { | |
2550 for (octave_idx_type i = 0; i < nm; i++) | |
2551 cwork[i] = 0.; | |
2552 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
2553 cwork[b.ridx (i)] = b.data (i); | |
2554 | |
2555 for (octave_idx_type k = nc-1; k >= 0; k--) | |
2556 { | |
2557 if (cwork[k] != 0.) | |
2558 { | |
2559 if (ridx (cidx (k+1)-1) != k | |
2560 || data (cidx (k+1)-1) == 0.) | |
2561 { | |
2562 err = -2; | |
2563 goto triangular_error; | |
2564 } | |
2565 | |
2566 Complex tmp = cwork[k] / data (cidx (k+1)-1); | |
2567 cwork[k] = tmp; | |
2568 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2569 { | |
2570 octave_idx_type iidx = ridx (i); | |
2571 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2572 } | |
2573 } | |
2574 } | |
2575 | |
2576 // Count nonzeros in work vector and adjust space in | |
2577 // retval if needed | |
2578 octave_idx_type new_nnz = 0; | |
2480 for (octave_idx_type i = 0; i < nc; i++) | 2579 for (octave_idx_type i = 0; i < nc; i++) |
2481 rperm[perm[i]] = i; | 2580 if (cwork[i] != 0.) |
2482 | 2581 new_nnz++; |
2483 for (octave_idx_type j = 0; j < b_nc; j++) | 2582 |
2484 { | 2583 if (ii + new_nnz > x_nz) |
2485 for (octave_idx_type i = 0; i < nm; i++) | 2584 { |
2486 cwork[i] = 0.; | 2585 // Resize the sparse matrix |
2487 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 2586 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
2488 cwork[b.ridx (i)] = b.data (i); | 2587 retval.change_capacity (sz); |
2489 | 2588 x_nz = sz; |
2490 for (octave_idx_type k = nc-1; k >= 0; k--) | 2589 } |
2491 { | 2590 |
2492 octave_idx_type kidx = perm[k]; | 2591 for (octave_idx_type i = 0; i < nc; i++) |
2493 | 2592 if (cwork[i] != 0.) |
2494 if (cwork[k] != 0.) | 2593 { |
2594 retval.xridx (ii) = i; | |
2595 retval.xdata (ii++) = cwork[i]; | |
2596 } | |
2597 retval.xcidx (j+1) = ii; | |
2598 } | |
2599 | |
2600 retval.maybe_compress (); | |
2601 | |
2602 if (calc_cond) | |
2603 { | |
2604 // Calculation of 1-norm of inv(*this) | |
2605 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2606 for (octave_idx_type i = 0; i < nm; i++) | |
2607 work[i] = 0.; | |
2608 | |
2609 for (octave_idx_type j = 0; j < nr; j++) | |
2610 { | |
2611 work[j] = 1.; | |
2612 | |
2613 for (octave_idx_type k = j; k >= 0; k--) | |
2614 { | |
2615 if (work[k] != 0.) | |
2495 { | 2616 { |
2496 if (ridx (cidx (kidx+1)-1) != k | 2617 double tmp = work[k] / data (cidx (k+1)-1); |
2497 || data (cidx (kidx+1)-1) == 0.) | 2618 work[k] = tmp; |
2498 { | 2619 for (octave_idx_type i = cidx (k); |
2499 err = -2; | 2620 i < cidx (k+1)-1; i++) |
2500 goto triangular_error; | |
2501 } | |
2502 | |
2503 Complex tmp = cwork[k] / data (cidx (kidx+1)-1); | |
2504 cwork[k] = tmp; | |
2505 for (octave_idx_type i = cidx (kidx); | |
2506 i < cidx (kidx+1)-1; i++) | |
2507 { | 2621 { |
2508 octave_idx_type iidx = ridx (i); | 2622 octave_idx_type iidx = ridx (i); |
2509 cwork[iidx] = cwork[iidx] - tmp * data (i); | 2623 work[iidx] = work[iidx] - tmp * data (i); |
2510 } | 2624 } |
2511 } | 2625 } |
2512 } | 2626 } |
2513 | 2627 double atmp = 0; |
2514 // Count nonzeros in work vector and adjust space in | 2628 for (octave_idx_type i = 0; i < j+1; i++) |
2515 // retval if needed | 2629 { |
2516 octave_idx_type new_nnz = 0; | 2630 atmp += fabs (work[i]); |
2517 for (octave_idx_type i = 0; i < nc; i++) | 2631 work[i] = 0.; |
2518 if (cwork[i] != 0.) | 2632 } |
2519 new_nnz++; | 2633 if (atmp > ainvnorm) |
2520 | 2634 ainvnorm = atmp; |
2521 if (ii + new_nnz > x_nz) | 2635 } |
2522 { | 2636 rcond = 1. / ainvnorm / anorm; |
2523 // Resize the sparse matrix | 2637 } |
2524 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | 2638 } |
2525 retval.change_capacity (sz); | 2639 |
2526 x_nz = sz; | 2640 triangular_error: |
2527 } | 2641 if (err != 0) |
2528 | 2642 { |
2529 for (octave_idx_type i = 0; i < nc; i++) | 2643 if (sing_handler) |
2530 if (cwork[rperm[i]] != 0.) | 2644 { |
2531 { | 2645 sing_handler (rcond); |
2532 retval.xridx (ii) = i; | 2646 mattype.mark_as_rectangular (); |
2533 retval.xdata (ii++) = cwork[rperm[i]]; | |
2534 } | |
2535 retval.xcidx (j+1) = ii; | |
2536 } | |
2537 | |
2538 retval.maybe_compress (); | |
2539 | |
2540 if (calc_cond) | |
2541 { | |
2542 // Calculation of 1-norm of inv(*this) | |
2543 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2544 for (octave_idx_type i = 0; i < nm; i++) | |
2545 work[i] = 0.; | |
2546 | |
2547 for (octave_idx_type j = 0; j < nr; j++) | |
2548 { | |
2549 work[j] = 1.; | |
2550 | |
2551 for (octave_idx_type k = j; k >= 0; k--) | |
2552 { | |
2553 octave_idx_type iidx = perm[k]; | |
2554 | |
2555 if (work[k] != 0.) | |
2556 { | |
2557 double tmp = work[k] / data (cidx (iidx+1)-1); | |
2558 work[k] = tmp; | |
2559 for (octave_idx_type i = cidx (iidx); | |
2560 i < cidx (iidx+1)-1; i++) | |
2561 { | |
2562 octave_idx_type idx2 = ridx (i); | |
2563 work[idx2] = work[idx2] - tmp * data (i); | |
2564 } | |
2565 } | |
2566 } | |
2567 double atmp = 0; | |
2568 for (octave_idx_type i = 0; i < j+1; i++) | |
2569 { | |
2570 atmp += fabs (work[i]); | |
2571 work[i] = 0.; | |
2572 } | |
2573 if (atmp > ainvnorm) | |
2574 ainvnorm = atmp; | |
2575 } | |
2576 rcond = 1. / ainvnorm / anorm; | |
2577 } | |
2578 } | 2647 } |
2579 else | 2648 else |
2580 { | 2649 warn_singular_matrix (rcond); |
2581 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | 2650 } |
2582 | 2651 |
2583 for (octave_idx_type j = 0; j < b_nc; j++) | 2652 volatile double rcond_plus_one = rcond + 1.0; |
2584 { | 2653 |
2585 for (octave_idx_type i = 0; i < nm; i++) | 2654 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
2586 cwork[i] = 0.; | 2655 { |
2587 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 2656 err = -2; |
2588 cwork[b.ridx (i)] = b.data (i); | 2657 |
2589 | 2658 if (sing_handler) |
2590 for (octave_idx_type k = nc-1; k >= 0; k--) | 2659 { |
2591 { | 2660 sing_handler (rcond); |
2592 if (cwork[k] != 0.) | 2661 mattype.mark_as_rectangular (); |
2593 { | 2662 } |
2594 if (ridx (cidx (k+1)-1) != k | 2663 else |
2595 || data (cidx (k+1)-1) == 0.) | 2664 warn_singular_matrix (rcond); |
2596 { | 2665 } |
2597 err = -2; | |
2598 goto triangular_error; | |
2599 } | |
2600 | |
2601 Complex tmp = cwork[k] / data (cidx (k+1)-1); | |
2602 cwork[k] = tmp; | |
2603 for (octave_idx_type i = cidx (k); i < cidx (k+1)-1; i++) | |
2604 { | |
2605 octave_idx_type iidx = ridx (i); | |
2606 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
2607 } | |
2608 } | |
2609 } | |
2610 | |
2611 // Count nonzeros in work vector and adjust space in | |
2612 // retval if needed | |
2613 octave_idx_type new_nnz = 0; | |
2614 for (octave_idx_type i = 0; i < nc; i++) | |
2615 if (cwork[i] != 0.) | |
2616 new_nnz++; | |
2617 | |
2618 if (ii + new_nnz > x_nz) | |
2619 { | |
2620 // Resize the sparse matrix | |
2621 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
2622 retval.change_capacity (sz); | |
2623 x_nz = sz; | |
2624 } | |
2625 | |
2626 for (octave_idx_type i = 0; i < nc; i++) | |
2627 if (cwork[i] != 0.) | |
2628 { | |
2629 retval.xridx (ii) = i; | |
2630 retval.xdata (ii++) = cwork[i]; | |
2631 } | |
2632 retval.xcidx (j+1) = ii; | |
2633 } | |
2634 | |
2635 retval.maybe_compress (); | |
2636 | |
2637 if (calc_cond) | |
2638 { | |
2639 // Calculation of 1-norm of inv(*this) | |
2640 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2641 for (octave_idx_type i = 0; i < nm; i++) | |
2642 work[i] = 0.; | |
2643 | |
2644 for (octave_idx_type j = 0; j < nr; j++) | |
2645 { | |
2646 work[j] = 1.; | |
2647 | |
2648 for (octave_idx_type k = j; k >= 0; k--) | |
2649 { | |
2650 if (work[k] != 0.) | |
2651 { | |
2652 double tmp = work[k] / data (cidx (k+1)-1); | |
2653 work[k] = tmp; | |
2654 for (octave_idx_type i = cidx (k); | |
2655 i < cidx (k+1)-1; i++) | |
2656 { | |
2657 octave_idx_type iidx = ridx (i); | |
2658 work[iidx] = work[iidx] - tmp * data (i); | |
2659 } | |
2660 } | |
2661 } | |
2662 double atmp = 0; | |
2663 for (octave_idx_type i = 0; i < j+1; i++) | |
2664 { | |
2665 atmp += fabs (work[i]); | |
2666 work[i] = 0.; | |
2667 } | |
2668 if (atmp > ainvnorm) | |
2669 ainvnorm = atmp; | |
2670 } | |
2671 rcond = 1. / ainvnorm / anorm; | |
2672 } | |
2673 } | |
2674 | |
2675 triangular_error: | |
2676 if (err != 0) | |
2677 { | |
2678 if (sing_handler) | |
2679 { | |
2680 sing_handler (rcond); | |
2681 mattype.mark_as_rectangular (); | |
2682 } | |
2683 else | |
2684 warn_singular_matrix (rcond); | |
2685 } | |
2686 | |
2687 volatile double rcond_plus_one = rcond + 1.0; | |
2688 | |
2689 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2690 { | |
2691 err = -2; | |
2692 | |
2693 if (sing_handler) | |
2694 { | |
2695 sing_handler (rcond); | |
2696 mattype.mark_as_rectangular (); | |
2697 } | |
2698 else | |
2699 warn_singular_matrix (rcond); | |
2700 } | |
2701 } | |
2702 else | |
2703 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2704 } | 2666 } |
2705 | 2667 |
2706 return retval; | 2668 return retval; |
2707 } | 2669 } |
2708 | 2670 |
2720 err = 0; | 2682 err = 0; |
2721 | 2683 |
2722 if (nr != b.rows ()) | 2684 if (nr != b.rows ()) |
2723 (*current_liboctave_error_handler) | 2685 (*current_liboctave_error_handler) |
2724 ("matrix dimension mismatch solution of linear equations"); | 2686 ("matrix dimension mismatch solution of linear equations"); |
2725 else if (nr == 0 || nc == 0 || b.cols () == 0) | 2687 |
2688 if (nr == 0 || nc == 0 || b.cols () == 0) | |
2726 retval = Matrix (nc, b.cols (), 0.0); | 2689 retval = Matrix (nc, b.cols (), 0.0); |
2727 else | 2690 else |
2728 { | 2691 { |
2729 // Print spparms("spumoni") info if requested | 2692 // Print spparms("spumoni") info if requested |
2730 int typ = mattype.type (); | 2693 int typ = mattype.type (); |
2731 mattype.info (); | 2694 mattype.info (); |
2732 | 2695 |
2733 if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower) | 2696 if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower) |
2734 { | 2697 (*current_liboctave_error_handler) ("incorrect matrix type"); |
2735 double anorm = 0.; | 2698 |
2736 double ainvnorm = 0.; | 2699 double anorm = 0.; |
2737 octave_idx_type b_nc = b.cols (); | 2700 double ainvnorm = 0.; |
2738 rcond = 1.; | 2701 octave_idx_type b_nc = b.cols (); |
2702 rcond = 1.; | |
2703 | |
2704 if (calc_cond) | |
2705 { | |
2706 // Calculate the 1-norm of matrix for rcond calculation | |
2707 for (octave_idx_type j = 0; j < nc; j++) | |
2708 { | |
2709 double atmp = 0.; | |
2710 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
2711 atmp += fabs (data (i)); | |
2712 if (atmp > anorm) | |
2713 anorm = atmp; | |
2714 } | |
2715 } | |
2716 | |
2717 if (typ == MatrixType::Permuted_Lower) | |
2718 { | |
2719 retval.resize (nc, b_nc); | |
2720 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2721 octave_idx_type *perm = mattype.triangular_perm (); | |
2722 | |
2723 for (octave_idx_type j = 0; j < b_nc; j++) | |
2724 { | |
2725 if (nc > nr) | |
2726 for (octave_idx_type i = 0; i < nm; i++) | |
2727 work[i] = 0.; | |
2728 for (octave_idx_type i = 0; i < nr; i++) | |
2729 work[perm[i]] = b(i,j); | |
2730 | |
2731 for (octave_idx_type k = 0; k < nc; k++) | |
2732 { | |
2733 if (work[k] != 0.) | |
2734 { | |
2735 octave_idx_type minr = nr; | |
2736 octave_idx_type mini = 0; | |
2737 | |
2738 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
2739 if (perm[ridx (i)] < minr) | |
2740 { | |
2741 minr = perm[ridx (i)]; | |
2742 mini = i; | |
2743 } | |
2744 | |
2745 if (minr != k || data (mini) == 0) | |
2746 { | |
2747 err = -2; | |
2748 goto triangular_error; | |
2749 } | |
2750 | |
2751 double tmp = work[k] / data (mini); | |
2752 work[k] = tmp; | |
2753 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
2754 { | |
2755 if (i == mini) | |
2756 continue; | |
2757 | |
2758 octave_idx_type iidx = perm[ridx (i)]; | |
2759 work[iidx] = work[iidx] - tmp * data (i); | |
2760 } | |
2761 } | |
2762 } | |
2763 | |
2764 for (octave_idx_type i = 0; i < nc; i++) | |
2765 retval(i, j) = work[i]; | |
2766 } | |
2739 | 2767 |
2740 if (calc_cond) | 2768 if (calc_cond) |
2741 { | 2769 { |
2742 // Calculate the 1-norm of matrix for rcond calculation | 2770 // Calculation of 1-norm of inv(*this) |
2743 for (octave_idx_type j = 0; j < nc; j++) | 2771 for (octave_idx_type i = 0; i < nm; i++) |
2744 { | 2772 work[i] = 0.; |
2745 double atmp = 0.; | 2773 |
2746 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 2774 for (octave_idx_type j = 0; j < nr; j++) |
2747 atmp += fabs (data (i)); | 2775 { |
2748 if (atmp > anorm) | 2776 work[j] = 1.; |
2749 anorm = atmp; | |
2750 } | |
2751 } | |
2752 | |
2753 if (typ == MatrixType::Permuted_Lower) | |
2754 { | |
2755 retval.resize (nc, b_nc); | |
2756 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2757 octave_idx_type *perm = mattype.triangular_perm (); | |
2758 | |
2759 for (octave_idx_type j = 0; j < b_nc; j++) | |
2760 { | |
2761 if (nc > nr) | |
2762 for (octave_idx_type i = 0; i < nm; i++) | |
2763 work[i] = 0.; | |
2764 for (octave_idx_type i = 0; i < nr; i++) | |
2765 work[perm[i]] = b(i,j); | |
2766 | 2777 |
2767 for (octave_idx_type k = 0; k < nc; k++) | 2778 for (octave_idx_type k = 0; k < nc; k++) |
2768 { | 2779 { |
2769 if (work[k] != 0.) | 2780 if (work[k] != 0.) |
2770 { | 2781 { |
2771 octave_idx_type minr = nr; | 2782 octave_idx_type minr = nr; |
2772 octave_idx_type mini = 0; | 2783 octave_idx_type mini = 0; |
2773 | 2784 |
2774 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 2785 for (octave_idx_type i = cidx (k); |
2786 i < cidx (k+1); i++) | |
2775 if (perm[ridx (i)] < minr) | 2787 if (perm[ridx (i)] < minr) |
2776 { | 2788 { |
2777 minr = perm[ridx (i)]; | 2789 minr = perm[ridx (i)]; |
2778 mini = i; | 2790 mini = i; |
2779 } | 2791 } |
2780 | 2792 |
2781 if (minr != k || data (mini) == 0) | |
2782 { | |
2783 err = -2; | |
2784 goto triangular_error; | |
2785 } | |
2786 | |
2787 double tmp = work[k] / data (mini); | 2793 double tmp = work[k] / data (mini); |
2788 work[k] = tmp; | 2794 work[k] = tmp; |
2789 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 2795 for (octave_idx_type i = cidx (k); |
2796 i < cidx (k+1); i++) | |
2790 { | 2797 { |
2791 if (i == mini) | 2798 if (i == mini) |
2792 continue; | 2799 continue; |
2793 | 2800 |
2794 octave_idx_type iidx = perm[ridx (i)]; | 2801 octave_idx_type iidx = perm[ridx (i)]; |
2795 work[iidx] = work[iidx] - tmp * data (i); | 2802 work[iidx] = work[iidx] - tmp * data (i); |
2796 } | 2803 } |
2797 } | 2804 } |
2798 } | 2805 } |
2799 | 2806 |
2800 for (octave_idx_type i = 0; i < nc; i++) | 2807 double atmp = 0; |
2801 retval(i, j) = work[i]; | 2808 for (octave_idx_type i = j; i < nc; i++) |
2802 } | 2809 { |
2803 | 2810 atmp += fabs (work[i]); |
2804 if (calc_cond) | 2811 work[i] = 0.; |
2805 { | 2812 } |
2806 // Calculation of 1-norm of inv(*this) | 2813 if (atmp > ainvnorm) |
2807 for (octave_idx_type i = 0; i < nm; i++) | 2814 ainvnorm = atmp; |
2808 work[i] = 0.; | 2815 } |
2809 | 2816 rcond = 1. / ainvnorm / anorm; |
2810 for (octave_idx_type j = 0; j < nr; j++) | 2817 } |
2811 { | 2818 } |
2812 work[j] = 1.; | 2819 else |
2813 | 2820 { |
2814 for (octave_idx_type k = 0; k < nc; k++) | 2821 OCTAVE_LOCAL_BUFFER (double, work, nm); |
2822 retval.resize (nc, b_nc, 0.); | |
2823 | |
2824 for (octave_idx_type j = 0; j < b_nc; j++) | |
2825 { | |
2826 for (octave_idx_type i = 0; i < nr; i++) | |
2827 work[i] = b(i,j); | |
2828 for (octave_idx_type i = nr; i < nc; i++) | |
2829 work[i] = 0.; | |
2830 for (octave_idx_type k = 0; k < nc; k++) | |
2831 { | |
2832 if (work[k] != 0.) | |
2833 { | |
2834 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | |
2815 { | 2835 { |
2816 if (work[k] != 0.) | 2836 err = -2; |
2817 { | 2837 goto triangular_error; |
2818 octave_idx_type minr = nr; | |
2819 octave_idx_type mini = 0; | |
2820 | |
2821 for (octave_idx_type i = cidx (k); | |
2822 i < cidx (k+1); i++) | |
2823 if (perm[ridx (i)] < minr) | |
2824 { | |
2825 minr = perm[ridx (i)]; | |
2826 mini = i; | |
2827 } | |
2828 | |
2829 double tmp = work[k] / data (mini); | |
2830 work[k] = tmp; | |
2831 for (octave_idx_type i = cidx (k); | |
2832 i < cidx (k+1); i++) | |
2833 { | |
2834 if (i == mini) | |
2835 continue; | |
2836 | |
2837 octave_idx_type iidx = perm[ridx (i)]; | |
2838 work[iidx] = work[iidx] - tmp * data (i); | |
2839 } | |
2840 } | |
2841 } | 2838 } |
2842 | 2839 |
2843 double atmp = 0; | 2840 double tmp = work[k] / data (cidx (k)); |
2844 for (octave_idx_type i = j; i < nc; i++) | 2841 work[k] = tmp; |
2842 for (octave_idx_type i = cidx (k)+1; | |
2843 i < cidx (k+1); i++) | |
2845 { | 2844 { |
2846 atmp += fabs (work[i]); | 2845 octave_idx_type iidx = ridx (i); |
2847 work[i] = 0.; | 2846 work[iidx] = work[iidx] - tmp * data (i); |
2848 } | 2847 } |
2849 if (atmp > ainvnorm) | 2848 } |
2850 ainvnorm = atmp; | 2849 } |
2851 } | 2850 |
2852 rcond = 1. / ainvnorm / anorm; | 2851 for (octave_idx_type i = 0; i < nc; i++) |
2853 } | 2852 retval.xelem (i, j) = work[i]; |
2854 } | 2853 } |
2855 else | 2854 |
2856 { | 2855 if (calc_cond) |
2857 OCTAVE_LOCAL_BUFFER (double, work, nm); | 2856 { |
2858 retval.resize (nc, b_nc, 0.); | 2857 // Calculation of 1-norm of inv(*this) |
2859 | 2858 for (octave_idx_type i = 0; i < nm; i++) |
2860 for (octave_idx_type j = 0; j < b_nc; j++) | 2859 work[i] = 0.; |
2861 { | 2860 |
2862 for (octave_idx_type i = 0; i < nr; i++) | 2861 for (octave_idx_type j = 0; j < nr; j++) |
2863 work[i] = b(i,j); | 2862 { |
2864 for (octave_idx_type i = nr; i < nc; i++) | 2863 work[j] = 1.; |
2865 work[i] = 0.; | 2864 |
2866 for (octave_idx_type k = 0; k < nc; k++) | 2865 for (octave_idx_type k = j; k < nc; k++) |
2867 { | 2866 { |
2867 | |
2868 if (work[k] != 0.) | 2868 if (work[k] != 0.) |
2869 { | 2869 { |
2870 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | |
2871 { | |
2872 err = -2; | |
2873 goto triangular_error; | |
2874 } | |
2875 | |
2876 double tmp = work[k] / data (cidx (k)); | 2870 double tmp = work[k] / data (cidx (k)); |
2877 work[k] = tmp; | 2871 work[k] = tmp; |
2878 for (octave_idx_type i = cidx (k)+1; | 2872 for (octave_idx_type i = cidx (k)+1; |
2879 i < cidx (k+1); i++) | 2873 i < cidx (k+1); i++) |
2880 { | 2874 { |
2881 octave_idx_type iidx = ridx (i); | 2875 octave_idx_type iidx = ridx (i); |
2882 work[iidx] = work[iidx] - tmp * data (i); | 2876 work[iidx] = work[iidx] - tmp * data (i); |
2883 } | 2877 } |
2884 } | 2878 } |
2885 } | 2879 } |
2886 | 2880 double atmp = 0; |
2887 for (octave_idx_type i = 0; i < nc; i++) | 2881 for (octave_idx_type i = j; i < nc; i++) |
2888 retval.xelem (i, j) = work[i]; | 2882 { |
2889 } | 2883 atmp += fabs (work[i]); |
2890 | 2884 work[i] = 0.; |
2891 if (calc_cond) | 2885 } |
2892 { | 2886 if (atmp > ainvnorm) |
2893 // Calculation of 1-norm of inv(*this) | 2887 ainvnorm = atmp; |
2894 for (octave_idx_type i = 0; i < nm; i++) | 2888 } |
2895 work[i] = 0.; | 2889 rcond = 1. / ainvnorm / anorm; |
2896 | 2890 } |
2897 for (octave_idx_type j = 0; j < nr; j++) | 2891 } |
2898 { | 2892 |
2899 work[j] = 1.; | 2893 triangular_error: |
2900 | 2894 if (err != 0) |
2901 for (octave_idx_type k = j; k < nc; k++) | 2895 { |
2902 { | 2896 if (sing_handler) |
2903 | 2897 { |
2904 if (work[k] != 0.) | 2898 sing_handler (rcond); |
2905 { | 2899 mattype.mark_as_rectangular (); |
2906 double tmp = work[k] / data (cidx (k)); | 2900 } |
2907 work[k] = tmp; | 2901 else |
2908 for (octave_idx_type i = cidx (k)+1; | 2902 warn_singular_matrix (rcond); |
2909 i < cidx (k+1); i++) | 2903 } |
2910 { | 2904 |
2911 octave_idx_type iidx = ridx (i); | 2905 volatile double rcond_plus_one = rcond + 1.0; |
2912 work[iidx] = work[iidx] - tmp * data (i); | 2906 |
2913 } | 2907 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
2914 } | 2908 { |
2915 } | 2909 err = -2; |
2916 double atmp = 0; | 2910 |
2917 for (octave_idx_type i = j; i < nc; i++) | 2911 if (sing_handler) |
2918 { | 2912 { |
2919 atmp += fabs (work[i]); | 2913 sing_handler (rcond); |
2920 work[i] = 0.; | 2914 mattype.mark_as_rectangular (); |
2921 } | 2915 } |
2922 if (atmp > ainvnorm) | 2916 else |
2923 ainvnorm = atmp; | 2917 warn_singular_matrix (rcond); |
2924 } | 2918 } |
2925 rcond = 1. / ainvnorm / anorm; | |
2926 } | |
2927 } | |
2928 | |
2929 triangular_error: | |
2930 if (err != 0) | |
2931 { | |
2932 if (sing_handler) | |
2933 { | |
2934 sing_handler (rcond); | |
2935 mattype.mark_as_rectangular (); | |
2936 } | |
2937 else | |
2938 warn_singular_matrix (rcond); | |
2939 } | |
2940 | |
2941 volatile double rcond_plus_one = rcond + 1.0; | |
2942 | |
2943 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2944 { | |
2945 err = -2; | |
2946 | |
2947 if (sing_handler) | |
2948 { | |
2949 sing_handler (rcond); | |
2950 mattype.mark_as_rectangular (); | |
2951 } | |
2952 else | |
2953 warn_singular_matrix (rcond); | |
2954 } | |
2955 } | |
2956 else | |
2957 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2958 } | 2919 } |
2959 | 2920 |
2960 return retval; | 2921 return retval; |
2961 } | 2922 } |
2962 | 2923 |
2974 err = 0; | 2935 err = 0; |
2975 | 2936 |
2976 if (nr != b.rows ()) | 2937 if (nr != b.rows ()) |
2977 (*current_liboctave_error_handler) | 2938 (*current_liboctave_error_handler) |
2978 ("matrix dimension mismatch solution of linear equations"); | 2939 ("matrix dimension mismatch solution of linear equations"); |
2979 else if (nr == 0 || nc == 0 || b.cols () == 0) | 2940 |
2941 if (nr == 0 || nc == 0 || b.cols () == 0) | |
2980 retval = SparseMatrix (nc, b.cols ()); | 2942 retval = SparseMatrix (nc, b.cols ()); |
2981 else | 2943 else |
2982 { | 2944 { |
2983 // Print spparms("spumoni") info if requested | 2945 // Print spparms("spumoni") info if requested |
2984 int typ = mattype.type (); | 2946 int typ = mattype.type (); |
2985 mattype.info (); | 2947 mattype.info (); |
2986 | 2948 |
2987 if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower) | 2949 if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower) |
2988 { | 2950 (*current_liboctave_error_handler) ("incorrect matrix type"); |
2989 double anorm = 0.; | 2951 |
2990 double ainvnorm = 0.; | 2952 double anorm = 0.; |
2991 rcond = 1.; | 2953 double ainvnorm = 0.; |
2954 rcond = 1.; | |
2955 | |
2956 if (calc_cond) | |
2957 { | |
2958 // Calculate the 1-norm of matrix for rcond calculation | |
2959 for (octave_idx_type j = 0; j < nc; j++) | |
2960 { | |
2961 double atmp = 0.; | |
2962 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
2963 atmp += fabs (data (i)); | |
2964 if (atmp > anorm) | |
2965 anorm = atmp; | |
2966 } | |
2967 } | |
2968 | |
2969 octave_idx_type b_nc = b.cols (); | |
2970 octave_idx_type b_nz = b.nnz (); | |
2971 retval = SparseMatrix (nc, b_nc, b_nz); | |
2972 retval.xcidx (0) = 0; | |
2973 octave_idx_type ii = 0; | |
2974 octave_idx_type x_nz = b_nz; | |
2975 | |
2976 if (typ == MatrixType::Permuted_Lower) | |
2977 { | |
2978 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2979 octave_idx_type *perm = mattype.triangular_perm (); | |
2980 | |
2981 for (octave_idx_type j = 0; j < b_nc; j++) | |
2982 { | |
2983 for (octave_idx_type i = 0; i < nm; i++) | |
2984 work[i] = 0.; | |
2985 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
2986 work[perm[b.ridx (i)]] = b.data (i); | |
2987 | |
2988 for (octave_idx_type k = 0; k < nc; k++) | |
2989 { | |
2990 if (work[k] != 0.) | |
2991 { | |
2992 octave_idx_type minr = nr; | |
2993 octave_idx_type mini = 0; | |
2994 | |
2995 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
2996 if (perm[ridx (i)] < minr) | |
2997 { | |
2998 minr = perm[ridx (i)]; | |
2999 mini = i; | |
3000 } | |
3001 | |
3002 if (minr != k || data (mini) == 0) | |
3003 { | |
3004 err = -2; | |
3005 goto triangular_error; | |
3006 } | |
3007 | |
3008 double tmp = work[k] / data (mini); | |
3009 work[k] = tmp; | |
3010 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3011 { | |
3012 if (i == mini) | |
3013 continue; | |
3014 | |
3015 octave_idx_type iidx = perm[ridx (i)]; | |
3016 work[iidx] = work[iidx] - tmp * data (i); | |
3017 } | |
3018 } | |
3019 } | |
3020 | |
3021 // Count nonzeros in work vector and adjust space in | |
3022 // retval if needed | |
3023 octave_idx_type new_nnz = 0; | |
3024 for (octave_idx_type i = 0; i < nc; i++) | |
3025 if (work[i] != 0.) | |
3026 new_nnz++; | |
3027 | |
3028 if (ii + new_nnz > x_nz) | |
3029 { | |
3030 // Resize the sparse matrix | |
3031 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
3032 retval.change_capacity (sz); | |
3033 x_nz = sz; | |
3034 } | |
3035 | |
3036 for (octave_idx_type i = 0; i < nc; i++) | |
3037 if (work[i] != 0.) | |
3038 { | |
3039 retval.xridx (ii) = i; | |
3040 retval.xdata (ii++) = work[i]; | |
3041 } | |
3042 retval.xcidx (j+1) = ii; | |
3043 } | |
3044 | |
3045 retval.maybe_compress (); | |
2992 | 3046 |
2993 if (calc_cond) | 3047 if (calc_cond) |
2994 { | 3048 { |
2995 // Calculate the 1-norm of matrix for rcond calculation | 3049 // Calculation of 1-norm of inv(*this) |
2996 for (octave_idx_type j = 0; j < nc; j++) | 3050 for (octave_idx_type i = 0; i < nm; i++) |
2997 { | 3051 work[i] = 0.; |
2998 double atmp = 0.; | 3052 |
2999 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 3053 for (octave_idx_type j = 0; j < nr; j++) |
3000 atmp += fabs (data (i)); | 3054 { |
3001 if (atmp > anorm) | 3055 work[j] = 1.; |
3002 anorm = atmp; | |
3003 } | |
3004 } | |
3005 | |
3006 octave_idx_type b_nc = b.cols (); | |
3007 octave_idx_type b_nz = b.nnz (); | |
3008 retval = SparseMatrix (nc, b_nc, b_nz); | |
3009 retval.xcidx (0) = 0; | |
3010 octave_idx_type ii = 0; | |
3011 octave_idx_type x_nz = b_nz; | |
3012 | |
3013 if (typ == MatrixType::Permuted_Lower) | |
3014 { | |
3015 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3016 octave_idx_type *perm = mattype.triangular_perm (); | |
3017 | |
3018 for (octave_idx_type j = 0; j < b_nc; j++) | |
3019 { | |
3020 for (octave_idx_type i = 0; i < nm; i++) | |
3021 work[i] = 0.; | |
3022 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
3023 work[perm[b.ridx (i)]] = b.data (i); | |
3024 | 3056 |
3025 for (octave_idx_type k = 0; k < nc; k++) | 3057 for (octave_idx_type k = 0; k < nc; k++) |
3026 { | 3058 { |
3027 if (work[k] != 0.) | 3059 if (work[k] != 0.) |
3028 { | 3060 { |
3029 octave_idx_type minr = nr; | 3061 octave_idx_type minr = nr; |
3030 octave_idx_type mini = 0; | 3062 octave_idx_type mini = 0; |
3031 | 3063 |
3032 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 3064 for (octave_idx_type i = cidx (k); |
3065 i < cidx (k+1); i++) | |
3033 if (perm[ridx (i)] < minr) | 3066 if (perm[ridx (i)] < minr) |
3034 { | 3067 { |
3035 minr = perm[ridx (i)]; | 3068 minr = perm[ridx (i)]; |
3036 mini = i; | 3069 mini = i; |
3037 } | 3070 } |
3038 | 3071 |
3039 if (minr != k || data (mini) == 0) | |
3040 { | |
3041 err = -2; | |
3042 goto triangular_error; | |
3043 } | |
3044 | |
3045 double tmp = work[k] / data (mini); | 3072 double tmp = work[k] / data (mini); |
3046 work[k] = tmp; | 3073 work[k] = tmp; |
3047 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 3074 for (octave_idx_type i = cidx (k); |
3075 i < cidx (k+1); i++) | |
3048 { | 3076 { |
3049 if (i == mini) | 3077 if (i == mini) |
3050 continue; | 3078 continue; |
3051 | 3079 |
3052 octave_idx_type iidx = perm[ridx (i)]; | 3080 octave_idx_type iidx = perm[ridx (i)]; |
3053 work[iidx] = work[iidx] - tmp * data (i); | 3081 work[iidx] = work[iidx] - tmp * data (i); |
3054 } | 3082 } |
3055 } | 3083 } |
3056 } | 3084 } |
3057 | 3085 |
3058 // Count nonzeros in work vector and adjust space in | 3086 double atmp = 0; |
3059 // retval if needed | 3087 for (octave_idx_type i = j; i < nr; i++) |
3060 octave_idx_type new_nnz = 0; | 3088 { |
3061 for (octave_idx_type i = 0; i < nc; i++) | 3089 atmp += fabs (work[i]); |
3062 if (work[i] != 0.) | 3090 work[i] = 0.; |
3063 new_nnz++; | 3091 } |
3064 | 3092 if (atmp > ainvnorm) |
3065 if (ii + new_nnz > x_nz) | 3093 ainvnorm = atmp; |
3066 { | 3094 } |
3067 // Resize the sparse matrix | 3095 rcond = 1. / ainvnorm / anorm; |
3068 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | 3096 } |
3069 retval.change_capacity (sz); | 3097 } |
3070 x_nz = sz; | 3098 else |
3071 } | 3099 { |
3072 | 3100 OCTAVE_LOCAL_BUFFER (double, work, nm); |
3073 for (octave_idx_type i = 0; i < nc; i++) | 3101 |
3074 if (work[i] != 0.) | 3102 for (octave_idx_type j = 0; j < b_nc; j++) |
3075 { | 3103 { |
3076 retval.xridx (ii) = i; | 3104 for (octave_idx_type i = 0; i < nm; i++) |
3077 retval.xdata (ii++) = work[i]; | 3105 work[i] = 0.; |
3078 } | 3106 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) |
3079 retval.xcidx (j+1) = ii; | 3107 work[b.ridx (i)] = b.data (i); |
3080 } | 3108 |
3081 | 3109 for (octave_idx_type k = 0; k < nc; k++) |
3082 retval.maybe_compress (); | 3110 { |
3083 | 3111 if (work[k] != 0.) |
3084 if (calc_cond) | 3112 { |
3085 { | 3113 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) |
3086 // Calculation of 1-norm of inv(*this) | |
3087 for (octave_idx_type i = 0; i < nm; i++) | |
3088 work[i] = 0.; | |
3089 | |
3090 for (octave_idx_type j = 0; j < nr; j++) | |
3091 { | |
3092 work[j] = 1.; | |
3093 | |
3094 for (octave_idx_type k = 0; k < nc; k++) | |
3095 { | 3114 { |
3096 if (work[k] != 0.) | 3115 err = -2; |
3097 { | 3116 goto triangular_error; |
3098 octave_idx_type minr = nr; | |
3099 octave_idx_type mini = 0; | |
3100 | |
3101 for (octave_idx_type i = cidx (k); | |
3102 i < cidx (k+1); i++) | |
3103 if (perm[ridx (i)] < minr) | |
3104 { | |
3105 minr = perm[ridx (i)]; | |
3106 mini = i; | |
3107 } | |
3108 | |
3109 double tmp = work[k] / data (mini); | |
3110 work[k] = tmp; | |
3111 for (octave_idx_type i = cidx (k); | |
3112 i < cidx (k+1); i++) | |
3113 { | |
3114 if (i == mini) | |
3115 continue; | |
3116 | |
3117 octave_idx_type iidx = perm[ridx (i)]; | |
3118 work[iidx] = work[iidx] - tmp * data (i); | |
3119 } | |
3120 } | |
3121 } | 3117 } |
3122 | 3118 |
3123 double atmp = 0; | 3119 double tmp = work[k] / data (cidx (k)); |
3124 for (octave_idx_type i = j; i < nr; i++) | 3120 work[k] = tmp; |
3121 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | |
3125 { | 3122 { |
3126 atmp += fabs (work[i]); | 3123 octave_idx_type iidx = ridx (i); |
3127 work[i] = 0.; | 3124 work[iidx] = work[iidx] - tmp * data (i); |
3128 } | 3125 } |
3129 if (atmp > ainvnorm) | 3126 } |
3130 ainvnorm = atmp; | 3127 } |
3131 } | 3128 |
3132 rcond = 1. / ainvnorm / anorm; | 3129 // Count nonzeros in work vector and adjust space in |
3133 } | 3130 // retval if needed |
3134 } | 3131 octave_idx_type new_nnz = 0; |
3135 else | 3132 for (octave_idx_type i = 0; i < nc; i++) |
3136 { | 3133 if (work[i] != 0.) |
3137 OCTAVE_LOCAL_BUFFER (double, work, nm); | 3134 new_nnz++; |
3138 | 3135 |
3139 for (octave_idx_type j = 0; j < b_nc; j++) | 3136 if (ii + new_nnz > x_nz) |
3140 { | 3137 { |
3141 for (octave_idx_type i = 0; i < nm; i++) | 3138 // Resize the sparse matrix |
3142 work[i] = 0.; | 3139 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
3143 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 3140 retval.change_capacity (sz); |
3144 work[b.ridx (i)] = b.data (i); | 3141 x_nz = sz; |
3145 | 3142 } |
3146 for (octave_idx_type k = 0; k < nc; k++) | 3143 |
3147 { | 3144 for (octave_idx_type i = 0; i < nc; i++) |
3145 if (work[i] != 0.) | |
3146 { | |
3147 retval.xridx (ii) = i; | |
3148 retval.xdata (ii++) = work[i]; | |
3149 } | |
3150 retval.xcidx (j+1) = ii; | |
3151 } | |
3152 | |
3153 retval.maybe_compress (); | |
3154 | |
3155 if (calc_cond) | |
3156 { | |
3157 // Calculation of 1-norm of inv(*this) | |
3158 for (octave_idx_type i = 0; i < nm; i++) | |
3159 work[i] = 0.; | |
3160 | |
3161 for (octave_idx_type j = 0; j < nr; j++) | |
3162 { | |
3163 work[j] = 1.; | |
3164 | |
3165 for (octave_idx_type k = j; k < nc; k++) | |
3166 { | |
3167 | |
3148 if (work[k] != 0.) | 3168 if (work[k] != 0.) |
3149 { | 3169 { |
3150 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | |
3151 { | |
3152 err = -2; | |
3153 goto triangular_error; | |
3154 } | |
3155 | |
3156 double tmp = work[k] / data (cidx (k)); | 3170 double tmp = work[k] / data (cidx (k)); |
3157 work[k] = tmp; | 3171 work[k] = tmp; |
3158 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | 3172 for (octave_idx_type i = cidx (k)+1; |
3173 i < cidx (k+1); i++) | |
3159 { | 3174 { |
3160 octave_idx_type iidx = ridx (i); | 3175 octave_idx_type iidx = ridx (i); |
3161 work[iidx] = work[iidx] - tmp * data (i); | 3176 work[iidx] = work[iidx] - tmp * data (i); |
3162 } | 3177 } |
3163 } | 3178 } |
3164 } | 3179 } |
3165 | 3180 double atmp = 0; |
3166 // Count nonzeros in work vector and adjust space in | 3181 for (octave_idx_type i = j; i < nc; i++) |
3167 // retval if needed | 3182 { |
3168 octave_idx_type new_nnz = 0; | 3183 atmp += fabs (work[i]); |
3169 for (octave_idx_type i = 0; i < nc; i++) | 3184 work[i] = 0.; |
3170 if (work[i] != 0.) | 3185 } |
3171 new_nnz++; | 3186 if (atmp > ainvnorm) |
3172 | 3187 ainvnorm = atmp; |
3173 if (ii + new_nnz > x_nz) | 3188 } |
3174 { | 3189 rcond = 1. / ainvnorm / anorm; |
3175 // Resize the sparse matrix | 3190 } |
3176 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | 3191 } |
3177 retval.change_capacity (sz); | 3192 |
3178 x_nz = sz; | 3193 triangular_error: |
3179 } | 3194 if (err != 0) |
3180 | 3195 { |
3181 for (octave_idx_type i = 0; i < nc; i++) | 3196 if (sing_handler) |
3182 if (work[i] != 0.) | 3197 { |
3183 { | 3198 sing_handler (rcond); |
3184 retval.xridx (ii) = i; | 3199 mattype.mark_as_rectangular (); |
3185 retval.xdata (ii++) = work[i]; | 3200 } |
3186 } | 3201 else |
3187 retval.xcidx (j+1) = ii; | 3202 warn_singular_matrix (rcond); |
3188 } | 3203 } |
3189 | 3204 |
3190 retval.maybe_compress (); | 3205 volatile double rcond_plus_one = rcond + 1.0; |
3191 | 3206 |
3192 if (calc_cond) | 3207 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
3193 { | 3208 { |
3194 // Calculation of 1-norm of inv(*this) | 3209 err = -2; |
3195 for (octave_idx_type i = 0; i < nm; i++) | 3210 |
3196 work[i] = 0.; | 3211 if (sing_handler) |
3197 | 3212 { |
3198 for (octave_idx_type j = 0; j < nr; j++) | 3213 sing_handler (rcond); |
3199 { | 3214 mattype.mark_as_rectangular (); |
3200 work[j] = 1.; | 3215 } |
3201 | 3216 else |
3202 for (octave_idx_type k = j; k < nc; k++) | 3217 warn_singular_matrix (rcond); |
3203 { | 3218 } |
3204 | |
3205 if (work[k] != 0.) | |
3206 { | |
3207 double tmp = work[k] / data (cidx (k)); | |
3208 work[k] = tmp; | |
3209 for (octave_idx_type i = cidx (k)+1; | |
3210 i < cidx (k+1); i++) | |
3211 { | |
3212 octave_idx_type iidx = ridx (i); | |
3213 work[iidx] = work[iidx] - tmp * data (i); | |
3214 } | |
3215 } | |
3216 } | |
3217 double atmp = 0; | |
3218 for (octave_idx_type i = j; i < nc; i++) | |
3219 { | |
3220 atmp += fabs (work[i]); | |
3221 work[i] = 0.; | |
3222 } | |
3223 if (atmp > ainvnorm) | |
3224 ainvnorm = atmp; | |
3225 } | |
3226 rcond = 1. / ainvnorm / anorm; | |
3227 } | |
3228 } | |
3229 | |
3230 triangular_error: | |
3231 if (err != 0) | |
3232 { | |
3233 if (sing_handler) | |
3234 { | |
3235 sing_handler (rcond); | |
3236 mattype.mark_as_rectangular (); | |
3237 } | |
3238 else | |
3239 warn_singular_matrix (rcond); | |
3240 } | |
3241 | |
3242 volatile double rcond_plus_one = rcond + 1.0; | |
3243 | |
3244 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3245 { | |
3246 err = -2; | |
3247 | |
3248 if (sing_handler) | |
3249 { | |
3250 sing_handler (rcond); | |
3251 mattype.mark_as_rectangular (); | |
3252 } | |
3253 else | |
3254 warn_singular_matrix (rcond); | |
3255 } | |
3256 } | |
3257 else | |
3258 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3259 } | 3219 } |
3260 | 3220 |
3261 return retval; | 3221 return retval; |
3262 } | 3222 } |
3263 | 3223 |
3275 err = 0; | 3235 err = 0; |
3276 | 3236 |
3277 if (nr != b.rows ()) | 3237 if (nr != b.rows ()) |
3278 (*current_liboctave_error_handler) | 3238 (*current_liboctave_error_handler) |
3279 ("matrix dimension mismatch solution of linear equations"); | 3239 ("matrix dimension mismatch solution of linear equations"); |
3280 else if (nr == 0 || nc == 0 || b.cols () == 0) | 3240 |
3241 if (nr == 0 || nc == 0 || b.cols () == 0) | |
3281 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 3242 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
3282 else | 3243 else |
3283 { | 3244 { |
3284 // Print spparms("spumoni") info if requested | 3245 // Print spparms("spumoni") info if requested |
3285 int typ = mattype.type (); | 3246 int typ = mattype.type (); |
3286 mattype.info (); | 3247 mattype.info (); |
3287 | 3248 |
3288 if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower) | 3249 if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower) |
3289 { | 3250 (*current_liboctave_error_handler) ("incorrect matrix type"); |
3290 double anorm = 0.; | 3251 |
3291 double ainvnorm = 0.; | 3252 double anorm = 0.; |
3292 octave_idx_type b_nc = b.cols (); | 3253 double ainvnorm = 0.; |
3293 rcond = 1.; | 3254 octave_idx_type b_nc = b.cols (); |
3255 rcond = 1.; | |
3256 | |
3257 if (calc_cond) | |
3258 { | |
3259 // Calculate the 1-norm of matrix for rcond calculation | |
3260 for (octave_idx_type j = 0; j < nc; j++) | |
3261 { | |
3262 double atmp = 0.; | |
3263 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
3264 atmp += fabs (data (i)); | |
3265 if (atmp > anorm) | |
3266 anorm = atmp; | |
3267 } | |
3268 } | |
3269 | |
3270 if (typ == MatrixType::Permuted_Lower) | |
3271 { | |
3272 retval.resize (nc, b_nc); | |
3273 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
3274 octave_idx_type *perm = mattype.triangular_perm (); | |
3275 | |
3276 for (octave_idx_type j = 0; j < b_nc; j++) | |
3277 { | |
3278 for (octave_idx_type i = 0; i < nm; i++) | |
3279 cwork[i] = 0.; | |
3280 for (octave_idx_type i = 0; i < nr; i++) | |
3281 cwork[perm[i]] = b(i,j); | |
3282 | |
3283 for (octave_idx_type k = 0; k < nc; k++) | |
3284 { | |
3285 if (cwork[k] != 0.) | |
3286 { | |
3287 octave_idx_type minr = nr; | |
3288 octave_idx_type mini = 0; | |
3289 | |
3290 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3291 if (perm[ridx (i)] < minr) | |
3292 { | |
3293 minr = perm[ridx (i)]; | |
3294 mini = i; | |
3295 } | |
3296 | |
3297 if (minr != k || data (mini) == 0) | |
3298 { | |
3299 err = -2; | |
3300 goto triangular_error; | |
3301 } | |
3302 | |
3303 Complex tmp = cwork[k] / data (mini); | |
3304 cwork[k] = tmp; | |
3305 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3306 { | |
3307 if (i == mini) | |
3308 continue; | |
3309 | |
3310 octave_idx_type iidx = perm[ridx (i)]; | |
3311 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3312 } | |
3313 } | |
3314 } | |
3315 | |
3316 for (octave_idx_type i = 0; i < nc; i++) | |
3317 retval(i, j) = cwork[i]; | |
3318 } | |
3294 | 3319 |
3295 if (calc_cond) | 3320 if (calc_cond) |
3296 { | 3321 { |
3297 // Calculate the 1-norm of matrix for rcond calculation | 3322 // Calculation of 1-norm of inv(*this) |
3298 for (octave_idx_type j = 0; j < nc; j++) | 3323 OCTAVE_LOCAL_BUFFER (double, work, nm); |
3299 { | 3324 for (octave_idx_type i = 0; i < nm; i++) |
3300 double atmp = 0.; | 3325 work[i] = 0.; |
3301 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 3326 |
3302 atmp += fabs (data (i)); | 3327 for (octave_idx_type j = 0; j < nr; j++) |
3303 if (atmp > anorm) | 3328 { |
3304 anorm = atmp; | 3329 work[j] = 1.; |
3305 } | |
3306 } | |
3307 | |
3308 if (typ == MatrixType::Permuted_Lower) | |
3309 { | |
3310 retval.resize (nc, b_nc); | |
3311 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
3312 octave_idx_type *perm = mattype.triangular_perm (); | |
3313 | |
3314 for (octave_idx_type j = 0; j < b_nc; j++) | |
3315 { | |
3316 for (octave_idx_type i = 0; i < nm; i++) | |
3317 cwork[i] = 0.; | |
3318 for (octave_idx_type i = 0; i < nr; i++) | |
3319 cwork[perm[i]] = b(i,j); | |
3320 | 3330 |
3321 for (octave_idx_type k = 0; k < nc; k++) | 3331 for (octave_idx_type k = 0; k < nc; k++) |
3322 { | 3332 { |
3323 if (cwork[k] != 0.) | 3333 if (work[k] != 0.) |
3324 { | 3334 { |
3325 octave_idx_type minr = nr; | 3335 octave_idx_type minr = nr; |
3326 octave_idx_type mini = 0; | 3336 octave_idx_type mini = 0; |
3327 | 3337 |
3328 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 3338 for (octave_idx_type i = cidx (k); |
3339 i < cidx (k+1); i++) | |
3329 if (perm[ridx (i)] < minr) | 3340 if (perm[ridx (i)] < minr) |
3330 { | 3341 { |
3331 minr = perm[ridx (i)]; | 3342 minr = perm[ridx (i)]; |
3332 mini = i; | 3343 mini = i; |
3333 } | 3344 } |
3334 | 3345 |
3335 if (minr != k || data (mini) == 0) | 3346 double tmp = work[k] / data (mini); |
3336 { | 3347 work[k] = tmp; |
3337 err = -2; | 3348 for (octave_idx_type i = cidx (k); |
3338 goto triangular_error; | 3349 i < cidx (k+1); i++) |
3339 } | |
3340 | |
3341 Complex tmp = cwork[k] / data (mini); | |
3342 cwork[k] = tmp; | |
3343 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3344 { | 3350 { |
3345 if (i == mini) | 3351 if (i == mini) |
3346 continue; | 3352 continue; |
3347 | 3353 |
3348 octave_idx_type iidx = perm[ridx (i)]; | 3354 octave_idx_type iidx = perm[ridx (i)]; |
3349 cwork[iidx] = cwork[iidx] - tmp * data (i); | 3355 work[iidx] = work[iidx] - tmp * data (i); |
3350 } | 3356 } |
3351 } | 3357 } |
3352 } | 3358 } |
3353 | 3359 |
3354 for (octave_idx_type i = 0; i < nc; i++) | 3360 double atmp = 0; |
3355 retval(i, j) = cwork[i]; | 3361 for (octave_idx_type i = j; i < nc; i++) |
3356 } | 3362 { |
3357 | 3363 atmp += fabs (work[i]); |
3358 if (calc_cond) | 3364 work[i] = 0.; |
3359 { | 3365 } |
3360 // Calculation of 1-norm of inv(*this) | 3366 if (atmp > ainvnorm) |
3361 OCTAVE_LOCAL_BUFFER (double, work, nm); | 3367 ainvnorm = atmp; |
3362 for (octave_idx_type i = 0; i < nm; i++) | 3368 } |
3363 work[i] = 0.; | 3369 rcond = 1. / ainvnorm / anorm; |
3364 | 3370 } |
3365 for (octave_idx_type j = 0; j < nr; j++) | 3371 } |
3366 { | 3372 else |
3367 work[j] = 1.; | 3373 { |
3368 | 3374 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
3369 for (octave_idx_type k = 0; k < nc; k++) | 3375 retval.resize (nc, b_nc, 0.); |
3376 | |
3377 for (octave_idx_type j = 0; j < b_nc; j++) | |
3378 { | |
3379 for (octave_idx_type i = 0; i < nr; i++) | |
3380 cwork[i] = b(i,j); | |
3381 for (octave_idx_type i = nr; i < nc; i++) | |
3382 cwork[i] = 0.; | |
3383 | |
3384 for (octave_idx_type k = 0; k < nc; k++) | |
3385 { | |
3386 if (cwork[k] != 0.) | |
3387 { | |
3388 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | |
3370 { | 3389 { |
3371 if (work[k] != 0.) | 3390 err = -2; |
3391 goto triangular_error; | |
3392 } | |
3393 | |
3394 Complex tmp = cwork[k] / data (cidx (k)); | |
3395 cwork[k] = tmp; | |
3396 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | |
3397 { | |
3398 octave_idx_type iidx = ridx (i); | |
3399 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3400 } | |
3401 } | |
3402 } | |
3403 | |
3404 for (octave_idx_type i = 0; i < nc; i++) | |
3405 retval.xelem (i, j) = cwork[i]; | |
3406 } | |
3407 | |
3408 if (calc_cond) | |
3409 { | |
3410 // Calculation of 1-norm of inv(*this) | |
3411 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3412 for (octave_idx_type i = 0; i < nm; i++) | |
3413 work[i] = 0.; | |
3414 | |
3415 for (octave_idx_type j = 0; j < nr; j++) | |
3416 { | |
3417 work[j] = 1.; | |
3418 | |
3419 for (octave_idx_type k = j; k < nc; k++) | |
3420 { | |
3421 | |
3422 if (work[k] != 0.) | |
3423 { | |
3424 double tmp = work[k] / data (cidx (k)); | |
3425 work[k] = tmp; | |
3426 for (octave_idx_type i = cidx (k)+1; | |
3427 i < cidx (k+1); i++) | |
3372 { | 3428 { |
3373 octave_idx_type minr = nr; | 3429 octave_idx_type iidx = ridx (i); |
3374 octave_idx_type mini = 0; | 3430 work[iidx] = work[iidx] - tmp * data (i); |
3375 | |
3376 for (octave_idx_type i = cidx (k); | |
3377 i < cidx (k+1); i++) | |
3378 if (perm[ridx (i)] < minr) | |
3379 { | |
3380 minr = perm[ridx (i)]; | |
3381 mini = i; | |
3382 } | |
3383 | |
3384 double tmp = work[k] / data (mini); | |
3385 work[k] = tmp; | |
3386 for (octave_idx_type i = cidx (k); | |
3387 i < cidx (k+1); i++) | |
3388 { | |
3389 if (i == mini) | |
3390 continue; | |
3391 | |
3392 octave_idx_type iidx = perm[ridx (i)]; | |
3393 work[iidx] = work[iidx] - tmp * data (i); | |
3394 } | |
3395 } | 3431 } |
3396 } | 3432 } |
3397 | 3433 } |
3398 double atmp = 0; | 3434 double atmp = 0; |
3399 for (octave_idx_type i = j; i < nc; i++) | 3435 for (octave_idx_type i = j; i < nc; i++) |
3400 { | 3436 { |
3401 atmp += fabs (work[i]); | 3437 atmp += fabs (work[i]); |
3402 work[i] = 0.; | 3438 work[i] = 0.; |
3403 } | 3439 } |
3404 if (atmp > ainvnorm) | 3440 if (atmp > ainvnorm) |
3405 ainvnorm = atmp; | 3441 ainvnorm = atmp; |
3406 } | 3442 } |
3407 rcond = 1. / ainvnorm / anorm; | 3443 rcond = 1. / ainvnorm / anorm; |
3408 } | 3444 } |
3445 } | |
3446 | |
3447 triangular_error: | |
3448 if (err != 0) | |
3449 { | |
3450 if (sing_handler) | |
3451 { | |
3452 sing_handler (rcond); | |
3453 mattype.mark_as_rectangular (); | |
3409 } | 3454 } |
3410 else | 3455 else |
3411 { | 3456 warn_singular_matrix (rcond); |
3412 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | 3457 } |
3413 retval.resize (nc, b_nc, 0.); | 3458 |
3414 | 3459 volatile double rcond_plus_one = rcond + 1.0; |
3415 for (octave_idx_type j = 0; j < b_nc; j++) | 3460 |
3416 { | 3461 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
3417 for (octave_idx_type i = 0; i < nr; i++) | 3462 { |
3418 cwork[i] = b(i,j); | 3463 err = -2; |
3419 for (octave_idx_type i = nr; i < nc; i++) | 3464 |
3420 cwork[i] = 0.; | 3465 if (sing_handler) |
3421 | 3466 { |
3422 for (octave_idx_type k = 0; k < nc; k++) | 3467 sing_handler (rcond); |
3423 { | 3468 mattype.mark_as_rectangular (); |
3424 if (cwork[k] != 0.) | 3469 } |
3425 { | 3470 else |
3426 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | 3471 warn_singular_matrix (rcond); |
3427 { | 3472 } |
3428 err = -2; | |
3429 goto triangular_error; | |
3430 } | |
3431 | |
3432 Complex tmp = cwork[k] / data (cidx (k)); | |
3433 cwork[k] = tmp; | |
3434 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | |
3435 { | |
3436 octave_idx_type iidx = ridx (i); | |
3437 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3438 } | |
3439 } | |
3440 } | |
3441 | |
3442 for (octave_idx_type i = 0; i < nc; i++) | |
3443 retval.xelem (i, j) = cwork[i]; | |
3444 } | |
3445 | |
3446 if (calc_cond) | |
3447 { | |
3448 // Calculation of 1-norm of inv(*this) | |
3449 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3450 for (octave_idx_type i = 0; i < nm; i++) | |
3451 work[i] = 0.; | |
3452 | |
3453 for (octave_idx_type j = 0; j < nr; j++) | |
3454 { | |
3455 work[j] = 1.; | |
3456 | |
3457 for (octave_idx_type k = j; k < nc; k++) | |
3458 { | |
3459 | |
3460 if (work[k] != 0.) | |
3461 { | |
3462 double tmp = work[k] / data (cidx (k)); | |
3463 work[k] = tmp; | |
3464 for (octave_idx_type i = cidx (k)+1; | |
3465 i < cidx (k+1); i++) | |
3466 { | |
3467 octave_idx_type iidx = ridx (i); | |
3468 work[iidx] = work[iidx] - tmp * data (i); | |
3469 } | |
3470 } | |
3471 } | |
3472 double atmp = 0; | |
3473 for (octave_idx_type i = j; i < nc; i++) | |
3474 { | |
3475 atmp += fabs (work[i]); | |
3476 work[i] = 0.; | |
3477 } | |
3478 if (atmp > ainvnorm) | |
3479 ainvnorm = atmp; | |
3480 } | |
3481 rcond = 1. / ainvnorm / anorm; | |
3482 } | |
3483 } | |
3484 | |
3485 triangular_error: | |
3486 if (err != 0) | |
3487 { | |
3488 if (sing_handler) | |
3489 { | |
3490 sing_handler (rcond); | |
3491 mattype.mark_as_rectangular (); | |
3492 } | |
3493 else | |
3494 warn_singular_matrix (rcond); | |
3495 } | |
3496 | |
3497 volatile double rcond_plus_one = rcond + 1.0; | |
3498 | |
3499 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3500 { | |
3501 err = -2; | |
3502 | |
3503 if (sing_handler) | |
3504 { | |
3505 sing_handler (rcond); | |
3506 mattype.mark_as_rectangular (); | |
3507 } | |
3508 else | |
3509 warn_singular_matrix (rcond); | |
3510 } | |
3511 } | |
3512 else | |
3513 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3514 } | 3473 } |
3515 | 3474 |
3516 return retval; | 3475 return retval; |
3517 } | 3476 } |
3518 | 3477 |
3530 err = 0; | 3489 err = 0; |
3531 | 3490 |
3532 if (nr != b.rows ()) | 3491 if (nr != b.rows ()) |
3533 (*current_liboctave_error_handler) | 3492 (*current_liboctave_error_handler) |
3534 ("matrix dimension mismatch solution of linear equations"); | 3493 ("matrix dimension mismatch solution of linear equations"); |
3535 else if (nr == 0 || nc == 0 || b.cols () == 0) | 3494 |
3495 if (nr == 0 || nc == 0 || b.cols () == 0) | |
3536 retval = SparseComplexMatrix (nc, b.cols ()); | 3496 retval = SparseComplexMatrix (nc, b.cols ()); |
3537 else | 3497 else |
3538 { | 3498 { |
3539 // Print spparms("spumoni") info if requested | 3499 // Print spparms("spumoni") info if requested |
3540 int typ = mattype.type (); | 3500 int typ = mattype.type (); |
3541 mattype.info (); | 3501 mattype.info (); |
3542 | 3502 |
3543 if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower) | 3503 if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower) |
3544 { | 3504 (*current_liboctave_error_handler) ("incorrect matrix type"); |
3545 double anorm = 0.; | 3505 |
3546 double ainvnorm = 0.; | 3506 double anorm = 0.; |
3547 rcond = 1.; | 3507 double ainvnorm = 0.; |
3508 rcond = 1.; | |
3509 | |
3510 if (calc_cond) | |
3511 { | |
3512 // Calculate the 1-norm of matrix for rcond calculation | |
3513 for (octave_idx_type j = 0; j < nc; j++) | |
3514 { | |
3515 double atmp = 0.; | |
3516 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | |
3517 atmp += fabs (data (i)); | |
3518 if (atmp > anorm) | |
3519 anorm = atmp; | |
3520 } | |
3521 } | |
3522 | |
3523 octave_idx_type b_nc = b.cols (); | |
3524 octave_idx_type b_nz = b.nnz (); | |
3525 retval = SparseComplexMatrix (nc, b_nc, b_nz); | |
3526 retval.xcidx (0) = 0; | |
3527 octave_idx_type ii = 0; | |
3528 octave_idx_type x_nz = b_nz; | |
3529 | |
3530 if (typ == MatrixType::Permuted_Lower) | |
3531 { | |
3532 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
3533 octave_idx_type *perm = mattype.triangular_perm (); | |
3534 | |
3535 for (octave_idx_type j = 0; j < b_nc; j++) | |
3536 { | |
3537 for (octave_idx_type i = 0; i < nm; i++) | |
3538 cwork[i] = 0.; | |
3539 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
3540 cwork[perm[b.ridx (i)]] = b.data (i); | |
3541 | |
3542 for (octave_idx_type k = 0; k < nc; k++) | |
3543 { | |
3544 if (cwork[k] != 0.) | |
3545 { | |
3546 octave_idx_type minr = nr; | |
3547 octave_idx_type mini = 0; | |
3548 | |
3549 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3550 if (perm[ridx (i)] < minr) | |
3551 { | |
3552 minr = perm[ridx (i)]; | |
3553 mini = i; | |
3554 } | |
3555 | |
3556 if (minr != k || data (mini) == 0) | |
3557 { | |
3558 err = -2; | |
3559 goto triangular_error; | |
3560 } | |
3561 | |
3562 Complex tmp = cwork[k] / data (mini); | |
3563 cwork[k] = tmp; | |
3564 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3565 { | |
3566 if (i == mini) | |
3567 continue; | |
3568 | |
3569 octave_idx_type iidx = perm[ridx (i)]; | |
3570 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3571 } | |
3572 } | |
3573 } | |
3574 | |
3575 // Count nonzeros in work vector and adjust space in | |
3576 // retval if needed | |
3577 octave_idx_type new_nnz = 0; | |
3578 for (octave_idx_type i = 0; i < nc; i++) | |
3579 if (cwork[i] != 0.) | |
3580 new_nnz++; | |
3581 | |
3582 if (ii + new_nnz > x_nz) | |
3583 { | |
3584 // Resize the sparse matrix | |
3585 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
3586 retval.change_capacity (sz); | |
3587 x_nz = sz; | |
3588 } | |
3589 | |
3590 for (octave_idx_type i = 0; i < nc; i++) | |
3591 if (cwork[i] != 0.) | |
3592 { | |
3593 retval.xridx (ii) = i; | |
3594 retval.xdata (ii++) = cwork[i]; | |
3595 } | |
3596 retval.xcidx (j+1) = ii; | |
3597 } | |
3598 | |
3599 retval.maybe_compress (); | |
3548 | 3600 |
3549 if (calc_cond) | 3601 if (calc_cond) |
3550 { | 3602 { |
3551 // Calculate the 1-norm of matrix for rcond calculation | 3603 // Calculation of 1-norm of inv(*this) |
3552 for (octave_idx_type j = 0; j < nc; j++) | 3604 OCTAVE_LOCAL_BUFFER (double, work, nm); |
3553 { | 3605 for (octave_idx_type i = 0; i < nm; i++) |
3554 double atmp = 0.; | 3606 work[i] = 0.; |
3555 for (octave_idx_type i = cidx (j); i < cidx (j+1); i++) | 3607 |
3556 atmp += fabs (data (i)); | 3608 for (octave_idx_type j = 0; j < nr; j++) |
3557 if (atmp > anorm) | 3609 { |
3558 anorm = atmp; | 3610 work[j] = 1.; |
3559 } | |
3560 } | |
3561 | |
3562 octave_idx_type b_nc = b.cols (); | |
3563 octave_idx_type b_nz = b.nnz (); | |
3564 retval = SparseComplexMatrix (nc, b_nc, b_nz); | |
3565 retval.xcidx (0) = 0; | |
3566 octave_idx_type ii = 0; | |
3567 octave_idx_type x_nz = b_nz; | |
3568 | |
3569 if (typ == MatrixType::Permuted_Lower) | |
3570 { | |
3571 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | |
3572 octave_idx_type *perm = mattype.triangular_perm (); | |
3573 | |
3574 for (octave_idx_type j = 0; j < b_nc; j++) | |
3575 { | |
3576 for (octave_idx_type i = 0; i < nm; i++) | |
3577 cwork[i] = 0.; | |
3578 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | |
3579 cwork[perm[b.ridx (i)]] = b.data (i); | |
3580 | 3611 |
3581 for (octave_idx_type k = 0; k < nc; k++) | 3612 for (octave_idx_type k = 0; k < nc; k++) |
3582 { | 3613 { |
3583 if (cwork[k] != 0.) | 3614 if (work[k] != 0.) |
3584 { | 3615 { |
3585 octave_idx_type minr = nr; | 3616 octave_idx_type minr = nr; |
3586 octave_idx_type mini = 0; | 3617 octave_idx_type mini = 0; |
3587 | 3618 |
3588 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | 3619 for (octave_idx_type i = cidx (k); |
3620 i < cidx (k+1); i++) | |
3589 if (perm[ridx (i)] < minr) | 3621 if (perm[ridx (i)] < minr) |
3590 { | 3622 { |
3591 minr = perm[ridx (i)]; | 3623 minr = perm[ridx (i)]; |
3592 mini = i; | 3624 mini = i; |
3593 } | 3625 } |
3594 | 3626 |
3595 if (minr != k || data (mini) == 0) | 3627 double tmp = work[k] / data (mini); |
3596 { | 3628 work[k] = tmp; |
3597 err = -2; | 3629 for (octave_idx_type i = cidx (k); |
3598 goto triangular_error; | 3630 i < cidx (k+1); i++) |
3599 } | |
3600 | |
3601 Complex tmp = cwork[k] / data (mini); | |
3602 cwork[k] = tmp; | |
3603 for (octave_idx_type i = cidx (k); i < cidx (k+1); i++) | |
3604 { | 3631 { |
3605 if (i == mini) | 3632 if (i == mini) |
3606 continue; | 3633 continue; |
3607 | 3634 |
3608 octave_idx_type iidx = perm[ridx (i)]; | 3635 octave_idx_type iidx = perm[ridx (i)]; |
3609 cwork[iidx] = cwork[iidx] - tmp * data (i); | 3636 work[iidx] = work[iidx] - tmp * data (i); |
3610 } | 3637 } |
3611 } | 3638 } |
3612 } | 3639 } |
3613 | 3640 |
3614 // Count nonzeros in work vector and adjust space in | 3641 double atmp = 0; |
3615 // retval if needed | 3642 for (octave_idx_type i = j; i < nc; i++) |
3616 octave_idx_type new_nnz = 0; | 3643 { |
3617 for (octave_idx_type i = 0; i < nc; i++) | 3644 atmp += fabs (work[i]); |
3618 if (cwork[i] != 0.) | 3645 work[i] = 0.; |
3619 new_nnz++; | 3646 } |
3620 | 3647 if (atmp > ainvnorm) |
3621 if (ii + new_nnz > x_nz) | 3648 ainvnorm = atmp; |
3622 { | 3649 } |
3623 // Resize the sparse matrix | 3650 rcond = 1. / ainvnorm / anorm; |
3624 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | 3651 } |
3625 retval.change_capacity (sz); | 3652 } |
3626 x_nz = sz; | 3653 else |
3627 } | 3654 { |
3628 | 3655 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
3629 for (octave_idx_type i = 0; i < nc; i++) | 3656 |
3630 if (cwork[i] != 0.) | 3657 for (octave_idx_type j = 0; j < b_nc; j++) |
3631 { | 3658 { |
3632 retval.xridx (ii) = i; | 3659 for (octave_idx_type i = 0; i < nm; i++) |
3633 retval.xdata (ii++) = cwork[i]; | 3660 cwork[i] = 0.; |
3634 } | 3661 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) |
3635 retval.xcidx (j+1) = ii; | 3662 cwork[b.ridx (i)] = b.data (i); |
3636 } | 3663 |
3637 | 3664 for (octave_idx_type k = 0; k < nc; k++) |
3638 retval.maybe_compress (); | 3665 { |
3639 | 3666 if (cwork[k] != 0.) |
3640 if (calc_cond) | 3667 { |
3641 { | 3668 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) |
3642 // Calculation of 1-norm of inv(*this) | |
3643 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3644 for (octave_idx_type i = 0; i < nm; i++) | |
3645 work[i] = 0.; | |
3646 | |
3647 for (octave_idx_type j = 0; j < nr; j++) | |
3648 { | |
3649 work[j] = 1.; | |
3650 | |
3651 for (octave_idx_type k = 0; k < nc; k++) | |
3652 { | 3669 { |
3653 if (work[k] != 0.) | 3670 err = -2; |
3671 goto triangular_error; | |
3672 } | |
3673 | |
3674 Complex tmp = cwork[k] / data (cidx (k)); | |
3675 cwork[k] = tmp; | |
3676 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | |
3677 { | |
3678 octave_idx_type iidx = ridx (i); | |
3679 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3680 } | |
3681 } | |
3682 } | |
3683 | |
3684 // Count nonzeros in work vector and adjust space in | |
3685 // retval if needed | |
3686 octave_idx_type new_nnz = 0; | |
3687 for (octave_idx_type i = 0; i < nc; i++) | |
3688 if (cwork[i] != 0.) | |
3689 new_nnz++; | |
3690 | |
3691 if (ii + new_nnz > x_nz) | |
3692 { | |
3693 // Resize the sparse matrix | |
3694 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
3695 retval.change_capacity (sz); | |
3696 x_nz = sz; | |
3697 } | |
3698 | |
3699 for (octave_idx_type i = 0; i < nc; i++) | |
3700 if (cwork[i] != 0.) | |
3701 { | |
3702 retval.xridx (ii) = i; | |
3703 retval.xdata (ii++) = cwork[i]; | |
3704 } | |
3705 retval.xcidx (j+1) = ii; | |
3706 } | |
3707 | |
3708 retval.maybe_compress (); | |
3709 | |
3710 if (calc_cond) | |
3711 { | |
3712 // Calculation of 1-norm of inv(*this) | |
3713 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3714 for (octave_idx_type i = 0; i < nm; i++) | |
3715 work[i] = 0.; | |
3716 | |
3717 for (octave_idx_type j = 0; j < nr; j++) | |
3718 { | |
3719 work[j] = 1.; | |
3720 | |
3721 for (octave_idx_type k = j; k < nc; k++) | |
3722 { | |
3723 | |
3724 if (work[k] != 0.) | |
3725 { | |
3726 double tmp = work[k] / data (cidx (k)); | |
3727 work[k] = tmp; | |
3728 for (octave_idx_type i = cidx (k)+1; | |
3729 i < cidx (k+1); i++) | |
3654 { | 3730 { |
3655 octave_idx_type minr = nr; | 3731 octave_idx_type iidx = ridx (i); |
3656 octave_idx_type mini = 0; | 3732 work[iidx] = work[iidx] - tmp * data (i); |
3657 | |
3658 for (octave_idx_type i = cidx (k); | |
3659 i < cidx (k+1); i++) | |
3660 if (perm[ridx (i)] < minr) | |
3661 { | |
3662 minr = perm[ridx (i)]; | |
3663 mini = i; | |
3664 } | |
3665 | |
3666 double tmp = work[k] / data (mini); | |
3667 work[k] = tmp; | |
3668 for (octave_idx_type i = cidx (k); | |
3669 i < cidx (k+1); i++) | |
3670 { | |
3671 if (i == mini) | |
3672 continue; | |
3673 | |
3674 octave_idx_type iidx = perm[ridx (i)]; | |
3675 work[iidx] = work[iidx] - tmp * data (i); | |
3676 } | |
3677 } | 3733 } |
3678 } | 3734 } |
3679 | 3735 } |
3680 double atmp = 0; | 3736 double atmp = 0; |
3681 for (octave_idx_type i = j; i < nc; i++) | 3737 for (octave_idx_type i = j; i < nc; i++) |
3682 { | 3738 { |
3683 atmp += fabs (work[i]); | 3739 atmp += fabs (work[i]); |
3684 work[i] = 0.; | 3740 work[i] = 0.; |
3685 } | 3741 } |
3686 if (atmp > ainvnorm) | 3742 if (atmp > ainvnorm) |
3687 ainvnorm = atmp; | 3743 ainvnorm = atmp; |
3688 } | 3744 } |
3689 rcond = 1. / ainvnorm / anorm; | 3745 rcond = 1. / ainvnorm / anorm; |
3690 } | 3746 } |
3747 } | |
3748 | |
3749 triangular_error: | |
3750 if (err != 0) | |
3751 { | |
3752 if (sing_handler) | |
3753 { | |
3754 sing_handler (rcond); | |
3755 mattype.mark_as_rectangular (); | |
3691 } | 3756 } |
3692 else | 3757 else |
3693 { | 3758 warn_singular_matrix (rcond); |
3694 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); | 3759 } |
3695 | 3760 |
3696 for (octave_idx_type j = 0; j < b_nc; j++) | 3761 volatile double rcond_plus_one = rcond + 1.0; |
3697 { | 3762 |
3698 for (octave_idx_type i = 0; i < nm; i++) | 3763 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
3699 cwork[i] = 0.; | 3764 { |
3700 for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++) | 3765 err = -2; |
3701 cwork[b.ridx (i)] = b.data (i); | 3766 |
3702 | 3767 if (sing_handler) |
3703 for (octave_idx_type k = 0; k < nc; k++) | 3768 { |
3704 { | 3769 sing_handler (rcond); |
3705 if (cwork[k] != 0.) | 3770 mattype.mark_as_rectangular (); |
3706 { | 3771 } |
3707 if (ridx (cidx (k)) != k || data (cidx (k)) == 0.) | 3772 else |
3708 { | 3773 warn_singular_matrix (rcond); |
3709 err = -2; | 3774 } |
3710 goto triangular_error; | |
3711 } | |
3712 | |
3713 Complex tmp = cwork[k] / data (cidx (k)); | |
3714 cwork[k] = tmp; | |
3715 for (octave_idx_type i = cidx (k)+1; i < cidx (k+1); i++) | |
3716 { | |
3717 octave_idx_type iidx = ridx (i); | |
3718 cwork[iidx] = cwork[iidx] - tmp * data (i); | |
3719 } | |
3720 } | |
3721 } | |
3722 | |
3723 // Count nonzeros in work vector and adjust space in | |
3724 // retval if needed | |
3725 octave_idx_type new_nnz = 0; | |
3726 for (octave_idx_type i = 0; i < nc; i++) | |
3727 if (cwork[i] != 0.) | |
3728 new_nnz++; | |
3729 | |
3730 if (ii + new_nnz > x_nz) | |
3731 { | |
3732 // Resize the sparse matrix | |
3733 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; | |
3734 retval.change_capacity (sz); | |
3735 x_nz = sz; | |
3736 } | |
3737 | |
3738 for (octave_idx_type i = 0; i < nc; i++) | |
3739 if (cwork[i] != 0.) | |
3740 { | |
3741 retval.xridx (ii) = i; | |
3742 retval.xdata (ii++) = cwork[i]; | |
3743 } | |
3744 retval.xcidx (j+1) = ii; | |
3745 } | |
3746 | |
3747 retval.maybe_compress (); | |
3748 | |
3749 if (calc_cond) | |
3750 { | |
3751 // Calculation of 1-norm of inv(*this) | |
3752 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3753 for (octave_idx_type i = 0; i < nm; i++) | |
3754 work[i] = 0.; | |
3755 | |
3756 for (octave_idx_type j = 0; j < nr; j++) | |
3757 { | |
3758 work[j] = 1.; | |
3759 | |
3760 for (octave_idx_type k = j; k < nc; k++) | |
3761 { | |
3762 | |
3763 if (work[k] != 0.) | |
3764 { | |
3765 double tmp = work[k] / data (cidx (k)); | |
3766 work[k] = tmp; | |
3767 for (octave_idx_type i = cidx (k)+1; | |
3768 i < cidx (k+1); i++) | |
3769 { | |
3770 octave_idx_type iidx = ridx (i); | |
3771 work[iidx] = work[iidx] - tmp * data (i); | |
3772 } | |
3773 } | |
3774 } | |
3775 double atmp = 0; | |
3776 for (octave_idx_type i = j; i < nc; i++) | |
3777 { | |
3778 atmp += fabs (work[i]); | |
3779 work[i] = 0.; | |
3780 } | |
3781 if (atmp > ainvnorm) | |
3782 ainvnorm = atmp; | |
3783 } | |
3784 rcond = 1. / ainvnorm / anorm; | |
3785 } | |
3786 } | |
3787 | |
3788 triangular_error: | |
3789 if (err != 0) | |
3790 { | |
3791 if (sing_handler) | |
3792 { | |
3793 sing_handler (rcond); | |
3794 mattype.mark_as_rectangular (); | |
3795 } | |
3796 else | |
3797 warn_singular_matrix (rcond); | |
3798 } | |
3799 | |
3800 volatile double rcond_plus_one = rcond + 1.0; | |
3801 | |
3802 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3803 { | |
3804 err = -2; | |
3805 | |
3806 if (sing_handler) | |
3807 { | |
3808 sing_handler (rcond); | |
3809 mattype.mark_as_rectangular (); | |
3810 } | |
3811 else | |
3812 warn_singular_matrix (rcond); | |
3813 } | |
3814 } | |
3815 else | |
3816 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3817 } | 3775 } |
3818 | 3776 |
3819 return retval; | 3777 return retval; |
3820 } | 3778 } |
3821 | 3779 |
3832 err = 0; | 3790 err = 0; |
3833 | 3791 |
3834 if (nr != nc || nr != b.rows ()) | 3792 if (nr != nc || nr != b.rows ()) |
3835 (*current_liboctave_error_handler) | 3793 (*current_liboctave_error_handler) |
3836 ("matrix dimension mismatch solution of linear equations"); | 3794 ("matrix dimension mismatch solution of linear equations"); |
3837 else if (nr == 0 || b.cols () == 0) | 3795 |
3796 if (nr == 0 || b.cols () == 0) | |
3838 retval = Matrix (nc, b.cols (), 0.0); | 3797 retval = Matrix (nc, b.cols (), 0.0); |
3839 else if (calc_cond) | 3798 else if (calc_cond) |
3840 (*current_liboctave_error_handler) | 3799 (*current_liboctave_error_handler) |
3841 ("calculation of condition number not implemented"); | 3800 ("calculation of condition number not implemented"); |
3842 else | 3801 else |
3981 err = 0; | 3940 err = 0; |
3982 | 3941 |
3983 if (nr != nc || nr != b.rows ()) | 3942 if (nr != nc || nr != b.rows ()) |
3984 (*current_liboctave_error_handler) | 3943 (*current_liboctave_error_handler) |
3985 ("matrix dimension mismatch solution of linear equations"); | 3944 ("matrix dimension mismatch solution of linear equations"); |
3986 else if (nr == 0 || b.cols () == 0) | 3945 |
3946 if (nr == 0 || b.cols () == 0) | |
3987 retval = SparseMatrix (nc, b.cols ()); | 3947 retval = SparseMatrix (nc, b.cols ()); |
3988 else if (calc_cond) | 3948 else if (calc_cond) |
3989 (*current_liboctave_error_handler) | 3949 (*current_liboctave_error_handler) |
3990 ("calculation of condition number not implemented"); | 3950 ("calculation of condition number not implemented"); |
3991 else | 3951 else |
4126 err = 0; | 4086 err = 0; |
4127 | 4087 |
4128 if (nr != nc || nr != b.rows ()) | 4088 if (nr != nc || nr != b.rows ()) |
4129 (*current_liboctave_error_handler) | 4089 (*current_liboctave_error_handler) |
4130 ("matrix dimension mismatch solution of linear equations"); | 4090 ("matrix dimension mismatch solution of linear equations"); |
4131 else if (nr == 0 || b.cols () == 0) | 4091 |
4092 if (nr == 0 || b.cols () == 0) | |
4132 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 4093 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
4133 else if (calc_cond) | 4094 else if (calc_cond) |
4134 (*current_liboctave_error_handler) | 4095 (*current_liboctave_error_handler) |
4135 ("calculation of condition number not implemented"); | 4096 ("calculation of condition number not implemented"); |
4136 else | 4097 else |
4277 err = 0; | 4238 err = 0; |
4278 | 4239 |
4279 if (nr != nc || nr != b.rows ()) | 4240 if (nr != nc || nr != b.rows ()) |
4280 (*current_liboctave_error_handler) | 4241 (*current_liboctave_error_handler) |
4281 ("matrix dimension mismatch solution of linear equations"); | 4242 ("matrix dimension mismatch solution of linear equations"); |
4282 else if (nr == 0 || b.cols () == 0) | 4243 |
4244 if (nr == 0 || b.cols () == 0) | |
4283 retval = SparseComplexMatrix (nc, b.cols ()); | 4245 retval = SparseComplexMatrix (nc, b.cols ()); |
4284 else if (calc_cond) | 4246 else if (calc_cond) |
4285 (*current_liboctave_error_handler) | 4247 (*current_liboctave_error_handler) |
4286 ("calculation of condition number not implemented"); | 4248 ("calculation of condition number not implemented"); |
4287 else | 4249 else |
4382 Bx, b_nr, err | 4344 Bx, b_nr, err |
4383 F77_CHAR_ARG_LEN (1))); | 4345 F77_CHAR_ARG_LEN (1))); |
4384 | 4346 |
4385 if (err != 0) | 4347 if (err != 0) |
4386 { | 4348 { |
4349 // FIXME: Should this be a warning? | |
4387 (*current_liboctave_error_handler) | 4350 (*current_liboctave_error_handler) |
4388 ("SparseMatrix::solve solve failed"); | 4351 ("SparseMatrix::solve solve failed"); |
4389 | 4352 |
4390 err = -1; | 4353 err = -1; |
4391 break; | 4354 break; |
4397 Bz, b_nr, err | 4360 Bz, b_nr, err |
4398 F77_CHAR_ARG_LEN (1))); | 4361 F77_CHAR_ARG_LEN (1))); |
4399 | 4362 |
4400 if (err != 0) | 4363 if (err != 0) |
4401 { | 4364 { |
4365 // FIXME: Should this be a warning? | |
4402 (*current_liboctave_error_handler) | 4366 (*current_liboctave_error_handler) |
4403 ("SparseMatrix::solve solve failed"); | 4367 ("SparseMatrix::solve solve failed"); |
4404 | 4368 |
4405 err = -1; | 4369 err = -1; |
4406 break; | 4370 break; |
4455 err = 0; | 4419 err = 0; |
4456 | 4420 |
4457 if (nr != nc || nr != b.rows ()) | 4421 if (nr != nc || nr != b.rows ()) |
4458 (*current_liboctave_error_handler) | 4422 (*current_liboctave_error_handler) |
4459 ("matrix dimension mismatch solution of linear equations"); | 4423 ("matrix dimension mismatch solution of linear equations"); |
4460 else if (nr == 0 || b.cols () == 0) | 4424 |
4425 if (nr == 0 || b.cols () == 0) | |
4461 retval = Matrix (nc, b.cols (), 0.0); | 4426 retval = Matrix (nc, b.cols (), 0.0); |
4462 else | 4427 else |
4463 { | 4428 { |
4464 // Print spparms("spumoni") info if requested | 4429 // Print spparms("spumoni") info if requested |
4465 volatile int typ = mattype.type (); | 4430 volatile int typ = mattype.type (); |
4557 ldm, result, b.rows (), err | 4522 ldm, result, b.rows (), err |
4558 F77_CHAR_ARG_LEN (1))); | 4523 F77_CHAR_ARG_LEN (1))); |
4559 | 4524 |
4560 if (err != 0) | 4525 if (err != 0) |
4561 { | 4526 { |
4527 // FIXME: Should this be a warning? | |
4562 (*current_liboctave_error_handler) | 4528 (*current_liboctave_error_handler) |
4563 ("SparseMatrix::solve solve failed"); | 4529 ("SparseMatrix::solve solve failed"); |
4564 err = -1; | 4530 err = -1; |
4565 } | 4531 } |
4566 } | 4532 } |
4698 err = 0; | 4664 err = 0; |
4699 | 4665 |
4700 if (nr != nc || nr != b.rows ()) | 4666 if (nr != nc || nr != b.rows ()) |
4701 (*current_liboctave_error_handler) | 4667 (*current_liboctave_error_handler) |
4702 ("matrix dimension mismatch solution of linear equations"); | 4668 ("matrix dimension mismatch solution of linear equations"); |
4703 else if (nr == 0 || b.cols () == 0) | 4669 |
4670 if (nr == 0 || b.cols () == 0) | |
4704 retval = SparseMatrix (nc, b.cols ()); | 4671 retval = SparseMatrix (nc, b.cols ()); |
4705 else | 4672 else |
4706 { | 4673 { |
4707 // Print spparms("spumoni") info if requested | 4674 // Print spparms("spumoni") info if requested |
4708 volatile int typ = mattype.type (); | 4675 volatile int typ = mattype.type (); |
4810 ldm, Bx, b_nr, err | 4777 ldm, Bx, b_nr, err |
4811 F77_CHAR_ARG_LEN (1))); | 4778 F77_CHAR_ARG_LEN (1))); |
4812 | 4779 |
4813 if (err != 0) | 4780 if (err != 0) |
4814 { | 4781 { |
4782 // FIXME: Should this be a warning? | |
4815 (*current_liboctave_error_handler) | 4783 (*current_liboctave_error_handler) |
4816 ("SparseMatrix::solve solve failed"); | 4784 ("SparseMatrix::solve solve failed"); |
4817 err = -1; | 4785 err = -1; |
4818 break; | 4786 break; |
4819 } | 4787 } |
5010 err = 0; | 4978 err = 0; |
5011 | 4979 |
5012 if (nr != nc || nr != b.rows ()) | 4980 if (nr != nc || nr != b.rows ()) |
5013 (*current_liboctave_error_handler) | 4981 (*current_liboctave_error_handler) |
5014 ("matrix dimension mismatch solution of linear equations"); | 4982 ("matrix dimension mismatch solution of linear equations"); |
5015 else if (nr == 0 || b.cols () == 0) | 4983 |
4984 if (nr == 0 || b.cols () == 0) | |
5016 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 4985 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
5017 else | 4986 else |
5018 { | 4987 { |
5019 // Print spparms("spumoni") info if requested | 4988 // Print spparms("spumoni") info if requested |
5020 volatile int typ = mattype.type (); | 4989 volatile int typ = mattype.type (); |
5125 ldm, Bx, b_nr, err | 5094 ldm, Bx, b_nr, err |
5126 F77_CHAR_ARG_LEN (1))); | 5095 F77_CHAR_ARG_LEN (1))); |
5127 | 5096 |
5128 if (err != 0) | 5097 if (err != 0) |
5129 { | 5098 { |
5099 // FIXME: Should this be a warning? | |
5130 (*current_liboctave_error_handler) | 5100 (*current_liboctave_error_handler) |
5131 ("SparseMatrix::solve solve failed"); | 5101 ("SparseMatrix::solve solve failed"); |
5132 err = -1; | 5102 err = -1; |
5133 break; | 5103 break; |
5134 } | 5104 } |
5139 ldm, Bz, b.rows (), err | 5109 ldm, Bz, b.rows (), err |
5140 F77_CHAR_ARG_LEN (1))); | 5110 F77_CHAR_ARG_LEN (1))); |
5141 | 5111 |
5142 if (err != 0) | 5112 if (err != 0) |
5143 { | 5113 { |
5114 // FIXME: Should this be a warning? | |
5144 (*current_liboctave_error_handler) | 5115 (*current_liboctave_error_handler) |
5145 ("SparseMatrix::solve solve failed"); | 5116 ("SparseMatrix::solve solve failed"); |
5146 err = -1; | 5117 err = -1; |
5147 break; | 5118 break; |
5148 } | 5119 } |
5303 err = 0; | 5274 err = 0; |
5304 | 5275 |
5305 if (nr != nc || nr != b.rows ()) | 5276 if (nr != nc || nr != b.rows ()) |
5306 (*current_liboctave_error_handler) | 5277 (*current_liboctave_error_handler) |
5307 ("matrix dimension mismatch solution of linear equations"); | 5278 ("matrix dimension mismatch solution of linear equations"); |
5308 else if (nr == 0 || b.cols () == 0) | 5279 |
5280 if (nr == 0 || b.cols () == 0) | |
5309 retval = SparseComplexMatrix (nc, b.cols ()); | 5281 retval = SparseComplexMatrix (nc, b.cols ()); |
5310 else | 5282 else |
5311 { | 5283 { |
5312 // Print spparms("spumoni") info if requested | 5284 // Print spparms("spumoni") info if requested |
5313 volatile int typ = mattype.type (); | 5285 volatile int typ = mattype.type (); |
5424 ldm, Bx, b_nr, err | 5396 ldm, Bx, b_nr, err |
5425 F77_CHAR_ARG_LEN (1))); | 5397 F77_CHAR_ARG_LEN (1))); |
5426 | 5398 |
5427 if (err != 0) | 5399 if (err != 0) |
5428 { | 5400 { |
5401 // FIXME: Should this be a warning? | |
5429 (*current_liboctave_error_handler) | 5402 (*current_liboctave_error_handler) |
5430 ("SparseMatrix::solve solve failed"); | 5403 ("SparseMatrix::solve solve failed"); |
5431 err = -1; | 5404 err = -1; |
5432 break; | 5405 break; |
5433 } | 5406 } |
5438 ldm, Bz, b_nr, err | 5411 ldm, Bz, b_nr, err |
5439 F77_CHAR_ARG_LEN (1))); | 5412 F77_CHAR_ARG_LEN (1))); |
5440 | 5413 |
5441 if (err != 0) | 5414 if (err != 0) |
5442 { | 5415 { |
5416 // FIXME: Should this be a warning? | |
5443 (*current_liboctave_error_handler) | 5417 (*current_liboctave_error_handler) |
5444 ("SparseMatrix::solve solve failed"); | 5418 ("SparseMatrix::solve solve failed"); |
5445 | 5419 |
5446 err = -1; | 5420 err = -1; |
5447 break; | 5421 break; |
5692 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, Ax, 0, | 5666 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, Ax, 0, |
5693 &Symbolic, control, info); | 5667 &Symbolic, control, info); |
5694 | 5668 |
5695 if (status < 0) | 5669 if (status < 0) |
5696 { | 5670 { |
5671 UMFPACK_DNAME (report_status) (control, status); | |
5672 UMFPACK_DNAME (report_info) (control, info); | |
5673 | |
5674 UMFPACK_DNAME (free_symbolic) (&Symbolic); | |
5675 | |
5676 // FIXME: Should this be a warning? | |
5697 (*current_liboctave_error_handler) | 5677 (*current_liboctave_error_handler) |
5698 ("SparseMatrix::solve symbolic factorization failed"); | 5678 ("SparseMatrix::solve symbolic factorization failed"); |
5699 err = -1; | 5679 err = -1; |
5700 | |
5701 UMFPACK_DNAME (report_status) (control, status); | |
5702 UMFPACK_DNAME (report_info) (control, info); | |
5703 | |
5704 UMFPACK_DNAME (free_symbolic) (&Symbolic); | |
5705 } | 5680 } |
5706 else | 5681 else |
5707 { | 5682 { |
5708 UMFPACK_DNAME (report_symbolic) (Symbolic, control); | 5683 UMFPACK_DNAME (report_symbolic) (Symbolic, control); |
5709 | 5684 |
5729 else | 5704 else |
5730 warn_singular_matrix (rcond); | 5705 warn_singular_matrix (rcond); |
5731 } | 5706 } |
5732 else if (status < 0) | 5707 else if (status < 0) |
5733 { | 5708 { |
5709 UMFPACK_DNAME (report_status) (control, status); | |
5710 UMFPACK_DNAME (report_info) (control, info); | |
5711 | |
5712 // FIXME: Should this be a warning? | |
5734 (*current_liboctave_error_handler) | 5713 (*current_liboctave_error_handler) |
5735 ("SparseMatrix::solve numeric factorization failed"); | 5714 ("SparseMatrix::solve numeric factorization failed"); |
5736 | |
5737 UMFPACK_DNAME (report_status) (control, status); | |
5738 UMFPACK_DNAME (report_info) (control, info); | |
5739 | 5715 |
5740 err = -1; | 5716 err = -1; |
5741 } | 5717 } |
5742 else | 5718 else |
5743 { | 5719 { |
5770 err = 0; | 5746 err = 0; |
5771 | 5747 |
5772 if (nr != nc || nr != b.rows ()) | 5748 if (nr != nc || nr != b.rows ()) |
5773 (*current_liboctave_error_handler) | 5749 (*current_liboctave_error_handler) |
5774 ("matrix dimension mismatch solution of linear equations"); | 5750 ("matrix dimension mismatch solution of linear equations"); |
5775 else if (nr == 0 || b.cols () == 0) | 5751 |
5752 if (nr == 0 || b.cols () == 0) | |
5776 retval = Matrix (nc, b.cols (), 0.0); | 5753 retval = Matrix (nc, b.cols (), 0.0); |
5777 else | 5754 else |
5778 { | 5755 { |
5779 // Print spparms("spumoni") info if requested | 5756 // Print spparms("spumoni") info if requested |
5780 volatile int typ = mattype.type (); | 5757 volatile int typ = mattype.type (); |
5943 Ai, Ax, &result[iidx], | 5920 Ai, Ax, &result[iidx], |
5944 &Bx[iidx], Numeric, control, | 5921 &Bx[iidx], Numeric, control, |
5945 info); | 5922 info); |
5946 if (status < 0) | 5923 if (status < 0) |
5947 { | 5924 { |
5925 UMFPACK_DNAME (report_status) (control, status); | |
5926 | |
5927 // FIXME: Should this be a warning? | |
5948 (*current_liboctave_error_handler) | 5928 (*current_liboctave_error_handler) |
5949 ("SparseMatrix::solve solve failed"); | 5929 ("SparseMatrix::solve solve failed"); |
5950 | 5930 |
5951 UMFPACK_DNAME (report_status) (control, status); | |
5952 | |
5953 err = -1; | 5931 err = -1; |
5954 | |
5955 break; | 5932 break; |
5956 } | 5933 } |
5957 } | 5934 } |
5958 | 5935 |
5959 UMFPACK_DNAME (report_info) (control, info); | 5936 UMFPACK_DNAME (report_info) (control, info); |
5989 err = 0; | 5966 err = 0; |
5990 | 5967 |
5991 if (nr != nc || nr != b.rows ()) | 5968 if (nr != nc || nr != b.rows ()) |
5992 (*current_liboctave_error_handler) | 5969 (*current_liboctave_error_handler) |
5993 ("matrix dimension mismatch solution of linear equations"); | 5970 ("matrix dimension mismatch solution of linear equations"); |
5994 else if (nr == 0 || b.cols () == 0) | 5971 |
5972 if (nr == 0 || b.cols () == 0) | |
5995 retval = SparseMatrix (nc, b.cols ()); | 5973 retval = SparseMatrix (nc, b.cols ()); |
5996 else | 5974 else |
5997 { | 5975 { |
5998 // Print spparms("spumoni") info if requested | 5976 // Print spparms("spumoni") info if requested |
5999 volatile int typ = mattype.type (); | 5977 volatile int typ = mattype.type (); |
6186 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, | 6164 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, |
6187 Ai, Ax, Xx, Bx, Numeric, | 6165 Ai, Ax, Xx, Bx, Numeric, |
6188 control, info); | 6166 control, info); |
6189 if (status < 0) | 6167 if (status < 0) |
6190 { | 6168 { |
6169 UMFPACK_DNAME (report_status) (control, status); | |
6170 | |
6171 // FIXME: Should this be a warning? | |
6191 (*current_liboctave_error_handler) | 6172 (*current_liboctave_error_handler) |
6192 ("SparseMatrix::solve solve failed"); | 6173 ("SparseMatrix::solve solve failed"); |
6193 | 6174 |
6194 UMFPACK_DNAME (report_status) (control, status); | |
6195 | |
6196 err = -1; | 6175 err = -1; |
6197 | |
6198 break; | 6176 break; |
6199 } | 6177 } |
6200 | 6178 |
6201 for (octave_idx_type i = 0; i < b_nr; i++) | 6179 for (octave_idx_type i = 0; i < b_nr; i++) |
6202 { | 6180 { |
6253 err = 0; | 6231 err = 0; |
6254 | 6232 |
6255 if (nr != nc || nr != b.rows ()) | 6233 if (nr != nc || nr != b.rows ()) |
6256 (*current_liboctave_error_handler) | 6234 (*current_liboctave_error_handler) |
6257 ("matrix dimension mismatch solution of linear equations"); | 6235 ("matrix dimension mismatch solution of linear equations"); |
6258 else if (nr == 0 || b.cols () == 0) | 6236 |
6237 if (nr == 0 || b.cols () == 0) | |
6259 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | 6238 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); |
6260 else | 6239 else |
6261 { | 6240 { |
6262 // Print spparms("spumoni") info if requested | 6241 // Print spparms("spumoni") info if requested |
6263 volatile int typ = mattype.type (); | 6242 volatile int typ = mattype.type (); |
6440 Ap, Ai, Ax, Xz, Bz, | 6419 Ap, Ai, Ax, Xz, Bz, |
6441 Numeric, control, info); | 6420 Numeric, control, info); |
6442 | 6421 |
6443 if (status < 0 || status2 < 0) | 6422 if (status < 0 || status2 < 0) |
6444 { | 6423 { |
6424 UMFPACK_DNAME (report_status) (control, status); | |
6425 | |
6426 // FIXME: Should this be a warning? | |
6445 (*current_liboctave_error_handler) | 6427 (*current_liboctave_error_handler) |
6446 ("SparseMatrix::solve solve failed"); | 6428 ("SparseMatrix::solve solve failed"); |
6447 | 6429 |
6448 UMFPACK_DNAME (report_status) (control, status); | |
6449 | |
6450 err = -1; | 6430 err = -1; |
6451 | |
6452 break; | 6431 break; |
6453 } | 6432 } |
6454 | 6433 |
6455 for (octave_idx_type i = 0; i < b_nr; i++) | 6434 for (octave_idx_type i = 0; i < b_nr; i++) |
6456 retval(i, j) = Complex (Xx[i], Xz[i]); | 6435 retval(i, j) = Complex (Xx[i], Xz[i]); |
6489 err = 0; | 6468 err = 0; |
6490 | 6469 |
6491 if (nr != nc || nr != b.rows ()) | 6470 if (nr != nc || nr != b.rows ()) |
6492 (*current_liboctave_error_handler) | 6471 (*current_liboctave_error_handler) |
6493 ("matrix dimension mismatch solution of linear equations"); | 6472 ("matrix dimension mismatch solution of linear equations"); |
6494 else if (nr == 0 || b.cols () == 0) | 6473 |
6474 if (nr == 0 || b.cols () == 0) | |
6495 retval = SparseComplexMatrix (nc, b.cols ()); | 6475 retval = SparseComplexMatrix (nc, b.cols ()); |
6496 else | 6476 else |
6497 { | 6477 { |
6498 // Print spparms("spumoni") info if requested | 6478 // Print spparms("spumoni") info if requested |
6499 volatile int typ = mattype.type (); | 6479 volatile int typ = mattype.type (); |
6697 Ap, Ai, Ax, Xz, Bz, | 6677 Ap, Ai, Ax, Xz, Bz, |
6698 Numeric, control, info); | 6678 Numeric, control, info); |
6699 | 6679 |
6700 if (status < 0 || status2 < 0) | 6680 if (status < 0 || status2 < 0) |
6701 { | 6681 { |
6682 UMFPACK_DNAME (report_status) (control, status); | |
6683 | |
6684 // FIXME: Should this be a warning? | |
6702 (*current_liboctave_error_handler) | 6685 (*current_liboctave_error_handler) |
6703 ("SparseMatrix::solve solve failed"); | 6686 ("SparseMatrix::solve solve failed"); |
6704 | 6687 |
6705 UMFPACK_DNAME (report_status) (control, status); | |
6706 | |
6707 err = -1; | 6688 err = -1; |
6708 | |
6709 break; | 6689 break; |
6710 } | 6690 } |
6711 | 6691 |
6712 for (octave_idx_type i = 0; i < b_nr; i++) | 6692 for (octave_idx_type i = 0; i < b_nr; i++) |
6713 { | 6693 { |
6797 || typ == MatrixType::Tridiagonal_Hermitian) | 6777 || typ == MatrixType::Tridiagonal_Hermitian) |
6798 retval = trisolve (mattype, b, err, rcond, sing_handler, false); | 6778 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
6799 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | 6779 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
6800 retval = fsolve (mattype, b, err, rcond, sing_handler, true); | 6780 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
6801 else if (typ != MatrixType::Rectangular) | 6781 else if (typ != MatrixType::Rectangular) |
6802 { | 6782 (*current_liboctave_error_handler) ("unknown matrix type"); |
6803 (*current_liboctave_error_handler) ("unknown matrix type"); | |
6804 return Matrix (); | |
6805 } | |
6806 | 6783 |
6807 // Rectangular or one of the above solvers flags a singular matrix | 6784 // Rectangular or one of the above solvers flags a singular matrix |
6808 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) | 6785 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
6809 { | 6786 { |
6810 rcond = 1.; | 6787 rcond = 1.; |
6865 || typ == MatrixType::Tridiagonal_Hermitian) | 6842 || typ == MatrixType::Tridiagonal_Hermitian) |
6866 retval = trisolve (mattype, b, err, rcond, sing_handler, false); | 6843 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
6867 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | 6844 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
6868 retval = fsolve (mattype, b, err, rcond, sing_handler, true); | 6845 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
6869 else if (typ != MatrixType::Rectangular) | 6846 else if (typ != MatrixType::Rectangular) |
6870 { | 6847 (*current_liboctave_error_handler) ("unknown matrix type"); |
6871 (*current_liboctave_error_handler) ("unknown matrix type"); | |
6872 return SparseMatrix (); | |
6873 } | |
6874 | 6848 |
6875 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) | 6849 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
6876 { | 6850 { |
6877 rcond = 1.; | 6851 rcond = 1.; |
6878 #ifdef USE_QRSOLVE | 6852 #ifdef USE_QRSOLVE |
6933 || typ == MatrixType::Tridiagonal_Hermitian) | 6907 || typ == MatrixType::Tridiagonal_Hermitian) |
6934 retval = trisolve (mattype, b, err, rcond, sing_handler, false); | 6908 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
6935 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | 6909 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
6936 retval = fsolve (mattype, b, err, rcond, sing_handler, true); | 6910 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
6937 else if (typ != MatrixType::Rectangular) | 6911 else if (typ != MatrixType::Rectangular) |
6938 { | 6912 (*current_liboctave_error_handler) ("unknown matrix type"); |
6939 (*current_liboctave_error_handler) ("unknown matrix type"); | |
6940 return ComplexMatrix (); | |
6941 } | |
6942 | 6913 |
6943 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) | 6914 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
6944 { | 6915 { |
6945 rcond = 1.; | 6916 rcond = 1.; |
6946 #ifdef USE_QRSOLVE | 6917 #ifdef USE_QRSOLVE |
7001 || typ == MatrixType::Tridiagonal_Hermitian) | 6972 || typ == MatrixType::Tridiagonal_Hermitian) |
7002 retval = trisolve (mattype, b, err, rcond, sing_handler, false); | 6973 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
7003 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | 6974 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
7004 retval = fsolve (mattype, b, err, rcond, sing_handler, true); | 6975 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
7005 else if (typ != MatrixType::Rectangular) | 6976 else if (typ != MatrixType::Rectangular) |
7006 { | 6977 (*current_liboctave_error_handler) ("unknown matrix type"); |
7007 (*current_liboctave_error_handler) ("unknown matrix type"); | |
7008 return SparseComplexMatrix (); | |
7009 } | |
7010 | 6978 |
7011 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) | 6979 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
7012 { | 6980 { |
7013 rcond = 1.; | 6981 rcond = 1.; |
7014 #ifdef USE_QRSOLVE | 6982 #ifdef USE_QRSOLVE |