如何阅读 C++代码或:没有文档该怎么办?
这个问题可能听起来有点奇怪:我想使用 Boost 的 ublas 和 ATLAS/Lapack 进行数值矩阵计算。我正在使用 Boost 数字绑定 来连接这两个库。但是,要么我找不到它,要么没有关于如何使用这些绑定的适当文档。另外,我是 Boost(实际上是 C++)的新手,所以我很难找到如何在我的代码中使用 Lapack 提供的函数。
我最终要解决的问题是找到对称带状矩阵的特征值和向量。据我了解,我将使用 lapack::steqr 来实现此目的。问题是,我不知道如何正确调用该函数。在数字绑定的代码中,我可以看到类似这样的内容:
template <typename D, typename E, typename Z, typename W>
inline
int steqr( char compz, D& d, E& e, Z& z, W& work ) {
int const n = traits::vector_size (d);
assert( traits::vector_size (e) == n-1 );
assert( traits::matrix_size1 (z) == n );
assert( traits::matrix_size2 (z) == n );
assert( compz=='N' || compz=='V' || compz=='I' );
...
现在,我该如何处理?我尝试了 steqr
和 double 数组,但不起作用。然后,为了找出要使用的正确参数,我选择了其中一个断言,并尝试找到任何适用于 traits::matrix_size1(...)
的内容 - 即使我无法找到编译,既不使用双数组也不使用 ublas::matrix 。
所以我的问题是,一般来说:当我找到这样一个没有完整文档的库时,我如何找到如何调用函数?我主要来自 C,对所有这些模板感到非常困惑。真的是追踪代码中所有内容的唯一方法吗?还是有什么小技巧?或者我可以从错误消息中获取信息吗?
这种错误消息的一个例子是,对于以下代码:
ublas::matrix<double> empty(N,N);
std::cout << traits::matrix_size1<ublas::matrix>(empty) << std::endl;
然后我在编译过程中得到:
eigenvalues.cpp:40:85: error: no matching function for call to ‘matrix_size1(boost::numeric::ublas::matrix<double, boost::numeric::ublas::basic_row_major<>, boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >&)’
eigenvalues.cpp:40:85: note: candidate is:
/usr/include/boost/numeric/bindings/traits/matrix_traits.hpp:148:18: note: template<class M> std::ptrdiff_t boost::numeric::bindings::traits::matrix_size1(M&)
候选者列在那里可能很有用,但我只是不知道如何阅读这一行并相应地调整我的代码。
再说一次:这个问题有点笼统,关于如何处理这样的事情。我知道类和模板的基本概念,但这对于我的知识来说有点太抽象了。
The question might sound a bit weird: I want to do numeric matrix calculations using Boost's ublas and ATLAS/Lapack. I am using the Boost numeric bindings to interface between those two libraries. However, either I just cannot find it or there is no proper documentation on how to use these bindings. Also, I am new to Boost (and actually C++ in general) so I have a hard time finding out how I can use functions provided by Lapack in my code.
The problem I want to solve in the end, is finding the Eigenvalues and -vectors of a symmetric banded matrix. As far as I understood it, I would be using lapack::steqr
for this. The thing is, I don't know, how to properly call the function. In the code of the numeric bindings, I can see something like this:
template <typename D, typename E, typename Z, typename W>
inline
int steqr( char compz, D& d, E& e, Z& z, W& work ) {
int const n = traits::vector_size (d);
assert( traits::vector_size (e) == n-1 );
assert( traits::matrix_size1 (z) == n );
assert( traits::matrix_size2 (z) == n );
assert( compz=='N' || compz=='V' || compz=='I' );
...
Now, how do I handle that? I tried steqr<double, double, double, double>(...)
and double arrays, which didn't work. Then, to find out the proper arguments to use, I picked one of the asserts and tried to find anything that works with traits::matrix_size1(...)
- Even that I couldn't get to compile, neither with a double array nor with a ublas::matrix
.
So my question is, in general: When I find such a library without complete documentation, how do I find out how to call functions? I am coming from C mainly and am extremely confused with all these templates. Is the only way really to track down everything in the code? Or are there little tricks? Or can I probably draw information from the error messages?
One example of such an error message is, for the following code:
ublas::matrix<double> empty(N,N);
std::cout << traits::matrix_size1<ublas::matrix>(empty) << std::endl;
Then I get during compilation:
eigenvalues.cpp:40:85: error: no matching function for call to ‘matrix_size1(boost::numeric::ublas::matrix<double, boost::numeric::ublas::basic_row_major<>, boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >&)’
eigenvalues.cpp:40:85: note: candidate is:
/usr/include/boost/numeric/bindings/traits/matrix_traits.hpp:148:18: note: template<class M> std::ptrdiff_t boost::numeric::bindings::traits::matrix_size1(M&)
It is probably useful, that the candidate is listed there, but I just don't know, how to read this line and adjust my code accordingly.
Again: This question is a bit more general, on how to deal with stuff like this. I know the basic concept of classes and templates, but this is just a bit too abstract for my knowledge.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于我不太精通模板化 C++,我个人发现使用 cblas 接口要容易得多,它只是原始 Fortran 代码的一个薄包装。
在这种方法中,您必须为矩阵创建自己的类,这与 Fortran 对矩阵的理解兼容。最简单的方法可能是继承
std::vector
或std::valarray
并提供您自己的索引操作。是的,这需要一点工作。但它并不像听起来那么糟糕:-)。
顺便说一下,请注意不要将单精度例程 (
ssteqr
) 与双精度参数一起使用。 LAPACK 不会报告任何错误,但结果将是完全错误的。Since I am not too proficient in templated c++, I personally find it much easier to use the
cblas
interface which is only a thin wrapper over the original Fortran code.In this approach, you'll have to make your own class for matrices, which would be compatible to the Fortran understanding of what a matrix is. The easiest way is probably to inherit from
std::vector
orstd::valarray
and provide your own indexing operation.Yes, it's a bit of work. But it's not as bad as it sounds :-).
And by the way, beware of using the single-precision routines (
ssteqr
) with double precision arguments. LAPACK will not report any error, but the result is going to be plain wrong.