C++ Eigen: recursive functions accepting any matrix class - c++

I want to have a recursive function
template <typename Derived>
void f(Eigen::MatrixBase<Derived>& m)
{
size_t blockRows = ...
size_t blockCols = ...
....
f(m.block(0, 0, blockRows, blockCols));
}
This unfortunately results in an infinite compile time recursion.
The first call would be to
f<Eigen::MatrixBase<Derived> >
The second would be to
f<Eigen::Block<Eigen::MatrixBase<Derived>, ... > >
The third call would be to
f<Eigen::Block<Eigen::Block<Eigen::MatrixBase<Derived>, ... >, ... > >
Every time a block of block is requested.
What is the best practice to implement recursive functions in Eigen, which still work on any Eigen matrix type?
I think, I should use some type, that still wraps the same piece of memory, but is not an expression template and it is evaluated.

You can cast your recursive block to an Eigen::Ref to avoid the infinite type instantiation:
Ref<MatrixXd> bl = m.block(0, 0, blockRows, blockCols);
f(bl);
To stay fully generic, you can replace MatrixXd by typename Derived::PlainObject.

Related

Compile-Time Creation of Array of Templated Objects in High Level Synthesis

I'm trying to accomplish this with HLS, not with "normal" C++, so most libraries (STL, boost, etc.) won't work as they can't be synthesized (manual memory management is not allowed). I think this should be possible with template metaprogramming, but I'm a little stuck.
I want to create an array of shift registers, each with a variable depth. I have N inputs, and I want to create N shift registers, with depths 1 to N, where N is known at compile time. My shift register class basically looks like
template<int DEPTH>
class shift_register{
int registers[DEPTH];
...
};
I tried following this and adapting it: Programmatically create static arrays at compile time in C++ , however, the issue is with the last line. Each templated shift register is going to be a different type, and so can't be put together in an array. But I do need an array, as there wouldn't be a way to access each shift register.
Any help would be appreciated!
Just to clarify, my problem was the following: generate N shift_registers, templated from 1 to N, where N is a compile time constant.
For example, if I had N=4, I could easily write this as:
shift_register<1> sr1;
shift_register<2> sr2;
shift_register<3> sr3;
shift_register<4> sr4;
But this wouldn't be easy to change, if I wanted a different value for N in the future.
I ended up using the preprocessor and took the solution from here: How do I write a recursive for-loop "repeat" macro to generate C code with the CPP preprocessor?
I used the macros from that solution like this:
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define BODY(i) shift_register<i> CAT(sr,i)
REPEAT_ADD_ONE(BODY, N, 1);
And then something similar to that in order to access the shift registers, in a sort of array fashion.
This let me achieve the compile time generation that I was looking for, and get the array type access I needed.
Your question was somewhat difficult to understand but I'll do my best...
template <typename ... Args>
constexpr auto make_array(Args && ... pArgs)
{
using type = std::common_type_t<std::decay_t<Args>...>;
return std::array<type, sizeof...(Args)>{ (type)pArgs ... };
}
Then use it like this:
auto constexpr var_array_of_arrays = std::make_tuple
(
make_array(1, 2, 3, 3),
make_array(2, 3, 4),
make_array(1, 2, 3 ,4 ,3, 5)
);
To get the M'th element you access it like this, n has to actually be a compile-time constant:
std::get<M>(var_array_of_arrays);
To access the Nth element in the Mth array:
auto constexpr value = std::get<M>(var_array_of_arrays)[N]
An to improve the interface:
template <size_t M, size_t N, typename T >
constexpr decltype(auto) get_element(T && pInput)
{
return std::get<M>(std::forward<T>(pInput))[N];
}
Used like this:
auto constexpr element0_1 = get_element<0, 1>(var_array_of_arrays);
This will allow you to use an array of variable length arrays, or atleast something that behaves like that and is identical to that in memory.
A full example is here:
Online compiler
Whenever I hear "compile time number sequence" I think std::index_sequence
namespace detail {
template <typename>
struct shift_registers;
template <std::size_t ... Is> // 0, 1, ... N-1
struct shift_registers<std::index_sequence<Is...> > {
using type = std::tuple<shift_register<Is + 1>...>;
};
template <typename T>
using shift_registers_t = typename shift_registers<T>::type
}
template <std::size_t N>
using shift_registers = detail::shift_registers_t<std::make_index_sequence<N>>;

