From 8b81fc4797847b74deba5ef6cade5a3fd6e0e96c Mon Sep 17 00:00:00 2001 From: Martin Wolf Date: Fri, 12 Sep 2014 20:30:15 +0200 Subject: [PATCH] Implement return data converter for bp::object return types, i.e. creating Python object arrays as output. --- .../converter/return_to_core_shape_data.hpp | 86 ++++++++++++++++--- .../numpy/dstream/wiring/detail/utilities.hpp | 59 +++++++++++++ .../wiring/generalized_wiring_model.hpp | 6 +- include/boost/numpy/mpl/is_type_of.hpp | 44 ++++++++++ 4 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 include/boost/numpy/mpl/is_type_of.hpp diff --git a/include/boost/numpy/dstream/wiring/converter/return_to_core_shape_data.hpp b/include/boost/numpy/dstream/wiring/converter/return_to_core_shape_data.hpp index 28f229f..84e56cc 100644 --- a/include/boost/numpy/dstream/wiring/converter/return_to_core_shape_data.hpp +++ b/include/boost/numpy/dstream/wiring/converter/return_to_core_shape_data.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -98,15 +99,13 @@ struct scalar_return_to_core_shape_data_impl out_arr_value_t; scalar_return_to_core_shape_data_impl( - numpy::detail::iter & iter + numpy::detail::iter & iter , std::vector< std::vector > const & out_core_shapes ) : iter_(iter) - , out_core_shapes_(out_core_shapes) { - BOOST_ASSERT((out_core_shapes_.size() == 1 && - out_core_shapes_[0].size() == 1 && - out_core_shapes_[0][0] == 1)); + BOOST_ASSERT((out_core_shapes.size() == 1 && + out_core_shapes[0].size() == 0)); } inline @@ -120,7 +119,6 @@ struct scalar_return_to_core_shape_data_impl } numpy::detail::iter & iter_; - std::vector< std::vector > const & out_core_shapes_; }; template @@ -154,6 +152,69 @@ struct select_scalar_return_to_core_shape_data_impl type; }; +//------------------------------------------------------------------------------ +template +struct bp_object_return_to_core_shape_data_impl +{ + typedef bp_object_return_to_core_shape_data_impl + type; + + bp_object_return_to_core_shape_data_impl( + numpy::detail::iter & iter + , std::vector< std::vector > const & out_core_shapes + ) + : iter_(iter) + { + BOOST_ASSERT((out_core_shapes.size() == 1 && + out_core_shapes[0].size() == 0)); + } + + inline + bool + operator()(RT const & obj) + { + uintptr_t * ptr_value_ptr = reinterpret_cast(iter_.get_data(0)); + // Increment the reference counter for the bp object so it does not get + // destroyed when the bp::object object gets out of scope. + *ptr_value_ptr = reinterpret_cast(python::xincref(obj.ptr())); + + return true; + } + + numpy::detail::iter & iter_; +}; + +template +struct select_bp_object_return_to_core_shape_data_impl +{ + typedef mapping::detail::out_mapping + out_mapping_utils; + + // Check if the output arity is 1. + typedef typename out_mapping_utils::template arity_is_equal_to<1>::type + is_unary_out_mapping; + + // Check if the output array has a scalar core shape. + typedef typename out_mapping_utils::template array<0>::is_scalar::type + is_scalar_out_array; + + // Check if the output array has a bp::object data holding type. + typedef typename is_same::type, python::object>::type + is_bp_object_out_array_data_type; + + typedef typename boost::mpl::if_< + typename boost::mpl::and_< + is_unary_out_mapping + , is_scalar_out_array + , is_bp_object_out_array_data_type + >::type + , bp_object_return_to_core_shape_data_impl + + , numpy::mpl::unspecified + >::type + type; +}; + //------------------------------------------------------------------------------ template struct get_multidim_std_vector_shape; @@ -279,11 +340,16 @@ struct select_return_to_core_shape_data_converter , select_scalar_return_to_core_shape_data_impl // TODO: Add bp::object types. - , typename boost::mpl::eval_if< - typename numpy::mpl::is_std_vector::type - , std_vector_return_to_core_shape_data + , typename boost::mpl::if_< + typename is_same::type + , select_bp_object_return_to_core_shape_data_impl - , numpy::mpl::unspecified + , typename boost::mpl::eval_if< + typename numpy::mpl::is_std_vector::type + , std_vector_return_to_core_shape_data + + , numpy::mpl::unspecified + >::type >::type >::type type; diff --git a/include/boost/numpy/dstream/wiring/detail/utilities.hpp b/include/boost/numpy/dstream/wiring/detail/utilities.hpp index e1add21..b2f27b1 100644 --- a/include/boost/numpy/dstream/wiring/detail/utilities.hpp +++ b/include/boost/numpy/dstream/wiring/detail/utilities.hpp @@ -64,6 +64,33 @@ struct all_out_arr_value_types_arity type; }; +template < + class WiringModelAPI + , template class UnaryMetaFunction + , unsigned out_arity +> +struct any_out_arr_value_type_arity; + +template < + class WiringModelAPI + , template class UnaryMetaFunction +> +struct any_out_arr_value_type_arity +{ + typedef boost::mpl::bool_ + type; +}; + +template < + class WiringModelAPI + , template class UnaryMetaFunction +> +struct any_out_arr_value_type_arity +{ + typedef typename UnaryMetaFunction< typename WiringModelAPI::template out_arr_value_type<0>::type >::type + type; +}; + #define BOOST_PP_ITERATION_PARAMS_1 \ (4, (2, BOOST_NUMPY_LIMIT_OUTPUT_ARITY, , 1)) #include BOOST_PP_ITERATE() @@ -79,6 +106,15 @@ struct utilities typedef typename all_out_arr_value_types_arity::type type; }; + + template < + template class UnaryMetaFunction + > + struct any_out_arr_value_type + { + typedef typename any_out_arr_value_type_arity::type + type; + }; }; }// namespace detail @@ -117,6 +153,29 @@ struct all_out_arr_value_types_arity class UnaryMetaFunction +> +struct any_out_arr_value_type_arity +{ + #define BOOST_NUMPY_DEF_pre_or(z, n, data) \ + typename boost::mpl::or_< + #define BOOST_NUMPY_DEF_unary_metafunction_result(n) \ + typename UnaryMetaFunction< typename WiringModelAPI::template out_arr_value_type::type >::type + #define BOOST_NUMPY_DEF_post_or(z, n, data) \ + BOOST_PP_COMMA() BOOST_NUMPY_DEF_unary_metafunction_result(BOOST_PP_ADD(n,1)) >::type + + typedef BOOST_PP_REPEAT(BOOST_PP_SUB(OUT_ARITY,1), BOOST_NUMPY_DEF_pre_or, ~) + BOOST_NUMPY_DEF_unary_metafunction_result(0) + BOOST_PP_REPEAT(BOOST_PP_SUB(OUT_ARITY,1), BOOST_NUMPY_DEF_post_or, ~) + type; + + #undef BOOST_NUMPY_DEF_post_or + #undef BOOST_NUMPY_DEF_unary_metafunction_result + #undef BOOST_NUMPY_DEF_pre_or +}; + #undef OUT_ARITY #endif // BOOST_PP_ITERATION_FLAGS == 1 diff --git a/include/boost/numpy/dstream/wiring/generalized_wiring_model.hpp b/include/boost/numpy/dstream/wiring/generalized_wiring_model.hpp index d4c3c2e..2857277 100644 --- a/include/boost/numpy/dstream/wiring/generalized_wiring_model.hpp +++ b/include/boost/numpy/dstream/wiring/generalized_wiring_model.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -94,7 +95,10 @@ struct generalized_wiring_model_api // Note: This could lead to the requirement that // the python GIL cannot released during the iteration! typedef typename boost::mpl::if_< - typename LoopService::object_arrays_are_involved + typename boost::mpl::or_< + typename LoopService::object_arrays_are_involved + , typename utilities< generalized_wiring_model_api >::template any_out_arr_value_type< numpy::mpl::is_type_of::apply >::type + >::type , numpy::detail::iter::flags::REFS_OK , numpy::detail::iter::flags::NONE >::type diff --git a/include/boost/numpy/mpl/is_type_of.hpp b/include/boost/numpy/mpl/is_type_of.hpp new file mode 100644 index 0000000..3b64331 --- /dev/null +++ b/include/boost/numpy/mpl/is_type_of.hpp @@ -0,0 +1,44 @@ +/** + * $Id$ + * + * Copyright (C) + * 2014 - $Date$ + * Martin Wolf + * + * \file boost/numpy/mpl/is_type_of.hpp + * \version $Revision$ + * \date $Date$ + * \author Martin Wolf + * + * \brief This file defines a MPL template for checking if a type T is the same + * as type U using an unary metafunction for checking. + * + * This file is 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_NUMPY_MPL_IS_TYPE_OF_HPP_INCLUDED +#define BOOST_NUMPY_MPL_IS_TYPE_OF_HPP_INCLUDED + +#include + +namespace boost { +namespace numpy { +namespace mpl { + +template +struct is_type_of +{ + template + struct apply + { + typedef typename is_same::type + type; + }; +}; + +}// namespace mpl +}// namespace numpy +}// namespace boost + +#endif // ! BOOST_NUMPY_MPL_IS_TYPE_OF_HPP_INCLUDED