OpenKalman
Inclination.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-2021 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_INCLINATION_HPP
17 #define OPENKALMAN_INCLINATION_HPP
18 
19 #include "values/functions/internal/update_real_part.hpp"
21 #include "coordinates/interfaces/coordinate_descriptor_traits.hpp"
22 #include "coordinates/descriptors/Any.hpp"
23 
25 {
33 #ifdef __cpp_concepts
34  template<values::fixed Down = values::fixed_pi<long double>> requires
35  (values::fixed_value_of_v<Down> > 0) and (not values::complex<Down>) and
36  std::convertible_to<values::value_type_of_t<Down>, float>
37 #else
38  template<typename Down = values::fixed_pi<long double>>
39 #endif
40  struct Inclination
41  {
42 #ifndef __cpp_concepts
43  static_assert(values::fixed<Down>);
44  static_assert(not values::complex<Down>);
45  static_assert(values::fixed_value_of_v<Down> > 0);
46  static_assert(stdex::convertible_to<values::value_type_of_t<Down>, float>);
47 #endif
48  };
49 
50 
52  namespace inclination
53  {
56 
57 
60 
61 
62  namespace detail
63  {
64  template<typename T>
65  struct is_inclination : std::false_type {};
66 
67  template<typename Down>
68  struct is_inclination<Inclination<Down>> : std::true_type {};
69  }
70 
71 
75  template<typename T>
76 #ifdef __cpp_concepts
77  concept inclination =
78 #else
79  static constexpr bool inclination =
80 #endif
82 
83  }
84 
85 }
86 
87 
88 namespace OpenKalman::interface
89 {
94  template<typename Down>
95  struct coordinate_descriptor_traits<coordinates::Inclination<Down>>
96  {
97  private:
98 
100  static constexpr auto down = values::fixed_value_of_v<Down>;
101 
102 
103  template<typename...Args>
104  static constexpr auto make_range(Args&&...args)
105  {
106  if constexpr ((... or values::fixed<Args>))
107  return std::tuple {std::forward<Args>(args)...};
108  else
109  return std::array<std::common_type_t<Args...>, sizeof...(Args)> {std::forward<Args>(args)...};
110  }
111 
112  public:
113 
114  static constexpr bool is_specialized = true;
115 
116 
117  static constexpr auto dimension = [](const T&) { return std::integral_constant<std::size_t, 1>{}; };
118 
119 
120  static constexpr auto stat_dimension = [](const T&) { return std::integral_constant<std::size_t, 2>{}; };
121 
122 
123  static constexpr auto is_euclidean = [](const T&) { return std::false_type{}; };
124 
125 
126  static constexpr auto hash_code = [](const T&)
127  {
128  constexpr auto a = static_cast<float>(down);
129  constexpr auto bits = std::numeric_limits<std::size_t>::digits;
130  if constexpr (bits < 32)
131  return std::integral_constant<std::size_t, 0x8CE6_uz + static_cast<std::size_t>(a * a * 0x1.p2f)>{};
132  else if constexpr (bits < 64)
133  return std::integral_constant<std::size_t, 0x8CE6267E_uz + static_cast<std::size_t>(a * a * 0x1.p4f)>{};
134  else
135  return std::integral_constant<std::size_t, 0x8CE6267E341642F7_uz + static_cast<std::size_t>(a * a * 0x1.p8f)>{};
136  };
137 
138 
144  static constexpr auto
145  to_stat_space = [](const T&, auto&& data_view)
146  {
147  decltype(auto) i = collections::get<0>(std::forward<decltype(data_view)>(data_view));
149  auto theta = [](auto&& i)
150  {
151  if constexpr (down == stdex::numbers::pi_v<R>) //< Avoid scaling, if possible.
152  {
153  return std::forward<decltype(i)>(i);
154  }
155  else
156  {
157  constexpr auto scale = values::operation(std::divides{}, values::fixed_pi<R>{}, values::cast_to<R>(Down{}));
158  return values::operation(std::multiplies{}, std::forward<decltype(i)>(i), scale);
159  }
160  }(std::forward<decltype(i)>(i));
161  auto w = values::sin(theta);
162  auto pos_w = values::internal::update_real_part(std::move(w), values::abs(values::real(w)));
163  return make_range(values::cos(std::move(theta)), std::move(pos_w));
164  };
165 
166 
172  static constexpr auto
173  from_stat_space = [](const T&, auto&& data_view)
174  {
175  decltype(auto) z = collections::get<0>(std::forward<decltype(data_view)>(data_view));
176  decltype(auto) w = collections::get<1>(std::forward<decltype(data_view)>(data_view));
178  auto pos_w = values::internal::update_real_part(std::forward<decltype(w)>(w), values::abs(values::real(w)));
179  if constexpr (down == stdex::numbers::pi_v<R>) //< avoid scaling, if possible
180  {
181  return std::array {values::atan2(std::move(pos_w), std::forward<decltype(z)>(z))};
182  }
183  else
184  {
185  constexpr auto scale = values::operation(std::divides{}, values::cast_to<R>(Down{}), values::fixed_pi<R>{});
186  return std::array {values::operation(std::multiplies{}, values::atan2(std::move(pos_w), std::forward<decltype(z)>(z)), scale)};
187  }
188  };
189 
190  private:
191 
192  struct wrap_theta
193  {
194  template<typename R>
195  constexpr R operator()(const R& theta_real) const
196  {
197  if (theta_real >= R{0} and theta_real <= R{down}) return theta_real;
198  constexpr R down2 = R{down * 2};
199  auto am = values::fmod(values::abs(theta_real), down2);
200  if (am > R{down}) return down2 - am;
201  else return am;
202  }
203  };
204 
205  public:
206 
210  static constexpr auto
211  wrap = [](const T&, auto&& data_view)
212  {
213  decltype(auto) i = collections::get<0>(std::forward<decltype(data_view)>(data_view));
214  return std::array {values::internal::update_real_part(std::forward<decltype(i)>(i),
215  values::operation(wrap_theta{}, values::real(values::real(i))))};
216  };
217 
218  };
219 
220 
221 }
222 
223 
224 namespace std
225 {
226  template<typename Down1, typename Down2>
227  struct common_type<OpenKalman::coordinates::Inclination<Down1>, OpenKalman::coordinates::Inclination<Down2>>
228  : std::conditional<
229  OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
230  OpenKalman::coordinates::Inclination<Down1>,
231  OpenKalman::coordinates::Any<>> {};
232 
233 
234  template<typename Down, typename Scalar>
235  struct common_type<OpenKalman::coordinates::Inclination<Down>, OpenKalman::coordinates::Any<Scalar>>
236  : common_type<OpenKalman::coordinates::Any<Scalar>, OpenKalman::coordinates::Inclination<Down>> {};
237 
238 
239  template<typename Down, typename T>
240  struct common_type<OpenKalman::coordinates::Inclination<Down>, T>
241  : std::conditional_t<
242  OpenKalman::coordinates::descriptor<T>,
243  OpenKalman::stdex::type_identity<OpenKalman::coordinates::Any<>>,
244  std::monostate> {};
245 }
246 
247 #endif
A fixed version of pi.
Definition: fixed-constants.hpp:33
constexpr auto fmod(const X &x, const Y &y)
A constexpr function for fmod.
Definition: fmod.hpp:44
Definition: basics.hpp:41
decltype(auto) constexpr to_stat_space(const T &t, R &&data_view)
Maps a range reflecting vector-space data to a corresponding range in a vector space for directional ...
Definition: to_stat_space.hpp:44
A non-negative real number φ representing an inclination (angle from the positive z axis)...
Definition: Inclination.hpp:40
typename real_type_of< T >::type real_type_of_t
Helper template for real_type_of.
Definition: real_type_of.hpp:55
typename value_type_of< T >::type value_type_of_t
Helper template for value_type_of.
Definition: value_type_of.hpp:52
constexpr bool complex
T is a value that reduces to std::complex or a custom complex type.
Definition: complex.hpp:47
decltype(auto) constexpr wrap(const T &t, R &&data_view)
wraps a range reflecting vector-space data to its primary range.
Definition: wrap.hpp:59
constexpr auto cos(const Arg &arg)
Constexpr alternative to the std::cos function.
Definition: cos.hpp:42
constexpr auto sin(const Arg &arg)
Constexpr alternative to the std::sin function.
Definition: sin.hpp:43
The root namespace for OpenKalman.
Definition: basics.hpp:34
The namespace for features relating to coordinates::pattern object.
Definition: compares_with.hpp:25
Inclusion file for collections.
constexpr auto atan2(const Y &y_arg, const X &x_arg)
Constexpr alternative to the std::atan2 function.
Definition: atan2.hpp:46
constexpr auto real(const 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:36
constexpr auto abs(const Arg &arg)
A constexpr alternative to std::abs.
Definition: abs.hpp:38
decltype(auto) constexpr from_stat_space(const T &t, R &&stat_data_view)
Maps a range in a vector space for directional-statistics back to a range reflecting vector-space dat...
Definition: from_stat_space.hpp:44
auto scale(M &&m, const S s)
Scale a covariance by a factor.
Definition: covariance-arithmetic.hpp:518
Definition: Any.hpp:42
constexpr auto operation(Operation &&op, Args &&...args)
A potentially constant-evaluated operation involving some number of values.
Definition: operation.hpp:98