bpp-core3  3.0.0
Range.h
Go to the documentation of this file.
1 //
2 // File: Range.h
3 // Authors:
4 // Julien Dutheil
5 // Created: 2011-11-21 15:52:00
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for numerical calculus.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #ifndef BPP_NUMERIC_RANGE_H
42 #define BPP_NUMERIC_RANGE_H
43 
44 
45 #include "../Clonable.h"
46 #include "../Text/TextTools.h"
47 
48 // From the STL:
49 #include <string>
50 #include <set>
51 #include <algorithm>
52 #include <iostream>
53 #include <cstddef>
54 
55 namespace bpp
56 {
62 template<class T> class Range :
63  public virtual Clonable
64 {
65 private:
66  T begin_;
67  T end_;
68 
69 public:
82  Range(const T& a = 0, const T& b = 0) :
83  begin_(std::min(a, b)),
84  end_(std::max(a, b))
85  {}
86 
87  Range(const Range<T>& range) : begin_(range.begin_), end_(range.end_) {}
88 
89  Range<T>& operator=(const Range<T>& range)
90  {
91  begin_ = range.begin_;
92  end_ = range.end_;
93  return *this;
94  }
95 
96  Range<T>* clone() const { return new Range<T>(*this); }
97 
98  virtual ~Range() {}
99 
100 public:
101  bool operator==(const Range<T>& r) const
102  {
103  return begin_ == r.begin_ && end_ == r.end_;
104  }
105  bool operator!=(const Range<T>& r) const
106  {
107  return begin_ != r.begin_ || end_ != r.end_;
108  }
109  bool operator<(const Range<T>& r) const
110  {
111  return begin_ < r.begin_ || end_ < r.end_;
112  }
113  virtual Range& operator+=(const T& val)
114  {
115  begin_ += val;
116  end_ += val;
117  return *this;
118  }
119  virtual Range operator+(const T& val)
120  {
121  return Range<T>(*this) += val;
122  }
123  virtual Range& operator-=(const T& val)
124  {
125  begin_ -= val;
126  end_ -= val;
127  return *this;
128  }
129  virtual Range operator-(const T& val)
130  {
131  return Range<T>(*this) -= val;
132  }
133 
134  T begin() const { return begin_; }
135 
136  T end() const { return end_; }
137 
138  T length() const { return end_ - begin_; }
139 
144  bool overlap(const Range& r) const
145  {
146  return r.begin_ < end_ && r.end_ > begin_;
147  }
148 
154  bool isContiguous(const Range& r) const
155  {
156  return r.begin_ == end_ || r.end_ == begin_;
157  }
158 
163  bool contains(const Range& r) const
164  {
165  return r.begin_ >= begin_ && r.end_ <= end_;
166  }
167 
174  void expandWith(const Range& r)
175  {
176  if (r.begin_ < begin_ && r.end_ >= begin_)
177  begin_ = r.begin_;
178  if (r.end_ > end_ && r.begin_ <= end_)
179  end_ = r.end_;
180  }
181 
188  void sliceWith(const Range& r)
189  {
190  if (!overlap(r))
191  {
192  begin_ = 0;
193  end_ = 0;
194  }
195  else
196  {
197  if (r.begin_ > begin_ && r.begin_ <= end_)
198  begin_ = r.begin_;
199  if (r.end_ < end_ && r.end_ >= begin_)
200  end_ = r.end_;
201  }
202  }
203 
207  bool isEmpty() const { return begin_ == end_; }
208 
212  std::string toString() const
213  {
214  return "[" + TextTools::toString(begin_) + "," + TextTools::toString(end_) + "[";
215  }
216 };
217 
221 template<class T> class RangeCollection
222 {
223 public:
224  virtual ~RangeCollection() {}
230  virtual void addRange(const Range<T>& r) = 0;
231 
239  virtual void restrictTo(const Range<T>& r) = 0;
240 
246  virtual void filterWithin(const Range<T>& r) = 0;
247 
251  virtual std::string toString() const = 0;
252 
256  virtual bool isEmpty() const = 0;
257 
261  virtual size_t size() const = 0;
262 
266  virtual size_t totalLength() const = 0;
267 
271  virtual const Range<T>& getRange(size_t i) const = 0;
272 
276  virtual void clear() = 0;
277 };
278 
282 template<class T> class rangeComp_
283 {
284 public:
285  bool operator()(const Range<T>* a, const Range<T>* b) const
286  {
287  return (*a) < (*b);
288  }
289 };
290 
296 template<class T> class RangeSet :
297  public virtual RangeCollection<T>
298 {
299 public:
300 
301 private:
302  std::vector< Range<T>* > ranges_;
303 
304 public:
305  RangeSet() : ranges_() {}
306 
307  RangeSet(const RangeSet<T>& set) : ranges_()
308  {
309  for (const auto& it : set.ranges_)
310  {
311  ranges_.push_back(it->clone());
312  }
313  }
314 
316  {
317  clear_();
318  for (const auto& it : set.ranges_)
319  {
320  ranges_.push_back(it->clone());
321  }
322  return *this;
323  }
324 
325  virtual ~RangeSet()
326  {
327  clear_();
328  }
329 
330 public:
331  void addRange(const Range<T>& r)
332  {
333  if (!r.isEmpty())
334  ranges_.push_back(r.clone());
335  }
336 
337  void restrictTo(const Range<T>& r)
338  {
339  auto it = ranges_.begin();
340  while (it != ranges_.end())
341  {
342  (**it).sliceWith(r);
343  if ((**it).isEmpty())
344  {
345  delete *it;
346  it = ranges_.erase(it);
347  }
348  else
349  {
350  ++it;
351  }
352  }
353  }
354 
355  void filterWithin(const Range<T>& r)
356  {
357  auto it = ranges_.begin();
358  while (it != ranges_.end())
359  {
360  if (r.contains(**it))
361  {
362  ++it;
363  }
364  else
365  {
366  delete *it;
367  it = ranges_.erase(it);
368  }
369  }
370  }
371 
372  std::string toString() const
373  {
374  std::string s = "{ ";
375  for (const auto& it : ranges_)
376  {
377  s += it->toString() + " ";
378  }
379  s += "}";
380  return s;
381  }
382 
383  bool isEmpty() const { return ranges_.size() == 0; }
384 
385  size_t size() const { return ranges_.size(); }
386 
390  size_t totalLength() const
391  {
392  size_t tot = 0;
393  for (const auto& it : ranges_)
394  {
395  tot += it->length();
396  }
397  return tot;
398  }
399 
400  const Range<T>& getRange(size_t i) const
401  {
402  return *ranges_[i];
403  }
404 
405  const std::vector< Range<T>* >& getSet() const { return ranges_; }
406 
407  std::vector< Range<T>* >& getSet() { return ranges_; }
408 
409  void clear()
410  {
411  clear_();
412  }
413 
414 private:
415  void clear_()
416  {
417  for (auto it = ranges_.begin(); it != ranges_.end(); ++it)
418  {
419  delete *it;
420  }
421  ranges_.clear();
422  }
423 };
424 
428 template<class T> class MultiRange :
429  public virtual RangeCollection<T>
430 {
431 private:
432  std::vector<Range<T>*> ranges_;
433 
434 public:
436 
438  {
439  for (size_t i = 0; i < mr.ranges_.size(); ++i)
440  {
441  ranges_.push_back(mr.ranges_[i]->clone());
442  }
443  }
444 
446  {
447  clear_();
448  for (size_t i = 0; i < mr.ranges_.size(); ++i)
449  {
450  ranges_.push_back(mr.ranges_[i]->clone());
451  }
452  return *this;
453  }
454 
455  virtual ~MultiRange()
456  {
457  clear_();
458  }
459 
460 public:
461  void addRange(const Range<T>& r)
462  {
463  // this is a bit tricky, as many cases can happen. we have to check how many ranges overlap with the new one:
464  std::vector<size_t> overlappingPositions;
465  for (size_t i = 0; i < ranges_.size(); ++i)
466  {
467  if (ranges_[i]->overlap(r))
468  overlappingPositions.push_back(i);
469  }
470  // check if not overlap:
471  if (overlappingPositions.size() == 0)
472  {
473  // We simply add the new range to the list:
474  ranges_.push_back(r.clone());
475  }
476  else
477  {
478  // We extend the first overlapping element:
479  ranges_[overlappingPositions[0]]->expandWith(r);
480  // Now we merge all other overlapping ranges, if any:
481  for (size_t i = overlappingPositions.size() - 1; i > 0; --i)
482  {
483  // Expand first range:
484  ranges_[overlappingPositions[0]]->expandWith(*ranges_[overlappingPositions[i]]);
485  // Then removes this range:
486  delete ranges_[overlappingPositions[i]];
487  ranges_.erase(ranges_.begin() + static_cast<ptrdiff_t>(overlappingPositions[i]));
488  }
489  }
490  clean_();
491  }
492 
493  void restrictTo(const Range<T>& r)
494  {
495  for (auto& it : ranges_)
496  {
497  it->sliceWith(r);
498  }
499  clean_();
500  }
501 
502  void filterWithin(const Range<T>& r)
503  {
504  auto it = ranges_.begin();
505  while (it != ranges_.end())
506  {
507  if (r.contains(**it))
508  {
509  ++it;
510  }
511  else
512  {
513  delete *it;
514  it = ranges_.erase(it);
515  }
516  }
517  }
518 
522  std::string toString() const
523  {
524  std::string s = "{ ";
525  for (const auto& it : ranges_)
526  {
527  s += it->toString() + " ";
528  }
529  s += "}";
530  return s;
531  }
532 
536  std::vector<T> getBounds() const
537  {
538  std::vector<T> bounds;
539  for (const auto& it : ranges_)
540  {
541  bounds.push_back(it->begin());
542  bounds.push_back(it->end());
543  }
544  return bounds;
545  }
546 
550  bool isEmpty() const { return ranges_.size() == 0; }
551 
552  size_t size() const { return ranges_.size(); }
553 
554  size_t totalLength() const
555  {
556  size_t tot = 0;
557  for (const auto& it : ranges_)
558  {
559  tot += it->length();
560  }
561  return tot;
562  }
563 
564  const Range<T>& getRange(size_t i) const { return *ranges_[i]; }
565 
566  void clear()
567  {
568  clear_();
569  }
570 
571 private:
572  void clean_()
573  {
574  // Reorder
576  std::sort(ranges_.begin(), ranges_.end(), comp);
577  // Remove empty intervals:
578  auto it = ranges_.begin();
579  while (it != ranges_.end())
580  {
581  if ((**it).isEmpty())
582  {
583  delete *it;
584  it = ranges_.erase(it);
585  }
586  else
587  {
588  ++it;
589  }
590  }
591  }
592 
593 private:
594  void clear_()
595  {
596  for (size_t i = 0; i < ranges_.size(); ++i)
597  {
598  delete ranges_[i];
599  }
600  ranges_.clear();
601  }
602 };
603 } // end of namespace bpp
604 #endif // BPP_NUMERIC_RANGE_H
bool comp(int a, int b)
The Clonable interface (allow an object to be cloned).
Definition: Clonable.h:103
This class implements a data structure describing a set of non-overlapping intervals.
Definition: Range.h:430
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:493
size_t size() const
Definition: Range.h:552
MultiRange(const MultiRange< T > &mr)
Definition: Range.h:437
void clear_()
Definition: Range.h:594
void clean_()
Definition: Range.h:572
MultiRange & operator=(const MultiRange< T > &mr)
Definition: Range.h:445
virtual ~MultiRange()
Definition: Range.h:455
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:461
void clear()
Clear the collection.
Definition: Range.h:566
bool isEmpty() const
Definition: Range.h:550
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:502
std::string toString() const
Definition: Range.h:522
size_t totalLength() const
Definition: Range.h:554
const Range< T > & getRange(size_t i) const
Definition: Range.h:564
std::vector< Range< T > * > ranges_
Definition: Range.h:432
std::vector< T > getBounds() const
Definition: Range.h:536
Interface discribing a collection of Range objects.
Definition: Range.h:222
virtual const Range< T > & getRange(size_t i) const =0
virtual ~RangeCollection()
Definition: Range.h:224
virtual bool isEmpty() const =0
virtual void addRange(const Range< T > &r)=0
Add a new range to the collection.
virtual void filterWithin(const Range< T > &r)=0
Only keep the ranges that fall within the given range.
virtual std::string toString() const =0
virtual size_t size() const =0
virtual size_t totalLength() const =0
virtual void clear()=0
Clear the collection.
virtual void restrictTo(const Range< T > &r)=0
Get the intersection with a given range.
This class implements a data structure describing a set of intervals.
Definition: Range.h:298
std::vector< Range< T > * > ranges_
Definition: Range.h:302
const Range< T > & getRange(size_t i) const
Definition: Range.h:400
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:331
RangeSet & operator=(const RangeSet< T > &set)
Definition: Range.h:315
virtual ~RangeSet()
Definition: Range.h:325
void clear_()
Definition: Range.h:415
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:355
std::vector< Range< T > * > & getSet()
Definition: Range.h:407
const std::vector< Range< T > * > & getSet() const
Definition: Range.h:405
void clear()
Clear the collection.
Definition: Range.h:409
size_t totalLength() const
Definition: Range.h:390
RangeSet(const RangeSet< T > &set)
Definition: Range.h:307
size_t size() const
Definition: Range.h:385
bool isEmpty() const
Definition: Range.h:383
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:337
std::string toString() const
Definition: Range.h:372
The Range class, defining an interval.
Definition: Range.h:64
virtual Range operator+(const T &val)
Definition: Range.h:119
Range< T > * clone() const
Create a copy of this object and send a pointer to it.
Definition: Range.h:96
bool isContiguous(const Range &r) const
Definition: Range.h:154
T end_
Definition: Range.h:67
virtual ~Range()
Definition: Range.h:98
T length() const
Definition: Range.h:138
T begin_
Definition: Range.h:66
T end() const
Definition: Range.h:136
virtual Range & operator-=(const T &val)
Definition: Range.h:123
bool contains(const Range &r) const
Definition: Range.h:163
void sliceWith(const Range &r)
Restrict the current interval to the intersection with the given one.
Definition: Range.h:188
bool operator==(const Range< T > &r) const
Definition: Range.h:101
virtual Range & operator+=(const T &val)
Definition: Range.h:113
Range(const Range< T > &range)
Definition: Range.h:87
bool isEmpty() const
Definition: Range.h:207
bool operator!=(const Range< T > &r) const
Definition: Range.h:105
T begin() const
Definition: Range.h:134
Range< T > & operator=(const Range< T > &range)
Definition: Range.h:89
Range(const T &a=0, const T &b=0)
Creates a new interval.
Definition: Range.h:82
virtual Range operator-(const T &val)
Definition: Range.h:129
bool overlap(const Range &r) const
Definition: Range.h:144
std::string toString() const
Definition: Range.h:212
bool operator<(const Range< T > &r) const
Definition: Range.h:109
void expandWith(const Range &r)
Expand the current interval with the given one.
Definition: Range.h:174
A special class used inside RangeCollection.
Definition: Range.h:283
bool operator()(const Range< T > *a, const Range< T > *b) const
Definition: Range.h:285
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:153