Last active
January 2, 2018 03:55
-
-
Save typhoonzero/5d03990b461bb4a5cb90331bfe302576 to your computer and use it in GitHub Desktop.
C++ expression template example for mixing sparse (indices) and dense vector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <set> | |
#include <initializer_list> | |
template<typename E> | |
struct ExpressionFunctor { | |
double operator[](size_t i) const { return static_cast<E const&>(*this)[i]; } | |
size_t size() const { return static_cast<E const&>(*this).size(); } | |
operator E& () { return static_cast<E&>(*this); } | |
operator const E& () const { return static_cast<const E&>(*this); } | |
}; | |
struct Vec : ExpressionFunctor<Vec> { | |
std::vector<double> elems_; | |
double operator[](size_t i) const { return elems_[i]; } | |
double &operator[](size_t i) { return elems_[i]; } | |
size_t size() const { return elems_.size(); } | |
Vec(size_t n) : elems_(n) {} | |
Vec(std::initializer_list<double> init) { | |
for(auto i:init) | |
elems_.push_back(i); | |
} | |
}; | |
struct Indices : ExpressionFunctor<Indices> { | |
std::set<int> elems_; | |
size_t size() const { return elems_.size(); } | |
Indices(std::initializer_list<int> init) { | |
for(auto i:init) | |
elems_.insert(i); | |
} | |
// check if has index in indices | |
inline bool Has(size_t n) const { | |
return elems_.find(n) != elems_.end(); | |
} | |
}; | |
template<typename E1, typename E2> | |
struct SumExp : ExpressionFunctor<SumExp<E1, E2>> { | |
E1 const& e1_; | |
E2 const& e2_; | |
SumExp(E1 const& u, E2 const& v) : e1_(u), e2_(v) { | |
std::cout << "construct VecSum" << std::endl; | |
} | |
// evaluation | |
double operator[](size_t i) const { return e1_[i] + e2_[i]; } | |
size_t size() const { return e2_.size(); } | |
}; | |
template<typename E1, typename IDX, typename E2> | |
struct SparseAddVec : ExpressionFunctor<SparseAddVec<E1, IDX, E2>> { | |
// select using index from v2 to add to v1 | |
E1 const& e1_; | |
IDX const& idx_; | |
E2 const& e2_; | |
SparseAddVec(E1 const& e1, IDX const& idx, E2 const& e2) : | |
e1_(e1), idx_(idx), e2_(e2) { | |
std::cout << "construct SparseAddVec" << std::endl; | |
} | |
// evaluation | |
double operator[](size_t i) const { | |
if (idx_.Has(i)) { | |
return e1_[i] + e2_[i]; | |
} else { | |
return e1_[i]; | |
} | |
} | |
size_t size() const { return e1_.size(); } | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some code for testing: