00001
00002
00008 #if !defined(__ads_array_IndexRange_h__)
00009 #define __ads_array_IndexRange_h__
00010
00011 #include "FixedArray.h"
00012
00013 #include "../iterator/TrivialOutputIterator.h"
00014 #include "../utility/string.h"
00015
00016 #include <iostream>
00017 #include <string>
00018 #include <sstream>
00019
00020 BEGIN_NAMESPACE_ADS
00021
00023
00036 template<int N, typename T = int>
00037 class IndexRange {
00038
00039
00040
00041
00042 public:
00043
00045 typedef T index_type;
00047 typedef FixedArray<N,index_type> multi_index_type;
00048
00049
00050
00051
00052
00053 private:
00054
00055 multi_index_type _lbounds, _ubounds;
00056
00057 public:
00058
00059
00061
00062
00064 IndexRange() :
00065 _lbounds(index_type(0)),
00066 _ubounds(index_type(0))
00067 {}
00068
00070 IndexRange(const index_type ubound) :
00071 _lbounds(index_type(0)),
00072 _ubounds(ubound) {
00073 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00074 }
00075
00077 IndexRange(const multi_index_type& ubounds) :
00078 _lbounds(index_type(0)),
00079 _ubounds(ubounds)
00080 {}
00081
00083 IndexRange(const multi_index_type& lbounds,
00084 const multi_index_type& ubounds) :
00085 _lbounds(lbounds),
00086 _ubounds(ubounds)
00087 {}
00088
00090 IndexRange(const index_type lb0, const index_type ub0) :
00091 _lbounds(lb0),
00092 _ubounds(ub0) {
00093 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00094 }
00095
00097 IndexRange(const index_type lb0, const index_type lb1,
00098 const index_type ub0, const index_type ub1) :
00099 _lbounds(lb0, lb1),
00100 _ubounds(ub0, ub1) {
00101 LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00102 }
00103
00105 IndexRange(const index_type lb0,
00106 const index_type lb1,
00107 const index_type lb2,
00108 const index_type ub0,
00109 const index_type ub1,
00110 const index_type ub2) :
00111 _lbounds(lb0, lb1, lb2),
00112 _ubounds(ub0, ub1, ub2) {
00113 LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00114 }
00115
00117 IndexRange(const IndexRange& x) :
00118 _lbounds(x._lbounds),
00119 _ubounds(x._ubounds)
00120 {}
00121
00123 ~IndexRange()
00124 {}
00125
00126
00127
00129
00130
00132 IndexRange&
00133 operator=(const IndexRange& other) {
00134 if (&other != this) {
00135 _lbounds = other._lbounds;
00136 _ubounds = other._ubounds;
00137 }
00138 return *this;
00139 }
00140
00141
00142
00144
00145
00146 void
00147 swap(IndexRange& other) {
00148 _lbounds.swap(other._lbounds);
00149 _ubounds.swap(other._ubounds);
00150 }
00151
00152
00153
00155
00156
00158 static
00159 int
00160 dimension() {
00161 return N;
00162 }
00163
00164
00165
00167
00168
00170 const multi_index_type&
00171 lbounds() const {
00172 return _lbounds;
00173 }
00174
00176 const multi_index_type&
00177 ubounds() const {
00178 return _ubounds;
00179 }
00180
00182 index_type
00183 lbound(const index_type i) const {
00184 return _lbounds[i];
00185 }
00186
00188 index_type
00189 ubound(const index_type i) const {
00190 return _ubounds[i];
00191 }
00192
00194
00197 multi_index_type
00198 extents() const {
00199 return _ubounds - _lbounds;
00200 }
00201
00203 index_type
00204 content() const {
00205 return computeProduct(extents());
00206 }
00207
00209 bool
00210 empty() const {
00211 for (int i = 0; i != N; ++i) {
00212 if (_ubounds[i] <= _lbounds[i]) {
00213 return true;
00214 }
00215 }
00216 return false;
00217 }
00218
00220 bool
00221 is_in(const multi_index_type& x) const {
00222 for (int i = 0; i != N; ++i) {
00223 if (x[i] < _lbounds[i] || _ubounds[i] <= x[i]) {
00224 return false;
00225 }
00226 }
00227 return true;
00228 }
00229
00231
00234 bool
00235 is_in(const index_type x) const {
00236 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00237 return (_lbounds[0] <= x && x < _ubounds[0]);
00238 }
00239
00241
00244 bool
00245 is_in(const index_type x, const index_type y) const {
00246 LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00247 return (_lbounds[0] <= x && x < _ubounds[0] &&
00248 _lbounds[1] <= y && y < _ubounds[1]);
00249 }
00250
00252
00255 bool
00256 is_in(const index_type x, const index_type y, const index_type z) const {
00257 LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00258 return (_lbounds[0] <= x && x < _ubounds[0] &&
00259 _lbounds[1] <= y && y < _ubounds[1] &&
00260 _lbounds[2] <= z && z < _ubounds[2]);
00261 }
00262
00263
00264
00266
00267
00268
00270 index_type
00271 lbound() const {
00272 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00273 return lbounds()[0];
00274 }
00275
00277 index_type
00278 ubound() const {
00279 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00280 return ubounds()[0];
00281 }
00282
00284
00287 index_type
00288 extent() const {
00289 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00290 return ubound() - lbound();
00291 }
00292
00293
00294
00296
00297
00299 void
00300 set_lbounds(const multi_index_type& lbounds) {
00301 _lbounds = lbounds;
00302 }
00303
00305 void
00306 set_ubounds(const multi_index_type& ubounds) {
00307 _ubounds = ubounds;
00308 }
00309
00311
00314 void
00315 set_lbounds(const index_type lb0) {
00316 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00317 _lbounds[0] = lb0;
00318 }
00319
00321
00324 void
00325 set_ubounds(const index_type ub0) {
00326 LOKI_STATIC_CHECK(N == 1, DimensionMustBe1);
00327 _ubounds[0] = ub0;
00328 }
00329
00331
00334 void
00335 set_lbounds(const index_type lb0, const index_type lb1) {
00336 LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00337 _lbounds[0] = lb0;
00338 _lbounds[1] = lb1;
00339 }
00340
00342
00345 void
00346 set_ubounds(const index_type ub0, const index_type ub1) {
00347 LOKI_STATIC_CHECK(N == 2, DimensionMustBe2);
00348 _ubounds[0] = ub0;
00349 _ubounds[1] = ub1;
00350 }
00351
00353
00356 void
00357 set_lbounds(const index_type lb0, const index_type lb1,
00358 const index_type lb2) {
00359 LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00360 _lbounds[0] = lb0;
00361 _lbounds[1] = lb1;
00362 _lbounds[2] = lb2;
00363 }
00364
00366
00369 void
00370 set_ubounds(const index_type ub0, const index_type ub1,
00371 const index_type ub2) {
00372 LOKI_STATIC_CHECK(N == 3, DimensionMustBe3);
00373 _ubounds[0] = ub0;
00374 _ubounds[1] = ub1;
00375 _ubounds[2] = ub2;
00376 }
00377
00378
00379
00381
00382
00384 void
00385 set_lbound(const index_type lbound) {
00386 set_lbounds(lbound);
00387 }
00388
00390 void
00391 set_ubound(const index_type ubound) {
00392 set_ubounds(ubound);
00393 }
00394
00395
00396
00398
00399
00400 bool
00401 operator==(const IndexRange& x) const {
00402 return _lbounds == x.lbounds() && _ubounds == x.ubounds();
00403 }
00404
00405
00406
00408
00409
00411 void
00412 put(std::ostream& out) const {
00413 out << _lbounds << " " << _ubounds;
00414 }
00415
00417
00421 void
00422 get(std::istream& in) {
00423
00424
00425 std::string line;
00426
00427 do {
00428
00429 std::getline(in, line);
00430 } while (line.empty() && in.good());
00431
00432 const int Size = ads::split(line, " ",
00433 ads::constructTrivialOutputIterator());
00434
00435 if (Size == N) {
00436
00437 _lbounds = 0;
00438
00439 std::istringstream stream(line);
00440 stream >> _ubounds;
00441 }
00442
00443 else if (Size == 2 * N) {
00444
00445 std::istringstream stream(line);
00446 stream >> _lbounds >> _ubounds;
00447 }
00448
00449 else {
00450 std::cerr
00451 << "Error in reading an IndexRange:\n"
00452 << "Wrong number of numbers. We expected either " << N
00453 << " or " << 2 * N << "\n"
00454 << "but got " << Size << "\n";
00455 assert(false);
00456 }
00457 }
00458
00460 void
00461 write(std::ostream& out) const {
00462 _lbounds.write(out);
00463 _ubounds.write(out);
00464 }
00465
00467 void
00468 read(std::istream& in) {
00469 _lbounds.read(in);
00470 _ubounds.read(in);
00471 }
00472
00474 };
00475
00476
00477
00478
00479
00480
00481 #if 0
00482
00483
00484 template<int N, typename T>
00485 inline
00486 bool
00487 operator==(const IndexRange<N,T>& a, const IndexRange<N,T>& b) {
00488 return a.is_equal(b);
00489 }
00490 #endif
00491
00493
00494 template<int N, typename T>
00495 inline
00496 bool
00497 operator!=(const IndexRange<N,T>& a, const IndexRange<N,T>& b) {
00498 return !(a == b);
00499 }
00500
00501
00502
00503
00504
00505
00507
00510 template<int N, typename T>
00511 inline
00512 std::ostream&
00513 operator<<(std::ostream& out, const IndexRange<N,T>& x) {
00514 x.put(out);
00515 return out;
00516 }
00517
00519
00522 template<int N, typename T>
00523 inline
00524 std::istream&
00525 operator>>(std::istream& in, IndexRange<N,T>& x) {
00526 x.get(in);
00527 return in;
00528 }
00529
00530
00531
00532
00533
00535
00536 template<int N, typename T>
00537 inline
00538 void
00539 compute_intersection(const IndexRange<N,T>& x, const IndexRange<N,T>& y,
00540 IndexRange<N,T>& result) {
00541 typename IndexRange<N,T>::multi_index_type lower, upper;
00542 for (int n = 0; n != N; ++n) {
00543 lower[n] = std::max(x.lbound(n), y.lbound(n));
00544 upper[n] = std::min(x.ubound(n), y.ubound(n));
00545
00546 upper[n] = std::max(lower[n], upper[n]);
00547 }
00548 result.set_lbounds(lower);
00549 result.set_ubounds(upper);
00550 }
00551
00552
00553 END_NAMESPACE_ADS
00554
00555 #endif