OSSIA
Open Scenario System for Interactive Application
min_max.hpp
1 #pragma once
2 #include <ossia/detail/flat_set.hpp>
3 #include <ossia/detail/small_vector.hpp>
5 
6 namespace ossia
7 {
8 namespace detail
9 {
11 
12 template <typename T>
14 {
15  OSSIA_INLINE ossia::value operator()(const T& value) const
16  {
17  if(value.min)
18  return value::make<typename T::value_type>(*value.min);
19  else
20  return ossia::value{};
21  }
22 };
23 
24 template <>
25 struct domain_min_visitor_helper<domain_base<bool>>
26 {
27  OSSIA_INLINE ossia::value operator()(const domain_base<bool>& value) const
28  {
29  return value.min;
30  }
31 };
32 
33 template <>
34 struct domain_min_visitor_helper<domain_base<impulse>>
35 {
36  OSSIA_INLINE ossia::value operator()(const domain_base<impulse>& value) const
37  {
38  return impulse{};
39  }
40 };
41 
42 template <>
43 struct domain_min_visitor_helper<domain_base<std::string>>
44 {
45  OSSIA_INLINE ossia::value operator()(const domain_base<std::string>& value) const
46  {
47  return {};
48  }
49 };
50 
51 template <>
52 struct domain_min_visitor_helper<domain_base<ossia::value>>
53 {
54  OSSIA_INLINE ossia::value operator()(const domain_base<ossia::value>& value) const
55  {
56  // TODO for this case, it would maybe be better to
57  // use the empty state of value instead of a boost::optional ?
58  if(value.min)
59  return *value.min;
60  else
61  return ossia::value{};
62  }
63 };
64 
65 template <>
66 struct domain_min_visitor_helper<vector_domain>
67 {
68  OSSIA_INLINE ossia::value operator()(const vector_domain& value) const
69  {
70  return value.min;
71  }
72 };
73 
74 template <std::size_t N>
75 struct domain_min_visitor_helper<vecf_domain<N>>
76 {
77  OSSIA_INLINE ossia::value operator()(const vecf_domain<N>& value) const
78  {
79  // TODO for this case, it would maybe be better to
80  // use the empty state of value instead of a boost::optional ?
81  std::array<float, N> arr;
82  for(auto& val : value.min)
83  if(!val)
84  return ossia::value{};
85 
86  for(std::size_t i = 0; i < N; i++)
87  {
88  arr[i] = *value.min[i];
89  }
90 
91  return arr;
92  }
93 };
94 
96 template <typename T>
98 {
99  OSSIA_INLINE ossia::value operator()(const T& value) const
100  {
101  if(value.max)
102  return value::make<typename T::value_type>(*value.max);
103  else
104  return ossia::value{};
105  }
106 };
107 
108 template <>
109 struct domain_max_visitor_helper<domain_base<bool>>
110 {
111  OSSIA_INLINE ossia::value operator()(const domain_base<bool>& value) const
112  {
113  return value.max;
114  }
115 };
116 
117 template <>
118 struct domain_max_visitor_helper<domain_base<impulse>>
119 {
120  OSSIA_INLINE ossia::value operator()(const domain_base<impulse>& value) const
121  {
122  return impulse{};
123  }
124 };
125 
126 template <>
127 struct domain_max_visitor_helper<domain_base<std::string>>
128 {
129  OSSIA_INLINE ossia::value operator()(const domain_base<std::string>& value) const
130  {
131  return {};
132  }
133 };
134 
135 template <>
136 struct domain_max_visitor_helper<domain_base<ossia::value>>
137 {
138  OSSIA_INLINE ossia::value operator()(const domain_base<ossia::value>& value) const
139  {
140  // TODO for this case, it would maybe be better to
141  // use the empty state of value instead of a boost::optional ?
142  if(value.max)
143  return *value.max;
144  else
145  return ossia::value{};
146  }
147 };
148 
149 template <>
150 struct domain_max_visitor_helper<vector_domain>
151 {
152  OSSIA_INLINE ossia::value operator()(const vector_domain& value) const
153  {
154  return value.max;
155  }
156 };
157 
158 template <std::size_t N>
159 struct domain_max_visitor_helper<vecf_domain<N>>
160 {
161  OSSIA_INLINE ossia::value operator()(const vecf_domain<N>& value) const
162  {
163  std::array<float, N> arr;
164  for(auto& val : value.max)
165  if(!val)
166  return ossia::value{};
167 
168  for(std::size_t i = 0; i < N; i++)
169  {
170  arr[i] = *value.max[i];
171  }
172 
173  return arr;
174  }
175 };
176 
178 using float_minmax = std::pair<std::optional<float>, std::optional<float>>;
179 template <typename T>
180 struct domain_float_minmax_visitor_helper
181 {
182  OSSIA_INLINE float_minmax operator()(const T& value) const
183  {
184  float_minmax ret;
185  if(value.min)
186  ret.first = *value.min;
187  if(value.max)
188  ret.second = *value.max;
189  return ret;
190  }
191 };
192 
193 template <>
194 struct domain_float_minmax_visitor_helper<domain_base<bool>>
195 {
196  OSSIA_INLINE float_minmax operator()(const domain_base<bool>& value) const
197  {
198  return std::make_pair(0.f, 1.f);
199  }
200 };
201 
202 template <>
203 struct domain_float_minmax_visitor_helper<domain_base<impulse>>
204 {
205  OSSIA_INLINE float_minmax operator()(const domain_base<impulse>& value) const
206  {
207  return {};
208  }
209 };
210 
211 template <>
212 struct domain_float_minmax_visitor_helper<domain_base<std::string>>
213 {
214  OSSIA_INLINE float_minmax operator()(const domain_base<std::string>& value) const
215  {
216  return {};
217  }
218 };
219 
220 template <>
221 struct domain_float_minmax_visitor_helper<domain_base<ossia::value>>
222 {
223  OSSIA_INLINE float_minmax operator()(const domain_base<ossia::value>& value) const
224  {
225  // TODO for this case, it would maybe be better to
226  // use the empty state of value instead of a boost::optional ?
227 
228  float_minmax ret;
229  if(value.min)
230  ret.first = ossia::convert<float>(*value.min);
231  if(value.max)
232  ret.second = ossia::convert<float>(*value.max);
233  return ret;
234  }
235 };
236 
237 template <>
238 struct domain_float_minmax_visitor_helper<vector_domain>
239 {
240  OSSIA_INLINE float_minmax operator()(const vector_domain& value) const { return {}; }
241 };
242 
243 template <std::size_t N>
244 struct domain_float_minmax_visitor_helper<vecf_domain<N>>
245 {
246  OSSIA_INLINE float_minmax operator()(const vecf_domain<N>& value) const { return {}; }
247 };
248 
249 }
250 
251 struct domain_min_visitor
252 {
253  template <typename T>
254  OSSIA_INLINE ossia::value operator()(const domain_base<T>& value) const
255  {
256  return detail::domain_min_visitor_helper<domain_base<T>>{}(value);
257  }
258 
259  OSSIA_INLINE ossia::value operator()(const vector_domain& value) const
260  {
261  return detail::domain_min_visitor_helper<vector_domain>{}(value);
262  }
263 
264  template <std::size_t N>
265  OSSIA_INLINE ossia::value operator()(const vecf_domain<N>& value) const
266  {
267  return detail::domain_min_visitor_helper<vecf_domain<N>>{}(value);
268  }
269 
270  template <typename... T>
271  OSSIA_INLINE ossia::value operator()(const T&...) const
272  {
273  return ossia::value{};
274  }
275 };
276 
277 struct domain_max_visitor
278 {
279  template <typename T>
280  OSSIA_INLINE ossia::value operator()(const domain_base<T>& value) const
281  {
282  return detail::domain_max_visitor_helper<domain_base<T>>{}(value);
283  }
284 
285  OSSIA_INLINE ossia::value operator()(const vector_domain& value) const
286  {
287  return detail::domain_max_visitor_helper<vector_domain>{}(value);
288  }
289 
290  template <std::size_t N>
291  OSSIA_INLINE ossia::value operator()(const vecf_domain<N>& value) const
292  {
293  return detail::domain_max_visitor_helper<vecf_domain<N>>{}(value);
294  }
295 
296  template <typename... T>
297  OSSIA_INLINE ossia::value operator()(const T&...) const
298  {
299  return ossia::value{};
300  }
301 };
302 
303 struct domain_float_minmax_visitor
304 {
305  using return_type = detail::float_minmax;
306  template <typename T>
307  OSSIA_INLINE return_type operator()(const domain_base<T>& value) const
308  {
309  return detail::domain_float_minmax_visitor_helper<domain_base<T>>{}(value);
310  }
311 
312  OSSIA_INLINE return_type operator()(const vector_domain& value) const
313  {
314  return detail::domain_float_minmax_visitor_helper<vector_domain>{}(value);
315  }
316 
317  template <std::size_t N>
318  OSSIA_INLINE return_type operator()(const vecf_domain<N>& value) const
319  {
320  return detail::domain_float_minmax_visitor_helper<vecf_domain<N>>{}(value);
321  }
322 
323  template <typename... T>
324  OSSIA_INLINE return_type operator()(const T&...) const
325  {
326  return {};
327  }
328 };
329 struct domain_set_min_visitor
330 {
331  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, int32_t incoming)
332  {
333  domain.min = incoming;
334  }
335  OSSIA_INLINE void operator()(domain_base<float>& domain, float incoming)
336  {
337  domain.min = incoming;
338  }
339  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, float incoming)
340  {
341  domain.min = incoming;
342  }
343  OSSIA_INLINE void operator()(domain_base<float>& domain, int32_t incoming)
344  {
345  domain.min = incoming;
346  }
347  OSSIA_INLINE void operator()(domain_base<bool>& domain, bool incoming) { }
348  OSSIA_INLINE void
349  operator()(vector_domain& domain, const std::vector<ossia::value>& incoming)
350  {
351  domain.min = incoming;
352  }
353 
354  template <std::size_t N>
355  OSSIA_INLINE void operator()(vecf_domain<N>& domain, float incoming)
356  {
357  for(std::size_t i = 0; i < N; i++)
358  domain.min[i] = incoming;
359  }
360 
361  template <std::size_t N>
362  OSSIA_INLINE void operator()(vecf_domain<N>& domain, int incoming)
363  {
364  for(std::size_t i = 0; i < N; i++)
365  domain.min[i] = incoming;
366  }
367 
368  template <std::size_t N>
369  OSSIA_INLINE void
370  operator()(vecf_domain<N>& domain, const std::array<float, N>& incoming)
371  {
372  for(std::size_t i = 0; i < N; i++)
373  domain.min[i] = incoming[i];
374  }
375 
376  template <std::size_t N>
377  OSSIA_INLINE void
378  operator()(vecf_domain<N>& domain, const std::vector<ossia::value>& incoming)
379  {
380  if(incoming.size() == N)
381  {
382  auto conv = ossia::convert<std::array<float, N>>(incoming);
383  for(std::size_t i = 0; i < N; i++)
384  domain.min[i] = conv[i];
385  }
386  else
387  {
388  for(std::size_t i = 0; i < N; i++)
389  domain.min[i] = std::nullopt;
390  }
391  }
392 
393  template <typename T>
394  OSSIA_INLINE void operator()(domain_base<ossia::value>& domain, const T& incoming)
395  {
396  domain.min = ossia::value{incoming};
397  }
398 
399  // Removal cases
400  // Here we could maybe allow a cast or something like this...
401  // for e.g. int -> float
402  template <typename... U>
403  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, U&&...)
404  {
405  domain.min = std::nullopt;
406  }
407  template <typename... U>
408  OSSIA_INLINE void operator()(domain_base<float>& domain, U&&...)
409  {
410  domain.min = std::nullopt;
411  }
412  template <typename... U>
413  OSSIA_INLINE void operator()(domain_base<bool>& domain, U&&...)
414  {
415  }
416  template <typename... U>
417  OSSIA_INLINE void operator()(vector_domain& domain, U&&...)
418  {
419  domain.min.clear();
420  }
421  template <std::size_t N, typename... U>
422  OSSIA_INLINE void operator()(vecf_domain<N>& domain, U&&...)
423  {
424  for(std::size_t i = 0; i < N; i++)
425  domain.min[i] = std::nullopt;
426  }
427  template <typename... U>
428  OSSIA_INLINE void operator()(domain_base<ossia::value>& domain, U&&...)
429  {
430  domain.min = std::nullopt;
431  }
432 
433  template <typename T, typename... U>
434  OSSIA_INLINE void operator()(const domain_base<T>& domain, U&&...)
435  {
436  }
437 };
438 
439 struct domain_set_max_visitor
440 {
441  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, int32_t incoming)
442  {
443  domain.max = incoming;
444  }
445  OSSIA_INLINE void operator()(domain_base<float>& domain, float incoming)
446  {
447  domain.max = incoming;
448  }
449  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, float incoming)
450  {
451  domain.max = incoming;
452  }
453  OSSIA_INLINE void operator()(domain_base<float>& domain, int32_t incoming)
454  {
455  domain.max = incoming;
456  }
457  OSSIA_INLINE void operator()(domain_base<bool>& domain, bool incoming) { }
458  OSSIA_INLINE void
459  operator()(vector_domain& domain, const std::vector<ossia::value>& incoming)
460  {
461  domain.max = incoming;
462  }
463 
464  template <std::size_t N>
465  OSSIA_INLINE void operator()(vecf_domain<N>& domain, float incoming)
466  {
467  for(std::size_t i = 0; i < N; i++)
468  domain.max[i] = incoming;
469  }
470 
471  template <std::size_t N>
472  OSSIA_INLINE void operator()(vecf_domain<N>& domain, int incoming)
473  {
474  for(std::size_t i = 0; i < N; i++)
475  domain.max[i] = incoming;
476  }
477 
478  template <std::size_t N>
479  OSSIA_INLINE void
480  operator()(vecf_domain<N>& domain, const std::array<float, N>& incoming)
481  {
482  for(std::size_t i = 0; i < N; i++)
483  domain.max[i] = incoming[i];
484  }
485 
486  template <std::size_t N>
487  OSSIA_INLINE void
488  operator()(vecf_domain<N>& domain, const std::vector<ossia::value>& incoming)
489  {
490  if(incoming.size() == N)
491  {
492  auto conv = ossia::convert<std::array<float, N>>(incoming);
493  for(std::size_t i = 0; i < N; i++)
494  domain.max[i] = conv[i];
495  }
496  else
497  {
498  for(std::size_t i = 0; i < N; i++)
499  domain.max[i] = std::nullopt;
500  }
501  }
502 
503  template <typename T>
504  OSSIA_INLINE void operator()(domain_base<ossia::value>& domain, const T& incoming)
505  {
506  domain.max = ossia::value{incoming};
507  }
508 
509  // Removal cases
510  template <typename... U>
511  OSSIA_INLINE void operator()(domain_base<int32_t>& domain, U&&...)
512  {
513  domain.max = std::nullopt;
514  }
515  template <typename... U>
516  OSSIA_INLINE void operator()(domain_base<float>& domain, U&&...)
517  {
518  domain.max = std::nullopt;
519  }
520  template <typename... U>
521  OSSIA_INLINE void operator()(domain_base<bool>& domain, U&&...)
522  {
523  }
524  template <typename... U>
525  OSSIA_INLINE void operator()(vector_domain& domain, U&&...)
526  {
527  domain.max.clear();
528  }
529  template <std::size_t N, typename... U>
530  OSSIA_INLINE void operator()(vecf_domain<N>& domain, U&&...)
531  {
532  for(std::size_t i = 0; i < N; i++)
533  domain.max[i] = std::nullopt;
534  }
535  template <typename... U>
536  OSSIA_INLINE void operator()(domain_base<ossia::value>& domain, U&&...)
537  {
538  domain.max = std::nullopt;
539  }
540 
541  template <typename T, typename... U>
542  OSSIA_INLINE void operator()(const domain_base<T>& domain, U&&...)
543  {
544  }
545 };
546 
547 struct domain_minmax_creation_visitor
548 {
549  template <typename T>
550  OSSIA_INLINE domain operator()(T min, T max)
551  {
552  return domain_base<T>(min, max);
553  }
554 
555  OSSIA_INLINE domain operator()(bool min, bool max) { return domain_base<bool>{}; }
556 
557  template <std::size_t N>
558  OSSIA_INLINE domain
559  operator()(const std::array<float, N>& lhs, const std::array<float, N>& rhs)
560  {
561  return vecf_domain<N>(lhs, rhs);
562  }
563 
564  OSSIA_INLINE domain
565  operator()(const std::vector<ossia::value>& min, const std::vector<ossia::value>& max)
566  {
567  return vector_domain(min, max);
568  }
569  OSSIA_INLINE domain
570  operator()(std::vector<ossia::value>&& min, std::vector<ossia::value>&& max)
571  {
572  return vector_domain(std::move(min), std::move(max));
573  }
574 
575  OSSIA_INLINE domain operator()(impulse, impulse) { return domain_base<impulse>{}; }
576 
577  OSSIA_INLINE domain operator()(const std::string&, const std::string&)
578  {
579  return domain_base<std::string>();
580  }
581  OSSIA_INLINE domain operator()(const value_map_type&, const value_map_type&)
582  {
583  return domain{};
584  }
585 
586  // Cases where there is no possible domain
587  template <typename T, typename U>
588  OSSIA_INLINE domain operator()(const T&, const U&)
589  {
590  return domain{};
591  }
592 };
593 
594 struct domain_min_creation_visitor
595 {
596  template <typename T>
597  OSSIA_INLINE domain operator()(T min)
598  {
599  domain_base<T> dom;
600  dom.min = std::move(min);
601  return dom;
602  }
603 
604  OSSIA_INLINE domain operator()(bool min) { return domain_base<bool>{}; }
605 
606  template <std::size_t N>
607  OSSIA_INLINE domain operator()(const std::array<float, N>& min)
608  {
609  vecf_domain<N> dom;
610  for(std::size_t i = 0; i < N; i++)
611  {
612  dom.min[i] = min[i];
613  }
614  return dom;
615  }
616 
617  OSSIA_INLINE domain operator()(const std::vector<ossia::value>& min)
618  {
619  vector_domain dom;
620  dom.min = min;
621  return dom;
622  }
623  OSSIA_INLINE domain operator()(const value_map_type& min) { return {}; }
624  OSSIA_INLINE domain operator()(std::vector<ossia::value>&& min)
625  {
626  return vector_domain(std::move(min), std::vector<ossia::value>(min.size()));
627  }
628 
629  OSSIA_INLINE domain operator()(impulse) { return domain_base<impulse>{}; }
630 
631  OSSIA_INLINE domain operator()(const std::string&)
632  {
633  return domain_base<std::string>();
634  }
635 };
636 
637 struct domain_max_creation_visitor
638 {
639  template <typename T>
640  OSSIA_INLINE domain operator()(T max)
641  {
642  domain_base<T> dom;
643  dom.max = std::move(max);
644  return dom;
645  }
646 
647  OSSIA_INLINE domain operator()(bool max) { return domain_base<bool>{}; }
648 
649  template <std::size_t N>
650  OSSIA_INLINE domain operator()(const std::array<float, N>& max)
651  {
652  vecf_domain<N> dom;
653  for(std::size_t i = 0; i < N; i++)
654  {
655  dom.max[i] = max[i];
656  }
657  return dom;
658  }
659 
660  OSSIA_INLINE domain operator()(const std::vector<ossia::value>& max)
661  {
662  vector_domain dom;
663  dom.max = max;
664  return dom;
665  }
666  OSSIA_INLINE domain operator()(std::vector<ossia::value>&& max)
667  {
668  return vector_domain(std::move(max), std::vector<ossia::value>(max.size()));
669  }
670 
671  OSSIA_INLINE domain operator()(const value_map_type& min) { return {}; }
672  OSSIA_INLINE domain operator()(impulse) { return domain_base<impulse>{}; }
673 
674  OSSIA_INLINE domain operator()(const std::string&)
675  {
676  return domain_base<std::string>();
677  }
678 };
679 
687 {
688  const ossia::small_vector<ossia::value, 2>& values;
689  template <typename T>
690  domain operator()(const T&)
691  {
692  // Cases where there is no possible domain
693  domain_base<T> dom;
694  for(auto& value : values)
695  {
696  if(auto r = value.target<T>())
697  dom.values.push_back(*r);
698  }
699  return dom;
700  }
701 
702  domain operator()(bool) { return domain_base<bool>{}; }
703 
704  domain operator()(const std::vector<ossia::value>& orig)
705  {
706  vector_domain res;
707  ossia::flat_set<ossia::value> vals;
708 
709  for(const auto& value : values)
710  vals.insert(value);
711 
712  res.values
713  = std::vector<ossia::flat_set<ossia::value>>(orig.size(), std::move(vals));
714 
715  return res;
716  }
717 
718  OSSIA_INLINE domain operator()(const value_map_type& min) { return {}; }
719 
720  template <std::size_t N>
721  domain operator()(const std::array<float, N>&)
722  {
723  vecf_domain<N> res;
724  ossia::flat_set<float> vals;
725 
726  for(const auto& value : values)
727  if(auto r = value.target<float>())
728  vals.insert(*r);
729 
730  for(std::size_t i = 0; i < N - 1; i++)
731  res.values[i] = vals;
732  res.values[N - 1] = std::move(vals);
733  return res;
734  }
735 
736  domain operator()()
737  {
738  // TODO
739  return {};
740  }
741 
742  domain operator()(const impulse&) { return domain{}; }
743 };
744 }
The value class.
Definition: value.hpp:173
Definition: git_info.h:7
constexpr OSSIA_INLINE auto min(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
min function tailored for values
Definition: math.hpp:125
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96
Max ///.
Definition: min_max.hpp:98
Min ///.
Definition: min_max.hpp:14
The domain_value_set_creation_visitor struct.
Definition: min_max.hpp:687
domain A domain of values
Definition: domain_base.hpp:23