libmonaa  0.5.2
interval.hh
Go to the documentation of this file.
1 #pragma once
8 #include <cmath>
9 
10 #include "zone.hh"
11 
15 struct Interval {
17  Bounds lowerBound;
19  Bounds upperBound;
20 
27  upperBound = Bounds{std::numeric_limits<double>::infinity(), false};
28  lowerBound = {0, true};
29  }
30 
36  Interval(int lower) {
37  upperBound = Bounds{std::numeric_limits<double>::infinity(), false};
38  lowerBound = {lower, false};
39  }
40 
47  Interval(int lower, int upper) {
48  upperBound = {upper, false};
49  lowerBound = {lower, false};
50  }
51 
52  Interval(Bounds lower, Bounds upper) : lowerBound(lower), upperBound(upper) {}
53 
70  inline void plus(std::vector<std::shared_ptr<Interval>> &plusIntervals) {
71  plusIntervals.clear();
72  if (std::isinf(upperBound.first)) {
73  plusIntervals = {std::make_shared<Interval>(lowerBound, upperBound)};
74  return;
75  }
76  const int m = ceil(double(lowerBound.first) /
77  double(upperBound.first - lowerBound.first));
78  plusIntervals.reserve(m + 1);
79  for (int i = 1; i < m; i++) {
80  plusIntervals.emplace_back(std::make_shared<Interval>(
81  Bounds{lowerBound.first * i, lowerBound.second},
82  Bounds{upperBound.first * i, upperBound.second}));
83  }
84  plusIntervals.emplace_back(std::make_shared<Interval>(
85  Bounds{lowerBound.first * m, lowerBound.second},
86  Bounds{std::numeric_limits<double>::infinity(), false}));
87  }
88 
89  inline bool contain(double value) const {
90  return (lowerBound.second ? lowerBound.first <= value
91  : lowerBound.first < value) and
92  (upperBound.second ? value <= upperBound.first
93  : value < upperBound.first);
94  }
95 };
96 
98 inline static Interval operator&&(const Interval &left, const Interval &right) {
99  Interval ret = Interval{std::max(left.lowerBound, right.lowerBound),
100  std::min(left.upperBound, right.upperBound)};
101  return ret;
102 }
103 
118 inline static void land(std::vector<std::shared_ptr<Interval>> &left,
119  const Interval &right) {
120  for (auto interval : left) {
121  (*interval) = (*interval) && right;
122  }
123  left.erase(std::remove_if(left.begin(), left.end(),
124  [](std::shared_ptr<Interval> interval) {
125  return interval->lowerBound >
126  interval->upperBound;
127  }),
128  left.end());
129 }
130 
145 inline static void land(std::vector<std::shared_ptr<Interval>> &left,
146  const std::vector<std::shared_ptr<Interval>> &right) {
147  std::vector<std::shared_ptr<Interval>> tmp;
148  for (auto interval : right) {
149  std::vector<std::shared_ptr<Interval>> tmpL = left;
150  for (auto &ptr : tmpL) {
151  ptr = std::make_shared<Interval>(*ptr);
152  }
153  land(tmpL, *interval);
154  tmp.insert(tmp.end(), tmpL.begin(), tmpL.end());
155  }
156 
157 #ifdef DEBUG
158  assert(left.size() * right.size() == tmp.size());
159 #endif
160  left = tmp;
161 }
162 
168 inline static Interval operator+(Interval left, const Interval &right) {
169  left.lowerBound += right.lowerBound;
170  left.upperBound += right.upperBound;
171  return left;
172 }
173 
188 inline static void
189 operator+=(std::vector<std::shared_ptr<Interval>> &left,
190  const std::vector<std::shared_ptr<Interval>> &right) {
191  std::vector<std::shared_ptr<Interval>> ans;
192  ans.reserve(left.size() * right.size());
193  for (auto intervalLeft : left) {
194  for (auto intervalRight : right) {
195  ans.emplace_back(
196  std::make_shared<Interval>(*intervalLeft + *intervalRight));
197  }
198  }
199  left = std::move(ans);
200 }
201 
203 inline void plus(std::vector<std::shared_ptr<Interval>> &intervals) {
204  if (intervals.size() >= 32) {
205  throw "too large expression";
206  }
207  std::vector<std::vector<std::shared_ptr<Interval>>> plusIntervals;
208  plusIntervals.resize(intervals.size());
209  for (std::size_t i = 0; i < intervals.size(); i++) {
210  if (std::isinf(intervals[i]->upperBound.first)) {
211  plusIntervals[i] = {intervals[i]};
212  } else {
213  intervals[i]->plus(plusIntervals[i]);
214  }
215  }
216  if (plusIntervals.size() == 1) {
217  intervals = std::move(plusIntervals[0]);
218  return;
219  }
220 
221  std::vector<std::shared_ptr<Interval>> ansIntervals;
222  const uint32_t subsetSize = 1 << intervals.size();
223  for (uint32_t i = 1; i < subsetSize; i++) {
224  std::vector<const std::vector<std::shared_ptr<Interval>> *> subSetVec;
225  subSetVec.reserve(intervals.size());
226  for (std::size_t j = 0; j < intervals.size(); j++) {
227  if ((1 << j) & i) {
228  subSetVec.emplace_back(&(plusIntervals[j]));
229  }
230  }
231  std::vector<std::shared_ptr<Interval>> tmpIntervals = {
232  std::make_shared<Interval>(Bounds{0, true}, Bounds{0, true})};
233  for (const auto &intervals : subSetVec) {
234  tmpIntervals += *intervals;
235  }
236  ansIntervals.insert(ansIntervals.end(), tmpIntervals.begin(),
237  tmpIntervals.end());
238  }
239  intervals = std::move(ansIntervals);
240 }
241 
242 // inline static std::vector<shared_ptr<Interval>>
243 // operator&&( const Interval &&left, const Interval &&right) {
244 // Interval ret = Interval{std::max(left.lowerBound, right.lowerBound),
245 // std::min(left.upperBound, right.upperBound)};
246 // return ret;
247 // }
248 
249 inline static std::ostream &operator<<(std::ostream &stream,
250  const Interval &interval) {
251  stream << '(' << interval.lowerBound << ',' << interval.upperBound << ')';
252  return stream;
253 }
static void land(std::vector< std::shared_ptr< Interval >> &left, const Interval &right)
The intersection of a set of intervals and an interval.
Definition: interval.hh:118
static Interval operator+(Interval left, const Interval &right)
The sum of two intervals. The formal definition is as follows.
Definition: interval.hh:168
static void operator+=(std::vector< std::shared_ptr< Interval >> &left, const std::vector< std::shared_ptr< Interval >> &right)
The sum of two sets of intervals.
Definition: interval.hh:189
static Interval operator&&(const Interval &left, const Interval &right)
The intersection of two intervals.
Definition: interval.hh:98
void plus(std::vector< std::shared_ptr< Interval >> &intervals)
Definition: interval.hh:203
Class for an interval.
Definition: interval.hh:15
Interval(int lower, int upper)
Constructor returning the interval (lower, upper)
Definition: interval.hh:47
void plus(std::vector< std::shared_ptr< Interval >> &plusIntervals)
The Kleene plus operator on intervals in [Dima'00].
Definition: interval.hh:70
Bounds lowerBound
the lower bound of the interval
Definition: interval.hh:17
Bounds upperBound
the upper bound of the interval
Definition: interval.hh:19
Interval(int lower)
Constructor returning the interval (lower, ∞)
Definition: interval.hh:36
Interval()
Defail constructor.
Definition: interval.hh:26