diff --git a/doc/v2/slice.html b/doc/v2/slice.html index cea06553..734e4218 100644 --- a/doc/v2/slice.html +++ b/doc/v2/slice.html @@ -105,7 +105,7 @@ constructors
slice();
Effects: constructs a slice with default stop, start, and -step values.  Equivalent to the slice object created by the Python +step values.  Equivalent to the slice object created as part of the Python expression base[::].
Throws: nothing.
@@ -115,13 +115,14 @@ slice(Int1 start, Int2 stop);
Requires: start, stop, and step -are of type slice_nil or convertible to type object.
+ are of type slice_nil + or convertible to type object.
Effects: constructs a new slice with default step value and the provided start and stop values.  Equivalent to the slice object created by the built-in Python function slice(start,stop), -or the Python expression base[start:stop].
+or as part of the Python expression base[start:stop].
Throws: error_already_set and sets a Python TypeError exception if no conversion is possible from the arguments to type object.
@@ -129,12 +130,12 @@ exception if no conversion is possible from the arguments to type object -
Requires: start, stop, and step are integers, slice_nil, or convertible to type object.
+
Requires: start, stop, and step are slice_nil or convertible to type object.
Effects: constructs a new slice with start stop and step values.  Equivalent to the slice object created by the built-in Python function slice(start,stop,step), -or the Python expression base[start:stop:step].
+or as part of the Python expression base[start:stop:step].
Throws: error_already_set and sets a Python TypeError exception if no conversion is possible from the arguments to type object.
@@ -142,9 +143,9 @@ object. observer functions
-object slice::start();
-object slice::stop();
-object slice::step();
+object slice::start() const;
+object slice::stop() const;
+object slice::step() const;
 
Effects: None.
@@ -153,7 +154,7 @@ object slice::step(); the slice was created with. If the parameter was omitted or slice_nil was used when the slice was created, than that parameter will be a reference to PyNone and compare equal to a default-constructed -object. In principal, any object may be used when creating a +object.  In principal, any object may be used when creating a slice object, but in practice they are usually integers.

@@ -161,7 +162,8 @@ slice object, but in practice they are usually integers. template <typename RandomAccessIterator> slice::range<RandomAccessIterator> slice::get_indicies( - RandomAccessIterator const& begin, RandomAccessIterator const& end); + RandomAccessIterator const& begin, + RandomAccessIterator const& end) const;
Arguments: A pair of STL-conforming Random Access @@ -203,7 +205,7 @@ list odd_elements(list l) return l[slice(_,_,2)]; } -// Perform a multidimensional rich slice of a Numeric.array +// Perform a multidimensional extended slice of a Numeric.array numeric::array even_columns(numeric::array arr) { // select every other column, starting with the second, of a 2-D array. @@ -212,7 +214,7 @@ numeric::array even_columns(numeric::array arr) } // Perform a summation over a slice of a std::vector. -double partial_sum(std::vector<double> const& Foo, slice index) +double partial_sum(std::vector<double> const& Foo, const slice index) { slice::range<std::vector<double>::const_iterator> bounds; try { @@ -222,7 +224,7 @@ double partial_sum(std::vector<double> const& Foo, slice index) return 0.0; } double sum = 0.0; - while (bounds.start != bounds.end) { + while (bounds.start != bounds.stop) { sum += *bounds.start; std::advance( bounds.start, bounds.step); } diff --git a/include/boost/python/slice.hpp b/include/boost/python/slice.hpp index 9354b485..9f296bc2 100644 --- a/include/boost/python/slice.hpp +++ b/include/boost/python/slice.hpp @@ -16,7 +16,7 @@ #include namespace boost { namespace python { - + class slice : public object { private: @@ -29,7 +29,8 @@ class slice : public object BOOST_PYTHON_DECL slice(); - // Each argument must be int, slice_nil, or implicitly convertable to int + // Each argument must be slice_nil, or implicitly convertable to object. + // They should normally be integers. template slice( Integer1 start, Integer2 stop) : object( new_slice( object(start).ptr(), object(stop).ptr(), NULL)) @@ -48,9 +49,9 @@ class slice : public object // equal to a default-constructed boost::python::object. // If a user-defined type wishes to support slicing, then support for the // special meaning associated with negative indicies is up to the user. - object start(); - object stop(); - object step(); + object start() const; + object stop() const; + object step() const; // The following algorithm is intended to automate the process of // determining a slice range when you want to fully support negative @@ -104,7 +105,7 @@ class slice : public object template range get_indicies( const RandomAccessIterator& begin, - const RandomAccessIterator& end) + const RandomAccessIterator& end) const { // This is based loosely on PySlice_GetIndicesEx(), but it has been // carefully crafted to ensure that these iterators never fall out of diff --git a/src/slice.cpp b/src/slice.cpp index 55f8e865..a4dd98f5 100644 --- a/src/slice.cpp +++ b/src/slice.cpp @@ -21,21 +21,21 @@ slice::slice() } object -slice::start() +slice::start() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->start)); } object -slice::stop() +slice::stop() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->stop)); } object -slice::step() +slice::step() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->step)); diff --git a/test/slice.cpp b/test/slice.cpp index 37d9e83d..d516d008 100644 --- a/test/slice.cpp +++ b/test/slice.cpp @@ -1,5 +1,6 @@ #include #include +#include using namespace boost::python; @@ -75,9 +76,37 @@ bool check_numeric_array_rich_slice() // Verify functions accepting a slice argument can be called bool accept_slice( slice) { return true; } +int check_slice_get_indicies(const slice index) +{ + // A vector of integers from [-5, 5]. + std::vector coll(11); + typedef std::vector::iterator coll_iterator; + + for (coll_iterator i = coll.begin(); i != coll.end(); ++i) { + *i = i - coll.begin() - 5; + } + + slice::range::iterator> bounds; + try { + bounds = index.get_indicies<>(coll.begin(), coll.end()); + } + catch (std::invalid_argument) { + return 0; + } + int sum = 0; + while (bounds.start != bounds.stop) { + sum += *bounds.start; + std::advance( bounds.start, bounds.step); + } + sum += *bounds.start; + return sum; +} + + BOOST_PYTHON_MODULE(slice_ext) { def( "accept_slice", accept_slice); def( "check_numeric_array_rich_slice", check_numeric_array_rich_slice); def( "check_string_rich_slice", check_string_rich_slice); + def( "check_slice_get_indicies", check_slice_get_indicies); } diff --git a/test/slice.py b/test/slice.py index fb6a7b03..fafe8a6f 100644 --- a/test/slice.py +++ b/test/slice.py @@ -37,6 +37,18 @@ test passed ... print 1 ... 1 +>>> check_slice_get_indicies( slice(None)) +0 +>>> check_slice_get_indicies( slice(2,-2)) +0 +>>> check_slice_get_indicies( slice(2, None, 2)) +5 +>>> check_slice_get_indicies( slice(2, None, -1)) +-12 +>>> check_slice_get_indicies( slice( 20, None)) +0 +>>> check_slice_get_indicies( slice( -2, -5, -2)) +6 """ # Performs an affirmative and negative argument resolution check,