如何阅读 C++代码或:没有文档该怎么办?

发布于 2024-12-20 10:22:43 字数 1926 浏览 3 评论 0原文

这个问题可能听起来有点奇怪:我想使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱花坊 2024-12-27 10:22:43

由于我不太精通模板化 C++,我个人发现使用 cblas 接口要容易得多,它只是原始 Fortran 代码的一个薄包装。

在这种方法中,您必须为矩阵创建自己的类,这与 Fortran 对矩阵的理解兼容。最简单的方法可能是继承 std::vectorstd::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 or std::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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文