// Copyright Jim Bosch 2010-2012. // Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef boost_python_numpy_invoke_matching_hpp_ #define boost_python_numpy_invoke_matching_hpp_ /** * @brief Template invocation based on dtype matching. */ #include #include #include namespace boost { namespace python { namespace numpy { namespace detail { struct add_pointer_meta { template struct apply { typedef typename boost::add_pointer::type type; }; }; struct dtype_template_match_found {}; struct nd_template_match_found {}; template struct dtype_template_invoker { template void operator()(T *) const { if (dtype::get_builtin() == m_dtype) { m_func.Function::template apply(); throw dtype_template_match_found(); } } dtype_template_invoker(dtype const & dtype_, Function func) : m_dtype(dtype_), m_func(func) {} private: dtype const & m_dtype; Function m_func; }; template struct dtype_template_invoker< boost::reference_wrapper > { template void operator()(T *) const { if (dtype::get_builtin() == m_dtype) { m_func.Function::template apply(); throw dtype_template_match_found(); } } dtype_template_invoker(dtype const & dtype_, Function & func) : m_dtype(dtype_), m_func(func) {} private: dtype const & m_dtype; Function & m_func; }; template struct nd_template_invoker { template void operator()(boost::mpl::integral_c *) const { if (m_nd == N) { m_func.Function::template apply(); throw nd_template_match_found(); } } nd_template_invoker(int nd, Function func) : m_nd(nd), m_func(func) {} private: int m_nd; Function m_func; }; template struct nd_template_invoker< boost::reference_wrapper > { template void operator()(boost::mpl::integral_c *) const { if (m_nd == N) { m_func.Function::template apply(); throw nd_template_match_found(); } } nd_template_invoker(int nd, Function & func) : m_nd(nd), m_func(func) {} private: int m_nd; Function & m_func; }; } // namespace boost::python::numpy::detail template void invoke_matching_nd(int nd, Function f) { detail::nd_template_invoker invoker(nd, f); try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);} catch (detail::nd_template_match_found &) { return;} PyErr_SetString(PyExc_TypeError, "number of dimensions not found in template list."); python::throw_error_already_set(); } template void invoke_matching_dtype(dtype const & dtype_, Function f) { detail::dtype_template_invoker invoker(dtype_, f); try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);} catch (detail::dtype_template_match_found &) { return;} PyErr_SetString(PyExc_TypeError, "dtype not found in template list."); python::throw_error_already_set(); } namespace detail { template struct array_template_invoker_wrapper_2 { template void apply() const { m_func.Function::template apply();} array_template_invoker_wrapper_2(Function & func) : m_func(func) {} private: Function & m_func; }; template struct array_template_invoker_wrapper_1 { template void apply() const { invoke_matching_nd(m_nd, array_template_invoker_wrapper_2(m_func));} array_template_invoker_wrapper_1(int nd, Function & func) : m_nd(nd), m_func(func) {} private: int m_nd; Function & m_func; }; template struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper > : public array_template_invoker_wrapper_1< DimSequence, Function > { array_template_invoker_wrapper_1(int nd, Function & func) : array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {} }; } // namespace boost::python::numpy::detail template void invoke_matching_array(ndarray const & array_, Function f) { detail::array_template_invoker_wrapper_1 wrapper(array_.get_nd(), f); invoke_matching_dtype(array_.get_dtype(), wrapper); } }}} // namespace boost::python::numpy #endif