Mercurial > hg > octave-lyh
comparison liboctave/dMatrix.cc @ 7476:e9f10b4c05cf
fix workspace size calculation for xGELSD
author | Jason Riedy |
---|---|
date | Tue, 12 Feb 2008 21:04:27 -0500 |
parents | a7a987b229b7 |
children | 8b22207ef9ca |
comparison
equal
deleted
inserted
replaced
7475:aa5208636bea | 7476:e9f10b4c05cf |
---|---|
57 | 57 |
58 // Fortran functions we call. | 58 // Fortran functions we call. |
59 | 59 |
60 extern "C" | 60 extern "C" |
61 { | 61 { |
62 octave_idx_type | |
63 F77_FUNC (ilaenv, ILAENV) (const octave_idx_type&, F77_CONST_CHAR_ARG_DECL, | |
64 F77_CONST_CHAR_ARG_DECL, | |
65 const octave_idx_type&, const octave_idx_type&, | |
66 const octave_idx_type&, const octave_idx_type& | |
67 F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); | |
68 | |
62 F77_RET_T | 69 F77_RET_T |
63 F77_FUNC (dgebal, DGEBAL) (F77_CONST_CHAR_ARG_DECL, | 70 F77_FUNC (dgebal, DGEBAL) (F77_CONST_CHAR_ARG_DECL, |
64 const octave_idx_type&, double*, const octave_idx_type&, octave_idx_type&, | 71 const octave_idx_type&, double*, const octave_idx_type&, octave_idx_type&, |
65 octave_idx_type&, double*, octave_idx_type& | 72 octave_idx_type&, double*, octave_idx_type& |
66 F77_CHAR_ARG_LEN_DECL); | 73 F77_CHAR_ARG_LEN_DECL); |
2101 // Ask DGELSD what the dimension of WORK should be. | 2108 // Ask DGELSD what the dimension of WORK should be. |
2102 octave_idx_type lwork = -1; | 2109 octave_idx_type lwork = -1; |
2103 | 2110 |
2104 Array<double> work (1); | 2111 Array<double> work (1); |
2105 | 2112 |
2106 // FIXME: Can SMLSIZ be other than 25? | 2113 const octave_idx_type smlsiz |
2107 octave_idx_type smlsiz = 25; | 2114 = F77_FUNC (ilaenv, ILAENV) (9, F77_CONST_CHAR_ARG2 ("DGELSD", 6), |
2115 F77_CONST_CHAR_ARG2 (" ", 1), | |
2116 0, 0, 0, 0 | |
2117 F77_CHAR_ARG_LEN (6) | |
2118 F77_CHAR_ARG_LEN (1)); | |
2108 | 2119 |
2109 // We compute the size of iwork because DGELSD in older versions | 2120 // We compute the size of iwork because DGELSD in older versions |
2110 // of LAPACK does not return it on a query call. | 2121 // of LAPACK does not return it on a query call. |
2111 double dminmn = static_cast<double> (minmn); | 2122 double dminmn = static_cast<double> (minmn); |
2112 double dsmlsizp1 = static_cast<double> (smlsiz+1); | 2123 double dsmlsizp1 = static_cast<double> (smlsiz+1); |
2126 octave_idx_type* piwork = iwork.fortran_vec (); | 2137 octave_idx_type* piwork = iwork.fortran_vec (); |
2127 | 2138 |
2128 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | 2139 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, |
2129 ps, rcond, rank, work.fortran_vec (), | 2140 ps, rcond, rank, work.fortran_vec (), |
2130 lwork, piwork, info)); | 2141 lwork, piwork, info)); |
2142 | |
2143 // The workspace query is broken in at least LAPACK 3.0.0 | |
2144 // through 3.1.1 when n > m. The obtuse formula below | |
2145 // should provide sufficient workspace for DGELSD to operate | |
2146 // efficiently. | |
2147 if (n > m) | |
2148 { | |
2149 const octave_idx_type wlalsd | |
2150 = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1); | |
2151 | |
2152 octave_idx_type addend = m; | |
2153 | |
2154 if (2*m-4 > addend) | |
2155 addend = 2*m-4; | |
2156 | |
2157 if (nrhs > addend) | |
2158 addend = nrhs; | |
2159 | |
2160 if (n-3*m > addend) | |
2161 addend = n-3*m; | |
2162 | |
2163 if (wlalsd > addend) | |
2164 addend = wlalsd; | |
2165 | |
2166 const octave_idx_type lworkaround = 4*m + m*m + addend; | |
2167 | |
2168 if (work(0) < lworkaround) | |
2169 work(0) = lworkaround; | |
2170 } | |
2131 | 2171 |
2132 if (f77_exception_encountered) | 2172 if (f77_exception_encountered) |
2133 (*current_liboctave_error_handler) | 2173 (*current_liboctave_error_handler) |
2134 ("unrecoverable error in dgelsd"); | 2174 ("unrecoverable error in dgelsd"); |
2135 else | 2175 else |