OpenKalman
Distance.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2018-2024 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_DISTANCE_HPP
17 #define OPENKALMAN_DISTANCE_HPP
18 
19 #include <cmath>
20 #include <type_traits>
22 #include "values/values.hpp"
23 #include "values/functions/internal/update_real_part.hpp"
24 #include "values/math/abs.hpp"
25 #include "values/functions/internal/constexpr_callable.hpp"
26 
28 {
34  struct Distance {};
35 
36 
37 } // namespace OpenKalman::coordinates
38 
39 
40 namespace OpenKalman::interface
41 {
46  template<>
47  struct coordinate_descriptor_traits<coordinates::Distance>
48  {
49  private:
50 
51  using T = coordinates::Distance;
52 
53  public:
54 
55  static constexpr bool is_specialized = true;
56 
57 
58  static constexpr auto
59  dimension(const T&) { return std::integral_constant<std::size_t, 1>{}; };
60 
61 
62  static constexpr auto
63  stat_dimension(const T&) { return std::integral_constant<std::size_t, 1>{}; };
64 
65 
66  static constexpr auto
67  is_euclidean(const T&) { return std::false_type{}; }
68 
69 
70  static constexpr std::size_t
71  hash_code(const T&)
72  {
73  constexpr auto bits = std::numeric_limits<std::size_t>::digits;
74  if constexpr (bits < 32) return 0xBD0A_uz;
75  else if constexpr (bits < 64) return 0xBD0A6689_uz;
76  else return 0xBD0A668977D34578_uz;
77  }
78 
79 
80  /*
81  * \brief Maps an element to positive coordinates in 1D Euclidean space.
82  * \param euclidean_local_index This is assumed to be 0.
83  */
84 #ifdef __cpp_concepts
85  static constexpr values::value auto
86  to_euclidean_component(const T& t, const auto& g, const values::index auto& euclidean_local_index)
87  requires requires(std::size_t i){ {g(i)} -> values::value; }
88 #else
89  template<typename Getter, typename L, std::enable_if_t<values::index<L> and
90  values::value<typename std::invoke_result<const Getter&, std::size_t>::type>, int> = 0>
91  static constexpr auto
92  to_euclidean_component(const T& t, const Getter& g, const L& euclidean_local_index)
93 #endif
94  {
95  return g(0_uz);
96  }
97 
98 
99  /*
100  * \brief Maps a coordinate in positive 1D Euclidean space to an element.
101  * \details The resulting distance should always be positive, so this function takes the absolute value.
102  * \param local_index This is assumed to be 0.
103  */
104 #ifdef __cpp_concepts
105  static constexpr values::value auto
106  from_euclidean_component(const T& t, const auto& g, const values::index auto& local_index)
107  requires requires(std::size_t i){ {g(i)} -> values::value; }
108 #else
109  template<typename Getter, typename L, std::enable_if_t<values::index<L> and
110  values::value<typename std::invoke_result<const Getter&, std::size_t>::type>, int> = 0>
111  static constexpr auto
112  from_euclidean_component(const T& t, const Getter& g, const L& local_index)
113 #endif
114  {
115  auto x = g(0_uz);
116  // The distance component may need to be wrapped to the positive half of the real axis:
117  return values::internal::update_real_part(x, values::abs(values::real(x)));
118  }
119 
120 
121  /*
122  * \details The wrapping operation is equivalent to taking the absolute value.
123  * \param local_index This is assumed to be 0.
124  */
125 #ifdef __cpp_concepts
126  static constexpr values::value auto
127  get_wrapped_component(const T& t, const auto& g, const values::index auto& local_index)
128  requires requires(std::size_t i){ {g(i)} -> values::value; }
129 #else
130  template<typename Getter, typename L, std::enable_if_t<values::index<L> and
131  values::value<typename std::invoke_result<const Getter&, std::size_t>::type>, int> = 0>
132  static constexpr auto
133  get_wrapped_component(const T& t, const Getter& g, const L& local_index)
134 #endif
135  {
136  auto x = g(0_uz);
137  return values::internal::update_real_part(x, values::abs(values::real(x)));
138  }
139 
140 
141  /*
142  * \details The operation is equivalent to setting and then changing to the absolute value.
143  * \param local_index This is assumed to be 0.
144  */
145 #ifdef __cpp_concepts
146  static constexpr void
147  set_wrapped_component(const T& t, const auto& s, const auto& g, const values::value auto& x, const values::index auto& local_index)
148  requires requires(std::size_t i){ s(x, i); s(g(i), i); }
149 #else
150  template<typename Setter, typename Getter, typename X, typename L, std::enable_if_t<values::value<X> and values::index<L> and
151  std::is_invocable<const Setter&, const X&, std::size_t>::value and
152  std::is_invocable<const Setter&, typename std::invoke_result<const Getter&, std::size_t>::type, std::size_t>::value, int> = 0>
153  static constexpr void
154  set_wrapped_component(const T& t, const Setter& s, const Getter& g, const X& x, const L& local_index)
155 #endif
156  {
157  s(values::internal::update_real_part(x, values::abs(values::real(x))), 0_uz);
158  }
159 
160  };
161 
162 
163 } // namespace OpenKalman::interface
164 
165 
166 #endif //OPENKALMAN_DISTANCE_HPP
Definition: basics.hpp:41
Header file for code relating to values (e.g., scalars and indices)
A non-negative real or integral number, [0,∞], representing a distance.
Definition: Distance.hpp:34
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: compares_with.hpp:28
constexpr auto real(Arg arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
Traits for coordinates::pattern objects.
Definition: coordinate_descriptor_traits.hpp:41
constexpr auto abs(const Arg &arg)
A constexpr alternative to std::abs.
Definition: abs.hpp:38
constexpr bool index
T is an index value.
Definition: index.hpp:56
Definition for ::value.