jaulib v1.4.1
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
31#include <jau/int_math_ct.hpp>
32#include <jau/int_types.hpp>
33#include <jau/type_concepts.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<jau::req::arithmetic T>
61 bool in_range(const T& a, const T& b, const T& range) {
62 return std::abs(a-b) <= range;
63 }
64
65 /**
66 * Returns the value of the sign function (w/o branching ?) in O(1).
67 * <pre>
68 * -1 for x < 0
69 * 0 for x = 0
70 * 1 for x > 0
71 * </pre>
72 * Implementation is type safe.
73 *
74 * Branching may occur due to relational operator.
75 *
76 * @tparam T an arithmetic number type
77 * @param x the arithmetic number
78 * @return function result
79 */
80 template <jau::req::signed_arithmetic T>
81 constexpr int sign(const T x) noexcept
82 {
83 return (int) ( (T(0) < x) - (x < T(0)) );
84 }
85
86 template <jau::req::unsigned_arithmetic T>
87 constexpr int sign(const T x) noexcept
88 {
89 return (int) ( T(0) < x );
90 }
91
92 /**
93 * Safely inverts the sign of an arithmetic number w/ branching in O(1)
94 *
95 * Implementation takes special care to have T_MIN, i.e. std::numeric_limits<T>::min(),
96 * converted to T_MAX, i.e. std::numeric_limits<T>::max().<br>
97 * This is necessary since <code>T_MAX < | -T_MIN |</code> and the result would
98 * not fit in the return type T otherwise.
99 *
100 * Hence for the extreme minimum case:
101 * <pre>
102 * jau::invert_sign<int32_t>(INT32_MIN) = | INT32_MIN | - 1 = INT32_MAX
103 * </pre>
104 *
105 * Otherwise with x < 0:
106 * <pre>
107 * jau::invert_sign<int32_t>(x) = | x | = -x
108 * </pre>
109 * and x >= 0:
110 * <pre>
111 * jau::invert_sign<int32_t>(x) = -x
112 * </pre>
113 *
114 * @tparam T an unsigned arithmetic number type
115 * @param x the number
116 * @return function result
117 */
118 template <jau::req::signed_arithmetic T>
119 constexpr T invert_sign(const T x) noexcept
120 {
121 return std::numeric_limits<T>::min() == x ? std::numeric_limits<T>::max() : -x;
122 }
123
124 template <jau::req::unsigned_arithmetic T>
125 constexpr T invert_sign(const T x) noexcept
126 {
127 return x;
128 }
129
130 /**
131 * Returns the absolute value of an arithmetic number (w/ branching) in O(1)
132 *
133 * - signed uses jau::invert_sign() to have a safe absolute value conversion
134 * - unsigned just returns the value
135 * - 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)
136 *
137 * This implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
138 *
139 * @tparam T an arithmetic number type
140 * @param x the number
141 * @return function result
142 */
143 template <jau::req::signed_arithmetic T>
144 constexpr T abs(const T x) noexcept
145 {
146 return jau::sign<T>(x) < 0 ? jau::invert_sign<T>( x ) : x;
147 }
148
149 template <jau::req::unsigned_arithmetic T>
150 constexpr T abs(const T x) noexcept
151 {
152 return x;
153 }
154
155 /**
156 * Returns the minimum of two integrals (w/ branching) in O(1)
157 *
158 * @tparam T an arithmetic number type
159 * @param x one number
160 * @param x the other number
161 */
162 template <jau::req::arithmetic T>
163 constexpr T min(const T x, const T y) noexcept
164 {
165 return x < y ? x : y;
166 }
167
168 /**
169 * Returns the maximum 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 <jau::req::arithmetic T>
176 constexpr T max(const T x, const T y) noexcept
177 {
178 return x > y ? x : y;
179 }
180
181 /**
182 * Returns constrained integral value to lie between given min- and maximum value (w/ branching) in O(1).
183 *
184 * Implementation returns `min(max(x, min_val), max_val)`, analog to GLSL's clamp()
185 *
186 * @tparam T an arithmetic number type
187 * @param x one number
188 * @param min_val the minimum limes, inclusive
189 * @param max_val the maximum limes, inclusive
190 */
191 template <jau::req::arithmetic T>
192 constexpr T clamp(const T x, const T min_val, const T max_val) noexcept
193 {
194 return jau::min<T>(jau::max<T>(x, min_val), max_val);
195 }
196
197 /**@}*/
198
199} // namespace jau
200
201#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)
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).
Definition base_math.hpp:81
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:61
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