WPILibC++ 2024.3.2
hypot.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2023 Keith O'Hara
4 ##
5 ## This file is part of the GCE-Math C++ library.
6 ##
7 ## Licensed under the Apache License, Version 2.0 (the "License");
8 ## you may not use this file except in compliance with the License.
9 ## You may obtain a copy of the License at
10 ##
11 ## http://www.apache.org/licenses/LICENSE-2.0
12 ##
13 ## Unless required by applicable law or agreed to in writing, software
14 ## distributed under the License is distributed on an "AS IS" BASIS,
15 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ## See the License for the specific language governing permissions and
17 ## limitations under the License.
18 ##
19 ################################################################################*/
20
21/*
22 * compile-time Pythagorean addition function
23 */
24
25// see: https://en.wikipedia.org/wiki/Pythagorean_addition
26
27#ifndef _gcem_hypot_HPP
28#define _gcem_hypot_HPP
29
30#include <algorithm>
31#include <cmath>
32#include <type_traits>
33
34namespace gcem
35{
36
37namespace internal
38{
39
40template<typename T>
41constexpr
42T
43hypot_compute(const T x, const T y)
44noexcept
45{
46 T a = std::max(abs(x), abs(y));
47 if (a) {
48 return a * sqrt((x / a) * (x / a) + (y / a) * (y / a));
49 } else {
50 return {};
51 }
52}
53
54template<typename T>
55constexpr
56T
57hypot_compute(const T x, const T y, const T z)
58noexcept
59{
60 T a = std::max({abs(x), abs(y), abs(z)});
61 if (a) {
62 return a * sqrt((x / a) * (x / a) + (y / a) * (y / a) + (z / a) * (z / a));
63 } else {
64 return {};
65 }
66}
67
68template<typename T>
69constexpr
70T
71hypot_vals_check(const T x, const T y)
72noexcept
73{
74 return( any_nan(x, y) ? \
76 //
77 any_inf(x,y) ? \
79 // indistinguishable from zero or one
80 GCLIM<T>::min() > abs(x) ? \
81 abs(y) :
82 GCLIM<T>::min() > abs(y) ? \
83 abs(x) :
84 // else
85 hypot_compute(x, y) );
86}
87
88template<typename T>
89constexpr
90T
91hypot_vals_check(const T x, const T y, const T z)
92noexcept
93{
94 return( any_nan(x, y, z) ? \
96 //
97 any_inf(x,y,z) ? \
99 // indistinguishable from zero or one
100 GCLIM<T>::min() > abs(x) && GCLIM<T>::min() > abs(y) ? \
101 abs(z) :
102 GCLIM<T>::min() > abs(x) && GCLIM<T>::min() > abs(z) ? \
103 abs(y) :
104 GCLIM<T>::min() > abs(y) && GCLIM<T>::min() > abs(z) ? \
105 abs(x) :
106 GCLIM<T>::min() > abs(x) ? \
107 hypot_vals_check(y, z) :
108 GCLIM<T>::min() > abs(y) ? \
109 hypot_vals_check(x, z) :
110 GCLIM<T>::min() > abs(z) ? \
111 hypot_vals_check(x, y) :
112 // else
113 hypot_compute(x, y, z) );
114}
115
116template<typename T1, typename T2, typename TC = common_return_t<T1,T2>>
117constexpr
118TC
119hypot_type_check(const T1 x, const T2 y)
120noexcept
121{
122 return hypot_vals_check(static_cast<TC>(x),static_cast<TC>(y));
123}
124
125template<typename T1, typename T2, typename T3, typename TC = common_return_t<T1,T2,T3>>
126constexpr
127TC
128hypot_type_check(const T1 x, const T2 y, const T3 z)
129noexcept
130{
131 return hypot_vals_check(static_cast<TC>(x),static_cast<TC>(y),static_cast<TC>(z));
132}
133
134}
135
136/**
137 * Compile-time Pythagorean addition function
138 *
139 * @param x a real-valued input.
140 * @param y a real-valued input.
141 * @return Computes \f$ x \oplus y = \sqrt{x^2 + y^2} \f$.
142 */
143
144template<typename T1, typename T2>
145constexpr
146common_return_t<T1,T2>
147hypot(const T1 x, const T2 y)
148noexcept
149{
151 return internal::hypot_type_check(x,y);
152 } else {
153 return std::hypot(x, y);
154 }
155}
156
157/**
158 * Compile-time Pythagorean addition function
159 *
160 * @param x a real-valued input.
161 * @param y a real-valued input.
162 * @param z a real-valued input.
163 * @return Computes \f$ x \oplus y \oplus z = \sqrt{x^2 + y^2 + z^2} \f$.
164 */
165
166template<typename T1, typename T2, typename T3>
167constexpr
168common_return_t<T1,T2,T3>
169hypot(const T1 x, const T2 y, const T3 z)
170noexcept
171{
173 return internal::hypot_type_check(x,y,z);
174 } else {
175 return std::hypot(x, y, z);
176 }
177}
178
179}
180
181#endif
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition: core.h:304
constexpr TC hypot_type_check(const T1 x, const T2 y) noexcept
Definition: hypot.hpp:119
constexpr bool any_nan(const T1 x, const T2 y) noexcept
Definition: is_nan.hpp:48
constexpr T hypot_compute(const T x, const T y) noexcept
Definition: hypot.hpp:43
constexpr T hypot_vals_check(const T x, const T y) noexcept
Definition: hypot.hpp:71
constexpr bool any_inf(const T1 x, const T2 y) noexcept
Definition: is_inf.hpp:140
Definition: is_even.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
constexpr common_return_t< T1, T2, T3 > hypot(const T1 x, const T2 y, const T3 z) noexcept
Compile-time Pythagorean addition function.
Definition: hypot.hpp:169
constexpr common_return_t< T1, T2 > hypot(const T1 x, const T2 y) noexcept
Compile-time Pythagorean addition function.
Definition: hypot.hpp:147
constexpr return_t< T > sqrt(const T x) noexcept
Compile-time square-root function.
Definition: sqrt.hpp:109
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
UnitTypeLhs() max(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition: base.h:3417