2018-01-15 18:31:47 +01:00
|
|
|
|
|
|
|
#ifndef __arith_h__
|
|
|
|
#define __arith_h__
|
|
|
|
|
2018-11-26 12:10:38 +01:00
|
|
|
#include <functional>
|
|
|
|
|
2018-07-17 20:01:25 +02:00
|
|
|
namespace MultiArrayTools
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-07-17 20:01:25 +02:00
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
struct ArgPack
|
|
|
|
{
|
|
|
|
template <class F, class Tuple, typename... As>
|
|
|
|
static inline auto mk(const Tuple& tp, As... as)
|
2018-07-20 19:13:42 +02:00
|
|
|
-> decltype(ArgPack<N-1>::template mk<F,Tuple,decltype(std::get<N>(tp)),As...>(tp, std::get<N>(tp), as...))
|
2018-07-17 20:01:25 +02:00
|
|
|
{
|
2018-07-20 19:13:42 +02:00
|
|
|
return ArgPack<N-1>::template mk<F,Tuple,decltype(std::get<N>(tp)),As...>(tp, std::get<N>(tp), as...);
|
2018-07-17 20:01:25 +02:00
|
|
|
}
|
2018-11-26 12:10:38 +01:00
|
|
|
|
|
|
|
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...);
|
|
|
|
}
|
2018-07-17 20:01:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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...);
|
|
|
|
}
|
2018-11-26 12:10:38 +01:00
|
|
|
|
|
|
|
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...);
|
|
|
|
}
|
2018-07-17 20:01:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, class F, typename... As>
|
|
|
|
struct StaticFunctionBase
|
|
|
|
{
|
|
|
|
static constexpr bool FISSTATIC = true;
|
|
|
|
typedef T value_type;
|
2021-01-18 19:00:12 +01:00
|
|
|
typedef F function;
|
|
|
|
|
2018-07-17 20:01:25 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
};
|
2018-11-26 12:10:38 +01:00
|
|
|
|
|
|
|
|
2018-01-15 18:31:47 +01:00
|
|
|
// OPERATIONS (STATIC)
|
2018-07-17 20:01:25 +02:00
|
|
|
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;
|
|
|
|
}
|
2021-01-18 19:00:12 +01:00
|
|
|
|
|
|
|
static inline T selfApply(T& a1, const T& a2)
|
|
|
|
{
|
|
|
|
return a1 = a2;
|
|
|
|
}
|
2018-07-17 20:01:25 +02:00
|
|
|
};
|
2019-07-24 18:49:53 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2020-12-07 13:46:01 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2019-07-24 18:49:53 +02:00
|
|
|
template <typename T>
|
|
|
|
using plus = plusx<T,T>;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
using minus = minusx<T,T>;
|
2018-07-17 20:01:25 +02:00
|
|
|
|
2019-07-24 18:49:53 +02:00
|
|
|
template <typename T>
|
|
|
|
using multiplies = multipliesx<T,T>;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
using divides = dividesx<T,T>;
|
|
|
|
|
|
|
|
/*
|
2018-01-15 18:31:47 +01:00
|
|
|
template <typename T>
|
2018-07-19 19:29:52 +02:00
|
|
|
struct plus : public StaticFunctionBase<T, plus<T>, T, T>
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-03-21 19:18:57 +01:00
|
|
|
static constexpr bool FISSTATIC = true;
|
2018-08-20 17:50:04 +02:00
|
|
|
using StaticFunctionBase<T, plus<T>, T, T>::apply;
|
2018-03-21 19:18:57 +01:00
|
|
|
|
2018-02-13 18:18:17 +01:00
|
|
|
static inline T apply(T a1, T a2)
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-02-13 18:18:17 +01:00
|
|
|
return a1 + a2;
|
2018-01-15 18:31:47 +01:00
|
|
|
}
|
2019-02-19 16:20:38 +01:00
|
|
|
|
|
|
|
static inline T& selfApply(T& a1, const T& a2)
|
|
|
|
{
|
|
|
|
return a1 += a2;
|
|
|
|
}
|
2018-01-15 18:31:47 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
2018-07-19 19:29:52 +02:00
|
|
|
struct minus : public StaticFunctionBase<T, minus<T>, T, T>
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-03-21 19:18:57 +01:00
|
|
|
static constexpr bool FISSTATIC = true;
|
2018-08-20 17:50:04 +02:00
|
|
|
using StaticFunctionBase<T, minus<T>, T, T>::apply;
|
2018-03-21 19:18:57 +01:00
|
|
|
|
2018-02-13 18:18:17 +01:00
|
|
|
static inline T apply(T a1, T a2)
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-02-13 18:18:17 +01:00
|
|
|
return a1 - a2;
|
2018-01-15 18:31:47 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
2018-07-19 19:29:52 +02:00
|
|
|
struct multiplies : public StaticFunctionBase<T, multiplies<T>, T, T>
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-03-21 19:18:57 +01:00
|
|
|
static constexpr bool FISSTATIC = true;
|
2018-08-20 17:50:04 +02:00
|
|
|
using StaticFunctionBase<T, multiplies<T>, T, T>::apply;
|
2018-03-21 19:18:57 +01:00
|
|
|
|
2018-02-13 18:18:17 +01:00
|
|
|
static inline T apply(T a1, T a2)
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-02-13 18:18:17 +01:00
|
|
|
return a1 * a2;
|
2018-01-15 18:31:47 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
2018-07-19 19:29:52 +02:00
|
|
|
struct divides : public StaticFunctionBase<T, divides<T>, T, T>
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-03-21 19:18:57 +01:00
|
|
|
static constexpr bool FISSTATIC = true;
|
2018-08-20 17:50:04 +02:00
|
|
|
using StaticFunctionBase<T, divides<T>, T, T>::apply;
|
2018-03-21 19:18:57 +01:00
|
|
|
|
2018-02-13 18:18:17 +01:00
|
|
|
static inline T apply(T a1, T a2)
|
2018-01-15 18:31:47 +01:00
|
|
|
{
|
2018-02-13 18:18:17 +01:00
|
|
|
return a1 / a2;
|
2018-01-15 18:31:47 +01:00
|
|
|
}
|
|
|
|
};
|
2019-07-24 18:49:53 +02:00
|
|
|
*/
|
2018-11-26 12:10:38 +01:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-07-19 19:29:52 +02:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-03-21 19:18:57 +01:00
|
|
|
/*
|
2018-03-19 18:38:53 +01:00
|
|
|
template <typename T, class Func>
|
|
|
|
struct dynamic_function
|
|
|
|
{
|
2018-03-21 19:18:57 +01:00
|
|
|
static constexpr bool FISSTATIC = false;
|
|
|
|
|
2018-03-19 18:38:53 +01:00
|
|
|
template <typename... Us>
|
2018-03-21 19:18:57 +01:00
|
|
|
inline T apply(Us... args)
|
2018-03-19 18:38:53 +01:00
|
|
|
{
|
|
|
|
return f(args...);
|
|
|
|
}
|
2018-03-21 19:18:57 +01:00
|
|
|
};
|
|
|
|
*/
|
2018-01-15 18:31:47 +01:00
|
|
|
} // end namespace MultiArrayHelper
|
|
|
|
|
|
|
|
#endif
|