|
Boost.Numeric.Bindings.LAPACK |
``LAPACK is a library of Fortran 77 subroutines for solving the most commonly occurring problems in numerical linear algebra. It has been designed to be efficient on a wide range of modern high-performance computers. The name LAPACK is an acronym for Linear Algebra PACKage.
LAPACK can solve systems of linear equations, linear least squares problems, eigenvalue problems and singular value problems. LAPACK can also handle many associated computations such as matrix factorizations or estimating condition numbers.
LAPACK contains driver routines for solving standard types of problems, computational routines to perform a distinct computational task, and auxiliary routines to perform a certain subtask or common low-level computation. Each driver routine typically calls a sequence of computational routines. Taken as a whole, the computational routines can perform a wider range of tasks than are covered by the driver routines. [...]
Dense and band matrices are provided for, but not general sparse matrices. In all areas, similar functionality is provided for real and complex matrices.''
For a complete overview of the LAPACK routines see chapter Contents of LAPACK in the LAPACK Users' Guide.
There is also the C version of LAPACK, called CLAPACK. ``The CLAPACK library was built using a Fortran to C conversion utility called f2c. The entire Fortran 77 LAPACK library is run through f2c to obtain C code, and then modified to improve readability. CLAPACK's goal is to provide LAPACK for someone who does not have access to a Fortran compiler.'' [quote from CLAPACK readme]
LAPACK Bindings Library provides generic, higher level interface to LAPACK routines. By `generic' we mean that bindings are based on traits and therefore can be used with various (sparse) matrix and vector classes, and by `higher level' that some complexities of the Fortran or C interfaces and calling conventions are hidden from the user. But, as LAPACK was written in Fortran (and CLAPACK is a direct conversion to C), matrices must have column major storage order.
boost/numeric/bindings/lapack
.
All `public'
functions are in the namespace boost::numeric::bindings::lapack
.
Note: LAPACK bindings can be used with either LAPACK or CLAPACK libraries. We recommend to use bindings with genuine LAPACK. But if you use CLAPACK, define BOOST_NUMERIC_BINDINGS_USE_CLAPACK before the inclusion of LAPACK bindings files.
A X = B
,
where A
is the coefficient matrix, the columns of
B
are the individual right hand sides and the columns of
X
are corresponding unknown vectors.
To find the solution (i.e. determine X
, given
A
and B
), A
is first factorised
as a product of triangular matrices (and in some cases also a diagonal
matrix or permutation matrix), and then a backward or forward
substitution is carried out.
The form of the factorisation depends on the structure and properties
of the matrix A
:
A = PLU
,
where P
is a permutation matrix, L
is lower
triangular (with unit diagonal elements) and U
is upper
triangular;
A = UTU
or A = LLT
(A
symmetric) and A = UHU
or A =
LLH
(A
Hermitian),
where U
and L
are upper and lower
triangular, respectively;
A = UDUT
or A = LDLT
or A = UDUH
or A = LDLH
,
where U
(or L
) is a product of permutation and unit upper (lower) triangular matrices, and D
is symmetric and block diagonal with diagonal blocks of order 1 or 2.
LAPACK bindings follow LAPACK's naming scheme, except for the first letter which denotes the type of the matrix elements as it is not needed (because of function overloading and templates). So, all function names have the form xxyyy (or xxyy), where xx denotes the structure/properties of the matrix, and yyy indicates the computation to be done:
ge
-- general,
po
-- symmetric/Hermitian positive definite (not packed),
pp
-- symmetric/Hermitian positive definite stored in packed format,
sy
-- symmetric (real and complex) indefinite (not packed),
sp
-- symmetric indefinite stored in packed format,
he
-- Hermitian indefinite (not packed),
hp
-- Hermitian indefinite stored in packed format;
sv
-- solve the system (driver routine),
trf
-- factor (computational routine),
trs
-- solve from factorisation, i.e. backward (or
forward) substitution (computational routine).
Our convention is to group the functions which solve the same problem
(or part of it) in separate files, named after the corresponding
driver routine -- for example, gesv()
,
getrf()
and getrs()
, that is, functions for
solving (perhaps in several steps) a system with general coefficient matrix,
are defined in gesv.hpp
.
boost/numeric/bindings/lapack/gesv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
, U
are matrices,
ipiv
is a vector of pivot indices representing
premutation matrix P
(for more details see description of
the LU factorisation above),
Trans
can be 'N'
,
'T'
or 'C'
, denoting
A
, AT
or AH
,
respectively, and ierr
is `diagnostic argument'
INFO
(as described in
LAPACK Users' Guide).
Expression | Semantics |
---|---|
gesv(A,ipiv,B) | using AP=LU ,
B <- A-1B , A <- LU ,
ipiv <- P ; returns ierr
|
gesv(A,B) | as above, with ipiv
allocated and deallocated internally
|
getrf(A,ipiv) | using AP=LU ,
A <- LU , ipiv <- P ; returns ierr
|
getrs(Trans,A,ipiv,B) |
B <- op(A)-1B assuming
A <- LU and ipiv <- P ,
op (A) == A || AT || AH ;
returns ierr
|
getrs(A,ipiv,B) | B <- A-1B assuming A <- LU and ipiv <- P ;
returns ierr
|
boost/numeric/bindings/lapack/posv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
are matrices (for more details see description of
the Cholesky factorisation above), Uplo
can be 'U'
or 'L'
, denoting that leading
upper or lower, respectively, triangular part of A
contains
the upper or lower triangular part of the symmetric/Hermitian matrix
(and that the lower or upper triangular part, respectively, is not referenced)
and ierr
is LAPACK's `diagnostic argument'
INFO
.
Expression | Semantics |
---|---|
posv(Uplo,A,B) |
B <- A-1B , using
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
posv(A,B) |
B <- A-1B , using
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr [1]
|
potrf(Uplo,A) |
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
potrf(A) |
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr [1]
|
potrs(Uplo,A,B) |
B <- A-1B assuming
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
potrs(A,B) |
B <- A-1B assuming
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr [1]
|
[1] It is assumed that matrix traits class can determine whether upper
or lower triangular part of A
contains the corresponding
part of the symmetric/Hermitian matrix (e.g. traits for
ublas::symmetric_adaptor<>
and ublas::hermitian_adaptor<>
).
boost/numeric/bindings/lapack/ppsv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
are matrices (for more details see description of
the Cholesky factorisation above)
and ierr
is LAPACK's `diagnostic argument' INFO
.
Matrix A
is stored in packed format (e.g.
ublas::symmetric_matrix<>
and ublas::hermitian_matrix<>
).
Expression | Semantics |
---|---|
ppsv(A,B) |
B <- A-1B , using
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
pptrf(A) |
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
pptrs(A,B) |
B <- A-1B assuming
A = UTU or A = LLT
or A = UHU or A = LLH ;
returns ierr
|
It is assumed that matrix traits class can determine whether
or lower triangular part of the symmetric/Hermitian matrix is stored
(e.g. traits for
ublas::symmetric_matrix<>
and ublas::hermitian_matrix<>
).
boost/numeric/bindings/lapack/sysv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
, D
are matrices, ipiv
is a
vector of pivot indices (for more details see description of
the Bunch-Kaufman factorisation above),
w
is a `work' vector,
Uplo
can be 'U'
or 'L'
, denoting that leading upper or lower, respectively, triangular part of A
contains
the upper or lower triangular part of the symmetric matrix
(and that the lower or upper triangular part, respectively, is not referenced),
Spec
can be 'O'
or 'M'
,
specifying whether optimal or minimum size is to be returned,
and ierr
is LAPACK's `diagnostic argument'
INFO
.
Expression | Semantics |
---|---|
sysv(Uplo,A,ipiv,B,w) |
B <- A-1B , using
A = UDUT or A = LDLT ;
returns ierr
|
sysv(Uplo,A,B) |
as above, with ipiv and w allocated and deallocated internally
|
sysv(A,ipiv,B,w) |
B <- A-1B , using
A = UDUT or A = LDLT ;
returns ierr
[1]
|
sysv(A,B) |
as above, with ipiv and w allocated and deallocated internally
[1]
|
sysv_work(Spec,Uplo,A) |
returns optimal or minimum size of the vector w
|
sysv_work(Spec,A) |
returns optimal or minimum size of the vector w [1]
|
sytrf(Uplo,A,ipiv,w) |
A = UDUT or A = LDLT ;
returns ierr
|
sytrf(Uplo,A,ipiv) |
as above, with w allocated and deallocated internally
|
sytrf(A,ipiv,w) |
A = UDUT or A = LDLT ;
returns ierr [1]
|
sytrf(A,ipiv) |
as above, with w allocated and deallocated internally [1]
|
sytrf_work(Spec,Uplo,A) |
returns optimal or minimum size of the vector w
|
sytrf_work(Spec,A) |
returns optimal or minimum size of the vector w [1]
|
sytrf_block(Spec,Uplo,A) | returns optimal or minimum block size [2] |
sytrf_block(Spec,A) | returns optimal or minimum block size [1][2] |
sytrs(Uplo,A,ipiv,B) |
B <- A-1B assuming
A = UDUT or A = LDLT ;
returns ierr
|
sytrs(A,ipiv,B) |
B <- A-1B assuming
A = UDUT or A = LDLT ;
returns ierr [1]
|
[1] It is assumed that matrix traits class can determine whether upper
or lower triangular part of A
contains the corresponding
part of the symmetric matrix (e.g. traits for
ublas::symmetric_adaptor<>
).
[2] Optimal size of the `work' vector w
is n*nb
, where
nb
is optimal block size and n
the
order of matrix A
.
boost/numeric/bindings/lapack/spsv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
, D
are matrices, ipiv
is a
vector of pivot indices (for more details see description of
the Bunch-Kaufman factorisation above)
and ierr
is LAPACK's `diagnostic argument' INFO
.
Matrix A
is stored in packed format (e.g.
ublas::symmetric_matrix<>
).
Expression | Semantics |
---|---|
spsv(A,ipiv,B) |
B <- A-1B , using
A = UDUT or A = LDLT ;
returns ierr
|
spsv(A,B) |
as above, with ipiv allocated and deallocated internally
|
sptrf(A,ipiv) |
A = UDUT or A = LDLT ;
returns ierr
|
sptrs(A,ipiv,B) |
B <- A-1B assuming
A = UDUT or A = LDLT ;
returns ierr
|
It is assumed that matrix traits class can determine whether upper
or lower triangular part of the symmetric matrix is stored (e.g. traits for
ublas::symmetric_matrix<>
).
boost/numeric/bindings/lapack/hesv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
, D
are matrices, ipiv
is a
vector of pivot indices (for more details see description of
the Bunch-Kaufman factorisation above), w
is a `work' vector, Uplo
can be 'U'
or 'L'
, denoting that leading upper or lower, respectively, triangular part of A
contains
the upper or lower triangular part of the Hermitian matrix
(and that the lower or upper triangular part, respectively, is not referenced),
Spec
can be 'O'
or 'M'
,
specifying whether optimal or minimum size is to be returned,
and ierr
is LAPACK's `diagnostic argument'
INFO
.
Expression | Semantics |
---|---|
hesv(Uplo,A,ipiv,B,w) |
B <- A-1B , using
A = UDUH or A = LDLH ;
returns ierr
|
hesv(Uplo,A,B) |
as above, with ipiv and w allocated and deallocated internally
|
hesv(A,ipiv,B,w) |
B <- A-1B , using
A = UDUH or A = LDLH ;
returns ierr
[1]
|
hesv(A,B) |
as above, with ipiv and w allocated and deallocated internally
[1]
|
hesv_work(Spec,Uplo,A) |
returns optimal or minimum size of the vector w
|
hesv_work(Spec,A) |
returns optimal or minimum size of the vector w [1]
|
hetrf(Uplo,A,ipiv,w) |
A = UDUH or A = LDLH ;
returns ierr
|
hetrf(Uplo,A,ipiv) |
as above, with w allocated and deallocated internally
|
hetrf(A,ipiv,w) |
A = UDUH or A = LDLH ;
returns ierr [1]
|
hetrf(A,ipiv) |
as above, with w allocated and deallocated internally [1]
|
hetrf_work(Spec,Uplo,A) |
returns optimal or minimum size of the vector w
|
hetrf_work(Spec,A) |
returns optimal or minimum size of the vector w [1]
|
hetrf_block(Spec,Uplo,A) | returns optimal or minimal block size [2] |
hetrf_block(Spec,A) | returns optimal or minimal block size [1][2] |
hetrs(Uplo,A,ipiv,B) |
B <- A-1B assuming
A = UDUH or A = LDLH ;
returns ierr
|
hetrs(A,ipiv,B) |
B <- A-1B assuming
A = UDUH or A = LDLH ;
returns ierr [1]
|
[1] It is assumed that matrix traits class can determine whether upper
or lower triangular part of A
contains the corresponding
part of the Hermitian matrix (e.g. traits for
ublas::hermitian_adaptor<>
).
[2] Optimal size of the `work' vector w
is n*nb
, where
nb
is optimal block size and n
the
order of matrix A
.
boost/numeric/bindings/lapack/hpsv.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, B
, L
,
U
, D
are matrices, ipiv
is a
vector of pivot indices (for more details see description of
the Bunch-Kaufman factorisation above)
and ierr
is LAPACK's `diagnostic argument' INFO
.
Matrix A
is stored in packed format (e.g.
ublas::hermitian_matrix<>
).
Expression | Semantics |
---|---|
hpsv(A,ipiv,B) |
B <- A-1B , using
A = UDUH or A = LDLH ;
returns ierr
|
hpsv(A,B) |
as above, with ipiv allocated and deallocated internally
|
hptrf(A,ipiv) |
A = UDUH or A = LDLH ;
returns ierr
|
hptrs(A,ipiv,B) |
B <- A-1B assuming
A = UDUH or A = LDLH ;
returns ierr
|
It is assumed that matrix traits class can determine whether upper
or lower triangular part of the Hermitian matrix is stored (e.g. traits for
ublas::hermitian_matrix<>
).
A
is given by
A = U S VT
if A
is real and by
A = U S VH
if A
is complex matrix. U
and V
are ortogonal in real case and unitary in complex case;
U
is m-by-m and V
is
n-by-n. First min(m,n) columns of
U
and V
are the left and right singular
vectors of A
. S
is an m-by-n
real matrix with non-negative elements sii and with sij==0 for
i!=
j. The sii are singular
values of A
.
Matrix S
is in LAPACK
represented by a vector s
(such that ii->
i).
LAPACK Bindings Library currently provides bindings for LAPACK driver routines only.
gesvd()
computes all the singular values
and optionally left and/or right singular vectors.
Defined in boost/numeric/bindings/lapack/gesvd.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, U
, VT
(denoting VT
or VH
-- namely, routine returns VT
or
VH
, not V
)
are matrices; s
is a vector representing matrix
S
; w
, rw
,
are `work' vectors (elements of w
can be real or complex,
elements of rw
are real).
Jobu
specifies options for computing U
:
'N'
-- no left singular vectors are computed,
'S'
-- left singular vectors are returned in
the first min(m,n) columns of U
,
'A'
-- complete matrix U
is computed,
'O'
-- left singular vectors are overwritten on
the first min(m,n) columns of A
.
Jobvt
specifies options for computing VT
:
'N'
-- no right singular vectors are computed,
'S'
-- right singular vectors are returned in
the first min(m,n) rows of VT
,
'A'
-- complete matrix VT
is computed,
'O'
-- right singular vectors are overwritten on
the first min(m,n) rows of A
.
Jobu
and Jobvt
cannot both be
'O'
.
Lw
can be 'O'
or 'M'
,
specifying whether optimal or minimum size of the `work' vector
is to be used or calculated; 'O'
can be used with LAPACK
version 3.0 only.
And finally, ierr
is LAPACK's `diagnostic argument' INFO
.
Expression | Semantics |
---|---|
gesvd(Jobu,Jobvt,A,s,U,VT,w) |
SVD of real A ;
returns ierr
|
gesvd(Jobu,Jobvt,A,s,U,VT,w,rw) |
SVD of complex A ;
returns ierr
|
gesvd(Lw,Jobu,Jobvt,A,s,U,VT) |
SVD of real or complex A , with `internal' work space;
returns ierr
|
gesvd(Jobu,Jobvt,A,s,U,VT) |
same as gesvd('O',Jobu,Jobvt,A,s,U,VT) ;
returns ierr
|
gesvd(A,s,U,VT) |
same as gesvd('O','S','S',A,s,U,VT) ;
returns ierr
|
gesvd(A,s) |
same as gesvd('O','N','N',A,s,U,VT) ;
returns ierr [1]
|
gesvd_work(Lw,Jobu,Jobvt,A) |
returns optimal or minimum size of the vector w
|
gesvd_rwork(A) |
returns minimum size of the vector rw
|
[1] U
and VT
are not referenced.
gesdd()
solves the same as the simple driver.
It is much faster than the simple driver for large matrices, but uses
more workspace.
Defined in boost/numeric/bindings/lapack/gesdd.hpp
.
Namespace is boost::numeric::bindings::lapack
.
In the following table A
, U
, VT
(denoting VT
or VH
)
are matrices; s
is a vector representing matrix
S
; w
, rw
, iw
,
are `work' vectors (elements of w
can be real or complex,
elements of rw
are real, elements of rw
are
int
s).
Jobz
specifies options for computing U
and VT
:
'N'
-- no left or right singular vectors are computed;
'S'
-- left singular vectors are returned in
the first min(m,n) columns of U
and right singular vectors are returned in
the first min(m,n) rows of VT
;
'A'
-- complete matrices U
and
VT
are computed;
'O'
-- if m>=
n,
left singular vectors are overwritten on
the first min(m,n) columns of A
and
complete VT
is computed; otherwise, right singular
vectors are overwritten on the first min(m,n) rows
of A
and complete U
is computed.
Lw
can be 'O'
or 'M'
,
specifying whether optimal or minimum size of the `work' vector
is to be used or calculated; 'O'
can be used with LAPACK
version 3.0 only.
Finally, ierr
is LAPACK's `diagnostic argument' INFO
.
Expression | Semantics |
---|---|
gesdd(Jobz,A,s,U,VT,w,iw) |
SVD of real A ;
returns ierr
|
gesdd(Jobz,A,s,U,VT,w,rw,iw) |
SVD of complex A ;
returns ierr
|
gesdd(Lw,Jobz,A,s,U,VT) |
SVD of real or complex A , with `internal' work space;
returns ierr
|
gesdd(Jobz,A,s,U,VT) |
same as gesdd('O',Jobz,A,s,U,VT) ;
returns ierr
|
gesdd(A,s,U,VT) |
same as gesdd('O','S',A,s,U,VT) ;
returns ierr
|
gesdd(A,s) |
same as gesdd('O','N',A,s,U,VT) ;
returns ierr [1]
|
gesdd_work(Lw,Jobz,A) |
returns optimal or minimum size of the vector w
|
gesdd_rwork(Jobz,A) |
returns minimum size of the vector rw
|
gesdd_iwork(A) |
returns minimum size of the vector iw
|
[1] U
and VT
are not referenced.
getrs
to provide guidelines for user's additions and extensions.
Implementation will be described in two stages:
1. There are four versions of almost all LAPACK routines for matrices with single and double precision real and complex elements. Type of the matrix elements is encoded as the first letter of the routine's name:
s
-- single precision real (REAL
),
which (usually) corresponds to float
in C/C++;
d
-- double precision real (DOUBLE PRECISION
),
which corresponds to double
in C/C++;
c
-- single precision complex (COMPLEX
);
unfortunately, it can't be said that corresponding type in C++ is
std::complex<float>
,[1]
although we don't know of any implementation where it is not the case;
z
-- double precision complex (COMPLEX*16
);
regarding std::complex<double>
see above.
sgetrs
, dgetrs
,
cgetrs
and zgetrs
.
There are several conventions for calling Fortran from C/C++:
some compilers require trailing underscore in function names,
some don't, etc.
So, the first step is to define `portable' function names
in lapack_names.h
using the macro
FORTRAN_ID
(defined in traits/fortran.h
):
#define LAPACK_SGETRS FORTRAN_ID( sgetrs ) #define LAPACK_DGETRS FORTRAN_ID( dgetrs ) #define LAPACK_CGETRS FORTRAN_ID( cgetrs ) #define LAPACK_ZGETRS FORTRAN_ID( zgetrs )
Next step is to declare interfaces of LAPACK routines in
lapack.h
. Only dgetrs
and
zgetrs
are shown below; sgetrs
and
cgetrs
differ only in the type of array parameters:
void LAPACK_DGETRS (char const* trans, int const* n, int const* nrhs, double const* a, int const* lda, int const* ipiv, double* b, int const* ldb, int* info); void LAPACK_ZGETRS (char const* trans, int const* n, int const* nrhs, dcomplex_t const* a, int const* lda, int const* ipiv, dcomplex_t* b, int const* ldb, int* info);All parameters, including scalars like
n
and
nrhs
, are defined as pointers; input parameters,
i.e. those which are not modified inside the routine, are pointers to
const
.
Functions have C linkage (extern "C" { ... }
)
and are in the global namespace.
Using function overloading, we can remove array parameters type from the function name:
void getrs (char const trans, int const n, int const nrhs, double const* a, int const lda, int const* ipiv, double* b, int const ldb, int* info) { LAPACK_DGETRS (&trans, &n, &nrhs, a, &lda, ipiv, b, &ldb, info); } void getrs (char const trans, int const n, int const nrhs, traits::complex_d const* a, int const lda, int const* ipiv, traits::complex_d* b, int const ldb, int* info) { LAPACK_ZGETRS (&trans, &n, &nrhs, traits::complex_ptr (a), &lda, ipiv, traits::complex_ptr (b), &ldb, info); }(and there are two more functions which call
sgetrs
and cgetrs
).
Now we are closer to C/C++ calling convention: array parameters are
pointers and scalars are passed by value.
As these overloads are not intended for direct use, they are in the
subnamespace detail
of boost::numeric::bindings::lapack
.
Finally, we can define higher level, generic C++ interface.
Higher level interfaces (bindings) are written in terms of
traits classes which are
the interface between LAPACK routines and
vector and matrix classes. Namely, the idea is to make bindings independent of the concrete vector/matrix libraries as much as possible.
LAPACK routines usually require the starting address of the matrix,
number of rows and columns and the so-called leading dimension.
So, matrix_traits<>
class and its specializations for
various matrix classes provide these functions and some typedef
s.
Note that bindings don't know and need not know anything
about traits specializations --
e.g. boost/numeric/bindings/traits/ublas_matrix.hpp
must be included in your program (if it uses
ublas::matrix<>
), but not in bindings headers, which
include only boost/numeric/bindings/traits/matrix_traits.hpp
.
To simplify the use of traits classes, some free accessor functions were introduced, so instead of writing e.g.
traits::matrix_traits<matrix_type const>::size1 (m)you can write just
traits::matrix_size1 (m)
As matrix objects (usually) know about their sizes, we can reduce the number parameters from nine to four[2] (and a return value):
template <typename MatrA, typename MatrB, typename IVec> int getrs (char const trans, MatrA const& a, IVec const& ipiv, MatrB& b)
The heart of this generic function is the call of the one of the functions (depending on the type of array pointers) from the overloaded set:
int info; detail::getrs (trans, traits::matrix_size1 (a), traits::matrix_size2 (b), traits::matrix_storage (a), traits::leading_dimension (a), traits::vector_storage (ipiv), traits::matrix_storage (b), traits::leading_dimension (b), &info);using accessor function which through matrix and vector traits classes extract appropriate data (storage addresses and sizes) from matrix and vector objects
a
, b
and ipiv
. Function returns info
.
Before the call we made some compile-time (matrix structure) and run-time (matching sizes) checks.
Overloaded set and the generic function are defined in gesv.hpp
.
In short, addition of a new binding is done in four steps:
FORTRAN_ID
, define names to be used to refer to LAPACK subroutines in C/C++ code;
Although not shown (and not needed) in the example, some type names must be known in certain cases. They can be obtained through traits classes, e.g.:
typedef typename traits::matrix_traits<MatrA>::value_type val_t; typedef typename traits::matrix_traits<MatrA>::pointer ptr_t; typedef typename traits::matrix_traits<MatrA>::matrix_structure mstruct_t;
2.
On compilers which do not support partial template specialisation,
traits classes cannot be used. Accessor functions are then
(i.e. when macro BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
is defined)
simple set of overloaded functions (defined in
traits/vector_raw.hpp
and traits/matrix_raw.hpp
).
Unfortunately, some of these compilers cannot distinguish functions
template <typename T, typename F, typename A> typename ublas::matrix<T,F,A>::const_pointer matrix_storage (ublas::matrix<T,F,A> const& m);and
template <typename T, typename F, typename A> typename ublas::matrix<T,F,A>::pointer matrix_storage (ublas::matrix<T,F,A>& m);(
boost
macro BOOST_NO_FUNCTION_TEMPLATE_ORDERING
covers this case).
Therefore we introduced additional function
template <typename T, typename F, typename A> typename ublas::matrix<T,F,A>::const_pointer matrix_storage_const (ublas::matrix<T,F,A> const& m);and the call in the generic
getrs()
is now :o(
detail::getrs (trans, traits::matrix_size1 (a), traits::matrix_size2 (b), #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING traits::matrix_storage (a), #else traits::matrix_storage_const (a), #endif traits::leading_dimension (a), #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING traits::vector_storage (ipiv), #else traits::vector_storage_const (ipiv), #endif traits::matrix_storage (b), traits::leading_dimension (b), &info);
If some type name is needed, workaround is e.g.:
template <typename MatrA> void func (M const&l m) { // ... #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS typedef typename traits::matrix_traits<MatrA>::value_type val_t; #else typedef typename MatrA::value_type val_t; #endif // ... }Prerequisite is, of course, that
MatrA
has value_type
defined.
[1] These are thorny issues; see C++ Standards Committee Papers:
G. Dos Reis: Enhancing Numerical Support
R. W. Grosse-Kunstleve and D. Abrahams: Predictable Data Layout for Certain Non-Pod Types
[2]
First parameter of getrs
, char const trans
,
specifies the form of the system of equations: AX = B
,
ATX = B
or AHX = B
.
As the form AX = B
is the most common, LAPACK Bindings Library
also provides version with three parameters:
templateint getrs (MatrA const& a, IVec const& ipiv, MatrB& b) { char const no_transpose = 'N'; return getrs (no_transpose, a, ipiv, b); }