1 //
2 // Copyright (c) 2002--2010
3 // Toon Knapen, Karl Meerbergen, Kresimir Fresl,
4 // Thomas Klimpel and Rutger ter Borg
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // THIS FILE IS AUTOMATICALLY GENERATED
11 // PLEASE DO NOT EDIT!
12 //
13 
14 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_DRIVER_GELSD_HPP
15 #define BOOST_NUMERIC_BINDINGS_LAPACK_DRIVER_GELSD_HPP
16 
17 #include <boost/assert.hpp>
18 #include <boost/numeric/bindings/begin.hpp>
19 #include <boost/numeric/bindings/detail/array.hpp>
20 #include <boost/numeric/bindings/is_column_major.hpp>
21 #include <boost/numeric/bindings/is_complex.hpp>
22 #include <boost/numeric/bindings/is_mutable.hpp>
23 #include <boost/numeric/bindings/is_real.hpp>
24 #include <boost/numeric/bindings/lapack/auxiliary/ilaenv.hpp>
25 #include <boost/numeric/bindings/lapack/workspace.hpp>
26 #include <boost/numeric/bindings/remove_imaginary.hpp>
27 #include <boost/numeric/bindings/size.hpp>
28 #include <boost/numeric/bindings/stride.hpp>
29 #include <boost/numeric/bindings/traits/detail/utils.hpp>
30 #include <boost/numeric/bindings/value_type.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/type_traits/is_same.hpp>
33 #include <boost/type_traits/remove_const.hpp>
34 #include <boost/utility/enable_if.hpp>
35 
36 //
37 // The LAPACK-backend for gelsd is the netlib-compatible backend.
38 //
39 #include <boost/numeric/bindings/lapack/detail/lapack.h>
40 #include <boost/numeric/bindings/lapack/detail/lapack_option.hpp>
41 
42 namespace boost {
43 namespace numeric {
44 namespace bindings {
45 namespace lapack {
46 
47 //
48 // The detail namespace contains value-type-overloaded functions that
49 // dispatch to the appropriate back-end LAPACK-routine.
50 //
51 namespace detail {
52 
53 //
54 // Overloaded function for dispatching to
55 // * netlib-compatible LAPACK backend (the default), and
56 // * float value-type.
57 //
gelsd(const fortran_int_t m,const fortran_int_t n,const fortran_int_t nrhs,float * a,const fortran_int_t lda,float * b,const fortran_int_t ldb,float * s,const float rcond,fortran_int_t & rank,float * work,const fortran_int_t lwork,fortran_int_t * iwork)58 inline std::ptrdiff_t gelsd( const fortran_int_t m, const fortran_int_t n,
59         const fortran_int_t nrhs, float* a, const fortran_int_t lda, float* b,
60         const fortran_int_t ldb, float* s, const float rcond,
61         fortran_int_t& rank, float* work, const fortran_int_t lwork,
62         fortran_int_t* iwork ) {
63     fortran_int_t info(0);
64     LAPACK_SGELSD( &m, &n, &nrhs, a, &lda, b, &ldb, s, &rcond, &rank, work,
65             &lwork, iwork, &info );
66     return info;
67 }
68 
69 //
70 // Overloaded function for dispatching to
71 // * netlib-compatible LAPACK backend (the default), and
72 // * double value-type.
73 //
gelsd(const fortran_int_t m,const fortran_int_t n,const fortran_int_t nrhs,double * a,const fortran_int_t lda,double * b,const fortran_int_t ldb,double * s,const double rcond,fortran_int_t & rank,double * work,const fortran_int_t lwork,fortran_int_t * iwork)74 inline std::ptrdiff_t gelsd( const fortran_int_t m, const fortran_int_t n,
75         const fortran_int_t nrhs, double* a, const fortran_int_t lda,
76         double* b, const fortran_int_t ldb, double* s, const double rcond,
77         fortran_int_t& rank, double* work, const fortran_int_t lwork,
78         fortran_int_t* iwork ) {
79     fortran_int_t info(0);
80     LAPACK_DGELSD( &m, &n, &nrhs, a, &lda, b, &ldb, s, &rcond, &rank, work,
81             &lwork, iwork, &info );
82     return info;
83 }
84 
85 //
86 // Overloaded function for dispatching to
87 // * netlib-compatible LAPACK backend (the default), and
88 // * complex<float> value-type.
89 //
gelsd(const fortran_int_t m,const fortran_int_t n,const fortran_int_t nrhs,std::complex<float> * a,const fortran_int_t lda,std::complex<float> * b,const fortran_int_t ldb,float * s,const float rcond,fortran_int_t & rank,std::complex<float> * work,const fortran_int_t lwork,float * rwork,fortran_int_t * iwork)90 inline std::ptrdiff_t gelsd( const fortran_int_t m, const fortran_int_t n,
91         const fortran_int_t nrhs, std::complex<float>* a,
92         const fortran_int_t lda, std::complex<float>* b,
93         const fortran_int_t ldb, float* s, const float rcond,
94         fortran_int_t& rank, std::complex<float>* work,
95         const fortran_int_t lwork, float* rwork, fortran_int_t* iwork ) {
96     fortran_int_t info(0);
97     LAPACK_CGELSD( &m, &n, &nrhs, a, &lda, b, &ldb, s, &rcond, &rank, work,
98             &lwork, rwork, iwork, &info );
99     return info;
100 }
101 
102 //
103 // Overloaded function for dispatching to
104 // * netlib-compatible LAPACK backend (the default), and
105 // * complex<double> value-type.
106 //
gelsd(const fortran_int_t m,const fortran_int_t n,const fortran_int_t nrhs,const std::complex<double> * a,const fortran_int_t lda,std::complex<double> * b,const fortran_int_t ldb,double * s,const double rcond,fortran_int_t & rank,std::complex<double> * work,const fortran_int_t lwork,double * rwork,fortran_int_t * iwork)107 inline std::ptrdiff_t gelsd( const fortran_int_t m, const fortran_int_t n,
108         const fortran_int_t nrhs, const std::complex<double>* a,
109         const fortran_int_t lda, std::complex<double>* b,
110         const fortran_int_t ldb, double* s, const double rcond,
111         fortran_int_t& rank, std::complex<double>* work,
112         const fortran_int_t lwork, double* rwork, fortran_int_t* iwork ) {
113     fortran_int_t info(0);
114     LAPACK_ZGELSD( &m, &n, &nrhs, a, &lda, b, &ldb, s, &rcond, &rank, work,
115             &lwork, rwork, iwork, &info );
116     return info;
117 }
118 
119 } // namespace detail
120 
121 //
122 // Value-type based template class. Use this class if you need a type
123 // for dispatching to gelsd.
124 //
125 template< typename Value, typename Enable = void >
126 struct gelsd_impl {};
127 
128 //
129 // This implementation is enabled if Value is a real type.
130 //
131 template< typename Value >
132 struct gelsd_impl< Value, typename boost::enable_if< is_real< Value > >::type > {
133 
134     typedef Value value_type;
135     typedef typename remove_imaginary< Value >::type real_type;
136 
137     //
138     // Static member function for user-defined workspaces, that
139     // * Deduces the required arguments for dispatching to LAPACK, and
140     // * Asserts that most arguments make sense.
141     //
142     template< typename MatrixA, typename MatrixB, typename VectorS,
143             typename WORK, typename IWORK >
invokeboost::numeric::bindings::lapack::gelsd_impl144     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
145             const real_type rcond, fortran_int_t& rank,
146             detail::workspace2< WORK, IWORK > work ) {
147         namespace bindings = ::boost::numeric::bindings;
148         BOOST_STATIC_ASSERT( (bindings::is_column_major< MatrixA >::value) );
149         BOOST_STATIC_ASSERT( (bindings::is_column_major< MatrixB >::value) );
150         BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
151                 typename bindings::value_type< MatrixA >::type >::type,
152                 typename remove_const< typename bindings::value_type<
153                 MatrixB >::type >::type >::value) );
154         BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
155                 typename bindings::value_type< MatrixA >::type >::type,
156                 typename remove_const< typename bindings::value_type<
157                 VectorS >::type >::type >::value) );
158         BOOST_STATIC_ASSERT( (bindings::is_mutable< MatrixA >::value) );
159         BOOST_STATIC_ASSERT( (bindings::is_mutable< MatrixB >::value) );
160         BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorS >::value) );
161         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
162                 size_column(a) );
163         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
164         std::ptrdiff_t nlvl = std::max<
165                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
166                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
167                 1))/std::log(2.0)) + 1, 0 );
168         BOOST_ASSERT( bindings::size(s) >= std::min<
169                 std::ptrdiff_t >(bindings::size_row(a),
170                 bindings::size_column(a)) );
171         BOOST_ASSERT( bindings::size(work.select(fortran_int_t())) >=
172                 min_size_iwork( minmn, nlvl ));
173         BOOST_ASSERT( bindings::size(work.select(real_type())) >=
174                 min_size_work( minmn, smlsiz, nlvl,
175                 bindings::size_column(b) ));
176         BOOST_ASSERT( bindings::size_column(a) >= 0 );
177         BOOST_ASSERT( bindings::size_column(b) >= 0 );
178         BOOST_ASSERT( bindings::size_minor(a) == 1 ||
179                 bindings::stride_minor(a) == 1 );
180         BOOST_ASSERT( bindings::size_minor(b) == 1 ||
181                 bindings::stride_minor(b) == 1 );
182         BOOST_ASSERT( bindings::size_row(a) >= 0 );
183         BOOST_ASSERT( bindings::stride_major(a) >= std::max< std::ptrdiff_t >(1,
184                 bindings::size_row(a)) );
185         BOOST_ASSERT( bindings::stride_major(b) >= std::max< std::ptrdiff_t >(1,
186                 std::max< std::ptrdiff_t >(bindings::size_row(a),
187                 bindings::size_column(a))) );
188         return detail::gelsd( bindings::size_row(a), bindings::size_column(a),
189                 bindings::size_column(b), bindings::begin_value(a),
190                 bindings::stride_major(a), bindings::begin_value(b),
191                 bindings::stride_major(b), bindings::begin_value(s), rcond,
192                 rank, bindings::begin_value(work.select(real_type())),
193                 bindings::size(work.select(real_type())),
194                 bindings::begin_value(work.select(fortran_int_t())) );
195     }
196 
197     //
198     // Static member function that
199     // * Figures out the minimal workspace requirements, and passes
200     //   the results to the user-defined workspace overload of the
201     //   invoke static member function
202     // * Enables the unblocked algorithm (BLAS level 2)
203     //
204     template< typename MatrixA, typename MatrixB, typename VectorS >
invokeboost::numeric::bindings::lapack::gelsd_impl205     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
206             const real_type rcond, fortran_int_t& rank,
207             minimal_workspace ) {
208         namespace bindings = ::boost::numeric::bindings;
209         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
210                 size_column(a) );
211         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
212         std::ptrdiff_t nlvl = std::max<
213                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
214                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
215                 1))/std::log(2.0)) + 1, 0 );
216         bindings::detail::array< real_type > tmp_work( min_size_work( minmn,
217                 smlsiz, nlvl, bindings::size_column(b) ) );
218         bindings::detail::array< fortran_int_t > tmp_iwork(
219                 min_size_iwork( minmn, nlvl ) );
220         return invoke( a, b, s, rcond, rank, workspace( tmp_work,
221                 tmp_iwork ) );
222     }
223 
224     //
225     // Static member function that
226     // * Figures out the optimal workspace requirements, and passes
227     //   the results to the user-defined workspace overload of the
228     //   invoke static member
229     // * Enables the blocked algorithm (BLAS level 3)
230     //
231     template< typename MatrixA, typename MatrixB, typename VectorS >
invokeboost::numeric::bindings::lapack::gelsd_impl232     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
233             const real_type rcond, fortran_int_t& rank,
234             optimal_workspace ) {
235         namespace bindings = ::boost::numeric::bindings;
236         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
237                 size_column(a) );
238         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
239         std::ptrdiff_t nlvl = std::max<
240                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
241                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
242                 1))/std::log(2.0)) + 1, 0 );
243         real_type opt_size_work;
244         bindings::detail::array< fortran_int_t > tmp_iwork(
245                 min_size_iwork( minmn, nlvl ) );
246         detail::gelsd( bindings::size_row(a), bindings::size_column(a),
247                 bindings::size_column(b), bindings::begin_value(a),
248                 bindings::stride_major(a), bindings::begin_value(b),
249                 bindings::stride_major(b), bindings::begin_value(s), rcond,
250                 rank, &opt_size_work, -1, bindings::begin_value(tmp_iwork) );
251         bindings::detail::array< real_type > tmp_work(
252                 traits::detail::to_int( opt_size_work ) );
253         return invoke( a, b, s, rcond, rank, workspace( tmp_work,
254                 tmp_iwork ) );
255     }
256 
257     //
258     // Static member function that returns the minimum size of
259     // workspace-array work.
260     //
min_size_workboost::numeric::bindings::lapack::gelsd_impl261     static std::ptrdiff_t min_size_work( const std::ptrdiff_t minmn,
262             const std::ptrdiff_t smlsiz, const std::ptrdiff_t nlvl,
263             const std::ptrdiff_t nrhs ) {
264         std::ptrdiff_t smlsiz_plus_one = smlsiz + 1;
265         return std::max< std::ptrdiff_t >( 1, 12*minmn + 2*minmn*smlsiz +
266                 8*minmn*nlvl + minmn*nrhs +
267                 smlsiz_plus_one * smlsiz_plus_one );
268     }
269 
270     //
271     // Static member function that returns the minimum size of
272     // workspace-array iwork.
273     //
min_size_iworkboost::numeric::bindings::lapack::gelsd_impl274     static std::ptrdiff_t min_size_iwork( const std::ptrdiff_t minmn,
275             const std::ptrdiff_t nlvl ) {
276         return std::max< std::ptrdiff_t >( 1, 3*minmn*nlvl + 11*minmn );
277     }
278 };
279 
280 //
281 // This implementation is enabled if Value is a complex type.
282 //
283 template< typename Value >
284 struct gelsd_impl< Value, typename boost::enable_if< is_complex< Value > >::type > {
285 
286     typedef Value value_type;
287     typedef typename remove_imaginary< Value >::type real_type;
288 
289     //
290     // Static member function for user-defined workspaces, that
291     // * Deduces the required arguments for dispatching to LAPACK, and
292     // * Asserts that most arguments make sense.
293     //
294     template< typename MatrixA, typename MatrixB, typename VectorS,
295             typename WORK, typename RWORK, typename IWORK >
invokeboost::numeric::bindings::lapack::gelsd_impl296     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
297             const real_type rcond, fortran_int_t& rank,
298             detail::workspace3< WORK, RWORK, IWORK > work ) {
299         namespace bindings = ::boost::numeric::bindings;
300         BOOST_STATIC_ASSERT( (bindings::is_column_major< MatrixA >::value) );
301         BOOST_STATIC_ASSERT( (bindings::is_column_major< MatrixB >::value) );
302         BOOST_STATIC_ASSERT( (boost::is_same< typename remove_const<
303                 typename bindings::value_type< MatrixA >::type >::type,
304                 typename remove_const< typename bindings::value_type<
305                 MatrixB >::type >::type >::value) );
306         BOOST_STATIC_ASSERT( (bindings::is_mutable< MatrixA >::value) );
307         BOOST_STATIC_ASSERT( (bindings::is_mutable< MatrixB >::value) );
308         BOOST_STATIC_ASSERT( (bindings::is_mutable< VectorS >::value) );
309         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
310                 size_column(a) );
311         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
312         std::ptrdiff_t nlvl = std::max<
313                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
314                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
315                 1))/std::log(2.0)) + 1, 0 );
316         BOOST_ASSERT( bindings::size(s) >= std::min<
317                 std::ptrdiff_t >(bindings::size_row(a),
318                 bindings::size_column(a)) );
319         BOOST_ASSERT( bindings::size(work.select(fortran_int_t())) >=
320                 min_size_iwork( minmn, nlvl ));
321         BOOST_ASSERT( bindings::size(work.select(real_type())) >=
322                 min_size_rwork( minmn, smlsiz, nlvl,
323                 bindings::size_column(b) ));
324         BOOST_ASSERT( bindings::size(work.select(value_type())) >=
325                 min_size_work( bindings::size_column(a), minmn,
326                 bindings::size_column(b) ));
327         BOOST_ASSERT( bindings::size_column(a) >= 0 );
328         BOOST_ASSERT( bindings::size_column(b) >= 0 );
329         BOOST_ASSERT( bindings::size_minor(a) == 1 ||
330                 bindings::stride_minor(a) == 1 );
331         BOOST_ASSERT( bindings::size_minor(b) == 1 ||
332                 bindings::stride_minor(b) == 1 );
333         BOOST_ASSERT( bindings::size_row(a) >= 0 );
334         BOOST_ASSERT( bindings::stride_major(a) >= std::max< std::ptrdiff_t >(1,
335                 bindings::size_row(a)) );
336         BOOST_ASSERT( bindings::stride_major(b) >= std::max< std::ptrdiff_t >(1,
337                 std::max< std::ptrdiff_t >(bindings::size_row(a),
338                 bindings::size_column(a))) );
339         return detail::gelsd( bindings::size_row(a), bindings::size_column(a),
340                 bindings::size_column(b), bindings::begin_value(a),
341                 bindings::stride_major(a), bindings::begin_value(b),
342                 bindings::stride_major(b), bindings::begin_value(s), rcond,
343                 rank, bindings::begin_value(work.select(value_type())),
344                 bindings::size(work.select(value_type())),
345                 bindings::begin_value(work.select(real_type())),
346                 bindings::begin_value(work.select(fortran_int_t())) );
347     }
348 
349     //
350     // Static member function that
351     // * Figures out the minimal workspace requirements, and passes
352     //   the results to the user-defined workspace overload of the
353     //   invoke static member function
354     // * Enables the unblocked algorithm (BLAS level 2)
355     //
356     template< typename MatrixA, typename MatrixB, typename VectorS >
invokeboost::numeric::bindings::lapack::gelsd_impl357     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
358             const real_type rcond, fortran_int_t& rank,
359             minimal_workspace ) {
360         namespace bindings = ::boost::numeric::bindings;
361         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
362                 size_column(a) );
363         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
364         std::ptrdiff_t nlvl = std::max<
365                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
366                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
367                 1))/std::log(2.0)) + 1, 0 );
368         bindings::detail::array< value_type > tmp_work( min_size_work(
369                 bindings::size_column(a), minmn, bindings::size_column(b) ) );
370         bindings::detail::array< real_type > tmp_rwork( min_size_rwork( minmn,
371                 smlsiz, nlvl, bindings::size_column(b) ) );
372         bindings::detail::array< fortran_int_t > tmp_iwork(
373                 min_size_iwork( minmn, nlvl ) );
374         return invoke( a, b, s, rcond, rank, workspace( tmp_work, tmp_rwork,
375                 tmp_iwork ) );
376     }
377 
378     //
379     // Static member function that
380     // * Figures out the optimal workspace requirements, and passes
381     //   the results to the user-defined workspace overload of the
382     //   invoke static member
383     // * Enables the blocked algorithm (BLAS level 3)
384     //
385     template< typename MatrixA, typename MatrixB, typename VectorS >
invokeboost::numeric::bindings::lapack::gelsd_impl386     static std::ptrdiff_t invoke( MatrixA& a, MatrixB& b, VectorS& s,
387             const real_type rcond, fortran_int_t& rank,
388             optimal_workspace ) {
389         namespace bindings = ::boost::numeric::bindings;
390         std::ptrdiff_t minmn = std::min< std::ptrdiff_t >( size_row(a),
391                 size_column(a) );
392         std::ptrdiff_t smlsiz = ilaenv(9, "GELSD", "");
393         std::ptrdiff_t nlvl = std::max<
394                 std::ptrdiff_t >( static_cast<std::ptrdiff_t>(std::log(
395                 static_cast<real_type>(minmn)/static_cast<real_type>(smlsiz+
396                 1))/std::log(2.0)) + 1, 0 );
397         value_type opt_size_work;
398         bindings::detail::array< real_type > tmp_rwork( min_size_rwork( minmn,
399                 smlsiz, nlvl, bindings::size_column(b) ) );
400         bindings::detail::array< fortran_int_t > tmp_iwork(
401                 min_size_iwork( minmn, nlvl ) );
402         detail::gelsd( bindings::size_row(a), bindings::size_column(a),
403                 bindings::size_column(b), bindings::begin_value(a),
404                 bindings::stride_major(a), bindings::begin_value(b),
405                 bindings::stride_major(b), bindings::begin_value(s), rcond,
406                 rank, &opt_size_work, -1, bindings::begin_value(tmp_rwork),
407                 bindings::begin_value(tmp_iwork) );
408         bindings::detail::array< value_type > tmp_work(
409                 traits::detail::to_int( opt_size_work ) );
410         return invoke( a, b, s, rcond, rank, workspace( tmp_work, tmp_rwork,
411                 tmp_iwork ) );
412     }
413 
414     //
415     // Static member function that returns the minimum size of
416     // workspace-array work.
417     //
min_size_workboost::numeric::bindings::lapack::gelsd_impl418     static std::ptrdiff_t min_size_work( const std::ptrdiff_t n,
419             const std::ptrdiff_t minmn, const std::ptrdiff_t nrhs ) {
420         return std::max< std::ptrdiff_t >( 1, 2*minmn + std::max<
421                 std::ptrdiff_t >( n, minmn*nrhs ) );
422     }
423 
424     //
425     // Static member function that returns the minimum size of
426     // workspace-array rwork.
427     //
min_size_rworkboost::numeric::bindings::lapack::gelsd_impl428     static std::ptrdiff_t min_size_rwork( const std::ptrdiff_t minmn,
429             const std::ptrdiff_t smlsiz, const std::ptrdiff_t nlvl,
430             const std::ptrdiff_t nrhs ) {
431         std::ptrdiff_t smlsiz_plus_one = smlsiz + 1;
432         return std::max< std::ptrdiff_t >( 1, 10*minmn + 2*minmn*smlsiz +
433                 8*minmn*nlvl + 3*smlsiz*nrhs +
434                 smlsiz_plus_one * smlsiz_plus_one );
435     }
436 
437     //
438     // Static member function that returns the minimum size of
439     // workspace-array iwork.
440     //
min_size_iworkboost::numeric::bindings::lapack::gelsd_impl441     static std::ptrdiff_t min_size_iwork( const std::ptrdiff_t minmn,
442             const std::ptrdiff_t nlvl ) {
443         return std::max< std::ptrdiff_t >( 1, 3*minmn*nlvl + 11*minmn );
444     }
445 };
446 
447 
448 //
449 // Functions for direct use. These functions are overloaded for temporaries,
450 // so that wrapped types can still be passed and used for write-access. In
451 // addition, if applicable, they are overloaded for user-defined workspaces.
452 // Calls to these functions are passed to the gelsd_impl classes. In the
453 // documentation, most overloads are collapsed to avoid a large number of
454 // prototypes which are very similar.
455 //
456 
457 //
458 // Overloaded function for gelsd. Its overload differs for
459 // * User-defined workspace
460 //
461 template< typename MatrixA, typename MatrixB, typename VectorS,
462         typename Workspace >
463 inline typename boost::enable_if< detail::is_workspace< Workspace >,
464         std::ptrdiff_t >::type
gelsd(MatrixA & a,MatrixB & b,VectorS & s,const typename remove_imaginary<typename bindings::value_type<MatrixA>::type>::type rcond,fortran_int_t & rank,Workspace work)465 gelsd( MatrixA& a, MatrixB& b, VectorS& s,
466         const typename remove_imaginary< typename bindings::value_type<
467         MatrixA >::type >::type rcond, fortran_int_t& rank,
468         Workspace work ) {
469     return gelsd_impl< typename bindings::value_type<
470             MatrixA >::type >::invoke( a, b, s, rcond, rank, work );
471 }
472 
473 //
474 // Overloaded function for gelsd. Its overload differs for
475 // * Default workspace-type (optimal)
476 //
477 template< typename MatrixA, typename MatrixB, typename VectorS >
478 inline typename boost::disable_if< detail::is_workspace< VectorS >,
479         std::ptrdiff_t >::type
gelsd(MatrixA & a,MatrixB & b,VectorS & s,const typename remove_imaginary<typename bindings::value_type<MatrixA>::type>::type rcond,fortran_int_t & rank)480 gelsd( MatrixA& a, MatrixB& b, VectorS& s,
481         const typename remove_imaginary< typename bindings::value_type<
482         MatrixA >::type >::type rcond, fortran_int_t& rank ) {
483     return gelsd_impl< typename bindings::value_type<
484             MatrixA >::type >::invoke( a, b, s, rcond, rank,
485             optimal_workspace() );
486 }
487 
488 } // namespace lapack
489 } // namespace bindings
490 } // namespace numeric
491 } // namespace boost
492 
493 #endif
494