PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // TinyVector.h: Definition of a tiny vector 00004 // Copyright (c) 2002 by Nicolas Chapados 00005 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // 00009 // 1. Redistributions of source code must retain the above copyright 00010 // notice, this list of conditions and the following disclaimer. 00011 // 00012 // 2. Redistributions in binary form must reproduce the above copyright 00013 // notice, this list of conditions and the following disclaimer in the 00014 // documentation and/or other materials provided with the distribution. 00015 // 00016 // 3. The name of the authors may not be used to endorse or promote 00017 // products derived from this software without specific prior written 00018 // permission. 00019 // 00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 // 00031 // This file is part of the PLearn library. For more information on the PLearn 00032 // library, go to the PLearn Web site at www.plearn.org 00033 00034 #ifndef TINYVECTOR_H_INC 00035 #define TINYVECTOR_H_INC 00036 00037 //#include <utility> 00038 //#include <stdexcept> // for out_of_range 00039 #include <algorithm> // for lexicographical_compare 00040 #include <typeinfo> 00041 00042 #include "plerror.h" 00043 00046 namespace PLearn { 00047 using namespace std; 00048 00050 template <class T> class TinyVectorTrait; 00051 00052 00053 //############################ CLASS TINYVECTOR ######################## 00054 00072 template < class T, unsigned N, class TTrait = TinyVectorTrait<T> > 00073 class TinyVector 00074 { 00075 public: 00077 typedef T value_type; 00078 typedef size_t size_type; 00079 typedef ptrdiff_t difference_type; 00080 00081 typedef T* iterator; 00082 typedef const T* const_iterator; 00083 00084 typedef T* pointer; 00085 typedef const T* const_pointer; 00086 typedef T& reference; 00087 typedef const T& const_reference; 00088 00089 public: 00091 inline iterator begin(); 00092 inline const_iterator begin() const; 00093 inline iterator end(); 00094 inline const_iterator end() const; 00095 00096 public: 00098 inline reference operator[](size_type n); 00099 inline const_reference operator[](size_type n) const; 00100 00102 reference at(size_type n); 00103 const_reference at(size_type n) const; 00104 00105 inline reference front(); 00106 inline const_reference front() const; 00107 inline reference back(); 00108 inline const_reference back() const; 00109 00110 public: 00112 inline TinyVector(); 00113 inline explicit TinyVector(size_type n, const T& val=T()); 00115 00116 // (Disabled for now; too many ambiguities) 00117 // //! Construct/Copy from Input iterator 00118 // template <class In> 00119 // TinyVector(In first, In last) { assign(first, last); } 00120 00121 template <class In> 00122 void assign(In first, In last) { 00124 resize(last-first); 00125 for (size_type i=0; first != last && i < N; ++i, ++first) 00126 arr[i] = *first; 00127 } 00128 00129 inline void assign(size_type n, const T& val); 00130 00131 public: 00133 void push_back(const T& x); 00134 void pop_back(); 00135 00136 public: 00138 00139 public: 00141 size_type size() const; 00142 bool empty() const { 00143 return size() == 0; 00144 } 00145 size_type max_size() { 00146 return N; 00147 } 00148 void resize(size_type sz, const T& val=T()); 00149 void reserve(size_type n); 00150 00151 public: 00152 // Other functions 00153 00155 void swap(TinyVector&); 00156 00158 void fill(const T&); 00159 00161 TinyVector copy() const { return *this; } 00162 00163 private: 00164 T arr[N]; 00165 }; 00166 00167 00169 template <class T, unsigned N, class TTrait> 00170 bool operator==(const TinyVector<T,N,TTrait>&, 00171 const TinyVector<T,N,TTrait>&); 00172 00174 template <class T, unsigned N, class TTrait> 00175 bool operator<(const TinyVector<T,N,TTrait>&, 00176 const TinyVector<T,N,TTrait>&); 00177 00180 template <class T, unsigned N, class TTrait> 00181 inline bool operator!=(const TinyVector<T,N,TTrait>& x, 00182 const TinyVector<T,N,TTrait>& y) 00183 { 00184 return !(x == y); 00185 } 00186 00187 template <class T, unsigned N, class TTrait> 00188 inline bool operator> (const TinyVector<T,N,TTrait>& x, 00189 const TinyVector<T,N,TTrait>& y) 00190 { 00191 return y < x; 00192 } 00193 00194 template <class T, unsigned N, class TTrait> 00195 inline bool operator<=(const TinyVector<T,N,TTrait>& x, 00196 const TinyVector<T,N,TTrait>& y) 00197 { 00198 return !(y < x); 00199 } 00200 00201 template <class T, unsigned N, class TTrait> 00202 inline bool operator>=(const TinyVector<T,N,TTrait>& x, 00203 const TinyVector<T,N,TTrait>& y) 00204 { 00205 return !(x < y); 00206 } 00207 00209 template <class T, unsigned N, class TTrait> 00210 inline void operator<<(TinyVector<T,N,TTrait>& x, 00211 const TinyVector<T,N,TTrait>& y) 00212 { 00213 x = y; 00214 } 00215 00216 00217 //######################### CLASS TINYVECTORTRAIT ###################### 00218 00234 template <typename T> class TinyVectorTrait {}; 00235 00236 template <> class TinyVectorTrait<unsigned char> { 00237 public: 00238 static const unsigned char Missing = UCHAR_MAX; 00239 typedef unsigned IOType; 00240 }; 00241 00242 template <> class TinyVectorTrait<signed char> { 00243 public: 00244 static const signed char Missing = CHAR_MAX; 00245 typedef int IOType; 00246 }; 00247 00248 template <> class TinyVectorTrait<char> { 00249 public: 00250 static const char Missing = CHAR_MAX; 00251 typedef int IOType; 00252 }; 00253 00254 template <> class TinyVectorTrait<unsigned short> { 00255 public: 00256 static const unsigned short Missing = USHRT_MAX; 00257 typedef unsigned short IOType; 00258 }; 00259 00260 template <> class TinyVectorTrait<short> { 00261 public: 00262 static const short Missing = SHRT_MAX; 00263 typedef short IOType; 00264 }; 00265 00266 template <> class TinyVectorTrait<unsigned int> { 00267 public: 00268 static const unsigned int Missing = UINT_MAX; 00269 typedef unsigned IOType; 00270 }; 00271 00272 template <> class TinyVectorTrait<int> { 00273 public: 00274 static const int Missing = INT_MAX; 00275 typedef int IOType; 00276 }; 00277 00278 00279 //##### Implementation of Iterators ##################################### 00280 00281 template <class T, unsigned N, class TTrait> 00282 typename TinyVector<T,N,TTrait>::iterator 00283 TinyVector<T,N,TTrait>::begin() 00284 { 00286 return &arr[0]; 00287 } 00288 00289 template <class T, unsigned N, class TTrait> 00290 typename TinyVector<T,N,TTrait>::const_iterator 00291 TinyVector<T,N,TTrait>::begin() const 00292 { 00294 return &arr[0]; 00295 } 00296 00297 template <class T, unsigned N, class TTrait> 00298 typename TinyVector<T,N,TTrait>::iterator 00299 TinyVector<T,N,TTrait>::end() 00300 { 00301 return &arr[0] + size(); 00302 } 00303 00304 template <class T, unsigned N, class TTrait> 00305 typename TinyVector<T,N,TTrait>::const_iterator 00306 TinyVector<T,N,TTrait>::end() const 00307 { 00308 return &arr[0] + size(); 00309 } 00310 00311 00312 //##### Implementation of Element Access ################################ 00313 00314 template <class T, unsigned N, class TTrait> 00315 typename TinyVector<T,N,TTrait>::reference 00316 TinyVector<T,N,TTrait>::operator[](size_type n) 00317 { 00318 #ifdef BOUNDCHECK 00319 if (n >= size()) 00320 PLERROR("%s: out-of-range.",typeid(*this).name()); 00321 #endif 00322 return arr[n]; 00323 } 00324 00325 template <class T, unsigned N, class TTrait> 00326 typename TinyVector<T,N,TTrait>::const_reference 00327 TinyVector<T,N,TTrait>::operator[](size_type n) const 00328 { 00329 #ifdef BOUNDCHECK 00330 if (n >= size()) 00331 PLERROR("%s: out-of-range.",typeid(*this).name()); 00332 #endif 00333 return arr[n]; 00334 } 00335 00336 template <class T, unsigned N, class TTrait> 00337 typename TinyVector<T,N,TTrait>::reference 00338 TinyVector<T,N,TTrait>::at(size_type n) 00339 { 00341 if (n >= size()) 00342 PLERROR("%s: out-of-range.",typeid(*this).name()); 00343 00344 return arr[n]; 00345 } 00346 00347 template <class T, unsigned N, class TTrait> 00348 typename TinyVector<T,N,TTrait>::const_reference 00349 TinyVector<T,N,TTrait>::at(size_type n) const 00350 { 00352 if (n >= size()) 00353 PLERROR("%s: out-of-range.",typeid(*this).name()); 00354 00355 return arr[n]; 00356 } 00357 00358 template <class T, unsigned N, class TTrait> 00359 typename TinyVector<T,N,TTrait>::reference 00360 TinyVector<T,N,TTrait>::front() 00361 { 00362 if (empty()) 00363 PLERROR("%s: out-of-range.",typeid(*this).name()); 00364 00365 return arr[0]; 00366 } 00367 00368 template <class T, unsigned N, class TTrait> 00369 typename TinyVector<T,N,TTrait>::const_reference 00370 TinyVector<T,N,TTrait>::front() const 00371 { 00372 if (empty()) 00373 PLERROR("%s: out-of-range.",typeid(*this).name()); 00374 00375 return arr[0]; 00376 } 00377 00378 template <class T, unsigned N, class TTrait> 00379 typename TinyVector<T,N,TTrait>::reference 00380 TinyVector<T,N,TTrait>::back() 00381 { 00382 if (empty()) 00383 PLERROR("%s: out-of-range.",typeid(*this).name()); 00384 00385 return *(end()-1); 00386 } 00387 00388 template <class T, unsigned N, class TTrait> 00389 typename TinyVector<T,N,TTrait>::const_reference 00390 TinyVector<T,N,TTrait>::back() const 00391 { 00392 if (empty()) 00393 PLERROR("%s: out-of-range.",typeid(*this).name()); 00394 00395 return *(end()-1); 00396 } 00397 00398 00399 //##### Implementation of Constructors, etc. ############################ 00400 00401 template <class T, unsigned N, class TTrait> 00402 void TinyVector<T,N,TTrait>::assign(size_type n, const T& val) 00403 { 00404 if (n > N) 00405 PLERROR("%s: out-of-range.",typeid(*this).name()); 00406 00407 resize(n); 00408 for (size_type i=0; i<n; ++i) 00409 arr[i] = val; 00410 } 00411 00412 template <class T, unsigned N, class TTrait> 00413 TinyVector<T,N,TTrait>::TinyVector() 00414 { 00415 assign(static_cast<size_type>(N), 00416 static_cast<const T&>(TTrait::Missing)); 00417 } 00418 00419 template <class T, unsigned N, class TTrait> 00420 TinyVector<T,N,TTrait>::TinyVector(size_type n, const T& val) 00421 { 00422 assign(n, val); 00423 if (n<N) 00424 for (size_type i=n; i<N; ++i) 00425 arr[i] = TTrait::Missing; 00426 } 00427 00428 00429 //##### Implementation of Stack Operations ############################## 00430 00431 template <class T, unsigned N, class TTrait> 00432 void TinyVector<T,N,TTrait>::push_back(const T& x) 00433 { 00434 size_type s = size(); 00435 if (s >= N) 00436 PLERROR("%s: out-of-range.",typeid(*this).name()); 00437 00438 arr[s] = x; 00439 } 00440 00441 template <class T, unsigned N, class TTrait> 00442 void TinyVector<T,N,TTrait>::pop_back() 00443 { 00444 size_type s = size(); 00445 if (s == 0) 00446 PLERROR("%s: out-of-range.",typeid(*this).name()); 00447 00448 arr[s-1] = TTrait::Missing; 00449 } 00450 00451 00452 //##### Implementation of Size/Capacity Operations ###################### 00453 00454 template <class T, unsigned N, class TTrait> 00455 typename TinyVector<T,N,TTrait>::size_type 00456 TinyVector<T,N,TTrait>::size() const 00457 { 00458 difference_type p = N-1; 00459 00460 while (p >= 0 && arr[p] == static_cast<T>(TTrait::Missing)) 00461 p--; 00462 return p+1; 00463 } 00464 00465 template <class T, unsigned N, class TTrait> 00466 void TinyVector<T,N,TTrait>::resize(size_type sz, const T& val) 00467 { 00468 if (sz > max_size()) 00469 PLERROR("%s: out-of-range.",typeid(*this).name()); 00470 00471 size_type s = size(); 00472 while (s < sz) 00473 arr[s++] = val; 00474 while (sz < N) 00475 arr[sz++] = TTrait::Missing; 00476 } 00477 00478 template <class T, unsigned N, class TTrait> 00479 void TinyVector<T,N,TTrait>::reserve(size_type n) 00480 { 00481 if (n > max_size()) 00482 PLERROR("%s: out-of-range.",typeid(*this).name()); 00483 00484 } 00485 00486 00487 //##### Implementation of Other Functions ############################### 00488 00489 template <class T, unsigned N, class TTrait> 00490 void TinyVector<T,N,TTrait>::swap(TinyVector<T,N,TTrait>& other) 00491 { 00492 using namespace std; 00493 00494 for (size_type i=0; i<N; ++i) 00495 swap(arr[i], other.arr[i]); 00496 } 00497 00498 template <class T, unsigned N, class TTrait> 00499 void TinyVector<T,N,TTrait>::fill(const T& value) 00500 { 00501 for (int i=0, n=size() ; i<n ; ++i) 00502 arr[i] = value; 00503 } 00504 00505 template <class T, unsigned N, class TTrait> 00506 bool operator==(const TinyVector<T,N,TTrait>& x, 00507 const TinyVector<T,N,TTrait>& y) 00508 { 00509 bool equal = true; 00510 typename TinyVector<T,N,TTrait>::const_iterator 00511 xit=x.begin(), xend=x.end(), yit=y.begin(), yend=y.end(); 00512 if (xend-xit != yend-yit) 00513 return false; 00514 for ( ; equal && xit != xend && yit != yend ; ++xit, ++yit) 00515 equal = (*xit == *yit); 00516 return equal; 00517 } 00518 00519 template <class T, unsigned N, class TTrait> 00520 bool operator<(const TinyVector<T,N,TTrait>& x, 00521 const TinyVector<T,N,TTrait>& y) 00522 { 00523 return std::lexicographical_compare(x.begin(), x.end(), 00524 y.begin(), y.end()); 00525 } 00526 00527 } // end of namespace PLearn 00528 00529 #endif // TINYVECTOR_H_INC 00530 00531 00532 /* 00533 Local Variables: 00534 mode:c++ 00535 c-basic-offset:4 00536 c-file-style:"stroustrup" 00537 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00538 indent-tabs-mode:nil 00539 fill-column:79 00540 End: 00541 */ 00542 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :