#ifndef META_H_ #define META_H_ #include #include namespace Fastor { //----------------------------------------------------------------------------------------------------------// template< bool B, class T = void > using enable_if_t_ = typename std::enable_if::type; template< bool B, class T = void > using disable_if_t_ = typename std::enable_if::type; template< bool B, class T, class F > using conditional_t_ = typename std::conditional::type; template< class T, class U > constexpr bool is_same_v_ = std::is_same::value; template< class T > constexpr bool is_fundamental_v_ = std::is_fundamental::value; template< class T > constexpr bool is_arithmetic_v_ = std::is_arithmetic::value; template< class T > constexpr bool is_integral_v_ = std::is_integral::value; template< class T > constexpr bool is_floating_v_ = std::is_floating_point::value; template< class T > constexpr bool is_array_v_ = std::is_array::value; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // If BLAS compatible type template< class T > struct is_numeric { static constexpr bool value = false; }; template<> struct is_numeric { static constexpr bool value = true; }; template<> struct is_numeric { static constexpr bool value = true; }; template<> struct is_numeric> { static constexpr bool value = true; }; template<> struct is_numeric> { static constexpr bool value = true; }; template< class T > constexpr bool is_numeric_v_ = is_numeric::value; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // If complex type template< class T > struct is_complex { static constexpr bool value = false; }; template< class T > struct is_complex> { static constexpr bool value = true; }; template< class T > constexpr bool is_complex_v_ = is_complex::value; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // If a type is std::is_fundamental + std::complex + any type that specialises this trait class // This class is provided because the behaviour of any code that specialises std::is_fundamental/arithmetic/ // integral/floating_point is undefined template< class T > struct is_primitive { static constexpr bool value = std::is_fundamental::value || is_numeric::value; }; template< class T > constexpr bool is_primitive_v_ = is_primitive::value; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // Checks if all parameters in a variadic parameter pack are arithmetic template struct is_arithmetic_pack; template struct is_arithmetic_pack { static constexpr bool value = std::is_arithmetic::value && is_arithmetic_pack::value; }; template struct is_arithmetic_pack { static constexpr bool value = std::is_arithmetic::value; }; template static constexpr bool is_arithmetic_pack_v = is_arithmetic_pack::value; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // Remove cv-qualified and their refs template struct remove_cvref_ { using type = T; }; template struct remove_cvref_ { using type = typename remove_cvref_::type; }; template struct remove_cvref_ { using type = typename remove_cvref_::type; }; template struct remove_cvref_ { using type = typename remove_cvref_::type; }; template struct remove_cvref_ { using type = typename remove_cvref_::type; }; template struct remove_cvref_ { using type = typename remove_cvref_::type; }; template using remove_cv_ref_t = typename remove_cvref_::type; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct remove_all { using type = T; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template struct remove_all { using type = typename remove_all::type; }; template using remove_all_t = typename remove_all::type; //----------------------------------------------------------------------------------------------------------// // Sum/multiply reduce all elements of a variadic pack //----------------------------------------------------------------------------------------------------------// // Sum template struct pack_add; template struct pack_add { static const size_t value = Head+pack_add::value;}; template<> struct pack_add<> { static const size_t value = 0;}; // Multiply template struct pack_prod; template struct pack_prod { static const size_t value = Head*pack_prod::value;}; template<> struct pack_prod<> { static const size_t value = 1;}; // Multiply first n elements template struct prod_nel; template struct prod_nel { static const size_t value = prod_nel::value;}; template struct prod_nel<1, First, Rest...> { static const size_t value = pack_prod::value;}; //! Partial product of a sequence up to an index up_to template constexpr inline T partial_prod(const T (&ind)[N], T up_to, T num=0) { return num == up_to ? ind[num] : ind[num]*partial_prod(ind, up_to, num+1); } //! Partial product of a sequence up to an index num from the end template constexpr inline T partial_prod_reverse(const T (&ind)[N], T up_to, T num=N-1) { return num == up_to ? ind[num] : ind[num]*partial_prod_reverse(ind, up_to, num-1); } template constexpr T size_proder_(T one){return one.size();} template constexpr T size_proder_(T one, T two){return one.size()*two.size();} template constexpr T size_proder_(T one, T two, Ts ... ts) {return _proder_(_proder_(one,two),ts...);} //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct get_value; template struct get_value { static const size_t value = get_value::value; }; template struct get_value<1,First,Rest...> { static const size_t value = First; }; template // Work around to avoid compiler errors struct get_value { static const size_t value = 0; }; template constexpr inline auto get_index(Args&&... as) -> decltype(std::get(std::forward_as_tuple(std::forward(as)...))) { return std::get(std::forward_as_tuple(std::forward(as)...)); } template using get_nth_type = typename std::tuple_element>::type; template struct get_all { static const size_t indices[sizeof...(Rest)]; }; //----------------------------------------------------------------------------------------------------------// // comparitors //----------------------------------------------------------------------------------------------------------// template struct is_equal { static constexpr bool value = I == J; }; template static constexpr bool is_equal_v_ = is_equal::value; template struct is_less { static constexpr bool value = (I < J); }; template static constexpr bool is_less_v_ = is_less::value; template struct is_less_equal { static constexpr bool value = I <= J; }; template static constexpr bool is_less_equal_v_ = is_less_equal::value; template struct is_greater { static constexpr bool value = I > J; }; template static constexpr bool is_greater_v_ = is_greater::value; template struct is_greater_equal { static constexpr bool value = I >= J; }; template static constexpr bool is_greater_equal_v_ = is_greater_equal::value; //----------------------------------------------------------------------------------------------------------// // min-max //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct meta_min; template struct meta_min { static constexpr size_t pval = meta_min::value; static const size_t value = (pval <= meta_min::value) ? pval : meta_min::value; }; template struct meta_min { static const size_t value = (m<=n) ? m : n; }; template struct meta_max; template struct meta_max { static constexpr size_t pval = meta_max::value; static const size_t value = (pval >= meta_max::value) ? pval : meta_max::value; }; template struct meta_max { static const size_t value = (m>=n) ? m : n; }; namespace internal { // namespace to avoid clash with MSVC macros template constexpr FASTOR_INLINE T min_(const T a, const T b) {return a < b ? a : b;} template constexpr FASTOR_INLINE T max_(const T a, const T b) {return a > b ? a : b;} } //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct meta_argmin; template struct meta_argmin { static constexpr size_t pval = meta_min::value; static const size_t value = (pval <= meta_min::value) ? meta_argmin::value : meta_argmin::value+1; }; template struct meta_argmin { static const size_t value = (m struct meta_argmax; template struct meta_argmax { static constexpr size_t pval = meta_max::value; static const size_t value = (pval >= meta_max::value) ? meta_argmax::value : meta_argmax::value+1; }; template struct meta_argmax { static const size_t value = (m>n) ? 0 : 1; }; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // square/cube //----------------------------------------------------------------------------------------------------------// namespace internal { template struct meta_square { static constexpr size_t value = Val*Val;}; template struct meta_cube { static constexpr size_t value = Val*Val*Val;}; } //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// //square root of integers at compile time, use like meta_sqrt<36>::ret template Y))) > // use ?: instead of || just to shut up a gcc 4.3 warning class meta_sqrt { enum { MidX = (InfX+SupX)/2, TakeInf = MidX*MidX > Y ? 1 : 0, NewInf = int(TakeInf) ? InfX : int(MidX), NewSup = int(TakeInf) ? int(MidX) : SupX }; public: enum { ret = meta_sqrt::ret }; }; template class meta_sqrt { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; }; //----------------------------------------------------------------------------------------------------------// } // end of namespace Fastor #endif // META_H_