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 8 : static void benchIntegers(GDALDataType eDT, T noData)
52 : {
53 16 : std::vector<T> x;
54 8 : x.resize(SIZE);
55 8 : randomFill(x.data(), x.size());
56 : T v_optim, v_ref;
57 : {
58 8 : auto start = std::chrono::steady_clock::now();
59 8 : int idx = 0;
60 16 : for (int i = 0; i < N_ITERS; ++i)
61 : {
62 8 : idx += static_cast<int>(
63 8 : gdal::min_element(x.data(), x.size(), eDT, false, 0));
64 : }
65 8 : idx /= N_ITERS;
66 8 : printf("min at idx %d (optimized), val=%s\n", idx,
67 8 : std::to_string(x[idx]).c_str());
68 8 : auto end = std::chrono::steady_clock::now();
69 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
70 8 : v_optim = x[idx];
71 : }
72 : {
73 8 : auto start = std::chrono::steady_clock::now();
74 8 : int idx = 0;
75 16 : for (int i = 0; i < N_ITERS; ++i)
76 : {
77 8 : idx += static_cast<int>(
78 8 : std::distance(x.begin(), std::min_element(x.begin(), x.end())));
79 : }
80 8 : idx /= N_ITERS;
81 8 : printf("min at idx %d (using std::min_element), val=%s\n", idx,
82 8 : std::to_string(x[idx]).c_str());
83 8 : auto end = std::chrono::steady_clock::now();
84 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
85 8 : v_ref = x[idx];
86 : }
87 8 : ASSERT_EQ(v_optim, v_ref);
88 :
89 : {
90 8 : auto start = std::chrono::steady_clock::now();
91 8 : int idx = 0;
92 16 : for (int i = 0; i < N_ITERS; ++i)
93 : {
94 8 : idx += static_cast<int>(
95 8 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
96 : }
97 8 : idx /= N_ITERS;
98 8 : printf("min at idx %d (nodata case, optimized), val=%s\n", idx,
99 8 : std::to_string(x[idx]).c_str());
100 8 : auto end = std::chrono::steady_clock::now();
101 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
102 8 : v_optim = x[idx];
103 : }
104 : {
105 8 : auto start = std::chrono::steady_clock::now();
106 8 : int idx = 0;
107 16 : for (int i = 0; i < N_ITERS; ++i)
108 : {
109 8 : idx += static_cast<int>(std::distance(
110 : x.begin(), std::min_element(x.begin(), x.end(),
111 160000000 : [noData](T a, T b)
112 : {
113 159882000 : return b == noData ? true
114 79882200 : : 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 : {
184 159882000 : return a == noData ? true
185 79882200 : : b == noData ? false
186 80000000 : : a < b;
187 : })));
188 : }
189 8 : idx /= N_ITERS;
190 8 : printf("max at idx %d (nodata case, using std::max_element with "
191 : "nodata aware comparison), val=%s\n",
192 8 : idx, std::to_string(x[idx]).c_str());
193 8 : auto end = std::chrono::steady_clock::now();
194 8 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
195 8 : v_ref = x[idx];
196 : }
197 8 : ASSERT_EQ(v_optim, v_ref);
198 8 : }
199 :
200 : template <class T>
201 : #if defined(__GNUC__)
202 : __attribute__((noinline))
203 : #endif
204 3 : static void 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 : {
235 79902300 : return CPLIsNan(b) ? true
236 49902300 : : CPLIsNan(a) ? false
237 39951200 : : a < b;
238 : })));
239 : }
240 3 : idx /= N_ITERS;
241 3 : printf("min at idx %d (using std::min_element with NaN aware "
242 : "comparison), val = %g\n",
243 3 : idx, static_cast<double>(x[idx]));
244 3 : auto end = std::chrono::steady_clock::now();
245 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
246 3 : v_ref = x[idx];
247 : }
248 3 : ASSERT_EQ(v_optim, v_ref);
249 :
250 : {
251 3 : auto start = std::chrono::steady_clock::now();
252 3 : int idx = 0;
253 6 : for (int i = 0; i < N_ITERS; ++i)
254 : {
255 3 : idx += static_cast<int>(
256 3 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
257 : }
258 3 : idx /= N_ITERS;
259 3 : printf("min at idx %d (nodata case, optimized), val = %g\n", idx,
260 3 : static_cast<double>(x[idx]));
261 3 : auto end = std::chrono::steady_clock::now();
262 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
263 3 : v_optim = x[idx];
264 : }
265 : {
266 3 : auto start = std::chrono::steady_clock::now();
267 3 : int idx = 0;
268 6 : for (int i = 0; i < N_ITERS; ++i)
269 : {
270 3 : idx += static_cast<int>(std::distance(
271 : x.begin(), std::min_element(x.begin(), x.end(),
272 69804600 : [noData](T a, T b)
273 : {
274 79902300 : return CPLIsNan(b) ? true
275 59853500 : : CPLIsNan(a) ? false
276 39804700 : : b == noData ? true
277 29853500 : : a == noData ? false
278 39951200 : : a < b;
279 : })));
280 : }
281 3 : idx /= N_ITERS;
282 3 : printf("min at idx %d (nodata case, using std::min_element with "
283 : "nodata aware and NaN aware comparison), val = %g\n",
284 3 : idx, static_cast<double>(x[idx]));
285 3 : auto end = std::chrono::steady_clock::now();
286 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
287 3 : v_ref = x[idx];
288 : }
289 3 : ASSERT_EQ(v_optim, v_ref);
290 :
291 : {
292 3 : auto start = std::chrono::steady_clock::now();
293 3 : int idx = 0;
294 6 : for (int i = 0; i < N_ITERS; ++i)
295 : {
296 3 : idx += static_cast<int>(
297 3 : gdal::max_element(x.data(), x.size(), eDT, false, 0));
298 : }
299 3 : idx /= N_ITERS;
300 3 : printf("max at idx %d (optimized), val = %g\n", idx,
301 3 : static_cast<double>(x[idx]));
302 3 : auto end = std::chrono::steady_clock::now();
303 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
304 3 : v_optim = x[idx];
305 : }
306 : {
307 3 : auto start = std::chrono::steady_clock::now();
308 3 : int idx = 0;
309 6 : for (int i = 0; i < N_ITERS; ++i)
310 : {
311 3 : idx += static_cast<int>(std::distance(
312 : x.begin(), std::max_element(x.begin(), x.end(),
313 30000000 : [](T a, T b)
314 : {
315 79902300 : return CPLIsNan(a) ? true
316 49902300 : : CPLIsNan(b) ? false
317 39951200 : : a < b;
318 : })));
319 : }
320 3 : idx /= N_ITERS;
321 3 : printf("max at idx %d (using std::max_element with NaN aware "
322 : "comparison), val = %g\n",
323 3 : idx, static_cast<double>(x[idx]));
324 3 : auto end = std::chrono::steady_clock::now();
325 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
326 3 : v_ref = x[idx];
327 : }
328 3 : ASSERT_EQ(v_optim, v_ref);
329 :
330 : {
331 3 : auto start = std::chrono::steady_clock::now();
332 3 : int idx = 0;
333 6 : for (int i = 0; i < N_ITERS; ++i)
334 : {
335 3 : idx += static_cast<int>(
336 3 : gdal::max_element(x.data(), x.size(), eDT, true, noData));
337 : }
338 3 : idx /= N_ITERS;
339 3 : printf("max at idx %d (nodata case, optimized), val = %g\n", idx,
340 3 : static_cast<double>(x[idx]));
341 3 : auto end = std::chrono::steady_clock::now();
342 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
343 3 : v_optim = x[idx];
344 : }
345 : {
346 3 : auto start = std::chrono::steady_clock::now();
347 3 : int idx = 0;
348 6 : for (int i = 0; i < N_ITERS; ++i)
349 : {
350 3 : idx += static_cast<int>(std::distance(
351 : x.begin(), std::max_element(x.begin(), x.end(),
352 69804600 : [noData](T a, T b)
353 : {
354 79902300 : return CPLIsNan(a) ? true
355 59853500 : : CPLIsNan(b) ? false
356 39804700 : : a == noData ? true
357 29853500 : : b == noData ? false
358 39951200 : : a < b;
359 : })));
360 : }
361 3 : idx /= N_ITERS;
362 3 : printf("max at idx %d (nodata case, using std::max_element with "
363 : "nodata aware and NaN aware comparison), val = %g\n",
364 3 : idx, static_cast<double>(x[idx]));
365 3 : auto end = std::chrono::steady_clock::now();
366 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
367 3 : v_ref = x[idx];
368 : }
369 3 : ASSERT_EQ(v_optim, v_ref);
370 3 : }
371 :
372 : template <class T>
373 : #if defined(__GNUC__)
374 : __attribute__((noinline))
375 : #endif
376 3 : static void benchFloatingPointsWithoutNaN(GDALDataType eDT, T noData)
377 : {
378 6 : std::vector<T> x;
379 3 : x.resize(SIZE);
380 3 : randomFill(x.data(), x.size(), false);
381 : T v_optim, v_ref;
382 :
383 : {
384 3 : auto start = std::chrono::steady_clock::now();
385 3 : int idx = 0;
386 6 : for (int i = 0; i < N_ITERS; ++i)
387 : {
388 3 : idx += static_cast<int>(
389 3 : gdal::min_element(x.data(), x.size(), eDT, false, 0));
390 : }
391 3 : idx /= N_ITERS;
392 3 : printf("min at idx %d (optimized), val = %g\n", idx,
393 3 : static_cast<double>(x[idx]));
394 3 : auto end = std::chrono::steady_clock::now();
395 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
396 3 : v_optim = x[idx];
397 : }
398 : {
399 3 : auto start = std::chrono::steady_clock::now();
400 3 : int idx = 0;
401 6 : for (int i = 0; i < N_ITERS; ++i)
402 : {
403 3 : idx += static_cast<int>(
404 3 : std::distance(x.begin(), std::min_element(x.begin(), x.end())));
405 : }
406 3 : idx /= N_ITERS;
407 3 : printf("min at idx %d (using std::min_element), val = %g\n", idx,
408 3 : static_cast<double>(x[idx]));
409 3 : auto end = std::chrono::steady_clock::now();
410 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
411 3 : v_ref = x[idx];
412 : }
413 3 : ASSERT_EQ(v_optim, v_ref);
414 :
415 : {
416 3 : auto start = std::chrono::steady_clock::now();
417 3 : int idx = 0;
418 6 : for (int i = 0; i < N_ITERS; ++i)
419 : {
420 3 : idx += static_cast<int>(
421 3 : gdal::min_element(x.data(), x.size(), eDT, true, noData));
422 : }
423 3 : idx /= N_ITERS;
424 3 : printf("min at idx %d (nodata case, optimized), val = %g\n", idx,
425 3 : static_cast<double>(x[idx]));
426 3 : auto end = std::chrono::steady_clock::now();
427 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
428 3 : v_optim = x[idx];
429 : }
430 : {
431 3 : auto start = std::chrono::steady_clock::now();
432 3 : int idx = 0;
433 6 : for (int i = 0; i < N_ITERS; ++i)
434 : {
435 3 : idx += static_cast<int>(std::distance(
436 : x.begin(), std::min_element(x.begin(), x.end(),
437 50000000 : [noData](T a, T b)
438 : {
439 60000000 : return b == noData ? true
440 30000000 : : a == noData ? false
441 40000000 : : a < b;
442 : })));
443 : }
444 3 : idx /= N_ITERS;
445 3 : printf("min at idx %d (nodata case, using std::min_element with "
446 : "nodata aware comparison), val = %g\n",
447 3 : idx, static_cast<double>(x[idx]));
448 3 : auto end = std::chrono::steady_clock::now();
449 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
450 3 : v_ref = x[idx];
451 : }
452 3 : ASSERT_EQ(v_optim, v_ref);
453 :
454 : {
455 3 : auto start = std::chrono::steady_clock::now();
456 3 : int idx = 0;
457 6 : for (int i = 0; i < N_ITERS; ++i)
458 : {
459 3 : idx += static_cast<int>(
460 3 : gdal::max_element(x.data(), x.size(), eDT, false, 0));
461 : }
462 3 : idx /= N_ITERS;
463 3 : printf("max at idx %d (optimized), val = %g\n", idx,
464 3 : static_cast<double>(x[idx]));
465 3 : auto end = std::chrono::steady_clock::now();
466 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
467 3 : v_optim = x[idx];
468 : }
469 : {
470 3 : auto start = std::chrono::steady_clock::now();
471 3 : int idx = 0;
472 6 : for (int i = 0; i < N_ITERS; ++i)
473 : {
474 3 : idx += static_cast<int>(
475 3 : std::distance(x.begin(), std::max_element(x.begin(), x.end())));
476 : }
477 3 : idx /= N_ITERS;
478 3 : printf("max at idx %d (using std::max_element), val = %g\n", idx,
479 3 : static_cast<double>(x[idx]));
480 3 : auto end = std::chrono::steady_clock::now();
481 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
482 3 : v_ref = x[idx];
483 : }
484 3 : ASSERT_EQ(v_optim, v_ref);
485 :
486 : {
487 3 : auto start = std::chrono::steady_clock::now();
488 3 : int idx = 0;
489 6 : for (int i = 0; i < N_ITERS; ++i)
490 : {
491 3 : idx += static_cast<int>(
492 3 : gdal::max_element(x.data(), x.size(), eDT, true, noData));
493 : }
494 3 : idx /= N_ITERS;
495 3 : printf("max at idx %d (nodata case, optimized), val = %g\n", idx,
496 3 : static_cast<double>(x[idx]));
497 3 : auto end = std::chrono::steady_clock::now();
498 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
499 3 : v_optim = x[idx];
500 : }
501 : {
502 3 : auto start = std::chrono::steady_clock::now();
503 3 : int idx = 0;
504 6 : for (int i = 0; i < N_ITERS; ++i)
505 : {
506 3 : idx += static_cast<int>(std::distance(
507 : x.begin(), std::max_element(x.begin(), x.end(),
508 50000000 : [noData](T a, T b)
509 : {
510 60000000 : return a == noData ? true
511 30000000 : : b == noData ? false
512 40000000 : : a < b;
513 : })));
514 : }
515 3 : idx /= N_ITERS;
516 3 : printf("max at idx %d (nodata case, using std::max_element with "
517 : "nodata aware comparison), val = %g\n",
518 3 : idx, static_cast<double>(x[idx]));
519 3 : auto end = std::chrono::steady_clock::now();
520 3 : printf("-> elapsed=%d\n", static_cast<int>((end - start).count()));
521 3 : v_ref = x[idx];
522 : }
523 3 : ASSERT_EQ(v_optim, v_ref);
524 3 : }
525 :
526 1 : int main(int /* argc */, char * /* argv */[])
527 : {
528 : {
529 : using T = uint8_t;
530 1 : constexpr GDALDataType eDT = GDT_Byte;
531 1 : printf("uint8:\n");
532 1 : benchIntegers<T>(eDT, 0);
533 : }
534 1 : printf("--------------------\n");
535 : {
536 : using T = int8_t;
537 1 : constexpr GDALDataType eDT = GDT_Int8;
538 1 : printf("int8:\n");
539 1 : benchIntegers<T>(eDT, 0);
540 : }
541 1 : printf("--------------------\n");
542 : {
543 : using T = uint16_t;
544 1 : constexpr GDALDataType eDT = GDT_UInt16;
545 1 : printf("uint16:\n");
546 1 : benchIntegers<T>(eDT, 0);
547 : }
548 1 : printf("--------------------\n");
549 : {
550 : using T = int16_t;
551 1 : constexpr GDALDataType eDT = GDT_Int16;
552 1 : printf("int16:\n");
553 1 : benchIntegers<T>(eDT, 0);
554 : }
555 1 : printf("--------------------\n");
556 : {
557 : using T = uint32_t;
558 1 : constexpr GDALDataType eDT = GDT_UInt32;
559 1 : printf("uint32:\n");
560 1 : benchIntegers<T>(eDT, 0);
561 : }
562 1 : printf("--------------------\n");
563 : {
564 : using T = int32_t;
565 1 : constexpr GDALDataType eDT = GDT_Int32;
566 1 : printf("int32:\n");
567 1 : benchIntegers<T>(eDT, 0);
568 : }
569 1 : printf("--------------------\n");
570 : {
571 : using T = uint64_t;
572 1 : constexpr GDALDataType eDT = GDT_UInt64;
573 1 : printf("uint64:\n");
574 1 : benchIntegers<T>(eDT, 0);
575 : }
576 1 : printf("--------------------\n");
577 : {
578 : using T = int64_t;
579 1 : constexpr GDALDataType eDT = GDT_Int64;
580 1 : printf("int64:\n");
581 1 : benchIntegers<T>(eDT, 0);
582 : }
583 1 : printf("--------------------\n");
584 : {
585 : using T = GFloat16;
586 1 : constexpr GDALDataType eDT = GDT_Float16;
587 1 : printf("float16 (*with* NaN):\n");
588 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
589 : }
590 1 : printf("--------------------\n");
591 : {
592 : using T = GFloat16;
593 1 : constexpr GDALDataType eDT = GDT_Float16;
594 1 : printf("float16 (without NaN):\n");
595 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
596 : }
597 1 : printf("--------------------\n");
598 : {
599 : using T = float;
600 1 : constexpr GDALDataType eDT = GDT_Float32;
601 1 : printf("float (*with* NaN):\n");
602 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
603 : }
604 1 : printf("--------------------\n");
605 : {
606 : using T = float;
607 1 : constexpr GDALDataType eDT = GDT_Float32;
608 1 : printf("float (without NaN):\n");
609 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
610 : }
611 1 : printf("--------------------\n");
612 : {
613 : using T = double;
614 1 : constexpr GDALDataType eDT = GDT_Float64;
615 1 : printf("double (*with* NaN):\n");
616 1 : benchFloatingPointsWithNaN<T>(eDT, 0);
617 : }
618 1 : printf("--------------------\n");
619 : {
620 : using T = double;
621 1 : constexpr GDALDataType eDT = GDT_Float64;
622 1 : printf("double (without NaN):\n");
623 1 : benchFloatingPointsWithoutNaN<T>(eDT, 0);
624 : }
625 1 : return 0;
626 : }
|