jaulib v1.3.0
Jau Support Library (C++, Java, ..)
test_int_math01.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 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#include <thread>
25#include <cassert>
26#include <cinttypes>
27#include <cstring>
28
30
31#include <jau/int_math.hpp>
32
33using namespace jau;
34using namespace jau::int_literals;
35
36TEST_CASE( "Int Math Test 00", "[sign][arithmetic][math]" ) {
37 REQUIRE( 1 == jau::sign( 1) );
38 REQUIRE( 0 == jau::sign( 0) );
39 REQUIRE( -1 == jau::sign(-1) );
40 REQUIRE( 1 == jau::sign( 1_i64) );
41 REQUIRE( 0 == jau::sign( 0_i64) );
42 REQUIRE( -1 == jau::sign(-1_i64) );
43 REQUIRE( 1 == jau::sign( 1_u64) );
44 REQUIRE( 0 == jau::sign( 0_u64) );
45
48 REQUIRE( -1 == jau::sign( std::numeric_limits<int64_t>::min() ) );
49}
50TEST_CASE( "Int Math Test 01", "[round][align][arithmetic][math]" ) {
51 {
52 REQUIRE( 0_u32 == jau::round_up( 0_u32, 1_u32) );
53 REQUIRE( 1_u32 == jau::round_up( 1_u32, 1_u32) );
54 REQUIRE( 2_u32 == jau::round_up( 2_u32, 1_u32) );
55
56 REQUIRE( 0_u32 == jau::round_up( 0_u32, 8_u32) );
57 REQUIRE( 8_u32 == jau::round_up( 1_u32, 8_u32) );
58 REQUIRE( 8_u32 == jau::round_up( 7_u32, 8_u32) );
59 REQUIRE( 8_u32 == jau::round_up( 8_u32, 8_u32) );
60 REQUIRE( 16_u32 == jau::round_up( 9_u32, 8_u32) );
61 }
62 {
63 REQUIRE( 0_u32 == jau::round_down( 0_u32, 1_u32) );
64 REQUIRE( 1_u32 == jau::round_down( 1_u32, 1_u32) );
65 REQUIRE( 2_u32 == jau::round_down( 2_u32, 1_u32) );
66
67 REQUIRE( 0_u32 == jau::round_down( 0_u32, 8_u32) );
68 REQUIRE( 0_u32 == jau::round_down( 1_u32, 8_u32) );
69 REQUIRE( 0_u32 == jau::round_down( 7_u32, 8_u32) );
70 REQUIRE( 8_u32 == jau::round_down( 8_u32, 8_u32) );
71 REQUIRE( 8_u32 == jau::round_down( 9_u32, 8_u32) );
72 }
73}
74TEST_CASE( "Int Math Test 02", "[abs][arithmetic][math]" ) {
75 {
76 // abs unsigned integral
77 REQUIRE( 1_u64 == jau::abs( 1_u64) );
79
80 // abs float
81 REQUIRE( 1.0f == jau::abs( 1.0f ) );
82 REQUIRE( 1.0f == jau::abs(-1.0f ) );
86 }
87 {
88 // abs signed integral
89 REQUIRE( 1 == jau::abs( 1) );
90 REQUIRE( 1 == jau::abs(-1) );
91 REQUIRE( 1 == jau::ct_abs( 1) );
92 REQUIRE( 1 == jau::ct_abs(-1) );
93 REQUIRE( 1_i64 == jau::abs( 1_i64) );
94 REQUIRE( 1_i64 == jau::abs(-1_i64) );
95 REQUIRE( 1_i64 == jau::ct_abs( 1_i64) );
96 REQUIRE( 1_i64 == jau::ct_abs(-1_i64) );
97
100
102 // REQUIRE( std::numeric_limits<int64_t>::min() == jau::ct_abs( std::numeric_limits<int64_t>::min() ) ); // UB
103
105 // REQUIRE( std::numeric_limits<int64_t>::max() == std::abs( std::numeric_limits<int64_t>::min() ) ); // UB
106
107 REQUIRE( INT32_MAX == jau::abs( INT32_MAX ) );
108 REQUIRE( INT32_MAX == jau::abs( INT32_MAX ) );
109
110 REQUIRE( INT32_MAX == jau::ct_abs( INT32_MAX ) );
111 // REQUIRE( INT32_MIN == jau::ct_abs( INT32_MIN ) ); // UB
112
113 REQUIRE( INT32_MAX == std::abs( INT32_MAX ) );
114 // REQUIRE( INT32_MAX == std::abs( INT32_MIN ) ); // UB
115 }
116}
117
118TEST_CASE( "Int Math Test 03a", "[min][max][clip][arithmetic][math]" ) {
119 REQUIRE( 0 == jau::min( 0, INT32_MAX ) );
120 REQUIRE( INT32_MAX == jau::max( 0, INT32_MAX ) );
121 REQUIRE( INT32_MAX-1== jau::min( INT32_MAX-1, INT32_MAX ) );
122 REQUIRE( INT32_MAX == jau::max( INT32_MAX-1, INT32_MAX ) );
123 REQUIRE( INT32_MIN == jau::min( 0, INT32_MIN ) );
124 REQUIRE( 0 == jau::max( 0, INT32_MIN ) );
125 REQUIRE( INT32_MIN == jau::min( INT32_MIN+1, INT32_MIN ) );
126 REQUIRE( INT32_MIN+1== jau::max( INT32_MIN+1, INT32_MIN ) );
127 REQUIRE( 0 == jau::clamp( 0, -10, 10 ) );
128 REQUIRE( -10 == jau::clamp( INT32_MIN, -10, 10 ) );
129 REQUIRE( 10 == jau::clamp( INT32_MAX, -10, 10 ) );
130}
131
132TEST_CASE( "Int Math Test 03b", "[ct_min][ct_max][clip2][arithmetic][math]" ) {
133 REQUIRE( 0 == jau::ct_min( 0, INT32_MAX ) );
134 REQUIRE( INT32_MAX == jau::ct_max( 0, INT32_MAX ) );
135 REQUIRE( INT32_MAX-1== jau::ct_min( INT32_MAX-1, INT32_MAX ) );
136 REQUIRE( INT32_MAX == jau::ct_max( INT32_MAX-1, INT32_MAX ) );
137 REQUIRE( INT32_MIN+1 == jau::ct_min( 0, INT32_MIN+1 ) ); // limitation: `MIN <= x - y <= MAX`
138 REQUIRE( 0 == jau::ct_max( 0, INT32_MIN+1 ) ); // limitation: `MIN <= x - y <= MAX`
139 REQUIRE( INT32_MIN == jau::ct_min( INT32_MIN+1, INT32_MIN ) );
140 REQUIRE( INT32_MIN+1== jau::ct_max( INT32_MIN+1, INT32_MIN ) );
141 REQUIRE( 0 == jau::ct_clamp( 0, -10, 10 ) );
142 REQUIRE( -10 == jau::ct_clamp( INT32_MIN+11, -10, 10 ) ); // limitation: `MIN <= x - y <= MAX`
143 REQUIRE( 10 == jau::ct_clamp( INT32_MAX-11, -10, 10 ) ); // limitation: `MIN <= x - y <= MAX`
144}
145
146
147TEST_CASE( "Int Math Test 10", "[bits][arithmetic][math]" ) {
148 {
149 REQUIRE( 0b0000000000000000U == ct_masked_merge( 0b0000000000000000U, 0b0000000000000000U, 0b0000000000000000U ) );
150 REQUIRE( 0b1100000000000011U == ct_masked_merge( 0b1111111100000000U, 0b1100000000000000U, 0b0000000000000011U ) );
151 REQUIRE( 64_u32 == ct_masked_merge( 0b1111111111111111U, 64_u32, 256_u32 ) );
152 REQUIRE( 256_u32 == ct_masked_merge( 0b0000000000000000U, 64_u32, 256_u32 ) );
153 }
154 {
155 REQUIRE( true == is_power_of_2( 2_u32 ) );
156 REQUIRE( true == is_power_of_2( 4_u32 ) );
157 REQUIRE( true == is_power_of_2( 64_u32 ) );
158 }
159 {
160 REQUIRE( 0 == round_to_power_of_2(0) );
161 REQUIRE( 1 == round_to_power_of_2(1) );
162 REQUIRE( 2 == round_to_power_of_2(2) );
163 REQUIRE( 4 == round_to_power_of_2(3) );
164 REQUIRE(64 == round_to_power_of_2(63) );
165 }
166 {
167 REQUIRE( 0 == ct_bit_count( 0b00000000000000000000000000000000UL ) );
168 REQUIRE( 1 == ct_bit_count( 0b00000000000000000000000000000001UL ) );
169 REQUIRE( 1 == ct_bit_count( 0b10000000000000000000000000000000UL ) );
170 REQUIRE( 16 == ct_bit_count( 0b10101010101010101010101010101010UL ) );
171 REQUIRE( 16 == ct_bit_count( 0b01010101010101010101010101010101UL ) );
172 REQUIRE( 32 == ct_bit_count( 0b11111111111111111111111111111111UL ) );
173 }
174 {
175 REQUIRE( 0 == high_bit( 0b00000000U ) );
176 REQUIRE( 1 == high_bit( 0b00000001U ) );
177 REQUIRE( 2 == high_bit( 0b00000010U ) );
178 REQUIRE( 2 == high_bit( 0b00000011U ) );
179 REQUIRE( 8 == high_bit( 0b11000011U ) );
180
181 REQUIRE( 64 == high_bit( 0b1100001111000011110000111100001111000011110000111100001111000011UL ) );
182 }
183}
184TEST_CASE( "Int Math Test 20", "[add][sub][overflow][arithmetic][math]" ) {
185 {
186 {
187 {
188 uint64_t a = 1, b = 2, r;
189 REQUIRE( false == jau::add_overflow(a, b, r) );
190 REQUIRE( a + b == r );
191 }
192 {
193 uint64_t a = std::numeric_limits<uint64_t>::max()-2, b = 2, r;
194 REQUIRE( false == jau::add_overflow(a, b, r) );
195 REQUIRE( a + b == r );
196 }
197 {
198 uint64_t a = std::numeric_limits<uint64_t>::max(), b = 2, r;
199 REQUIRE( true == jau::add_overflow(a, b, r) );
200 }
201 }
202 {
203 {
204 uint64_t a = 2, b = 1, r;
205 REQUIRE( false == jau::sub_overflow(a, b, r) );
206 REQUIRE( a - b == r );
207 }
208 {
209 uint64_t a = std::numeric_limits<uint64_t>::min()+2, b = 2, r;
210 REQUIRE( false == jau::sub_overflow(a, b, r) );
211 REQUIRE( a - b == r );
212 }
213 {
214 uint64_t a = 1, b = 2, r;
215 REQUIRE( true == jau::sub_overflow(a, b, r) );
216 }
217 {
218 uint64_t a = std::numeric_limits<uint64_t>::min(), b = 2, r;
219 REQUIRE( true == jau::sub_overflow(a, b, r) );
220 }
221 }
222 }
223 {
224 {
225 {
226 int64_t a = 1, b = 2, r;
227 REQUIRE( false == jau::add_overflow(a, b, r) );
228 REQUIRE( a + b == r );
229 }
230 {
231 int64_t a = std::numeric_limits<int64_t>::max()-2, b = 2, r;
232 REQUIRE( false == jau::add_overflow(a, b, r) );
233 REQUIRE( a + b == r );
234 }
235 {
236 int64_t a = std::numeric_limits<int64_t>::max(), b = 2, r;
237 REQUIRE( true == jau::add_overflow(a, b, r) );
238 }
239 }
240 {
241 {
242 int64_t a = 2, b = 1, r;
243 REQUIRE( false == jau::sub_overflow(a, b, r) );
244 REQUIRE( a - b == r );
245 }
246 {
247 int64_t a = std::numeric_limits<int64_t>::min()+2, b = 2, r;
248 REQUIRE( false == jau::sub_overflow(a, b, r) );
249 REQUIRE( a - b == r );
250 }
251 {
252 int64_t a = 1, b = 2, r;
253 REQUIRE( false == jau::sub_overflow(a, b, r) );
254 REQUIRE( a - b == r );
255 }
256 {
257 uint64_t a = std::numeric_limits<uint64_t>::min(), b = 2, r;
258 REQUIRE( true == jau::sub_overflow(a, b, r) );
259 }
260 }
261 }
262}
263TEST_CASE( "Int Math Test 21", "[mul][overflow][arithmetic][math]" ) {
264 {
265 {
266 uint64_t a = 1, b = 2, r;
267 REQUIRE( false == jau::mul_overflow(a, b, r) );
268 REQUIRE( a * b == r );
269 }
270 {
271 uint64_t a = std::numeric_limits<uint64_t>::max()/2, b = 2, r;
272 REQUIRE( false == jau::mul_overflow(a, b, r) );
273 REQUIRE( a * b == r );
274 }
275 {
276 uint64_t a = std::numeric_limits<uint64_t>::max(), b = 2, r;
277 REQUIRE( true == jau::mul_overflow(a, b, r) );
278 }
279 }
280 {
281 {
282 int64_t a = 1, b = 2, r;
283 REQUIRE( false == jau::mul_overflow(a, b, r) );
284 REQUIRE( a * b == r );
285 }
286 {
287 int64_t a = std::numeric_limits<int64_t>::max()/2, b = 2, r;
288 REQUIRE( false == jau::mul_overflow(a, b, r) );
289 REQUIRE( a * b == r );
290 }
291 {
292 int64_t a = std::numeric_limits<int64_t>::max(), b = 2, r;
293 REQUIRE( true == jau::mul_overflow(a, b, r) );
294 }
295 }
296}
constexpr uint32_t ct_bit_count(uint32_t n) noexcept
Returns the number of set bits within given 32bit integer (w/o branching) in O(1) and constant time (...
constexpr T ct_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 for MIN <= x - y <= MA...
constexpr T ct_abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/o branching) in O(1) and constant time (CT),...
Definition: int_math_ct.hpp:95
constexpr T ct_max(const T x, const T y) noexcept
Returns the maximum of two integrals for MIN <= x - y <= MAX (w/o branching) in O(1) and constant tim...
constexpr T ct_masked_merge(T mask, T a_if_masked, T b_if_unmasked)
Returns merged a_if_masked bits selected by mask 1 bits and b_if_unmasked bits selected by mask 0 bit...
constexpr T ct_min(const T x, const T y) noexcept
Returns the minimum of two integrals for MIN <= x - y <= MAX (w/o branching) in O(1) and constant tim...
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 round_up(const T n, const U align_to)
Round up w/ branching in O(1)
Definition: int_math.hpp:101
constexpr nsize_t high_bit(T x)
Return the index of the highest set bit w/ branching (loop) in O(n), actually O(n/2).
Definition: int_math.hpp:164
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
constexpr bool mul_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware multiplication returning true if overflow occurred, otherwise false having the...
Definition: int_math.hpp:259
constexpr bool sub_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware subtraction returning true if overflow occurred, otherwise false having the re...
Definition: int_math.hpp:225
constexpr uint32_t round_to_power_of_2(const uint32_t n)
If the given n is not is_power_of_2() return next_power_of_2(), otherwise return n unchanged.
Definition: int_math.hpp:152
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 round_down(T n, U align_to)
Round down w/ branching in O(1)
Definition: int_math.hpp:123
constexpr bool add_overflow(const T a, const T b, T &res) noexcept
Integer overflow aware addition returning true if overflow occurred, otherwise false having the resul...
Definition: int_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
constexpr bool is_power_of_2(const T x) noexcept
Power of 2 test (w/o branching ?) in O(1)
Definition: int_math.hpp:140
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
TEST_CASE("Int Math Test 00", "[sign][arithmetic][math]")