eigen: create Vector-like Replicate (access with one index, LinearAccessBit) - c++

I want to create an Eigen::Replicate object that can be accessed like a vector, i.e. with a single index. I got that to work with the fixed-size replicate<Index,Index>(), which I can't use in reality, the non-one factor is not a compile-time constant. It also works when manually creating a Replicate object, but I feel like I'm just overlooking the obvious way of using a replicate function to achieve this:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replDynamic { v.replicate(nReplications, 1) };
/* with a dynamic replication, two indexes are required to access a coeff */
std::cout << "5th entry: " << replDynamic(4,0) << '\n';
auto replFixed { v.replicate<nReplications, 1>() };
/* I want to use only one index, but I require the number of replications
* in one dimension to be dynamic */
std::cout << "5th entry: " << replFixed(4) << '\n';
/* don't know how to access the VectorwiseOp variant */
// auto replVector { v.replicate(nReplications) };
// std::cout << "5th entry: " << replVector(4) << '\n';
/* this function doesn't exist */
// auto replDefined { v.replicate<Dynamic,1>(nReplications, 1) };
// std::cout << "5th entry: " << replDefined(4) << '\n';
/* I'd rather not define it manually (it's not the intended way), but it works */
Replicate<Vector3i,Dynamic,1> replManual { v, nReplications, 1 };
std::cout << "5th entry: " << replManual(4) << '\n';
return 0;
}
The source code shows VectorwiseOp<...>::replicate(Index factor) in line 134, which sounds like what I need, but I don't seem to be able to access it.
And a function such as replicate<Index,Index>(Index,Index) doesn't exist.

Assuming I understand what you are asking, since a Vector3i is a one column Eigen::Matrix, you can get a VectorwiseOp<...> expression template from a Vector3i (say) by using the colwise() function and then call the one argument replicate with that.
That is,
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main() {
Vector3i v(3);
v << 0, 1, 2;
auto foo = v.colwise().replicate(2);
std::cout << "5th entry: " << foo(4) << '\n';
return 0;
}
Note though that using type deduction on a expression template, or "pseudo expression" as they are called in the Eigen documentation, is generally a bad idea i.e. writing Eigen::Matrix<int, 6, 1> foo = v.colwise().replicate(2) is safer; the Eigen documentation mentions the issue here.

By adding a .reshaped() after the replicate(...) call, the ColsAtCompileTime are set to 1, and therefore, the resulting object can be accessed like a vector:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replReshaped { v.replicate(nReplications, 1).reshaped() };
std::cout << "5th entry: " << replReshaped(4) << '\n';
return 0;
}

Related

Apply function to section of armadillo vector

I would like to calculate some summary functions (e.g. mean) on a section of a column of an armadillo matrix. Key is not to create a temporary copy of the data.
This works with entire columns, using unsafe_col:
arma::mat x;
double d = mean(x.unsafe_col(0));
To obtain a section of a vector, I could use:
x.col(0).subvec(0,100);
However, this creates a copy of the vector data, which I want to avoid.
What would be the most efficient way to apply the armadillo-provided functions to sections of column vectors? Performance is absolutely critical in this applications.
One way I found was to construct a vector with pointers to the underlying memory, using what is called an "advanced constructor" in the armadillo documentation, but first getting pointers to double for the column start and the adding offsets for start and end just to create a shorter vector seems quite a hack...
UPDATE: Here is an example of the behaviour:
#include <armadillo>
#include <iostream>
arma::mat m( {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}});
const arma::vec view1() {
return m.unsafe_col(0).subvec(0,2);
}
const arma::vec view2() {
double *start = &m[0,0];
const int n = 3;
return arma::vec(start, 3, false, false);
}
int main() {
std::cout << &m(0,0) << " " << &m(1,0) << " " << &m(0,1) << std::endl;
auto v1(view1());
auto v2(view2());
std::cout << &v1(0) << std::endl;
std::cout << &v2(0) << std::endl;
return 0;
}
which returns, for example:
0x56419b070170 0x56419b070178 0x56419b070190
0x7ffcb36f7510
0x56419b070170
So view1() created a copy, but view2() did not.

