OpenKalman
make_complex_number.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) 2022-2025 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 
17 #ifndef OPENKALMAN_MAKE_COMPLEX_NUMBER_HPP
18 #define OPENKALMAN_MAKE_COMPLEX_NUMBER_HPP
19 
24 #include "values/math/real.hpp"
25 #include "values/math/imag.hpp"
30 
32 {
33  namespace detail
34  {
40 #ifdef __cpp_concepts
41  template<typename T = void> requires number<T> or std::same_as<T, void>
42 #else
43  template<typename T = void, typename = void>
44 #endif
46 
47 
53 #ifdef __cpp_concepts
54  template<number T>
55  struct make_complex_number<T>
56 #else
57  template<typename T>
58  struct make_complex_number<T, std::enable_if_t<number<T>>>
59 #endif
60  {
61 #if __cpp_nontype_template_args < 201911L
62  private:
63 
64  template<typename C, typename Re, typename Im>
65  struct FixedComplex
66  {
67  using value_type = C;
68  static constexpr value_type value {interface::number_traits<C>::make_complex(fixed_value_of_v<Re>, fixed_value_of_v<Im>)};
69  using type = FixedComplex;
70  constexpr operator value_type() const { return value; }
71  constexpr value_type operator()() const { return value; }
72  };
73 
74  public:
75 #endif
76 
85 #ifdef __cpp_concepts
86  template<value Re, value Im = fixed_value<real_type_of_t<T>, 0>> requires (not values::complex<Re>) and (not values::complex<Im>) and
87  std::convertible_to<Re, real_type_of_t<T>> and std::convertible_to<Im, real_type_of_t<T>> and
88  requires { interface::number_traits<std::decay_t<T>>::make_complex(to_value_type(std::declval<Re>()), to_value_type(std::declval<Im>())); }
89  constexpr complex decltype(auto)
90 #else
91  template<typename Re, typename Im = fixed_value<real_type_of_t<T>, 0>, std::enable_if_t<value<Re> and value<Im> and
92  (not values::complex<Re>) and (not values::complex<Im>) and
93  stdex::convertible_to<Re, real_type_of_t<T>> and stdex::convertible_to<Im, real_type_of_t<T>>, int> = 0>
94  constexpr decltype(auto)
95 #endif
96  operator()(Re&& re, Im&& im = {}) const
97  {
98  if constexpr (fixed<Re> and fixed<Im>)
99  {
100  constexpr auto r = fixed_value_of_v<Re>;
101  constexpr auto i = fixed_value_of_v<Im>;
102  using C = std::decay_t<decltype(interface::number_traits<std::decay_t<T>>::make_complex(r, i))>;
103 #if __cpp_nontype_template_args >= 201911L
104  return fixed_value<C, r, i>{};
105 #else
106  if constexpr (r == static_cast<std::intmax_t>(r) and i == static_cast<std::intmax_t>(i))
107  return fixed_value<C, static_cast<std::intmax_t>(r), static_cast<std::intmax_t>(i)>{};
108  else
109  return FixedComplex<C, std::decay_t<Re>, std::decay_t<Im>>{};
110 #endif
111  }
112  else
113  {
114  return interface::number_traits<std::decay_t<T>>::make_complex(to_value_type(std::forward<Re>(re)), to_value_type(std::forward<Im>(im)));
115  }
116  }
117 
118 
124 #ifdef __cpp_concepts
125  template<complex Arg> requires std::convertible_to<real_type_of_t<Arg>, real_type_of_t<T>>
126  constexpr complex decltype(auto)
127 #else
128  template<typename Arg, std::enable_if_t<number<T> and complex<Arg> and
129  stdex::convertible_to<real_type_of_t<Arg>, real_type_of_t<T>>, int> = 0>
130  constexpr decltype(auto)
131 #endif
132  operator()(Arg&& arg) const
133  {
134  if constexpr (std::is_same_v<real_type_of_t<T>, real_type_of_t<Arg>>)
135  {
136  return std::forward<Arg>(arg);
137  }
138  else
139  {
140  return operator()(values::real(std::forward<Arg>(arg)), values::imag(std::forward<Arg>(arg)));
141  }
142  }
143  };
144 
145 
151  template<>
152  struct make_complex_number<void>
153  {
159 #ifdef __cpp_concepts
160  template<number Re, number Im = fixed_value<real_type_of_t<Re>, 0>> requires
161  (not complex<Re>) and (not complex<Im>) and std::common_with<value_type_of_t<Re>, value_type_of_t<Im>>
162  constexpr complex decltype(auto)
163 #else
164  template<typename Re, typename Im = fixed_value<real_type_of_t<Re>, 0>, std::enable_if_t<
165  number<Re> and number<Im> and (not complex<Re>) and (not complex<Im>), int> = 0>
166  constexpr decltype(auto)
167 #endif
168  operator()(Re&& re, Im&& im) const
169  {
170  using T = std::decay_t<std::common_type_t<value_type_of_t<Re>, value_type_of_t<Im>>>;
171  return make_complex_number<T>{}(std::forward<Re>(re), std::forward<Im>(im));
172  }
173  };
174  }
175 
176 
177 #ifdef __cpp_concepts
178  template<typename T = void> requires number<T> or std::same_as<T, void>
179 #else
180  template<typename T = void, typename = void>
181 #endif
182  inline constexpr auto make_complex_number = detail::make_complex_number<T>{};
183 
184 
185 }
186 
187 #endif
typename real_type_of< T >::type real_type_of_t
Helper template for real_type_of.
Definition: real_type_of.hpp:55
Definition: fixed_value.hpp:41
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
Definition for values::to_value_type.
decltype(auto) constexpr to_value_type(Arg &&arg)
Convert, if necessary, a fixed or dynamic value to its underlying base type.
Definition: to_value_type.hpp:28
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
constexpr auto imag(const Arg &arg)
A constexpr function to obtain the imaginary part of a (complex) number.
Definition: imag.hpp:40
Definition for values::imag.
decltype(auto) constexpr operator()(Arg &&arg) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: make_complex_number.hpp:132
decltype(auto) constexpr operator()(Re &&re, Im &&im) const
Make a complex number from real and imaginary parts, deriving the complex type from the arguments...
Definition: make_complex_number.hpp:168
Definition: make_complex_number.hpp:45
Definition of utilities for atan functions.
Definition: fixed.hpp:24
constexpr auto real(const Arg &arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
Definition for values::fixed_value_of.
Definition for values::number.
Definition for value:real_type_of and value:real_type_of_t.
Definition for values::real.
Definition: number_traits.hpp:36
Traits for arithmetic and complex scalar types.
Definition for values::complex.
Definition for values::value.