Skip to content

Commit

Permalink
Adding basic view bindings to the tools bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
whaeck committed Apr 22, 2024
1 parent d96f5f3 commit 9005571
Show file tree
Hide file tree
Showing 2 changed files with 242 additions and 0 deletions.
32 changes: 32 additions & 0 deletions python/src/tools.python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <pybind11/stl.h>

// other includes
#include "views.hpp"

// namespace aliases
namespace python = pybind11;
Expand All @@ -17,4 +18,35 @@ namespace python = pybind11;
*/
PYBIND11_MODULE( tools, module ) {

// create the views submodule
python::module viewmodule = module.def_submodule(

"sequence",
"sequence - tools sequences (internal use only)"
);

// wrap some basic recurring views
// none of these are supposed to be created directly by the user
// @todo test performance against range-v3
wrapBasicRandomAccessAnyViewOf< double >(
viewmodule,
"AnyRandomAccessView< double >" );
wrapBasicRandomAccessAnyViewOf< int >(
viewmodule,
"AnyRandomAccessView< unsigned int >" );
wrapBasicRandomAccessAnyViewOf< unsigned int >(
viewmodule,
"AnyRandomAccessView< unsigned int >" );
wrapBasicRandomAccessAnyViewOf< long >(
viewmodule,
"AnyRandomAccessView< long >" );
wrapBasicRandomAccessAnyViewOf< BasicRandomAccessAnyView< double > >(
viewmodule,
"any_view< any_view< double, random_access >, random_access >" );
wrapBasicRandomAccessAnyViewOf< BasicRandomAccessAnyView< BasicRandomAccessAnyView< double > > >(
viewmodule,
"any_view< any_view< any_view< double, random_access >, random_access >, random_access >" );
wrapBasicRandomAccessAnyViewOf< std::complex< double > >(
viewmodule,
"any_view< std::complex< double , random_access >" );
}
210 changes: 210 additions & 0 deletions python/src/views.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#ifndef NJOY_TOOLS_PYTHON_VIEWS
#define NJOY_TOOLS_PYTHON_VIEWS

// system includes
#include <complex>

// other includes
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "tools/views/AnyView.hpp"

namespace python = pybind11;
namespace std20 = nano;

/**
* @brief Type aliases for basic any views
*
* The ReferenceType template represents the type of the AnyView reference type.
*/
template < typename ReferenceType >
using BasicInputAnyView = njoy::tools::views::AnyInputView< ReferenceType >;
template < typename ReferenceType >
using BasicForwardAnyView = njoy::tools::views::AnyForwardView< ReferenceType >;
template < typename ReferenceType >
using BasicBidirectionalAnyView = njoy::tools::views::AnyBidirectionalView< ReferenceType >;
template < typename ReferenceType >
using BasicRandomAccessAnyView = njoy::tools::views::AnyRandomAccessView< ReferenceType >;

/**
* @brief Type aliases for any views using a reference wrapper to a const
* Element
*
* The resulting any_view contains std::reference_wrapper< const Element >
* instead of just Element to fix an issue with any_views. Views already
* containing reference wrappers (e.g. variants of reference wrappers) should
* continue to use the Basic... versions of the any views.
*/
template < typename ReferenceType >
using InputAnyView = BasicInputAnyView< const ReferenceType& >;
template < typename ReferenceType >
using ForwardAnyView = BasicForwardAnyView< const ReferenceType& >;
template < typename ReferenceType >
using BidirectionalAnyView = BasicBidirectionalAnyView< const ReferenceType& >;
template < typename ReferenceType >
using RandomAccessAnyView = BasicRandomAccessAnyView< const ReferenceType& >;

/**
* @brief Some recurring basic views
*/
using DoubleRange = BasicRandomAccessAnyView< double >;
using LongRange = BasicRandomAccessAnyView< long >;
using IntRange = BasicRandomAccessAnyView< int >;
using UnsignedIntRange = BasicRandomAccessAnyView< unsigned int >;
using DoubleRange2D = BasicRandomAccessAnyView< DoubleRange >;
using DoubleRange3D = BasicRandomAccessAnyView< DoubleRange2D >;
using ComplexRange = BasicRandomAccessAnyView< std::complex< double > >;

