1 // Copyright Jim Bosch 2010-2012.
2 // Copyright Stefan Seefeld 2016.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef boost_python_numpy_invoke_matching_hpp_
8 #define boost_python_numpy_invoke_matching_hpp_
11 * @brief Template invocation based on dtype matching.
14 #include <boost/python/numpy/dtype.hpp>
15 #include <boost/python/numpy/ndarray.hpp>
16 #include <boost/mpl/integral_c.hpp>
18 namespace boost { namespace python { namespace numpy {
22 struct BOOST_NUMPY_DECL add_pointer_meta
27 typedef typename boost::add_pointer<T>::type type;
32 struct BOOST_NUMPY_DECL dtype_template_match_found {};
33 struct BOOST_NUMPY_DECL nd_template_match_found {};
35 template <typename Function>
36 struct dtype_template_invoker
40 void operator()(T *) const
42 if (dtype::get_builtin<T>() == m_dtype)
44 m_func.Function::template apply<T>();
45 throw dtype_template_match_found();
49 dtype_template_invoker(dtype const & dtype_, Function func)
50 : m_dtype(dtype_), m_func(func) {}
53 dtype const & m_dtype;
57 template <typename Function>
58 struct dtype_template_invoker< boost::reference_wrapper<Function> >
62 void operator()(T *) const
64 if (dtype::get_builtin<T>() == m_dtype)
66 m_func.Function::template apply<T>();
67 throw dtype_template_match_found();
71 dtype_template_invoker(dtype const & dtype_, Function & func)
72 : m_dtype(dtype_), m_func(func) {}
75 dtype const & m_dtype;
79 template <typename Function>
80 struct nd_template_invoker
83 void operator()(boost::mpl::integral_c<int,N> *) const
87 m_func.Function::template apply<N>();
88 throw nd_template_match_found();
92 nd_template_invoker(int nd, Function func) : m_nd(nd), m_func(func) {}
99 template <typename Function>
100 struct nd_template_invoker< boost::reference_wrapper<Function> >
103 void operator()(boost::mpl::integral_c<int,N> *) const
107 m_func.Function::template apply<N>();
108 throw nd_template_match_found();
112 nd_template_invoker(int nd, Function & func) : m_nd(nd), m_func(func) {}
119 } // namespace boost::python::numpy::detail
121 template <typename Sequence, typename Function>
122 void invoke_matching_nd(int nd, Function f)
124 detail::nd_template_invoker<Function> invoker(nd, f);
125 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
126 catch (detail::nd_template_match_found &) { return;}
127 PyErr_SetString(PyExc_TypeError, "number of dimensions not found in template list.");
128 python::throw_error_already_set();
131 template <typename Sequence, typename Function>
132 void invoke_matching_dtype(dtype const & dtype_, Function f)
134 detail::dtype_template_invoker<Function> invoker(dtype_, f);
135 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
136 catch (detail::dtype_template_match_found &) { return;}
137 PyErr_SetString(PyExc_TypeError, "dtype not found in template list.");
138 python::throw_error_already_set();
144 template <typename T, typename Function>
145 struct array_template_invoker_wrapper_2
148 void apply() const { m_func.Function::template apply<T,N>();}
149 array_template_invoker_wrapper_2(Function & func) : m_func(func) {}
155 template <typename DimSequence, typename Function>
156 struct array_template_invoker_wrapper_1
158 template <typename T>
159 void apply() const { invoke_matching_nd<DimSequence>(m_nd, array_template_invoker_wrapper_2<T,Function>(m_func));}
160 array_template_invoker_wrapper_1(int nd, Function & func) : m_nd(nd), m_func(func) {}
167 template <typename DimSequence, typename Function>
168 struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper<Function> >
169 : public array_template_invoker_wrapper_1< DimSequence, Function >
171 array_template_invoker_wrapper_1(int nd, Function & func)
172 : array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {}
175 } // namespace boost::python::numpy::detail
177 template <typename TypeSequence, typename DimSequence, typename Function>
178 void invoke_matching_array(ndarray const & array_, Function f)
180 detail::array_template_invoker_wrapper_1<DimSequence,Function> wrapper(array_.get_nd(), f);
181 invoke_matching_dtype<TypeSequence>(array_.get_dtype(), wrapper);
184 }}} // namespace boost::python::numpy