00001 /*!@file ModelNeuron/NeuralSimUtils.H A bunch of utility classes, 00002 mostly some template idioms inspired from Alexandrescu, 2001*/ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David J. Berg <dberg@usc.edu> 00035 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/ModelNeuron/NeuralSimUtils.H$ 00036 00037 #ifndef MODELNEURON_NEURALSIMUTILS_H_DEFINED 00038 #define MODELNEURON_NEURALSIMUTILS_H_DEFINED 00039 00040 #ifdef INVT_USE_CPPOX//we need c++ 0X features for this to work 00041 00042 #include "Image/Image.H" 00043 #include "GenericUtils/GenericFactory.H" 00044 #include "GenericUtils/CreateFunctor.H" 00045 00046 #include <iterator> 00047 #include <vector> 00048 00049 namespace nsu 00050 { 00051 // ###################################################################### 00052 // Used to represent null and empty types 00053 // ###################################################################### 00054 class NullType { }; 00055 class EmptyType { }; 00056 00057 // ###################################################################### 00058 // A simple class to 'typeify' an integral constant, useful for making 00059 // decisions about possible control paths at compile time. From 00060 // Alexandrescu, 2001 00061 // ###################################################################### 00062 template <int type> 00063 struct Int2Type 00064 { 00065 enum { value = type }; 00066 }; 00067 00068 // ###################################################################### 00069 // A simple class to hold type information. This is useful as a light 00070 // weight way of choosing overloaded functions from types. From 00071 // Alexandrescu, 2001 00072 // ###################################################################### 00073 template <class Type> 00074 struct Type2Type 00075 { 00076 typedef Type type; 00077 }; 00078 00079 // ###################################################################### 00080 // A simple class to choose one of two different types, from a compile 00081 // time decision. The type an be retrieved by: 00082 // 00083 // Select<boolean expression, Class1, class2>::Result 00084 // 00085 // Where if expression is true, ::Result will be of type Class1, else ::Result 00086 // will be of type Class2 00087 // From Alexandrescu, 2001 00088 // ###################################################################### 00089 template <bool expression, class C_true, class C_false> 00090 struct SelectType //if expression is true, Type will be of C_true type. 00091 { 00092 typedef C_true Type; 00093 }; 00094 00095 template <class C_true, class C_false> 00096 struct SelectType<false, C_true, C_false> //if false, call this specialization 00097 { 00098 typedef C_false Type; 00099 }; 00100 00101 // ###################################################################### 00102 // A type traits class to deterimine properties of a template type 00103 // ###################################################################### 00104 template <typename T> 00105 class TypeTraits 00106 { 00107 private: 00108 template <class U> struct PointerTraits 00109 { 00110 enum { result = false }; 00111 typedef U PointeeType; 00112 }; 00113 00114 template <class U> struct PointerTraits <U*> 00115 { 00116 enum { result = true }; 00117 typedef U PointeeType; 00118 }; 00119 00120 public: 00121 enum { isPointer = PointerTraits<T>::result }; 00122 typedef typename PointerTraits<T>::PointeeType PointeeType; 00123 }; 00124 00125 // ###################################################################### 00126 //An extension to std::vector that handles polymorphic types. Put in a pointer to a virtual base class, but use the 00127 //access operators and iterators as if you had a non-pointer type. The virtual base must supply a clone() method which 00128 //makes a polymorphic deep copy. Derived classes must override clone() to create the correct object, and then return a 00129 //pointer to the base class. The vector will call delete on its members when they need to be destroyed. For safety, 00130 //the virtual pas should make its copy constructor and assignment operator protected or private. 00131 00132 //A non-pointer object can be supplied and the vector works like a std::vector. The template specialization mechanism 00133 //chooses the classes and functions at compile time and on modern compilers this wrapper class should incure little or 00134 //no overhead. 00135 00136 //The const/non-const iterators work just like std::vector iterators when the object is no polyphomic. When the vector 00137 //contains a polymorphic type, the iterators provided have an additional pointer() function, which returns a reference 00138 //to the underlying pointer at the iterators position in the array. Using this function could be very dangerous if you 00139 //don't know what your doing and is not reccommended, put provided for advanced uses. For polymophic classes non-const 00140 //iterators allow manipulation of the object or its pointer through pointer(). const iterators will forbid 00141 //modification of the object or its pointer through pointer(), but delete could still be called on it, so be carefull. 00142 //###################################################################### 00143 template<class T> 00144 class vector 00145 { 00146 std::vector<T> itsV; 00147 00148 public: 00149 typedef typename std::vector<T>::iterator iterator; 00150 typedef typename std::vector<T>::const_iterator const_iterator; 00151 typedef T Type; 00152 typedef EmptyType PointerType; 00153 enum {isPointer = 0 }; 00154 00155 // constructor 00156 vector() : itsV() { }; 00157 00158 // constructor 00159 vector(size_t size, const T& value) : itsV(size, value) { }; 00160 00161 //destructor 00162 ~vector() { }; 00163 00164 // return a reference 00165 T& operator[](const int pos) { return itsV[pos]; };//not save for assignment, use set_at 00166 const T& operator[](const int pos) const { return itsV[pos]; }; 00167 00168 // set an element at the specified position 00169 void set_at(const uint pos, const T& element) { itsV[pos] = element; }; 00170 00171 // push an element on 00172 void push_back(const T& element) { itsV.push_back(element); }; 00173 00174 // pop an element 00175 void pop_back() { itsV.pop_back(); }; 00176 00177 // reference to element at back 00178 T& back() { itsV.back(); }; 00179 const T& back() const { itsV.back(); }; 00180 00181 // reference to element at front 00182 T& front() { itsV.front(); }; 00183 const T& front() const { itsV.front(); }; 00184 00185 // get the size 00186 const size_t size() const {return itsV.size(); }; 00187 00188 // clear contents 00189 void clear() { itsV.clear(); }; 00190 00191 // get iterator to element at front 00192 iterator begin() { return itsV.begin(); }; 00193 const_iterator begin() const { return itsV.begin(); }; 00194 00195 //get iterator to element at back 00196 iterator end() { return itsV.end(); }; 00197 const_iterator end() const { return itsV.end(); }; 00198 00199 //return true if the element as pos is null 00200 const bool isNull(const uint pos) const {return false; }; 00201 }; 00202 00203 // ###################################################################### 00204 // specialization for pointer type 00205 // ###################################################################### 00206 template<class T> 00207 class vector<T*> //in this case, T will be the pointee type 00208 { 00209 template<class U> class cp_iterator; //forward declaration 00210 00211 //define iterator 00212 template <class U> //U will be the pointee type 00213 class p_iterator : public std::iterator<std::random_access_iterator_tag, U> 00214 { 00215 friend class cp_iterator<U>; 00216 typedef unsigned long diff_t; 00217 typedef typename std::vector<U*>::iterator v_iterator; 00218 v_iterator iter; 00219 00220 public: 00221 //constructors 00222 p_iterator() : iter() { }; 00223 p_iterator(const p_iterator& rhs) : iter(rhs.iter) { }; 00224 p_iterator(const v_iterator& rhs) : iter(rhs) { }; 00225 00226 //default assignment OK 00227 00228 //logical 00229 bool operator==(const p_iterator& rhs) const { return iter == rhs.iter; }; 00230 bool operator!=(const p_iterator& rhs) const { return iter != rhs.iter; }; 00231 bool operator<(const p_iterator& rhs) const { return iter < rhs.iter; }; 00232 bool operator<=(const p_iterator& rhs) const { return iter <= rhs.iter; }; 00233 bool operator>(const p_iterator& rhs) const { return iter > rhs.iter; }; 00234 bool operator>=(const p_iterator& rhs) const { return iter >= rhs.iter; }; 00235 00236 //increment and decrement 00237 p_iterator& operator++() { 00238 ++iter; 00239 return *this; 00240 }; 00241 p_iterator operator++(int) { 00242 p_iterator tmp = *this; 00243 ++iter; 00244 return tmp; 00245 }; 00246 void operator+=(diff_t d) { 00247 iter += d; }; 00248 p_iterator& operator--() { 00249 --iter; 00250 return *this; 00251 }; 00252 p_iterator operator--(int) { 00253 p_iterator tmp = *this; 00254 --iter; 00255 return tmp; 00256 }; 00257 void operator-=(diff_t d) { 00258 iter -= d; }; 00259 00260 //access 00261 U& operator*() { return **iter; }; 00262 U*& pointer() { return *iter; }; 00263 U* operator->() { return *iter; }; //evaluated as *( *iter ). 00264 }; 00265 00266 //define const iterator 00267 template <class U> //U will be the pointee type 00268 class cp_iterator : public std::iterator<std::random_access_iterator_tag, U> 00269 { 00270 typedef unsigned long diff_t; 00271 typedef typename std::vector<U*>::const_iterator v_iterator; 00272 v_iterator iter; 00273 00274 public: 00275 //constructors 00276 cp_iterator() : iter() { }; 00277 cp_iterator(const cp_iterator& rhs) : iter(rhs.iter) { }; 00278 cp_iterator(const p_iterator<U>& rhs) : iter(rhs.iter) { }; 00279 cp_iterator(const v_iterator& rhs) : iter(rhs) { }; 00280 00281 //default assignment OK 00282 00283 //logical 00284 bool operator==(const cp_iterator& rhs) const {return iter == rhs.iter; }; 00285 bool operator!=(const cp_iterator& rhs) const {return iter != rhs.iter; }; 00286 bool operator<(const cp_iterator& rhs) const {return iter < rhs.iter; }; 00287 bool operator<=(const cp_iterator& rhs) const {return iter <= rhs.iter; }; 00288 bool operator>(const cp_iterator& rhs) const {return iter > rhs.iter; }; 00289 bool operator>=(const cp_iterator& rhs) const {return iter >= rhs.iter; }; 00290 00291 //increment and decrement 00292 cp_iterator& operator++() { 00293 ++iter; 00294 return *this; 00295 }; 00296 cp_iterator operator++(int) { 00297 cp_iterator tmp = *this; 00298 ++iter; 00299 return tmp; 00300 }; 00301 void operator+=(diff_t d) { 00302 iter += d; }; 00303 cp_iterator& operator--() { 00304 --iter; 00305 return *this; 00306 }; 00307 cp_iterator operator--(int) { 00308 cp_iterator tmp = *this; 00309 --iter; 00310 return tmp; 00311 }; 00312 void operator-=(diff_t d) { 00313 iter -= d; }; 00314 00315 //access 00316 const U& operator*() const { return **iter; }; 00317 const U* const pointer() const { return *iter; }; 00318 const U* operator->() const { return *iter; }; //evaluated as *( *iter ). 00319 }; 00320 00321 //private members of vector<T*> 00322 //our storage container 00323 std::vector<T*> itsV; 00324 00325 //for our storage container iterator 00326 typedef typename std::vector<T*>::const_iterator v_iterator; 00327 00328 public: 00329 typedef p_iterator<T> iterator; 00330 typedef cp_iterator<T> const_iterator; 00331 typedef T Type; 00332 typedef T* PointerType; 00333 enum {isPointer = 1 }; 00334 00335 // constructor 00336 vector() : itsV() { }; 00337 00338 // constructor 00339 vector(size_t size, const T& value) : itsV() 00340 { 00341 for (uint ii = 0; ii < (uint)size; ++ii) 00342 itsV.push_back(value.clone()); 00343 }; 00344 00345 //copy constructor 00346 vector(const vector& rhs) 00347 { 00348 clear(); 00349 v_iterator i(rhs.itsV.begin()), end(rhs.itsV.end()); 00350 while (i != end) 00351 itsV.push_back( (*i++)->clone() ); 00352 }; 00353 00354 //assignment operator 00355 vector& operator=(const vector& rhs) 00356 { 00357 if (this != &rhs) 00358 { 00359 clear(); 00360 v_iterator i(rhs.itsV.begin()), end(rhs.itsV.end()); 00361 while (i != end) 00362 itsV.push_back( (*i++)->clone() ); 00363 } 00364 return *this; 00365 }; 00366 00367 //destructor 00368 ~vector() 00369 { 00370 clear(); 00371 }; 00372 00373 // return a reference 00374 T& operator[](const int pos) { return *itsV[pos]; };//not safe for assignment, use set_at 00375 const T& operator[](const int pos) const { return *itsV[pos]; }; 00376 00377 // set an element at the specified position 00378 void set_at(const uint pos, const T& element) { delete itsV[pos]; itsV[pos] = element.clone(); }; 00379 00380 // push an element on, when the element is a reference 00381 void push_back(const T& element) { itsV.push_back(element.clone()); }; 00382 00383 // pop an element 00384 void pop_back() { delete itsV.back(); itsV.pop_back(); }; 00385 00386 // reference to element at back 00387 T& back() { *itsV.back(); }; 00388 const T& back() const { *itsV.back(); }; 00389 00390 // reference to element at front 00391 T& front() { *itsV.front(); }; 00392 const T& front() const { *itsV.front(); }; 00393 00394 // get the size 00395 const size_t size() const {return itsV.size(); }; 00396 00397 // clear contents 00398 void clear() 00399 { 00400 v_iterator begin(itsV.begin()), end(itsV.end()); 00401 while (begin != end) 00402 delete *begin++; 00403 itsV.clear(); 00404 }; 00405 00406 // get iterator to element at front 00407 iterator begin() { return iterator(itsV.begin()); }; 00408 const_iterator begin() const { return const_iterator(itsV.begin()); }; 00409 00410 //get iterator to element at back 00411 iterator end() { return iterator(itsV.end()); }; 00412 const_iterator end() const { return const_iterator(itsV.end()); }; 00413 00414 //check if the element at pos is null 00415 const bool isNull(const uint pos) const { return (itsV[pos] == NULL) ? true : false; }; 00416 }; 00417 00418 // ###################################################################### 00419 // A wrapper for an iterator, that is an iterator itself. If the 00420 // iterator's ::value_type is a pointer than dereferencing this 00421 // iterator will return a reference by dereferning the pointer that 00422 // the iterator points to. If the ::value_type is not a pointer, the 00423 // iterator behaves like a normal iterator. 00424 // ###################################################################### 00425 00426 /* template <class Itr> //Itr will be an iterator 00427 class p_iterator 00428 { 00429 private: 00430 Itr iter; //the underylying iterator 00431 typedef unsigned long diff_t; 00432 00433 public: 00434 typedef typename Itr::value_type value_type; 00435 typedef typename Itr::pointer pointer; 00436 typedef typename Itr::reference reference; 00437 typedef ptrdiff_t difference_type; 00438 typedef std::random_access_iterator_tag iterator_category; 00439 00440 //constructors 00441 p_iterator(const Itr& rhs) : iter(rhs) { }; 00442 00443 //logical 00444 bool operator==(const p_iterator& rhs) const { return iter == rhs.iter; }; 00445 bool operator!=(const p_iterator& rhs) const { return iter != rhs.iter; }; 00446 bool operator<(const p_iterator& rhs) const { return iter < rhs.iter; }; 00447 bool operator<=(const p_iterator& rhs) const { return iter <= rhs.iter; }; 00448 bool operator>(const p_iterator& rhs) const { return iter > rhs.iter; }; 00449 bool operator>=(const p_iterator& rhs) const { return iter >= rhs.iter; }; 00450 00451 //increase, decrease iterator location 00452 p_iterator& operator++() { 00453 ++iter; 00454 return *this; 00455 }; 00456 p_iterator operator++(int) { 00457 p_iterator tmp = *this; 00458 ++iter; 00459 return tmp; 00460 }; 00461 void operator+=(diff_t d) 00462 { iter += d; }; 00463 p_iterator& operator--() { 00464 --iter; 00465 return *this; 00466 }; 00467 p_iterator operator--(int) { 00468 p_iterator tmp = *this; 00469 --iter; 00470 return tmp; 00471 }; 00472 void operator-=(diff_t d) 00473 { iter += d; } 00474 00475 //access correct deref and arrow function based on whether the value_type is 00476 //a pointer or not. 00477 reference operator*() 00478 { return deref( Int2Type<TypeTraits<value_type>::isPointer >() ); }; 00479 00480 pointer operator->() 00481 { return arrow( Int2Type<TypeTraits<value_type>::isPointer >() ); }; 00482 00483 //where the true or false refers to whether or not the data is polymorphic 00484 reference deref(Int2Type<false>) 00485 { return *iter; }; 00486 00487 reference deref(Int2Type<true>) 00488 { return **iter; }; 00489 00490 pointer arrow(Int2Type<false>) 00491 { return iter; }; 00492 00493 pointer arrow(Int2Type<true>) 00494 { return *iter; }; 00495 }; 00496 */ 00497 00498 /* 00499 // ###################################################################### 00500 // A simple iterator that takes a raw pointer and automatically double 00501 // dereferences pointer to pointers. 00502 // ###################################################################### 00503 template <class T> class raw_iterator 00504 { 00505 private: 00506 //declare, but do not implement default p2p_traits. This way the 00507 //whole things will bail if a non-specialization is called 00508 template <class U> struct p2p_traits; 00509 00510 //specializiation for when we are a pointer 00511 template <class U> struct p2p_traits<U*> 00512 { 00513 enum { result = false }; 00514 typedef U value_type; 00515 typedef U* pointer; 00516 typedef U& reference; 00517 }; 00518 00519 //specializiation for when we are a pointer to a pointer 00520 template <class U> struct p2p_traits<U**> 00521 { 00522 enum { result = true } ; 00523 typedef U* value_type; 00524 typedef U* pointer; 00525 typedef U& reference; 00526 }; 00527 00528 //specialization when we are a pointer to a const pointer to a U 00529 template <class U> struct p2p_traits<U* const*> 00530 { 00531 enum { result = true } ; 00532 typedef U* value_type; 00533 typedef U* pointer; 00534 typedef U& reference; 00535 }; 00536 00537 //a type for adding constants to iterators 00538 typedef unsigned long diff_t; 00539 00540 T iter;//our raw pointer 00541 00542 public: 00543 typedef typename p2p_traits<T>::value_type value_type; 00544 typedef typename p2p_traits<T>::pointer pointer; 00545 typedef typename p2p_traits<T>::reference reference; 00546 typedef typename p2p_traits<T>::value_type& mutate_type; 00547 00548 //constructors 00549 raw_iterator(const T rhs) : iter(rhs) { }; 00550 00551 //logical 00552 bool operator==(const raw_iterator& rhs) const { return iter == rhs.iter; }; 00553 bool operator!=(const raw_iterator& rhs) const { return iter != rhs.iter; }; 00554 bool operator<(const raw_iterator& rhs) const { return iter < rhs.iter; }; 00555 bool operator<=(const raw_iterator& rhs) const { return iter <= rhs.iter; }; 00556 bool operator>(const raw_iterator& rhs) const { return iter > rhs.iter; }; 00557 bool operator>=(const raw_iterator& rhs) const { return iter >= rhs.iter; }; 00558 00559 //increase, decrease iterator location 00560 raw_iterator& operator++() { 00561 ++iter; 00562 return *this; 00563 }; 00564 raw_iterator operator++(int) { 00565 raw_iterator tmp = *this; 00566 ++iter; 00567 return tmp; 00568 }; 00569 void operator+=(diff_t d) 00570 { iter += d; }; 00571 raw_iterator& operator--() { 00572 --iter; 00573 return *this; 00574 }; 00575 raw_iterator operator--(int) { 00576 raw_iterator tmp = *this; 00577 --iter; 00578 return tmp; 00579 }; 00580 void operator-=(diff_t d) 00581 { iter += d; }; 00582 00583 //access correct deref and arrow function based on whether the value_type is 00584 //a pointer or not. 00585 reference operator*() 00586 { return deref( Int2Type<p2p_traits<T>::result >() ); }; 00587 00588 pointer operator->() 00589 { return arrow( Int2Type<p2p_traits<T>::result >() ); }; 00590 00591 pointer topointer() 00592 { return arrow( Int2Type<TypeTraits<value_type>::isPointer >() ); }; 00593 00594 mutate_type mutate() 00595 { return *iter; }; 00596 00597 //where the true or false refers to whether or not the data is polymorphic 00598 reference deref(Int2Type<false>) 00599 { return *iter; }; 00600 00601 reference deref(Int2Type<true>) 00602 { return **iter; }; 00603 00604 pointer arrow(Int2Type<false>) 00605 { return iter; }; 00606 00607 pointer arrow(Int2Type<true>) 00608 { return *iter; }; 00609 }; 00610 */ 00611 00612 // ###################################################################### 00613 //This function is used when the TypeCreator template argument of a 00614 //ReusableFactory is a CreateFunctor, and one wants to set a parameter 00615 //for all CreateFunctors in the the factory by the paramters type. 00616 //###################################################################### 00617 template <typename Factory, typename... Params> 00618 void setParameter(Factory& factory, const Params&... params) 00619 { 00620 typename Factory::iterator iter = factory.begin(); 00621 while (iter != factory.end()) 00622 { 00623 iter->second.updateParams(params...); 00624 ++iter; 00625 } 00626 } 00627 }//end namespace 00628 #endif 00629 #endif 00630 // ###################################################################### 00631 /* So things look consistent in everyone's emacs... */ 00632 /* Local Variables: */ 00633 /* indent-tabs-mode: nil */ 00634 /* End: */