/**
* @brief Wrap a BasicBidirectionalAnyView templated on the Element type
*
* @param[in,out] module the python module
* @param[in,out] name the unique type name
*/
template < typename Element, typename CopyElement = Element >
void wrapBasicBidirectionalAnyViewOf( python::module& module, const std::string& name ) {

python::class_< BasicBidirectionalAnyView< Element > >( module, name.c_str() )
.def( "__len__",
[] ( BasicBidirectionalAnyView< Element >& view )
{ return std::distance( view.begin(), view.end() ); },
"Return the length of the sequence" )
.def( "__iter__",
[] ( BasicBidirectionalAnyView< Element >& view )
{ return python::make_iterator<
python::return_value_policy::reference_internal,
nano::iterator_t< BasicBidirectionalAnyView< Element > >,
nano::sentinel_t< BasicBidirectionalAnyView< Element > >,
Element >( view.begin(), view.end() ); },
"Return an iterator for the sequence",
python::keep_alive< 0, 1 >() )
.def( "front",
[] ( BasicBidirectionalAnyView< Element >& view )
{ return view.front(); },
"Return the front element of the sequence",
python::keep_alive< 0, 1 >() )
.def( "to_list",
[] ( BasicBidirectionalAnyView< Element >& view )
-> std::vector< Element >
{ return std::vector< Element >( view.begin(), view.end() ); },
"Convert the sequence to a list (this is a deep copy for primitive\n"
"types (like integer and floats) and a shallow copy for custom types" )
.def( "copy",
[] ( BasicRandomAccessAnyView< Element >& view )
-> std::vector< CopyElement >
{ return std::vector< CopyElement >( view.begin(), view.end() ); },
"Copy the sequence to a list (this is a deep copy for both primitive\n"
"types (like integer and floats) and custom types" );
}

/**
* @brief Wrap a BasicRandomAccessAnyView templated on the Element type
*
* @param[in,out] module the python module
* @param[in,out] name the unique type name
*/
template < typename Element, typename CopyElement = Element >
void wrapBasicRandomAccessAnyViewOf( python::module& module, const std::string& name ) {

auto index = [] ( auto i, auto length ) {

if ( i < 0 ) {

i += length;
}
if ( i < 0 || i >= length ) {

throw python::index_error();
}
return i;
};

python::class_< BasicRandomAccessAnyView< Element > >( module, name.c_str() )
.def( "__len__",
[] ( BasicRandomAccessAnyView< Element >& view )
{ return std::distance( view.begin(), view.end() ); },
"Return the length of the sequence" )
.def( "__getitem__",
[index] ( BasicRandomAccessAnyView< Element >& view, int i ) {

return view[index( i, std::distance( view.begin(), view.end() ) )];
},
"Return the value in the sequence at the given index or throw an\n"
"exception when the index is out of range",
python::return_value_policy::reference_internal )
.def( "__getitem__",
[] ( BasicRandomAccessAnyView< Element >& view,
const python::slice& slice ) {

python::size_t start, stop, step, length;
if ( !slice.compute( std::distance( view.begin(), view.end() ),
&start, &stop, &step, &length ) ) {

throw python::error_already_set();
}
std::vector< Element > list;
for ( unsigned int i = 0; i < length; ++i ) {

list.emplace_back( view[start] );
start += step;
}
return list;
},
"Return a list corresponding to the sliced sequence or throw an\n"
"exception when the slice is invalid. The resulting list is a deep\n"
"copy for primitive types (like integer and floats) and a shallow\n"
"copy for custom types",
python::return_value_policy::reference_internal )
.def( "__iter__",
[] ( BasicRandomAccessAnyView< Element >& view )
{ return python::make_iterator<
python::return_value_policy::reference_internal,
nano::iterator_t< BasicBidirectionalAnyView< Element > >,
nano::sentinel_t< BasicBidirectionalAnyView< Element > >,
Element >( view.begin(), view.end() ); },
"Return an iterator for the sequence",
python::keep_alive< 0, 1 >() )
.def( "front",
[] ( BasicRandomAccessAnyView< Element >& view )
{ return view.front(); },
"Return the front element of the sequence",
python::keep_alive< 0, 1 >() )
.def( "to_list",
[] ( BasicRandomAccessAnyView< Element >& view )
-> std::vector< Element >
{ return std::vector< Element >( view.begin(), view.end() ); },
"Convert the sequence to a list (this is a deep copy for primitive\n"
"types (like integer and floats) and a shallow copy for custom types" )
.def( "copy",
[] ( BasicRandomAccessAnyView< Element >& view )
-> std::vector< CopyElement >
{ return std::vector< CopyElement >( view.begin(), view.end() ); },
"Copy the sequence to a list (this is a deep copy for both primitive\n"
"types (like integer and floats) and custom types" );
}

/**
* @brief Wrap a BidirectionalAnyView templated on the Element type
*
* @param[in,out] module the python module
* @param[in,out] name the unique type name
*/
template < typename Element >
void wrapBidirectionalAnyViewOf( python::module& module, const std::string& name ) {

wrapBasicBidirectionalAnyViewOf< const Element&, Element >( module, name );
}

/**
* @brief Wrap a RandomAccessAnyView templated on the Element type
*
* @param[in,out] module the python module
* @param[in,out] name the unique type name
*/
template < typename Element >
void wrapRandomAccessAnyViewOf( python::module& module, const std::string& name ) {

wrapBasicRandomAccessAnyViewOf< const Element&, Element >( module, name );
}

#endif

0 comments on commit 9005571

Please sign in to comment.