indexset::indexset(const irange & rg) : m_len(0) , m_ranges() { m_len = rg.length() == 0 ? 0 : 1; m_ranges.push_back(rg); }
inline void print_slice(std::ostream& o, const irange& i) { if (i.step() == 0) { o << '[' << i.start() << ']'; } else { o << '['; if (i.start() != std::numeric_limits<intptr_t>::min()) { o << i.start(); } o << ':'; if (i.finish() != std::numeric_limits<intptr_t>::max()) { o << i.finish(); } if (i.step() != 1) { o << ':'; o << i.step(); } o << ']'; } }
static inline Return dispatch(Ref& A, size_type row, const irange& col_range, boost::mpl::false_) { return Return(vector_size(A, col_range), &A[row][col_range.start()], num_rows(A)); }
static inline Return dispatch(Ref& A, size_type row, const irange& col_range, boost::mpl::true_) { return Return(vector_size(A, col_range), const_cast<value_type*>(&A[row][col_range.start()])); // TODO make work without const cast }
static inline size_type vector_size(const Ref& A, const irange& col_range) { using std::min; size_type finish= min(col_range.finish(), num_cols(A)); return col_range.start() < finish ? finish - col_range.start() : 0; }
void check_sub_range() { typedef string::iterator iterator; typedef string::const_iterator const_iterator; typedef iterator_range<iterator> irange; typedef iterator_range<const_iterator> cirange; string str = "hello world"; const string cstr = "const world"; irange r = make_iterator_range( str ); r = make_iterator_range( str.begin(), str.end() ); cirange r2 = make_iterator_range( cstr ); r2 = make_iterator_range( cstr.begin(), cstr.end() ); r2 = make_iterator_range( str ); typedef sub_range<string> srange; typedef sub_range<const string> csrange; srange s = r; BOOST_CHECK( r == r ); BOOST_CHECK( s == r ); s = make_iterator_range( str ); csrange s2 = r; s2 = r2; s2 = make_iterator_range( cstr ); BOOST_CHECK( r2 == r2 ); BOOST_CHECK( s2 != r2 ); s2 = make_iterator_range( str ); BOOST_CHECK( !(s != s) ); BOOST_CHECK( r.begin() == s.begin() ); BOOST_CHECK( r2.begin()== s2.begin() ); BOOST_CHECK( r.end() == s.end() ); BOOST_CHECK( r2.end() == s2.end() ); BOOST_CHECK_EQUAL( r.size(), s.size() ); BOOST_CHECK_EQUAL( r2.size(), s2.size() ); //#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // if( !(bool)r ) // BOOST_CHECK( false ); // if( !(bool)r2 ) // BOOST_CHECK( false ); // if( !(bool)s ) // BOOST_CHECK( false ); // if( !(bool)s2 ) // BOOST_CHECK( false ); //#else if( !r ) BOOST_CHECK( false ); if( !r2 ) BOOST_CHECK( false ); if( !s ) BOOST_CHECK( false ); if( !s2 ) BOOST_CHECK( false ); //#endif cout << r << r2 << s << s2; string res = copy_range<string>( r ); BOOST_CHECK( equal( res.begin(), res.end(), r.begin() ) ); r.empty(); s.empty(); r.size(); s.size(); // // As of range v2 not legal anymore. // //irange singular_irange; //BOOST_CHECK( singular_irange.empty() ); //BOOST_CHECK( singular_irange.size() == 0 ); // //srange singular_srange; //BOOST_CHECK( singular_srange.empty() ); //BOOST_CHECK( singular_srange.size() == 0 ); // //BOOST_CHECK( empty( singular_irange ) ); //BOOST_CHECK( empty( singular_srange ) ); // srange rr = make_iterator_range( str ); BOOST_CHECK( rr.equal( r ) ); rr = make_iterator_range( str.begin(), str.begin() + 5 ); BOOST_CHECK( rr == as_literal("hello") ); BOOST_CHECK( rr != as_literal("hell") ); BOOST_CHECK( rr < as_literal("hello dude") ); BOOST_CHECK( as_literal("hello") == rr ); BOOST_CHECK( as_literal("hell") != rr ); BOOST_CHECK( ! (as_literal("hello dude") < rr ) ); irange rrr = rr; BOOST_CHECK( rrr == rr ); BOOST_CHECK( !( rrr != rr ) ); BOOST_CHECK( !( rrr < rr ) ); const irange cr = make_iterator_range( str ); BOOST_CHECK_EQUAL( cr.front(), 'h' ); BOOST_CHECK_EQUAL( cr.back(), 'd' ); BOOST_CHECK_EQUAL( cr[1], 'e' ); BOOST_CHECK_EQUAL( cr(1), 'e' ); rrr = make_iterator_range( str, 1, -1 ); BOOST_CHECK( rrr == as_literal("ello worl") ); rrr = make_iterator_range( rrr, -1, 1 ); BOOST_CHECK( rrr == str ); rrr.front() = 'H'; rrr.back() = 'D'; rrr[1] = 'E'; BOOST_CHECK( rrr == as_literal("HEllo worlD") ); }
void check_iterator_range() { typedef std::string::iterator iterator; typedef std::string::const_iterator const_iterator; typedef boost::iterator_range<iterator> irange; typedef boost::iterator_range<const_iterator> cirange; std::string str = "hello world"; const std::string cstr = "const world"; irange r = boost::make_iterator_range( str ); r = boost::make_iterator_range( str.begin(), str.end() ); cirange r2 = boost::make_iterator_range( cstr ); r2 = boost::make_iterator_range( cstr.begin(), cstr.end() ); r2 = boost::make_iterator_range( str ); BOOST_CHECK( !r.empty() ); BOOST_CHECK( !r2.empty() ); //#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // if( !(bool)r ) // BOOST_CHECK( false ); // if( !(bool)r2 ) // BOOST_CHECK( false ); //#else if( !r ) BOOST_CHECK( false ); if( !r2 ) BOOST_CHECK( false ); //#endif BOOST_CHECK_EQUAL( r.size(), size( r ) ); BOOST_CHECK_EQUAL( r2.size(), size( r2 ) ); BOOST_CHECK_EQUAL( std::distance( r.begin(), r.end() ), std::distance( boost::begin( r2 ), boost::end( r2 ) ) ); std::cout << r << r2; #ifndef BOOST_NO_STD_WSTRING std::wcout << boost::make_iterator_range( std::wstring( L"a wide string" ) ) << boost::make_iterator_range( L"another wide string" ); #endif std::string res = boost::copy_range<std::string>( r ); BOOST_CHECK_EQUAL_COLLECTIONS( res.begin(), res.end(), r.begin(), r.end() ); irange rr = boost::make_iterator_range( str ); BOOST_CHECK( rr.equal( r ) ); rr = boost::make_iterator_range( str.begin(), str.begin() + 5 ); BOOST_CHECK( rr == boost::as_literal("hello") ); BOOST_CHECK( rr != boost::as_literal("hell") ); BOOST_CHECK( rr < boost::as_literal("hello dude") ); BOOST_CHECK( boost::as_literal("hello") == rr ); BOOST_CHECK( boost::as_literal("hell") != rr ); BOOST_CHECK( ! (boost::as_literal("hello dude") < rr ) ); irange rrr = rr; BOOST_CHECK( rrr == rr ); BOOST_CHECK( !( rrr != rr ) ); BOOST_CHECK( !( rrr < rr ) ); const irange cr = boost::make_iterator_range( str ); BOOST_CHECK_EQUAL( cr.front(), 'h' ); BOOST_CHECK_EQUAL( cr.back(), 'd' ); BOOST_CHECK_EQUAL( cr[1], 'e' ); BOOST_CHECK_EQUAL( cr(1), 'e' ); rrr = boost::make_iterator_range( str, 1, -1 ); BOOST_CHECK( rrr == boost::as_literal("ello worl") ); rrr = boost::make_iterator_range( rrr, -1, 1 ); BOOST_CHECK( rrr == str ); check_reference_type(); // Check that an iterator range can be instantiated with // a pointer to an array as an iterator. int arr[2][2]; boost::make_iterator_range(arr, arr + 2); }
void dynd::apply_single_linear_index(const irange& irnge, intptr_t dimension_size, intptr_t error_i, const ndt::type* error_tp, bool& out_remove_dimension, intptr_t& out_start_index, intptr_t& out_index_stride, intptr_t& out_dimension_size) { intptr_t step = irnge.step(); if (step == 0) { // A single index out_remove_dimension = true; intptr_t idx = irnge.start(); if (idx >= 0) { if (idx < dimension_size) { out_start_index = idx; out_index_stride = 1; out_dimension_size = 1; } else { if (error_tp) { intptr_t ndim = error_tp->extended()->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw index_out_of_bounds(idx, error_i, ndim, shape.get()); } else { throw index_out_of_bounds(idx, dimension_size); } } } else if (idx >= -dimension_size) { out_start_index = idx + dimension_size; out_index_stride = 1; out_dimension_size = 1; } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw index_out_of_bounds(idx, error_i, ndim, shape.get()); } else { throw index_out_of_bounds(idx, dimension_size); } } } else if (step > 0) { // A range with a positive step intptr_t start = irnge.start(); if (start >= 0) { if (start < dimension_size) { // Starts with a positive index } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); // check that we get here error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw irange_out_of_bounds(irnge, error_i, ndim, shape.get()); } else { throw irange_out_of_bounds(irnge, dimension_size); } } } else if (start >= -dimension_size) { // Starts with Python style negative index start += dimension_size; } else { // Signal for "from the beginning" whenever the index // is more negative start = 0; } intptr_t end = irnge.finish(); if (end >= 0) { if (end <= dimension_size) { // Ends with a positive index, or the end of the array } else { // Any end value greater or equal to the dimension size // signals to slice to the end end = dimension_size; } } else if (end >= -dimension_size) { // Ends with a Python style negative index end += dimension_size; } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw irange_out_of_bounds(irnge, error_i, ndim, shape.get()); } else { throw irange_out_of_bounds(irnge, dimension_size); } } intptr_t size = end - start; out_remove_dimension = false; if (size > 0) { if (step == 1) { // Simple range out_start_index = start; out_index_stride = 1; out_dimension_size = size; } else { // Range with a stride out_start_index = start; out_index_stride = step; out_dimension_size = (size + step - 1) / step; } } else { // Empty slice out_start_index = 0; out_index_stride = 1; out_dimension_size = 0; } } else { // A range with a negative step intptr_t start = irnge.start(); if (start >= 0) { if (start < dimension_size) { // Starts with a positive index } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw irange_out_of_bounds(irnge, error_i, ndim, shape.get()); } else { throw irange_out_of_bounds(irnge, dimension_size); } } } else if (start >= -dimension_size) { // Starts with Python style negative index start += dimension_size; } else if (start == std::numeric_limits<intptr_t>::min()) { // Signal for "from the beginning" (which means the last element) start = dimension_size - 1; } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw irange_out_of_bounds(irnge, error_i, ndim, shape.get()); } else { throw irange_out_of_bounds(irnge, dimension_size); } } intptr_t end = irnge.finish(); if (end >= 0) { if (end < dimension_size) { // Ends with a positive index, or the end of the array } else if (end == std::numeric_limits<intptr_t>::max()) { // Signal for "until the end" (which means towards index 0 of the data) end = -1; } else { if (error_tp) { intptr_t ndim = error_tp->get_ndim(); dimvector shape(ndim); error_tp->extended()->get_shape(ndim, 0, shape.get(), NULL, NULL); throw irange_out_of_bounds(irnge, error_i, ndim, shape.get()); } else { throw irange_out_of_bounds(irnge, dimension_size); } } } else if (end >= -dimension_size) { // Ends with a Python style negative index end += dimension_size; } else { // If the value is too negative, -1 means to go all the // way to the beginning (with the negative step) end = -1; } intptr_t size = start - end; out_remove_dimension = false; if (size > 0) { if (step == -1) { // Simple range out_start_index = start; out_index_stride = -1; out_dimension_size = size; } else { // Range with a stride out_start_index = start; out_index_stride = step; out_dimension_size = (size + (-step) - 1) / (-step); } } else { // Empty slice out_start_index = 0; out_index_stride = 1; out_dimension_size = 0; } } }
const self operator[]( irange r ) const { return sub_vector(*this, r.start(), r.finish()); }
void check_iterator_range() { typedef string::iterator iterator; typedef string::const_iterator const_iterator; typedef iterator_range<iterator> irange; typedef iterator_range<const_iterator> cirange; string str = "hello world"; const string cstr = "const world"; irange r = make_iterator_range( str ); r = make_iterator_range( str.begin(), str.end() ); cirange r2 = make_iterator_range( cstr ); r2 = make_iterator_range( cstr.begin(), cstr.end() ); r2 = make_iterator_range( str ); BOOST_CHECK( !r.empty() ); BOOST_CHECK( !r2.empty() ); //#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // if( !(bool)r ) // BOOST_CHECK( false ); // if( !(bool)r2 ) // BOOST_CHECK( false ); //#else if( !r ) BOOST_CHECK( false ); if( !r2 ) BOOST_CHECK( false ); //#endif BOOST_CHECK_EQUAL( r.size(), size( r ) ); BOOST_CHECK_EQUAL( r2.size(), size( r2 ) ); BOOST_CHECK_EQUAL( distance( r.begin(), r.end() ), distance( begin( r2 ), end( r2 ) ) ); cout << r << r2; #ifndef BOOST_NO_STD_WSTRING wcout << make_iterator_range( wstring( L"a wide string" ) ) << make_iterator_range( L"another wide string" ); #endif string res = copy_range<string>( r ); BOOST_CHECK( equal( res.begin(), res.end(), r.begin() ) ); irange rr = make_iterator_range( str ); BOOST_CHECK( rr.equal( r ) ); rr = make_iterator_range( str.begin(), str.begin() + 5 ); BOOST_CHECK( rr == as_literal("hello") ); BOOST_CHECK( rr != as_literal("hell") ); BOOST_CHECK( rr < as_literal("hello dude") ); BOOST_CHECK( as_literal("hello") == rr ); BOOST_CHECK( as_literal("hell") != rr ); BOOST_CHECK( ! (as_literal("hello dude") < rr ) ); irange rrr = rr; BOOST_CHECK( rrr == rr ); BOOST_CHECK( !( rrr != rr ) ); BOOST_CHECK( !( rrr < rr ) ); const irange cr = make_iterator_range( str ); BOOST_CHECK_EQUAL( cr.front(), 'h' ); BOOST_CHECK_EQUAL( cr.back(), 'd' ); BOOST_CHECK_EQUAL( cr[1], 'e' ); BOOST_CHECK_EQUAL( cr(1), 'e' ); rrr = make_iterator_range( str, 1, -1 ); BOOST_CHECK( rrr == as_literal("ello worl") ); rrr = make_iterator_range( rrr, -1, 1 ); BOOST_CHECK( rrr == str ); check_reference_type(); }