Trying to sum two compile time tuple integer sequences

If you're keeping track of my question history, I'm updating a dimensional analysis library for the sake of ditching a nightmare of macros and learning C++11, variadic templates, and meta programming and functional programming paradigms. For the life of me, this stuff is still magic.
Anyway, I have tuples of exponent constants that define physical units.
template<int... I>
using make_dimension = std::tuple<std::ratio<I>...>;
using scalar_dimension = make_dimension<0, 0, 0, 0, 0, 0, 0>;
using length_dimension = make_dimension<1, 0, 0, 0, 0, 0, 0>;
using time_dimension = make_dimension<0, 0, 1, 0, 0, 0, 0>;
This is (part) of a library that models the SI units. You can only multiply unlike units, you can additionally add like units and scalars. These libraries are dandy in that they cause compile time errors if you mix units inappropriately. There are >400 units and most of them are defined in terms of other units. When multiplying units, exponents are added, and when dividing units, exponents are subtracted. So to define velocity, I would love a means of expressing:
using velocity_dimension = divide_dimensions<length_dimension, time_dimension>;
And that should be functionally equivalent to writing:
using velocity_dimension = make_dimension<1, 0, -1, 0, 0, 0, 0>;
I've been Googling, but I just don't know the terminology to land some hits. The closest I've found was a for_each that applies a function to elements of a tuple at runtime... And it's kind of blowing my mind, so I can't quite figure out how to turn it into a compile time iteration over the elements. 'make_dimension' above was explained to me a moment ago and it blew my mind, but I recovered. I'm kind of bugged asking for a handout, so does anyone have any good resources for learning this stuff? I'm having a hard time believing I'm the only one remotely interested in doing this.
#dyp's solution in the comments uses a recursively instantiated template. While that's one of the most general techniques for variadic templates, in this case recursion is probably overkill, as the entire set of transformations can be performed in a single pack expansion that expands two parameter packs simultaneously:
template<template<class, class> class, class, class>
struct tuple_transform; // undefined
template<template<class, class> class Transform, class...Ts, class...Vs>
struct tuple_transform<Transform, std::tuple<Ts...>, std::tuple<Vs...>> {
using type = std::tuple<Transform<Ts, Vs>...>;
};
template<class T, class U>
using divide_dimensions = typename tuple_transform<std::ratio_subtract, T, U>::type;
Note that the above assumes that Transform<T, U> is an alias for the desired resulting type. This matches the behavior of ratio_add etc. - they are alias templates for the resulting std::ratio, so typename ratio_add<...>::type is not necessary.
Demo.
While T.C.s answer is correct you can simply take std::integer_sequence (which is C++ 14 but can be simply implemented) instead of ratio and tuple which (in my opinion) don't really fit und use a constexpr functor for manipulation.
Now your code should look like the following (which I didn't try to compile):
template<int... I>
using make_dimension = std::integer_sequence<int, I...>;
template<class Functor, class Dim1, class Dim2>
struct transfrom;
template<class Functor, int... Dims1, int... Dims2>
struct transform<
Functor,
std::integer_sequence<int, Dims1...>,
std::integer_sequence<int, Dims2...>
> {
static_assert(sizeof...(Dims1)==sizeof...(Dims2), "wrong dimensions");
static constexpr Functor f;
using type=std::integer_sequence<int, f(Dims1,Dims2)...>;
};
struct add {
constexpr int operator()(int l, int r) const { return l+r; }
};
struct sub {
constexpr int operator()(int l, int r) const { return l-r; }
};
template<class T, class U>
using divide_dimensions = typename transform<sub, T, U>::type;
I don't have enough info, but it looks like (1,0,-2,0,0,0,0) would be what you would need for acceleration. The 1 represents meters and the - 2 would represent division by seconds squared just as a negative exponent does in math.

Generating permutations via templates

I'd like a function, or function object, that can generate a permutation of its inputs with the permutation specified at compile time. To be clear, I am not looking to generate all of the permutations, only a specific one. For instance, permute<1,4,3,2>( a, b, c, d ) would return (a,d,c,b). Obviously, it is straightforward to do this with a permutation of a specific length, e.g. 2, like this
#include <boost/tuple.hpp>
template< unsigned a, unsigned b>
struct permute {
template< class T >
boost::tuple< T, T > operator()( T ta, T tb ) {
boost::tuple< T, T > init = boost::make_tuple( ta, tb );
return boost::make_tuple( init.get< a >(), init.get< b >() );
}
};
But, how would I go about doing this for an arbitrary length permuation? Also, is there a cleaner way of writing the above code? Yes, the above code is not restricted to making permutations as permute<2,2>(a,b) is allowed, but I don't see that as a flaw. However, can it be restricted to only allowing actual permutations?
C++0x provides variadic templates, which you should be able to use to handle an arbitrary length permutation. They were added specifically because the current version of C++ doesn't have a clean way of dealing with this kind of problem.

C++ Template Class Constructor with Variable Arguments

Is it possible to create a template function that takes a variable number of arguments, for example, in this Vector< T, C > class constructor:
template < typename T, uint C >
Vector< T, C >::Vector( T, ... )
{
va_list arg_list;
va_start( arg_list, C );
for( uint i = 0; i < C; i++ ) {
m_data[ i ] = va_arg( arg_list, T );
}
va_end( arg_list );
}
This almost works, but if someone calls Vector< double, 3 >( 1, 1, 1 ), only the first argument has the correct value. I suspect that the first parameter is correct because it is cast to a double during the function call, and that the others are interpreted as ints and then the bits are stuffed into a double. Calling Vector< double, 3 >( 1.0, 1.0, 1.0 ) gives the desired results. Is there a preferred way to do something like this?
Alas, right now there's no good way to do this. Most of the Boost packages that need to do something similar use macro tricks to define things like this:
template < typename T >
Vector< T >::Vector( T )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1 )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1, C c2 )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1, C c2, C c3 )
{ ... }
The macros generate some set number (typically around 10) versions, and provide a mechanism to change the max number of parameters before expanding the construction.
Basically, its a real pain which is why C++0x is introducing variable-length template arguments and delegation methods that will let you do this cleanly (and safely). In the meantime you can either do it with macros, or try a C++ compiler that has support for (some of) these new experimental features. GCC is a good one for this.
Be warned though that since C++0x isn't actually out yet, things can still change and your code may not be in sync with the final version of the standard. Plus, even after the standard comes out, there'll be 5 years or so during which many compilers will only partially support the standard, so your code won't be very portable.
This code looks dangerous and I think your analysis on why it isn't working is spot on, there's no way for the compiler to know that when calling:
Vector< double, 3 >( 1, 1, 1 )
the ones should be passed as doubles.
I would change the constructor to something like:
Vector< T, C >::Vector(const T(&data)[C])
instead, and have the user pass the arguments as an array. Another sort of ugly solution would be something like this:
template < typename T, uint C >
Vector< T, C >::Vector(const Vector<T, C - 1>& elements, T extra) {
}
and call it like this (with some typedefs):
Vector3(Vector2(Vector1(1), 1), 1);
You can do what you want, but don't do it, because it's not typesafe. Best pass a vector of T or a pair of iterators containing those values.
template < typename T, uint C >
Vector< T, C >::Vector(int N, ... )
{
assert(N < C && "Overflow!");
va_list arg_list;
va_start(arg_list, N);
for(uint i = 0; i < N; i++) {
m_data[i] = va_arg(arg_list, T);
}
va_end(arg_list);
}
Vector<int> v(3, 1, 2, 3);
This can be better solved, since all the elements are homogeneous typed anyway.
template < typename Iter, uint C >
Vector< T, C >::Vector(Iter begin, Iter end)
{
T *data = m_data;
while(begin != end)
*data++ = *begin++;
}
int values[] = { 1, 2, 3 };
Vector<int> v(values, values + 3);
Of course, you have to make sure there is enough place in m_data.
Does TypeList fit your needs?
Generic Programming:Typelists and Applications
Loki C++ Library
Tiny Template Library: implementing typelist
In C++0x (really should be called C++1x), you can use template varargs to achieve what you want in a typesafe fashion (and you won't even need to specify the number of arguments!). However, in the current version of C++ (ISO C++ 1998 with 2003 amendments), there is no way to accomplish what you want. You can either hold off or do what Boost does, which is use preprocessor macro magic to repeat the definition of the constructor multiple times with different numbers of parameters up to a hard-coded, but large limit. Given that Boost.Preprocessor is kind of complicating, you could just define all of the following yourself:
Vector<T,C>::Vector();
Vector<T,C>::Vector(const T&);
Vector<T,C>::Vector(const T&, const T&);
// ...
Since the above is kind of painful to do by hand, though, you could write a script to generate it.
std::tr1::array (which looks similar to yours) does not define a constructor, and can be initialized as an aggregate (?)
std::tr1::array<int, 10> arr = {{ 1, 2, 3, 4, 5, 6 }};
Also you could check out Boost.Assignment library.
For example the constructor could be
template < typename T, uint C >
template < typename Range >
Vector< T, C >::Vector( const Range& r )
and instances created with
Vector<int, 4> vec(boost::assign::cref_list_of<4>(1)(3)(4)(7));
You can use variadic , variadic means template with variable argument.more
The problem with variable arguments in constructors is :
you need the cdecl calling convention (or another one that can handle varargs)
you cant define cdecl for a constructor (in MSVS)
So the "correct" code (MS) could be :
template < typename T, uint C > __cdecl Vector< T, C >::Vector( T, ... )
but the compiler will say:
illegal calling convention for constructor/destructor (MS C4166)

How to avoid infinite recursion in C++ class templates

I have a matrix class with the size determined by template parameters.
template <unsigned cRows, unsigned cCols>
class Matrix {
...
};
My program uses matrices of a few sizes, typically 2x2, 3x3, and 4x4. By setting the matrix size with template parameters rather than run-time parameters allows the compiler to do a lot of inlining and optimization.
But now I need a member function that returns a new matrix that has one fewer row and one fewer column.
Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const { ... }
The idea is that that it will return a matrix with the specified row and column deleted. In practice, this will only ever be called with a matrix that has at least three rows and three columns, returning a 2x2 at the smallest.
The compiler doesn't see the lower bound, so it gets stuck in an infinite recursion trying to instantiate the templates with ever decreasing sizes. I tried putting two clues in the function itself that these smaller sizes cannot occur:
Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const {
static_assert(cRows > 1 && cCols > 1);
if (cRows <= 1 || cCols <= 1) throw std::domain_error();
Matrix<cRows - 1, cCols - 1> r;
// ... initialize r ...
return r;
}
Neither the static_assert nor the if-statement seems to be a strong enough clue to the compiler that a 0x0 matrix will never be generated. (Ironically, it does complain about the if-statement having a constant compile-time condition.)
Does anyone have any suggestions on how to avoid this compile-time infinite recursion?
You need to provide a specialization for a Matrix that has no rows or no columns.
E.g.
template<unsigned cRows>
class Matrix< cRows, 0 >
{
Matrix<cRows - 1, 0> Reduced() { return Matrix<cRows - 1, 0>(); }
};
template<unsigned cCols>
class Matrix< 0, cCols >
{
Matrix<0, cCols - 1> Reduced() { return Matrix<0, cCols - 1>(); }
};
template<>
class Matrix< 0, 0 >
{
Matrix<0, 0> Reduced() { return Matrix<0, 0>(); }
};
The issue you have is that attempting to instantiate the Matrix Reduced function with a particular set of template parameters always required instantiating the Matrix template for a different set of parameters (cRows - 1, cCols -1). This recursion has to be stopped somewhere. If you are only ever dealing with square matrices, then you can get away with fewer specializations.
Also, you can could stop the recursion with a completely empty class if you are never going to use, say, a 1x1 matrix, the result of reduce on a 2x2 matrix.
template<>
class Matrix< 1, 1 > {};
You can specify a template specializations for small values of cRows or cCols which does not include that method.
You seem a bit confused about compile time and run time behaviour, and I'm a bit confused by your code, but I think what you want is a specialisation of the template for the values, 0, 0, which terminates the recursion.
If you haven't already got it, I suggest reading
C++ Templates: The Complete Guide by Vandervoorde & Josuttis, which covers this sort of thing in detail.
You need to explicitly specify the behaviour for the case where you want the recursion to end. See this DDJ article for more details. Here is a simple example from the article:
template<int n>
class META_FACTORIAL
{
public:
enum{
RET = n * META_FACTORIAL<n-1>::RET
};
};
template<>
class META_FACTORIAL<0>
{
public:
enum{ RET = 1 };
};
Rather than specializing the entire class to terminate the recursion, another option might be to use boost::enable_if on the function to make it available only when the matrix size is above 2x2.