LCOV - code coverage report
Current view: top level - perftests - testperf_gdal_minmax_element.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 388 390 99.5 %
Date: 2025-08-19 18:03:11 Functions: 71 71 100.0 %

          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             : }

Generated by: LCOV version 1.14