bpp-core3  3.0.0
Range.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_NUMERIC_RANGE_H
6 #define BPP_NUMERIC_RANGE_H
7 
8 
9 #include "../Clonable.h"
10 #include "../Text/TextTools.h"
11 
12 // From the STL:
13 #include <string>
14 #include <set>
15 #include <algorithm>
16 #include <iostream>
17 #include <cstddef>
18 
19 namespace bpp
20 {
26 template<class T> class Range :
27  public virtual Clonable
28 {
29 private:
30  T begin_;
31  T end_;
32 
33 public:
46  Range(const T& a = 0, const T& b = 0) :
47  begin_(std::min(a, b)),
48  end_(std::max(a, b))
49  {}
50 
51  Range(const Range<T>& range) : begin_(range.begin_), end_(range.end_) {}
52 
53  Range<T>& operator=(const Range<T>& range)
54  {
55  begin_ = range.begin_;
56  end_ = range.end_;
57  return *this;
58  }
59 
60  Range<T>* clone() const { return new Range<T>(*this); }
61 
62  virtual ~Range() {}
63 
64 public:
65  bool operator==(const Range<T>& r) const
66  {
67  return begin_ == r.begin_ && end_ == r.end_;
68  }
69  bool operator!=(const Range<T>& r) const
70  {
71  return begin_ != r.begin_ || end_ != r.end_;
72  }
73  bool operator<(const Range<T>& r) const
74  {
75  return begin_ < r.begin_ || end_ < r.end_;
76  }
77  virtual Range& operator+=(const T& val)
78  {
79  begin_ += val;
80  end_ += val;
81  return *this;
82  }
83  virtual Range operator+(const T& val)
84  {
85  return Range<T>(*this) += val;
86  }
87  virtual Range& operator-=(const T& val)
88  {
89  begin_ -= val;
90  end_ -= val;
91  return *this;
92  }
93  virtual Range operator-(const T& val)
94  {
95  return Range<T>(*this) -= val;
96  }
97 
98  T begin() const { return begin_; }
99 
100  T end() const { return end_; }
101 
102  T length() const { return end_ - begin_; }
103 
108  bool overlap(const Range& r) const
109  {
110  return r.begin_ < end_ && r.end_ > begin_;
111  }
112 
118  bool isContiguous(const Range& r) const
119  {
120  return r.begin_ == end_ || r.end_ == begin_;
121  }
122 
127  bool contains(const Range& r) const
128  {
129  return r.begin_ >= begin_ && r.end_ <= end_;
130  }
131 
138  void expandWith(const Range& r)
139  {
140  if (r.begin_ < begin_ && r.end_ >= begin_)
141  begin_ = r.begin_;
142  if (r.end_ > end_ && r.begin_ <= end_)
143  end_ = r.end_;
144  }
145 
152  void sliceWith(const Range& r)
153  {
154  if (!overlap(r))
155  {
156  begin_ = 0;
157  end_ = 0;
158  }
159  else
160  {
161  if (r.begin_ > begin_ && r.begin_ <= end_)
162  begin_ = r.begin_;
163  if (r.end_ < end_ && r.end_ >= begin_)
164  end_ = r.end_;
165  }
166  }
167 
171  bool isEmpty() const { return begin_ == end_; }
172 
176  std::string toString() const
177  {
178  return "[" + TextTools::toString(begin_) + "," + TextTools::toString(end_) + "[";
179  }
180 };
181 
185 template<class T> class RangeCollection
186 {
187 public:
188  virtual ~RangeCollection() {}
194  virtual void addRange(const Range<T>& r) = 0;
195 
203  virtual void restrictTo(const Range<T>& r) = 0;
204 
210  virtual void filterWithin(const Range<T>& r) = 0;
211 
215  virtual std::string toString() const = 0;
216 
220  virtual bool isEmpty() const = 0;
221 
225  virtual size_t size() const = 0;
226 
230  virtual size_t totalLength() const = 0;
231 
235  virtual const Range<T>& getRange(size_t i) const = 0;
236 
240  virtual void clear() = 0;
241 };
242 
246 template<class T> class rangeComp_
247 {
248 public:
249  bool operator()(const Range<T>* a, const Range<T>* b) const
250  {
251  return (*a) < (*b);
252  }
253 };
254 
260 template<class T> class RangeSet :
261  public virtual RangeCollection<T>
262 {
263 public:
264 
265 private:
266  std::vector< Range<T>* > ranges_;
267 
268 public:
269  RangeSet() : ranges_() {}
270 
271  RangeSet(const RangeSet<T>& set) : ranges_()
272  {
273  for (const auto& it : set.ranges_)
274  {
275  ranges_.push_back(it->clone());
276  }
277  }
278 
280  {
281  clear_();
282  for (const auto& it : set.ranges_)
283  {
284  ranges_.push_back(it->clone());
285  }
286  return *this;
287  }
288 
289  virtual ~RangeSet()
290  {
291  clear_();
292  }
293 
294 public:
295  void addRange(const Range<T>& r)
296  {
297  if (!r.isEmpty())
298  ranges_.push_back(r.clone());
299  }
300 
301  void restrictTo(const Range<T>& r)
302  {
303  auto it = ranges_.begin();
304  while (it != ranges_.end())
305  {
306  (**it).sliceWith(r);
307  if ((**it).isEmpty())
308  {
309  delete *it;
310  it = ranges_.erase(it);
311  }
312  else
313  {
314  ++it;
315  }
316  }
317  }
318 
319  void filterWithin(const Range<T>& r)
320  {
321  auto it = ranges_.begin();
322  while (it != ranges_.end())
323  {
324  if (r.contains(**it))
325  {
326  ++it;
327  }
328  else
329  {
330  delete *it;
331  it = ranges_.erase(it);
332  }
333  }
334  }
335 
336  std::string toString() const
337  {
338  std::string s = "{ ";
339  for (const auto& it : ranges_)
340  {
341  s += it->toString() + " ";
342  }
343  s += "}";
344  return s;
345  }
346 
347  bool isEmpty() const { return ranges_.size() == 0; }
348 
349  size_t size() const { return ranges_.size(); }
350 
354  size_t totalLength() const
355  {
356  size_t tot = 0;
357  for (const auto& it : ranges_)
358  {
359  tot += it->length();
360  }
361  return tot;
362  }
363 
364  const Range<T>& getRange(size_t i) const
365  {
366  return *ranges_[i];
367  }
368 
369  const std::vector< Range<T>* >& getSet() const { return ranges_; }
370 
371  std::vector< Range<T>* >& getSet() { return ranges_; }
372 
373  void clear()
374  {
375  clear_();
376  }
377 
378 private:
379  void clear_()
380  {
381  for (auto it = ranges_.begin(); it != ranges_.end(); ++it)
382  {
383  delete *it;
384  }
385  ranges_.clear();
386  }
387 };
388 
392 template<class T> class MultiRange :
393  public virtual RangeCollection<T>
394 {
395 private:
396  std::vector<Range<T>*> ranges_;
397 
398 public:
399  MultiRange() : ranges_() {}
400 
401  MultiRange(const MultiRange<T>& mr) : ranges_()
402  {
403  for (size_t i = 0; i < mr.ranges_.size(); ++i)
404  {
405  ranges_.push_back(mr.ranges_[i]->clone());
406  }
407  }
408 
410  {
411  clear_();
412  for (size_t i = 0; i < mr.ranges_.size(); ++i)
413  {
414  ranges_.push_back(mr.ranges_[i]->clone());
415  }
416  return *this;
417  }
418 
419  virtual ~MultiRange()
420  {
421  clear_();
422  }
423 
424 public:
425  void addRange(const Range<T>& r)
426  {
427  // this is a bit tricky, as many cases can happen. we have to check how many ranges overlap with the new one:
428  std::vector<size_t> overlappingPositions;
429  for (size_t i = 0; i < ranges_.size(); ++i)
430  {
431  if (ranges_[i]->overlap(r))
432  overlappingPositions.push_back(i);
433  }
434  // check if not overlap:
435  if (overlappingPositions.size() == 0)
436  {
437  // We simply add the new range to the list:
438  ranges_.push_back(r.clone());
439  }
440  else
441  {
442  // We extend the first overlapping element:
443  ranges_[overlappingPositions[0]]->expandWith(r);
444  // Now we merge all other overlapping ranges, if any:
445  for (size_t i = overlappingPositions.size() - 1; i > 0; --i)
446  {
447  // Expand first range:
448  ranges_[overlappingPositions[0]]->expandWith(*ranges_[overlappingPositions[i]]);
449  // Then removes this range:
450  delete ranges_[overlappingPositions[i]];
451  ranges_.erase(ranges_.begin() + static_cast<ptrdiff_t>(overlappingPositions[i]));
452  }
453  }
454  clean_();
455  }
456 
457  void restrictTo(const Range<T>& r)
458  {
459  for (auto& it : ranges_)
460  {
461  it->sliceWith(r);
462  }
463  clean_();
464  }
465 
466  void filterWithin(const Range<T>& r)
467  {
468  auto it = ranges_.begin();
469  while (it != ranges_.end())
470  {
471  if (r.contains(**it))
472  {
473  ++it;
474  }
475  else
476  {
477  delete *it;
478  it = ranges_.erase(it);
479  }
480  }
481  }
482 
486  std::string toString() const
487  {
488  std::string s = "{ ";
489  for (const auto& it : ranges_)
490  {
491  s += it->toString() + " ";
492  }
493  s += "}";
494  return s;
495  }
496 
500  std::vector<T> getBounds() const
501  {
502  std::vector<T> bounds;
503  for (const auto& it : ranges_)
504  {
505  bounds.push_back(it->begin());
506  bounds.push_back(it->end());
507  }
508  return bounds;
509  }
510 
514  bool isEmpty() const { return ranges_.size() == 0; }
515 
516  size_t size() const { return ranges_.size(); }
517 
518  size_t totalLength() const
519  {
520  size_t tot = 0;
521  for (const auto& it : ranges_)
522  {
523  tot += it->length();
524  }
525  return tot;
526  }
527 
528  const Range<T>& getRange(size_t i) const { return *ranges_[i]; }
529 
530  void clear()
531  {
532  clear_();
533  }
534 
535 private:
536  void clean_()
537  {
538  // Reorder
540  std::sort(ranges_.begin(), ranges_.end(), comp);
541  // Remove empty intervals:
542  auto it = ranges_.begin();
543  while (it != ranges_.end())
544  {
545  if ((**it).isEmpty())
546  {
547  delete *it;
548  it = ranges_.erase(it);
549  }
550  else
551  {
552  ++it;
553  }
554  }
555  }
556 
557 private:
558  void clear_()
559  {
560  for (size_t i = 0; i < ranges_.size(); ++i)
561  {
562  delete ranges_[i];
563  }
564  ranges_.clear();
565  }
566 };
567 } // end of namespace bpp
568 #endif // BPP_NUMERIC_RANGE_H
void expandWith(const Range &r)
Expand the current interval with the given one.
Definition: Range.h:138
RangeSet & operator=(const RangeSet< T > &set)
Definition: Range.h:279
size_t size() const
Definition: Range.h:516
Interface discribing a collection of Range objects.
Definition: Range.h:185
Range(const T &a=0, const T &b=0)
Creates a new interval.
Definition: Range.h:46
void clear_()
Definition: Range.h:379
MultiRange(const MultiRange< T > &mr)
Definition: Range.h:401
std::vector< T > getBounds() const
Definition: Range.h:500
virtual Range & operator-=(const T &val)
Definition: Range.h:87
The Range class, defining an interval.
Definition: Range.h:26
Range< T > * clone() const
Create a copy of this object and send a pointer to it.
Definition: Range.h:60
const Range< T > & getRange(size_t i) const
Definition: Range.h:364
T begin() const
Definition: Range.h:98
const std::vector< Range< T > *> & getSet() const
Definition: Range.h:369
T length() const
Definition: Range.h:102
This class implements a data structure describing a set of non-overlapping intervals.
Definition: Range.h:392
std::vector< Range< T > *> & getSet()
Definition: Range.h:371
STL namespace.
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:319
std::vector< Range< T > *> ranges_
Definition: Range.h:266
bool isEmpty() const
Definition: Range.h:171
void clear()
Clear the collection.
Definition: Range.h:530
MultiRange & operator=(const MultiRange< T > &mr)
Definition: Range.h:409
void filterWithin(const Range< T > &r)
Only keep the ranges that fall within the given range.
Definition: Range.h:466
Range(const Range< T > &range)
Definition: Range.h:51
virtual Range operator+(const T &val)
Definition: Range.h:83
void sliceWith(const Range &r)
Restrict the current interval to the intersection with the given one.
Definition: Range.h:152
std::vector< Range< T > * > ranges_
Definition: Range.h:396
std::string toString() const
Definition: Range.h:176
bool isEmpty() const
Definition: Range.h:514
A special class used inside RangeCollection.
Definition: Range.h:246
std::string toString() const
Definition: Range.h:336
std::string toString() const
Definition: Range.h:486
T end() const
Definition: Range.h:100
size_t totalLength() const
Definition: Range.h:354
Range< T > & operator=(const Range< T > &range)
Definition: Range.h:53
virtual ~MultiRange()
Definition: Range.h:419
void clear()
Clear the collection.
Definition: Range.h:373
bool operator==(const Range< T > &r) const
Definition: Range.h:65
bool isContiguous(const Range &r) const
Definition: Range.h:118
bool contains(const Range &r) const
Definition: Range.h:127
The Clonable interface (allow an object to be cloned).
Definition: Clonable.h:63
bool isEmpty() const
Definition: Range.h:347
bool comp(int a, int b)
size_t size() const
Definition: Range.h:349
virtual ~RangeCollection()
Definition: Range.h:188
bool operator()(const Range< T > *a, const Range< T > *b) const
Definition: Range.h:249
void clean_()
Definition: Range.h:536
T begin_
Definition: Range.h:30
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:295
virtual ~Range()
Definition: Range.h:62
This class implements a data structure describing a set of intervals.
Definition: Range.h:260
virtual Range operator-(const T &val)
Definition: Range.h:93
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:301
virtual ~RangeSet()
Definition: Range.h:289
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
T end_
Definition: Range.h:31
void clear_()
Definition: Range.h:558
const Range< T > & getRange(size_t i) const
Definition: Range.h:528
size_t totalLength() const
Definition: Range.h:518
bool operator!=(const Range< T > &r) const
Definition: Range.h:69
RangeSet(const RangeSet< T > &set)
Definition: Range.h:271
void restrictTo(const Range< T > &r)
Get the intersection with a given range.
Definition: Range.h:457
virtual Range & operator+=(const T &val)
Definition: Range.h:77
void addRange(const Range< T > &r)
Add a new range to the collection.
Definition: Range.h:425
bool overlap(const Range &r) const
Definition: Range.h:108