ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 namespace array_details { 00025 00026 template<bool IS_INTEGER> 00027 struct range_tool 00028 { 00029 }; 00030 00031 template<> 00032 struct range_tool<true> 00033 { 00034 template <class T> 00035 class const_iterator { 00036 private: 00037 typedef typename types::to_signed<T>::type step_type; 00038 T val; 00039 step_type step; 00040 00041 public: 00042 // iterator_traits 00043 typedef std::random_access_iterator_tag iterator_category; 00044 typedef typename types::remove_const<T>::type value_type; 00045 typedef ptrdiff_t difference_type; 00046 typedef const value_type pointer; 00047 typedef const T reference; 00048 00049 const_iterator() { } 00050 const_iterator(const const_iterator& it) 00051 : val(it.val), step(it.step) { } 00052 // for begin 00053 const_iterator(T val, step_type step) : val(val), step(step) { } 00054 // for end 00055 const_iterator(T val, step_type step, T begin) 00056 : val(val), step(step) 00057 { 00058 this->val -= step_type(val - begin) % step; 00059 } 00060 00061 const_iterator& operator++() { val+=step; return *this; } 00062 const_iterator& operator--() { val-=step; return *this; } 00063 00064 const_iterator operator++(int) 00065 { const_iterator tmp(*this); val+=step; return tmp; } 00066 const_iterator operator--(int) 00067 { const_iterator tmp(*this); val-=step; return tmp; } 00068 00069 // random access 00070 const_iterator operator +(const difference_type i) const 00071 { const_iterator tmp(val + T(i) * step); return tmp; } 00072 const_iterator operator -(const difference_type i) const 00073 { const_iterator tmp(val - T(i) * step); return tmp; } 00074 const_iterator& operator +=(const difference_type i) 00075 { val+=T(i) * step; return *this; } 00076 const_iterator& operator -=(const difference_type i) 00077 { val-=T(i) * step; return *this; } 00078 00079 const T operator *() const { return val; } 00080 00081 //TODO: make use of pointer face or something 00082 //const T* operator ->() const { return &val; } 00083 00084 const T operator [](size_t j) const { return val + T(j) * step; } 00085 00086 const_iterator& operator=(const const_iterator& it) 00087 { this->val = it.val; this->step = it.step; return *this; } 00088 00089 difference_type operator-(const const_iterator& it) const 00090 { return (val - it.val) / step; } 00091 00092 bool operator==(const const_iterator& it) const 00093 { return this->val == it.val; } 00094 bool operator!=(const const_iterator& it) const 00095 { return this->val != it.val; } 00096 bool operator<(const const_iterator& o) const 00097 { return (step > 0) ? (val < o.val) : (val > o.val); } 00098 bool operator<=(const const_iterator& o) const 00099 { return (step > 0) ? (val <= o.val) : (val >= o.val); } 00100 bool operator>(const const_iterator& o) const 00101 { return (step > 0) ? (val > o.val) : (val < o.val); } 00102 bool operator>=(const const_iterator& o) const 00103 { return (step > 0) ? (val >= o.val) : (val <= o.val); } 00104 00105 }; 00106 00107 }; 00108 00109 template<> 00110 struct range_tool<false> 00111 { 00112 template <class T> 00113 class const_iterator { 00114 private: 00115 typedef typename types::to_signed<T>::type step_type; 00116 T first; 00117 step_type step; 00118 size_t i; 00119 00120 // constructor for internal use 00121 explicit const_iterator(T first, step_type step, ptrdiff_t i, int) 00122 : first(first), step(step), i(i) { } 00123 00124 public: 00125 // iterator_traits 00126 typedef std::random_access_iterator_tag iterator_category; 00127 typedef typename types::remove_const<T>::type value_type; 00128 typedef ptrdiff_t difference_type; 00129 typedef const value_type* pointer; 00130 typedef const T reference; 00131 00132 const_iterator() { } 00133 const_iterator(const const_iterator& it) 00134 : first(it.first), step(it.step), i(it.i) { } 00135 // for begin 00136 const_iterator(T val, T step) : first(val), step(step), i(0) { } 00137 // for end 00138 const_iterator(T val, T step, T begin) : first(begin), step(step), 00139 i(size_t(step_type(val - begin) / step)) { } 00140 00141 const_iterator& operator++() { ++i; return *this; } 00142 const_iterator& operator--() { --i; return *this; } 00143 00144 const_iterator operator++(int) 00145 { const_iterator tmp(*this); i++; return tmp; } 00146 const_iterator operator--(int) 00147 { const_iterator tmp(*this); i--; return tmp; } 00148 00149 // random access 00150 const_iterator operator +(const difference_type off) const 00151 { const_iterator tmp(first, step, i + off, 0); return tmp; } 00152 const_iterator operator -(const difference_type off) const 00153 { const_iterator tmp(first, step, i - off, 0); return tmp; } 00154 const_iterator& operator +=(const difference_type off) 00155 { i += off; return *this; } 00156 const_iterator& operator -=(const difference_type off) 00157 { i -= off; return *this; } 00158 00159 const T operator *() const { return first + step_type(i) * step; } 00160 00161 // TODO: make use of a pointer face or something similar here... 00162 // TODO: fix this issue for all non-pointer iterators making correct 00163 // definition of iterator::pointer 00164 // const T* operator ->() const { return &(val + step_type(i) * step); } 00165 // this could mean that operator T[] may return an object that can 00166 // have & on it and return a pointer, and can be convertible to T. ouch! 00167 00168 const T operator [](size_t j) const 00169 { return first + step_type(i + j) * step; } 00170 00171 const_iterator& operator=(const const_iterator& it) 00172 { this->first = it.first; this->step = it.step; 00173 this->i = it.i; return *this; } 00174 00175 difference_type operator-(const const_iterator& it) const 00176 { return ptrdiff_t(i) - ptrdiff_t(it.i); } 00177 00178 bool operator==(const const_iterator& o) const { return i == o.i; } 00179 bool operator!=(const const_iterator& o) const { return i != o.i; } 00180 bool operator<(const const_iterator& o) const { return (i < o.i); } 00181 bool operator<=(const const_iterator& o) const { return (i <= o.i); } 00182 bool operator>(const const_iterator& o) const { return (i > o.i); } 00183 bool operator>=(const const_iterator& o) const { return (i >= o.i); } 00184 00185 }; 00186 }; 00187 00188 } /* namespace array_details */ 00189 00195 template <class T, 00196 class DERIVED_INFO 00197 > 00198 class array<T, data::range<DERIVED_INFO> > : 00199 public array_common_base<array<T, data::range<DERIVED_INFO> > > 00200 { 00201 private: 00202 typedef array_common_base<array<T, 00203 data::range<DERIVED_INFO> > > common_base_class; 00204 00205 protected: 00206 00207 public: 00208 typedef typename types::to_signed<T>::type step_type; 00209 00210 T first; 00211 T last; 00212 step_type step; 00213 00214 typedef array this_type; 00215 00216 typedef this_type this_array_type; 00217 00218 typedef this_type array_type; 00219 00220 typedef T elem_type; 00221 00222 typedef typename this_type::derived_type derived_type; 00223 00224 /* TODO: present derived_array_type which will be one type before e.g. range<T>, having DATA_TYPE and DERIVED_INFO, 00225 or otherwise, derived_creatable_type. because range in an array_nd should yield create_new = array_nd, however 00226 range in a range<T> should yield create_new = array. Temporarily fix with create_new = array cause range in 00227 array_nd is currently unsupported anyway. 00228 */ 00229 00230 typedef typename common_base_class::base_class base_class; 00231 00232 typedef size_t size_type; 00233 00234 typedef ptrdiff_t diff_type; 00235 00236 using base_class::derived; 00237 00238 typedef typename array_details::range_tool<types::is_integer<T>::value> 00239 ::template const_iterator<T> const_iterator; 00240 typedef std::reverse_iterator<T> const_reverse_iterator; 00241 00242 typedef typename const_iterator::reference const_reference; 00243 00244 typedef const_iterator best_iterator; 00245 typedef const_reference best_reference; 00246 00247 const_iterator begin() const 00248 { 00249 return const_iterator(first, step); 00250 } 00251 const_iterator end() const 00252 { 00253 return const_iterator(last + step, step, first); 00254 } 00255 const_reverse_iterator rbegin() const 00256 { return end(); } 00257 const_reverse_iterator rend() const 00258 { return begin(); } 00259 00262 //TODO: explain this better. 00264 size_t length() const 00265 { 00266 return size_t(step_type(last - first) / step + 1); 00267 } 00269 size_type size() const { return length(); } 00271 size_t numel() const { return length(); } 00274 typedef ptrdiff_t iter_border_walker; 00275 iter_border_walker first_to_last() const { return this->length() - 1; } 00276 iter_border_walker begin_to_end() const { return this->length(); } 00277 00283 00284 const_reference operator[] (size_t i) const 00285 { 00286 CHECK(i >= 0 && i < length() ,erange); 00287 return first + step_type(i) * step; 00288 } 00289 00295 00296 array() { } 00297 00299 array(const this_type& a) 00300 { 00301 first = a.first; 00302 last = a.last; 00303 step = a.step; 00304 } 00305 00307 ~array() { } 00308 00309 00321 this_type& operator=(const this_type& a) // copy operator 00322 { 00323 // Note: if(this != &a) is checked here because the base operator 00324 // is ignored. 00325 if(this == &a) return *this; 00326 first = a.first; 00327 last = a.last; 00328 step = a.step; 00329 return *this; 00330 } 00333 void init(const this_type& a) 00334 { 00335 first = a.first; 00336 last = a.last; 00337 step = a.step; 00338 } 00342 00343 std::ostream& print(std::ostream& os) const; 00346 //array<T> cat(const array<T>& a) const; 00347 00348 00349 }; 00350 00351 template <class T, class P> 00352 std::ostream& array<T, ivl::data::range<P> >::print( 00353 std::basic_ostream<char, std::char_traits<char> >& os) const 00354 { 00355 if(last >= first && step == T(1)) 00356 os << "(" << first << ":" << last << ")"; 00357 else if(last < first && step == -1) 00358 os << "(" << first << ":" << last << ")"; 00359 else 00360 os << "(" << first << ":" << step << ":" << last << ")"; 00361 00362 return os; 00363 } 00364 00365 #if 0 00366 template <class T> 00367 class range 00368 : public array<T, data::range, ivl::range<T> > 00369 { 00370 public: 00371 range() {} 00372 00373 range(T first, T last, T step) 00374 { 00375 this->first = first; 00376 this->last = last; 00377 this->step = step; 00378 } 00379 }; 00380 #endif