bpp-core  2.1.0
 All Classes Namespaces Files Functions Variables Typedefs Friends
Range.h
Go to the documentation of this file.
1 //
2 // File: Range.h
3 // Created by: Julien Dutheil
4 // Created on: Mon Nov 21 15:52 2011
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
9 
10  This software is a computer program whose purpose is to provide classes
11  for numerical calculus.
12 
13  This software is governed by the CeCILL license under French law and
14  abiding by the rules of distribution of free software. You can use,
15  modify and/ or redistribute the software under the terms of the CeCILL
16  license as circulated by CEA, CNRS and INRIA at the following URL
17  "http://www.cecill.info".
18 
19  As a counterpart to the access to the source code and rights to copy,
20  modify and redistribute granted by the license, users are provided only
21  with a limited warranty and the software's author, the holder of the
22  economic rights, and the successive licensors have only limited
23  liability.
24 
25  In this respect, the user's attention is drawn to the risks associated
26  with loading, using, modifying and/or developing or reproducing the
27  software by the user in light of its specific status of free software,
28  that may mean that it is complicated to manipulate, and that also
29  therefore means that it is reserved for developers and experienced
30  professionals having in-depth computer knowledge. Users are therefore
31  encouraged to load and test the software's suitability as regards their
32  requirements in conditions enabling the security of their systems and/or
33  data to be ensured and, more generally, to use and operate it in the
34  same conditions as regards security.
35 
36  The fact that you are presently reading this means that you have had
37  knowledge of the CeCILL license and that you accept its terms.
38  */
39 
40 #ifndef _RANGE_H_
41 #define _RANGE_H_
42 
43 #include "../Text/TextTools.h"
44 #include "../Clonable.h"
45 
46 //From the STL:
47 #include <string>
48 #include <set>
49 #include <algorithm>
50 
51 #include <iostream>
52 
53 namespace bpp {
54 
60 template<class T> class Range:
61  public virtual Clonable
62 {
63  private:
64  T begin_;
65  T end_;
66 
67  public:
80  Range(const T& a = 0, const T& b = 0):
81  begin_(std::min(a, b)),
82  end_(std::max(a, b))
83  {}
84 
85  Range(const Range<T>& range): begin_(range.begin_), end_(range.end_) {}
86 
87  Range<T>& operator=(const Range<T>& range) {
88  begin_ = range.begin_;
89  end_ = range.end_;
90  return *this;
91  }
92 
93  Range<T>* clone() const { return new Range<T>(*this); }
94 
95  virtual ~Range() {}
96 
97  public:
98  bool operator==(const Range<T>& r) const {
99  return begin_ == r.begin_ && end_ == r.end_;
100  }
101  bool operator!=(const Range<T>& r) const {
102  return begin_ != r.begin_ || end_ != r.end_;
103  }
104  bool operator<(const Range<T>& r) const {
105  return begin_ < r.begin_ || end_ < r.end_;
106  }
107  virtual Range& operator+=(const T& val) {
108  begin_ += val;
109  end_ += val;
110  return *this;
111  }
112  virtual Range operator+(const T& val) {
113  return Range<T>(*this) += val;
114  }
115  virtual Range& operator-=(const T& val) {
116  begin_ -= val;
117  end_ -= val;
118  return *this;
119  }
120  virtual Range operator-(const T& val) {
121  return Range<T>(*this) -= val;
122  }
123 
124  T begin() const { return begin_; }
125 
126  T end() const { return end_; }
127 
128  T length() const { return end_ - begin_; }
129 
134  bool overlap(const Range& r) const
135  {
136  return (r.begin_ < end_ && r.end_ > begin_);
137  }
138 
144  bool isContiguous(const Range& r) const
145  {
146  return (r.begin_ == end_ || r.end_ == begin_);
147  }
148 
153  bool contains(const Range& r) const
154  {
155  return (r.begin_ >= begin_ && r.end_ <= end_);
156  }
157 
164  void expandWith(const Range& r)
165  {
166  if (r.begin_ < begin_ && r.end_ >= begin_)
167  begin_ = r.begin_;
168  if (r.end_ > end_ && r.begin_ <= end_)
169  end_ = r.end_;
170  }
171 
178  void sliceWith(const Range& r)
179  {
180  if (!overlap(r)) {
181  begin_ = 0;
182  end_ = 0;
183  } else {
184  if (r.begin_ > begin_ && r.begin_ <= end_)
185  begin_ = r.begin_;
186  if (r.end_ < end_ && r.end_ >= begin_)
187  end_ = r.end_;
188  }
189  }
190 
194  bool isEmpty() const { return begin_ == end_; }
195 
199  std::string toString() const {
200  return ("[" + TextTools::toString(begin_) + "," + TextTools::toString(end_) + "[");
201  }
202 
203 };
204 
208 template<class T> class RangeCollection {
209  public:
210  virtual ~RangeCollection() {}
216  virtual void addRange(const Range<T>& r) = 0;
217 
225  virtual void restrictTo(const Range<T>& r) = 0;
226 
232  virtual void filterWithin(const Range<T>& r) = 0;
233 
237  virtual std::string toString() const = 0;
238 
242  virtual bool isEmpty() const = 0;
243 
247  virtual size_t size() const = 0;
248 
252  virtual const Range<T>& getRange(size_t i) const = 0;
253 
257  virtual void clear() = 0;
258 };
259 
263 template<class T> class rangeComp_ {
264  public:
265  bool operator() (const Range<T>* a, const Range<T>* b) const {
266  return ((*a) < (*b));
267  }
268 };
269 
275 template<class T> class RangeSet:
276  public RangeCollection<T>
277 {
278  public:
279 
280  private:
281  std::set< Range<T>*, rangeComp_<T> > ranges_;
282 
283  public:
285 
286  RangeSet(const RangeSet<T>& set): ranges_()
287  {
288  for (typename std::set< Range<T>* >::iterator it = set.ranges_.begin(); it != set.ranges_.end(); ++it) {
289  ranges_.insert(ranges_.end(), (**it).clone());
290  }
291  }
292 
294  {
295  clear_();
296  for (typename std::set< Range<T>* >::iterator it = set.ranges_.begin(); it != set.ranges_.end(); ++it) {
297  ranges_.insert(ranges_.end(), (**it).clone());
298  }
299  return *this;
300  }
301 
302  virtual ~RangeSet() {
303  clear_();
304  }
305 
306  public:
307  void addRange(const Range<T>& r) {
308  if (!r.isEmpty())
309  ranges_.insert(r.clone());
310  }
311 
312  void restrictTo(const Range<T>& r) {
313  typename std::set< Range<T>* >::iterator it = ranges_.begin();
314  while (it != ranges_.end()) {
315  (**it).sliceWith(r);
316  if ((**it).isEmpty()) {
317  typename std::set< Range<T>* >::iterator it2 = it;
318  delete *it;
319  ++it;
320  ranges_.erase(it2);
321  } else {
322  ++it;
323  }
324  }
325  }
326 
327  void filterWithin(const Range<T>& r) {
328  typename std::set< Range<T>* >::iterator it = ranges_.begin();
329  while (it != ranges_.end()) {
330  if (r.contains(**it)) {
331  ++it;
332  } else {
333  typename std::set< Range<T>* >::iterator it2 = it;
334  delete *it;
335  ++it;
336  ranges_.erase(it2);
337  }
338  }
339  }
340 
341  std::string toString() const {
342  std::string s = "{ ";
343  for (typename std::set< Range<T>* >::const_iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
344  s += (**it).toString() + " ";
345  }
346  s += "}";
347  return s;
348  }
349 
350  bool isEmpty() const { return ranges_.size() == 0; }
351 
352  size_t size() const { return ranges_.size(); }
353 
354  const Range<T>& getRange(size_t i) const {
355  typename std::set< Range<T>* >::const_iterator it = ranges_.begin();
356  for (size_t c = 0; c < i; ++c)
357  ++it;
358  //it = it++;
359  return **it;
360  }
361 
362  const std::set< Range<T>*, rangeComp_<T> >& getSet() const { return ranges_; }
363 
364  std::set< Range<T>*, rangeComp_<T> >& getSet() { return ranges_; }
365 
366  void clear() {
367  clear_();
368  }
369 
370  private:
371  void clear_() {
372  for (typename std::set< Range<T>* >::const_iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
373  delete *it;
374  }
375  ranges_.clear();
376  }
377 };
378 
382 template<class T> class MultiRange:
383  public RangeCollection<T>
384 {
385  private:
386  std::vector<Range<T>*> ranges_;
387 
388  public:
390 
392  {
393  for (size_t i = 0; i < mr.ranges_.size(); ++i)
394  ranges_.push_back(mr.ranges_[i]->clone());
395  }
396 
398  {
399  clear_();
400  for (size_t i = 0; i < mr.ranges_.size(); ++i)
401  ranges_.push_back(mr.ranges_[i]->clone());
402  return *this;
403  }
404 
405  virtual ~MultiRange() {
406  clear_();
407  }
408 
409 
410  public:
411  void addRange(const Range<T>& r) {
412  //this is a bit tricky, as many cases can happen. we have to check how many ranges overlap with the new one:
413  std::vector<size_t> overlappingPositions;
414  for (size_t i = 0; i < ranges_.size(); ++i) {
415  if (ranges_[i]->overlap(r))
416  overlappingPositions.push_back(i);
417  }
418  //check if not overlap:
419  if (overlappingPositions.size() == 0) {
420  //We simply add the new range to the list:
421  ranges_.push_back(r.clone());
422  } else {
423  //We extend the first overlapping element:
424  ranges_[overlappingPositions[0]]->expandWith(r);
425  //Now we merge all other overlapping ranges, if any:
426  for (size_t i = overlappingPositions.size() - 1; i > 0; --i) {
427  //Expand first range:
428  ranges_[overlappingPositions[0]]->expandWith(*ranges_[overlappingPositions[i]]);
429  //Then removes this range:
430  delete ranges_[overlappingPositions[i]];
431  ranges_.erase(ranges_.begin() + overlappingPositions[i]);
432  }
433  }
434  clean_();
435  }
436 
437  void restrictTo(const Range<T>& r) {
438  for (size_t i = 0; i < ranges_.size(); ++i)
439  ranges_[i]->sliceWith(r);
440  clean_();
441  }
442 
443  void filterWithin(const Range<T>& r) {
444  typename std::vector< Range<T>* >::iterator it = ranges_.begin();
445  while (it != ranges_.end()) {
446  if (r.contains(**it)) {
447  ++it;
448  } else {
449  delete *it;
450  it = ranges_.erase(it);
451  }
452  }
453  }
454 
458  std::string toString() const {
459  std::string s = "{ ";
460  for (size_t i = 0; i < ranges_.size(); ++i)
461  s += ranges_[i]->toString() + " ";
462  s += "}";
463  return s;
464  }
465 
469  std::vector<T> getBounds() const {
470  std::vector<T> bounds;
471  for (size_t i = 0; i < ranges_.size(); ++i) {
472  bounds.push_back(ranges_[i]->begin());
473  bounds.push_back(ranges_[i]->end());
474  }
475  return bounds;
476  }
477 
481  bool isEmpty() const { return ranges_.size() == 0; }
482 
483  size_t size() const { return ranges_.size(); }
484 
485  const Range<T>& getRange(size_t i) const { return *ranges_[i]; }
486 
487  void clear() {
488  clear_();
489  }
490 
491  private:
492  void clean_() {
493  //Reorder
495  std::sort(ranges_.begin(), ranges_.end(), comp);
496  //Remove empty intervals:
497  typename std::vector< Range<T>* >::iterator it = ranges_.begin();
498  while (it != ranges_.end()) {
499  if ((**it).isEmpty()) {
500  delete *it;
501  it = ranges_.erase(it);
502  } else {
503  ++it;
504  }
505  }
506  }
507  private:
508  void clear_() {
509  for (size_t i = 0; i < ranges_.size(); ++i) {
510  delete ranges_[i];
511  }
512  ranges_.clear();
513  }
514 
515 };
516 
517 } //end of namespace bpp
518 
519 #endif //_RANGE_H_