00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_STRIDED_VECTOR_REF_INCLUDE
00013 #define MTL_STRIDED_VECTOR_REF_INCLUDE
00014
00015
00016 #include <iostream>
00017 #include <cassert>
00018 #include <vector>
00019 #include <algorithm>
00020 #include <boost/static_assert.hpp>
00021 #include <boost/type_traits.hpp>
00022 #include <boost/utility/enable_if.hpp>
00023
00024 #include <boost/numeric/mtl/mtl_fwd.hpp>
00025 #include <boost/numeric/mtl/utility/exception.hpp>
00026 #include <boost/numeric/mtl/utility/ashape.hpp>
00027 #include <boost/numeric/mtl/utility/common_include.hpp>
00028 #include <boost/numeric/mtl/vector/all_vec_expr.hpp>
00029 #include <boost/numeric/mtl/vector/parameter.hpp>
00030 #include <boost/numeric/mtl/vector/crtp_base_vector.hpp>
00031 #include <boost/numeric/mtl/utility/dense_el_cursor.hpp>
00032 #include <boost/numeric/mtl/utility/range_generator.hpp>
00033 #include <boost/numeric/mtl/utility/property_map.hpp>
00034 #include <boost/numeric/mtl/utility/irange.hpp>
00035 #include <boost/numeric/mtl/utility/is_row_major.hpp>
00036 #include <boost/numeric/mtl/utility/strided_dense_el_iterator.hpp>
00037 #include <boost/numeric/mtl/utility/strided_dense_el_cursor.hpp>
00038
00039
00040 namespace mtl { namespace vector {
00041
00042
00044 template <class Value, typename Parameters = parameters<> >
00045 class strided_vector_ref
00046 : public vec_expr<strided_vector_ref<Value, Parameters> >,
00047 public crtp_base_vector< strided_vector_ref<Value, Parameters>, Value, std::size_t >
00048 {
00049 typedef strided_vector_ref self;
00050 typedef crtp_base_vector< self, Value, std::size_t > crtp_base;
00051 typedef crtp_vector_assign< self, Value, std::size_t > assign_base;
00052 typedef vec_expr<strided_vector_ref<Value, Parameters> > expr_base;
00053 public:
00054 typedef typename boost::remove_const<Value>::type value_type ;
00055 typedef std::size_t size_type ;
00056 typedef Value& reference ;
00057 typedef Value const& const_reference ;
00058 typedef Value* pointer ;
00059 typedef Value const* const_pointer ;
00060 typedef const_pointer key_type;
00061 typedef mtl::strided_dense_el_cursor<Value> cursor_type;
00062 typedef mtl::strided_dense_el_const_iterator<Value> const_iterator;
00063 typedef mtl::strided_dense_el_iterator<Value> iterator;
00064 typedef typename Parameters::orientation orientation;
00065
00066 void check_index( size_type i ) const
00067 {
00068 MTL_DEBUG_THROW_IF( i < 0 || i >= size(), index_out_of_range());
00069 }
00070
00071 void check_dim( size_type s ) const
00072 {
00073 MTL_DEBUG_THROW_IF( size() != 0 && size() != s, incompatible_size());
00074 }
00075
00076 template <class E>
00077 void check_consistent_shape( vec_expr<E> const& ) const
00078 {
00079 MTL_DEBUG_THROW_IF((!boost::is_same<
00080 typename ashape::ashape<self>::type
00081 , typename ashape::ashape<E>::type
00082 >::value),
00083 incompatible_shape());
00084 }
00085
00086 private:
00088 strided_vector_ref();
00089
00090 public:
00091
00093 strided_vector_ref( size_type length, pointer start_address, size_type stride= 1)
00094 : data(start_address), my_size(length), my_stride(stride) {}
00095
00096
00097
00098 size_type size() const { return my_size ; }
00099 size_type stride() const { return my_stride ; }
00100
00101 reference operator()( size_type i ) { check_index(i); return data[i * my_stride]; }
00102 const_reference operator()( size_type i ) const { check_index(i); return data[i * my_stride]; }
00103
00104 reference operator[]( size_type i ) { return (*this)( i ) ; }
00105 const_reference operator[]( size_type i ) const { return (*this)( i ) ; }
00106
00107 self operator[]( irange r ) { return sub_vector(*this, r.start(), r.finish()); }
00108 const self operator[]( irange r ) const { return sub_vector(*this, r.start(), r.finish()); }
00109
00110 void delay_assign() const {}
00111
00112 const_iterator begin() const { return const_iterator(data, my_stride); }
00113 const_iterator end() const { return const_iterator(data + my_size * my_stride, my_stride); }
00114
00115 iterator begin() { return iterator(data, my_stride); }
00116 iterator end() { return iterator(data + my_size * my_stride, my_stride); }
00117
00119 pointer address_data() { return data; }
00120 const_pointer address_data() const { return data; }
00121
00122
00123 size_type offset(const_pointer p) const
00124 {
00125 size_type o= p - data, i= o / my_stride;
00126 MTL_DEBUG_THROW_IF(o % my_stride, logic_error("Address not consistent with stride."));
00127 check_index(i);
00128 return i;
00129 }
00130
00131 friend size_type inline num_rows(const self& v) { return mtl::traits::is_row_major<self>::value ? 1 : v.size(); }
00132 friend size_type inline num_cols(const self& v) { return mtl::traits::is_row_major<self>::value ? v.size() : 1; }
00133 friend size_type inline size(const self& v) { return v.size(); }
00134
00135 vec_vec_asgn_expr<self, self> operator=( self const& e )
00136 {
00137 return vec_vec_asgn_expr<self, self>( *this, e );
00138 }
00139
00140
00141
00142 using assign_base::operator=;
00143
00144 template <typename Value2> friend void fill(self& vector, const Value2& value)
00145 {
00146 std::fill(vector.begin(), vector.end(), value);
00147 }
00148
00150 friend void swap(self& vector1, self& vector2)
00151 {
00152 vector1.check_dim(vector2.size());
00153 for (size_type i= 0; i < vector1.size(); ++i)
00154 swap(vector1[i], vector2[i]);
00155 }
00156
00157 void change_dim(size_type n) { MTL_DEBUG_THROW_IF(my_size != n, incompatible_size()); }
00158 void crop() {}
00159
00160 private:
00161 pointer data;
00162 size_type my_size, my_stride;
00163 } ;
00164
00165
00166
00167 template <typename Value, typename Parameters>
00168 strided_vector_ref<Value, Parameters>
00169 inline sub_vector(strided_vector_ref<Value, Parameters>& v,
00170 typename strided_vector_ref<Value, Parameters>::size_type start,
00171 typename strided_vector_ref<Value, Parameters>::size_type finish)
00172 {
00173 using std::min;
00174 typedef strided_vector_ref<Value, Parameters> Vector;
00175 typedef typename Vector::size_type size_type;
00176
00177 MTL_DEBUG_THROW_IF( start < 0 || finish < 0, index_out_of_range());
00178 finish= min(finish, size(v));
00179 start= min(start, finish);
00180 return Vector(start <= finish ? finish - start : size_type(0), &v[start], v.stride());
00181 }
00182
00183 template <typename Value, typename Parameters>
00184 const strided_vector_ref<Value, Parameters>
00185 inline sub_vector(const strided_vector_ref<Value, Parameters>& v,
00186 typename strided_vector_ref<Value, Parameters>::size_type start,
00187 typename strided_vector_ref<Value, Parameters>::size_type finish)
00188 {
00189 typedef strided_vector_ref<Value, Parameters> Vector;
00190 return sub_vector(const_cast<Vector&>(v), start, finish);
00191 }
00192
00193
00194 }}
00195
00196
00197 namespace mtl { namespace traits {
00198
00199
00200
00201
00202
00203
00204
00205 template <typename Value, class Parameters>
00206 struct range_generator<tag::all, vector::strided_vector_ref<Value, Parameters> >
00207 : public detail::strided_element_range_generator<
00208 vector::strided_vector_ref<Value, Parameters>,
00209 const vector::strided_vector_ref<Value, Parameters>,
00210 mtl::strided_dense_el_cursor<Value>
00211 > {};
00212
00213 template <typename Value, class Parameters>
00214 struct range_generator<tag::nz, vector::strided_vector_ref<Value, Parameters> >
00215 : public range_generator<tag::all, vector::strided_vector_ref<Value, Parameters> > {};
00216
00217 template <typename Value, class Parameters>
00218 struct range_generator<tag::iter::all, vector::strided_vector_ref<Value, Parameters> >
00219 : public detail::strided_element_range_generator<
00220 vector::strided_vector_ref<Value, Parameters>,
00221 vector::strided_vector_ref<Value, Parameters>,
00222 mtl::strided_dense_el_iterator<Value>
00223 > {};
00224
00225 template <typename Value, class Parameters>
00226 struct range_generator<tag::iter::nz, vector::strided_vector_ref<Value, Parameters> >
00227 : public range_generator<tag::iter::all, vector::strided_vector_ref<Value, Parameters> > {};
00228
00229 template <typename Value, class Parameters>
00230 struct range_generator<tag::const_iter::all, vector::strided_vector_ref<Value, Parameters> >
00231 : public detail::strided_element_range_generator<
00232 vector::strided_vector_ref<Value, Parameters>,
00233 const vector::strided_vector_ref<Value, Parameters>,
00234 mtl::strided_dense_el_const_iterator<Value>
00235 > {};
00236
00237 template <typename Value, class Parameters>
00238 struct range_generator<tag::const_iter::nz, vector::strided_vector_ref<Value, Parameters> >
00239 : public range_generator<tag::const_iter::all, vector::strided_vector_ref<Value, Parameters> >
00240 {};
00241
00242
00243 }}
00244
00245
00246 #endif // MTL_STRIDED_VECTOR_REF_INCLUDE
00247