Go to the documentation of this file.00001
00002
00003
00004
00005 #ifndef BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED
00006 #define BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED
00007
00013 #include <boost/numpy/dtype.hpp>
00014 #include <boost/numpy/ndarray.hpp>
00015
00016 #include <boost/mpl/integral_c.hpp>
00017
00018 namespace boost
00019 {
00020 namespace numpy
00021 {
00022 namespace detail
00023 {
00024
00025 struct add_pointer_meta
00026 {
00027 template <typename T>
00028 struct apply
00029 {
00030 typedef typename boost::add_pointer<T>::type type;
00031 };
00032
00033 };
00034
00035 struct dtype_template_match_found {};
00036 struct nd_template_match_found {};
00037
00038 template <typename Function>
00039 struct dtype_template_invoker
00040 {
00041
00042 template <typename T>
00043 void operator()(T *) const
00044 {
00045 if (dtype::get_builtin<T>() == m_dtype)
00046 {
00047 m_func.Function::template apply<T>();
00048 throw dtype_template_match_found();
00049 }
00050 }
00051
00052 dtype_template_invoker(dtype const & dtype_, Function func)
00053 : m_dtype(dtype_), m_func(func) {}
00054
00055 private:
00056 dtype const & m_dtype;
00057 Function m_func;
00058 };
00059
00060 template <typename Function>
00061 struct dtype_template_invoker< boost::reference_wrapper<Function> >
00062 {
00063
00064 template <typename T>
00065 void operator()(T *) const
00066 {
00067 if (dtype::get_builtin<T>() == m_dtype)
00068 {
00069 m_func.Function::template apply<T>();
00070 throw dtype_template_match_found();
00071 }
00072 }
00073
00074 dtype_template_invoker(dtype const & dtype_, Function & func)
00075 : m_dtype(dtype_), m_func(func) {}
00076
00077 private:
00078 dtype const & m_dtype;
00079 Function & m_func;
00080 };
00081
00082 template <typename Function>
00083 struct nd_template_invoker
00084 {
00085 template <int N>
00086 void operator()(boost::mpl::integral_c<int,N> *) const
00087 {
00088 if (m_nd == N)
00089 {
00090 m_func.Function::template apply<N>();
00091 throw nd_template_match_found();
00092 }
00093 }
00094
00095 nd_template_invoker(int nd, Function func) : m_nd(nd), m_func(func) {}
00096
00097 private:
00098 int m_nd;
00099 Function m_func;
00100 };
00101
00102 template <typename Function>
00103 struct nd_template_invoker< boost::reference_wrapper<Function> >
00104 {
00105 template <int N>
00106 void operator()(boost::mpl::integral_c<int,N> *) const
00107 {
00108 if (m_nd == N)
00109 {
00110 m_func.Function::template apply<N>();
00111 throw nd_template_match_found();
00112 }
00113 }
00114
00115 nd_template_invoker(int nd, Function & func) : m_nd(nd), m_func(func) {}
00116
00117 private:
00118 int m_nd;
00119 Function & m_func;
00120 };
00121
00122 }
00123
00124 template <typename Sequence, typename Function>
00125 void invoke_matching_nd(int nd, Function f)
00126 {
00127 detail::nd_template_invoker<Function> invoker(nd, f);
00128 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
00129 catch (detail::nd_template_match_found &) { return;}
00130 PyErr_SetString(PyExc_TypeError, "number of dimensions not found in template list.");
00131 python::throw_error_already_set();
00132 }
00133
00134 template <typename Sequence, typename Function>
00135 void invoke_matching_dtype(dtype const & dtype_, Function f)
00136 {
00137 detail::dtype_template_invoker<Function> invoker(dtype_, f);
00138 try { boost::mpl::for_each< Sequence, detail::add_pointer_meta >(invoker);}
00139 catch (detail::dtype_template_match_found &) { return;}
00140 PyErr_SetString(PyExc_TypeError, "dtype not found in template list.");
00141 python::throw_error_already_set();
00142 }
00143
00144 namespace detail
00145 {
00146
00147 template <typename T, typename Function>
00148 struct array_template_invoker_wrapper_2
00149 {
00150 template <int N>
00151 void apply() const { m_func.Function::template apply<T,N>();}
00152 array_template_invoker_wrapper_2(Function & func) : m_func(func) {}
00153
00154 private:
00155 Function & m_func;
00156 };
00157
00158 template <typename DimSequence, typename Function>
00159 struct array_template_invoker_wrapper_1
00160 {
00161 template <typename T>
00162 void apply() const { invoke_matching_nd<DimSequence>(m_nd, array_template_invoker_wrapper_2<T,Function>(m_func));}
00163 array_template_invoker_wrapper_1(int nd, Function & func) : m_nd(nd), m_func(func) {}
00164
00165 private:
00166 int m_nd;
00167 Function & m_func;
00168 };
00169
00170 template <typename DimSequence, typename Function>
00171 struct array_template_invoker_wrapper_1< DimSequence, boost::reference_wrapper<Function> >
00172 : public array_template_invoker_wrapper_1< DimSequence, Function >
00173 {
00174 array_template_invoker_wrapper_1(int nd, Function & func)
00175 : array_template_invoker_wrapper_1< DimSequence, Function >(nd, func) {}
00176 };
00177
00178 }
00179
00180 template <typename TypeSequence, typename DimSequence, typename Function>
00181 void invoke_matching_array(ndarray const & array_, Function f)
00182 {
00183 detail::array_template_invoker_wrapper_1<DimSequence,Function> wrapper(array_.get_nd(), f);
00184 invoke_matching_dtype<TypeSequence>(array_.get_dtype(), wrapper);
00185 }
00186
00187 }
00188 }
00189
00190 #endif // !BOOST_NUMPY_INVOKE_MATCHING_HPP_INCLUDED