#ifndef __arith_h__ #define __arith_h__ #include <functional> namespace MultiArrayTools { template <size_t N> struct ArgPack { template <class F, class Tuple, typename... As> static inline auto mk(const Tuple& tp, As... as) -> decltype(ArgPack<N-1>::template mk<F,Tuple,decltype(std::get<N>(tp)),As...>(tp, std::get<N>(tp), as...)) { return ArgPack<N-1>::template mk<F,Tuple,decltype(std::get<N>(tp)),As...>(tp, std::get<N>(tp), as...); } template <class F, class Tuple, typename... As> static inline auto mkd(const F& ff, const Tuple& tp, As... as) -> decltype(ArgPack<N-1>::template mkd<F,Tuple,decltype(std::get<N>(tp)),As...>(ff, tp, std::get<N>(tp), as...)) { return ArgPack<N-1>::template mkd<F,Tuple,decltype(std::get<N>(tp)),As...>(ff, tp, std::get<N>(tp), as...); } }; template <> struct ArgPack<0> { template <class F, class Tuple, typename... As> static inline auto mk(const Tuple& tp, As... as) -> decltype(F::apply(std::get<0>(tp), as...)) { return F::apply(std::get<0>(tp), as...); } template <class F, class Tuple, typename... As> static inline auto mkd(const F& ff, const Tuple& tp, As... as) -> decltype(ff(std::get<0>(tp), as...)) { return ff(std::get<0>(tp), as...); } }; template <typename T, class F, typename... As> struct StaticFunctionBase { static constexpr bool FISSTATIC = true; typedef T value_type; typedef F function; template <class... Ops> static auto mk(const Ops&... ops) -> Operation<T,F,Ops...> { return Operation<T,F,Ops...>(ops...); } static inline T apply(const std::tuple<As...>& arg) { return ArgPack<sizeof...(As)-1>::template mk<F,std::tuple<As...> >(arg); } }; // OPERATIONS (STATIC) template <typename T> struct identity : public StaticFunctionBase<T, identity<T>, T> { //static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, identity<T>, T>::apply; static inline T apply(T a) { return a; } static inline T selfApply(T& a1, const T& a2) { return a1 = a2; } }; template <typename T, typename U> using plusv = decltype(std::declval<T>()+std::declval<U>()); template <typename T, typename U> using minusv = decltype(std::declval<T>()-std::declval<U>()); template <typename T, typename U> using multipliesv = decltype(std::declval<T>()*std::declval<U>()); template <typename T, typename U> using dividesv = decltype(std::declval<T>()/std::declval<U>()); template <typename T, typename U> struct plusx : public StaticFunctionBase<plusv<T,U>, plusx<T,U>, T, U> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<plusv<T,U>, plusx<T,U>, T, U>::apply; static inline plusv<T,U> apply(T a1, U a2) { return a1 + a2; } static inline T& selfApply(T& a1, const T& a2) { return a1 += a2; } }; template <typename T, typename U> struct minusx : public StaticFunctionBase<minusv<T,U>, minusx<T,U>, T, U> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<minusv<T,U>, minusx<T,U>, T, U>::apply; static inline plusv<T,U> apply(T a1, U a2) { return a1 - a2; } }; template <typename T, typename U> struct multipliesx : public StaticFunctionBase<multipliesv<T,U>, multipliesx<T,U>, T, U> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<multipliesv<T,U>, multipliesx<T,U>, T, U>::apply; static inline multipliesv<T,U> apply(T a1, U a2) { return a1 * a2; } }; template <typename T, typename U> struct dividesx : public StaticFunctionBase<dividesv<T,U>, dividesx<T,U>, T, U> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<dividesv<T,U>, dividesx<T,U>, T, U>::apply; static inline dividesv<T,U> apply(T a1, U a2) { return a1 / a2; } }; template <typename T> struct negate : public StaticFunctionBase<T, negate<T>, T> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, negate<T>, T>::apply; static inline T apply(T a) { return -a; } }; template <typename T> using plus = plusx<T,T>; template <typename T> using minus = minusx<T,T>; template <typename T> using multiplies = multipliesx<T,T>; template <typename T> using divides = dividesx<T,T>; /* template <typename T> struct plus : public StaticFunctionBase<T, plus<T>, T, T> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, plus<T>, T, T>::apply; static inline T apply(T a1, T a2) { return a1 + a2; } static inline T& selfApply(T& a1, const T& a2) { return a1 += a2; } }; template <typename T> struct minus : public StaticFunctionBase<T, minus<T>, T, T> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, minus<T>, T, T>::apply; static inline T apply(T a1, T a2) { return a1 - a2; } }; template <typename T> struct multiplies : public StaticFunctionBase<T, multiplies<T>, T, T> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, multiplies<T>, T, T>::apply; static inline T apply(T a1, T a2) { return a1 * a2; } }; template <typename T> struct divides : public StaticFunctionBase<T, divides<T>, T, T> { static constexpr bool FISSTATIC = true; using StaticFunctionBase<T, divides<T>, T, T>::apply; static inline T apply(T a1, T a2) { return a1 / a2; } }; */ // OPERATIONS (STATIC) template <typename R, typename... Args> class function { public: static constexpr bool FISSTATIC = false; private: std::function<R(Args...)> mF; public: function() = default; function(const std::function<R(Args...)>& in) : mF(in) {} inline R operator()(const Args&... args) { return mF(args...); } inline R operator()(const std::tuple<Args...>& args) { return ArgPack<sizeof...(Args)-1>::template mkd<std::function<R(Args...)>,std::tuple<Args...>>>(mF, args); } }; #include <cmath> #define regFunc1(fff) template <typename T>\ struct x_##fff : public StaticFunctionBase<T, x_##fff<T>, T> {\ static constexpr bool FISSTATIC = true;\ static inline T apply(T a){\ return fff(a); } }; #include "extensions/math.h" #undef regFunc1 template <size_t N> struct x_ipow { static constexpr bool FISSTATIC = true; template <typename T> static inline T apply(T a) { return a * x_ipow<N-1>::apply(a); } }; template <> struct x_ipow<0> { static constexpr bool FISSTATIC = true; template <typename T> static inline T apply(T a) { return a; } }; /* template <typename T, class Func> struct dynamic_function { static constexpr bool FISSTATIC = false; template <typename... Us> inline T apply(Us... args) { return f(args...); } }; */ } // end namespace MultiArrayHelper #endif