00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef SHTTL_ARRAY2D_H
00033 #define SHTTL_ARRAY2D_H
00034
00035 #include <cmath>
00036 #include <limits>
00037 #include <stdexcept>
00038 #include <iterator>
00039 #include <memory>
00040
00041 #include "shttl_types.h"
00042
00043 namespace shttl
00044 {
00045
00046
00047 template<class T, class Allocator = std::allocator<T> >
00048 class array2d
00049 {
00050 public:
00051
00052
00053
00054 typedef T value_type;
00055 typedef size_t size_type;
00056 typedef std::allocator<T> allocator_type;
00057 typedef T& reference;
00058 typedef const T& const_reference;
00059 typedef ssize_t difference_type;
00060 typedef T* pointer;
00061 typedef const T* const_pointer;
00062
00063 typedef array2d<T> this_type;
00064
00065 static const std::numeric_limits<size_type> size_info;
00066
00067
00068 protected:
00069
00070
00071 class _iterator_base
00072 {
00073 protected:
00074
00075 size_type _r;
00076 size_type _c;
00077
00078 const size_type _col;
00079
00080
00081 _iterator_base(
00082 const size_type r,
00083 const size_type c,
00084 const size_type col
00085 ) :
00086 _r(r), _c(c), _col(col)
00087 {
00088 }
00089
00090 public:
00091
00092
00093
00094 size_type row() const { return _r; }
00095 size_type col() const { return _c; }
00096
00097
00098
00099 bool operator==(const _iterator_base& rhs) const
00100 { return _r == rhs._r && _c == rhs._c; }
00101 bool operator!=(const _iterator_base& rhs) const
00102 { return !(*this == rhs); }
00103 bool operator<(const _iterator_base& rhs) const
00104 { return std::make_pair(_r, _c) < std::make_pair(rhs._r, rhs._c); }
00105 bool operator<=(const _iterator_base& rhs) const
00106 { return std::make_pair(_r, _c) <= std::make_pair(rhs._r, rhs._c); }
00107 bool operator>(const _iterator_base& rhs) const
00108 { return std::make_pair(_r, _c) > std::make_pair(rhs._r, rhs._c); }
00109 bool operator>=(const _iterator_base& rhs) const
00110 { return std::make_pair(_r, _c) >= std::make_pair(rhs._r, rhs._c); }
00111
00112 _iterator_base& operator+=(const size_type c)
00113 {
00114 const size_type cc = _c + c;
00115 if (cc < _col) {
00116 _c = cc;
00117 } else {
00118 _c = cc % _col;
00119 _r += cc / _col;
00120 }
00121 return *this;
00122 }
00123
00124 _iterator_base& operator-=(const size_type c)
00125 {
00126 const size_type cc = _c - c;
00127 if (cc > 0) {
00128 _c = cc;
00129 } else {
00130 _c = cc % _col;
00131 _r += cc / _col;
00132 }
00133 return *this;
00134 }
00135 };
00136
00137 public:
00138
00139 class const_iterator :
00140 public _iterator_base,
00141 public std::iterator<std::random_access_iterator_tag, T>
00142 {
00143 private:
00144
00145 const this_type* const _a;
00146
00147 using _iterator_base::_r;
00148 using _iterator_base::_c;
00149
00150 public:
00151
00152 const_iterator(
00153 const this_type* const a,
00154 const size_type r,
00155 const size_type c
00156 ) :
00157 _iterator_base(r, c, a->cols()),
00158 _a(a)
00159 {
00160 }
00161
00162 bool operator==(const const_iterator& rhs) const
00163 {
00164 return _iterator_base::operator==(rhs) && _a == rhs._a;
00165 }
00166
00167 bool operator!=(const const_iterator& rhs) const
00168 {
00169 return _iterator_base::operator!=(rhs) || _a != rhs._a;
00170 }
00171
00172 const_iterator operator+(const size_type c) const
00173 {
00174 const_iterator r = *this;
00175 return r._iterator_base.operator+=(c);
00176 }
00177
00178 const_iterator operator-(const size_type c) const
00179 {
00180 const_iterator r = *this;
00181 return r._iterator_base::operator-=(c);
00182 }
00183
00184 const T& operator[](const size_type c) const
00185 {
00186 const_iterator i = *this + c;
00187 return *i;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 const_reference operator*()
00201 {
00202 #ifdef SHTTL_DEBUG
00203 if (_r < 0 || _a->rows() < _r ||
00204 _c < 0 || _a->cols() < _c
00205 ){
00206 throw std::out_of_range("array2d::const_iterator::operator T*");
00207 }
00208 #endif
00209
00210 return _a->_ptr[(_r << _a->_col_bit) + _c];
00211 }
00212 };
00213
00214
00215 class iterator :
00216 public _iterator_base,
00217 public std::iterator<std::random_access_iterator_tag, T>
00218 {
00219 private:
00220
00221 this_type* const _a;
00222
00223 using _iterator_base::_r;
00224 using _iterator_base::_c;
00225
00226 public:
00227
00228 iterator(
00229 this_type* const a,
00230 const size_type r,
00231 const size_type c
00232 ) :
00233 _iterator_base(r, c, a->cols()),
00234 _a(a)
00235 {
00236 }
00237
00238 iterator operator+(const size_type c) const
00239 {
00240 iterator r = *this;
00241 r._iterator_base::operator+=(c);
00242 return r;
00243 }
00244
00245 iterator operator-(const size_type c) const
00246 {
00247 iterator r = *this;
00248 r._iterator_base::operaotr-=(c);
00249 return r;
00250 }
00251
00252 iterator& operator+=(const size_type c)
00253 {
00254 this->_iterator_base::operator+=(c);
00255 return *this;
00256 }
00257
00258 iterator& operator-=(const size_type c)
00259 {
00260 this->_iterator_base::operator-=(c);
00261 return *this;
00262 }
00263
00264 iterator& operator++()
00265 {
00266 return *this += 1;
00267 }
00268
00269 iterator& operator--()
00270 {
00271 return *this -= 1;
00272 }
00273
00274 iterator& operator++(int)
00275 {
00276 iterator r = *this;
00277 *this += 1;
00278 return r;
00279 }
00280
00281 iterator& operator--(int)
00282 {
00283 iterator r = *this;
00284 *this -= 1;
00285 return r;
00286 }
00287
00288 T& operator[](const size_type c)
00289 {
00290 iterator i = *this + c;
00291 return *i;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 T& operator *()
00307 {
00308 #ifdef SHTTL_DEBUG
00309 if (_r < 0 || _a->rows() < _r ||
00310 _c < 0 || _a->cols() < _c
00311 ){
00312 throw std::out_of_range("array2d::const_iterator::operator T*");
00313 }
00314 #endif
00315
00316 return _a->_ptr[(_r << _a->_col_bit) + _c];
00317 }
00318 };
00319
00320 protected:
00321
00322
00323
00324 const size_type _row;
00325 const size_type _col;
00326 const size_type _col_bit;
00327
00328 value_type* const _ptr;
00329
00330 allocator_type _a;
00331
00332 public:
00333
00334
00335
00336 size_type rows() const { return _row; }
00337 size_type cols() const { return _col; }
00338 size_type size() const { return rows() * cols(); }
00339 size_type max_size() const { return size(); }
00340
00341
00342
00343
00344 private:
00345
00346
00347
00348
00349
00350 size_type _c2b(const size_type c) const
00351 {
00352 if (c <= 0)
00353 throw std::invalid_argument("array2d::_c2b");
00354
00355 const double log2c = log(static_cast<double>(c)) / log(2.0);
00356 return static_cast<size_type>(ceil(log2c));
00357 }
00358
00359 public:
00360
00361 explicit array2d(
00362 const size_type c,
00363 const size_type r,
00364 const T& t = T()
00365 ) :
00366 _row(r), _col(c),
00367 _col_bit(_c2b(c)),
00368 _ptr(_a.allocate((size_t)r << _col_bit))
00369 {
00370 if (r <= 0 || c <= 0)
00371 throw std::invalid_argument("array2d::array2d");
00372
00373 for (size_type i = 0; i < (r << _col_bit); ++i)
00374 _ptr[i] = t;
00375 }
00376
00377 ~array2d()
00378 {
00379 for (size_type i = 0; i < (rows() << _col_bit); ++i)
00380 _a.destroy(_ptr + i);
00381 _a.deallocate(_ptr, (size_t)rows() << _col_bit);
00382 }
00383
00384
00385
00386 const const_iterator operator[](const size_type r) const
00387 {
00388 #ifdef SHTTL_DEBUG
00389 if (r < 0 || rows() <= r)
00390 throw std::out_of_range("array2d::operator[]");
00391 #endif
00392
00393 return const_iterator(this, r, 0);
00394 }
00395
00396 iterator operator[](const size_type r)
00397 {
00398 #ifdef SHTTL_DEBUG
00399 if (r < 0 || rows() <= r)
00400 throw std::out_of_range("array2d::operator[]");
00401 #endif
00402
00403 return iterator(this, r, 0);
00404 }
00405
00406
00407
00408
00409 const_iterator begin() const
00410 {
00411 return const_iteraotr(this, 0, 0);
00412 }
00413 const_iterator end() const
00414 {
00415 return const_iterator(this, size(), 0);
00416 }
00417 iterator begin()
00418 {
00419 return iterator(this, 0, 0);
00420 }
00421 iterator end()
00422 {
00423 return iterator(this, size(), 0);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 };
00436
00437 }
00438
00439 #endif // SHTTL_ARRAY2D_H