Commit 34885294 authored by Praetorius, Simon's avatar Praetorius, Simon

Merge branch 'issue/functor_expression_args' into 'master'

Issue/functor expression args

Correct a bug in the functor expressions with variadic arguments, especially a bug in `traits/basic.hpp` when importing `boost::mpl` constants/classes.

See merge request !1
parents 77592d44 7f00308f
......@@ -41,10 +41,10 @@ namespace AMDiS
struct is_constant : is_numeric<T>::type {};
template<typename T>
struct is_constant<WorldVector<T> > : boost::mpl::bool_<true> {};
struct is_constant<WorldVector<T> > : bool_<true> {};
template<typename T>
struct is_constant<WorldMatrix<T> > : boost::mpl::bool_<true> {};
struct is_constant<WorldMatrix<T> > : bool_<true> {};
// type-traits for terms
......@@ -56,18 +56,18 @@ namespace AMDiS
// type-traits for arguments, filter terms and constants
// ___________________________________________________________________________
template<typename T>
struct is_valid_arg : boost::mpl::or_
struct is_valid_arg : or_
<
typename is_expr<T>::type,
typename is_constant<T>::type
>::type {};
template<typename T1, typename T2>
struct is_valid_arg2 : boost::mpl::and_
struct is_valid_arg2 : and_
<
typename is_valid_arg<T1>::type,
typename is_valid_arg<T2>::type,
typename boost::mpl::or_
typename or_
<
typename is_expr<T1>::type,
typename is_expr<T2>::type
......@@ -75,12 +75,12 @@ namespace AMDiS
>::type {};
template<typename T1, typename T2, typename T3>
struct is_valid_arg3 : boost::mpl::and_
struct is_valid_arg3 : and_
<
typename is_valid_arg<T1>::type,
typename is_valid_arg<T2>::type,
typename is_valid_arg<T3>::type,
typename boost::mpl::or_
typename or_
<
typename is_expr<T1>::type,
typename is_expr<T2>::type,
......@@ -92,7 +92,7 @@ namespace AMDiS
// expressions
template < typename T >
struct category<T, typename boost::enable_if< typename is_expr<T>::type >::type >
struct category<T, typename enable_if< typename is_expr<T>::type >::type >
{
typedef tag::expression tag;
typedef typename T::value_type value_type;
......
......@@ -5,7 +5,7 @@
* Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
* Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
*
* Authors:
* Authors:
* Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
......@@ -15,7 +15,7 @@
* This file is part of AMDiS
*
* See also license.opensource.txt in the distribution.
*
*
******************************************************************************/
......@@ -34,10 +34,10 @@
#include <boost/static_assert.hpp>
#include <tuple>
#include <utility>
#include <utility>
#include <functional>
namespace AMDiS
namespace AMDiS
{
/// for_each for std::tuple
template<std::size_t I = 0, typename FuncT, typename... Tp>
......@@ -54,8 +54,8 @@ namespace AMDiS
template<int I>
using int_ = std::integral_constant<int, I>;
namespace traits
{
/// get the degree of a functor by combining the degrees of the arguments
......@@ -65,14 +65,14 @@ namespace AMDiS
template<typename... Int>
static int eval(F f, Int... d) { return 0; }
};
template<typename F>
struct functor_degree<F, typename enable_if< boost::is_base_of<FunctorBase, F> >::type >
{
template<typename... Int>
static int eval(F f, Int... d) { return f.getDegree(d...); }
};
// specialization for abstract-functions
template<typename R, typename... Args>
struct functor_degree<AbstractFunction<R, Args...> >
......@@ -80,28 +80,28 @@ namespace AMDiS
template<typename... Int>
static int eval(AbstractFunction<R, Args...> const& fct, Int... d) { return fct.getDegree(); }
};
template<typename R, typename Arg0, typename Arg1>
struct functor_degree<BinaryAbstractFunction<R, Arg0, Arg1> >
{
template<typename... Int>
static int eval(BinaryAbstractFunction<R, Arg0, Arg1> const& fct, Int... d) { return fct.getDegree(); }
};
template<typename R, typename Arg0, typename Arg1, typename Arg2>
struct functor_degree<TertiaryAbstractFunction<R, Arg0, Arg1, Arg2> >
{
template<typename... Int>
static int eval(TertiaryAbstractFunction<R, Arg0, Arg1, Arg2> const& fct, Int... d) { return fct.getDegree(); }
};
} // end namespace traits
namespace result_of
{
{
template<class T>
struct void_{ typedef void type; };
/// extract result type from function pointers
template <class FPtr>
struct Function;
......@@ -117,7 +117,7 @@ namespace AMDiS
{
typedef R type;
};
template <class T>
typename Function<T>::type function_helper(T);
......@@ -127,7 +127,7 @@ namespace AMDiS
{
typedef decltype(function_helper(&F::operator())) type;
};
template <class R, class... As>
struct Functor<std::function<R(As...)> >
{
......@@ -139,50 +139,50 @@ namespace AMDiS
{
typedef typename F::value_type type;
};
template <class F>
struct Functor<F, typename void_<typename F::result_type>::type>
{
typedef typename F::result_type type;
};
} // end namespace result_of
namespace detail
namespace detail
{
/// Functor that initializes the feSpace list
template<typename List>
struct InsertFeSpaces
struct InsertFeSpaces
{
List& feSpaces;
InsertFeSpaces(List& feSpaces_) : feSpaces(feSpaces_) {};
template<typename Term>
void operator()(Term& term) {
term.insertFeSpaces(feSpaces);
}
};
/// Functor that is called on each term to initialize it on an element
template<typename OT>
struct InitElement
struct InitElement
{
OT* ot;
const ElInfo *elInfo, *elInfo2;
SubAssembler* subAssembler;
Quadrature *quad;
const BasisFunction *basisFct;
InitElement(OT* ot_, const ElInfo* elInfo_, SubAssembler* subAssembler_, Quadrature *quad_, const BasisFunction *basisFct_)
: ot(ot_), elInfo(elInfo_), elInfo2(NULL), subAssembler(subAssembler_),
quad(quad_), basisFct(basisFct_) {}
InitElement(OT* ot_, const ElInfo* smallElInfo_, const ElInfo* largeElInfo_, SubAssembler* subAssembler_, Quadrature *quad_, const BasisFunction *basisFct_)
: ot(ot_), elInfo(smallElInfo_), elInfo2(largeElInfo_), subAssembler(subAssembler_),
quad(quad_), basisFct(basisFct_) {}
template<typename Term>
void operator()(Term& term) {
if (elInfo2)
......@@ -191,21 +191,21 @@ namespace AMDiS
term.initElement(ot, elInfo, subAssembler, quad, basisFct);
}
};
} // end namespace detail
/// Operator term with arbitrary number of sub-term (expressions)
template <class... Terms>
struct LazyOperatorTerms : public LazyOperatorTermBase
{
std::tuple<Terms...> term_tuple;
template <class... Terms_>
LazyOperatorTerms(Terms_... terms_)
: term_tuple(terms_...)
: term_tuple(terms_...)
{ }
template <class List>
inline void insertFeSpaces(List& feSpaces)
{
......@@ -214,7 +214,7 @@ namespace AMDiS
template <class OT>
inline void initElement(OT* ot, const ElInfo* elInfo,
SubAssembler* subAssembler, Quadrature *quad,
SubAssembler* subAssembler, Quadrature *quad,
const BasisFunction *basisFct = NULL)
{
for_each(term_tuple, detail::InitElement<OT>(ot, elInfo, subAssembler, quad, basisFct));
......@@ -222,20 +222,20 @@ namespace AMDiS
template <class OT>
inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo,
SubAssembler* subAssembler, Quadrature *quad,
SubAssembler* subAssembler, Quadrature *quad,
const BasisFunction *basisFct = NULL)
{
for_each(term_tuple, detail::InitElement<OT>(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct));
}
inline double operator()(const int& iq) const;
};
// the expressions
// _____________________________________________________________________________
namespace expressions
namespace expressions
{
/// Functor that takes arbitrary number of arguments
template <class F, class... Terms>
......@@ -243,29 +243,29 @@ namespace AMDiS
{
typedef LazyOperatorTerms<Terms...> super;
static const int N = sizeof...(Terms);
typedef typename result_of::Functor<F>::type value_type;
BOOST_STATIC_ASSERT_MSG( (!boost::is_same<value_type, traits::no_valid_type>::value), "********** ERROR: You have to define a result_type for your Functor **********" );
F f; ///< the functor
template <class... Terms_>
FunctionN(F const& f_, Terms_... terms_)
: super(terms_...), f(f_) {}
// call f.getDegree() function
// call f.getDegree() function
template<int I, class... Terms_>
int getDegree(int_<I>, Terms_&&... terms) const
{
return getDegree(int_<I-1>(), std::get<I-1>(super::term_tuple), std::forward<Terms_>(terms)...);
}
template <class... Terms_>
int getDegree(int_<0>, Terms_&&... terms) const
{
return traits::functor_degree<F>::eval(f, terms.getDegree()...);
}
int getDegree() const
{
return getDegree(int_<N>());
......@@ -277,42 +277,42 @@ namespace AMDiS
{
return eval(iq, int_<I-1>(), std::get<I-1>(super::term_tuple), std::forward<Terms_>(terms)...);
}
template <class... Terms_>
inline value_type eval(const int& iq, int_<0>, Terms_&&... terms) const
{
return f(terms(iq)...); // f(term1(iq), term2(iq), term3(iq),...)
}
inline value_type operator()(const int& iq) const { return eval(iq, int_<N>()); }
template <int I>
std::string str(int_<I>) const
{
return str(int_<I-1>()) + ", " + std::get<I>(super::term_tuple).str();
}
std::string str(int_<0>) const
{
return std::get<0>(super::term_tuple).str();
}
std::string str() const { return std::string("F(") + str(int_<N-1>()) + ")"; }
};
template<typename F, typename Term>
using Function1 = FunctionN<F, Term>;
template<typename F, typename Term1, typename Term2>
using Function2 = FunctionN<F, Term1, Term2>;
template<typename F, typename Term1, typename Term2, typename Term3>
using Function3 = FunctionN<F, Term1, Term2, Term3>;
template<typename F, typename Term1, typename Term2, typename Term3, typename Term4>
using Function4 = FunctionN<F, Term1, Term2, Term3, Term4>;
/// A wrapper functor for AMDiS::AbstractFunctions
template <class TOut, class TIn>
struct Wrapper : public FunctorBase
......@@ -320,63 +320,63 @@ namespace AMDiS
typedef TOut result_type;
Wrapper(AbstractFunction<TOut, TIn>* fct_) : fct(fct_) {}
int getDegree(int degree) const { return fct->getDegree(); }
TOut operator()(const TIn& x) const
TOut operator()(const TIn& x) const
{
return (*fct)(x);
}
protected:
AbstractFunction<TOut, TIn>* fct;
};
template <int D, class F>
struct DegreeWrapper : public FunctorBase
{
typedef typename result_of::Functor<F>::type result_type;
DegreeWrapper(F&& fct_) : fct(fct_) {}
DegreeWrapper(F const& fct_) : fct(fct_) {}
template <class... Int>
int getDegree(Int... degrees) const { return D; }
template <class... Ts>
result_type operator()(Ts&&... args) const
result_type operator()(Ts&&... args) const
{
return fct(args...);
return fct(std::forward<Ts>(args)...);
}
protected:
F fct;
};
template <class F, class DegF>
struct DegreeWrapper2 : public FunctorBase
{
{
typedef typename result_of::Functor<F>::type result_type;
DegreeWrapper2(F&& fct_, DegF&& degfct_)
DegreeWrapper2(F const& fct_, DegF const& degfct_)
: fct(fct_), degfct(degfct_) {}
template <class... Int>
int getDegree(Int... degrees) const
{
return degfct(degrees...);
int getDegree(Int... degrees) const
{
return degfct(degrees...);
}
template <class... Ts>
result_type operator()(Ts&&... args) const
result_type operator()(Ts&&... args) const
{
return fct(args...);
return fct(std::forward<Ts>(args)...);
}
protected:
F fct;
DegF degfct;
};
} // end namespace expressions
......@@ -387,16 +387,16 @@ namespace AMDiS
struct FunctionN : std::enable_if
<
and_< typename traits::is_valid_arg<Terms>::type... >::value,
expressions::FunctionN< F, typename traits::to_expr<Terms>::type...>
expressions::FunctionN< F, typename traits::to_expr<Terms>::type...>
> {};
template <typename F, typename Term>
struct FunctionN<F, Term> : std::enable_if
<
traits::is_valid_arg<Term>::value,
expressions::FunctionN< F, typename traits::to_expr<Term>::type>
expressions::FunctionN< F, typename traits::to_expr<Term>::type>
> {};
} // end namespace result_of
// generator-functions
......@@ -404,34 +404,34 @@ namespace AMDiS
template<typename F, typename... Terms>
inline typename result_of::FunctionN<F, Terms...>::type
function_(F const& f, Terms... ts)
function_(F const& f, Terms... ts)
{
return expressions::FunctionN<F, typename traits::to_expr<Terms>::to::type...>
(f, traits::to_expr<Terms>::to::get(ts)...);
(f, traits::to_expr<Terms>::to::get(ts)...);
}
template<typename F, typename... Terms>
inline typename result_of::FunctionN<F, Terms...>::type
func(F const& f, Terms... ts)
func(F const& f, Terms... ts)
{
return expressions::FunctionN<F, typename traits::to_expr<Terms>::to::type...>
(f, traits::to_expr<Terms>::to::get(ts)...);
(f, traits::to_expr<Terms>::to::get(ts)...);
}
template<typename F, typename Term0, typename... Terms>
inline typename result_of::FunctionN<F, Term0, Terms...>::type
eval(F const& f, Term0 t0, Terms... ts)
eval(F const& f, Term0 t0, Terms... ts)
{
return expressions::FunctionN<F, typename traits::to_expr<Term0>::to::type,
return expressions::FunctionN<F, typename traits::to_expr<Term0>::to::type,
typename traits::to_expr<Terms>::to::type...>
(f, traits::to_expr<Term0>::to::get(t0), traits::to_expr<Terms>::to::get(ts)...);
(f, traits::to_expr<Term0>::to::get(t0), traits::to_expr<Terms>::to::get(ts)...);
}
// function wrapper for abstract functions
// _____________________________________________________________________________
template<typename TOut, typename TIn>
inline expressions::Wrapper<TOut,TIn> wrap(AbstractFunction<TOut, TIn>* fct)
inline expressions::Wrapper<TOut,TIn> wrap(AbstractFunction<TOut, TIn>* fct)
{ return expressions::Wrapper<TOut,TIn>(fct); }
template <int Degree, class F>
......@@ -440,14 +440,14 @@ namespace AMDiS
{
return expressions::DegreeWrapper<Degree, F>(fct);
}
template <class F, class DegF>
inline expressions::DegreeWrapper2<F, DegF>
deg(F const& fct, DegF const& degfct)
{
return expressions::DegreeWrapper2<F, DegF>(fct, degfct);
}
} // end namespace AMDiS
#endif // AMDIS_FUNCTOR_N_EXPRESSION_HPP
......@@ -35,7 +35,7 @@
#include <boost/utility/enable_if.hpp>
#endif
#ifdef HAS_CPP11
#ifdef HAS_CXX11
#include <type_traits>
#endif
......@@ -44,11 +44,52 @@ namespace AMDiS
// introduce some shortcuts for boost::mpl
// ---------------------------------------
#ifdef HAS_CXX11
template <bool B>
using bool_ = std::integral_constant<bool, B>;
using true_ = bool_<true>;
using false_ = bool_<false>;
namespace aux
{
template <class... Ts> struct or_;
template <class T0, class... Ts>
struct or_<T0, Ts...> : bool_<T0::value || or_<Ts...>::value> {};
template <>
struct or_<> : false_ {};
template <class... Ts> struct and_;
template <class T0, class... Ts>
struct and_<T0, Ts...> : bool_<T0::value && and_<Ts...>::value> {};
template <>
struct and_<> : true_ {};
} // end namespace aux
template <class... Ts>
using and_ = aux::and_<Ts...>;
template <class... Ts>
using or_ = aux::or_<Ts...>;
template <class A>
using not_ = bool_<!(A::value)>;
#else
using boost::mpl::bool_;
using boost::mpl::true_;
using boost::mpl::false_;
using boost::mpl::and_;
using boost::mpl::or_;
using boost::mpl::not_;
#endif
using boost::enable_if;
using boost::enable_if_c;
......@@ -74,13 +115,8 @@ namespace AMDiS
boost::is_same< typename mtl::Addable<A,B>::result_type,
no_valid_type > > {};
#ifdef HAS_CPP11
template <typename T>
struct is_trivially_copyable : std::is_trivially_copyable<T> {};
#else
template <typename T>
struct is_trivially_copyable : boost::is_pod<T> {};
#endif
template <class T, T A, T B>
struct equal : boost::mpl::if_c< A == B, true_, false_ > {};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment