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 #ifndef IVL_ARRAY_DETAILS_COMMON_READWRITE_ARRAY_COMMON_HPP 00025 #define IVL_ARRAY_DETAILS_COMMON_READWRITE_ARRAY_COMMON_HPP 00026 00027 namespace ivl { 00028 00029 namespace array_details { 00030 00031 template < 00032 class T, class S, 00033 class BASE, 00034 class IS_WRITEABLE > 00035 class readwrite_array_common 00036 { 00037 }; 00038 00039 //not writeable 00040 template <class T, class S, class BASE> 00041 class readwrite_array_common<T, S, BASE, types::t_false> 00042 : public conversions_array_common<T, S, BASE> 00043 { 00044 private: 00045 typedef readwrite_array_common prv_this_type; 00046 typedef array<T, S> t; 00047 t& to_array() { return static_cast<t&>(*this); } 00048 const t& to_array() const { return static_cast<const t&>(*this); } 00049 public: 00050 // ++ 00051 // for not writeable arrays, ++ iterates through all the elements... 00052 t& operator++() 00053 { 00054 typedef typename t::const_iterator c_it; 00055 for(c_it i = to_array().begin(); i!= to_array().end(); i++) *i; 00056 return to_array(); 00057 } 00058 }; 00059 00060 //writeable 00061 template <class T, class S, class BASE> 00062 class readwrite_array_common<T, S, BASE, types::t_true> 00063 : public conversions_array_common<T, S, BASE> 00064 { 00065 private: 00066 typedef readwrite_array_common prv_this_type; 00067 typedef array<T, S> t; 00068 t& to_array() { return static_cast<t&>(*this); } 00069 const t& to_array() const { return static_cast<const t&>(*this); } 00070 00071 public: 00072 typedef typename prv_this_type::derived_type derived_type; 00073 // everything is defined twice 00074 // the unsafe way (function call) and the safe way (operator). 00075 00076 // the unsafe way ------------------------------------------- 00077 00078 //plus_assign(), for += 00079 template <class A> 00080 derived_type& plus_assign(const A& a) 00081 { 00082 loop_on<loops::assign_plus_class>(this->derived(), a); 00083 return this->derived(); 00084 } 00085 00086 //minus_assign(), for -= 00087 template <class A> 00088 derived_type& minus_assign(const A& a) 00089 { 00090 loop_on<loops::assign_minus_class>(this->derived(), a); 00091 return this->derived(); 00092 } 00093 00094 //times_assign(), for *= 00095 template <class A> 00096 derived_type& times_assign(const A& a) 00097 { 00098 loop_on<loops::assign_times_class>(this->derived(), a); 00099 return this->derived(); 00100 } 00101 00102 //divide_assign(), for /= 00103 template <class A> 00104 derived_type& divide_assign(const A& a) 00105 { 00106 loop_on<loops::assign_divide_class>(this->derived(), a); 00107 return this->derived(); 00108 } 00109 00110 // mod_assign(), for %= 00111 template <class A> 00112 derived_type& mod_assign(const A& a) 00113 { 00114 loop_on<loops::assign_mod_class>(this->derived(), a); 00115 return this->derived(); 00116 } 00117 00118 // bitor_assign(), for |= 00119 template <class A> 00120 derived_type& bitor_assign(const A& a) 00121 { 00122 loop_on<loops::assign_bitor_class>(this->derived(), a); 00123 return this->derived(); 00124 } 00125 00126 // bitand_assign(), for &= 00127 template <class A> 00128 derived_type& bitand_assign(const A& a) 00129 { 00130 loop_on<loops::assign_bitand_class>(this->derived(), a); 00131 return this->derived(); 00132 } 00133 00134 // bitxor_assign(), for ^= 00135 template <class A> 00136 derived_type& bitxor_assign(const A& a) 00137 { 00138 loop_on<loops::assign_bitxor_class>(this->derived(), a); 00139 return this->derived(); 00140 } 00141 00142 // bitlshift_assign(), for <<= 00143 template <class A> 00144 derived_type& bitlshift_assign(const A& a) 00145 { 00146 loop_on<loops::assign_bitlshift_class>(this->derived(), a); 00147 return this->derived(); 00148 } 00149 00150 // bitrshift_assign(), for >>= 00151 template <class A> 00152 derived_type& bitrshift_assign(const A& a) 00153 { 00154 loop_on<loops::assign_bitrshift_class>(this->derived(), a); 00155 return this->derived(); 00156 } 00157 00158 00159 // decrement(), for --. no safe/unsafe way 00160 derived_type& decrement() 00161 { 00162 //todo: unary loop 00163 this->minus_assign(1); 00164 return this->derived(); 00165 } 00166 00167 // increment(), for ++. no safe/unsafe way 00168 derived_type& increment() 00169 { 00170 //todo: unary loop 00171 this->plus_assign(1); 00172 return this->derived(); 00173 } 00174 00175 // -------------------------------------------------------- 00176 // the safe way (operator) 00177 00178 00179 //+= 00180 template <class A> 00181 derived_type& operator+=(const A& a) 00182 { 00183 safe_loop_on<loops::assign_plus_class>(this->derived(), a); 00184 return this->derived(); 00185 } 00186 00187 //-= 00188 template <class A> 00189 derived_type& operator-=(const A& a) 00190 { 00191 safe_loop_on<loops::assign_minus_class>(this->derived(), a); 00192 return this->derived(); 00193 } 00194 00195 //*= 00196 template <class A> 00197 derived_type& operator*=(const A& a) 00198 { 00199 safe_loop_on<loops::assign_times_class>(this->derived(), a); 00200 return this->derived(); 00201 } 00202 00203 // /= 00204 template <class A> 00205 derived_type& operator/=(const A& a) 00206 { 00207 safe_loop_on<loops::assign_divide_class>(this->derived(), a); 00208 return this->derived(); 00209 } 00210 00211 // %= 00212 template <class A> 00213 derived_type& operator%=(const A& a) 00214 { 00215 safe_loop_on<loops::assign_mod_class>(this->derived(), a); 00216 return this->derived(); 00217 } 00218 00219 // |= 00220 template <class A> 00221 derived_type& operator|=(const A& a) 00222 { 00223 safe_loop_on<loops::assign_bitor_class>(this->derived(), a); 00224 return this->derived(); 00225 } 00226 00227 // &= 00228 template <class A> 00229 derived_type& operator&=(const A& a) 00230 { 00231 safe_loop_on<loops::assign_bitand_class>(this->derived(), a); 00232 return this->derived(); 00233 } 00234 00235 // ^= 00236 template <class A> 00237 derived_type& operator^=(const A& a) 00238 { 00239 safe_loop_on<loops::assign_bitxor_class>(this->derived(), a); 00240 return this->derived(); 00241 } 00242 00243 // <<= 00244 template <class A> 00245 derived_type& operator<<=(const A& a) 00246 { 00247 safe_loop_on<loops::assign_bitlshift_class>(this->derived(), a); 00248 return this->derived(); 00249 } 00250 00251 // >>= 00252 template <class A> 00253 derived_type& operator>>=(const A& a) 00254 { 00255 safe_loop_on<loops::assign_bitrshift_class>(this->derived(), a); 00256 return this->derived(); 00257 } 00258 00259 // -- 00260 derived_type& operator--() 00261 { 00262 //todo: unary loop 00263 this->decrement(); 00264 return this->derived(); 00265 } 00266 00267 elem_func_unary<T, plus1_class, 00268 typename readwrite_array_common::derived_type> operator--(int) 00269 { 00270 //todo: unary loop 00271 typedef elem_func_unary<T, plus1_class, 00272 typename readwrite_array_common::derived_type> ret_t; 00273 this->decrement(); 00274 return ret_t(this->derived()); 00275 } 00276 00277 // ++ 00278 derived_type& operator++() 00279 { 00280 //todo: unary loop 00281 this->increment(); 00282 return this->derived(); 00283 } 00284 00285 elem_func_unary<T, minus1_class, 00286 typename readwrite_array_common::derived_type> operator++(int) 00287 { 00288 //todo: unary loop 00289 typedef elem_func_unary<T, minus1_class, 00290 typename readwrite_array_common::derived_type> ret_t; 00291 this->increment(); 00292 return ret_t(this->derived()); 00293 } 00294 00295 00296 template <class D> 00297 void swap(array<T, D>& a) 00298 { 00299 // This algorithm is really bad. 00300 // Needs some improvement. However this is not a priority. 00301 // Also: I need to check that arrays are of the same level. 00302 size_t tl = to_array().length(); 00303 size_t al = a.length(); 00304 size_t mxs = std::max(tl, al); 00305 bool ok; 00306 /* 00307 int mns = std::min(length(), a.length()); 00308 loops::loop_ww<write_write_swap_class, T, T>(*this, a);*/ 00309 ok = types::r_resize(to_array(), mxs); 00310 CHECK(ok, ecomp); 00311 ok = types::r_resize(a, mxs); 00312 CHECK(ok, ecomp); 00313 00314 // not fast enough. need loop with count or something. 00315 loops::loop_ww<loops::write_write_swap_class, T, T>(to_array(), a); 00316 00317 ok = types::r_resize(to_array(), al); 00318 CHECK(ok, ecomp); 00319 ok = types::r_resize(a, tl); 00320 CHECK(ok, ecomp); 00321 } 00322 00323 }; 00324 00325 00326 } /* namespace array_details */ 00327 00328 } /* namespace ivl */ 00329 00330 #endif // IVL_ARRAY_DETAILS_COMMON_READWRITE_ARRAY_COMMON_HPP