How to read C++ code or: What to do without documentation? - c++

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.

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.

Related

Is there a way to force a template argument within a certain range?

Forgive me, as I've tried searching and maybe I'm just using the wrong keywords. I'm almost positive there is a way where I can bound an integer template argument to a positive value. I just know from bitter experience that it's probably not intuitive at all.
Just so you know, STL widgets for doing this (if there are such animals) are pretty much off the table because as much as I love the STL I can't use the STL for the code I'm targeting outside minor stuff like definitions because a lot of the platforms I'm targeting with this code don't have it available. (32kb machines and such)
basically what I want is this
template<const size_t TCapacity /* bounded to a minimum of one */ > class Buffer {
...
};
Where a compile error is thrown if TCapacity is zero such that
Buffer<0> buffer; // won't compile
I mean, not only do i think i have encountered this sort of sorcery before, I've seen things like the Spirit framework do much more complicated things so I'm pretty sure there's an answer. I just doubt it's obvious.
Thanks in advance!
In C++11, you could just use a static_assert inside the class:
template<std::size_t TCapacity> class Buffer
{
static_assert(TCapacity > 0, "The size must be greater than zero");
// ...
};
If the expression is true, this declaration has no effect. Otherwise a compile-time error is issued, and the text is included in the diagnostic message.
template<std::size_t cap> requires(cap >= 1) class Buffer;
I doubt it can be very reliably doable in C++11. Of course, you can use some pre-concepts SFINAE, like
template<std::size_t cap, class = std::enable_if_t<(cap > 0)>> class Buffer;
or even something more contrived, like
template<std::size_t cap> class Buffer
: private std::enable_if_t<(cap > 0)
, std::integral_constant<std::size_t, cap>>> {};
but they can be overcome quite easily with things like
template<> class Buffer<0> {};

C++: Using boost to calculate simple definite integrals

Anyone know how to use Boost to solve simple definite integrals?
E.g. -x^2 + 1 from -1 to 1?
I have tried reading the boost documentation, but I can't seem to figure out how to properly pass the function.
Thanks
Edit: My attempt so far
using namespace boost::math;
typename function_type; // this is probably wrong
function_type f // and this
{
return -x*x+1;
};
int main(int, char**)
{
const double val =
integral(0.0,
1,
0.001,
f); // my question is, what do I put in here? How do I format f.
}
The first thing to observe is that the Boost library you've shown doesn't actually have a function to calculate integrals. That might have set you on the wrong track.
The library is used for multi-precision floating point operations, and one of the examples happens to be a simple approximation of integrals, per Riemann. The point of the example is that Riemann integrals are so simple that you can use them to demonstrate a fancy library.
In your case, you wouldn't even need to bother with passing a function. You can just write out the Riemann method substituting -x^2 + 1 directly.
That said, the typical C++ way to pass it as an argument would be [](double x) { return -x*x+1.0;}. That's an unnamed function or lambda. It doesn't need a name of its own, since the parameter already has a name.

Why can't I assign matrix_exp from dlib to std::vector? [duplicate]

