OSSIA
Open Scenario System for Interactive Application
closest_element.hpp
1 #pragma once
2 #include <ossia/detail/hash_map.hpp>
3 
4 #include <cmath>
5 
6 #include <algorithm>
7 #include <cassert>
8 #include <utility>
9 #include <vector>
10 
11 namespace ossia
12 {
13 namespace detail
14 {
15 struct lower_bound_helper
16 {
17  template <typename T, typename U>
18  auto operator()(const T& vec, const U& val) const noexcept
19  {
20  return std::lower_bound(vec.begin(), vec.end(), val);
21  }
22  template <typename T, typename U>
23  requires requires(T vec, U val) { vec.lower_bound(val); }
24  auto operator()(const T& vec, const U& val) const noexcept
25  {
26  return vec.lower_bound(val);
27  }
28 };
29 struct map_key_helper
30 {
31  template <typename T>
32  requires requires(T it) { it->first; }
33  auto operator()(const T& it) const noexcept
34  {
35  return it->first;
36  }
37 
38  template <typename T>
39  auto operator()(const T& it) const noexcept
40  {
41  return *it;
42  }
43 };
44 }
45 
46 template <typename T, typename U>
47 const auto& closest_element(const T& vec, const U& val) noexcept
48 {
49  using namespace std;
50  using namespace ossia::detail;
51  assert(!vec.empty());
52 
53  auto it = lower_bound_helper{}(vec, val);
54  if(it != vec.cend())
55  {
56  if(it != vec.cbegin())
57  {
58  auto prev = it - 1;
59  if(abs(map_key_helper{}(prev)-val) < abs(map_key_helper{}(it)-val))
60  return *prev;
61  else
62  return *it;
63  }
64  else
65  {
66  return *it;
67  }
68  }
69  else
70  {
71  return *vec.crbegin();
72  }
73 }
74 template <typename T, typename U>
75 auto closest_element_it(const T& vec, const U& val) noexcept
76 {
77  using namespace std;
78  using namespace ossia::detail;
79  if(vec.empty())
80  return vec.cend();
81 
82  auto it = lower_bound_helper{}(vec, val);
83  if(it != vec.cend())
84  {
85  if(it != vec.cbegin())
86  {
87  auto prev = it - 1;
88  if(std::abs(map_key_helper{}(prev)-val) < std::abs(map_key_helper{}(it)-val))
89  return prev;
90  else
91  return it;
92  }
93  else
94  {
95  return it;
96  }
97  }
98  else
99  {
100  return vec.end() - 1;
101  }
102 }
103 
104 template <typename T, typename U>
105 auto closest_next_element(T it, T end, const U& val) noexcept
106 {
107  using namespace std;
108  using namespace ossia::detail;
109  auto next_it = it + 1;
110  while(next_it != end)
111  {
112  if(std::abs(map_key_helper{}(it)-val) < std::abs(map_key_helper{}(next_it)-val))
113  return it;
114  it = next_it;
115  ++next_it;
116  }
117 
118  return it;
119 }
120 
121 template <typename T, typename U>
122  requires requires(T it) {
123  it->first;
124  it->second;
125  }
126 auto closest_next_element(T it, T end, const U& val) noexcept
127 {
128  using namespace std;
129  using namespace ossia::detail;
130  auto next_it = it + 1;
131  while(next_it != end)
132  {
133  // why the hell is this needed ?!
134  if(std::abs(map_key_helper{}(it)-val) < std::abs(map_key_helper{}(next_it)-val))
135  return it;
136  it = next_it;
137  ++next_it;
138  }
139 
140  return it;
141 }
142 }
Definition: transitive_closure.hpp:27
Definition: git_info.h:7