jaulib v1.3.0
Jau Support Library (C++, Java, ..)
base_math.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef JAU_BASE_MATH_HPP_
26#define JAU_BASE_MATH_HPP_
27
28#include <cstdint>
29#include <cmath>
30#include <climits>
31
32#include <jau/int_types.hpp>
33#include <jau/int_math_ct.hpp>
34
35namespace jau {
36
37 /** \addtogroup Integer
38 *
39 * @{
40 */
41
42 /**
43 * base_math: arithmetic types, i.e. integral + floating point types
44 * int_math: integral types
45 * float_math: floating point types
46 // *************************************************
47 // *************************************************
48 // *************************************************
49 */
50
51 // Remember: constexpr specifier used in a function or static data member (since C++17) declaration implies inline.
52
53 /**
54 * Returns true, if both integer point values differ less than the given range.
55 * @tparam T an arithmetic type
56 * @param a value to compare
57 * @param b value to compare
58 * @param range the maximum difference both values may differ
59 */
60 template<class T,
61 std::enable_if_t<std::is_arithmetic_v<T>, bool> = true>
62 bool in_range(const T& a, const T& b, const T& range) {
63 return std::abs(a-b) <= range;
64 }
65
66 /**
67 * Returns the value of the sign function (w/o branching ?) in O(1).
68 * <pre>
69 * -1 for x < 0
70 * 0 for x = 0
71 * 1 for x > 0
72 * </pre>
73 * Implementation is type safe.
74 *
75 * Branching may occur due to relational operator.
76 *
77 * @tparam T an arithmetic number type
78 * @param x the arithmetic number
79 * @return function result
80 */
81 template <typename T,
82 std::enable_if_t< std::is_arithmetic_v<T> &&
83 !std::is_unsigned_v<T>, bool> = true>
84 constexpr int sign(const T x) noexcept
85 {
86 return (int) ( (T(0) < x) - (x < T(0)) );
87 }
88
89 template <typename T,
90 std::enable_if_t< std::is_arithmetic_v<T> &&
91 std::is_unsigned_v<T>, bool> = true>
92 constexpr int sign(const T x) noexcept
93 {
94 return (int) ( T(0) < x );
95 }
96
97 /**
98 * Safely inverts the sign of an arithmetic number w/ branching in O(1)
99 *
100 * Implementation takes special care to have T_MIN, i.e. std::numeric_limits<T>::min(),
101 * converted to T_MAX, i.e. std::numeric_limits<T>::max().<br>
102 * This is necessary since <code>T_MAX < | -T_MIN |</code> and the result would
103 * not fit in the return type T otherwise.
104 *
105 * Hence for the extreme minimum case:
106 * <pre>
107 * jau::invert_sign<int32_t>(INT32_MIN) = | INT32_MIN | - 1 = INT32_MAX
108 * </pre>
109 *
110 * Otherwise with x < 0:
111 * <pre>
112 * jau::invert_sign<int32_t>(x) = | x | = -x
113 * </pre>
114 * and x >= 0:
115 * <pre>
116 * jau::invert_sign<int32_t>(x) = -x
117 * </pre>
118 *
119 * @tparam T an unsigned arithmetic number type
120 * @param x the number
121 * @return function result
122 */
123 template <typename T,
124 std::enable_if_t< std::is_arithmetic_v<T> &&
125 !std::is_unsigned_v<T>, bool> = true>
126 constexpr T invert_sign(const T x) noexcept
127 {
129 }
130
131 template <typename T,
132 std::enable_if_t< std::is_arithmetic_v<T> &&
133 std::is_unsigned_v<T>, bool> = true>
134 constexpr T invert_sign(const T x) noexcept
135 {
136 return x;
137 }
138
139 /**
140 * Returns the absolute value of an arithmetic number (w/ branching) in O(1)
141 *
142 * - signed uses jau::invert_sign() to have a safe absolute value conversion
143 * - unsigned just returns the value
144 * - 2-complement branch-less is not used due to lack of INT_MIN -> INT_MAX conversion, [bithacks Integer-Abs](http://www.graphics.stanford.edu/~seander/bithacks.html#IntegerAbs)
145 *
146 * This implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
147 *
148 * @tparam T an arithmetic number type
149 * @param x the number
150 * @return function result
151 */
152 template <typename T,
153 std::enable_if_t< std::is_arithmetic_v<T> &&
154 !std::is_unsigned_v<T>, bool> = true>
155 constexpr T abs(const T x) noexcept
156 {
157 return jau::sign<T>(x) < 0 ? jau::invert_sign<T>( x ) : x;
158 }
159
160 template <typename T,
161 std::enable_if_t< std::is_arithmetic_v<T> &&
162 std::is_unsigned_v<T>, bool> = true>
163 constexpr T abs(const T x) noexcept
164 {
165 return x;
166 }
167
168 /**
169 * Returns the minimum of two integrals (w/ branching) in O(1)
170 *
171 * @tparam T an arithmetic number type
172 * @param x one number
173 * @param x the other number
174 */
175 template <typename T,
176 std::enable_if_t< std::is_arithmetic_v<T>, bool> = true>
177 constexpr T min(const T x, const T y) noexcept
178 {
179 return x < y ? x : y;
180 }
181
182 /**
183 * Returns the maximum of two integrals (w/ branching) in O(1)
184 *
185 * @tparam T an arithmetic number type
186 * @param x one number
187 * @param x the other number
188 */
189 template <typename T,
190 std::enable_if_t< std::is_arithmetic_v<T>, bool> = true>
191 constexpr T max(const T x, const T y) noexcept
192 {
193 return x > y ? x : y;
194 }
195
196 /**
197 * Returns constrained integral value to lie between given min- and maximum value (w/ branching) in O(1).
198 *
199 * Implementation returns `min(max(x, min_val), max_val)`, analog to GLSL's clamp()
200 *
201 * @tparam T an arithmetic number type
202 * @param x one number
203 * @param min_val the minimum limes, inclusive
204 * @param max_val the maximum limes, inclusive
205 */
206 template <typename T,
207 std::enable_if_t< std::is_arithmetic_v<T>, bool> = true>
208 constexpr T clamp(const T x, const T min_val, const T max_val) noexcept
209 {
210 return jau::min<T>(jau::max<T>(x, min_val), max_val);
211 }
212
213 /**@}*/
214
215} // namespace jau
216
217#endif /* JAU_BASE_MATH_HPP_ */
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an arithmetic number w/ branching in O(1)
Definition: base_math.hpp:126
constexpr T clamp(const T x, const T min_val, const T max_val) noexcept
Returns constrained integral value to lie between given min- and maximum value (w/ branching) in O(1)...
Definition: base_math.hpp:208
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:177
bool in_range(const T &a, const T &b, const T &range)
base_math: arithmetic types, i.e.
Definition: base_math.hpp:62
constexpr int sign(const T x) noexcept
Returns the value of the sign function (w/o branching ?) in O(1).
Definition: base_math.hpp:84
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:191
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
Definition: base_math.hpp:155
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32