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 template <class T, class J> struct force_class; 00025 00026 namespace array_details { 00027 00028 template <template <typename, typename> class F> 00029 struct is_not_force_elem_class : public types::t_true { }; 00030 00031 template <> 00032 struct is_not_force_elem_class <force_class> : public types::t_false { }; 00033 00034 } /* namespace array_details */ 00035 00036 00042 template <class T, 00043 template <typename, typename> class F, class A, 00044 class DERIVED_INFO 00045 > 00046 class array<T, data::unary_elem_func<F, A, DERIVED_INFO> > : 00047 00048 public array_common_base<array<T, 00049 data::unary_elem_func<F, A, DERIVED_INFO> > > 00050 { 00051 00052 private: 00053 typedef array_common_base<array<T, 00054 data::unary_elem_func<F, A, DERIVED_INFO> > > common_base_class; 00055 00056 protected: 00057 typedef typename array::has_random_access prv_has_random_access; 00058 00059 typedef array_details::elem_func_tools<typename A::elem_type, 00060 prv_has_random_access::value> tool; 00061 00062 friend class tool::not_a_type; // allow disabled types only in our class 00063 00064 typedef typename types::t_or_3< 00065 types::t_eq<typename A::data_type, val_repeat>, 00066 types::t_eq<typename A::data_type, ref_val_repeat>, 00067 types::is_base<data::ice_wrap_array_attr_base_identifier, 00068 typename A::data_type> 00069 //types::is_base<data::member_identifier, typename A1::data_type> 00070 >::type 00071 in_is_scalar; 00072 00073 typedef typename types::t_if<in_is_scalar, 00074 internal::pointer_face<A>, const A*>::type in_t; 00075 00076 00077 in_t in1; 00078 00079 public: 00080 00081 // grant special treatment for the force_class as about the 00082 // is_referencing_array tag. 00083 // TODO: force wont be elem func any more. Act accordingly. 00084 typedef typename array_details::is_not_force_elem_class<F>::type 00085 is_referencing_array; 00086 00087 typedef array this_type; 00088 00089 typedef this_type this_array_type; 00090 00091 typedef this_type array_type; 00092 00093 typedef T elem_type; 00094 00095 typedef typename this_type::derived_type derived_type; 00096 00097 typedef typename common_base_class::base_class base_class; 00098 00100 typedef size_t size_type; 00101 00103 typedef ptrdiff_t diff_type; 00104 00105 using base_class::derived; 00106 00107 typedef typename array::has_random_access has_random_access; 00108 00109 class const_iterator 00110 { 00111 private: 00112 typedef typename A::const_iterator iter_1; 00113 00114 iter_1 i1; 00115 00116 typedef typename tool::template rnd_it<const_iterator>::type rnd_iter; 00117 00118 public: 00119 00120 // iterator_traits 00121 typedef typename types::t_if<has_random_access, 00122 std::random_access_iterator_tag, 00123 std::bidirectional_iterator_tag>::type iterator_category; 00124 00125 typedef T value_type; 00126 typedef ptrdiff_t difference_type; 00127 //typedef const T* pointer; 00128 //typedef const T reference; 00129 typedef internal::pointer_face<const T> pointer; 00130 // using this to comply with std:: iterators. if it is not optimized-out 00131 // by the compiler, consider using 00132 // `const internal::reference_face<const T, types::skip>' 00133 typedef const internal::reference_face<const T, const_iterator> 00134 reference; 00135 00136 // TODO: A::iter_border_walker, and correct place for this 00137 typedef ptrdiff_t iter_border_walker; 00138 00139 // constructors 00140 const_iterator() { } 00141 00142 const_iterator(const iter_1& i1) : i1(i1) { } 00143 00144 const_iterator(const const_iterator& it) : i1(it.i1) { } 00145 00146 pointer operator ->() const 00147 { 00148 return pointer(array_details::elem_func_unary_op< 00149 T, F<T, typename std::iterator_traits<iter_1>::value_type> >:: 00150 from(*i1)); 00151 } 00152 00153 // members 00154 reference operator *() const 00155 { 00156 return reference(array_details::elem_func_unary_op< 00157 T, F<T, typename std::iterator_traits<iter_1>::value_type> >:: 00158 from(*i1), *this); 00159 } 00160 00161 // optional random access in iterator 00162 reference operator[] 00163 (typename tool::brackets_arg j) const 00164 { 00165 return reference(array_details::elem_func_unary_op< 00166 T, F<T, typename std::iterator_traits<iter_1>::value_type> >:: 00167 from(tool::brackets(i1, j)), 00168 // hope that the below line will be optimized-out when using T. 00169 // or disregard the `tight' std:: standard that &(*iter) == &(*iter) 00170 rnd_iter(tool::add_op(i1, j))); 00171 } 00172 00173 // increment-decrement 00174 const_iterator& operator++() 00175 { 00176 ++i1; 00177 return *this; 00178 } 00179 const_iterator& operator--() 00180 { 00181 --i1; 00182 return *this; 00183 } 00184 00185 const_iterator operator++(int) 00186 { const_iterator tmp(*this); ++(*this); return tmp; } 00187 00188 const_iterator operator--(int) 00189 { const_iterator tmp(*this); --(*this); return tmp; } 00190 00191 // random access. enabled only if 'has_random_access' 00192 const_iterator& operator +=(typename tool::brackets_arg j) 00193 { 00194 tool::add_asgn(i1, j); 00195 return *this; 00196 } 00197 const_iterator& operator -=(typename tool::brackets_arg j) 00198 { 00199 tool::sub_asgn(i1, j); 00200 return *this; 00201 } 00202 inline rnd_iter operator +(typename tool::brackets_arg j) const 00203 { 00204 return rnd_iter(tool::add_op(i1, j)); 00205 } 00206 inline rnd_iter operator -(typename tool::brackets_arg j) const 00207 { 00208 return rnd_iter(tool::sub_op(i1, j)); 00209 } 00210 00211 // difference 00212 difference_type operator -(const rnd_iter& a) const 00213 { 00214 return tool::dif_op(i1, a.i1); 00215 } 00216 00217 //copy same type iterator 00218 const_iterator& operator=(const const_iterator& o) 00219 { 00220 i1 = o.i1; 00221 return *this; 00222 } 00223 00224 bool operator==(const const_iterator& o) const { return (i1 == o.i1); } 00225 bool operator!=(const const_iterator& o) const { return (i1 != o.i1); } 00226 bool operator<(const const_iterator& o) const { return (i1 < o.i1); } 00227 bool operator<=(const const_iterator& o) const { return (i1 <= o.i1); } 00228 bool operator>(const const_iterator& o) const { return (i1 > o.i1); } 00229 bool operator>=(const const_iterator& o) const { return (i1 >= o.i1); } 00230 }; 00231 00232 typedef typename const_iterator::reference const_reference; 00233 typedef const_reference best_reference; 00234 typedef const_iterator best_iterator; 00235 00236 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00237 00238 typedef typename const_iterator::iter_border_walker iter_border_walker; 00239 // TODO: correct place, same for binary elem_func, A::iter_border_walker, etc. 00240 iter_border_walker first_to_last() const { return this->length() - 1; } 00241 iter_border_walker begin_to_end() const { return this->length(); } 00242 00243 00244 const_iterator begin() const { return const_iterator(in1->begin()); } 00245 const_iterator end() const { return const_iterator(in1->end()); } 00246 00247 const_reverse_iterator rbegin() const 00248 { return const_reverse_iterator(in1->end()); } 00249 const_reverse_iterator rend() const 00250 { return const_reverse_iterator(in1->begin()); } 00251 00252 00255 00256 00257 size_t length() const 00258 { 00259 return in1->derived().length(); 00260 } 00261 00263 size_type size() const { return length(); } 00265 size_t numel() const { return length(); } 00274 00275 00276 /* 00277 T operator[]( 00278 typename tool::brackets_arg i) const 00279 { 00280 CHECK(i >= 0 && i < length(), erange); 00281 00282 return array_details::elem_func_unary_op< 00283 T, F<T, typename A::elem_type> >:: 00284 from(tool::brackets(in1->derived(), i)); 00285 }*/ 00286 00287 const_reference operator[]( 00288 typename tool::brackets_arg i) const 00289 { 00290 CHECK(i >= 0 && i < length(), erange); 00291 00292 return (begin()[i]); 00293 } 00302 00303 00304 00305 void setref(const A& a) 00306 { 00307 in1 = &a; 00308 } 00309 00310 template <class D> 00311 inline bool self_overlap(const D& a) const 00312 { 00313 // Do we need to specialize this so that in1->overlap(a) call is 00314 // avoided? or is the inline mechanism adequate to cleverly 00315 // optimize it out. For now let's rely on the compiler, 00316 // since we've been doing this from the beginning. 00317 return types::r_if<is_referencing_array>(a.overlap(*in1), false); 00318 } 00319 00320 // TODO: place 00321 void init(const A& a) { setref(a); } 00322 00323 void init(const array& o) { setref(*o.in1); } 00324 00329 00330 array() { } 00331 00333 array(const A& a) { setref(a); } 00334 00336 array(const array& o) { setref(*o.in1); } 00337 00342 00343 array(size_t) {} 00344 00346 array(size_t, const T&) {} 00347 00349 template <class J, class D> 00350 array(size_t, const array<J, D>&) {} 00351 00353 array(size_t, const T*) {} 00354 00356 template<class J, class S> 00357 array(const array<J, S>& a) {} 00358 00360 array& operator=(const array& o) 00361 { 00362 setref(*o.in1); 00363 return *this; 00364 //TODO: check 00365 } 00366 00368 ~array() { } 00369 00370 00371 }; 00372 00373 template <class T, class J> 00374 struct force_class 00375 { 00376 typedef types::number<1> cost; 00377 static inline T elem_op(const J& elem1) 00378 { 00379 return elem1; 00380 } 00381 };