Skip to content

Commit

Permalink
Improve VectorToNumpy return policy. Refs #5624
Browse files Browse the repository at this point in the history
There are now two: VectorRefToNumpy & VectorToNumpy. The latter only
allows clones as the return could be a return by value.
  • Loading branch information
martyngigg committed Jul 17, 2012
1 parent fd04c58 commit d9eb9e1
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/if.hpp>
#include <vector>

namespace Mantid
Expand All @@ -41,12 +42,30 @@ namespace Mantid

namespace // anonymous
{
//-----------------------------------------------------------------------
// MPL helper structs
//-----------------------------------------------------------------------
/// MPL struct to figure out if a type is a std::vector
/// The general one inherits from boost::false_type
template<typename T>
struct is_std_vector : boost::false_type
{};

/// Specialization for std::vector types to inherit from
/// boost::true_type
template<typename T>
struct is_std_vector<std::vector<T> > : boost::true_type
{};


//-----------------------------------------------------------------------
// VectorRefToNumpyImpl - Policy for reference returns
//-----------------------------------------------------------------------
/**
* Helper struct that implements the conversion
* policy.
* Helper struct that implements the conversion policy.
*/
template<typename VectorType, typename ConversionPolicy>
struct VectorToNumpyImpl
struct VectorRefToNumpyImpl
{
inline PyObject * operator()(const VectorType & cvector) const
{
Expand All @@ -58,53 +77,86 @@ namespace Mantid
return Converters::getNDArrayType();
}
};

template<typename T>
struct VectorRefToNumpy_Requires_Reference_To_StdVector_Return_Type
{};
}

/**
* Implements a return value policy that
* returns a numpy array from a rerence to a std::vector
*
* The type of conversion is specified by a policy:
* (1) WrapReadOnly - Creates a read-only array around the original data (no copy is performed)
* (2) WrapReadWrite - Creates a read-write array around the original data (no copy is performed)
*/
template<typename ConversionPolicy>
struct VectorRefToNumpy
{
// The boost::python framework calls return_value_policy::apply<T>::type
template <class T>
struct apply
{
// Typedef that removes and const or reference qualifiers from the type
typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type non_const_type;
// MPL compile-time check that T is a reference to a std::vector
typedef typename boost::mpl::if_c<
boost::mpl::and_<boost::is_reference<T>, is_std_vector<non_const_type> >::value,
VectorRefToNumpyImpl<non_const_type, ConversionPolicy>,
VectorRefToNumpy_Requires_Reference_To_StdVector_Return_Type<T>
>::type type;
};
};

//-----------------------------------------------------------------------
// return_value_policy
// VectorToNumpy return_value_policy
//-----------------------------------------------------------------------
namespace
{
/// MPL struct to figure out if a type is a std::vector
/// The general one inherits from boost::false_type
template<typename T>
struct is_std_vector : boost::false_type
{};
/**
* Helper struct that implements the conversion policy. This can only clone
* as wrapping would wrap a temporary
*/
template<typename VectorType>
struct VectorToNumpyImpl
{
inline PyObject * operator()(const VectorType & cvector) const
{
return Converters::VectorToNDArray<typename VectorType::value_type, Converters::Clone>()(cvector);
}

/// Specialization for std::vector types to inherit from
/// boost::true_type
template<typename T>
struct is_std_vector<std::vector<T> > : boost::true_type
{};
inline PyTypeObject const* get_pytype() const
{
return Converters::getNDArrayType();
}
};

template<typename T>
struct VectorToNumpy_Requires_StdVector_Return_Type
struct VectorToNumpy_Requires_StdVector_Return_By_Value
{};

}

/**
* Implements a return value policy that
* returns a numpy array from a std::vector
* returns a numpy array from a function returning a std::vector by value
*
* The type of conversion is specified by a policy:
* (1) WrapReadOnly - Creates a read-only array around the original data (no copy is performed)
* (2) WrapReadWrite - Creates a read-write array around the original data (no copy is performed)
* It is only possible to clone these types since a wrapper would wrap temporary
*/
template<typename ConversionPolicy>
struct VectorToNumpy
{
// The boost::python framework calls return_value_policy::apply<T>::type
template <class T>
struct apply
{
// Typedef that removes and const or reference qualifiers from the type
typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type non_const_type;
// MPL compile-time check that T is a reference to a std::vector
// Typedef that removes any const from the type
typedef typename boost::remove_const<T>::type non_const_type;
// MPL compile-time check that T is a std::vector
typedef typename boost::mpl::if_c<
boost::mpl::and_<boost::is_reference<T>, is_std_vector<non_const_type> >::value
, VectorToNumpyImpl<non_const_type, ConversionPolicy>
, VectorToNumpy_Requires_StdVector_Return_Type<T>
>::type type;
is_std_vector<non_const_type>::value,
VectorRefToNumpyImpl<non_const_type, Converters::Clone>,
VectorToNumpy_Requires_StdVector_Return_By_Value<T>
>::type type;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ namespace
/// Typedef for data access, i.e. dataX,Y,E members
typedef Mantid::MantidVec&(MatrixWorkspace::*data_modifier)(const std::size_t);
/// return_value_policy for read-only numpy array
typedef return_value_policy<Policies::VectorToNumpy<Converters::WrapReadOnly> > return_readonly_numpy;
typedef return_value_policy<Policies::VectorRefToNumpy<Converters::WrapReadOnly> > return_readonly_numpy;
/// return_value_policy for read-write numpy array
typedef return_value_policy<Policies::VectorToNumpy<Converters::WrapReadWrite> > return_readwrite_numpy;
typedef return_value_policy<Policies::VectorRefToNumpy<Converters::WrapReadWrite> > return_readwrite_numpy;

//------------------------------- Overload macros ---------------------------
// Overloads for binIndexOf function which has 1 optional argument
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using namespace boost::python;
namespace
{
/// return_value_policy for cloned numpy array
typedef return_value_policy<Policies::VectorToNumpy<Converters::Clone> > return_cloned_numpy;
typedef return_value_policy<Policies::VectorRefToNumpy<Converters::Clone> > return_cloned_numpy;

#define EXPORT_ARRAY_PROP(type, prefix) \
class_<ArrayProperty<type>, \
Expand Down

0 comments on commit d9eb9e1

Please sign in to comment.