jaulib v1.5.0
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
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 <climits>
29#include <cmath>
30#include <concepts>
31#include <type_traits>
32
33#include <jau/int_math_ct.hpp>
34#include <jau/int_types.hpp>
35#include <jau/type_concepts.hpp>
36
37namespace jau {
38
39 /** \addtogroup Integer
40 *
41 * @{
42 */
43
44 /**
45 * base_math: arithmetic types, i.e. integral + floating point types
46 * int_math: integral types
47 * float_math: floating point types
48 // *************************************************
49 // *************************************************
50 // *************************************************
51 */
52
53 // Remember: constexpr specifier used in a function or static data member (since C++17) declaration implies inline.
54
55 /**
56 * Returns true, if both integer point values differ less than the given range.
57 * @tparam T an arithmetic type
58 * @param a value to compare
59 * @param b value to compare
60 * @param range the maximum difference both values may differ
61 */
62 template<jau::req::arithmetic T>
63 bool in_range(const T& a, const T& b, const T& range) {
64 return std::abs(a-b) <= range;
65 }
66
67 /** Returns true of the given integral is positive, i.e. >= 0. */
68 template<typename T>
70 constexpr bool is_positive(const T a) noexcept {
71 return a >= 0;
72 }
73
74 template<typename T>
75 requires std::floating_point<T>
76 constexpr bool is_positive(const T a) noexcept {
77 return a >= 0;
78 }
79
80 template<typename T>
82 constexpr bool is_positive(const T) noexcept {
83 return true;
84 }
85
86 /**
87 * Returns the value of the sign function (w/o branching ?) in O(1).
88 * <pre>
89 * -1 for x < 0
90 * 0 for x = 0
91 * 1 for x > 0
92 * </pre>
93 * Implementation is type safe.
94 *
95 * Branching may occur due to relational operator.
96 *
97 * @tparam T an arithmetic number type
98 * @param x the arithmetic number
99 * @return function result
100 */
101 template <jau::req::signed_arithmetic T>
102 constexpr int sign(const T x) noexcept
103 {
104 return (int) ( (T(0) < x) - (x < T(0)) );
105 }
106
107 template <jau::req::unsigned_arithmetic T>
108 constexpr int sign(const T x) noexcept
109 {
110 return (int) ( T(0) < x );
111 }
112
113 /**
114 * Safely inverts the sign of an arithmetic number w/ branching in O(1)
115 *
116 * Implementation takes special care to have T_MIN, i.e. std::numeric_limits<T>::min(),
117 * converted to T_MAX, i.e. std::numeric_limits<T>::max().<br>
118 * This is necessary since <code>T_MAX < | -T_MIN |</code> and the result would
119 * not fit in the return type T otherwise.
120 *
121 * Hence for the extreme minimum case:
122 * <pre>
123 * jau::invert_sign<int32_t>(INT32_MIN) = | INT32_MIN | - 1 = INT32_MAX
124 * </pre>
125 *
126 * Otherwise with x < 0:
127 * <pre>
128 * jau::invert_sign<int32_t>(x) = | x | = -x
129 * </pre>
130 * and x >= 0:
131 * <pre>
132 * jau::invert_sign<int32_t>(x) = -x
133 * </pre>
134 *
135 * @tparam T an unsigned arithmetic number type
136 * @param x the number
137 * @return function result
138 */
139 template <jau::req::signed_arithmetic T>
140 constexpr T invert_sign(const T x) noexcept
141 {
142 return std::numeric_limits<T>::min() == x ? std::numeric_limits<T>::max() : -x;
143 }
144
145 template <jau::req::unsigned_arithmetic T>
146 constexpr T invert_sign(const T x) noexcept
147 {
148 return x;
149 }
150
151 /**
152 * Returns the absolute value of an arithmetic number (w/ branching) in O(1)
153 *
154 * - signed uses jau::invert_sign() to have a safe absolute value conversion
155 * - unsigned just returns the value
156 * - 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)
157 *
158 * This implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
159 *
160 * @tparam T an arithmetic number type
161 * @param x the number
162 * @return function result
163 */
164 template <jau::req::signed_arithmetic T>
165 constexpr T abs(const T x) noexcept
166 {
167 return jau::sign<T>(x) < 0 ? jau::invert_sign<T>( x ) : x;
168 }
169
170 template <jau::req::unsigned_arithmetic T>
171 constexpr T abs(const T x) noexcept
172 {
173 return x;
174 }
175
176 /**
177 * Returns the unsigned typed absolute value of an arithmetic number (w/ branching) in O(1)
178 *
179 * Implementation handles 2-complement case INT_MIN -> -INT_MIN, i.e. INT_MAX+1 as unsigned
180 *
181 * @tparam T an arithmetic number type
182 * @param x the number
183 * @return function result
184 */
185 template<jau::req::signed_arithmetic T>
186 constexpr std::make_unsigned_t<T> unsigned_value(const T x) noexcept {
187 using U = std::make_unsigned_t<T>;
188 if (jau::sign<T>(x) < 0) {
189 if (std::numeric_limits<T>::min() == x) {
190 return U(std::numeric_limits<T>::max()) + U(1);
191 } else {
192 return U(-x);
193 }
194 } else {
195 return U(x);
196 }
197 }
198
199 template <jau::req::unsigned_arithmetic T>
200 constexpr T unsigned_value(const T x) noexcept
201 {
202 return x;
203 }
204
205 /**
206 * Returns the minimum of two integrals (w/ branching) in O(1)
207 *
208 * @tparam T an arithmetic number type
209 * @param x one number
210 * @param x the other number
211 */
212 template <jau::req::arithmetic T>
213 constexpr T min(const T x, const T y) noexcept
214 {
215 return x < y ? x : y;
216 }
217
218 /**
219 * Returns the maximum of two integrals (w/ branching) in O(1)
220 *
221 * @tparam T an arithmetic number type
222 * @param x one number
223 * @param x the other number
224 */
225 template <jau::req::arithmetic T>
226 constexpr T max(const T x, const T y) noexcept
227 {
228 return x > y ? x : y;
229 }
230
231 /**
232 * Returns constrained integral value to lie between given min- and maximum value (w/ branching) in O(1).
233 *
234 * Implementation returns `min(max(x, min_val), max_val)`, analog to GLSL's clamp()
235 *
236 * @tparam T an arithmetic number type
237 * @param x one number
238 * @param min_val the minimum limes, inclusive
239 * @param max_val the maximum limes, inclusive
240 */
241 template <jau::req::arithmetic T>
242 constexpr T clamp(const T x, const T min_val, const T max_val) noexcept
243 {
244 return jau::min<T>(jau::max<T>(x, min_val), max_val);
245 }
246
247 /**@}*/
248
249} // namespace jau
250
251#endif /* JAU_BASE_MATH_HPP_ */
Concept of type-trait std::is_signed and std::is_integral.
Concept of type-trait std::is_unsigned and std::is_integral.
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an arithmetic number w/ branching in O(1)
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)...
constexpr int sign(const T x) noexcept
Returns the value of the sign function (w/o branching ?) in O(1).
constexpr bool is_positive(const T a) noexcept
Returns true of the given integral is positive, i.e.
Definition base_math.hpp:70
constexpr std::make_unsigned_t< T > unsigned_value(const T x) noexcept
Returns the unsigned typed absolute value of an arithmetic number (w/ branching) in O(1)
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
bool in_range(const T &a, const T &b, const T &range)
base_math: arithmetic types, i.e.
Definition base_math.hpp:63
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32