Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////////
2 : //
3 : // Project: C++ Test Suite for GDAL/OGR
4 : // Purpose: Test gdal_minmax_element.hpp
5 : // Author: Even Rouault <even.rouault at spatialys.com>
6 : //
7 : ///////////////////////////////////////////////////////////////////////////////
8 : // Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
9 : /*
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "gdal_unit_test.h"
14 :
15 : #include "gdal_minmax_element.hpp"
16 :
17 : #include "gtest_include.h"
18 :
19 : #include <limits>
20 :
21 : namespace
22 : {
23 :
24 : struct test_gdal_minmax_element : public ::testing::Test
25 : {
26 : };
27 :
28 4 : TEST_F(test_gdal_minmax_element, uint8)
29 : {
30 : using T = uint8_t;
31 1 : constexpr GDALDataType eDT = GDT_Byte;
32 1 : T min_v = 3;
33 1 : T max_v = 7;
34 : {
35 1 : T nodata = 0;
36 2 : std::vector<T> v{max_v, nodata, min_v};
37 : {
38 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
39 1 : EXPECT_EQ(idx_min, 0);
40 : }
41 : {
42 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
43 1 : EXPECT_EQ(idx_min, 0);
44 : }
45 : {
46 : auto idx_min =
47 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
48 1 : EXPECT_EQ(v[idx_min], min_v);
49 : auto idx_max =
50 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
51 1 : EXPECT_EQ(v[idx_max], max_v);
52 : }
53 : {
54 1 : auto [idx_min, idx_max] =
55 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
56 1 : EXPECT_EQ(v[idx_min], min_v);
57 1 : EXPECT_EQ(v[idx_max], max_v);
58 : }
59 : }
60 : {
61 1 : T nodata = 0;
62 2 : std::vector<T> v{nodata, max_v, min_v};
63 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
64 1 : EXPECT_EQ(v[idx_min], min_v);
65 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
66 1 : EXPECT_EQ(v[idx_max], max_v);
67 : }
68 : {
69 1 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2),
70 1 : static_cast<T>(max_v - 1),
71 : max_v,
72 1 : static_cast<T>(max_v - 1),
73 1 : static_cast<T>(min_v + 1),
74 : min_v,
75 2 : static_cast<T>(min_v + 1)};
76 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
77 1 : EXPECT_EQ(v[idx_min], min_v);
78 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
79 1 : EXPECT_EQ(v[idx_max], max_v);
80 : }
81 : {
82 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
83 1 : v[125] = static_cast<T>(min_v + 1);
84 1 : v[126] = min_v;
85 1 : v[127] = static_cast<T>(min_v + 1);
86 1 : v[128] = static_cast<T>(max_v - 1);
87 1 : v[129] = max_v;
88 1 : v[130] = static_cast<T>(max_v - 1);
89 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
90 1 : EXPECT_EQ(v[idx_min], min_v);
91 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
92 1 : EXPECT_EQ(v[idx_max], max_v);
93 : }
94 : {
95 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
96 1 : v[128] = static_cast<T>(min_v + 1);
97 1 : v[256] = min_v;
98 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
99 1 : static_cast<T>(min_v + 1));
100 1 : EXPECT_EQ(v[idx_min], min_v);
101 : }
102 : {
103 2 : std::vector<T> v(257, 0);
104 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, 0);
105 1 : EXPECT_TRUE(idx_min == 0 || idx_min == 256) << idx_min;
106 : }
107 : {
108 2 : std::vector<T> v(257, 0);
109 1 : v[127] = static_cast<T>(min_v + 1);
110 1 : v[255] = min_v;
111 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, 0);
112 1 : EXPECT_EQ(v[idx_min], min_v);
113 : }
114 : {
115 2 : std::vector<T> v(259, static_cast<T>((min_v + max_v) / 2));
116 1 : v[0] = min_v;
117 1 : v[256] = static_cast<T>(max_v - 1);
118 1 : v[257] = max_v;
119 1 : v[258] = static_cast<T>(max_v - 1);
120 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
121 1 : EXPECT_EQ(v[idx_min], min_v);
122 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
123 1 : EXPECT_EQ(v[idx_max], max_v);
124 : }
125 : {
126 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
127 1 : v[0] = min_v;
128 1 : v[127] = max_v;
129 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
130 1 : EXPECT_EQ(v[idx_min], min_v);
131 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
132 1 : EXPECT_EQ(v[idx_max], max_v);
133 : }
134 : {
135 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
136 1 : v[127] = min_v;
137 1 : v[0] = max_v;
138 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
139 1 : EXPECT_EQ(v[idx_min], min_v);
140 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
141 1 : EXPECT_EQ(v[idx_max], max_v);
142 : }
143 : {
144 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
145 1 : v[0] = min_v;
146 1 : v[129] = max_v;
147 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
148 1 : EXPECT_EQ(v[idx_min], min_v);
149 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
150 1 : EXPECT_EQ(v[idx_max], max_v);
151 : }
152 : {
153 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
154 1 : v[129] = min_v;
155 1 : v[0] = max_v;
156 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
157 1 : EXPECT_EQ(v[idx_min], min_v);
158 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
159 1 : EXPECT_EQ(v[idx_max], max_v);
160 : }
161 : {
162 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
163 1 : v[129] = min_v;
164 1 : v[256] = max_v;
165 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
166 1 : EXPECT_EQ(v[idx_min], min_v);
167 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
168 1 : EXPECT_EQ(v[idx_max], max_v);
169 : }
170 : {
171 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
172 1 : v[256] = min_v;
173 1 : v[129] = max_v;
174 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
175 1 : EXPECT_EQ(v[idx_min], min_v);
176 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
177 1 : EXPECT_EQ(v[idx_max], max_v);
178 : }
179 : {
180 2 : std::vector<T> v(257, 0);
181 1 : v[65] = static_cast<T>(max_v - 2);
182 1 : v[66] = static_cast<T>(max_v - 1);
183 1 : v[129] = max_v;
184 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, 0);
185 1 : EXPECT_EQ(v[idx_max], max_v);
186 : }
187 1 : }
188 :
189 4 : TEST_F(test_gdal_minmax_element, int8)
190 : {
191 : using T = int8_t;
192 1 : T min_v = -1;
193 1 : T max_v = 3;
194 1 : constexpr GDALDataType eDT = GDT_Int8;
195 : {
196 1 : T nodata = 0;
197 2 : std::vector<T> v{max_v, nodata, min_v};
198 : {
199 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
200 1 : EXPECT_EQ(idx_min, 0);
201 : }
202 : {
203 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
204 1 : EXPECT_EQ(idx_min, 0);
205 : }
206 : {
207 : auto idx_min =
208 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
209 1 : EXPECT_EQ(v[idx_min], min_v);
210 : auto idx_max =
211 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
212 1 : EXPECT_EQ(v[idx_max], max_v);
213 : }
214 : {
215 1 : auto [idx_min, idx_max] =
216 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
217 1 : EXPECT_EQ(v[idx_min], min_v);
218 1 : EXPECT_EQ(v[idx_max], max_v);
219 : }
220 : }
221 : {
222 1 : T nodata = 0;
223 2 : std::vector<T> v{nodata, max_v, min_v};
224 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
225 1 : EXPECT_EQ(v[idx_min], min_v);
226 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
227 1 : EXPECT_EQ(v[idx_max], max_v);
228 : }
229 : {
230 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
231 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
232 1 : EXPECT_EQ(v[idx_min], min_v);
233 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
234 1 : EXPECT_EQ(v[idx_max], max_v);
235 : }
236 : {
237 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
238 1 : v[5] = min_v;
239 1 : v[31] = max_v;
240 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
241 1 : EXPECT_EQ(v[idx_min], min_v);
242 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
243 1 : EXPECT_EQ(v[idx_max], max_v);
244 : }
245 : {
246 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
247 1 : v[128] = static_cast<T>(min_v + 1);
248 1 : v[256] = min_v;
249 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
250 1 : static_cast<T>(min_v + 1));
251 1 : EXPECT_EQ(v[idx_min], min_v);
252 : }
253 1 : }
254 :
255 4 : TEST_F(test_gdal_minmax_element, uint16)
256 : {
257 : using T = uint16_t;
258 1 : constexpr GDALDataType eDT = GDT_UInt16;
259 1 : T min_v = 1000;
260 1 : T max_v = 2000;
261 : {
262 1 : T nodata = 0;
263 2 : std::vector<T> v{max_v, nodata, min_v};
264 : {
265 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
266 1 : EXPECT_EQ(idx_min, 0);
267 : }
268 : {
269 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
270 1 : EXPECT_EQ(idx_min, 0);
271 : }
272 : {
273 : auto idx_min =
274 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
275 1 : EXPECT_EQ(v[idx_min], min_v);
276 : auto idx_max =
277 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
278 1 : EXPECT_EQ(v[idx_max], max_v);
279 : }
280 : {
281 1 : auto [idx_min, idx_max] =
282 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
283 1 : EXPECT_EQ(v[idx_min], min_v);
284 1 : EXPECT_EQ(v[idx_max], max_v);
285 : }
286 : }
287 : {
288 1 : T nodata = 0;
289 2 : std::vector<T> v{nodata, max_v, min_v};
290 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
291 1 : EXPECT_EQ(v[idx_min], min_v);
292 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
293 1 : EXPECT_EQ(v[idx_max], max_v);
294 : }
295 : {
296 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
297 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
298 1 : EXPECT_EQ(v[idx_min], min_v);
299 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
300 1 : EXPECT_EQ(v[idx_max], max_v);
301 : }
302 : {
303 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
304 1 : v[5] = min_v;
305 1 : v[31] = max_v;
306 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
307 1 : EXPECT_EQ(v[idx_min], min_v);
308 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
309 1 : EXPECT_EQ(v[idx_max], max_v);
310 : }
311 : {
312 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
313 1 : v[128] = static_cast<T>(min_v + 1);
314 1 : v[256] = min_v;
315 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
316 1 : static_cast<T>(min_v + 1));
317 1 : EXPECT_EQ(v[idx_min], min_v);
318 : }
319 1 : }
320 :
321 4 : TEST_F(test_gdal_minmax_element, int16)
322 : {
323 : using T = int16_t;
324 1 : constexpr GDALDataType eDT = GDT_Int16;
325 1 : T min_v = -1000;
326 1 : T max_v = 2000;
327 : {
328 1 : T nodata = 0;
329 2 : std::vector<T> v{max_v, nodata, min_v};
330 : {
331 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
332 1 : EXPECT_EQ(idx_min, 0);
333 : }
334 : {
335 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
336 1 : EXPECT_EQ(idx_min, 0);
337 : }
338 : {
339 : auto idx_min =
340 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
341 1 : EXPECT_EQ(v[idx_min], min_v);
342 : auto idx_max =
343 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
344 1 : EXPECT_EQ(v[idx_max], max_v);
345 : }
346 : {
347 1 : auto [idx_min, idx_max] =
348 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
349 1 : EXPECT_EQ(v[idx_min], min_v);
350 1 : EXPECT_EQ(v[idx_max], max_v);
351 : }
352 : }
353 : {
354 1 : T nodata = 0;
355 2 : std::vector<T> v{nodata, max_v, min_v};
356 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
357 1 : EXPECT_EQ(v[idx_min], min_v);
358 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
359 1 : EXPECT_EQ(v[idx_max], max_v);
360 : }
361 : {
362 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
363 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
364 1 : EXPECT_EQ(v[idx_min], min_v);
365 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
366 1 : EXPECT_EQ(v[idx_max], max_v);
367 : }
368 : {
369 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
370 1 : v[5] = min_v;
371 1 : v[31] = max_v;
372 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
373 1 : EXPECT_EQ(v[idx_min], min_v);
374 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
375 1 : EXPECT_EQ(v[idx_max], max_v);
376 : }
377 : {
378 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
379 1 : v[128] = static_cast<T>(min_v + 1);
380 1 : v[256] = min_v;
381 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
382 1 : static_cast<T>(min_v + 1));
383 1 : EXPECT_EQ(v[idx_min], min_v);
384 : }
385 1 : }
386 :
387 4 : TEST_F(test_gdal_minmax_element, uint32)
388 : {
389 : using T = uint32_t;
390 1 : constexpr GDALDataType eDT = GDT_UInt32;
391 1 : T min_v = 10000000;
392 1 : T max_v = 20000000;
393 : {
394 1 : T nodata = 0;
395 2 : std::vector<T> v{max_v, nodata, min_v};
396 : {
397 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
398 1 : EXPECT_EQ(idx_min, 0);
399 : }
400 : {
401 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
402 1 : EXPECT_EQ(idx_min, 0);
403 : }
404 : {
405 : auto idx_min =
406 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
407 1 : EXPECT_EQ(v[idx_min], min_v);
408 : auto idx_max =
409 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
410 1 : EXPECT_EQ(v[idx_max], max_v);
411 : }
412 : {
413 1 : auto [idx_min, idx_max] =
414 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
415 1 : EXPECT_EQ(v[idx_min], min_v);
416 1 : EXPECT_EQ(v[idx_max], max_v);
417 : }
418 : }
419 : {
420 1 : T nodata = 0;
421 2 : std::vector<T> v{nodata, max_v, min_v};
422 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
423 1 : EXPECT_EQ(v[idx_min], min_v);
424 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
425 1 : EXPECT_EQ(v[idx_max], max_v);
426 : }
427 : {
428 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
429 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
430 1 : EXPECT_EQ(v[idx_min], min_v);
431 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
432 1 : EXPECT_EQ(v[idx_max], max_v);
433 : }
434 : {
435 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
436 1 : v[5] = min_v;
437 1 : v[31] = max_v;
438 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
439 1 : EXPECT_EQ(v[idx_min], min_v);
440 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
441 1 : EXPECT_EQ(v[idx_max], max_v);
442 : }
443 : {
444 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
445 1 : v[128] = static_cast<T>(min_v + 1);
446 1 : v[256] = min_v;
447 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
448 1 : static_cast<T>(min_v + 1));
449 1 : EXPECT_EQ(v[idx_min], min_v);
450 : }
451 1 : }
452 :
453 4 : TEST_F(test_gdal_minmax_element, int32)
454 : {
455 : using T = int32_t;
456 1 : constexpr GDALDataType eDT = GDT_Int32;
457 1 : T min_v = -10000000;
458 1 : T max_v = 20000000;
459 : {
460 1 : T nodata = 0;
461 2 : std::vector<T> v{max_v, nodata, min_v};
462 : {
463 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
464 1 : EXPECT_EQ(idx_min, 0);
465 : }
466 : {
467 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
468 1 : EXPECT_EQ(idx_min, 0);
469 : }
470 : {
471 : auto idx_min =
472 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
473 1 : EXPECT_EQ(v[idx_min], min_v);
474 : auto idx_max =
475 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
476 1 : EXPECT_EQ(v[idx_max], max_v);
477 : }
478 : {
479 1 : auto [idx_min, idx_max] =
480 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
481 1 : EXPECT_EQ(v[idx_min], min_v);
482 1 : EXPECT_EQ(v[idx_max], max_v);
483 : }
484 : }
485 : {
486 1 : T nodata = 0;
487 2 : std::vector<T> v{nodata, max_v, min_v};
488 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
489 1 : EXPECT_EQ(v[idx_min], min_v);
490 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
491 1 : EXPECT_EQ(v[idx_max], max_v);
492 : }
493 : {
494 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
495 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
496 1 : EXPECT_EQ(v[idx_min], min_v);
497 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
498 1 : EXPECT_EQ(v[idx_max], max_v);
499 : }
500 : {
501 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
502 1 : v[5] = min_v;
503 1 : v[31] = max_v;
504 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
505 1 : EXPECT_EQ(v[idx_min], min_v);
506 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
507 1 : EXPECT_EQ(v[idx_max], max_v);
508 : }
509 : {
510 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
511 1 : v[128] = static_cast<T>(min_v + 1);
512 1 : v[256] = min_v;
513 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
514 1 : static_cast<T>(min_v + 1));
515 1 : EXPECT_EQ(v[idx_min], min_v);
516 : }
517 1 : }
518 :
519 4 : TEST_F(test_gdal_minmax_element, uint64)
520 : {
521 : using T = uint64_t;
522 1 : constexpr GDALDataType eDT = GDT_UInt64;
523 1 : T min_v = 100000000000000;
524 1 : T max_v = 200000000000000;
525 : {
526 1 : double nodata = 0;
527 2 : std::vector<T> v{max_v, static_cast<T>(nodata), min_v};
528 : {
529 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
530 1 : EXPECT_EQ(idx_min, 0);
531 : }
532 : {
533 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
534 1 : EXPECT_EQ(idx_min, 0);
535 : }
536 : {
537 : auto idx_min =
538 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
539 1 : EXPECT_EQ(v[idx_min], min_v);
540 : auto idx_max =
541 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
542 1 : EXPECT_EQ(v[idx_max], max_v);
543 : }
544 : {
545 1 : auto [idx_min, idx_max] =
546 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
547 1 : EXPECT_EQ(v[idx_min], min_v);
548 1 : EXPECT_EQ(v[idx_max], max_v);
549 : }
550 : }
551 : {
552 1 : double nodata = 0;
553 2 : std::vector<T> v{static_cast<T>(nodata), max_v, min_v};
554 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
555 1 : EXPECT_EQ(v[idx_min], min_v);
556 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
557 1 : EXPECT_EQ(v[idx_max], max_v);
558 : }
559 : {
560 2 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2), max_v, min_v};
561 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
562 1 : EXPECT_EQ(v[idx_min], min_v);
563 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
564 1 : EXPECT_EQ(v[idx_max], max_v);
565 : }
566 : {
567 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
568 1 : v[5] = min_v;
569 1 : v[31] = max_v;
570 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
571 1 : EXPECT_EQ(v[idx_min], min_v);
572 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
573 1 : EXPECT_EQ(v[idx_max], max_v);
574 : }
575 : {
576 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
577 1 : v[128] = static_cast<T>(min_v + 1);
578 1 : v[256] = min_v;
579 : auto idx_min =
580 1 : gdal::min_element(v.data(), v.size(), eDT, true,
581 1 : static_cast<double>(static_cast<T>(min_v + 1)));
582 1 : EXPECT_EQ(v[idx_min], min_v);
583 : }
584 1 : }
585 :
586 4 : TEST_F(test_gdal_minmax_element, int64)
587 : {
588 : using T = int64_t;
589 1 : constexpr GDALDataType eDT = GDT_Int64;
590 1 : T min_v = -100000000000000;
591 1 : T max_v = 200000000000000;
592 : {
593 1 : double nodata = 0;
594 2 : std::vector<T> v{max_v, static_cast<T>(nodata), min_v};
595 : {
596 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
597 1 : EXPECT_EQ(idx_min, 0);
598 : }
599 : {
600 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
601 1 : EXPECT_EQ(idx_min, 0);
602 : }
603 : {
604 : auto idx_min =
605 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
606 1 : EXPECT_EQ(v[idx_min], min_v);
607 : auto idx_max =
608 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
609 1 : EXPECT_EQ(v[idx_max], max_v);
610 : }
611 : {
612 1 : auto [idx_min, idx_max] =
613 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
614 1 : EXPECT_EQ(v[idx_min], min_v);
615 1 : EXPECT_EQ(v[idx_max], max_v);
616 : }
617 : }
618 : {
619 1 : double nodata = 0;
620 2 : std::vector<T> v{static_cast<T>(nodata), max_v, min_v};
621 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
622 1 : EXPECT_EQ(v[idx_min], min_v);
623 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
624 1 : EXPECT_EQ(v[idx_max], max_v);
625 : }
626 : {
627 1 : std::vector<T> v{static_cast<T>((min_v + max_v) / 2),
628 1 : max_v - 1,
629 : max_v,
630 1 : max_v - 1,
631 1 : min_v + 1,
632 : min_v,
633 2 : min_v + 1};
634 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
635 1 : EXPECT_EQ(v[idx_min], min_v);
636 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
637 1 : EXPECT_EQ(v[idx_max], max_v);
638 : }
639 : {
640 2 : std::vector<T> v(257, static_cast<T>((min_v + max_v) / 2));
641 1 : v[5] = min_v;
642 1 : v[31] = max_v;
643 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
644 1 : EXPECT_EQ(v[idx_min], min_v);
645 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
646 1 : EXPECT_EQ(v[idx_max], max_v);
647 : }
648 : {
649 2 : std::vector<T> v(257, static_cast<T>(min_v + 2));
650 1 : v[128] = static_cast<T>(min_v + 1);
651 1 : v[256] = min_v;
652 : auto idx_min =
653 1 : gdal::min_element(v.data(), v.size(), eDT, true,
654 1 : static_cast<double>(static_cast<T>(min_v + 1)));
655 1 : EXPECT_EQ(v[idx_min], min_v);
656 : }
657 1 : }
658 :
659 4 : TEST_F(test_gdal_minmax_element, float32)
660 : {
661 : using T = float;
662 1 : constexpr GDALDataType eDT = GDT_Float32;
663 1 : T min_v = 1.0f;
664 1 : T max_v = 1.5f;
665 : {
666 1 : T nodata = 2.0f;
667 2 : std::vector<T> v{max_v, nodata, min_v};
668 : {
669 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
670 1 : EXPECT_EQ(idx_min, 0);
671 : }
672 : {
673 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
674 1 : EXPECT_EQ(idx_min, 0);
675 : }
676 : {
677 : auto idx_min =
678 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
679 1 : EXPECT_EQ(v[idx_min], min_v);
680 : auto idx_max =
681 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
682 1 : EXPECT_EQ(v[idx_max], max_v);
683 : }
684 : {
685 1 : auto [idx_min, idx_max] =
686 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
687 1 : EXPECT_EQ(v[idx_min], min_v);
688 1 : EXPECT_EQ(v[idx_max], max_v);
689 : }
690 : }
691 : {
692 1 : T nodata = 2.0f;
693 2 : std::vector<T> v{nodata, max_v, min_v};
694 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
695 1 : EXPECT_EQ(v[idx_min], min_v);
696 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
697 1 : EXPECT_EQ(v[idx_max], max_v);
698 : }
699 : {
700 1 : T nodata = 2.0f;
701 : std::vector<T> v{std::numeric_limits<T>::quiet_NaN(),
702 : std::numeric_limits<T>::quiet_NaN(), nodata, max_v,
703 2 : min_v};
704 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
705 1 : EXPECT_EQ(v[idx_min], min_v);
706 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
707 1 : EXPECT_EQ(v[idx_max], max_v);
708 : }
709 : {
710 1 : T nodata = std::numeric_limits<T>::quiet_NaN();
711 : std::vector<T> v{std::numeric_limits<T>::quiet_NaN(),
712 : std::numeric_limits<T>::quiet_NaN(), nodata, max_v,
713 2 : min_v};
714 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
715 1 : EXPECT_EQ(v[idx_min], min_v);
716 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
717 1 : EXPECT_EQ(v[idx_max], max_v);
718 : }
719 : {
720 : std::vector<T> v{std::numeric_limits<T>::quiet_NaN(),
721 : std::numeric_limits<T>::quiet_NaN(),
722 : max_v,
723 : std::numeric_limits<T>::quiet_NaN(),
724 : min_v,
725 2 : std::numeric_limits<T>::quiet_NaN()};
726 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
727 1 : EXPECT_EQ(v[idx_min], min_v);
728 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
729 1 : EXPECT_EQ(v[idx_max], max_v);
730 : }
731 : {
732 2 : std::vector<T> v{max_v, std::numeric_limits<T>::quiet_NaN(), min_v};
733 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
734 1 : EXPECT_EQ(v[idx_min], min_v);
735 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
736 1 : EXPECT_EQ(v[idx_max], max_v);
737 : }
738 : {
739 2 : std::vector<T> v(257, std::numeric_limits<T>::quiet_NaN());
740 1 : v[125] = static_cast<T>(min_v + 0.1f);
741 1 : v[126] = min_v;
742 1 : v[127] = static_cast<T>(min_v + 0.1f);
743 1 : v[128] = static_cast<T>(max_v - 0.1f);
744 1 : v[129] = max_v;
745 1 : v[130] = static_cast<T>(max_v - 0.1f);
746 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
747 1 : EXPECT_EQ(v[idx_min], min_v);
748 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
749 1 : EXPECT_EQ(v[idx_max], max_v);
750 : }
751 : {
752 2 : std::vector<T> v(33, 1.2f);
753 1 : v[5] = min_v;
754 1 : v[15] = max_v;
755 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
756 1 : EXPECT_EQ(v[idx_min], min_v);
757 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
758 1 : EXPECT_EQ(v[idx_max], max_v);
759 : }
760 : {
761 2 : std::vector<T> v(255, std::numeric_limits<T>::quiet_NaN());
762 1 : v[v.size() - 2] = min_v;
763 1 : v.back() = max_v;
764 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
765 1 : EXPECT_EQ(v[idx_min], min_v);
766 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
767 1 : EXPECT_EQ(v[idx_max], max_v);
768 : }
769 : {
770 2 : std::vector<T> v(257, static_cast<T>(min_v + 0.2f));
771 1 : v[128] = static_cast<T>(min_v + 0.1f);
772 1 : v[256] = min_v;
773 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
774 1 : static_cast<T>(min_v + 0.1f));
775 1 : EXPECT_EQ(v[idx_min], min_v);
776 : }
777 1 : }
778 :
779 4 : TEST_F(test_gdal_minmax_element, float64)
780 : {
781 : using T = double;
782 1 : constexpr GDALDataType eDT = GDT_Float64;
783 1 : T min_v = 1.0;
784 1 : T max_v = 1.5;
785 : {
786 1 : T nodata = 2.0;
787 2 : std::vector<T> v{max_v, nodata, min_v};
788 : {
789 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, true, nodata);
790 1 : EXPECT_EQ(idx_min, 0);
791 : }
792 : {
793 1 : auto idx_min = gdal::min_element(v.data(), 0, eDT, false, 0);
794 1 : EXPECT_EQ(idx_min, 0);
795 : }
796 : {
797 : auto idx_min =
798 1 : gdal::min_element(v.data(), v.size(), eDT, true, nodata);
799 1 : EXPECT_EQ(v[idx_min], min_v);
800 : auto idx_max =
801 1 : gdal::max_element(v.data(), v.size(), eDT, true, nodata);
802 1 : EXPECT_EQ(v[idx_max], max_v);
803 : }
804 : {
805 1 : auto [idx_min, idx_max] =
806 1 : gdal::minmax_element(v.data(), v.size(), eDT, true, nodata);
807 1 : EXPECT_EQ(v[idx_min], min_v);
808 1 : EXPECT_EQ(v[idx_max], max_v);
809 : }
810 : }
811 : {
812 1 : T nodata = 2.0;
813 2 : std::vector<T> v{nodata, max_v, min_v};
814 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
815 1 : EXPECT_EQ(v[idx_min], min_v);
816 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
817 1 : EXPECT_EQ(v[idx_max], max_v);
818 : }
819 : {
820 1 : T nodata = 2.0;
821 : std::vector<T> v{std::numeric_limits<T>::quiet_NaN(),
822 : std::numeric_limits<T>::quiet_NaN(), nodata, max_v,
823 2 : min_v};
824 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true, nodata);
825 1 : EXPECT_EQ(v[idx_min], min_v);
826 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, true, nodata);
827 1 : EXPECT_EQ(v[idx_max], max_v);
828 : }
829 : {
830 2 : std::vector<T> v{max_v, std::numeric_limits<T>::quiet_NaN(), min_v};
831 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
832 1 : EXPECT_EQ(v[idx_min], min_v);
833 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
834 1 : EXPECT_EQ(v[idx_max], max_v);
835 : }
836 : {
837 : std::vector<T> v{std::numeric_limits<T>::quiet_NaN(),
838 : std::numeric_limits<T>::quiet_NaN(),
839 : max_v,
840 : std::numeric_limits<T>::quiet_NaN(),
841 : min_v,
842 2 : std::numeric_limits<T>::quiet_NaN()};
843 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
844 1 : EXPECT_EQ(v[idx_min], min_v);
845 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
846 1 : EXPECT_EQ(v[idx_max], max_v);
847 : }
848 : {
849 2 : std::vector<T> v(33, std::numeric_limits<T>::quiet_NaN());
850 1 : v[5] = min_v;
851 1 : v[15] = max_v;
852 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
853 1 : EXPECT_EQ(v[idx_min], min_v);
854 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
855 1 : EXPECT_EQ(v[idx_max], max_v);
856 : }
857 : {
858 2 : std::vector<T> v(255, std::numeric_limits<T>::quiet_NaN());
859 1 : v[v.size() - 2] = min_v;
860 1 : v.back() = max_v;
861 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, false, 0);
862 1 : EXPECT_EQ(v[idx_min], min_v);
863 1 : auto idx_max = gdal::max_element(v.data(), v.size(), eDT, false, 0);
864 1 : EXPECT_EQ(v[idx_max], max_v);
865 : }
866 : {
867 2 : std::vector<T> v(257, static_cast<T>(min_v + 0.2));
868 1 : v[128] = static_cast<T>(min_v + 0.1);
869 1 : v[256] = min_v;
870 1 : auto idx_min = gdal::min_element(v.data(), v.size(), eDT, true,
871 : static_cast<T>(min_v + 0.1));
872 1 : EXPECT_EQ(v[idx_min], min_v);
873 : }
874 1 : }
875 :
876 4 : TEST_F(test_gdal_minmax_element, unsupported)
877 : {
878 1 : float v[2] = {0, 0};
879 2 : CPLErrorHandlerPusher oErrorHandler(CPLQuietErrorHandler);
880 : {
881 1 : CPLErrorReset();
882 1 : EXPECT_EQ(gdal::min_element(v, 1, GDT_CFloat32, false, 0), 0);
883 1 : EXPECT_EQ(CPLGetLastErrorNo(), CPLE_NotSupported);
884 : }
885 : {
886 1 : CPLErrorReset();
887 1 : EXPECT_EQ(gdal::max_element(v, 1, GDT_CFloat32, false, 0), 0);
888 1 : EXPECT_EQ(CPLGetLastErrorNo(), CPLE_NotSupported);
889 : }
890 : {
891 1 : CPLErrorReset();
892 1 : auto [idx_min, idx_max] =
893 1 : gdal::minmax_element(v, 1, GDT_CFloat32, false, 0);
894 1 : EXPECT_EQ(idx_min, 0);
895 1 : EXPECT_EQ(idx_max, 0);
896 1 : EXPECT_EQ(CPLGetLastErrorNo(), CPLE_NotSupported);
897 : }
898 1 : }
899 :
900 : } // namespace
|