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