How to compare if two tensors are equal in Eigen?

There is this:
https://codeyarns.com/2016/02/16/how-to-compare-eigen-matrices-for-equality/
But there is no isApprox for tensors.
The following doesn't do what I want:
#include <Eigen/Core>
#include <unsupported/Eigen/CXX11/Tensor>
#include <array>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
// Create 2 matrices using tensors of rank 2
Eigen::Tensor<int, 2> a(2, 3);
Eigen::Tensor<int, 2>* b = &a;
cerr<<(*b==*b)<<endl;
}
because it does coordinate wise comparison and returns a tensor of the same dimension instead of a true/false vale.
How do I check if two tensors are identical? No isApprox for tensors.
I could write my own function, but I want to be able to use GPU power when available, and it seems like Eigen has built-in GPU support.
For an exact comparison of 2 tensors A and B, you can use the comparison operator followed by a boolean reduction:
Tensor<bool, 0> eq = (A==B).all();
This will return a tensor of rank 0 (i.e. a scalar) that contains a boolean value that's true iff each coefficient of A is equal to the corresponding coefficient of B.
There is no approximate comparison at the moment, although it wouldn't be difficult to add.
You can always use a couple of Eigen::Maps to do the isApprox checks.
#include <iostream>
#include <unsupported/Eigen/CXX11/Tensor>
using namespace Eigen;
int main()
{
Tensor<double, 3> t(2, 3, 4);
Tensor<double, 3> r(2, 3, 4);
t.setConstant(2.1);
r.setConstant(2.1);
t(1, 2, 3) = 2.2;
std::cout << "Size: " << r.size() << "\n";
std::cout << "t: " << t << "\n";
std::cout << "r: " << r << "\n";
Map<VectorXd> mt(t.data(), t.size());
Map<VectorXd> mr(r.data(), r.size());
std::cout << "Default isApprox: " << mt.isApprox(mr) << "\n";
std::cout << "Coarse isApprox: " << mt.isApprox(mr, 0.11) << "\n";
return 0;
}
P.S./N.B. Regarding Eigen's built in GPU support... Last I checked it is fairly limited and with good reason. It is/was limited to fixed size matrices as dynamic allocation on a GPU is really something you want to avoid like the common cold (if not like the plague). I take it back. It looks like the Tensor module supports GPUs pretty well.

I am trying to use templates in c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
#include <iostream>
using namespace std;
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
However, I am getting compilation error. Can somebody help me to find the solution of this problem?
Your problem is using namespace std.
This is a perfect example of why "using namespace std;" screws you up when you least expect it with misleading and confusing error messages.
Remove "using namespace std" from your code, and always explicitly specify "std" when needed, i.e. std::cin, std::cout, etc....
You need to promise yourself that you will never write "using namespace std" ever again. Completely forget that this is a part of the C++ language.
The fixed version of your program, which compiles without any issues, is simply:
#include <iostream>
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
swap() is already a defined function in the std namespace. Rename your method to something else.
using namespace std;
template <typename T>
void swaper(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swaper(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
The error message clearly says: error: call to 'swap' is ambiguous.
This is because swap is part of the namespace std.
And since you are using namespace std; - this is ambiguous!
You can solve this by either:
1.Remove the line using namespace std;
2.Rename the template function to something else
There is actually a number of problems in your code that cause the error message. And one contributor to the problem due to your implementation (i.e. the standard library you are using).
Firstly, you have defined a templated swap() with the same form (accepting two objects of the same type by reference) as an existing function named swap().
Second, the using namespace std tells the compiler that names in namespace std are candidates for matching names in your code. So, when the compiler sees your code swap(m,n) where m and n are int, it sees both your definition and the one in namespace std (i.e. std::swap() as viable candidates to match the name swap() in your code. Both candidates are able to accept two arguments of type (reference to) int, so the compiler has no reason to prefer one over the other. Hence it rejects your code with an error message about ambiguity.
The third problem is in your implementation (i.e. your compiler and its associated standard library) - <iostream> has apparently drawn in the definition of std::swap(). The problem is that <iostream> is neither required to do that (i.e. you cannot rely on it happening if you build your code with a different compiler) nor required not to (i.e. your code will compile alright with some compilers/libraries but not others).
In reality, std::swap() is required by the standard to be declared in <algorithm>, not in <iostream>.
Your options to get your code working with ALL compilers are therefore simple. A first option is to not define your own swap() at all, and rely on the standard library.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
using namespace std;
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A second option is to rename your function so it does not clash with std::swap().
#include <iostream>
using namespace std;
template <typename T>
void your_swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
your_swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A third option is to remove using namespace std from your code. This will allow you to safely declare your own swap(), without clashes with std::swap().
#include <iostream>
#include <algorithm>
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
This last example will actually compile nicely - even with <algorithm> deliberately being used to draw in declarations of std::swap() - because the compiler has not been told to view names in std as candidates. It does require adding std:: prefixes to names in namespace std (std::cout, std::endl) that you intend to use. It will also compile nicely if swap(m,n) is replaced by std::swap(m,n).
A fourth option (which I normally would prefer in professional coding) is to rely on the standard library AND not employ using namespace std.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
std::swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
The short explanation of my preference for this option is that it avoids various other problems of ambiguity as well. The saved typing of not having to prefix std:: on names is not worth the trouble caused when other problems of ambiguity emerge.

Template equivalent of #var in macro

In C++ macros you can use #var to get the literal string of the argument passed:
#define PRINT_SIZE(type) \
(std::cout << sizeof(type) << " " << #type << std::endl)
Using this macro, I can write a very simple program which will give me the lengths of specific types on my machine:
PRINT_SIZE(bool);
PRINT_SIZE(char);
…
This does work but I would like to use C++ templates instead. Obtaining the size is easy with the following template function:
template <typename T>
void print_size() {
std::cout << sizeof(T) << std::endl;
}
I can call this function with any type and it will output the size:
print_size<bool>();
print_size<char>();
…
Is there any way I could get a literal "bool" from this anywhere such that the output would be as nice as the one with macros?
It can sortof be done using RTTI (runtime type inference) using typeid:
#include <iostream>
#include <typeinfo>
template <typename T>
void print_size() {
T a;
std::cout << typeid(a).name() << ": " << sizeof(T) << std::endl;
}
int main(){
print_size<bool>();
print_size<char>();
print_size<long>();
return 0;
}
This outputs:
b: 1
c: 1
l: 8
You can use typeid() as in:
int i;
cout << typeid(i).name(); // Most likely will print int but g++ prints i
cout << typeid(int).name(); // Also most likely will print int but g++ prints i
Note that the name it returns depends on the compiler and may be some unusual form of the type. More information here.
Edit:
g++ (4.8) prints only the first letter of fundamental types. For user defined classes, it prints the number of characters in the name followed by the name. Ex:
#include <iostream>
#include <typeinfo>
class myclass
{
myclass() {}
};
class my
{
my() {}
};
int main()
{
std::cout << typeid(int).name() << std::endl;
std::cout << typeid(bool).name() << std::endl;
std::cout << typeid(myclass).name() << std::endl;
std::cout << typeid(my).name() << std::endl;
}
Produces the following output:
i
b
7myclass
2my

Using a boost::fusion::map in boost::spirit::karma

I am using boost spirit to parse some text files into a data structure and now I am beginning to generate text from this data structure (using spirit karma).
One attempt at a data structure is a boost::fusion::map (as suggested in an answer to
this question). But although I can use boost::spirit::qi::parse() and get data in it easily, when I tried to generate text from it using karma, I failed.
Below is my attempt (look especially at the "map_data" type). After some reading and playing around with other fusion types, I found boost::fusion::vector and BOOST_FUSION_DEFINE_ASSOC_STRUCT. I succeeded to generate output with both of them, but they don't seem ideal: in vector you cannot access a member using a name (it is like a tuple) -- and in the other solution, I don't think I need both ways (member name and key type) to access the members.
#include <iostream>
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/make_map.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/transform.hpp>
struct sb_key;
struct id_key;
using boost::fusion::pair;
typedef boost::fusion::map
< pair<sb_key, int>
, pair<id_key, unsigned long>
> map_data;
typedef boost::fusion::vector < int, unsigned long > vector_data;
#include <boost/fusion/include/define_assoc_struct.hpp>
BOOST_FUSION_DEFINE_ASSOC_STRUCT(
(), assocstruct_data,
(int, a, sb_key)
(unsigned long, b, id_key))
namespace karma = boost::spirit::karma;
template <typename X>
std::string to_string ( const X& data )
{
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
karma::generate_delimited ( sink, karma::int_ << karma::ulong_, karma::space, data );
return generated;
}
int main()
{
map_data d1(boost::fusion::make_map<sb_key, id_key>(234, 35314988526ul));
vector_data d2(boost::fusion::make_vector(234, 35314988526ul));
assocstruct_data d3(234,35314988526ul);
std::cout << "map_data as_vector: " << boost::fusion::as_vector(d1) << std::endl;
//std::cout << "map_data to_string: " << to_string(d1) << std::endl; //*FAIL No 1*
std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d1) << boost::fusion::at_c<0>(d1) << std::endl << std::endl;
std::cout << "vector_data: " << d2 << std::endl;
std::cout << "vector_data to_string: " << to_string(d2) << std::endl << std::endl;
std::cout << "assoc_struct as_vector: " << boost::fusion::as_vector(d3) << std::endl;
std::cout << "assoc_struct to_string: " << to_string(d3) << std::endl;
std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d3) << d3.a << boost::fusion::at_c<0>(d3) << std::endl;
return 0;
}
Including the commented line gives lots of pages of compilation errors, among which notably something like:
no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘double’
no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘float’
Might it be that to_string needs the values of the map_data, and not the pairs? Though I am not good with templates, I tried to get a vector from a map using transform in the following way
template <typename P>
struct take_second
{
typename P::second_type operator() (P p)
{
return p.second;
}
};
// ... inside main()
pair <char, int> ff(32);
std::cout << "take_second (expect 32): "
<< take_second<pair<char,int>>()(ff) << std::endl;
std::cout << "transform map_data and to_string: "
<< to_string(boost::fusion::transform(d1, take_second<>())); //*FAIL No 2*
But I don't know what types am I supposed to give when instantiating take_second and anyway I think there must be an easier way to get (iterate over) the values of a map (is there?)
If you answer this question, please also give your opinion on whether using an ASSOC_STRUCT or a map is better.
I think I noticed your question on the [spirit-general] list earlier.
It got 14 views there - and I did some fairly deep investigation. Sadly, to the best of my knowledge I don't think Spirit has any support for associate Fusion structures.
In fact, outside MSM and Phoenix, there was no place in boost where I see fusion::map being used.
Is there a chance you could just use std::map/std::pair instead? Here's a tiny proof of concept:
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/adapted.hpp>
int main()
{
const auto data = std::map<std::string, double> {
{ "pi", 3.1415925 },
{ "e", 2.718281828 },
{ "Answer", 42 } };
namespace karma = boost::spirit::karma;
std::cout << karma::format((karma::string << " = " << karma::double_) % karma::eol, data)
<< std::endl;
}
Output:
Answer = 42.0
e = 2.718
pi = 3.142