I'm attempting to get a basic constant forward-iterator to work in C++.
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
int begin_col(int j) { return p[j]; };
int end_col(int j) { return p[j + 1]; };
class iterator {
public:
int index;
iterator(SparseMatrix& g) : parent(g) {}
iterator(int ind) { index = ind; }; // ERROR!
bool operator!=(int x) const { return index != x; };
iterator operator++(int) { ++index; return (*this); };
int row() { return parent.i[index]; };
double value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
};
}
My intention is to use the iterator in contexts similar to the following:
// sum of values in column 7
Rcpp::SparseMatrix A(nrow, ncol, fill::random);
double sum = 0;
for(Rcpp::SparseMatrix::iterator it = A.begin_col(7); it != A.end_col(7); it++)
sum += it.value();
Two questions:
The compiler throws an error on the line indicated above: uninitialized reference member in 'class Rcpp::SparseMatrix&' [-fpermissive]. How can this be fixed?
How might double value() { return parent.x[index]; }; be re-worked to return a pointer to the value rather than a copy of the value?
A little context on the SparseMatrix class: like a dgCMatrix in R, this object of class SparseMatrix consists of three vectors:
i holds row pointers for every element in x
p gives indices in i which correspond to the start of each column
x contains non-zero values
Thanks to #Evg, here's the solution:
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
class iterator {
public:
int index;
iterator(SparseMatrix& g, int ind) : parent(g) { index = ind; }
bool operator!=(iterator x) const { return index != x.index; };
iterator& operator++() { ++index; return (*this); };
int row() { return parent.i[index]; };
double& value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
iterator begin_col(int j) { return iterator(*this, p[j]); };
iterator end_col(int j) { return iterator(*this, p[j + 1]); };
};
}
And it can be used as follows, for instance, to calculate colSums:
//[[Rcpp::export]]
Rcpp::NumericVector Rcpp_colSums(Rcpp::SparseMatrix& A) {
Rcpp::NumericVector sums(A.cols());
for (int i = 0; i < A.cols(); ++i)
for (Rcpp::SparseMatrix::iterator it = A.begin_col(i); it != A.end_col(i); it++)
sums(i) += it.value();
return sums;
}
And, the above function is faster than RcppArmadillo, RcppEigen, and R::Matrix equivalents when microbenchmarked from R!
Edit:
The above syntax is inspired by Armadillo. I've come to realize that a slightly different syntax (which involves fewer constructions) gives an iterator similar to Eigen:
class col_iterator {
public:
col_iterator(SparseMatrix& ptr, int col) : ptr(ptr) { indx = ptr.p[col]; max_index = ptr.p[col + 1]; }
operator bool() const { return (indx != max_index); }
col_iterator& operator++() { ++indx; return *this; }
const double& value() const { return ptr.x[indx]; }
int row() const { return ptr.i[indx]; }
private:
SparseMatrix& ptr;
int indx, max_index;
};
Which can then be used like this:
int col = 0;
for (Rcpp::SparseMatrix::col_iterator it(A, col); it; ++it)
Rprintf("row: %3d, value: %10.2e", it.row(), it.value());
Related
I'm a complete newbie at C++. I want to create my own predicate. But the part with bool operator seems to be wrong (at least in my humble opinion). Could someone give me a hint? I don't want to change the overall structure of this idea, I'm just sure I don't understand some details about operator () implementation or something related to classes in c++.
#include <iostream>
#include <vector>
class Predicate
{
private:
int number = 0;
public:
Predicate() = default;
Predicate(const int number)
{
this->number = number;
}
bool operator()(int value) const
{
Predicate *pred = new Predicate();
bool result = pred->operator()(value);
return result;
}
};
class Even : public Predicate
{
bool operator()(int value) const
{
return value % 2 == 0;
}
};
class Negative : public Predicate
{
bool operator()(int value) const
{
return value < 0;
}
};
int count(const std::vector<int> &elements, const Predicate &predicate)
{
int count = 0;
for (int index = 0; index < elements.size(); ++index)
{
if (predicate(elements[index]))
{
++count;
}
}
return count;
}
int main()
{
const std::vector<int> elements{-7, 12, -11, 2, 9, -4, -6, 5, 23, -1};
std::cout << count(elements, Even()) << " " << count(elements, Negative()) << std::endl;
}
What you need is:
define Predicate as an abstract type,
implements different versions of it.
Predicate as an abstract type:
class Predicate {
public:
virtual bool operator(int v) const = 0;
};
Implementing (realising) a given Predicate:
class IsNegative : public Predicate { // means IsNegatives are Predicates
public:
virtual bool operator(int v) const { return v<0; } // realisation of the operator
};
it's supposed to be an easy question, but i couldnt find the answer on google. So, how do i assign a maximum possible value to a variable?
So i want my variable to be no more than 10 as apossible value no matter what
int example;
example = ?;
You might create a custom class to handle your needs, something like:
template <int Min, int Max>
class BoundedValue
{
public:
BoundedValue(int value = Min) : mValue(Min) { set_value(value); }
int get_value() const { return mValue; }
void set_value(int value) {
if (value < Min || Max < value) {
throw std::out_of_range("!"); // Or other error handling as clamping
// value = std::clamp(value, Min, Max);
}
mValue = value;
}
BoundedValue& operator= (int value) { set_value(value); }
BoundedValue& operator ++() { set_value(mValue + 1); return *this; }
BoundedValue operator ++(int) { auto tmp = *this; ++*this; return tmp; }
// other convenient functions
operator int() const { return mValue; }
private:
int mValue = Min;
};
And then use it:
BoundedValue<0, 10> example;
++example;
example = 11; // "Error"
Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.
Suppose I have a simple vector class where elements are accessed through a proxy class.
Vector class:
class vec {
public:
vec(int len) {
length = len;
data = new double [len];
}
proxy operator[](int i) {
if (i >= 0 && i < length) {
return proxy(i, data);
}
else {
std::cerr << "AHHHH!\n";
exit(1);
}
}
private:
int length;
double * data;
};
Proxy class:
class proxy {
public:
proxy(int i, double * d) {
index = i;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
private:
int index;
double * data;
};
How can I assign elements from the vector (or rather, from the proxy) to a variable of type double? In other words, how do I accomplish the following:
int main() {
vec a(2);
double x = 3.14;
a[0] = x; // Works!
x = a[0]; // How to make work?
return 0;
}
Unfortunately, I can't write something like:
friend double operator=(double & lhs, const proxy & p) { ... }
since operator= must be a member.
Add a conversion function to your proxy class:
class proxy
{
public:
operator double() const { return data[index]; }
// ...
};
I write a small animation program with OpenSceneGraph(osg). In each frame, I should update the models(vertex position,normal, color and other stuff) in the scene.
Now I shoudl convert the data to osg in each frame. The code is like:
cog_.vertex_->clear();
cog_.vertex_->push_back(osg::Vec3(1.0,1.0,1.0));
However these convertion is very time consuming. So I'm wondering how to access data directly via pointer. I tried but failed. The following is what I did, hope someone can help me to find the problem, or tell me better solution:
First, I wrap the a pointer to osg::Vec3,
class vec3_map : public osg::Vec3
{
public:
typedef osg::Vec3::value_type value_type;
osg::Vec3::value_type* p_;
vec3_map() :p_(0) {}
vec3_map(osg::Vec3::value_type*p, int offset = 0) :p_(p+offset){}
inline value_type& x() { return *(p_+0); }
inline value_type& y() { return *(p_+1); }
inline value_type& z() { return *(p_+2); }
// some other stuff
};
When I want to build an array of vec3_map, I found that osg use a tempalte to typedef Vec3Array, but there isn't any type for a pointer, so I choose the closet one (I know pointer is a variable with unsigned long int type):
typedef osg::TemplateArray<vec3_map, osg::Array::UIntArrayType, 1, GL_UNSIGNED_INT> Vec3_map_Array;
With this definition, I can rewrite my problem to the following:
#define BOOST_ALL_NO_LIB
#include <boost/shared_ptr.hpp>
#include <fstream>
#include <vector>
#include <osg/Group>
#include <osg/Geometry>
#include <osgViewer/Viewer>
#include <osg/Vec3>
class vec3_map : public osg::Vec3
{
public:
typedef osg::Vec3::value_type value_type;
osg::Vec3::value_type* p_;
vec3_map() :p_(0) {}
vec3_map(osg::Vec3::value_type*p, int offset = 0) :p_(p + offset) {}
inline value_type* ptr() { return p_; }
inline const value_type* ptr() const { return p_; }
inline value_type& operator [] (int i) { return *(p_ + i); }
inline value_type operator [] (int i) const { return *(p_ + i); }
inline value_type& x() { return *(p_ + 0); }
inline value_type& y() { return *(p_ + 1); }
inline value_type& z() { return *(p_ + 2); }
inline value_type x() const { return *(p_); }
inline value_type y() const { return *(p_ + 1); }
inline value_type z() const { return *(p_ + 2); }
};
typedef osg::TemplateArray<vec3_map, osg::Array::UIntArrayType, 1, GL_UNSIGNED_INT> Vec3_map_Array;
struct point_data
{
point_data(float xx, float yy, float zz) { x = xx; y = yy; z = zz; }
float x;
float y;
float z;
};
osg::Geode* create_point_node(boost::shared_ptr<std::vector<point_data> > ptr)
{
osg::Geode *geode_ = new osg::Geode;
osg::Geometry* geometry_ = new osg::Geometry;
Vec3_map_Array* vertex_ = new Vec3_map_Array;
osg::DrawElementsUInt* point_idx_ = new osg::DrawElementsUInt;
vertex_->reserve(ptr->size());
point_idx_->reserve(ptr->size());
vec3_map vm;
std::vector<point_data> & pd = *ptr;
for (size_t i = 0; i < ptr->size(); ++i)
{
vertex_->push_back(vec3_map(&(pd[i].x)));
point_idx_->push_back(i);
}
geometry_->setVertexArray(vertex_);
geometry_->addPrimitiveSet(point_idx_);
geode_->addDrawable(geometry_);
return geode_;
}
int main(int argc, char *argv[])
{
boost::shared_ptr<std::vector<point_data> > pd(new std::vector<point_data>);
pd->push_back(point_data(1.0, 1.0, 1.0));
pd->push_back(point_data(2.0, 2.0, 2.0));
osgViewer::Viewer viewer;
osg::Node *node = create_point_node(pd);
viewer.setSceneData(node);
return viewer.run();
}
However, this problem crashes. I'm not sure whether I can do something like this.