bpp-core  2.2.0
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 #include <iostream>
51 #include <cstddef>
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() + static_cast<ptrdiff_t>(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_
void expandWith(const Range &r)
Expand the current interval with the given one.
Definition: Range.h:164
RangeSet & operator=(const RangeSet< T > &set)
Definition: Range.h:293
virtual bool isEmpty() const =0
size_t size() const
Definition: Range.h:483
Interface discribing a collection of Range objects.
Definition: Range.h:208
Range(const T &a=0, const T &b=0)
Creates a new interval.
Definition: Range.h:80
void clear_()
Definition: Range.h:371
MultiRange(const MultiRange< T > &mr)
Definition: Range.h:391
std::vector< T > getBounds() const
Definition: Range.h:469
virtual Range & operator-=(const T &val)
Definition: Range.h:115
The Range class, defining an interval.
Definition: Range.h:60
This class allows to perform a correspondence analysis.
virtual void restrictTo(const Range< T > &r)=0
Get the intersection with a given range.
virtual void addRange(const Range< T > &r)=0
Add a new range to the collection.
std::set< Range< T > *, rangeComp_< T > > ranges_
Definition: Range.h:281
Range< T > * clone() const
Create a copy of this object and send a pointer to it.
Definition: Range.h:93
const Range< T > & getRange(size_t i) const
Definition: Range.h:354
T begin() const
Definition: Range.h:124
T length() const
Definition: Range.h:128
This class implements a data structure describing a set of non-overlapping intervales.
Definition: Range.h:382
STL namespace.
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:327
virtual std::string toString() const =0
static std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:189
bool isEmpty() const
Definition: Range.h:194
virtual void clear()=0
Clear the collection.
void clear()
Clear the collection.
Definition: Range.h:487
MultiRange & operator=(const MultiRange< T > &mr)
Definition: Range.h:397
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:443
std::set< Range< T > *, rangeComp_< T > > & getSet()
Definition: Range.h:364
Range(const Range< T > &range)
Definition: Range.h:85
virtual Range operator+(const T &val)
Definition: Range.h:112
const std::set< Range< T > *, rangeComp_< T > > & getSet() const
Definition: Range.h:362
void sliceWith(const Range &r)
Restrict the current interval to the intersection with the given one.
Definition: Range.h:178
std::vector< Range< T > * > ranges_
Definition: Range.h:386
std::string toString() const
Definition: Range.h:199
bool isEmpty() const
Definition: Range.h:481
A special class used inside RangeCollection.
Definition: Range.h:263
std::string toString() const
Definition: Range.h:341
std::string toString() const
Definition: Range.h:458
T end() const
Definition: Range.h:126
Range< T > & operator=(const Range< T > &range)
Definition: Range.h:87
virtual ~MultiRange()
Definition: Range.h:405
void clear()
Clear the collection.
Definition: Range.h:366
bool operator==(const Range< T > &r) const
Definition: Range.h:98
bool isContiguous(const Range &r) const
Definition: Range.h:144
bool contains(const Range &r) const
Definition: Range.h:153
The Clonable interface (allow an object to be cloned).
Definition: Clonable.h:99
bool isEmpty() const
Definition: Range.h:350
virtual size_t size() const =0
bool comp(int a, int b)
size_t size() const
Definition: Range.h:352
virtual ~RangeCollection()
Definition: Range.h:210
bool operator()(const Range< T > *a, const Range< T > *b) const
Definition: Range.h:265
void clean_()
Definition: Range.h:492
T begin_
Definition: Range.h:64
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:307
virtual ~Range()
Definition: Range.h:95
This class implements a data structure describing a set of intervales.
Definition: Range.h:275
virtual Range operator-(const T &val)
Definition: Range.h:120
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:312
virtual ~RangeSet()
Definition: Range.h:302
T end_
Definition: Range.h:65
void clear_()
Definition: Range.h:508
const Range< T > & getRange(size_t i) const
Definition: Range.h:485
bool operator!=(const Range< T > &r) const
Definition: Range.h:101
RangeSet(const RangeSet< T > &set)
Definition: Range.h:286
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:437
virtual const Range< T > & getRange(size_t i) const =0
virtual Range & operator+=(const T &val)
Definition: Range.h:107
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:411
virtual void filterWithin(const Range< T > &r)=0
Only keep the ranges that fall within the given range.
bool overlap(const Range &r) const
Definition: Range.h:134