Last active
March 26, 2017 13:35
-
-
Save hryniuk/e0141e2994d07745c1ed to your computer and use it in GitHub Desktop.
Reduce
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 "Op.hpp" | |
#include "Reduce.hpp" | |
int main() | |
{ | |
std::vector<double> values{1.0, 2.0, 5.0, 4.0, 5.5}; | |
Reduce<SumOp, SumFloorOp, ProductOp, SumSquareOp> r; | |
std::for_each(std::begin(values), std::end(values), [&r](auto&& v){r(v);}); | |
auto v = r.GetResult(); | |
for (const auto& i : v) { | |
std::cout << i << '\n'; | |
} | |
} |
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
#ifndef OP_HPP | |
#define OP_HPP | |
#include <array> | |
#include <cmath> | |
#include <functional> | |
template <typename T1, typename T2, typename T3=void> | |
using _RefFunTemplate = std::function<T3(T1, T2)>; | |
using DoubleRefFun = _RefFunTemplate<double&,double>; | |
template<typename T> | |
const std::array<T, 4> ref_funs | |
{ | |
[](auto&& rAccum, auto&& v){rAccum += v;}, | |
[](auto&& rAccum, auto&& v){rAccum += std::floor(v);}, | |
[](auto&& rAccum, auto&& v){rAccum += v * v;}, | |
[](auto&& rAccum, auto&& v){rAccum *= v;} | |
}; | |
template<int i, int init, typename TRefFun=DoubleRefFun> | |
struct _RefOp | |
{ | |
using F = std::decay_t<typename TRefFun::first_argument_type>; | |
static constexpr F init_val{static_cast<F>(init)}; | |
TRefFun op_{ref_funs<TRefFun>[i]}; | |
F getInitVal() const | |
{ | |
return init_val; | |
} | |
void operator()(F& rAccum, F v) | |
{ | |
op_(rAccum, v); | |
} | |
}; | |
using SumOp = _RefOp<0,0,DoubleRefFun>; | |
using SumFloorOp = _RefOp<1,0,DoubleRefFun>; | |
using SumSquareOp = _RefOp<2,0,DoubleRefFun>; | |
using ProductOp = _RefOp<3,1,DoubleRefFun>; | |
#endif |
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
#ifndef REDUCE_HPP | |
#define REDUCE_HPP | |
#include <algorithm> | |
#include <functional> | |
#include <iostream> | |
#include <tuple> | |
#include <type_traits> | |
#include <vector> | |
template<typename... TOp> | |
struct Reduce | |
{ | |
static constexpr int N{sizeof...(TOp)}; | |
std::tuple<TOp...> op_; | |
std::vector<double> result_; | |
Reduce() | |
: op_{std::tuple<TOp...>{}}, result_(N) | |
{ | |
initialize(result_); | |
} | |
std::vector<double> GetResult() const | |
{ | |
return result_; | |
} | |
template<int i=0> | |
void initialize(std::vector<double>& v, bool) {} | |
template<int i=0> | |
void initialize(std::vector<double>& v, int={}) | |
{ | |
result_[i] = std::get<i>(op_).getInitVal(); | |
initialize<i+1>(v, std::conditional_t< (i+1 < N), int, bool>{}); | |
} | |
template<int i=0> | |
void operator()(double a, bool) {} | |
template<int i=0> | |
void operator()(double a, int _k=0) | |
{ | |
std::get<i>(op_)(result_[i], a); | |
operator()<i+1>(a, std::conditional_t< (i+1 < N), int, bool>{}); | |
} | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment