Skip to content

Commit

Permalink
Implement return data converter for bp::object return types, i.e. cre…
Browse files Browse the repository at this point in the history
…ating Python object arrays as output.
  • Loading branch information
Martin Wolf committed Sep 12, 2014
1 parent 210bdee commit 8b81fc4
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <boost/mpl/and.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/python/refcount.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/remove_reference.hpp>

Expand Down Expand Up @@ -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<intptr_t> > 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
Expand All @@ -120,7 +119,6 @@ struct scalar_return_to_core_shape_data_impl
}

numpy::detail::iter & iter_;
std::vector< std::vector<intptr_t> > const & out_core_shapes_;
};

template <class WiringModelAPI, class OutMapping, class RT>
Expand Down Expand Up @@ -154,6 +152,69 @@ struct select_scalar_return_to_core_shape_data_impl
type;
};

//------------------------------------------------------------------------------
template <class WiringModelAPI, class OutMapping, class RT>
struct bp_object_return_to_core_shape_data_impl
{
typedef bp_object_return_to_core_shape_data_impl<WiringModelAPI, OutMapping, RT>
type;

bp_object_return_to_core_shape_data_impl(
numpy::detail::iter & iter
, std::vector< std::vector<intptr_t> > 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<uintptr_t *>(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<uintptr_t>(python::xincref<PyObject>(obj.ptr()));

return true;
}

numpy::detail::iter & iter_;
};

template <class WiringModelAPI, class OutMapping, class RT>
struct select_bp_object_return_to_core_shape_data_impl
{
typedef mapping::detail::out_mapping<OutMapping>
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<typename WiringModelAPI::template out_arr_value_type<0>::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<WiringModelAPI, OutMapping, RT>

, numpy::mpl::unspecified
>::type
type;
};

//------------------------------------------------------------------------------
template <class VectorT, unsigned nd>
struct get_multidim_std_vector_shape;
Expand Down Expand Up @@ -279,11 +340,16 @@ struct select_return_to_core_shape_data_converter
, select_scalar_return_to_core_shape_data_impl<WiringModelAPI, OutMapping, RT>

// TODO: Add bp::object types.
, typename boost::mpl::eval_if<
typename numpy::mpl::is_std_vector<bare_rt>::type
, std_vector_return_to_core_shape_data<WiringModelAPI, OutMapping, RT, RT, 1>
, typename boost::mpl::if_<
typename is_same<bare_rt, python::object>::type
, select_bp_object_return_to_core_shape_data_impl<WiringModelAPI, OutMapping, RT>

, numpy::mpl::unspecified
, typename boost::mpl::eval_if<
typename numpy::mpl::is_std_vector<bare_rt>::type
, std_vector_return_to_core_shape_data<WiringModelAPI, OutMapping, RT, RT, 1>

, numpy::mpl::unspecified
>::type
>::type
>::type
type;
Expand Down
59 changes: 59 additions & 0 deletions include/boost/numpy/dstream/wiring/detail/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,33 @@ struct all_out_arr_value_types_arity<WiringModelAPI, UnaryMetaFunction, 1>
type;
};

template <
class WiringModelAPI
, template <class T> class UnaryMetaFunction
, unsigned out_arity
>
struct any_out_arr_value_type_arity;

template <
class WiringModelAPI
, template <class T> class UnaryMetaFunction
>
struct any_out_arr_value_type_arity<WiringModelAPI, UnaryMetaFunction, 0>
{
typedef boost::mpl::bool_<false>
type;
};

template <
class WiringModelAPI
, template <class T> class UnaryMetaFunction
>
struct any_out_arr_value_type_arity<WiringModelAPI, UnaryMetaFunction, 1>
{
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, <boost/numpy/dstream/wiring/detail/utilities.hpp>, 1))
#include BOOST_PP_ITERATE()
Expand All @@ -79,6 +106,15 @@ struct utilities
typedef typename all_out_arr_value_types_arity<WiringModelAPI, UnaryMetaFunction, WiringModelAPI::mapping_definition_t::out::arity>::type
type;
};

template <
template<class T> class UnaryMetaFunction
>
struct any_out_arr_value_type
{
typedef typename any_out_arr_value_type_arity<WiringModelAPI, UnaryMetaFunction, WiringModelAPI::mapping_definition_t::out::arity>::type
type;
};
};

}// namespace detail
Expand Down Expand Up @@ -117,6 +153,29 @@ struct all_out_arr_value_types_arity<WiringModelAPI, UnaryMetaFunction, OUT_ARIT
#undef BOOST_NUMPY_DEF_pre_and
};

template <
class WiringModelAPI
, template <class T> class UnaryMetaFunction
>
struct any_out_arr_value_type_arity<WiringModelAPI, UnaryMetaFunction, OUT_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<n>::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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <boost/mpl/bitor.hpp>
#include <boost/mpl/if.hpp>

#include <boost/numpy/mpl/is_type_of.hpp>
#include <boost/numpy/mpl/types_from_fctptr_signature.hpp>
#include <boost/numpy/dstream/wiring.hpp>
#include <boost/numpy/dstream/wiring/converter/arg_from_core_shape_data.hpp>
Expand Down Expand Up @@ -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<MappingDefinition, FTypes> >::template any_out_arr_value_type< numpy::mpl::is_type_of<python::object>::apply >::type
>::type
, numpy::detail::iter::flags::REFS_OK
, numpy::detail::iter::flags::NONE
>::type
Expand Down
44 changes: 44 additions & 0 deletions include/boost/numpy/mpl/is_type_of.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* $Id$
*
* Copyright (C)
* 2014 - $Date$
* Martin Wolf <boostnumpy@martin-wolf.org>
*
* \file boost/numpy/mpl/is_type_of.hpp
* \version $Revision$
* \date $Date$
* \author Martin Wolf <boostnumpy@martin-wolf.org>
*
* \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 <boost/type_traits/is_same.hpp>

namespace boost {
namespace numpy {
namespace mpl {

template <class U>
struct is_type_of
{
template <class T>
struct apply
{
typedef typename is_same<T, U>::type
type;
};
};

}// namespace mpl
}// namespace numpy
}// namespace boost

#endif // ! BOOST_NUMPY_MPL_IS_TYPE_OF_HPP_INCLUDED

0 comments on commit 8b81fc4

Please sign in to comment.