File indexing completed on 2025-02-22 10:26:14
0001
0002
0003
0004
0005
0006
0007 #ifndef boost_python_numpy_invoke_matching_hpp_
0008 #define boost_python_numpy_invoke_matching_hpp_
0009
0010
0011
0012
0013
0014 #include <boost/python/numpy/dtype.hpp>
0015 #include <boost/python/numpy/ndarray.hpp>
0016 #include <boost/mpl/integral_c.hpp>
0017
0018 namespace boost { namespace python { namespace numpy {
0019 namespace detail
0020 {
0021
0022 struct BOOST_NUMPY_DECL add_pointer_meta
0023 {
0024 template <typename T>
0025 struct apply
0026 {
0027 typedef typename boost::add_pointer<T>::type type;
0028 };
0029
0030 };
0031
0032 struct BOOST_NUMPY_DECL dtype_template_match_found {};
0033 struct BOOST_NUMPY_DECL nd_template_match_found {};
0034
0035 template <typename Function>
0036 struct dtype_template_invoker
0037 {
0038
0039 template <typename T>
0040 void operator()(T *) const
0041 {
0042 if (dtype::get_builtin<T>() == m_dtype)
0043 {
0044 m_func.Function::template apply<T>();
0045 throw dtype_template_match_found();
0046 }
0047 }
0048
0049 dtype_template_invoker(dtype const & dtype_, Function func)
0050 : m_dtype(dtype_), m_func(func) {}
0051
0052 private:
0053 dtype const & m_dtype;
0054 Function m_func;
0055 };
0056
0057 template <typename Function>
0058 struct dtype_template_invoker< boost::reference_wrapper<Function> >
0059 {
0060
0061 template <typename T>
0062 void operator()(T *) const
0063 {
0064 if (dtype::get_builtin<T>() == m_dtype)
0065 {
0066 m_func.Function::template apply<T>();
0067 throw dtype_template_match_found();
0068 }
0069 }
0070
0071 dtype_template_invoker(dtype const & dtype_, Function & func)
0072 : m_dtype(dtype_), m_func(func) {}
0073
0074 private:
0075 dtype const & m_dtype;
0076 Function & m_func;
0077 };
0078
0079 template <typename Function>
0080 struct nd_template_invoker
0081 {
0082 template <int N>
0083 void operator()(boost::mpl::integral_c<int,N> *) const
0084 {
0085 if (m_nd == N)
0086 {
0087 m_func.Function::template apply<N>();
0088 throw nd_template_match_found();
0089 }
0090 }
0091
0092 nd_template_invoker(int nd, Function func) : m_nd(nd), m_func(func) {}
0093
0094 private:
0095 int m_nd;
0096 Function m_func;
0097 };
0098
0099 template <typename Function>
0100 struct nd_template_invoker< boost::reference_wrapper<Function> >
0101 {
0102 template <int N>
0103 void operator()(boost::mpl::integral_c<int,N> *) const
0104 {
0105 if (m_nd == N)
0106 {
0107 m_func.Function::template apply<N>();
0108 throw nd_template_match_found();
0109 }
0110 }
0111
0112 nd_template_invoker(int nd, Function & func) : m_nd(nd), m_func(func) {}
0113
0114 private:
0115 int m_nd;
0116 Function & m_func;
0117 };
0118
0119 }
0120
0121 template <typename Sequence, typename Function>
0122 void invoke_matching_nd(int nd, Function f)
0123 {
0124 detail::nd_template_invoker<Function> invoker(nd, f);
0125 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
0126 catch (detail::nd_template_match_found &) { return;}
0127 PyErr_SetString(PyExc_TypeError, "number of dimensions not found in template list.");
0128 python::throw_error_already_set();
0129 }
0130
0131 template <typename Sequence, typename Function>
0132 void invoke_matching_dtype(dtype const & dtype_, Function f)
0133 {
0134 detail::dtype_template_invoker<Function> invoker(dtype_, f);
0135 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
0136 catch (detail::dtype_template_match_found &) { return;}
0137 PyErr_SetString(PyExc_TypeError, "dtype not found in template list.");
0138 python::throw_error_already_set();
0139 }
0140
0141 namespace detail
0142 {
0143
0144 template <typename T, typename Function>
0145 struct array_template_invoker_wrapper_2
0146 {
0147 template <int N>
0148 void apply() const { m_func.Function::template apply<T,N>();}
0149 array_template_invoker_wrapper_2(Function & func) : m_func(func) {}
0150
0151 private:
0152 Function & m_func;
0153 };
0154
0155 template <typename DimSequence, typename Function>
0156 struct array_template_invoker_wrapper_1
0157 {
0158 template <typename T>
0159 void apply() const { invoke_matching_nd<DimSequence>(m_nd, array_template_invoker_wrapper_2<T,Function>(m_func));}
0160 array_template_invoker_wrapper_1(int nd, Function & func) : m_nd(nd), m_func(func) {}
0161
0162 private:
0163 int m_nd;
0164 Function & m_func;
0165 };
0166
0167 template <typename DimSequence, typename Function>
0168 struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper<Function> >
0169 : public array_template_invoker_wrapper_1< DimSequence, Function >
0170 {
0171 array_template_invoker_wrapper_1(int nd, Function & func)
0172 : array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {}
0173 };
0174
0175 }
0176
0177 template <typename TypeSequence, typename DimSequence, typename Function>
0178 void invoke_matching_array(ndarray const & array_, Function f)
0179 {
0180 detail::array_template_invoker_wrapper_1<DimSequence,Function> wrapper(array_.get_nd(), f);
0181 invoke_matching_dtype<TypeSequence>(array_.get_dtype(), wrapper);
0182 }
0183
0184 }}}
0185
0186 #endif