This question already has answers here:
how to convert a matrix in dlib to a std::vector
(2 answers)
Closed 5 years ago.
I am using Dlib thanks to its great matrix sub module. I find it very complete and useful to do fast scientific algorithm. I managed to add some custom operations and get the overall idea how it works.
However, there is a question that bother me since quite some time. Is there specific reason why it seems impossible to assign any kind of matrix expression to an std::vector ?
EDIT:
Here is a typical dlib function:
template <typename EXP>
const matrix_op<op_trans<EXP> > trans(const matrix_exp<EXP>& m) {
typedef op_trans<EXP> op;
return matrix_op<op>(op(m.ref());
}
And if I want to implement the corresponding function that takes and returns std::vector instead, I think I would do:
template <typename EXP>
const std::vector<matrix_op<op_trans<EXP> > > trans(const std::vector<matrix_exp<EXP> >& ms) {
std::vector<matrix_op<op_trans<EXP> > > out(ms.size());
typedef op_resize_bilinear<EXP> op;
for (int i = 0; i < ms.size(); ++i)
out[i] = matrix_op<op>(op(ms.ref()));
return out;
}
But as it works, any expression is seen as matrix_exp being matrix, matrix_op, matrix_add_exp... But this is not true with std::vector<matrix_exp>:
‘const std::vector<smu::matrix<float> >’ is not derived from ‘const std::vector<smu::matrix_exp<EXP> >’
I just want to know if this is intentional from dlib, if there are any reason for it as it could be useful in several algorithms that need to process several matrices at once... and if some work around this could work
(Disclaimer: First time I am looking at dlib, I'm taking a shot in the dark here and have no idea how dlib / its matrix class actually work.)
A dlib::matrix has member functions including begin() and end(), which will...
...iterate over the elements of the matrix in row major order if layout is row_major_layout or in column major order if layout is column_major_layout.
Assigning to a std::vector can thus be done pretty straightforward:
dlib::matrix< ... > mat;
// fill the matrix, do operations on it etc.
std::vector< mat::type > vec( mat.begin(), mat.end() );
Whether that is what you are looking for, I don't know, because you did not really tell us. ;-)

How to minimize C++ function using boost?

so I have a function like
int f(int i, int j, int c, double d) {
/*...any operations with i, j, c, d affect on some return int we have*/
}
Is there any thing in boost or STD that would take my function and find the input arguments that minimize my function output?
I assume you're trying to do a "simple" mathematical multi-dimensional minimization.
GSL has some functions to help you with this. I wouldn't look any further ;)
I understand you to be looking for code to perform mathematical optimization.
Boost does not have anything to do this as far as I know, and neither does the standard library; however, NLopt may be what you're looking for.
You can use Brent's algorithm to minimise simple functions.
http://www.boost.org/doc/libs/1_65_0/libs/math/doc/html/math_toolkit/roots/brent_minima.html

C++ domain specific embedded language operators

In numerical oriented languages (Matlab, Fortran) range operator and semantics is very handy when working with multidimensional data.
For example:
A(i:j,k,:n) // represents two-dimensional slice B(i:j,0:n) of A at index k
unfortunately C++ does not have range operator (:). of course it can be emulated using range/slice functor, but semantics is less clean than Matlab. I am prototyping matrix/tensor domain language in C++ and am wondering if there any options to reproduce range operator.
I still would like to rely on C++/prprocessor framework exclusively.
So far I have looked through boost wave which might be an suitable option.
is there any other means to introduce new non-native operators to C++ DSL?
I know you cannot add new operators.am specifically looking for workaround.
One thing I came up (very ugly hack and I do not intend to use):
#define A(r) A[range(((1)?r), ((0)?r))] // assume A overloads []
A(i:j); // abuse ternary operator
A solution that I've used before is to write an external preprocessor that parses the source and replaces any uses of your custom operator with vanilla C++. For your purposes, a : b uses would be replaced with something like a.operator_range_(b), and operator:() declarations with declarations of range_ operator_range_(). In your makefile you then add a rule that preprocesses source files before compiling them. This can be done with relative ease in Perl.
However, having worked with a similar solution in the past, I do not recommend it. It has the potential to create maintainability and portability issues if you do not remain vigilant of how source is processed and generated.
No -- you can't define your own operators in C++. Bjarne Stroustrup details why..
As Billy said, you cannot overload operators. However, you can come very close yo what you want with "regular" operator overloading (and maybe some template metaprogramming). It would be quite easy to allow for something like this:
#include <iostream>
class FakeNumber {
int n;
public:
FakeNumber(int nn) : n(nn) {}
operator int() const { return n; }
};
class Range {
int f, t;
public:
Range(const int& ff, const int& tt) : f(ff), t(tt) {};
int from() const { return f; }
int to() const { return t; }
};
Range operator-(const FakeNumber& a, const int b) {
return Range(a,b);
}
class Matrix {
public:
void operator()(const Range& a, const Range& b) {
std::cout << "(" << a.from() << ":" << a.to() << "," << b.from() << ":" << b.to() << ")" << std::endl;
}
};
int main() {
FakeNumber a=1,b=2,c=3,d=4;
Matrix m;
m(a-b,c-d);
return 0;
}
The downside is that This solution doesn't support all-literal expressions. Either from or to have to be user-defined classes, since we can't overload operator- for two primitive types.
You can also overload operator* to allow specifying stepping, like so:
m(a-b*3,c-d); // equivalent to m[a:b:3,c:d]
And overload both versions of operator-- to allow ignoring one of the bounds:
m(a--,--d); // equivalent to m[a:,:d]
Another option is to define two objects, named something like Matrix::start and Matrix::end, or whatever you like, and then instead of using operator--, you could use them, and then the other bound wouldn't have to be a variable and could be a literal:
m(start-15,38-end); // This clutters the syntax however
And you could of course use both ways.
I think it's pretty much the best you can get without resorting to bizarre solutions, such as custom prebuild tools or macro abuse (of the sort Matthieu presented and suggested against using them:)).
An alternative is to build a C++ variant dialect using a program transformation tool.
The DMS Software Reengineering Toolkit is a program transformation engine, with an industrial strength C++ Front End. DMS, using this front end, can parse full C++ (it even has a preprocessor and can retain most preprocessor directives unexpanded), automatically build ASTs and complete symbol tables.
The C++ front end comes in source, using a grammar derived directly from the standard. It is technically straightforward to add new grammar rules including those that would allow ":" syntax as array subscripts as you have described, and as Fortran90+ has implemented. One can then use the program transformation capability of DMS to transform the "new" syntax into "vanilla" C++ for use in conventional C++ compilers. (This scheme is a generalization of the Intentional Programming model of "add DSL concepts to your language").
We in fact did a concept demonstration of "Vector C++" using this approach.
We added a multidimensional Vector datatype, whose storage semantics are only that array elements are distinct. This is different than C++'s model of sequential locations, but you need this different semantic if you want the compiler/transformer to have freedom to lay out memory arbitrarily, and this is fundamental if you want to use SIMD machine instructions and/or efficient cache accesses along different axes.
We added Fortran-90 style scalar and subarray range accesses, added virtually all of F90's array-processing operations, added a good fraction of APL's matrix operations, all by adjusting the DMS C++ grammar.
Finally, we built two translators using DMS transformational capability: one mapping a significant part of this (remember, this was a concept demo) to vanilla C++ so you could compile and run Vector C++ applications on a typical workstation, and the other mapping C++ to a PowerPC C++ dialect with SIMD instruction extensions, and we generated SIMD code that was pretty reasonable we thought. Took us about 6 man-months to do all this.
The customer for this ultimately bailed out (his business model didn't include supporting a custom compiler in spite of his severe need for parallel/SIMD based operations), and it has been languishing on the shelf. We've chosen not to pursue this in the broader market because it isn't clear what the market really is. I'm pretty sure there are organizations for which this would be valuable.
Point is, you really can do this. It is almost impossible using ad hoc methods. It is technically quite straightforward with a strong enough program transformation system. It isn't a walk in the park.
The easiest solution is to use a method on matrix instead of an operator.
A.range(i, j, k, n);
Note that typically you do not use , in a subscript operator [], eg A[i][j] instead of A[i,j]. The second form could be possible by overloading the comma operator but then you force i and j to be objects not numbers.
You could define a range class that could be used as a subscript for your matrix class.
class RealMatrix
{
public:
MatrixRowRangeProxy operator[] (int i) {
return operator[](range(i, 1));
}
MatrixRowRangeProxy operator[] (range r);
// ...
RealMatrix(const MatrixRangeProxy proxy);
};
// A generic view on a matrix
class MatrixProxy
{
protected:
RealMatrix * matrix;
};
// A view on a matrix of a range of rows
class MatrixRowRangeProxy : public MatrixProxy
{
public:
MatrixColRangeProxy operator[] (int i) {
return operator[](range(i, 1));
}
MatrixColRangeProxy operator[] (const range & r);
// ...
};
// A view on a matrix of a range of columns
class MatrixColRangeProxy : public MatrixProxy
{
public:
MatrixRangeProxy operator[] (int i) {
return operator[](range(i, 1));
}
MatrixRangeProxy operator[] (const range & r);
// ...
};
Then you can copy a range from one matrix into another.
RealMatrix A = ...
RealMatrix B = A[range(i,j)][range(k,n)];
Finally by creating a Matrix class that can hold either a RealMatrix or a MatrixProxy you can make a RealMatrix and a MatrixProxy appear the same from the outside.
Note the operator[] on the proxies are not and cannot be virtual.
If you want to have fun, you may check out IdOp.
If you are really working on a project, I don't suggest using this trick though. Maintenance will suffer from clever tricks.
Your best bet is thus to bite the bullet and use explicit notation. A short function called range which yields a custom defined object for which the operators are overloaded seems especially suitable.
Matrix<10,30,50> matrix = /**/;
MatrixView<5,6,7> view = matrix[range(0,5)][range(0,6)][range(0,7)];
Matrix<5,6,7> n = view;
Note that the operator[] only has 4 overloads (const/non-const + basic int / range) and yields a proxy object (until the last dimension). Once applied to the last dimension, it gives a view of the matrix. A normal matrix may be built from a view that has the same dimensions (non-explicit constructor).