I'm wondering if there is an elegant solution for composing mathematical operators in C++. By operator, I mean something like the following:
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
The above class makes use of a "helper function" h(x). For example,
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
return 0;
}
Now, I would like to compose the operator twice or more times, i.e. compute A^2(f,2.0). In the above example, this would return h(x)*h(x)*f(x). Note that this is not function composition, i.e. I do not want to compute A(A(f,2.0),2.0). Rather, think in terms of computing powers of a matrix: if h(x) = M (a matrix), I want M*M*...*M*x.
I was able to use std::bind() to achieve my desired result for A^2 (but not higher powers!) as follows:
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
With the resulting g, I can apply A^2(f,2.0) by simply calling A(g,2.0). With the above examples, this would return h(x)*h(x)*f(x) = x*x*x*x*exp(x)
How would I generalize this to iteratively applying the operator A N times? I really liked the answer posted here, but it doesn't quite work here. I tried doing nested std:binds but quickly got into deep compiler errors.
Any ideas?
Complete working example:
#include<iostream>
#include<math.h>
#include<functional> //For std::bind
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
std::cout<<"A^2(f,2.0) = "<<A(g,2.0) <<std::endl; //Returns 2^4*exp(2) = 118.225...
return 0;
}
Try this, using template specialization
#include<iostream>
#include<math.h>
#include<functional> //For std::bind
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
// C++ doesn't permit recursive "partial specialization" in function
// So, make it a struct instead
template<typename T, typename U, typename W, int i>
struct Binder {
auto binder(U b, W c) {
// Recursively call it with subtracting i by one
return [&](T x){ return b(Binder<T, U, W, i-1>().binder(b, c), x); };
}
};
// Specialize this "struct", when i = 2
template<typename T, typename U, typename W>
struct Binder<T, U, W, 2> {
auto binder(U b, W c) {
return [&](T x){ return b(c, x); };
}
};
// Helper function to call this struct (this is our goal, function template not
// struct)
template<int i, typename T, typename U, typename W>
auto binder(U b, W d) {
return Binder<T, U, W, i>().binder(b, d);
}
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
// We don't need to give all the template parameters, C++ will infer the rest
auto g = binder<2, double>(A, f);
std::cout<<"A^2(f,2.0) = "<<A(g,2.0) <<std::endl; //Returns 2^4*exp(2) = 118.225...
auto g1 = binder<3, double>(A, f);
std::cout<<"A^3(f,2.0) = "<<A(g1,2.0) <<std::endl; //Returns 2^6*exp(2) = 472.2
auto g2 = binder<4, double>(A, f);
std::cout<<"A^4(f,2.0) = "<<A(g2,2.0) <<std::endl; //Returns 2^8*exp(2) = 1891.598...
return 0;
}
From what I could understand from you question, you are essentially trying to define
A^1(h, f, x) = h(x) * f(x)
A^n(h, f, x) = h(x) * A^(n-1)(h, f, x)
If you are open to using C++17, here is something you can build upon:
#include <iostream>
#include <math.h>
template <int N>
struct apply_n_helper {
template <typename H, typename F>
auto operator()(H h, F f, double x) const {
if constexpr(N == 0) {
return f(x);
} else {
return h(x) * apply_n_helper<N - 1>()(h, f, x);
}
}
};
template <int N>
constexpr auto apply_n = apply_n_helper<N>();
int main() {
auto sqr = [](double x) { return x * x; };
auto exp_ = [](double x) { return exp(x); };
std::cout << apply_n<100>(sqr, exp_, 2.0) << '\n';
std::cout << apply_n<200>(sqr, exp_, 2.0) << '\n';
return 0;
}
If C++17 is not an option, you can easily rewrite this to use template specializations instead of constexpr-if. I will leave this as an exercise. Here is a link to compiler explorer with this code: https://godbolt.org/z/5ZMw-W
EDIT Looking back at this question, I see that you are essentially trying to compute (h(x))^n * f(x) in a manner so that you don't have to actually do any looping at runtime and the generated code is equivalent to something like:
auto y = h(x);
auto result = y * y * ... * y * f(x)
\_____________/
n times
return result;
Another way of achieving this would be to have something as follows
#include <cmath>
#include <iostream>
template <size_t N, typename T>
T pow(const T& x) {
if constexpr(N == 0) {
return 1;
} else if (N == 1) {
return x;
} else {
return pow<N/2>(x) * pow<N - N/2>(x);
}
}
template <int N>
struct apply_n_helper {
template <typename H, typename F>
auto operator()(H h, F f, double x) const {
auto tmp = pow<N>(h(x));
return tmp * f(x);
}
};
template <int N>
constexpr auto apply_n = apply_n_helper<N>();
int main()
{
auto sqr = [](double x) { return x * x; };
auto exp_ = [](double x) { return exp(x); };
std::cout << apply_n<100>(sqr, exp_, 2.0) << '\n';
std::cout << apply_n<200>(sqr, exp_, 2.0) << '\n';
return 0;
}
Here, the usage of pow function is saving us from evaluating h(x) several times.
I mean you can use a other class:
template <typename T, std::size_t N>
struct Pow
{
Pow(T t) : t(t) {}
double operator()(double x) const
{
double res = 1.;
for (int i = 0; i != N; ++i) {
res *= t(x);
}
return res;
}
T t;
};
And use
ApplyOp<Pow<Helper, 2>> B(h); instead of ApplyOp<Helper> A(h);
Demo
So you want to be able to multiply functions. Well, that sounds good. Why not + and - and / while we are in there?
template<class F>
struct alg_fun;
template<class F>
alg_fun<F> make_alg_fun( F f );
template<class F>
struct alg_fun:F {
alg_fun(F f):F(std::move(f)){}
alg_fun(alg_fun const&)=default;
alg_fun(alg_fun &&)=default;
alg_fun& operator=(alg_fun const&)=default;
alg_fun& operator=(alg_fun &&)=default;
template<class G, class Op>
friend auto bin_op( alg_fun<F> f, alg_fun<G> g, Op op ) {
return make_alg_fun(
[f=std::move(f), g=std::move(g), op=std::move(op)](auto&&...args){
return op( f(decltype(args)(args)...), g(decltype(args)(args)...) );
}
);
}
template<class G>
friend auto operator+( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g), std::plus<>{} );
}
template<class G>
friend auto operator-( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g), std::minus<>{} );
}
template<class G>
friend auto operator*( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g),
std::multiplies<>{} );
}
template<class G>
friend auto operator/( alg_fun<F> f, alg_fun<G> g ) {
return bin_op( std::move(f), std::move(g),
std::divides<>{} );
}
template<class Rhs,
std::enable_if_t< std::is_convertible<alg_fun<Rhs>, F>{}, bool> = true
>
alg_fun( alg_fun<Rhs> rhs ):
F(std::move(rhs))
{}
// often doesn't compile:
template<class G>
alg_fun& operator-=( alg_fun<G> rhs )& {
*this = std::move(*this)-std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator+=( alg_fun<G> rhs )& {
*this = std::move(*this)+std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator*=( alg_fun<G> rhs )& {
*this = std::move(*this)*std::move(rhs);
return *this;
}
template<class G>
alg_fun& operator/=( alg_fun<G> rhs )& {
*this = std::move(*this)/std::move(rhs);
return *this;
}
};
template<class F>
alg_fun<F> make_alg_fun( F f ) { return {std::move(f)}; }
auto identity = make_alg_fun([](auto&& x){ return decltype(x)(x); });
template<class X>
auto always_return( X&& x ) {
return make_alg_fun([x=std::forward<X>(x)](auto&&... /* ignored */) {
return x;
});
}
I think that about does it.
auto square = identity*identity;
we can also have type-erased alg funs.
template<class Out, class...In>
using alg_map = alg_fun< std::function<Out(In...)> >;
these are the ones that support things like *=. alg_fun in general don't type erase enough to.
template<class Out, class... In>
alg_map<Out, In...> pow( alg_map<Out, In...> f, std::size_t n ) {
if (n==0) return always_return(Out(1));
auto r = f;
for (std::size_t i = 1; i < n; ++i) {
r *= f;
}
return r;
}
could be done more efficiently.
Test code:
auto add_3 = make_alg_fun( [](auto&& x){ return x+3; } );
std::cout << (square * add_3)(3) << "\n";; // Prints 54, aka 3*3 * (3+3)
alg_map<int, int> f = identity;
std::cout << pow(f, 10)(2) << "\n"; // prints 1024
Live example.
Here is a more efficient pow that works without type erasure:
inline auto raise(std::size_t n) {
return make_alg_fun([n](auto&&x)
-> std::decay_t<decltype(x)>
{
std::decay_t<decltype(x)> r = 1;
auto tmp = decltype(x)(x);
std::size_t bit = 0;
auto mask = n;
while(mask) {
if ( mask & (1<<bit))
r *= tmp;
mask = mask & ~(1<<bit);
tmp *= tmp;
++bit;
}
return r;
});
}
template<class F>
auto pow( alg_fun<F> f, std::size_t n ) {
return compose( raise(n), std::move(f) );
}
Live example. It uses a new function compose in alg_fun:
template<class G>
friend auto compose( alg_fun lhs, alg_fun<G> rhs ) {
return make_alg_fun( [lhs=std::move(lhs), rhs=std::move(rhs)](auto&&...args){
return lhs(rhs(decltype(args)(args)...));
});
}
which does compose(f,g)(x) := f(g(x))
Your code now literally becomes
alg_fun<Helper> h;
alg_fun<F> f;
auto result = pow( h, 10 )*f;
which is h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*h(x)*f(x). Except (with the efficient version) I only call h once and just raise the result to the power 10.
Related
I am trying to understand expression templates to be able to efficiently evaluate multivariate polynomials like:
double PAx,PAy, aAB;
double val = (PAx*PAx*PAx*PAx + 6*PAx*PAX*aAB + 3*aAB*aAB)*(PAy*PAy*PAy*PAy);
using expression templates, if possible. How do I modify the following code snippet to achieve this goal?
#include <utility>
#include <iostream>
template<typename T1, typename T2>
struct plus;
template<typename T1, typename T2>
struct times;
template<typename T, typename U>
constexpr auto operator+(T l, U r){ return plus(l,r);}
template<typename T, typename U>
constexpr auto operator*(T l, U r){ return times(l,r);}
template<typename T1, typename T2>
struct plus{
constexpr plus(T1 t1_, T2 t2_):t1{t1_},t2{t2_}{}
T1 t1;
T2 t2;
template<typename T>
constexpr auto operator()(T&& t) const {return t1(std::forward<T>(t))+t2(std::forward<T>(t));}
};
template<typename T>
struct is_plus : std::false_type{};
template<typename T1, typename T2>
struct is_plus<plus<T1, T2>> : std::true_type{};
template<typename T1, typename T2>
struct times{
constexpr times(T1 t1_, T2 t2_):t1{t1_},t2{t2_}{}
T1 t1;
T2 t2;
template<typename T>
constexpr auto operator()(T&& t) const {return t1(std::forward<T>(t))*t2(std::forward<T>(t));}
};
template<typename T>
struct is_times : std::false_type{};
template<typename T1, typename T2>
struct is_times<times<T1, T2>> : std::true_type{};
template <typename T, typename U>
using same = std::is_same<typename std::decay<T>::type,typename std::decay<U>::type>;
int main(){
constexpr auto x = [](auto t){ return [t](auto t2){return t ;};};
constexpr auto y = [](auto t){ return [t](auto t2){return t2;};};
constexpr auto c = [](auto t){ return [t](auto){ return [t](auto){return t;};};};
constexpr auto zero = [](auto t){ return [t](auto t2){return 0 ;};};
constexpr auto one = [](auto t){ return [t](auto t2){return 1 ;};};
constexpr auto recursion = [one, zero, x, y](auto tag, auto t, auto self){
using t_t = decltype(t);
using x_t = decltype(x);
using y_t = decltype(y);
using tag_t = decltype(tag);
if constexpr (same<t_t,x_t>::value)
if constexpr (same<tag_t,x_t>::value)
return one;
else
return zero;
else if constexpr(same<t_t, y_t>::value)
if constexpr (same<tag_t,y_t>::value)
return one;
else
return zero;
else if constexpr( is_plus<typename std::decay<decltype(t)>::type>::value)
return plus{self(tag, t.t1, self), self(tag, t.t2, self)};
else if constexpr( is_times<typename std::decay<decltype(t)>::type>::value)
return plus{times{self(tag, t.t1, self), t.t2}, times{t.t1, self(tag, t.t2, self)}};
else
return zero;
};
constexpr auto Dx = [recursion,x](auto t){return recursion(x, t, recursion);};
constexpr auto Dy = [recursion,y](auto t){return recursion(y, t, recursion);};
// Having defined variables like:
double PAx,PAy,aAB;
auto constexpr ex = Dy(x*x*c(4.)+y*x*c(4.)); // I am interested in evaluating expressioons like (PAx*PAx*PAx*PAx + 6*PAx*PAx*aAB + 3*aAB*aAB)*(PAy*PAy*PAy*PAy)
auto constexpr val1=ex(5.);
auto constexpr val=(val1+x(1.))(0.);
std::cout<<val<<"\n";
}
The fact that in my application PAx, PAy and aAB, are only known at execution time can have a negative impact on the performance improvement that I am expecting? Can lazy evaluation be preserved?
The snippet is based on this tutorial I tested the snippet of code above on godbolt.org and here you can see the instantiation of the templates specializations.
Update
Taking into account the suggestions in the comments below, the code was modified as follows:
#include <utility>
#include <tuple>
#include <functional>
#include <iostream>
#include <cmath>
namespace expr_types {
template<class D>
struct formula {
constexpr auto operator()(auto...args) const {
return eval(*static_cast<D const*>(this))(args...);
}
};
template<std::size_t I>
struct var_t:formula<var_t<I>> {
friend constexpr auto eval( var_t ) {
return [](auto...args){return std::get<I>( std::make_tuple(args...) );};
}
};
template<std::size_t N>
constexpr var_t<N> var = {};
template<class T=double>
struct val_t:formula<val_t<T>> {
T k = {};
constexpr val_t(T in):k(in){}
friend constexpr auto eval( val_t self ) {
return [self](auto...){return self.k;};
}
friend constexpr auto diff( auto, val_t ) {
return val_t{0};
}
};
template<class T>
val_t(T)->val_t<T>;
template<class Lhs, class Op, class Rhs>
struct tree:formula<tree<Lhs, Op, Rhs>> {
Lhs lhs;
Op op;
Rhs rhs;
constexpr tree(Lhs l, Op o, Rhs r):lhs(l),op(o),rhs(r){}
friend constexpr auto eval( tree self ) {
return eval(self.lhs, self.op, self.rhs);
}
friend constexpr auto diff( auto D, tree self ) {
return diff(D, self.lhs, self.op, self.rhs);
}
};
auto operator+( auto lhs, auto rhs ) {
return tree{lhs, std::plus<>{}, rhs};
}
auto operator-( auto lhs, auto rhs ) {
return tree{lhs, std::minus<>{}, rhs};
}
auto operator*( auto lhs, auto rhs ) {
return tree{lhs, std::multiplies<>{}, rhs};
}
auto operator/( auto lhs, auto rhs ) {
return tree{lhs, std::divides<>{}, rhs};
}
struct pow_t {
auto operator()(auto lhs, auto rhs)const{
return std::pow(lhs, rhs);
}
};
auto operator^( auto lhs, auto rhs ) {
return tree{lhs, pow_t{}, rhs};
}
// what * means:
constexpr auto eval( auto lhs, auto op, auto rhs )
{
return [=](auto...args){
// use std::multiplies to avoid seeing above operator*
return op(eval(lhs)(args...), eval(rhs)(args...));
};
}
// What D(a*b) means:
constexpr auto diff(auto D, auto lhs, std::multiplies<>, auto rhs) {
return D(lhs)*rhs + lhs*D(rhs);
}
// What D(a/b) means:
constexpr auto diff(auto D, auto lhs, std::divides<>, auto rhs) {
return (D(lhs)*rhs - lhs*D(rhs)) / ( rhs^val_t{2} );
}
// What D(a+b) means:
constexpr auto diff(auto D, auto lhs, std::plus<>, auto rhs) {
return D(lhs)+D(rhs);
}
// What D(a-b) means:
constexpr auto diff(auto D, auto lhs, std::minus<>, auto rhs) {
return D(lhs)-D(rhs);
}
template<class V, class T=double>
struct differential_t {
constexpr auto operator()( auto f ) const {
return diff( *this, f );
}
};
template<std::size_t N, class T, std::size_t M>
constexpr val_t<T> diff( differential_t<var_t<N>, T>, var_t<M> ) {
return val_t<T>{N==M};
}
}
namespace expr {
constexpr auto x = expr_types::var<0>;
constexpr auto y = expr_types::var<1>;
constexpr auto val(auto x){
using namespace expr_types;
return val_t(x);
}
constexpr auto one = val(1);
constexpr auto zero = val(0);
template<auto V, class T=double>
constexpr expr_types::differential_t<decltype(V),T> D = {};
}
int main()
{
using namespace expr;
auto f = x*one + x*x + x*x*y + zero;
std::cout << f(1.0, 2.0) << "\n";
auto df = D<x>(f);
std::cout << df(1.0, 2.0) << "\n";
auto g = (one + x)*(one + y);
std::cout << g(1.0, 1.0) << "\n";
std::cout << D<y>(g)(1.0, 1.0) << "\n";
auto h = (x^val(2));
std::cout << h(2.0, 2.0) << "\n";
}
I tried to write a function in C++ which can compose a variable amount of lambdas. My first attempt kind of works (even though I suspect it isn't perfect)
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
template <typename F, typename G, typename... Fs>
auto pipe(F f, G g, Fs... fs) {
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return pipe(fg, fs...);
} else {
return compose(f, g);
}
}
int main() {
auto add_x = [](const auto &x) {
return [x](auto y) {
std::cout << "+" << x << std::endl;
return y + x;
};
};
auto to_str = [](const auto &s) {
std::cout << "to_str" << std::endl;
return std::string("String:") + std::to_string(s);
};
auto add_1 = add_x(1);
auto add_2 = add_x(2);
auto add_3 = add_x(3);
auto piped = pipe(add_1, add_2, add_3, to_str);
auto x = piped(3);
std::cout << x << std::endl;
}
However, I'd like to have the pipe function itself to be a lambda function. This is kind of hard however, since, as I understood it, lambdas can't capture themselves. This makes simply "lambdafying" my template function problematic. Does anyone have an alternative approach or an idea how to get similar results with a lambda function?
You can use the y combinator to make a recursive lambda.
template<class Fun>
class y_combinator_result {
Fun fun_;
public:
template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
template<class ...Args>
decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...);
}
};
template<class Fun>
decltype(auto) y_combinator(Fun &&fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
auto pipe = y_combinator([](auto self, auto f, auto g, auto... fs){
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return self(fg, fs...);
} else {
return compose(f, g);
}
});
See it live
I'm trying to globally scale and add together callable/indexible objects (vectors in the abstract mathematical sense of the word).
That is to say, I'm trying to take linear combinations of objects that define operator[] or operator().
For example, I want to be able to do this:
LinearCombination<std::function<double(double, double)>> A([](double x, double y){
return 1+x+std::pow(x,2)+std::sin(y);
});
LinearCombination<std::function<double(double, double)>> B([](double x, double y){
return 1-x+std::cos(y);
});
A*= 2.5;
A += B;
std::cout << A(1.0,2.0) << std::endl;
My attempt
// ZERO ///////////////////////////////////////////////////////////////////////////////////////////
namespace hidden {
// tag dispatching: from https://stackoverflow.com/a/60248176/827280
template<int r>
struct rank : rank<r - 1> {};
template<>
struct rank<0> {};
template<typename T>
auto zero(rank<2>) -> decltype(static_cast<T>(0)) {
return static_cast<T>(0);
}
template<typename T>
auto zero(rank<1>) -> decltype(T::zero()) {
return T::zero();
}
template<typename T>
auto zero(rank<0>)->std::enable_if_t<
std::is_assignable<std::function<double(double,double)>, T>::value
, std::function<double(double,double)>> {
return []() {
return 0.0;
};
}
}
template<typename T>
auto zero() { return hidden::zero<T>(hidden::rank<10>{}); }
// LINEAR COMBINATION ///////////////////////////////////////////////////////////////////////////////////////////
template<typename V, typename C = double>
struct LinearCombination {
struct Term {
C coeff;
V vector;
// if V(x...) is defined
template<typename ...X>
auto operator()(X&&... x) const -> std::remove_reference_t<decltype(std::declval<V>()(std::forward<X>(x)...))> {
return vector(std::forward<X>(x)...) * coeff;
}
// if V[i] is defined
template<typename I>
auto operator[](I i) const -> std::remove_reference_t<decltype(std::declval<V>()[i])> {
return vector[i] * coeff;
}
};
std::vector<Term> terms;
LinearCombination() {} // zero
/*implicit*/ LinearCombination(V&& v) {
terms.push_back({ static_cast<C>(1), std::move(v) });
}
/*implicit*/ LinearCombination(Term&& term) {
terms.push_back(std::move(term));
}
LinearCombination<V, C>& operator+=(LinearCombination<V, C>&& other) {
terms.reserve(terms.size() + other.terms.size());
std::move(std::begin(other.terms), std::end(other.terms), std::back_inserter(terms));
other.terms.clear();
return *this;
}
LinearCombination<V, C>& operator*=(C multiplier) {
for (auto& term : terms) {
term.coeff *= multiplier;
}
return *this;
}
// if V(x...) is defined
template<typename ...X>
auto operator()(X&&... x) const
-> std::remove_reference_t<decltype(std::declval<V>()(std::forward<X>(x)...))> {
auto result = zeroVector()(std::forward<X>(x)...); <--------------- *** BAD FUNCTION CALL ***
*************************
for (const auto& term : terms) {
result += term(std::forward<X>(x)...);
}
return result;
}
// if V[i] is defined
template<typename I>
auto operator[](I i) const -> std::remove_reference_t<decltype(std::declval<V>()[i])> {
auto result = zeroVector()[i];
for (const auto& term : terms) {
result += term[i];
}
return result;
}
private:
static const V& zeroVector() {
static V z = zero<V>();
return z;
}
};
This compiles fine for me, but I get an exception on the indicated line (bad function call). Can you help?
This function:
template<typename T>
auto zero(rank<2>) -> decltype(static_cast<T>(0));
wins overload resolution against:
template<typename T>
auto zero(rank<0>)->std::enable_if_t<
std::is_assignable<std::function<double(double,double)>, T>::value
, std::function<double(double,double)>>;
This is because rank<2> is a better match for rank<10>{} than rank<0>, and also:
static_cast<std::function<double(double,double)>>(0)
is a valid expression.
That is, std::function has the following constructor:
function(std::nullptr_t) noexcept;
which makes it a viable choice for the 0 argument, and static_cast does considers constructors.
You end up with std::function<double(double,double)> initialized with 0 (empty), which leads to the exception when you attempt to invoke it.
Please consider the following boost::math::pdf-like implementation of a generic probability density function evaluation:
template<typename T, class Distribution>
inline typename Distribution::result_type pdf(Distribution const& d, T const& x) {
return pdf(d, static_cast<typename Distribution::result_type>(x));
}
template<typename RealType>
RealType pdf(std::uniform_real_distribution<RealType> const& d, RealType const& x)
{
if (d.a() <= x && x <= d.b())
return 1 / (d.b() - d.a());
return 0;
}
I'd like to define another pdf function which takes a distribution and a vector and evaluates the probability density of each vector component. The function should be invokable for nested vectors as well. I've tried something like this:
template<typename T, class Distribution>
inline typename Distribution::result_type pdf(Distribution const& d, std::vector<T> const& x)
{
return std::reduce(x.begin(), x.end(), typename Distribution::result_type{ 1 },
[&](auto const& p, auto const& x) { return p * pdf(d, x); });
}
Example code:
std::vector<std::vector<double>> x = { {1}, {2, 3}, {4} };
std::vector<double> y = { 1, 2, 3, 4 };
std::uniform_real_distribution<> d;
std::cout << pdf(d, x) << std::endl;
std::cout << pdf(d, y) << std::endl;
This works as it should be. However, if I change std::uniform_real_distribution<> d; to std::uniform_real_distribution<float> d;, then I end up in an infinite recursion for the call of pdf(d, x) (for obvious reasons). So, how do I need to change the code? Maybe such that it works for other containers as well.
Instead of having two overloads for the first case (which basically do the same thing):
template<typename T, class Distribution>
inline typename Distribution::result_type pdf(Distribution const& d, T const& x) {
return pdf(d, static_cast<typename Distribution::result_type>(x));
}
template<typename RealType>
RealType pdf(std::uniform_real_distribution<RealType> const& d, RealType const& x)
{
if (d.a() <= x && x <= d.b())
return 1 / (d.b() - d.a());
return 0;
}
collapse them into one:
template <typename R, typename T, std::enable_if_t<std::is_convertible_v<T, R>, int> = 0>
auto pdf(std::uniform_real_distribution<R> const& d, T x) -> R
{
if (d.a() <= x && x <= d.b()) {
return 1 / (d.b() - d.a());
}
return 0;
}
Or simpler to just block type deduction on the 2nd argument entirely (std::type_identity is C++20 but is trivial to implement):
template <typename R>
auto pdf(std::uniform_real_distribution<R> const& d, std::type_identity_t<R> x) -> R
I am currently coding some cryptographic algorithms in C++11 that require a lot of function compositions. There are 2 types of composition I have to deal with :
Compose a function on itself a variable number of times. Mathematically, for a certain function F, F^n(x) = (F^{n-1} o F)(x) = F^{n-1}(F(x)).
Compose different functions together. For example, for some functions f,g,h,i,j and k of the same type, I'll have f(g(h(i(j(k(x)))))).
In my case, I'm using the following definition of F :
const std::vector<uint8_t> F(const std::vector<uint8_t> &x);
I would like to compose this function on itself n times. I have implemented the composition in a simple recursive way which is working fine :
const std::vector<uint8_t> compose(const uint8_t n, const std::vector<uint8_t> &x)
{
if(n > 1)
return compose(n-1, F(x));
return F(x);
}
For this case, is there a more efficient way an proper way to implement this composition using c++11 but without using BOOST ?
It would be great to use this form if it is possible of course :
answer = compose<4>(F)(x); // Same as 'answer = F^4(x) = F(F(F(F(x))))'
For the second case, I would like to implement the composition of a variable number of functions. For a given set of functions F0, F1, ..., Fn having the same definition as F, is there an efficient and proper way to compose them where n is variable ?
I think variadic template would be useful here, but I don't know how to use them in that case.
Thanks for your help.
Something along these lines, perhaps (untested):
template <typename F>
class Composer {
int n_;
F f_;
public:
Composer(int n, F f) : n_(n), f_(f) {}
template <typename T>
T operator()(T x) const {
int n = n_;
while (n--) {
x = f_(x);
}
return x;
}
};
template <int N, typename F>
Composer<F> compose(F f) {
return Composer<F>(N, f);
}
EDIT: And for the second case (tested this time):
#include <iostream>
template <typename F0, typename... F>
class Composer2 {
F0 f0_;
Composer2<F...> tail_;
public:
Composer2(F0 f0, F... f) : f0_(f0), tail_(f...) {}
template <typename T>
T operator() (const T& x) const {
return f0_(tail_(x));
}
};
template <typename F>
class Composer2<F> {
F f_;
public:
Composer2(F f) : f_(f) {}
template <typename T>
T operator() (const T& x) const {
return f_(x);
}
};
template <typename... F>
Composer2<F...> compose2(F... f) {
return Composer2<F...>(f...);
}
int f(int x) { return x + 1; }
int g(int x) { return x * 2; }
int h(int x) { return x - 1; }
int main() {
std::cout << compose2(f, g, h)(42);
return 0;
}
Thanks for the fun question, Gabriel of year 2013.
Here is a solution. It works in c++14.
#include <functional>
#include <iostream>
using std::function;
// binary function composition for arbitrary types
template <class F, class G> auto compose(F f, G g) {
return [f, g](auto x) { return f(g(x)); };
}
// for convienience
template <class F, class G> auto operator*(F f, G g) { return compose(f, g); }
// composition for n arguments
template <class F, typename... Fs> auto compose(F f, Fs &&... fs) {
return f * compose(fs...);
}
// composition for n copies of f
template <int i, class F>
// must wrap chain in a struct to allow partial template specialization
struct multi {
static F chain(F f) { return f * multi<i - 1, F>::chain(f); }
};
template <class F> struct multi<2, F> {
static F chain(F f) { return f * f; }
};
template <int i, class F> F compose(F f) { return multi<i, F>::chain(f); }
int main(int argc, char const *argv[]) {
function<double(int)> f = [](auto i) { return i + 3; };
function<int(double)> g = [](auto i) { return i * 2; };
function<int(int)> h = [](auto i) { return i + 1; };
std::cout << '\n'
<< "9 == " << compose(f, g, f)(0) << '\n'
<< "5 == " << (f * g * h)(0) << '\n'
<< "100 == " << compose<100>(h)(0) << '\n';
return 0;
}
You can define
Matrix compose(Matrix f, Matrix g);
or
Rotation compose(Rotation f, Rotation g);
to reuse this code for all sorts of things.
A very general example (g++ -std=c++1y composition.cpp):
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Library part:
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
The whole program:
// g++ -std=c++1y composition.cpp
#include <iostream>
using namespace std;
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Here is a simple c++14 solution (it may probably be re-written to c++11):
#include <iostream>
// base condition
template <typename F>
auto compose(F&& f)
{
return [a = std::move(f)](auto&&... args){
return a(std::move(args)...);
};
}
// recursive composition
// from compose(a, b, c...) to compose(ab, c...)
template <typename F1, typename F2, typename... Fs>
auto compose(F1&& f1, F2&& f2, Fs&&... fs)
{
return compose(
[first = std::move(f1), second = std::move(f2)]
(auto&&... args){
return second(first(std::move(args)...));
},
std::move(fs)...
);
}
Possible usage:
int main()
{
const auto f = compose(
[](const auto n){return n * n;},
[](const auto n){return n + 2;},
[](const auto n){return n + 2;}
);
std::cout << f(10) << std::endl; // outputs 104
}
Here is a link to the repo with a few more examples: https://github.com/nestoroprysk/FunctionComposition
A quick implementation of function iteration with argument forwarding. The helper type is unfortunately necessary because function templates can’t be partially specialised.
#include <functional>
#include <iostream>
using namespace std;
template<int n, typename A>
struct iterate_helper {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(iterate_helper<n - 1, A>(f)(forward<A>(x)));
};
};
template<typename A>
struct iterate_helper<1, A> {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(forward<A>(x));
};
};
template<int n, typename A>
function<A(A)> iterate(function<A(A)> f) {
return iterate_helper<n, A>(f);
}
int succ(int x) {
return x + 1;
}
int main() {
auto add5 = iterate<5>(function<int(int)>(succ));
cout << add5(10) << '\n';
}
You haven't shown the body of F, but if you can modify it so that it mutates the input to form the output then change the signature to:
void F(std::vector<uint8_t>& x);
Thereafter you can implement Fn as:
void Fn(std::vector<uint8_t>& x, size_t n)
{
for (size_t i = 0; i < n; i++)
F(x);
}
The compiler will unroll the loop for you if it is more efficient, but even if it doesn't an increment/compare of a local variable will be orders of magnitude faster than calling F.
You can then explcitly copy-construct new vectors when you actually want to make a copy:
vector<uint8_t> v1 = ...;
vector<uint8_t> v2 = v1; // explicitly take copy
Fn(v2,10);
What about (untested):
template < typename Func, typename T >
T compose_impl( Func &&, T &&x, std::integral_constant<std::size_t, 0> )
{ return std::forward<T>(x); }
template < typename Func, typename T, std::size_t N >
T compose_impl( Func &&f, T &&x, std::integral_constant<std::size_t, N> )
{
return compose_impl( std::forward<Func>(f),
std::forward<Func>(f)(std::forward<T>( x )),
std::integral_constant<std::size_t, N-1>{} );
}
template < std::size_t Repeat = 1, typename Func, typename T >
T compose( Func &&f, T &&x )
{
return compose_impl( std::forward<Func>(f), std::forward<T>(x),
std::integral_constant<std::size_t, Repeat>{} );
}
We can use variadic function templates for multiple functions (untested):
template < typename Func, typename T >
constexpr // C++14 only, due to std::forward not being constexpr in C++11
auto chain_compose( Func &&f, T &&x )
noexcept( noexcept(std::forward<Func>( f )( std::forward<T>(x) )) )
-> decltype( std::forward<Func>(f)(std::forward<T>( x )) )
{ return std::forward<Func>(f)(std::forward<T>( x )); }
template < typename Func1, typename Func2, typename Func3, typename ...RestAndT >
constexpr // C++14 only, due to std::forward
auto chain_compose( Func1 &&f, Func2 &&g, Func3 &&h, RestAndT &&...i_and_x )
noexcept( CanAutoWorkHereOtherwiseDoItYourself )
-> decltype( auto ) // C++14 only
{
return chain_compose( std::forward<Func1>(f),
chain_compose(std::forward<Func2>( g ), std::forward<Func3>( h ),
std::forward<RestAndT>( i_and_x )...) );
}
The upcoming decltype(auto) construct automatically computes the return type from an inlined function. I don't know if there's a similar automatic computation for noexcept