artdaq_mfextensions  v1_06_02
ma_domain_ops.h
1 #ifndef ERROR_HANDLER_MA_DOMAIN_OPS_H
2 #define ERROR_HANDLER_MA_DOMAIN_OPS_H
3 
4 #include "ErrorHandler/MessageAnalyzer/ma_types.h"
5 
6 namespace novadaq {
7 namespace errorhandler {
8 
9 // ----------------------------------------------------------------
10 // intersection of domains
11 
12 // element op
13 inline int and_op(int i, int j);
14 
15 // 1. (s_out, t_out) = (s1, t1) n (s2, t2), in-place and
16 // intersection of two cond_domain objects
17 inline ma_cond_domain&
18 domain_intersect(ma_cond_domain& d1, ma_cond_domain const& d2);
19 
20 // copy version
21 inline ma_cond_domain
22 domain_intersect_copy(ma_cond_domain d1, ma_cond_domain const& d2);
23 
24 // 2. (s_out, t_out) = (s1, t1) n (s2, t2) n ... n (s_n, t_n), in-place and
25 // intersection of multiple cond_domain objects
26 inline ma_cond_domain&
27 domain_intersect(ma_cond_domains& d);
28 
29 // copy version
30 inline ma_cond_domain
31 domain_intersect_copy(ma_cond_domains d);
32 
33 // 3. intersection of two domain objects, result stores in the first
34 inline ma_domain&
35 domain_intersect(ma_domain& d1, ma_domain const& d2);
36 
37 // copy version
38 inline ma_domain
39 domain_intersect_copy(ma_domain d1, ma_domain const& d2);
40 
41 // 4. (so1, to1), (so2, to2) ...
42 // = (s1_1, t1_1) n (s1_2, t1_2) n (s1_3, t1_3) ... ,
43 // (s2_1, t2_1) n (s2_2, t2_2) n (s2_3, t2_3) ... ,
44 // ...
45 // intersection of multiple ma_domain objects
46 // in-place calculation, result will be placed in d[0]
47 inline ma_domain&
48 domain_intersect(ma_domains& d);
49 
50 // copy version
51 inline ma_domain
52 domain_intersect_copy(ma_domains d);
53 
54 // ----------------------------------------------------------------
55 // union of domains
56 
57 // element op -- test if a contains(>=) b
58 inline bool contains_op(int a, int b);
59 
60 // 0. compare two cond_domains see if they contain one to another
61 enum domain_compare_result_t
62 {
63  NO_COMMON,
64  EQUAL,
65  L_CONTAINS,
66  R_CONTAINS
67 };
68 
69 inline domain_compare_result_t
70 domain_compare(ma_cond_domain const& d1, ma_cond_domain const& d2);
71 
72 // 1. add a new cond_domain to a list of cond_domains
73 inline ma_cond_domains&
74 domain_union(ma_cond_domains& ds, ma_cond_domain const& new_d);
75 
76 // 2. (s1_1, t1_1) U (s1_2, t1_2) U (s1_3, t1_3) ... ,
77 // (s2_1, t2_1) U (s2_2, t2_2) U (s2_3, t2_3) ... ,
78 // ...
79 // * in-place union
80 inline ma_domains&
81 domain_union(ma_domains& ds);
82 
83 // utility functions
84 inline bool
85 domain_is_null(ma_cond_domain const& d);
86 
87 inline bool
88 domain_is_null(ma_domain const& d);
89 
90 inline void
91 domain_union_construct(ma_domains& ds, ma_domain& d, std::vector<ma_cond_domains>& mid, int depth, int max);
92 
93 // construct a null ma_cond_domain (nil, nil)
94 inline ma_cond_domain
95 ma_cond_domain_ctor_null();
96 
97 // construct a any ma_cond_domain (*,*)
98 inline ma_cond_domain
99 ma_cond_domain_ctor_any();
100 
101 // construct a ma_cond_domain from s and t
102 inline ma_cond_domain
103 ma_cond_domain_ctor(int s, int t);
104 
105 // construct a ma_cond_domain from a value and arg type (source or target)
106 // ends up with a ma_cond_domain of (i,*) or (*,i)
107 inline ma_cond_domain
108 ma_cond_domain_ctor(int i, arg_t t);
109 
110 // construct a null ma_domain
111 inline ma_domain
112 ma_domain_ctor_null();
113 
114 // construct a null ma_domain
115 inline ma_domain
116 ma_domain_ctor_null(size_t size);
117 
118 // construct a any ma_domain with size s
119 inline ma_domain
120 ma_domain_ctor_any(size_t size);
121 
122 // construct a ma_domain object with size s and init'd to d
123 inline ma_domain
124 ma_domain_ctor(size_t size, ma_cond_domain d);
125 
126 } // end of namespace errorhandler
127 } // end of namespace novadaq
128 
129 // ------------------------------------------------------------------
130 // utility functions
131 
132 novadaq::errorhandler::ma_cond_domain
133 novadaq::errorhandler::ma_cond_domain_ctor_null()
134 {
135  return ma_cond_domain_ctor(D_NIL, D_NIL);
136 }
137 
138 novadaq::errorhandler::ma_cond_domain
139 novadaq::errorhandler::ma_cond_domain_ctor_any()
140 {
141  return ma_cond_domain_ctor(D_ANY, D_ANY);
142 }
143 
144 novadaq::errorhandler::ma_cond_domain
145 novadaq::errorhandler::ma_cond_domain_ctor(int s, int t)
146 {
147  return ma_cond_domain(s, t);
148 }
149 
150 novadaq::errorhandler::ma_cond_domain
151 novadaq::errorhandler::ma_cond_domain_ctor(int i, arg_t t)
152 {
153  return (t == SOURCE) ? ma_cond_domain(i, D_ANY) : ma_cond_domain(D_ANY, i);
154 }
155 
156 novadaq::errorhandler::ma_domain
157 novadaq::errorhandler::ma_domain_ctor_null()
158 {
159  return ma_domain(1, ma_cond_domain_ctor_null());
160 }
161 
162 novadaq::errorhandler::ma_domain
163 novadaq::errorhandler::ma_domain_ctor_null(size_t size)
164 {
165  return ma_domain(size, ma_cond_domain_ctor_null());
166 }
167 
168 novadaq::errorhandler::ma_domain
169 novadaq::errorhandler::ma_domain_ctor_any(size_t size)
170 {
171  return ma_domain(size, ma_cond_domain_ctor_any());
172 }
173 
174 novadaq::errorhandler::ma_domain
175 novadaq::errorhandler::ma_domain_ctor(size_t size, ma_cond_domain d)
176 {
177  return ma_domain(size, d);
178 }
179 
180 // ------------------------------------------------------------------
181 // domain intersection
182 
183 int novadaq::errorhandler::and_op(int i, int j)
184 {
185  if (i == D_NIL || j == D_NIL) return D_NIL;
186 
187  if (i == j) return i;
188  if (i == D_ANY) return j;
189  if (j == D_ANY) return i;
190 
191  return D_NIL;
192 }
193 
194 novadaq::errorhandler::ma_cond_domain&
195 novadaq::errorhandler::domain_intersect(ma_cond_domain& d1, ma_cond_domain const& d2)
196 {
197  d1.first = and_op(d1.first, d2.first);
198  d1.second = and_op(d1.second, d2.second);
199 
200  if (domain_is_null(d1))
201  d1 = ma_cond_domain_ctor_null();
202 
203  return d1;
204 }
205 
206 novadaq::errorhandler::ma_cond_domain
207 novadaq::errorhandler::domain_intersect_copy(ma_cond_domain d1, ma_cond_domain const& d2)
208 {
209  return domain_intersect(d1, d2);
210 }
211 
212 novadaq::errorhandler::ma_cond_domain&
213 novadaq::errorhandler::domain_intersect(ma_cond_domains& ds)
214 {
215  if (ds.empty())
216  {
217  ds.push_back(ma_cond_domain_ctor_null());
218  return ds.front();
219  }
220 
221  ma_cond_domains::const_iterator it = ds.begin();
222  while (++it != ds.end() && !domain_is_null(ds.front()))
223  domain_intersect(ds.front(), *it);
224 
225  return ds.front();
226 }
227 
228 novadaq::errorhandler::ma_cond_domain
229 novadaq::errorhandler::domain_intersect_copy(ma_cond_domains d)
230 {
231  return domain_intersect(d);
232 }
233 
234 novadaq::errorhandler::ma_domain&
235 novadaq::errorhandler::domain_intersect(ma_domain& d1, ma_domain const& d2)
236 {
237  if (domain_is_null(d1) || domain_is_null(d2))
238  {
239  d1 = ma_domain_ctor_null();
240  return d1;
241  }
242 
243  if (d1.size() != d2.size())
244  throw std::runtime_error("domain size incomparable while doing domain_intersect");
245 
246  for (size_t i = 0; i < d1.size(); ++i)
247  {
248  domain_intersect(d1[i], d2[i]);
249 
250  if (domain_is_null(d1[i]))
251  {
252  d1 = ma_domain_ctor_null();
253  return d1;
254  }
255  }
256 
257  return d1;
258 }
259 
260 novadaq::errorhandler::ma_domain
261 novadaq::errorhandler::domain_intersect_copy(ma_domain d1, ma_domain const& d2)
262 {
263  return domain_intersect(d1, d2);
264 }
265 
266 novadaq::errorhandler::ma_domain&
267 novadaq::errorhandler::domain_intersect(ma_domains& ds)
268 {
269  if (ds.empty())
270  {
271  ds.push_back(ma_domain_ctor_null());
272  return ds.front();
273  }
274 
275  ma_domains::const_iterator it = ds.begin();
276  while (++it != ds.end())
277  {
278  for (size_t i = 0; i < ds.front().size(); ++i)
279  {
280  domain_intersect(ds.front()[i], (*it)[i]);
281 
282  if (domain_is_null(ds.front()[i]))
283  {
284  ds.front() = ma_domain_ctor_null();
285  goto exit;
286  }
287  }
288  }
289 
290 exit:
291 
292  return ds.front();
293 }
294 
295 novadaq::errorhandler::ma_domain
296 novadaq::errorhandler::domain_intersect_copy(ma_domains ds)
297 {
298  return domain_intersect(ds);
299 }
300 
301 // ------------------------------------------------------------------
302 // domain union
303 
304 bool novadaq::errorhandler::contains_op(int a, int b)
305 {
306  return (a == b) ? (true) : ((a == D_ANY || b == D_NIL) ? true : false);
307 }
308 
309 bool novadaq::errorhandler::domain_is_null(ma_cond_domain const& d)
310 {
311  return (d.first == D_NIL || d.second == D_NIL) ? true : false;
312 }
313 
314 bool novadaq::errorhandler::domain_is_null(ma_domain const& d)
315 {
316  if (d.empty()) return true;
317 
318  for (size_t i = 0; i < d.size(); ++i)
319  if (domain_is_null(d[i])) return true;
320 
321  return false;
322 }
323 
324 novadaq::errorhandler::domain_compare_result_t
325 novadaq::errorhandler::domain_compare(ma_cond_domain const& d1, ma_cond_domain const& d2)
326 {
327  if (d1.first == d2.first && d1.second == d2.second)
328  return EQUAL;
329 
330  bool flag1 = false;
331  bool flag2 = false;
332 
333  if (contains_op(d1.first, d2.first)) flag1 = true;
334  if (contains_op(d1.second, d2.second)) flag2 = true;
335 
336  if (flag1 != flag2)
337  return NO_COMMON;
338 
339  if (flag1)
340  return L_CONTAINS;
341  else
342  return R_CONTAINS;
343 }
344 
345 novadaq::errorhandler::ma_cond_domains&
346 novadaq::errorhandler::domain_union(ma_cond_domains& ds, ma_cond_domain const& new_d)
347 {
348  if (domain_is_null(new_d)) return ds;
349 
350  ma_cond_domains::iterator it = ds.begin();
351  while (it != ds.end())
352  {
353  domain_compare_result_t r = domain_compare(*it, new_d);
354 
355  if (r == EQUAL || r == L_CONTAINS)
356  return ds;
357 
358  if (r == R_CONTAINS)
359  {
360  ds.erase(it);
361  return domain_union(ds, new_d);
362  }
363 
364  // NO_COMMON
365  ++it;
366  }
367 
368  ds.push_back(new_d);
369  return ds;
370 }
371 
372 void novadaq::errorhandler::domain_union_construct(ma_domains& ds, ma_domain& d, std::vector<ma_cond_domains>& mid, int depth, int max)
373 {
374  ma_cond_domains::const_iterator it = mid[depth].begin();
375 
376  while (it != mid[depth].end())
377  {
378  d[depth] = *it;
379 
380  if (depth != max)
381  domain_union_construct(ds, d, mid, depth + 1, max);
382  else
383  ds.push_back(d);
384 
385  ++it;
386  }
387 }
388 
389 novadaq::errorhandler::ma_domains&
390 novadaq::errorhandler::domain_union(ma_domains& ds)
391 {
392  if (ds.empty()) return ds;
393 
394  // domain size (how many conditions in a domain)
395  size_t size = ds.front().size();
396 
397  // temp place to hold intermediate results
398  std::vector<ma_cond_domains> mid(size);
399 
400  ma_domains::const_iterator it = ds.begin();
401  while (it != ds.end())
402  {
403  for (size_t i = 0; i < size; ++i)
404  domain_union(mid[i], (*it)[i]);
405 
406  ++it;
407  }
408 
409  ma_domains result;
410  ma_domain domain(size);
411 
412  domain_union_construct(result, domain, mid, 0, size - 1);
413 
414  ds = result;
415  return ds;
416 }
417 
418 #endif