jaulib v1.3.0
Jau Support Library (C++, Java, ..)
test_math_mat4f_02_mul.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 <cinttypes>
26#include <cstring>
27
29
30#include <jau/math/mat4f.hpp>
31
32using namespace jau;
33using namespace jau::math;
34
35static const float m1_0[] = { 1, 3, 4, 0,
36 6, 7, 8, 5,
37 98, 7, 6, 9,
38 54, 3, 2, 5 };
39static const Mat4f m1(m1_0);
40
41static const float m2_0[] = { 1, 6, 98, 54,
42 3, 7, 7, 3,
43 4, 8, 6, 2,
44 0, 5, 9, 5 };
45static const Mat4f m2(m2_0);
46
47TEST_CASE( "Test 05 Perf01", "[mat4f][linear_algebra][math]" ) {
48 Mat4f res_m;
49
50 const size_t warmups = is_debug_enabled() ? 100_u64 : 1000_u64;
51 const size_t loops = is_debug_enabled() ? 1_u64*1000000_u64 : 300_u64*1000000_u64;
54
55 const uint64_t tI5Max = 1000; // 1s
56 size_t loops5a = 0;
58 size_t loops5b = 0;
60
61 // avoid optimizing out unused computation results by simply adding up determinat
62 double dr = 1;
63
64 //
65 // Mat4f
66 //
67
68 // warm-up
69 for(size_t i=0; i<warmups; i++) {
70 res_m = m1 * m2;
71 dr += res_m.determinant();
72 res_m = m2 * m1;
73 dr += res_m.determinant();
74 }
75
77 for(size_t i=0; i<loops; i++) {
78 res_m = m1 * m2;
79 dr += res_m.determinant();
80 res_m = m2 * m1;
81 dr += res_m.determinant();
82 }
83 tI4a = (getMonotonicTime() - t_0).to_fraction_i64();
84 REQUIRE( dr > 0 );
85
86 // warm-up
87 for(size_t i=0; i<warmups; i++) {
88 res_m.load(m1);
89 res_m.mul(m2);
90 dr += res_m.determinant();
91 res_m.load(m2);
92 res_m.mul(m1);
93 dr += res_m.determinant();
94 }
95
97 for(size_t i=0; i<loops; i++) {
98 res_m.load(m1);
99 res_m.mul(m2);
100 dr += res_m.determinant();
101 res_m.load(m2);
102 res_m.mul(m1);
103 dr += res_m.determinant();
104 }
105 tI4b = (getMonotonicTime() - t_0).to_fraction_i64();
106 REQUIRE( dr > 0 );
107
108 if( catch_perf_analysis ) {
109 tI5a = fractions_i64::zero;
110 t_0 = jau::getMonotonicTime();
111 uint64_t t_5 = jau::getCurrentMilliseconds();
112 uint64_t td_5=0;
113 while( td_5 < tI5Max ) {
114 res_m = m1 * m2;
115 dr += res_m.determinant();
116 res_m = m2 * m1;
117 dr += res_m.determinant();
118 ++loops5a;
119 // if( 0 == loops5a % 1000000 ) {
120 td_5 = jau::getCurrentMilliseconds() - t_5;
121 // }
122 }
123 tI5a = (getMonotonicTime() - t_0).to_fraction_i64();
124 REQUIRE( dr > 0 );
125
126 tI5b = fractions_i64::zero;
127 t_0 = jau::getMonotonicTime();
129 td_5=0;
130 while( td_5 < tI5Max ) {
131 res_m.load(m1);
132 res_m.mul(m2);
133 dr += res_m.determinant();
134 res_m.load(m2);
135 res_m.mul(m1);
136 dr += res_m.determinant();
137 ++loops5b;
138 // if( 0 == loops5b % 1000000 ) {
139 td_5 = jau::getCurrentMilliseconds() - t_5;
140 // }
141 }
142 tI5b = (getMonotonicTime() - t_0).to_fraction_i64();
143 REQUIRE( dr > 0 );
144 }
145
146 printf("Checkmark %f\n", dr);
147 printf("Summary loops %6zu: I4a %6s ms total (%s us), %f ns/mul, I4a / I4b %f%%\n", loops,
148 jau::to_decstring(tI4a.to_ms()).c_str(), jau::to_decstring(tI4a.to_us()).c_str(),
149 (double)tI4a.to_ns()/2.0/(double)loops, tI4a.to_double()/tI4b.to_double()*100.0);
150 printf("Summary loops %6zu: I4b %6s ms total (%s us), %f ns/mul, I4b / I4a %f%%\n", loops,
151 jau::to_decstring(tI4b.to_ms()).c_str(), jau::to_decstring(tI4b.to_us()).c_str(),
152 (double)tI4b.to_ns()/2.0/(double)loops, tI4b.to_double()/tI4a.to_double()*100.0);
153
154 if( catch_perf_analysis ) {
155 printf("Summary loops %6zu: I5a %6s ms total, %f ns/mul, I5a / I5b %f%%\n", loops5a,
156 jau::to_decstring(tI5a.to_ms()).c_str(),
157 (double)tI5a.to_ns()/2.0/(double)loops5a, tI5a.to_double()/tI5b.to_double()*100.0);
158 printf("Summary loops %6zu: I5b %6s ms total, %f ns/mul, I5b / I5a %f%%\n", loops5b,
159 jau::to_decstring(tI5b.to_ms()).c_str(),
160 (double)tI5b.to_ns()/2.0/(double)loops5b, tI5b.to_double()/tI5a.to_double()*100.0);
161 }
162}
bool catch_perf_analysis
Run w/ command-line arg '–perf_analysis'.
constexpr double to_double() const noexcept
Returns the converted fraction to lossy double.
constexpr int_type to_ms() const noexcept
Convenient shortcut to to_num_of(1_ms)
constexpr int_type to_us() const noexcept
Convenient shortcut to to_num_of(1_us)
constexpr int_type to_ns() const noexcept
Convenient shortcut to to_num_of(1_ns)
Basic 4x4 value_type matrix implementation using fields for intensive use-cases (host operations).
Definition: mat4f.hpp:112
value_type determinant() const noexcept
Returns the determinant of this matrix.
Definition: mat4f.hpp:438
constexpr Matrix4 & mul(const Matrix4 &b) noexcept
Multiply matrix: [this] = [this] x [b].
Definition: mat4f.hpp:717
constexpr Matrix4 & load(const_iterator src) noexcept
Load the values of the given matrix src to this matrix w/o boundary check.
Definition: mat4f.hpp:264
consteval_cxx20 bool is_debug_enabled() noexcept
Returns true if compiled with debug information and w/o optimization, i.e.
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
std::string to_decstring(const value_type &v, const char separator=',', const nsize_t width=0) noexcept
Produce a decimal string representation of an integral integer value.
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:64
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
static const Mat4f m1(m1_0)
static const float m2_0[]
TEST_CASE("Test 05 Perf01", "[mat4f][linear_algebra][math]")
static const float m1_0[]
static const Mat4f m2(m2_0)
static int loops
int printf(const char *format,...)
Operating Systems predefined macros.