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