Line data Source code
1 : /******************************************************************************
2 : * Project: GDAL Core
3 : * Purpose: Test performance of gdal_minmax_element.hpp
4 : * Author: Even Rouault, <even dot rouault at spatialys.com>
5 : *
6 : ******************************************************************************
7 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
8 : *
9 : * SPDX-License-Identifier: MIT
10 : ****************************************************************************/
11 :
12 : #include "gdal_minmax_element.hpp"
13 :
14 : #include <chrono>
15 : #include <random>
16 :
17 14 : template <class T> void randomFill(T *v, size_t size, bool withNaN = true)
18 : {
19 28 : std::random_device rd;
20 14 : std::mt19937 gen{rd()};
21 14 : std::normal_distribution<> dist{
22 : cpl::NumericLimits<T>::is_signed ? -63 : 127, 30};
23 140000000 : for (size_t i = 0; i < size; i++)
24 : {
25 140000000 : v[i] = static_cast<T>(dist(gen));
26 : if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double> ||
27 : std::is_same_v<T, GFloat16>)
28 : {
29 60000000 : if (withNaN && (i == 0 || (i > 10 && ((i + 1) % 1024) <= 4)))
30 146478 : v[i] = cpl::NumericLimits<T>::quiet_NaN();
31 : }
32 : }
33 14 : }
34 :
35 : constexpr size_t SIZE = 10 * 1000 * 1000 + 1;
36 : constexpr int N_ITERS = 1;
37 :
38 56 : template <class T> inline void ASSERT_EQ(T v_optim, T v_ref)
39 : {
40 56 : if (v_optim != v_ref)
41 : {
42 0 : fprintf(stderr, "Optim value != ref value\n");
43 0 : exit(1);
44 : }
45 56 : }
46 :
47 : template <class T>
48 : #if defined(__GNUC__)
49 : __attribute__((noinline))
50 : #endif
51 : static void
52 8 : benchIntegers(GDALDataType eDT, T noData)
53 : {
54 16 : std::vector<T> x;
55 8 : x.resize(SIZE);
56 8 : randomFill(x.data(), x.size());
57 : T v_optim, v_ref;
58 : {
59 8 : auto start = std::chrono::steady_clock::now();
60 8 : int idx = 0;
61 16 : for (int i = 0; i < N_ITERS; ++i)
62 : {
63 8 : idx += static_cast<int>(
64 8 : gdal::min_element(x.data(), x.size(), eDT, false, 0));
65 : }
66 8 : idx /= N_ITERS;
67 8 : printf("min at idx %d (optimized), val=%s\n", idx,
68 8 : std::to_string(x[idx]).c_str());
69 8 : auto end = std::chrono::steady_clock::now();
70 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
71 8 : v_optim = x[idx];
72 : }
73 : {
74 8 : auto start = std::chrono::steady_clock::now();
75 8 : int idx = 0;
76 16 : for (int i = 0; i < N_ITERS; ++i)
77 : {
78 8 : idx += static_cast<int>(
79 8 : std::distance(x.begin(), std::min_element(x.begin(), x.end())));
80 : }
81 8 : idx /= N_ITERS;
82 8 : printf("min at idx %d (using std::min_element), val=%s\n", idx,
83 8 : std::to_string(x[idx]).c_str());
84 8 : auto end = std::chrono::steady_clock::now();
85 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
86 8 : v_ref = x[idx];
87 : }
88 8 : ASSERT_EQ(v_optim, v_ref);
89 :
90 : {
91 8 : auto start = std::chrono::steady_clock::now();
92 8 : int idx = 0;
93 16 : for (int i = 0; i < N_ITERS; ++i)
94 : {
95 8 : idx += static_cast<int>(
96 8 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
97 : }
98 8 : idx /= N_ITERS;
99 8 : printf("min at idx %d (nodata case, optimized), val=%s\n", idx,
100 8 : std::to_string(x[idx]).c_str());
101 8 : auto end = std::chrono::steady_clock::now();
102 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
103 8 : v_optim = x[idx];
104 : }
105 : {
106 8 : auto start = std::chrono::steady_clock::now();
107 8 : int idx = 0;
108 16 : for (int i = 0; i < N_ITERS; ++i)
109 : {
110 8 : idx += static_cast<int>(std::distance(
111 : x.begin(), std::min_element(x.begin(), x.end(),
112 160000000 : [noData](T a, T b) {
113 159883000 : return b == noData ? true
114 79882800 : : a == noData ? false
115 80000000 : : a < b;
116 : })));
117 : }
118 8 : idx /= N_ITERS;
119 8 : printf("min at idx %d (nodata case, using std::min_element with "
120 : "nodata aware comparison), val=%s\n",
121 8 : idx, std::to_string(x[idx]).c_str());
122 8 : auto end = std::chrono::steady_clock::now();
123 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
124 8 : v_ref = x[idx];
125 : }
126 8 : ASSERT_EQ(v_optim, v_ref);
127 :
128 : {
129 8 : auto start = std::chrono::steady_clock::now();
130 8 : int idx = 0;
131 16 : for (int i = 0; i < N_ITERS; ++i)
132 : {
133 8 : idx += static_cast<int>(
134 8 : gdal::max_element(x.data(), x.size(), eDT, false, 0));
135 : }
136 8 : idx /= N_ITERS;
137 8 : printf("max at idx %d (optimized), val=%s\n", idx,
138 8 : std::to_string(x[idx]).c_str());
139 8 : auto end = std::chrono::steady_clock::now();
140 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
141 8 : v_optim = x[idx];
142 : }
143 : {
144 8 : auto start = std::chrono::steady_clock::now();
145 8 : int idx = 0;
146 16 : for (int i = 0; i < N_ITERS; ++i)
147 : {
148 8 : idx += static_cast<int>(
149 8 : std::distance(x.begin(), std::max_element(x.begin(), x.end())));
150 : }
151 8 : idx /= N_ITERS;
152 8 : printf("max at idx %d (using std::max_element), val=%s\n", idx,
153 8 : std::to_string(x[idx]).c_str());
154 8 : auto end = std::chrono::steady_clock::now();
155 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
156 8 : v_ref = x[idx];
157 : }
158 8 : ASSERT_EQ(v_optim, v_ref);
159 :
160 : {
161 8 : auto start = std::chrono::steady_clock::now();
162 8 : int idx = 0;
163 16 : for (int i = 0; i < N_ITERS; ++i)
164 : {
165 8 : idx += static_cast<int>(
166 8 : gdal::max_element(x.data(), x.size(), eDT, true, noData));
167 : }
168 8 : idx /= N_ITERS;
169 8 : printf("max at idx %d (nodata case, optimized), val=%s\n", idx,
170 8 : std::to_string(x[idx]).c_str());
171 8 : auto end = std::chrono::steady_clock::now();
172 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
173 8 : v_optim = x[idx];
174 : }
175 : {
176 8 : auto start = std::chrono::steady_clock::now();
177 8 : int idx = 0;
178 16 : for (int i = 0; i < N_ITERS; ++i)
179 : {
180 8 : idx += static_cast<int>(std::distance(
181 : x.begin(), std::max_element(x.begin(), x.end(),
182 160000000 : [noData](T a, T b) {
183 159883000 : return a == noData ? true
184 79882800 : : b == noData ? false
185 80000000 : : a < b;
186 : })));
187 : }
188 8 : idx /= N_ITERS;
189 8 : printf("max at idx %d (nodata case, using std::max_element with "
190 : "nodata aware comparison), val=%s\n",
191 8 : idx, std::to_string(x[idx]).c_str());
192 8 : auto end = std::chrono::steady_clock::now();
193 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
194 8 : v_ref = x[idx];
195 : }
196 8 : ASSERT_EQ(v_optim, v_ref);
197 8 : }
198 :
199 : template <class T>
200 : #if defined(__GNUC__)
201 : __attribute__((noinline))
202 : #endif
203 : static void
204 3 : benchFloatingPointsWithNaN(GDALDataType eDT, T noData)
205 : {
206 6 : std::vector<T> x;
207 3 : x.resize(SIZE);
208 3 : randomFill(x.data(), x.size());
209 : T v_optim, v_ref;
210 :
211 : {
212 3 : auto start = std::chrono::steady_clock::now();
213 3 : int idx = 0;
214 6 : for (int i = 0; i < N_ITERS; ++i)
215 : {
216 3 : idx += static_cast<int>(
217 3 : gdal::min_element(x.data(), x.size(), eDT, false, 0));
218 : }
219 3 : idx /= N_ITERS;
220 3 : printf("min at idx %d (optimized), val = %g\n", idx,
221 3 : static_cast<double>(x[idx]));
222 3 : auto end = std::chrono::steady_clock::now();
223 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
224 3 : v_optim = x[idx];
225 : }
226 : {
227 3 : auto start = std::chrono::steady_clock::now();
228 3 : int idx = 0;
229 6 : for (int i = 0; i < N_ITERS; ++i)
230 : {
231 3 : idx += static_cast<int>(std::distance(
232 : x.begin(), std::min_element(x.begin(), x.end(),
233 30000000 : [](T a, T b) {
234 79902300 : return CPLIsNan(b) ? true
235 49902300 : : CPLIsNan(a) ? false
236 39951200 : : a < b;
237 : })));
238 : }
239 3 : idx /= N_ITERS;
240 3 : printf("min at idx %d (using std::min_element with NaN aware "
241 : "comparison), val = %g\n",
242 3 : idx, static_cast<double>(x[idx]));
243 3 : auto end = std::chrono::steady_clock::now();
244 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
245 3 : v_ref = x[idx];
246 : }
247 3 : ASSERT_EQ(v_optim, v_ref);
248 :
249 : {
250 3 : auto start = std::chrono::steady_clock::now();
251 3 : int idx = 0;
252 6 : for (int i = 0; i < N_ITERS; ++i)
253 : {
254 3 : idx += static_cast<int>(
255 3 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
256 : }
257 3 : idx /= N_ITERS;
258 3 : printf("min at idx %d (nodata case, optimized), val = %g\n", idx,
259 3 : static_cast<double>(x[idx]));
260 3 : auto end = std::chrono::steady_clock::now();
261 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
262 3 : v_optim = x[idx];
263 : }
264 : {
265 3 : auto start = std::chrono::steady_clock::now();
266 3 : int idx = 0;
267 6 : for (int i = 0; i < N_ITERS; ++i)
268 : {
269 3 : idx += static_cast<int>(std::distance(
270 : x.begin(), std::min_element(x.begin(), x.end(),
271 69804600 : [noData](T a, T b)
272 : {
273 79902300 : return CPLIsNan(b) ? true
274 59853500 : : CPLIsNan(a) ? false
275 39804700 : : b == noData ? true
276 29853500 : : a == noData ? false
277 39951200 : : a < b;
278 : })));
279 : }
280 3 : idx /= N_ITERS;
281 3 : printf("min at idx %d (nodata case, using std::min_element with "
282 : "nodata aware and NaN aware comparison), val = %g\n",
283 3 : idx, static_cast<double>(x[idx]));
284 3 : auto end = std::chrono::steady_clock::now();
285 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
286 3 : v_ref = x[idx];
287 : }
288 3 : ASSERT_EQ(v_optim, v_ref);
289 :
290 : {
291 3 : auto start = std::chrono::steady_clock::now();
292 3 : int idx = 0;
293 6 : for (int i = 0; i < N_ITERS; ++i)
294 : {
295 3 : idx += static_cast<int>(
296 3 : gdal::max_element(x.data(), x.size(), eDT, false, 0));
297 : }
298 3 : idx /= N_ITERS;
299 3 : printf("max at idx %d (optimized), val = %g\n", idx,
300 3 : static_cast<double>(x[idx]));
301 3 : auto end = std::chrono::steady_clock::now();
302 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
303 3 : v_optim = x[idx];
304 : }
305 : {
306 3 : auto start = std::chrono::steady_clock::now();
307 3 : int idx = 0;
308 6 : for (int i = 0; i < N_ITERS; ++i)
309 : {
310 3 : idx += static_cast<int>(std::distance(
311 : x.begin(), std::max_element(x.begin(), x.end(),
312 30000000 : [](T a, T b) {
313 79902300 : return CPLIsNan(a) ? true
314 49902300 : : CPLIsNan(b) ? false
315 39951200 : : a < b;
316 : })));
317 : }
318 3 : idx /= N_ITERS;
319 3 : printf("max at idx %d (using std::max_element with NaN aware "
320 : "comparison), val = %g\n",
321 3 : idx, static_cast<double>(x[idx]));
322 3 : auto end = std::chrono::steady_clock::now();
323 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
324 3 : v_ref = x[idx];
325 : }
326 3 : ASSERT_EQ(v_optim, v_ref);
327 :
328 : {
329 3 : auto start = std::chrono::steady_clock::now();
330 3 : int idx = 0;
331 6 : for (int i = 0; i < N_ITERS; ++i)
332 : {
333 3 : idx += static_cast<int>(
334 3 : gdal::max_element(x.data(), x.size(), eDT, true, noData));
335 : }
336 3 : idx /= N_ITERS;
337 3 : printf("max at idx %d (nodata case, optimized), val = %g\n", idx,
338 3 : static_cast<double>(x[idx]));
339 3 : auto end = std::chrono::steady_clock::now();
340 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
341 3 : v_optim = x[idx];
342 : }
343 : {
344 3 : auto start = std::chrono::steady_clock::now();
345 3 : int idx = 0;
346 6 : for (int i = 0; i < N_ITERS; ++i)
347 : {
348 3 : idx += static_cast<int>(std::distance(
349 : x.begin(), std::max_element(x.begin(), x.end(),
350 69804600 : [noData](T a, T b)
351 : {
352 79902300 : return CPLIsNan(a) ? true
353 59853500 : : CPLIsNan(b) ? false
354 39804700 : : a == noData ? true
355 29853500 : : b == noData ? false
356 39951200 : : a < b;
357 : })));
358 : }
359 3 : idx /= N_ITERS;
360 3 : printf("max at idx %d (nodata case, using std::max_element with "
361 : "nodata aware and NaN aware comparison), val = %g\n",
362 3 : idx, static_cast<double>(x[idx]));
363 3 : auto end = std::chrono::steady_clock::now();
364 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
365 3 : v_ref = x[idx];
366 : }
367 3 : ASSERT_EQ(v_optim, v_ref);
368 3 : }
369 :
370 : template <class T>
371 : #if defined(__GNUC__)
372 : __attribute__((noinline))
373 : #endif
374 : static void
375 3 : benchFloatingPointsWithoutNaN(GDALDataType eDT, T noData)
376 : {
377 6 : std::vector<T> x;
378 3 : x.resize(SIZE);
379 3 : randomFill(x.data(), x.size(), false);
380 : T v_optim, v_ref;
381 :
382 : {
383 3 : auto start = std::chrono::steady_clock::now();
384 3 : int idx = 0;
385 6 : for (int i = 0; i < N_ITERS; ++i)
386 : {
387 3 : idx += static_cast<int>(
388 3 : gdal::min_element(x.data(), x.size(), eDT, false, 0));
389 : }
390 3 : idx /= N_ITERS;
391 3 : printf("min at idx %d (optimized), val = %g\n", idx,
392 3 : static_cast<double>(x[idx]));
393 3 : auto end = std::chrono::steady_clock::now();
394 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
395 3 : v_optim = x[idx];
396 : }
397 : {
398 3 : auto start = std::chrono::steady_clock::now();
399 3 : int idx = 0;
400 6 : for (int i = 0; i < N_ITERS; ++i)
401 : {
402 3 : idx += static_cast<int>(
403 3 : std::distance(x.begin(), std::min_element(x.begin(), x.end())));
404 : }
405 3 : idx /= N_ITERS;
406 3 : printf("min at idx %d (using std::min_element), val = %g\n", idx,
407 3 : static_cast<double>(x[idx]));
408 3 : auto end = std::chrono::steady_clock::now();
409 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
410 3 : v_ref = x[idx];
411 : }
412 3 : ASSERT_EQ(v_optim, v_ref);
413 :
414 : {
415 3 : auto start = std::chrono::steady_clock::now();
416 3 : int idx = 0;
417 6 : for (int i = 0; i < N_ITERS; ++i)
418 : {
419 3 : idx += static_cast<int>(
420 3 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
421 : }
422 3 : idx /= N_ITERS;
423 3 : printf("min at idx %d (nodata case, optimized), val = %g\n", idx,
424 3 : static_cast<double>(x[idx]));
425 3 : auto end = std::chrono::steady_clock::now();
426 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
427 3 : v_optim = x[idx];
428 : }
429 : {
430 3 : auto start = std::chrono::steady_clock::now();
431 3 : int idx = 0;
432 6 : for (int i = 0; i < N_ITERS; ++i)
433 : {
434 3 : idx += static_cast<int>(std::distance(
435 : x.begin(), std::min_element(x.begin(), x.end(),
436 50000000 : [noData](T a, T b) {
437 60000000 : return b == noData ? true
438 30000000 : : a == noData ? false
439 40000000 : : a < b;
440 : })));
441 : }
442 3 : idx /= N_ITERS;
443 3 : printf("min at idx %d (nodata case, using std::min_element with "
444 : "nodata aware comparison), val = %g\n",
445 3 : idx, static_cast<double>(x[idx]));
446 3 : auto end = std::chrono::steady_clock::now();
447 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
448 3 : v_ref = x[idx];
449 : }
450 3 : ASSERT_EQ(v_optim, v_ref);
451 :
452 : {
453 3 : auto start = std::chrono::steady_clock::now();
454 3 : int idx = 0;
455 6 : for (int i = 0; i < N_ITERS; ++i)
456 : {
457 3 : idx += static_cast<int>(
458 3 : gdal::max_element(x.data(), x.size(), eDT, false, 0));
459 : }
460 3 : idx /= N_ITERS;
461 3 : printf("max at idx %d (optimized), val = %g\n", idx,
462 3 : static_cast<double>(x[idx]));
463 3 : auto end = std::chrono::steady_clock::now();
464 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
465 3 : v_optim = x[idx];
466 : }
467 : {
468 3 : auto start = std::chrono::steady_clock::now();
469 3 : int idx = 0;
470 6 : for (int i = 0; i < N_ITERS; ++i)
471 : {
472 3 : idx += static_cast<int>(
473 3 : std::distance(x.begin(), std::max_element(x.begin(), x.end())));
474 : }
475 3 : idx /= N_ITERS;
476 3 : printf("max at idx %d (using std::max_element), val = %g\n", idx,
477 3 : static_cast<double>(x[idx]));
478 3 : auto end = std::chrono::steady_clock::now();
479 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
480 3 : v_ref = x[idx];
481 : }
482 3 : ASSERT_EQ(v_optim, v_ref);
483 :
484 : {
485 3 : auto start = std::chrono::steady_clock::now();
486 3 : int idx = 0;
487 6 : for (int i = 0; i < N_ITERS; ++i)
488 : {
489 3 : idx += static_cast<int>(
490 3 : gdal::max_element(x.data(), x.size(), eDT, true, noData));
491 : }
492 3 : idx /= N_ITERS;
493 3 : printf("max at idx %d (nodata case, optimized), val = %g\n", idx,
494 3 : static_cast<double>(x[idx]));
495 3 : auto end = std::chrono::steady_clock::now();
496 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
497 3 : v_optim = x[idx];
498 : }
499 : {
500 3 : auto start = std::chrono::steady_clock::now();
501 3 : int idx = 0;
502 6 : for (int i = 0; i < N_ITERS; ++i)
503 : {
504 3 : idx += static_cast<int>(std::distance(
505 : x.begin(), std::max_element(x.begin(), x.end(),
506 50000000 : [noData](T a, T b) {
507 60000000 : return a == noData ? true
508 30000000 : : b == noData ? false
509 40000000 : : a < b;
510 : })));
511 : }
512 3 : idx /= N_ITERS;
513 3 : printf("max at idx %d (nodata case, using std::max_element with "
514 : "nodata aware comparison), val = %g\n",
515 3 : idx, static_cast<double>(x[idx]));
516 3 : auto end = std::chrono::steady_clock::now();
517 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
518 3 : v_ref = x[idx];
519 : }
520 3 : ASSERT_EQ(v_optim, v_ref);
521 3 : }
522 :
523 1 : int main(int /* argc */, char * /* argv */[])
524 : {
525 : {
526 : using T = uint8_t;
527 1 : constexpr GDALDataType eDT = GDT_Byte;
528 1 : printf("uint8:\n");
529 1 : benchIntegers<T>(eDT, 0);
530 : }
531 1 : printf("--------------------\n");
532 : {
533 : using T = int8_t;
534 1 : constexpr GDALDataType eDT = GDT_Int8;
535 1 : printf("int8:\n");
536 1 : benchIntegers<T>(eDT, 0);
537 : }
538 1 : printf("--------------------\n");
539 : {
540 : using T = uint16_t;
541 1 : constexpr GDALDataType eDT = GDT_UInt16;
542 1 : printf("uint16:\n");
543 1 : benchIntegers<T>(eDT, 0);
544 : }
545 1 : printf("--------------------\n");
546 : {
547 : using T = int16_t;
548 1 : constexpr GDALDataType eDT = GDT_Int16;
549 1 : printf("int16:\n");
550 1 : benchIntegers<T>(eDT, 0);
551 : }
552 1 : printf("--------------------\n");
553 : {
554 : using T = uint32_t;
555 1 : constexpr GDALDataType eDT = GDT_UInt32;
556 1 : printf("uint32:\n");
557 1 : benchIntegers<T>(eDT, 0);
558 : }
559 1 : printf("--------------------\n");
560 : {
561 : using T = int32_t;
562 1 : constexpr GDALDataType eDT = GDT_Int32;
563 1 : printf("int32:\n");
564 1 : benchIntegers<T>(eDT, 0);
565 : }
566 1 : printf("--------------------\n");
567 : {
568 : using T = uint64_t;
569 1 : constexpr GDALDataType eDT = GDT_UInt64;
570 1 : printf("uint64:\n");
571 1 : benchIntegers<T>(eDT, 0);
572 : }
573 1 : printf("--------------------\n");
574 : {
575 : using T = int64_t;
576 1 : constexpr GDALDataType eDT = GDT_Int64;
577 1 : printf("int64:\n");
578 1 : benchIntegers<T>(eDT, 0);
579 : }
580 1 : printf("--------------------\n");
581 : {
582 : using T = GFloat16;
583 1 : constexpr GDALDataType eDT = GDT_Float16;
584 1 : printf("float16 (*with* NaN):\n");
585 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
586 : }
587 1 : printf("--------------------\n");
588 : {
589 : using T = GFloat16;
590 1 : constexpr GDALDataType eDT = GDT_Float16;
591 1 : printf("float16 (without NaN):\n");
592 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
593 : }
594 1 : printf("--------------------\n");
595 : {
596 : using T = float;
597 1 : constexpr GDALDataType eDT = GDT_Float32;
598 1 : printf("float (*with* NaN):\n");
599 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
600 : }
601 1 : printf("--------------------\n");
602 : {
603 : using T = float;
604 1 : constexpr GDALDataType eDT = GDT_Float32;
605 1 : printf("float (without NaN):\n");
606 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
607 : }
608 1 : printf("--------------------\n");
609 : {
610 : using T = double;
611 1 : constexpr GDALDataType eDT = GDT_Float64;
612 1 : printf("double (*with* NaN):\n");
613 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
614 : }
615 1 : printf("--------------------\n");
616 : {
617 : using T = double;
618 1 : constexpr GDALDataType eDT = GDT_Float64;
619 1 : printf("double (without NaN):\n");
620 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
621 : }
622 1 : return 0;
623 : }
|