jaulib v1.3.0
Jau Support Library (C++, Java, ..)
test_fractions_01.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022 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/basic_types.hpp>
32
33using namespace jau;
34using namespace jau::fractions_i64_literals;
35using namespace jau::int_literals;
36
37#if 0
38static fraction<int64_t> ratio_multiply(const fraction<int64_t>& r1, const fraction<int64_t>& r2) {
39 const uint64_t gcd1 = gcd<uint64_t>((uint64_t)abs(r1.num), r2.denom);
40 const uint64_t gcd2 = gcd<uint64_t>((uint64_t)abs(r2.num), r1.denom);
41
42 return fraction<int64_t>( ( r1.num / gcd1 ) * ( r2.num / gcd2),
43 ( r1.denom / gcd2 ) * ( r2.denom / gcd1) );
44}
45
46static fraction<int64_t> ratio_divide(const fraction<int64_t>& r1, const fraction<int64_t>& r2) {
47 return ratio_multiply(r1, fraction<int64_t>(r2.denom, r2.num));
48}
49
50static fraction<int64_t> duration_common_type(const fraction<int64_t>& p1, const fraction<int64_t>& p2) {
51 const uint64_t gcd_num = gcd<uint64_t>((uint64_t)abs(p1.num), (uint64_t)abs(p2.num));
52 const uint64_t gcd_den = gcd<uint64_t>(p1.denom, p2.denom);
53 return fraction<int64_t>( gcd_num * jau::sign(p1.num) * jau::sign(p2.num), ( p1.denom / gcd_den ) * p2.denom );
54}
55#endif
56
57
58template<typename int_type>
59static void test_gcd_fract(const int_type n, const std::make_unsigned_t<int_type> d,
60 const int_type exp_gcd, const int_type exp_num, const std::make_unsigned_t<int_type> exp_denom) {
61 {
62 const int_type n1 = sign(n) * abs(n);
63 const std::make_unsigned_t<int_type> d1 = sign(d) * abs(d);
64 REQUIRE( n == n1 );
65 REQUIRE( d == d1 );
66 }
67
68 const int_type _gcd = gcd( n, static_cast<int_type>(d) );
69 REQUIRE( exp_gcd == _gcd );
70
71 fraction<int_type> f1(n, d);
72 REQUIRE( exp_num == f1.num );
73 REQUIRE( exp_denom == f1.denom);
74}
75
76template<typename int_type>
77static void test_gcd_fract_pm(const int_type n, const std::make_unsigned_t<int_type> d,
78 const int_type exp_gcd, const int_type exp_num, const std::make_unsigned_t<int_type> exp_denom) {
79 test_gcd_fract( n, d, exp_gcd, exp_num, exp_denom);
80 test_gcd_fract(-n, d, exp_gcd, -exp_num, exp_denom);
81}
82
83template<typename int_type>
85 const fraction<int_type>& exp_max, const fraction<int_type>& exp_min,
86 const fraction<int_type>& exp_sum, const fraction<int_type>& exp_diff,
87 const fraction<int_type>& exp_mul, const fraction<int_type>& exp_div)
88{
89 const bool show_double = true;
90 INFO_STR( "max(a "+a.to_string(show_double)+", b "+b.to_string(show_double)+") = "+max(a,b).to_string(show_double));
91 INFO_STR( "min(a "+a.to_string(show_double)+", b "+b.to_string(show_double)+") = "+min(a,b).to_string(show_double));
92 INFO_STR( "a "+a.to_string(show_double)+" + b "+b.to_string(show_double)+" = "+(a+b).to_string(show_double));
93 INFO_STR( "a "+a.to_string(show_double)+" - b "+b.to_string(show_double)+" = "+(a-b).to_string(show_double));
94 INFO_STR( "a "+a.to_string(show_double)+" * b "+b.to_string(show_double)+" = "+(a*b).to_string(show_double));
95 INFO_STR( "a "+a.to_string(show_double)+" / b "+b.to_string(show_double)+" = "+(a/b).to_string(show_double));
96 {
97 const double epsilon = std::numeric_limits<double>::epsilon();
98 const double ad = a.to_double();
99 const double bd = b.to_double();
100 if( std::abs( ad - bd ) <= epsilon ) {
101 REQUIRE( a == b );
102 REQUIRE( !(a != b) );
103 REQUIRE( a <= b );
104 REQUIRE( a >= b );
105 } else if( std::abs( ad - bd ) > epsilon ) {
106 REQUIRE( a != b );
107 REQUIRE( !(a == b) );
108 if( ad - bd < -epsilon ) {
109 REQUIRE( a < b );
110 REQUIRE( a <= b );
111 REQUIRE( b > a );
112 REQUIRE( b >= a );
113 } else {
114 REQUIRE( a > b );
115 REQUIRE( a >= b );
116 REQUIRE( b < a );
117 REQUIRE( b <= a );
118 }
119 }
120 }
121 {
122 fraction<int_type> has_max = max(a, b);
123 fraction<int_type> has_min = min(a, b);
124 REQUIRE_MSG( "exp "+to_string(exp_max)+" == has "+to_string(has_max), exp_max == has_max );
125 REQUIRE_MSG( "exp "+to_string(exp_min)+" == has "+to_string(has_min), exp_min == has_min );
126 REQUIRE( has_max >= has_min );
127 REQUIRE( has_min <= has_max );
128 }
129 {
130 const fraction<int_type> has_sum = a + b;
131 const double exp_double = a.to_double() + b.to_double();
132 const double has_double = has_sum.to_double();
133 REQUIRE_MSG( "exp "+std::to_string(exp_double)+" == has "+std::to_string(has_double), abs( exp_double - has_double ) <= std::numeric_limits<double>::epsilon() );
134 REQUIRE_MSG( "exp "+to_string(exp_sum)+" == has "+to_string(has_sum), exp_sum == has_sum );
135 }
136 {
137 fraction<int_type> has_diff = a - b;
138 const double exp_double = a.to_double() - b.to_double();
139 const double has_double = has_diff.to_double();
140 REQUIRE_MSG( "exp "+std::to_string(exp_double)+" == has "+std::to_string(has_double), abs( exp_double - has_double ) <= std::numeric_limits<double>::epsilon() );
141 REQUIRE_MSG( "exp "+to_string(exp_diff)+" == has "+to_string(has_diff), exp_diff == has_diff );
142 }
143 {
144 fraction<int_type> has_mul = a * b;
145 const double exp_double = a.to_double() * b.to_double();
146 const double has_double = has_mul.to_double();
147 REQUIRE_MSG( "exp "+std::to_string(exp_double)+" == has "+std::to_string(has_double), abs( exp_double - has_double ) <= std::numeric_limits<double>::epsilon() );
148 REQUIRE_MSG( "exp "+to_string(exp_mul)+" == has "+to_string(has_mul), exp_mul == has_mul);
149 }
150 {
151 fraction<int_type> has_div = a / b;
152 const double exp_double = a.to_double() / b.to_double();
153 const double has_double = has_div.to_double();
154 REQUIRE_MSG( "exp "+std::to_string(exp_double)+" == has "+std::to_string(has_double), abs( exp_double - has_double ) <= std::numeric_limits<double>::epsilon() );
155 REQUIRE_MSG( "exp "+to_string(exp_div)+" == has "+to_string(has_div), exp_div == has_div);
156 }
157 {
158 const fraction<int_type> step(1, a.denom);
159 const fraction<int_type> lim(a + ( step * (int_type)10 ));
161 int count;
162 for(count = 0; i < lim; i+=step, ++count) { }
163 REQUIRE( i == lim );
164 REQUIRE( i > a );
165 REQUIRE( 10 == count );
166
167 i+=step;
168 REQUIRE( i > lim );
169 REQUIRE( i == lim + step );
170 }
171 if( !std::is_unsigned_v<int_type> ) {
172 const fraction<int_type> step(1, a.denom);
173 const fraction<int_type> lim(a - ( step * (int_type)10 ));
175 int count;
176 for(count = 0; i > lim; i-=step, ++count) { }
177 REQUIRE( i == lim );
178 REQUIRE( i < a );
179 REQUIRE( 10 == count );
180
181 i-=step;
182 REQUIRE( i < lim );
183 REQUIRE( i == lim - step );
184 }
185}
186
187template<typename Rep, typename Period, typename int_type>
188static void test_duration(const fraction<int_type>& a, const std::chrono::duration<Rep, Period>& dur_ref,
189 const Rep exp_count)
190{
191 INFO_STR( " given duration: ( " + std::to_string(dur_ref.count()) + " * " + std::to_string(Period::num) + " = " + std::to_string(dur_ref.count() * Period::num) + " ) / " + std::to_string(Period::den) );
192 {
193 const int64_t d_num = a.to_num_of( fraction_i64(Period::num, Period::den) );
194 std::chrono::duration<Rep, Period> d = a.to_duration( dur_ref );
195 INFO_STR( " fraction-1 " + a.to_string(true) + " -> duration_count " + std::to_string( d_num ) + ", duration " + std::to_string( d.count() ) );
196 INFO_STR( " resulting duration-1: ( " + std::to_string(d.count()) + " * " + std::to_string(Period::num) + " = " + std::to_string(d.count() * Period::num) + " ) / " + std::to_string(Period::den) );
197
198 // fully functional conversion check
200 INFO_STR( " reconverted fraction-2 " + b.to_string(true));
201 REQUIRE( exp_count == d_num );
202 REQUIRE( exp_count == d.count() );
203 REQUIRE( a == b );
204 }
205#if 0
206 {
207 typename std::chrono::duration<Rep, Period>::rep d_count = a.to_duration_count( dur_ref );
208 auto d = a.to_auto_duration();
209 INFO_STR( " fraction-2 " + a.to_string(true) + " -> duration_count " + std::to_string( d_count ) + ", duration " + std::to_string( d.count() ) );
210 INFO_STR( " resulting duration-2: ( " + std::to_string(d.count()) + " * " + std::to_string(Period::num) + " = " + std::to_string(d.count() * Period::num) + " ) / " + std::to_string(Period::den) );
211 INFO_STR( " resulting duration-2: ( " + std::to_string(d.count()) + " * " + std::to_string(decltype(d)::num) + " = " + std::to_string(d.count() * decltype(d)::num) + " ) / " + std::to_string(decltype(d)::den) );
212
213 // fully functional conversion check
215 INFO_STR( " reconverted fraction-2 " + b.to_string(true));
216 REQUIRE( exp_count == d_count );
217 REQUIRE( exp_count == d.count() );
218 REQUIRE( a == b );
219 }
220#endif
221}
222
223
224TEST_CASE( "Fraction Types Test 00", "[fraction][type]" ) {
225 {
226 INFO_STR(" is_trivially_copyable_v<fraction_i64>: " + std::to_string(std::is_trivially_copyable_v<fraction_i64>));
227 INFO_STR(" is_trivially_copyable<fraction_timespec>: " + std::to_string(std::is_trivially_copyable_v<fraction_timespec>));
228 REQUIRE( true == std::is_trivially_copyable_v<fraction_i64> );
229 REQUIRE( true == std::is_trivially_copyable_v<fraction_timespec> );
231 (void)check_type_01;
232 }
233 {
234 INFO_STR(" is_trivially_copyable_v<fraction_i64>: " + std::to_string(std::is_trivially_copyable_v<fraction_i64>));
235 REQUIRE( true == std::is_trivially_copyable_v<fraction_i64> );
237 (void)check_type_01;
238 }
239 {
240 REQUIRE( INT64_MAX == std::numeric_limits<int64_t>::max() );
241 REQUIRE( INT64_MIN == std::numeric_limits<int64_t>::min() );
242
243 REQUIRE( UINT64_MAX == std::numeric_limits<uint64_t>::max() );
244 }
245 {
246 // copy-ctor
247 fraction<int> a(1, 6);
248 fraction<int> b(a);
249 REQUIRE( a == b );
250 }
251 {
252 // move-ctor
253 fraction<int> a0(1, 6);
254 fraction<int> a1(a0);
255 fraction<int> b( a0 );
256 REQUIRE( a1 == b );
257 }
258 {
259 // assignment
260 fraction<int> a(1, 6);
261 fraction<int> b(6, 1);
262 b = a;
263 REQUIRE( a == b );
264 }
265 {
266 // move-assignment
267 fraction<int> a(1, 6);
268 fraction<int> a2(a);
269 fraction<int> b(6, 1);
270 b = a2;
271 REQUIRE( a == b );
272 }
273 {
274 REQUIRE( fractions_i64::zero == 0_s );
275 REQUIRE( fractions_i64::zero == 0_one );
276
277 REQUIRE( fractions_i64::one == 1_one );
278 REQUIRE( fractions_i64::one == 1_s );
279
280 REQUIRE( 3_i64*fractions_i64::tera == 3_T );
281 REQUIRE( 3_i64*fractions_i64::giga == 3_G );
282 REQUIRE( 3_i64*fractions_i64::mega == 3_M );
283 REQUIRE( 3_i64*fractions_i64::kilo == 3_k );
284 REQUIRE( 3_i64*fractions_i64::one == 3_one );
285 REQUIRE( 3_i64*fractions_i64::milli == 3_m );
286 REQUIRE( 3_i64*fractions_i64::micro == 3_u );
287 REQUIRE( 3_i64*fractions_i64::nano == 3_n );
288 REQUIRE( 3_i64*fractions_i64::pico == 3_p );
289
290 REQUIRE( 3_i64*fractions_i64::days == 3_d );
291 REQUIRE( 3_i64*fractions_i64::hours == 3_h );
292 REQUIRE( 3_i64*fractions_i64::minutes == 3_min );
293 REQUIRE( 3_i64*fractions_i64::seconds == 3_s );
294 REQUIRE( 3_i64*fractions_i64::milli == 3_ms );
295 REQUIRE( 3_i64*fractions_i64::micro == 3_us );
296 REQUIRE( 3_i64*fractions_i64::nano == 3_ns );
297 }
298}
299
300TEST_CASE( "Fraction GCD and Modulo Test 00", "[integer][fraction][gcd]" ) {
301 test_gcd_fract<int>(0, 0, 0, 0, 1);
302 test_gcd_fract<uint32_t>(0, 0, 0, 0, 1);
303
304 test_gcd_fract_pm<int>(15, 5, 5, 3, 1);
305 test_gcd_fract_pm<int>(17, 5, 1, 17, 5);
306
307 test_gcd_fract<uint32_t>(15, 5, 5, 3, 1);
308 test_gcd_fract<uint32_t>(17, 5, 1, 17, 5);
309}
310
311static void test_to_num_of(const int64_t exp, const fraction<int64_t>& v, const fraction<int64_t>& new_base, bool exp_overflow=false) noexcept {
312 bool overflow = false;
313 int64_t rr = v.to_num_of(new_base, &overflow);
314 INFO_STR(" value " + v.to_string() );
315 INFO_STR(" new_base " + new_base.to_string() );
316 std::string rr_s = exp == rr ? " - OK " : " - ********* ERROR ";
317 INFO_STR(" rr " + std::to_string(rr) + " =?= " + std::to_string(exp) + rr_s + ", overflow[exp " + std::to_string(exp_overflow) + ", has " + std::to_string(overflow) + "]");
318 if constexpr ( false ) {
319 // leaving elaboration code in .. for future testing overflows
320 const uint64_t _gcd = gcd<uint64_t>( v.denom, new_base.denom );
321 const uint64_t _lcm = ( v.denom * new_base.denom ) / _gcd;
322 int64_t r0 = ( v.num * (int64_t)( _lcm / v.denom ) ) / new_base.num;
323 int64_t r2 = ( v.num * (int64_t)new_base.denom ) / ( (int64_t) v.denom ) / new_base.num;
324 INFO_STR(" gcd " + std::to_string(_gcd) );
325 INFO_STR(" lcm " + std::to_string(_lcm) );
326 INFO_STR(" lcm / v_denom " + std::to_string( _lcm / v.denom) );
327 INFO_STR(" v_num * nb_denum " + std::to_string( v.num * (int64_t)new_base.denom ) );
328 std::string r0_s = exp == r0 ? " - OK " : " - ********* ERROR ";
329 INFO_STR(" r0 " + std::to_string(r0) + " =?= " + std::to_string(exp) + r0_s);
330 std::string r2_s = exp == r2 ? " - OK " : " - ********* ERROR ";
331 INFO_STR(" r2 " + std::to_string(r2) + " =?= " + std::to_string(exp) + r2_s);
332 }
333 REQUIRE( exp_overflow == overflow );
334 if( !exp_overflow ) {
335 REQUIRE( exp == rr );
336 }
337}
338
339TEST_CASE( "Fraction Cast Test 01.1", "[integer][fraction][type][to_num_of]" ) {
340 {
341 test_to_num_of( 2_i64, fractions_i64::one, fraction_i64(1_i64, 2_u64) ); // one -> halves
346 }
347 {
348 fraction_i64 a ( 10_s + 400_ms );
349 fraction_i64 b ( 0_s + 400_ms );
350 fraction_i64 exp_sum ( 10_s + 800_ms );
351
353 test_to_num_of( 10'400'000'000_i64, a, fractions_i64::nano );
355 test_to_num_of( 400'000'000_i64, b, fractions_i64::nano );
356 test_to_num_of( 10_i64, exp_sum, fractions_i64::seconds );
357 test_to_num_of( 10'800'000'000_i64, exp_sum, fractions_i64::nano );
358 }
359 {
360 fraction_i64 n1 ( 999'999'999_ns );
361 fraction_i64 n2 ( 999'999'999_ns );
362 fraction_i64 exp_nsum ( 1'999'999'998_ns );
363 REQUIRE( exp_nsum == n1 + n2 );
364 test_to_num_of( 999'999'999_i64, n1, fractions_i64::nano );
365 test_to_num_of( 1'999'999'998_i64, exp_nsum, fractions_i64::nano );
366 test_to_num_of( 999'999_i64, n1, fractions_i64::micro );
367 test_to_num_of( 1'999'999_i64, exp_nsum, fractions_i64::micro );
368 // OVERFLOW
369 test_to_num_of( 999'999'999'000_i64, n1, fractions_i64::pico, true /* overflow */ );
370 test_to_num_of( 1'999'999'998'000_i64, exp_nsum, fractions_i64::pico, true /* overflow */ );
371 }
372 { // OVERFLOW
373 // 1'000'000'000'000
374 // 999'999'999'999
375 // 1'999'999'999'998
376 fraction_i64 p1 ( 999'999'999'999_p );
377 // fraction_i64 p2 ( 999'999'999'999_p );
378 fraction_i64 exp_sum ( 1'999'999'999'998_p );
379 test_to_num_of( 999'999'999_i64, p1, fractions_i64::pico, true /* overflow */ );
380 test_to_num_of( 1'999'999'999'998_i64, exp_sum, fractions_i64::pico, true /* overflow */);
381 // REQUIRE( exp_sum == p1 + p2 );
382 }
383}
384
385TEST_CASE( "Fraction String Test 01.2", "[integer][fraction][type][string]" ) {
386 {
387 fraction_i64 a;
388 fraction_i64 exp = 10_s;
389
390 REQUIRE( true == to_fraction_i64(a, "10/1", 0_s, 365_d) );
391 REQUIRE( exp == a );
392 {
393 fraction_i64 b;
394 REQUIRE( true == to_fraction_i64(b, a.to_string(), a, a) );
395 REQUIRE( exp == b );
396 }
397
398 REQUIRE( true == to_fraction_i64(a, "10/1", 10_s, 10_s) );
399 REQUIRE( exp == a );
400 {
401 fraction_i64 b;
402 REQUIRE( true == to_fraction_i64(b, a.to_string(), a, a) );
403 REQUIRE( exp == b );
404 }
405
406 REQUIRE( false == to_fraction_i64(a, "10/1", 100_ns, 9_s) );
407 REQUIRE( false == to_fraction_i64(a, "10/1", 11_s, 365_d) );
408 }
409 {
410 fraction_i64 a;
411 REQUIRE( true == to_fraction_i64(a, " 10 / 1000000 ", 0_s, 365_d) );
412 REQUIRE( 10_us == a );
413 {
414 fraction_i64 b;
415 REQUIRE( true == to_fraction_i64(b, a.to_string(), a, a) );
416 REQUIRE( 10_us == b );
417 }
418
419 REQUIRE( false == to_fraction_i64(a, " 10x / 1000000 ", 0_s, 365_d) );
420 REQUIRE( false == to_fraction_i64(a, " 10 / 1000000x ", 0_s, 365_d) );
421 REQUIRE( false == to_fraction_i64(a, " 10 % 1000000x ", 0_s, 365_d) );
422 REQUIRE( false == to_fraction_i64(a, " 10 ", 0_s, 365_d) );
423 }
424}
425
426TEST_CASE( "Fraction Arithmetic Test 02", "[integer][fraction]" ) {
427 {
428 fraction<int> b(1, 6);
429 REQUIRE( b == fraction<int>(2, 12U));
430 }
431 {
432 fraction<int> b(6, 1);
433 REQUIRE( b == fraction<int>(12, 2U));
434 }
435 {
436 fraction<int> a(1, 4), b(1, 6);
437 fraction<int> exp_sum(5, 12);
438 fraction<int> exp_diff(1, 12);
439 fraction<int> exp_mul(1, 24);
440 fraction<int> exp_div(3, 2);
441 test_comp_fract(a, b, a, b, exp_sum, exp_diff, exp_mul, exp_div);
442 }
443 {
444 fraction<int> a(1, 4), b(6, 1);
445 fraction<int> exp_sum(25, 4);
446 fraction<int> exp_diff(-23, 4);
447 fraction<int> exp_mul(3, 2);
448 fraction<int> exp_div(1, 24);
449 test_comp_fract(a, b, b, a, exp_sum, exp_diff, exp_mul, exp_div);
450 }
451 {
452 fraction<int64_t> a(-1, 4), b(-1, 6);
453 fraction<int64_t> exp_sum(-5, 12);
454 fraction<int64_t> exp_diff(-1, 12);
455 fraction<int64_t> exp_mul(1, 24);
456 fraction<int64_t> exp_div(3, 2);
457 test_comp_fract(a, b, b, a, exp_sum, exp_diff, exp_mul, exp_div);
458 }
459 {
460 fraction<int> a(-1, 4), b(-1, 6);
461 fraction<int> exp_sum(-5, 12);
462 fraction<int> exp_diff(-1, 12);
463 fraction<int> exp_mul(1, 24);
464 fraction<int> exp_div(3, 2);
465 test_comp_fract(a, b, b, a, exp_sum, exp_diff, exp_mul, exp_div);
466 }
467 {
468 fraction<int> a(-1, 4), b( 1, 6);
469 fraction<int> exp_sum(-1, 12);
470 fraction<int> exp_diff(-5, 12);
471 fraction<int> exp_mul(-1, 24);
472 fraction<int> exp_div(-3, 2);
473 test_comp_fract(a, b, b, a, exp_sum, exp_diff, exp_mul, exp_div);
474 }
475 {
476 fraction<int> a(1, 4), b(-1, 6);
477 fraction<int> exp_sum(1, 12);
478 fraction<int> exp_diff(5, 12);
479 fraction<int> exp_mul(-1, 24);
480 fraction<int> exp_div(-3, 2);
481 test_comp_fract(a, b, a, b, exp_sum, exp_diff, exp_mul, exp_div);
482 }
483 {
484 // unsigned: micro + nano
485 fraction_u64 a(1, 1'000_u64), b(1, 1'000'000'000_u64);
486 fraction_u64 exp_sum( 1000001_u64, 100'0000'000_u64);
487 fraction_u64 exp_diff( 999999_u64, 1'000'000'000_u64);
488 fraction_u64 exp_mul( 1_u64, 1'000'000'000'000_u64);
489 fraction_u64 exp_div( 1000000_u64, 1_u64);
490 test_comp_fract(a, b, a, b, exp_sum, exp_diff, exp_mul, exp_div);
491 }
492 {
493 // signed: micro + nano
494 fraction_i64 a(1_m), b(1_n);
495 fraction_i64 exp_sum( 1000001_n);
496 fraction_i64 exp_diff( 999999_n);
497 fraction_i64 exp_mul( 1_p);
498 fraction_i64 exp_div( 1000000_one);
499 test_comp_fract(a, b, a, b, exp_sum, exp_diff, exp_mul, exp_div);
500 }
501 {
502 // signed: 100 micro + 1'000'000 nano
503 fraction_i64 a(100_i64*fractions_i64::milli), b(1'000'000_i64*fractions_i64::nano);
504 fraction_i64 exp_sum( 101_i64, 1'000_u64);
505 fraction_i64 exp_diff( 99_i64, 1'000_u64);
506 fraction_i64 exp_mul( 1_i64, 10'000_u64);
507 fraction_i64 exp_div( 100_i64, 1_u64);
508 test_comp_fract(a, b, a, b, exp_sum, exp_diff, exp_mul, exp_div);
509 }
510 {
511 const std::chrono::milliseconds::rep exp_count = 100;
512 const fraction<int64_t> a(static_cast<int64_t>(exp_count) * fractions_i64::milli);
514 }
515 {
516 const std::chrono::nanoseconds::rep exp_count = -50;
517 const fraction_i64 a(static_cast<int64_t>(exp_count) * fractions_i64::nano);
519 }
520 {
521 const std::chrono::hours::rep exp_count = 24;
522 const fraction_i64 a(static_cast<int64_t>(exp_count) * fractions_i64::hours);
524 }
525 {
526 const fraction_i64 refresh_rate = 60_i64/1_s;
527 const fraction_i64 fps = 1_i64 / refresh_rate;
528 REQUIRE( 1_i64 / fps == refresh_rate );
529 REQUIRE( fps == 1_i64 / refresh_rate );
530 REQUIRE( 2_i64 * fps == 1_i64 / ( refresh_rate / 2_i64 ) );
531
532 REQUIRE( fractions_i64::milli / 2_i64 == 500_i64 * fractions_i64::micro );
533 REQUIRE( 1_m / 2_one == 500_one * 1_u );
534 REQUIRE( 1_i64 / fractions_i64::milli == fractions_i64::kilo );
535 REQUIRE( fractions_i64::milli/-1000_i64 == -fractions_i64::micro );
536 REQUIRE( 500_i64 * fractions_i64::milli == fractions_i64::seconds/2_i64 );
537 REQUIRE( 1000_ms == fractions_i64::seconds );
538 REQUIRE( 1_i64 * fractions_i64::seconds == 60_i64/fractions_i64::minutes );
539 REQUIRE( 60_s == fractions_i64::minutes );
540 REQUIRE( 60_s == 1_min );
541 REQUIRE( 60_i64 * fractions_i64::minutes == fractions_i64::hours );
542 REQUIRE( 24_i64 * fractions_i64::hours == fractions_i64::days );
543 REQUIRE( 24_h == 1_d );
544
545 const fraction_i64 m(720_i64 * fractions_i64::minutes); // 12 hours
546 const fraction_i64 h( 48_i64 * fractions_i64::hours);
547 const fraction_i64 d( 2_i64 * fractions_i64::days);
548 const fraction_i64 t = m + h + d;
549 REQUIRE( m == h/4_i64 );
550 REQUIRE( h == d );
551 REQUIRE( t > 4_i64 * fractions_i64::days );
552 }
553 {
554 fraction_i64 a ( 1'000l, 1lu ); // 1'000s
555 fraction_i64 b ( 1'000l, 1'000'000'000lu ); // 1'000ns
556 REQUIRE( 1000_s == a );
557 REQUIRE( 1000_ns == b );
558 fraction_i64 c = a + b;
559 fraction_i64 exp_c ( 1'000'000'000lu + 1lu, 1'000'000lu ); // 1'000ns
560 REQUIRE( exp_c == c );
561 }
562}
563
564/**
565 * Resembling the GNU/Linux bits/types.h,
566 * documenting whether time_t is 32-bit (arm-32) or 64-bit (arm-64, x86_64, ..).
567 */
568static int sizeof_time_t() {
569/* X32 kernel interface is 64-bit. */
570#if defined __x86_64__ && defined __ILP32__
571 // 64 bit size
572 #if __WORDSIZE == 32
573 return sizeof( __int64_t );
574 #else
575 return sizeof( long int );
576 #endif
577#else
578 // 32 bit or 64 bit
579 return sizeof( long int );
580#endif
581}
582
583/**
584 * Resembling the GNU/Linux bits/types.h,
585 * documenting whether tv_nsec of struct timespec is 32-bit (arm-32) or 64-bit (arm-64, x86_64, ..).
586 */
587static int sizeof_tv_nsec() {
588#if __WORDSIZE == 64 \
589 || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) \
590 || __TIMESIZE == 32
591 // 32 bit or 64 bit: __syscall_slong_t
592 return sizeof( int64_t );
593#else
594 // 32 bit or 64 bit
595 return sizeof( long int );
596#endif
597}
598
599TEST_CASE( "struct timespec type validation Test 03.00", "[fraction][struct_timespec][time]" ) {
600 // testing fraction_timespec::to_timespec()
601 {
602 using time_t_type = decltype(timespec::tv_sec);
603 INFO_STR(" tv_sec: sizeof=" + std::to_string( sizeof( time_t_type ) ) + ", signed " + std::to_string( std::is_signed_v<time_t_type>) );
604 CHECK( sizeof_time_t() == sizeof( time_t_type ) );
605 CHECK( true == std::is_signed_v<time_t_type> );
606
607 using ns_type = decltype(timespec::tv_nsec);
608 INFO_STR(" tv_nsec: sizeof=" + std::to_string( sizeof( ns_type ) ) + ", signed " + std::to_string( std::is_signed_v<ns_type>) );
609 CHECK( sizeof_tv_nsec() == sizeof( ns_type ) );
610 CHECK( true == std::is_signed_v<ns_type> );
611 }
612}
613
614
615TEST_CASE( "Fraction Time Arithmetic Add Test 03.1", "[fraction][fraction_timespec][add]" ) {
616 const int64_t ns_per_sec = 1'000'000'000_i64;
617
618 // 12.4 + 12.4 = 24.8 w/ double overflow in tv_nsec
619 {
620 fraction_timespec a ( 10_i64, 2 * ns_per_sec + 400000000_i64 );
621 fraction_timespec b ( 10_i64, 2 * ns_per_sec + 400000000_i64 );
622 fraction_timespec exp_sum ( 24_i64, 800000000_i64 );
623 INFO_STR(" a " + a.to_string() );
624 INFO_STR(" b " + b.to_string() );
625 INFO_STR(" a+b " + (a+b).to_string() );
626 REQUIRE( ( a + b ) == exp_sum );
627 }
628 // 13.4 - 3.4 = 10.0 w/ double overflow in tv_nsec
629 {
630 fraction_timespec a ( 13_i64, 400000000_i64 );
631 fraction_timespec b ( 1_i64, 2 * ns_per_sec + 400000000_i64 );
632 fraction_timespec exp_sum ( 10_i64, 0_i64 );
633 INFO_STR(" a " + a.to_string() );
634 INFO_STR(" b " + b.to_string() );
635 INFO_STR(" a-b " + (a-b).to_string() );
636 REQUIRE( ( a - b ) == exp_sum );
637 }
638 // 12.0 - 1.9 = 10.1 w/ double overflow in tv_nsec
639 {
640 fraction_timespec a ( 12_i64, 0_i64 );
641 fraction_timespec b ( 3_i64, -2 * ns_per_sec + 900000000_i64 );
642 fraction_timespec exp_sum ( 10_i64, 100000000_i64 );
643 INFO_STR(" a " + a.to_string() );
644 INFO_STR(" b " + b.to_string() );
645 INFO_STR(" a-b " + (a-b).to_string() );
646 REQUIRE( ( a - b ) == exp_sum );
647 }
648 // 10.4 + 0.4 = 10.8
649 {
650 fraction_timespec a ( 10_i64, 400000000_i64 );
651 fraction_timespec b ( 0_i64, 400000000_i64 );
652 fraction_timespec exp_sum ( 10_i64, 800000000_i64 );
653 REQUIRE( ( a + b ) == exp_sum );
654 }
655 // 10.4 + 0.4 = 10.8
656 {
657 fraction_i64 a ( 10_s + 400_ms );
658 fraction_i64 b ( 0_s + 400_ms );
659 fraction_i64 exp_sum ( 10_s + 800_ms );
660 INFO_STR(" a " + a.to_string() );
661 INFO_STR(" b " + b.to_string() );
662 INFO_STR(" a+b " + (a+b).to_string() );
663 REQUIRE( ( a + b ) == exp_sum );
664 }
665 // 10.4 + 0.4 = 10.8
666 {
667 fraction_timespec a ( 10_s + 400_ms );
668 fraction_timespec b ( 0_s + 400_ms );
669 fraction_timespec exp_sum ( 10_s + 800_ms );
670 INFO_STR(" a " + a.to_string() );
671 INFO_STR(" b " + b.to_string() );
672 INFO_STR(" a+b " + (a+b).to_string() );
673 REQUIRE( ( a + b ) == exp_sum );
674 }
675 // 10.4 + 0.7 = 11.1
676 {
677 fraction_timespec a { 10_s + 400_ms };
678 fraction_timespec b { 0_s + 700_ms };
679 fraction_timespec exp_sum { 11_s + 100_ms };
680 INFO_STR(" a " + a.to_string() );
681 INFO_STR(" b " + b.to_string() );
682 INFO_STR(" a+b " + (a+b).to_string() );
683 REQUIRE( ( a + b ) == exp_sum );
684 }
685 // 10.4 + 2.7 (in denominator) = 13.1
686 {
687 fraction_timespec a { 10_s + 400_ms };
688 fraction_timespec b { 0_s + 2700_ms };
689 fraction_timespec exp_sum { 13_s + 100_ms };
690 INFO_STR(" a " + a.to_string() );
691 INFO_STR(" b " + b.to_string() );
692 INFO_STR(" a+b " + (a+b).to_string() );
693 REQUIRE( ( a + b ) == exp_sum );
694 }
695 // 10.4 + -0.3 = 10.1
696 {
697 fraction_timespec a { 10_s + 400_ms };
698 fraction_timespec b { 0_s + -300_ms };
699 fraction_timespec exp_sum { 10_s + 100_ms };
700 REQUIRE( ( a + b ) == exp_sum );
701 }
702 // 10.-3 + 0.4 = 10.1
703 {
704 fraction_timespec a { 10_s + -300_ms };
705 fraction_timespec b { 0_s + 400_ms };
706 fraction_timespec exp_sum { 10_s + 100_ms };
707 REQUIRE( ( a + b ) == exp_sum );
708 }
709 // 10.4 + -0.9 = 9.5
710 {
711 fraction_timespec a { 10_s + 400_ms };
712 fraction_timespec b { 0_s + -900_ms };
713 fraction_timespec exp_sum { 9_s + 500_ms };
714 INFO_STR(" a " + a.to_string() );
715 INFO_STR(" b " + b.to_string() );
716 INFO_STR(" a+b " + (a+b).to_string() );
717 REQUIRE( ( a + b ) == exp_sum );
718 }
719 // 10.4 + -2.7 = 7.7
720 {
721 fraction_timespec a { 10_s + 400_ms };
722 fraction_timespec b { 0_s + -2700_ms };
723 fraction_timespec exp_sum { 7_s + 700_ms };
724 INFO_STR(" a " + a.to_string() );
725 INFO_STR(" b " + b.to_string() );
726 INFO_STR(" a+b " + (a+b).to_string() );
727 REQUIRE( ( a + b ) == exp_sum );
728 }
729 // 10.-9 + 0.4 = 9.5
730 {
731 fraction_timespec a { 10_s + -900_ms };
732 fraction_timespec b { 0_s + 400_ms };
733 fraction_timespec exp_sum { 9_s + 500_ms };
734 INFO_STR(" a " + a.to_string() );
735 INFO_STR(" b " + b.to_string() );
736 INFO_STR(" a+b " + (a+b).to_string() );
737 REQUIRE( ( a + b ) == exp_sum );
738 }
739}
740
741TEST_CASE( "Fraction Time Arithmetic Sub Test 03.2", "[fraction][fraction_timespec][sub]" ) {
742 // normalize tests
743 // normalize: 1 s + 4*1000000000 ns = 5s
744 {
745 fraction_timespec a( 1, 4000000000_i64 );
746 INFO_STR(" a " + a.to_string() );
747 REQUIRE( a.tv_sec == 5 );
748 REQUIRE( a.tv_nsec == 0_i64 );
749 }
750 // normalize: -1 s - 4*1000000000 ns = -5s
751 {
752 fraction_timespec a( -1, -4000000000_i64 );
753 INFO_STR(" a " + a.to_string() );
754 REQUIRE( a.tv_sec == -5 );
755 REQUIRE( a.tv_nsec == 0_i64 );
756 }
757 // normalize: -1 s + 4*1000000000 ns = 3s
758 {
759 fraction_timespec a( -1, 4000000000_i64 );
760 INFO_STR(" a " + a.to_string() );
761 REQUIRE( a.tv_sec == 3 );
762 REQUIRE( a.tv_nsec == 0_i64 );
763 }
764 // normalize: 1 - 0.4 = 0.6
765 {
766 fraction_timespec a( 1, -400000000_i64 );
767 INFO_STR(" a " + a.to_string() );
768 REQUIRE( a.tv_sec == 0 );
769 REQUIRE( a.tv_nsec == 600000000_i64 );
770 }
771 // normalize: -1 + 0.4 = -0.6
772 {
773 fraction_timespec a( -1, +400000000_i64 );
774 INFO_STR(" a " + a.to_string() );
775 REQUIRE( a.tv_sec == 0 );
776 REQUIRE( a.tv_nsec == -600000000_i64 );
777 }
778 // 674.0 - 675.547 = -1.547
779 {
780 fraction_timespec a( 674, 0 );
781 fraction_timespec b( 675, 547000000_i64 );
782 fraction_timespec exp_sum( -1, -547000000_i64 );
783 INFO_STR(" a " + a.to_string() );
784 INFO_STR(" b " + b.to_string() );
785 INFO_STR(" exp " + exp_sum.to_string() );
786 INFO_STR(" a-b " + (a-b).to_string() );
787 REQUIRE( ( a - b ) == exp_sum );
788 }
789 // 674.0 - 675.547 = -1.547
790 {
791 fraction_timespec a { 674_s + 0_ms };
792 fraction_timespec b { 675_s + 547_ms };
793 fraction_timespec exp_sum { -1_s - 547_ms };
794 INFO_STR(" a " + a.to_string() );
795 INFO_STR(" b " + b.to_string() );
796 INFO_STR(" exp " + exp_sum.to_string() );
797 INFO_STR(" a-b " + (a-b).to_string() );
798 REQUIRE( ( a - b ) == exp_sum );
799 }
800 // 10.4 - 0.3 = 10.1
801 {
802 fraction_timespec a ( 10_i64, 400000000_i64 );
803 fraction_timespec b ( 0_i64, 300000000_i64 );
804 fraction_timespec exp_sum ( 10_i64, 100000000_i64 );
805 REQUIRE( ( a - b ) == exp_sum );
806 }
807 // 10.4 - 0.3 = 10.1
808 {
809 fraction_timespec a ( 10_s + 400_ms );
810 fraction_timespec b ( 0_s + 300_ms );
811 fraction_timespec exp_sum ( 10_s + 100_ms );
812 REQUIRE( ( a - b ) == exp_sum );
813 }
814 // 10.4 - 0.7 = 9.7
815 {
816 fraction_timespec a { 10_s + 400_ms };
817 fraction_timespec b { 0_s + 700_ms };
818 fraction_timespec exp_sum { 9_s + 700_ms };
819 INFO_STR(" a " + a.to_string() );
820 INFO_STR(" b " + b.to_string() );
821 INFO_STR(" a-b " + (a-b).to_string() );
822 REQUIRE( ( a - b ) == exp_sum );
823 }
824 // 10.4 - 2.7 (in denominator) = 7.7
825 {
826 fraction_timespec a { 10_s + 400_ms };
827 fraction_timespec b { 0_s + 2700_ms };
828 fraction_timespec exp_sum { 7_s + 700_ms };
829 INFO_STR(" a " + a.to_string() );
830 INFO_STR(" b " + b.to_string() );
831 INFO_STR(" a-b " + (a-b).to_string() );
832 REQUIRE( ( a - b ) == exp_sum );
833 }
834
835 // 10.4 - -0.3 = 10.7
836 {
837 fraction_timespec a { 10_s + 400_ms };
838 fraction_timespec b { 0_s + -300_ms };
839 fraction_timespec exp_sum { 10_s + 700_ms };
840 REQUIRE( ( a - b ) == exp_sum );
841 }
842 // 10.-2 - 0.4 = 9.4
843 {
844 fraction_timespec a { 10_s + -200_ms };
845 fraction_timespec b { 0_s + 400_ms };
846 fraction_timespec exp_sum { 9_s + 400_ms };
847 INFO_STR(" a " + a.to_string() );
848 INFO_STR(" b " + b.to_string() );
849 INFO_STR(" a-b " + (a-b).to_string() );
850 REQUIRE( ( a - b ) == exp_sum );
851 }
852 // 10.4 - -0.9 = 11.3
853 {
854 fraction_timespec a { 10_s + 400_ms };
855 fraction_timespec b { 0_s + -900_ms };
856 fraction_timespec exp_sum { 11_s + 300_ms };
857 INFO_STR(" a " + a.to_string() );
858 INFO_STR(" b " + b.to_string() );
859 INFO_STR(" a-b " + (a-b).to_string() );
860 REQUIRE( ( a - b ) == exp_sum );
861 }
862 // 10.-9 - 0.4 = 8.7
863 {
864 fraction_timespec a { 10_s + -900_ms };
865 fraction_timespec b { 0_s + 400_ms };
866 fraction_timespec exp_sum { 8_s + 700_ms };
867 INFO_STR(" a " + a.to_string() );
868 INFO_STR(" b " + b.to_string() );
869 INFO_STR(" a-b " + (a-b).to_string() );
870 REQUIRE( ( a - b ) == exp_sum );
871 }
872}
873
874TEST_CASE( "Fraction Time Measurement Test 04.01", "[fraction][fraction_timespec][time]" ) {
875 const int64_t sleep_ms = 50;
876 //
877 // Ideally we assume accuracy of at least 1/2 millisecond, hence the difference shall not be greater
878 // const fraction_i64 accuracy = fractions_i64::milli*2_i64/3_i64;
879 // However, running within virtual machines etc, we have to be more generous here: 60_ms
880 // Detected using KVM on GNU/Linux host for FreeBSD 13.1 target
881 const fraction_i64 accuracy = fractions_i64::milli*60_i64;
882 //
883 {
885 sleep_for( sleep_ms * 1_ms );
887 const fraction_timespec td_1 = t1 - t0;
888 const fraction_i64 td_2 = td_1.to_fraction_i64();
889 const fraction_i64 terr = abs( td_2 - fractions_i64::milli * sleep_ms );
890 INFO_STR( " Test-1: sleep_for() getMonotonicTime:");
891 INFO_STR( " - t0 " + t0.to_string() );
892 INFO_STR( " - t1 " + t1.to_string() );
893 INFO_STR( " - td_1 " + td_1.to_string() );
894 INFO_STR( " - td_2 " + td_2.to_string(true) + ", " + std::to_string( td_2.to_num_of(1_ms) ) + "ms, err " + terr.to_string(true) + " <?= " + accuracy.to_string(true) );
895 REQUIRE( t0.tv_sec >= 0 );
896 REQUIRE( t0.tv_nsec >= 0 );
897 REQUIRE( t1.tv_sec >= 0 );
898 REQUIRE( t1.tv_nsec >= 0 );
899 REQUIRE( td_1.tv_sec >= 0 );
900 REQUIRE( td_1.tv_nsec >= 0 );
901 REQUIRE( td_2 >= fractions_i64::zero );
902 // Check accuracy
903 REQUIRE( terr <= accuracy );
904 }
905 {
907 sleep_until( t0 + fraction_timespec( sleep_ms * 1_ms ) );
909 const fraction_timespec td_1 = t1 - t0;
910 const fraction_i64 td_2 = td_1.to_fraction_i64();
911 const fraction_i64 terr = abs( td_2 - fractions_i64::milli * sleep_ms );
912 INFO_STR( " Test-2: sleep_until() getMonotonicTime:");
913 INFO_STR( " - t0 " + t0.to_string() );
914 INFO_STR( " - t1 " + t1.to_string() );
915 INFO_STR( " - td_1 " + td_1.to_string() );
916 INFO_STR( " - td_2 " + td_2.to_string(true) + ", " + std::to_string( td_2.to_num_of(1_ms) ) + "ms, err " + terr.to_string(true) + " <?= " + accuracy.to_string(true) );
917 REQUIRE( t0.tv_sec >= 0 );
918 REQUIRE( t0.tv_nsec >= 0 );
919 REQUIRE( t1.tv_sec >= 0 );
920 REQUIRE( t1.tv_nsec >= 0 );
921 REQUIRE( td_1.tv_sec >= 0 );
922 REQUIRE( td_1.tv_nsec >= 0 );
923 REQUIRE( td_2 >= fractions_i64::zero );
924 // Check accuracy
925 REQUIRE( terr <= accuracy );
926 }
927}
#define INFO_STR(msg)
Definition: catch2_ext.hpp:75
#define REQUIRE_MSG(MSG,...)
Definition: catch2_ext.hpp:58
std::string to_string(const bool show_double=false) const noexcept
Returns a string representation of this fraction.
uint_type denom
Denominator, always positive.
int_type num
Numerator, carries the sign.
constexpr double to_double() const noexcept
Returns the converted fraction to lossy double.
constexpr int_type to_num_of(const fraction< int_type > &new_base, bool *overflow_ptr=nullptr) const noexcept
Converts this this fraction to a numerator for the given new base fraction.
std::chrono::duration< Rep, Period > to_duration(const std::chrono::duration< Rep, Period > &dur_ref, bool *overflow_ptr=nullptr) const noexcept
Convert this fraction into std::chrono::duration with given Rep and Period.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
bool to_fraction_i64(fraction_i64 &result, const std::string &value, const fraction_i64 &min_allowed, const fraction_i64 &max_allowed) noexcept
Stores the fraction_i64 value of the given string value in format <num>/<denom>, which may contain wh...
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
Definition: basic_types.cpp:52
fraction< int64_t > fraction_i64
fraction using int64_t as integral type
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 T gcd(T a, T b) noexcept
Returns the greatest common divisor (GCD) of the two given integer values following Euclid's algorith...
Definition: int_math.hpp:298
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
constexpr const jau::fraction_i64 tera(1 '000 '000 '000 '000l, 1lu)
tera is 10^12
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
constexpr const jau::fraction_i64 minutes(60l, 1lu)
minutes is 60/1
constexpr const jau::fraction_i64 nano(1l, 1 '000 '000 '000lu)
nano is 10^-9
constexpr const jau::fraction_i64 milli(1l, 1 '000lu)
milli is 10^-3
constexpr const jau::fraction_i64 seconds(1l, 1lu)
seconds is 1/1
constexpr const jau::fraction_i64 kilo(1 '000l, 1lu)
kilo is 10^3
constexpr const jau::fraction_i64 pico(1l, 1 '000 '000 '000 '000lu)
pico is 10^-12
constexpr const jau::fraction_i64 one(1l, 1lu)
one is 10^0 or 1/1
constexpr const jau::fraction_i64 days(86 '400l, 1lu)
days is 86400/1
constexpr const jau::fraction_i64 giga(1 '000 '000 '000l, 1lu)
giga is 10^9
constexpr const jau::fraction_i64 micro(1l, 1 '000 '000lu)
micro is 10^-6
constexpr const jau::fraction_i64 mega(1 '000 '000l, 1lu)
mega is 10^6
constexpr const jau::fraction_i64 hours(3 '600l, 1lu)
hours is 3660/1
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
bool sleep_until(const fraction_timespec &absolute_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_until causes the current thread to block until the specific time is reached.
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
int64_t tv_nsec
Nanoseconds component with its absolute value in range [0..1'000'000'000[ or [0..1'000'000'000),...
int64_t tv_sec
Seconds component, with its absolute value in range [0..inf[ or [0..inf), sharing same sign with tv_n...
std::string to_string() const noexcept
Return simple string representation in seconds and nanoseconds.
Definition: basic_types.cpp:77
constexpr fraction_i64 to_fraction_i64() const noexcept
Returns the sum of both components.
static void test_comp_fract(const fraction< int_type > &a, const fraction< int_type > &b, const fraction< int_type > &exp_max, const fraction< int_type > &exp_min, const fraction< int_type > &exp_sum, const fraction< int_type > &exp_diff, const fraction< int_type > &exp_mul, const fraction< int_type > &exp_div)
static void test_to_num_of(const int64_t exp, const fraction< int64_t > &v, const fraction< int64_t > &new_base, bool exp_overflow=false) noexcept
static int sizeof_time_t()
Resembling the GNU/Linux bits/types.h, documenting whether time_t is 32-bit (arm-32) or 64-bit (arm-6...
static void test_gcd_fract_pm(const int_type n, const std::make_unsigned_t< int_type > d, const int_type exp_gcd, const int_type exp_num, const std::make_unsigned_t< int_type > exp_denom)
static void test_gcd_fract(const int_type n, const std::make_unsigned_t< int_type > d, const int_type exp_gcd, const int_type exp_num, const std::make_unsigned_t< int_type > exp_denom)
TEST_CASE("Fraction Types Test 00", "[fraction][type]")
static int sizeof_tv_nsec()
Resembling the GNU/Linux bits/types.h, documenting whether tv_nsec of struct timespec is 32-bit (arm-...
static void test_duration(const fraction< int_type > &a, const std::chrono::duration< Rep, Period > &dur_ref, const Rep exp_count)