LCOV - code coverage report
Current view: top level - autotest/cpp - testcopywords.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 887 896 99.0 %
Date: 2026-05-29 18:47:21 Functions: 539 655 82.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Test GDALCopyWords().
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009-2011, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_conv.h"
      14             : #include "cpl_float.h"
      15             : #include "gdal.h"
      16             : 
      17             : #include <cmath>
      18             : #include <cstdint>
      19             : #include <iostream>
      20             : #include <limits>
      21             : #include <type_traits>
      22             : 
      23             : #include "gtest_include.h"
      24             : 
      25             : namespace
      26             : {
      27             : 
      28             : // ---------------------------------------------------------------------------
      29             : 
      30             : template <class OutType, class CT1, class CT2>
      31       63606 : void AssertRes(GDALDataType intype, CT1 inval, GDALDataType outtype,
      32             :                CT2 expected_outval, OutType outval, int numLine)
      33             : {
      34       66344 :     if (static_cast<double>(expected_outval) == static_cast<double>(outval) ||
      35        2738 :         (std::isnan(static_cast<double>(expected_outval)) &&
      36         201 :          std::isnan(static_cast<double>(outval))))
      37             :     {
      38             :         // ok
      39             :     }
      40             :     else
      41             :     {
      42        2336 :         EXPECT_NEAR((double)outval, (double)expected_outval, 1.0)
      43           0 :             << "Test failed at line " << numLine
      44           0 :             << " (intype=" << GDALGetDataTypeName(intype)
      45           0 :             << ",inval=" << (double)inval
      46           0 :             << ",outtype=" << GDALGetDataTypeName(outtype) << ",got "
      47           0 :             << (double)outval << " expected  " << expected_outval;
      48             :     }
      49       63606 : }
      50             : 
      51             : #define MY_EXPECT(intype, inval, outtype, expected_outval, outval)             \
      52             :     AssertRes(intype, inval, outtype, expected_outval, outval, numLine)
      53             : 
      54             : class TestCopyWords : public ::testing::Test
      55             : {
      56             :   protected:
      57         138 :     void SetUp() override
      58             :     {
      59         138 :         pIn = (GByte *)malloc(2048);
      60         138 :         pOut = (GByte *)malloc(2048);
      61         138 :     }
      62             : 
      63         138 :     void TearDown() override
      64             :     {
      65             : 
      66         138 :         free(pIn);
      67         138 :         free(pOut);
      68         138 :     }
      69             : 
      70             :     GByte *pIn;
      71             :     GByte *pOut;
      72             : 
      73             :     template <class InType, class OutType, class ConstantType>
      74        1085 :     void Test(GDALDataType intype, ConstantType inval, ConstantType invali,
      75             :               GDALDataType outtype, ConstantType outval, ConstantType outvali,
      76             :               int numLine)
      77             :     {
      78        1085 :         memset(pIn, 0xff, 1024);
      79        1085 :         memset(pOut, 0xff, 1024);
      80             : 
      81        1085 :         *(InType *)(pIn) = (InType)inval;
      82        1085 :         *(InType *)(pIn + 32) = (InType)inval;
      83        1085 :         if (GDALDataTypeIsComplex(intype))
      84             :         {
      85         250 :             ((InType *)(pIn))[1] = (InType)invali;
      86         250 :             ((InType *)(pIn + 32))[1] = (InType)invali;
      87             :         }
      88             : 
      89             :         /* Test positive offsets */
      90        1085 :         GDALCopyWords(pIn, intype, 32, pOut, outtype, 32, 2);
      91             : 
      92             :         /* Test negative offsets */
      93        1085 :         GDALCopyWords(pIn + 32, intype, -32, pOut + 1024 - 16, outtype, -32, 2);
      94             : 
      95        1085 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut));
      96        1085 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut + 32));
      97        1085 :         MY_EXPECT(intype, inval, outtype, outval,
      98             :                   *(OutType *)(pOut + 1024 - 16));
      99        1085 :         MY_EXPECT(intype, inval, outtype, outval,
     100             :                   *(OutType *)(pOut + 1024 - 16 - 32));
     101             : 
     102        1085 :         if (GDALDataTypeIsComplex(outtype))
     103             :         {
     104         312 :             MY_EXPECT(intype, invali, outtype, outvali, ((OutType *)(pOut))[1]);
     105         312 :             MY_EXPECT(intype, invali, outtype, outvali,
     106             :                       ((OutType *)(pOut + 32))[1]);
     107             : 
     108         312 :             MY_EXPECT(intype, invali, outtype, outvali,
     109             :                       ((OutType *)(pOut + 1024 - 16))[1]);
     110         312 :             MY_EXPECT(intype, invali, outtype, outvali,
     111             :                       ((OutType *)(pOut + 1024 - 16 - 32))[1]);
     112             :         }
     113             :         else
     114             :         {
     115         773 :             constexpr int N = 32 + 31;
     116       49472 :             for (int i = 0; i < N; ++i)
     117             :             {
     118       48699 :                 *(InType *)(pIn + i * GDALGetDataTypeSizeBytes(intype)) =
     119       10017 :                     (InType)inval;
     120             :             }
     121             : 
     122             :             /* Test packed offsets */
     123         773 :             GDALCopyWords(pIn, intype, GDALGetDataTypeSizeBytes(intype), pOut,
     124             :                           outtype, GDALGetDataTypeSizeBytes(outtype), N);
     125             : 
     126       49472 :             for (int i = 0; i < N; ++i)
     127             :             {
     128       48699 :                 MY_EXPECT(
     129             :                     intype, inval, outtype, outval,
     130             :                     *(OutType *)(pOut + i * GDALGetDataTypeSizeBytes(outtype)));
     131             :             }
     132             :         }
     133        1085 :     }
     134             : 
     135             :     template <class InType, class ConstantType>
     136        1085 :     void FromR_2(GDALDataType intype, ConstantType inval, ConstantType invali,
     137             :                  GDALDataType outtype, ConstantType outval,
     138             :                  ConstantType outvali, int numLine)
     139             :     {
     140        1085 :         if (outtype == GDT_Byte)
     141          81 :             Test<InType, GByte, ConstantType>(intype, inval, invali, outtype,
     142             :                                               outval, outvali, numLine);
     143        1004 :         else if (outtype == GDT_Int8)
     144          65 :             Test<InType, GInt8, ConstantType>(intype, inval, invali, outtype,
     145             :                                               outval, outvali, numLine);
     146         939 :         else if (outtype == GDT_Int16)
     147          96 :             Test<InType, GInt16, ConstantType>(intype, inval, invali, outtype,
     148             :                                                outval, outvali, numLine);
     149         843 :         else if (outtype == GDT_UInt16)
     150          75 :             Test<InType, GUInt16, ConstantType>(intype, inval, invali, outtype,
     151             :                                                 outval, outvali, numLine);
     152         768 :         else if (outtype == GDT_Int32)
     153         101 :             Test<InType, GInt32, ConstantType>(intype, inval, invali, outtype,
     154             :                                                outval, outvali, numLine);
     155         667 :         else if (outtype == GDT_UInt32)
     156          76 :             Test<InType, GUInt32, ConstantType>(intype, inval, invali, outtype,
     157             :                                                 outval, outvali, numLine);
     158         591 :         else if (outtype == GDT_Int64)
     159          75 :             Test<InType, std::int64_t, ConstantType>(
     160             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     161         516 :         else if (outtype == GDT_UInt64)
     162          54 :             Test<InType, std::uint64_t, ConstantType>(
     163             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     164         462 :         else if (outtype == GDT_Float16)
     165          39 :             Test<InType, GFloat16, ConstantType>(intype, inval, invali, outtype,
     166             :                                                  outval, outvali, numLine);
     167         423 :         else if (outtype == GDT_Float32)
     168          57 :             Test<InType, float, ConstantType>(intype, inval, invali, outtype,
     169             :                                               outval, outvali, numLine);
     170         366 :         else if (outtype == GDT_Float64)
     171          54 :             Test<InType, double, ConstantType>(intype, inval, invali, outtype,
     172             :                                                outval, outvali, numLine);
     173         312 :         else if (outtype == GDT_CInt16)
     174          91 :             Test<InType, GInt16, ConstantType>(intype, inval, invali, outtype,
     175             :                                                outval, outvali, numLine);
     176         221 :         else if (outtype == GDT_CInt32)
     177          91 :             Test<InType, GInt32, ConstantType>(intype, inval, invali, outtype,
     178             :                                                outval, outvali, numLine);
     179         130 :         else if (outtype == GDT_CFloat16)
     180          28 :             Test<InType, GFloat16, ConstantType>(intype, inval, invali, outtype,
     181             :                                                  outval, outvali, numLine);
     182         102 :         else if (outtype == GDT_CFloat32)
     183          51 :             Test<InType, float, ConstantType>(intype, inval, invali, outtype,
     184             :                                               outval, outvali, numLine);
     185          51 :         else if (outtype == GDT_CFloat64)
     186          51 :             Test<InType, double, ConstantType>(intype, inval, invali, outtype,
     187             :                                                outval, outvali, numLine);
     188        1085 :     }
     189             : 
     190             :     template <class ConstantType>
     191        1085 :     void FromR(GDALDataType intype, ConstantType inval, ConstantType invali,
     192             :                GDALDataType outtype, ConstantType outval, ConstantType outvali,
     193             :                int numLine)
     194             :     {
     195        1085 :         if (intype == GDT_Byte)
     196          47 :             FromR_2<GByte, ConstantType>(intype, inval, invali, outtype, outval,
     197             :                                          outvali, numLine);
     198        1038 :         else if (intype == GDT_Int8)
     199          46 :             FromR_2<GInt8, ConstantType>(intype, inval, invali, outtype, outval,
     200             :                                          outvali, numLine);
     201         992 :         else if (intype == GDT_Int16)
     202          42 :             FromR_2<GInt16, ConstantType>(intype, inval, invali, outtype,
     203             :                                           outval, outvali, numLine);
     204         950 :         else if (intype == GDT_UInt16)
     205          45 :             FromR_2<GUInt16, ConstantType>(intype, inval, invali, outtype,
     206             :                                            outval, outvali, numLine);
     207         905 :         else if (intype == GDT_Int32)
     208          57 :             FromR_2<GInt32, ConstantType>(intype, inval, invali, outtype,
     209             :                                           outval, outvali, numLine);
     210         848 :         else if (intype == GDT_UInt32)
     211          49 :             FromR_2<GUInt32, ConstantType>(intype, inval, invali, outtype,
     212             :                                            outval, outvali, numLine);
     213         799 :         else if (intype == GDT_Int64)
     214          39 :             FromR_2<std::int64_t, ConstantType>(intype, inval, invali, outtype,
     215             :                                                 outval, outvali, numLine);
     216         760 :         else if (intype == GDT_UInt64)
     217          45 :             FromR_2<std::uint64_t, ConstantType>(intype, inval, invali, outtype,
     218             :                                                  outval, outvali, numLine);
     219         715 :         else if (intype == GDT_Float16)
     220         135 :             FromR_2<GFloat16, ConstantType>(intype, inval, invali, outtype,
     221             :                                             outval, outvali, numLine);
     222         580 :         else if (intype == GDT_Float32)
     223         166 :             FromR_2<float, ConstantType>(intype, inval, invali, outtype, outval,
     224             :                                          outvali, numLine);
     225         414 :         else if (intype == GDT_Float64)
     226         164 :             FromR_2<double, ConstantType>(intype, inval, invali, outtype,
     227             :                                           outval, outvali, numLine);
     228         250 :         else if (intype == GDT_CInt16)
     229          38 :             FromR_2<GInt16, ConstantType>(intype, inval, invali, outtype,
     230             :                                           outval, outvali, numLine);
     231         212 :         else if (intype == GDT_CInt32)
     232          38 :             FromR_2<GInt32, ConstantType>(intype, inval, invali, outtype,
     233             :                                           outval, outvali, numLine);
     234         174 :         else if (intype == GDT_CFloat16)
     235          58 :             FromR_2<GFloat16, ConstantType>(intype, inval, invali, outtype,
     236             :                                             outval, outvali, numLine);
     237         116 :         else if (intype == GDT_CFloat32)
     238          58 :             FromR_2<float, ConstantType>(intype, inval, invali, outtype, outval,
     239             :                                          outvali, numLine);
     240          58 :         else if (intype == GDT_CFloat64)
     241          58 :             FromR_2<double, ConstantType>(intype, inval, invali, outtype,
     242             :                                           outval, outvali, numLine);
     243        1085 :     }
     244             : };
     245             : 
     246             : #define FROM_R(intype, inval, outtype, outval)                                 \
     247             :     FromR<GIntBig>(intype, inval, 0, outtype, outval, 0, __LINE__)
     248             : #define FROM_R_F(intype, inval, outtype, outval)                               \
     249             :     FromR<double>(intype, inval, 0, outtype, outval, 0, __LINE__)
     250             : 
     251             : #define FROM_C(intype, inval, invali, outtype, outval, outvali)                \
     252             :     FromR<GIntBig>(intype, inval, invali, outtype, outval, outvali, __LINE__)
     253             : #define FROM_C_F(intype, inval, invali, outtype, outval, outvali)              \
     254             :     FromR<double>(intype, inval, invali, outtype, outval, outvali, __LINE__)
     255             : 
     256             : #define IS_UNSIGNED(x)                                                         \
     257             :     (x == GDT_Byte || x == GDT_UInt16 || x == GDT_UInt32 || x == GDT_UInt64)
     258             : #define IS_FLOAT(x)                                                            \
     259             :     (x == GDT_Float16 || x == GDT_Float32 || x == GDT_Float64 ||               \
     260             :      x == GDT_CFloat16 || x == GDT_CFloat32 || x == GDT_CFloat64)
     261             : 
     262             : #define CST_3000000000 (((GIntBig)3000) * 1000 * 1000)
     263             : #define CST_5000000000 (((GIntBig)5000) * 1000 * 1000)
     264             : 
     265           4 : TEST_F(TestCopyWords, GDT_Byte)
     266             : {
     267             :     /* GDT_Byte */
     268          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     269          16 :          outtype = (GDALDataType)(outtype + 1))
     270             :     {
     271          16 :         FROM_R(GDT_Byte, 0, outtype, 0);
     272          16 :         FROM_R(GDT_Byte, 127, outtype, 127);
     273          16 :         if (outtype != GDT_Int8)
     274          15 :             FROM_R(GDT_Byte, 255, outtype, 255);
     275             :     }
     276             : 
     277          18 :     for (int i = 0; i < 17; i++)
     278             :     {
     279          17 :         pIn[i] = (GByte)i;
     280             :     }
     281             : 
     282           1 :     memset(pOut, 0xff, 128);
     283           1 :     GDALCopyWords(pIn, GDT_Byte, 1, pOut, GDT_Int32, 4, 17);
     284          18 :     for (int i = 0; i < 17; i++)
     285             :     {
     286          17 :         AssertRes(GDT_Byte, i, GDT_Int32, i, ((int *)pOut)[i], __LINE__);
     287             :     }
     288             : 
     289           1 :     memset(pOut, 0xff, 128);
     290           1 :     GDALCopyWords(pIn, GDT_Byte, 1, pOut, GDT_Float32, 4, 17);
     291          18 :     for (int i = 0; i < 17; i++)
     292             :     {
     293          17 :         AssertRes(GDT_Byte, i, GDT_Float32, i, ((float *)pOut)[i], __LINE__);
     294             :     }
     295           1 : }
     296             : 
     297           4 : TEST_F(TestCopyWords, GDT_Int8)
     298             : {
     299             :     /* GDT_Int8 */
     300           1 :     FROM_R(GDT_Int8, -128, GDT_Byte, 0);    /* clamp */
     301           1 :     FROM_R(GDT_Int8, -128, GDT_Int8, -128); /* clamp */
     302           1 :     FROM_R(GDT_Int8, -128, GDT_Int16, -128);
     303           1 :     FROM_R(GDT_Int8, -128, GDT_UInt16, 0); /* clamp */
     304           1 :     FROM_R(GDT_Int8, -128, GDT_Int32, -128);
     305           1 :     FROM_R(GDT_Int8, -128, GDT_UInt32, 0); /* clamp */
     306           1 :     FROM_R(GDT_Int8, -128, GDT_Int64, -128);
     307           1 :     FROM_R(GDT_Int8, -128, GDT_UInt64, 0); /* clamp */
     308           1 :     FROM_R(GDT_Int8, -128, GDT_Float16, -128);
     309           1 :     FROM_R(GDT_Int8, -128, GDT_Float32, -128);
     310           1 :     FROM_R(GDT_Int8, -128, GDT_Float64, -128);
     311           1 :     FROM_R(GDT_Int8, -128, GDT_CInt16, -128);
     312           1 :     FROM_R(GDT_Int8, -128, GDT_CInt32, -128);
     313           1 :     FROM_R(GDT_Int8, -128, GDT_CFloat16, -128);
     314           1 :     FROM_R(GDT_Int8, -128, GDT_CFloat32, -128);
     315           1 :     FROM_R(GDT_Int8, -128, GDT_CFloat64, -128);
     316          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     317          16 :          outtype = (GDALDataType)(outtype + 1))
     318             :     {
     319          16 :         FROM_R(GDT_Int8, 127, outtype, 127);
     320             :     }
     321             : 
     322           1 :     FROM_R(GDT_Int8, 127, GDT_Byte, 127);
     323           1 :     FROM_R(GDT_Int8, 127, GDT_Int8, 127);
     324           1 :     FROM_R(GDT_Int8, 127, GDT_Int16, 127);
     325           1 :     FROM_R(GDT_Int8, 127, GDT_UInt16, 127);
     326           1 :     FROM_R(GDT_Int8, 127, GDT_Int32, 127);
     327           1 :     FROM_R(GDT_Int8, 127, GDT_UInt32, 127);
     328           1 :     FROM_R(GDT_Int8, 127, GDT_Int64, 127);
     329           1 :     FROM_R(GDT_Int8, 127, GDT_UInt64, 127);
     330           1 :     FROM_R(GDT_Int8, 127, GDT_Float32, 127);
     331           1 :     FROM_R(GDT_Int8, 127, GDT_Float64, 127);
     332           1 :     FROM_R(GDT_Int8, 127, GDT_CInt16, 127);
     333           1 :     FROM_R(GDT_Int8, 127, GDT_CInt32, 127);
     334           1 :     FROM_R(GDT_Int8, 127, GDT_CFloat32, 127);
     335           1 :     FROM_R(GDT_Int8, 127, GDT_CFloat64, 127);
     336           1 : }
     337             : 
     338           4 : TEST_F(TestCopyWords, GDT_Int16)
     339             : {
     340             :     /* GDT_Int16 */
     341           1 :     FROM_R(GDT_Int16, -32000, GDT_Byte, 0); /* clamp */
     342           1 :     FROM_R(GDT_Int16, -32000, GDT_Int16, -32000);
     343           1 :     FROM_R(GDT_Int16, -32000, GDT_UInt16, 0); /* clamp */
     344           1 :     FROM_R(GDT_Int16, -32000, GDT_Int32, -32000);
     345           1 :     FROM_R(GDT_Int16, -32000, GDT_UInt32, 0); /* clamp */
     346           1 :     FROM_R(GDT_Int16, -32000, GDT_Int64, -32000);
     347           1 :     FROM_R(GDT_Int16, -32000, GDT_UInt64, 0); /* clamp */
     348           1 :     FROM_R(GDT_Int16, -32000, GDT_Float32, -32000);
     349           1 :     FROM_R(GDT_Int16, -32000, GDT_Float64, -32000);
     350           1 :     FROM_R(GDT_Int16, -32000, GDT_CInt16, -32000);
     351           1 :     FROM_R(GDT_Int16, -32000, GDT_CInt32, -32000);
     352           1 :     FROM_R(GDT_Int16, -32000, GDT_CFloat32, -32000);
     353           1 :     FROM_R(GDT_Int16, -32000, GDT_CFloat64, -32000);
     354          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     355          16 :          outtype = (GDALDataType)(outtype + 1))
     356             :     {
     357          16 :         FROM_R(GDT_Int16, 127, outtype, 127);
     358             :     }
     359             : 
     360           1 :     FROM_R(GDT_Int16, 32000, GDT_Byte, 255); /* clamp */
     361           1 :     FROM_R(GDT_Int16, 32000, GDT_Int16, 32000);
     362           1 :     FROM_R(GDT_Int16, 32000, GDT_UInt16, 32000);
     363           1 :     FROM_R(GDT_Int16, 32000, GDT_Int32, 32000);
     364           1 :     FROM_R(GDT_Int16, 32000, GDT_UInt32, 32000);
     365           1 :     FROM_R(GDT_Int16, 32000, GDT_Int64, 32000);
     366           1 :     FROM_R(GDT_Int16, 32000, GDT_UInt64, 32000);
     367           1 :     FROM_R(GDT_Int16, 32000, GDT_Float32, 32000);
     368           1 :     FROM_R(GDT_Int16, 32000, GDT_Float64, 32000);
     369           1 :     FROM_R(GDT_Int16, 32000, GDT_CInt16, 32000);
     370           1 :     FROM_R(GDT_Int16, 32000, GDT_CInt32, 32000);
     371           1 :     FROM_R(GDT_Int16, 32000, GDT_CFloat32, 32000);
     372           1 :     FROM_R(GDT_Int16, 32000, GDT_CFloat64, 32000);
     373           1 : }
     374             : 
     375           4 : TEST_F(TestCopyWords, GDT_UInt16)
     376             : {
     377             :     /* GDT_UInt16 */
     378          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     379          16 :          outtype = (GDALDataType)(outtype + 1))
     380             :     {
     381          16 :         FROM_R(GDT_UInt16, 0, outtype, 0);
     382          16 :         FROM_R(GDT_UInt16, 127, outtype, 127);
     383             :     }
     384             : 
     385           1 :     FROM_R(GDT_UInt16, 65000, GDT_Byte, 255);    /* clamp */
     386           1 :     FROM_R(GDT_UInt16, 65000, GDT_Int16, 32767); /* clamp */
     387           1 :     FROM_R(GDT_UInt16, 65000, GDT_UInt16, 65000);
     388           1 :     FROM_R(GDT_UInt16, 65000, GDT_Int32, 65000);
     389           1 :     FROM_R(GDT_UInt16, 65000, GDT_UInt32, 65000);
     390           1 :     FROM_R(GDT_UInt16, 65000, GDT_Int64, 65000);
     391           1 :     FROM_R(GDT_UInt16, 65000, GDT_UInt64, 65000);
     392           1 :     FROM_R(GDT_UInt16, 65000, GDT_Float32, 65000);
     393           1 :     FROM_R(GDT_UInt16, 65000, GDT_Float64, 65000);
     394           1 :     FROM_R(GDT_UInt16, 65000, GDT_CInt16, 32767); /* clamp */
     395           1 :     FROM_R(GDT_UInt16, 65000, GDT_CInt32, 65000);
     396           1 :     FROM_R(GDT_UInt16, 65000, GDT_CFloat32, 65000);
     397           1 :     FROM_R(GDT_UInt16, 65000, GDT_CFloat64, 65000);
     398           1 : }
     399             : 
     400           4 : TEST_F(TestCopyWords, GDT_Int32)
     401             : {
     402             :     /* GDT_Int32 */
     403           1 :     FROM_R(GDT_Int32, -33000, GDT_Byte, 0);       /* clamp */
     404           1 :     FROM_R(GDT_Int32, -33000, GDT_Int16, -32768); /* clamp */
     405           1 :     FROM_R(GDT_Int32, -33000, GDT_UInt16, 0);     /* clamp */
     406           1 :     FROM_R(GDT_Int32, -33000, GDT_Int32, -33000);
     407           1 :     FROM_R(GDT_Int32, -33000, GDT_UInt32, 0); /* clamp */
     408           1 :     FROM_R(GDT_Int32, -33000, GDT_Int64, -33000);
     409           1 :     FROM_R(GDT_Int32, -33000, GDT_UInt64, 0); /* clamp */
     410           1 :     FROM_R(GDT_Int32, -33000, GDT_Float32, -33000);
     411           1 :     FROM_R(GDT_Int32, -33000, GDT_Float64, -33000);
     412           1 :     FROM_R(GDT_Int32, -33000, GDT_CInt16, -32768); /* clamp */
     413           1 :     FROM_R(GDT_Int32, -33000, GDT_CInt32, -33000);
     414           1 :     FROM_R(GDT_Int32, -33000, GDT_CFloat32, -33000);
     415           1 :     FROM_R(GDT_Int32, -33000, GDT_CFloat64, -33000);
     416          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     417          16 :          outtype = (GDALDataType)(outtype + 1))
     418             :     {
     419          16 :         FROM_R(GDT_Int32, 127, outtype, 127);
     420             :     }
     421             : 
     422           1 :     FROM_R(GDT_Int32, 67000, GDT_Byte, 255);     /* clamp */
     423           1 :     FROM_R(GDT_Int32, 67000, GDT_Int16, 32767);  /* clamp */
     424           1 :     FROM_R(GDT_Int32, 67000, GDT_UInt16, 65535); /* clamp */
     425           1 :     FROM_R(GDT_Int32, 67000, GDT_Int32, 67000);
     426           1 :     FROM_R(GDT_Int32, 67000, GDT_UInt32, 67000);
     427           1 :     FROM_R(GDT_Int32, 67000, GDT_Int64, 67000);
     428           1 :     FROM_R(GDT_Int32, 67000, GDT_UInt64, 67000);
     429           1 :     FROM_R(GDT_Int32, 67000, GDT_Float32, 67000);
     430           1 :     FROM_R(GDT_Int32, 67000, GDT_Float64, 67000);
     431           1 :     FROM_R(GDT_Int32, 67000, GDT_CInt16, 32767); /* clamp */
     432           1 :     FROM_R(GDT_Int32, 67000, GDT_CInt32, 67000);
     433           1 :     FROM_R(GDT_Int32, 67000, GDT_CFloat32, 67000);
     434           1 :     FROM_R(GDT_Int32, 67000, GDT_CFloat64, 67000);
     435             : 
     436           1 :     FROM_R(GDT_Int32, INT_MIN, GDT_Int32, INT_MIN);
     437           1 :     FROM_R(GDT_Int32, INT_MIN + 1, GDT_Int32, INT_MIN + 1);
     438           1 :     FROM_R(GDT_Int32, -1, GDT_Int32, -1);
     439           1 :     FROM_R(GDT_Int32, 1, GDT_Int32, 1);
     440           1 :     FROM_R(GDT_Int32, INT_MAX - 1, GDT_Int32, INT_MAX - 1);
     441           1 :     FROM_R(GDT_Int32, INT_MAX, GDT_Int32, INT_MAX);
     442             : 
     443           1 :     FROM_R(GDT_Int32, INT_MIN, GDT_UInt32, 0);
     444           1 :     FROM_R(GDT_Int32, INT_MIN + 1, GDT_UInt32, 0);
     445           1 :     FROM_R(GDT_Int32, -1, GDT_UInt32, 0);
     446           1 :     FROM_R(GDT_Int32, 1, GDT_UInt32, 1);
     447           1 :     FROM_R(GDT_Int32, INT_MAX - 1, GDT_UInt32, INT_MAX - 1);
     448           1 :     FROM_R(GDT_Int32, INT_MAX, GDT_UInt32, INT_MAX);
     449           1 : }
     450             : 
     451           4 : TEST_F(TestCopyWords, GDT_UInt32)
     452             : {
     453             :     /* GDT_UInt32 */
     454          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     455          16 :          outtype = (GDALDataType)(outtype + 1))
     456             :     {
     457          16 :         FROM_R(GDT_UInt32, 0, outtype, 0);
     458          16 :         FROM_R(GDT_UInt32, 127, outtype, 127);
     459             :     }
     460             : 
     461           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Byte, 255);      /* clamp */
     462           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int16, 32767);   /* clamp */
     463           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt16, 65535);  /* clamp */
     464           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int32, INT_MAX); /* clamp */
     465           1 :     FROM_R(GDT_UInt32, INT_MAX - 1, GDT_Int32, INT_MAX - 1);
     466           1 :     FROM_R(GDT_UInt32, INT_MAX, GDT_Int32, INT_MAX);
     467           1 :     FROM_R(GDT_UInt32, 1U << 31U, GDT_Int32, INT_MAX);  /* clamp */
     468           1 :     FROM_R(GDT_UInt32, UINT32_MAX, GDT_Int32, INT_MAX); /* clamp */
     469           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt32, 3000000000U);
     470           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int64, 3000000000U);
     471           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt64, 3000000000U);
     472           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Float32, 3000000000U);
     473           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Float64, 3000000000U);
     474           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CInt16, 32767);   /* clamp */
     475           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CInt32, INT_MAX); /* clamp */
     476           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CFloat32, 3000000000U);
     477           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CFloat64, 3000000000U);
     478           1 : }
     479             : 
     480           4 : TEST_F(TestCopyWords, check_GDT_Int64)
     481             : {
     482             :     /* GDT_Int64 */
     483           1 :     FROM_R(GDT_Int64, -33000, GDT_Byte, 0);       /* clamp */
     484           1 :     FROM_R(GDT_Int64, -33000, GDT_Int16, -32768); /* clamp */
     485           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt16, 0);     /* clamp */
     486           1 :     FROM_R(GDT_Int64, -33000, GDT_Int32, -33000);
     487           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt32, 0); /* clamp */
     488           1 :     FROM_R(GDT_Int64, -33000, GDT_Int64, -33000);
     489           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt64, 0); /* clamp */
     490           1 :     FROM_R(GDT_Int64, -33000, GDT_Float32, -33000);
     491           1 :     FROM_R(GDT_Int64, -33000, GDT_Float64, -33000);
     492           1 :     FROM_R(GDT_Int64, -33000, GDT_CInt16, -32768); /* clamp */
     493           1 :     FROM_R(GDT_Int64, -33000, GDT_CInt32, -33000);
     494           1 :     FROM_R(GDT_Int64, -33000, GDT_CFloat32, -33000);
     495           1 :     FROM_R(GDT_Int64, -33000, GDT_CFloat64, -33000);
     496          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     497          16 :          outtype = (GDALDataType)(outtype + 1))
     498             :     {
     499          16 :         FROM_R(GDT_Int64, 127, outtype, 127);
     500             :     }
     501             : 
     502           1 :     FROM_R(GDT_Int64, 67000, GDT_Byte, 255);     /* clamp */
     503           1 :     FROM_R(GDT_Int64, 67000, GDT_Int16, 32767);  /* clamp */
     504           1 :     FROM_R(GDT_Int32, 67000, GDT_UInt16, 65535); /* clamp */
     505           1 :     FROM_R(GDT_Int32, 67000, GDT_Int32, 67000);
     506           1 :     FROM_R(GDT_Int64, 67000, GDT_UInt32, 67000);
     507           1 :     FROM_R(GDT_Int32, 67000, GDT_Int64, 67000);
     508           1 :     FROM_R(GDT_Int64, 67000, GDT_UInt64, 67000);
     509           1 :     FROM_R(GDT_Int64, 67000, GDT_Float32, 67000);
     510           1 :     FROM_R(GDT_Int64, 67000, GDT_Float64, 67000);
     511           1 :     FROM_R(GDT_Int64, 67000, GDT_CInt16, 32767); /* clamp */
     512           1 :     FROM_R(GDT_Int64, 67000, GDT_CInt32, 67000);
     513           1 :     FROM_R(GDT_Int64, 67000, GDT_CFloat32, 67000);
     514           1 :     FROM_R(GDT_Int64, 67000, GDT_CFloat64, 67000);
     515           1 : }
     516             : 
     517           4 : TEST_F(TestCopyWords, GDT_UInt64)
     518             : {
     519             :     /* GDT_UInt64 */
     520          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     521          16 :          outtype = (GDALDataType)(outtype + 1))
     522             :     {
     523          16 :         FROM_R(GDT_UInt64, 0, outtype, 0);
     524          16 :         FROM_R(GDT_UInt64, 127, outtype, 127);
     525             :     }
     526             : 
     527           1 :     std::uint64_t nVal = static_cast<std::uint64_t>(3000000000) * 1000;
     528           1 :     FROM_R(GDT_UInt64, nVal, GDT_Byte, 255);           /* clamp */
     529           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int16, 32767);        /* clamp */
     530           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt16, 65535);       /* clamp */
     531           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int32, 2147483647);   /* clamp */
     532           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt32, 4294967295U); /* clamp */
     533           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int64, nVal);
     534           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt64, nVal);
     535           1 :     FROM_R(GDT_UInt64, nVal, GDT_Float32,
     536             :            static_cast<uint64_t>(static_cast<float>(nVal)));
     537           1 :     FROM_R(GDT_UInt64, nVal, GDT_Float64, nVal);
     538           1 :     FROM_R(GDT_UInt64, nVal, GDT_CInt16, 32767);      /* clamp */
     539           1 :     FROM_R(GDT_UInt64, nVal, GDT_CInt32, 2147483647); /* clamp */
     540           1 :     FROM_R(GDT_UInt64, nVal, GDT_CFloat32,
     541             :            static_cast<uint64_t>(static_cast<float>(nVal)));
     542           1 :     FROM_R(GDT_UInt64, nVal, GDT_CFloat64, nVal);
     543           1 : }
     544             : 
     545           4 : TEST_F(TestCopyWords, GDT_Float64)
     546             : {
     547           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::max(), GDT_Float32,
     548             :              std::numeric_limits<double>::infinity());
     549           1 :     FROM_R_F(GDT_Float64, -std::numeric_limits<double>::max(), GDT_Float32,
     550             :              -std::numeric_limits<double>::infinity());
     551           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::quiet_NaN(), GDT_Float32,
     552             :              std::numeric_limits<double>::quiet_NaN());
     553           1 : }
     554             : 
     555           4 : TEST_F(TestCopyWords, GDT_Float16only)
     556             : {
     557           1 :     GDALDataType intype = GDT_Float16;
     558          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     559          16 :          outtype = (GDALDataType)(outtype + 1))
     560             :     {
     561          16 :         if (IS_FLOAT(outtype))
     562             :         {
     563           6 :             FROM_R_F(intype, 127.1, outtype, 127.1);
     564           6 :             FROM_R_F(intype, -127.1, outtype, -127.1);
     565             :         }
     566             :         else
     567             :         {
     568          10 :             FROM_R_F(intype, 125.1, outtype, 125);
     569          10 :             FROM_R_F(intype, 125.9, outtype, 126);
     570             : 
     571          10 :             FROM_R_F(intype, 0.4, outtype, 0);
     572          10 :             FROM_R_F(intype, 0.5, outtype,
     573             :                      1); /* We could argue how to do this rounding */
     574          10 :             FROM_R_F(intype, 0.6, outtype, 1);
     575          10 :             FROM_R_F(intype, 126.5, outtype,
     576             :                      127); /* We could argue how to do this rounding */
     577             : 
     578          10 :             if (!IS_UNSIGNED(outtype))
     579             :             {
     580           6 :                 FROM_R_F(intype, -125.9, outtype, -126);
     581           6 :                 FROM_R_F(intype, -127.1, outtype, -127);
     582             : 
     583           6 :                 FROM_R_F(intype, -0.4, outtype, 0);
     584           6 :                 FROM_R_F(intype, -0.5, outtype,
     585             :                          -1); /* We could argue how to do this rounding */
     586           6 :                 FROM_R_F(intype, -0.6, outtype, -1);
     587           6 :                 FROM_R_F(intype, -127.5, outtype,
     588             :                          -128); /* We could argue how to do this rounding */
     589             :             }
     590             :         }
     591             :     }
     592           1 :     FROM_R(intype, -30000, GDT_Byte, 0);
     593           1 :     FROM_R(intype, -32768, GDT_Byte, 0);
     594           1 :     FROM_R(intype, -1, GDT_Byte, 0);
     595           1 :     FROM_R(intype, 256, GDT_Byte, 255);
     596           1 :     FROM_R(intype, 30000, GDT_Byte, 255);
     597           1 :     FROM_R(intype, -330000, GDT_Int16, -32768);
     598           1 :     FROM_R(intype, -33000, GDT_Int16, -32768);
     599           1 :     FROM_R(intype, 33000, GDT_Int16, 32767);
     600           1 :     FROM_R(intype, -33000, GDT_UInt16, 0);
     601           1 :     FROM_R(intype, -1, GDT_UInt16, 0);
     602           1 :     FROM_R(intype, 60000, GDT_UInt16, 60000);
     603           1 :     FROM_R(intype, -33000, GDT_Int32, -32992);
     604           1 :     FROM_R(intype, 33000, GDT_Int32, 32992);
     605           1 :     FROM_R(intype, -1, GDT_UInt32, 0);
     606           1 :     FROM_R(intype, 60000, GDT_UInt32, 60000U);
     607           1 :     FROM_R(intype, 33000, GDT_Float32, 32992);
     608           1 :     FROM_R(intype, -33000, GDT_Float32, -32992);
     609           1 :     FROM_R(intype, 33000, GDT_Float64, 32992);
     610           1 :     FROM_R(intype, -33000, GDT_Float64, -32992);
     611           1 :     FROM_R(intype, -33000, GDT_CInt16, -32768);
     612           1 :     FROM_R(intype, 33000, GDT_CInt16, 32767);
     613           1 :     FROM_R(intype, -33000, GDT_CInt32, -32992);
     614           1 :     FROM_R(intype, 33000, GDT_CInt32, 32992);
     615           1 :     FROM_R(intype, 33000, GDT_CFloat32, 32992);
     616           1 :     FROM_R(intype, -33000, GDT_CFloat32, -32992);
     617           1 :     FROM_R(intype, 33000, GDT_CFloat64, 32992);
     618           1 :     FROM_R(intype, -33000, GDT_CFloat64, -32992);
     619             : 
     620           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::min(), GDT_Float16, 0);
     621           1 :     FROM_R_F(GDT_Float32, -std::numeric_limits<float>::min(), GDT_Float16, 0);
     622             :     // smallest positive subnormal float16 number
     623           1 :     FROM_R_F(GDT_Float32, 0.000000059604645f, GDT_Float16, 0.000000059604645f);
     624           1 :     FROM_R_F(GDT_Float32, 65504.0f, GDT_Float16, 65504.0f);
     625           1 :     FROM_R_F(GDT_Float32, 65535.0f, GDT_Float16,
     626             :              std::numeric_limits<double>::infinity());
     627           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::max(), GDT_Float16,
     628             :              std::numeric_limits<double>::infinity());
     629           1 :     FROM_R_F(GDT_Float32, -std::numeric_limits<float>::max(), GDT_Float16,
     630             :              -std::numeric_limits<double>::infinity());
     631           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::quiet_NaN(), GDT_Float16,
     632             :              std::numeric_limits<double>::quiet_NaN());
     633             : 
     634           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::max(), GDT_Float16,
     635             :              std::numeric_limits<double>::infinity());
     636           1 :     FROM_R_F(GDT_Float64, -std::numeric_limits<double>::max(), GDT_Float16,
     637             :              -std::numeric_limits<double>::infinity());
     638           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::quiet_NaN(), GDT_Float16,
     639             :              std::numeric_limits<double>::quiet_NaN());
     640             : 
     641             :     // Float16 to Int64
     642             :     {
     643           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     644           1 :         int64_t out_value = 0;
     645           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     646           1 :         EXPECT_EQ(out_value, 0);
     647             :     }
     648             : 
     649             :     {
     650           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     651           1 :         int64_t out_value = 0;
     652           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     653           1 :         EXPECT_EQ(out_value, INT64_MIN);
     654             :     }
     655             : 
     656             :     {
     657           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::max();
     658           1 :         int64_t out_value = 0;
     659           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     660           1 :         EXPECT_EQ(out_value, -65504);
     661             :     }
     662             : 
     663             :     {
     664           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::max();
     665           1 :         int64_t out_value = 0;
     666           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     667           1 :         EXPECT_EQ(out_value, 65504);
     668             :     }
     669             : 
     670             :     {
     671           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::infinity();
     672           1 :         int64_t out_value = 0;
     673           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     674           1 :         EXPECT_EQ(out_value, INT64_MAX);
     675             :     }
     676             : 
     677             :     // Float16 to UInt64
     678             :     {
     679           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     680           1 :         uint64_t out_value = 0;
     681           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     682           1 :         EXPECT_EQ(out_value, 0);
     683             :     }
     684             : 
     685             :     {
     686           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     687           1 :         uint64_t out_value = 0;
     688           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     689           1 :         EXPECT_EQ(out_value, 0);
     690             :     }
     691             : 
     692             :     {
     693           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::max();
     694           1 :         uint64_t out_value = 0;
     695           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     696           1 :         EXPECT_EQ(out_value, 0);
     697             :     }
     698             : 
     699             :     {
     700           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::max();
     701           1 :         uint64_t out_value = 0;
     702           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     703           1 :         EXPECT_EQ(out_value, 65504);
     704             :     }
     705             : 
     706             :     {
     707           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::infinity();
     708           1 :         uint64_t out_value = 0;
     709           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     710           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     711             :     }
     712           1 : }
     713             : 
     714           4 : TEST_F(TestCopyWords, GDT_Float32and64)
     715             : {
     716             :     /* GDT_Float32 and GDT_Float64 */
     717           3 :     for (int i = 0; i < 2; i++)
     718             :     {
     719           2 :         const GDALDataType intype = (i == 0) ? GDT_Float32 : GDT_Float64;
     720          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     721          32 :              outtype = (GDALDataType)(outtype + 1))
     722             :         {
     723          32 :             if (IS_FLOAT(outtype))
     724             :             {
     725          12 :                 FROM_R_F(intype, 127.1, outtype, 127.1);
     726          12 :                 FROM_R_F(intype, -127.1, outtype, -127.1);
     727             :             }
     728             :             else
     729             :             {
     730          20 :                 FROM_R_F(intype, 125.1, outtype, 125);
     731          20 :                 FROM_R_F(intype, 125.9, outtype, 126);
     732             : 
     733          20 :                 FROM_R_F(intype, 0.4, outtype, 0);
     734          20 :                 FROM_R_F(intype, 0.5, outtype,
     735             :                          1); /* We could argue how to do this rounding */
     736          20 :                 FROM_R_F(intype, 0.6, outtype, 1);
     737          20 :                 FROM_R_F(intype, 126.5, outtype,
     738             :                          127); /* We could argue how to do this rounding */
     739             : 
     740          20 :                 if (!IS_UNSIGNED(outtype))
     741             :                 {
     742          12 :                     FROM_R_F(intype, -125.9, outtype, -126);
     743          12 :                     FROM_R_F(intype, -127.1, outtype, -127);
     744             : 
     745          12 :                     FROM_R_F(intype, -0.4, outtype, 0);
     746          12 :                     FROM_R_F(intype, -0.5, outtype,
     747             :                              -1); /* We could argue how to do this rounding */
     748          12 :                     FROM_R_F(intype, -0.6, outtype, -1);
     749          12 :                     FROM_R_F(intype, -127.5, outtype,
     750             :                              -128); /* We could argue how to do this rounding */
     751             :                 }
     752             : 
     753          20 :                 FROM_R_F(intype, std::numeric_limits<float>::quiet_NaN(),
     754             :                          outtype, 0);
     755             : 
     756          20 :                 constexpr double NEGATIVE_ZERO =
     757             :                     -1.0f / std::numeric_limits<float>::infinity();
     758          20 :                 FROM_R_F(intype, NEGATIVE_ZERO, outtype, 0);
     759             :             }
     760             :         }
     761           2 :         FROM_R(intype, -CST_3000000000, GDT_Byte, 0);
     762           2 :         FROM_R(intype, -32768, GDT_Byte, 0);
     763           2 :         FROM_R(intype, -1, GDT_Byte, 0);
     764           2 :         FROM_R(intype, 256, GDT_Byte, 255);
     765           2 :         FROM_R(intype, 65536, GDT_Byte, 255);
     766           2 :         FROM_R(intype, CST_3000000000, GDT_Byte, 255);
     767           2 :         FROM_R(intype, -CST_3000000000, GDT_Int16, -32768);
     768           2 :         FROM_R(intype, -33000, GDT_Int16, -32768);
     769           2 :         FROM_R(intype, 33000, GDT_Int16, 32767);
     770           2 :         FROM_R(intype, CST_3000000000, GDT_Int16, 32767);
     771           2 :         FROM_R(intype, -CST_3000000000, GDT_UInt16, 0);
     772           2 :         FROM_R(intype, -1, GDT_UInt16, 0);
     773           2 :         FROM_R(intype, 66000, GDT_UInt16, 65535);
     774           2 :         FROM_R(intype, CST_3000000000, GDT_UInt16, 65535);
     775           2 :         FROM_R(intype, -CST_3000000000, GDT_Int32, INT_MIN);
     776           2 :         FROM_R(intype, CST_3000000000, GDT_Int32, 2147483647);
     777           2 :         FROM_R(intype, -1, GDT_UInt32, 0);
     778           2 :         FROM_R(intype, CST_5000000000, GDT_UInt32, 4294967295UL);
     779           2 :         FROM_R(intype, CST_5000000000, GDT_Float32, CST_5000000000);
     780           2 :         FROM_R(intype, -CST_5000000000, GDT_Float32, -CST_5000000000);
     781           2 :         FROM_R(intype, CST_5000000000, GDT_Float64, CST_5000000000);
     782           2 :         FROM_R(intype, -CST_5000000000, GDT_Float64, -CST_5000000000);
     783           2 :         FROM_R(intype, -33000, GDT_CInt16, -32768);
     784           2 :         FROM_R(intype, 33000, GDT_CInt16, 32767);
     785           2 :         FROM_R(intype, -CST_3000000000, GDT_CInt32, INT_MIN);
     786           2 :         FROM_R(intype, CST_3000000000, GDT_CInt32, 2147483647);
     787           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat32, CST_5000000000);
     788           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat32, -CST_5000000000);
     789           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat64, CST_5000000000);
     790           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat64, -CST_5000000000);
     791             :     }
     792             : 
     793             :     // Float32 to Int64
     794             :     {
     795           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     796           1 :         int64_t out_value = 0;
     797           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     798           1 :         EXPECT_EQ(out_value, 0);
     799             :     }
     800             : 
     801             :     {
     802           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     803           1 :         int64_t out_value = 0;
     804           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     805           1 :         EXPECT_EQ(out_value, INT64_MIN);
     806             :     }
     807             : 
     808             :     {
     809           1 :         float in_value = -cpl::NumericLimits<float>::max();
     810           1 :         int64_t out_value = 0;
     811           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     812           1 :         EXPECT_EQ(out_value, INT64_MIN);
     813             :     }
     814             : 
     815             :     {
     816           1 :         float in_value = cpl::NumericLimits<float>::max();
     817           1 :         int64_t out_value = 0;
     818           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     819           1 :         EXPECT_EQ(out_value, INT64_MAX);
     820             :     }
     821             : 
     822             :     {
     823           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     824           1 :         int64_t out_value = 0;
     825           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     826           1 :         EXPECT_EQ(out_value, INT64_MAX);
     827             :     }
     828             : 
     829             :     // Float64 to Int64
     830             :     {
     831           1 :         double in_value = cpl::NumericLimits<double>::quiet_NaN();
     832           1 :         int64_t out_value = 0;
     833           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     834           1 :         EXPECT_EQ(out_value, 0);
     835             :     }
     836             : 
     837             :     {
     838           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     839           1 :         int64_t out_value = 0;
     840           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     841           1 :         EXPECT_EQ(out_value, INT64_MIN);
     842             :     }
     843             : 
     844             :     {
     845           1 :         double in_value = -cpl::NumericLimits<double>::max();
     846           1 :         int64_t out_value = 0;
     847           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     848           1 :         EXPECT_EQ(out_value, INT64_MIN);
     849             :     }
     850             : 
     851             :     {
     852           1 :         double in_value = cpl::NumericLimits<double>::max();
     853           1 :         int64_t out_value = 0;
     854           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     855           1 :         EXPECT_EQ(out_value, INT64_MAX);
     856             :     }
     857             : 
     858             :     {
     859           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     860           1 :         int64_t out_value = 0;
     861           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     862           1 :         EXPECT_EQ(out_value, INT64_MAX);
     863             :     }
     864             : 
     865             :     // Float32 to UInt64
     866             :     {
     867           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     868           1 :         uint64_t out_value = 0;
     869           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     870           1 :         EXPECT_EQ(out_value, 0);
     871             :     }
     872             : 
     873             :     {
     874           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     875           1 :         uint64_t out_value = 0;
     876           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     877           1 :         EXPECT_EQ(out_value, 0);
     878             :     }
     879             : 
     880             :     {
     881           1 :         float in_value = -cpl::NumericLimits<float>::max();
     882           1 :         uint64_t out_value = 0;
     883           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     884           1 :         EXPECT_EQ(out_value, 0);
     885             :     }
     886             : 
     887             :     {
     888           1 :         float in_value = cpl::NumericLimits<float>::max();
     889           1 :         uint64_t out_value = 0;
     890           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     891           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     892             :     }
     893             : 
     894             :     {
     895           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     896           1 :         uint64_t out_value = 0;
     897           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     898           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     899             :     }
     900             : 
     901             :     // Float64 to UInt64
     902             :     {
     903           1 :         double in_value = -cpl::NumericLimits<double>::quiet_NaN();
     904           1 :         uint64_t out_value = 0;
     905           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     906           1 :         EXPECT_EQ(out_value, 0);
     907             :     }
     908             : 
     909             :     {
     910           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     911           1 :         uint64_t out_value = 0;
     912           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     913           1 :         EXPECT_EQ(out_value, 0);
     914             :     }
     915             : 
     916             :     {
     917           1 :         double in_value = -cpl::NumericLimits<double>::max();
     918           1 :         uint64_t out_value = 0;
     919           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     920           1 :         EXPECT_EQ(out_value, 0);
     921             :     }
     922             : 
     923             :     {
     924           1 :         double in_value = cpl::NumericLimits<double>::max();
     925           1 :         uint64_t out_value = 0;
     926           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     927           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     928             :     }
     929             : 
     930             :     {
     931           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     932           1 :         uint64_t out_value = 0;
     933           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     934           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     935             :     }
     936           1 : }
     937             : 
     938           4 : TEST_F(TestCopyWords, GDT_CInt16)
     939             : {
     940             :     /* GDT_CInt16 */
     941           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Byte, 0, 0); /* clamp */
     942           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int16, -32000, 0);
     943           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt16, 0, 0); /* clamp */
     944           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int32, -32000, 0);
     945           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt32, 0, 0); /* clamp */
     946           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float32, -32000, 0);
     947           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float64, -32000, 0);
     948           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt16, -32000, -32500);
     949           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt32, -32000, -32500);
     950           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat32, -32000, -32500);
     951           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat64, -32000, -32500);
     952          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     953          16 :          outtype = (GDALDataType)(outtype + 1))
     954             :     {
     955          16 :         FROM_C(GDT_CInt16, 127, 128, outtype, 127, 128);
     956             :     }
     957             : 
     958           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Byte, 255, 0); /* clamp */
     959           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int16, 32000, 0);
     960           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt16, 32000, 0);
     961           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int32, 32000, 0);
     962           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt32, 32000, 0);
     963           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float32, 32000, 0);
     964           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float64, 32000, 0);
     965           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt16, 32000, 32500);
     966           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt32, 32000, 32500);
     967           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat32, 32000, 32500);
     968           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat64, 32000, 32500);
     969           1 : }
     970             : 
     971           4 : TEST_F(TestCopyWords, GDT_CInt32)
     972             : {
     973             :     /* GDT_CInt32 */
     974           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Byte, 0, 0);       /* clamp */
     975           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int16, -32768, 0); /* clamp */
     976           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt16, 0, 0);     /* clamp */
     977           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int32, -33000, 0);
     978           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt32, 0, 0); /* clamp */
     979           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float32, -33000, 0);
     980           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float64, -33000, 0);
     981           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt16, -32768, -32768); /* clamp */
     982           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt32, -33000, -33500);
     983           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat32, -33000, -33500);
     984           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat64, -33000, -33500);
     985          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     986          16 :          outtype = (GDALDataType)(outtype + 1))
     987             :     {
     988          16 :         FROM_C(GDT_CInt32, 127, 128, outtype, 127, 128);
     989             :     }
     990             : 
     991           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Byte, 255, 0);     /* clamp */
     992           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int16, 32767, 0);  /* clamp */
     993           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt16, 65535, 0); /* clamp */
     994           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int32, 67000, 0);
     995           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt32, 67000, 0);
     996           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float32, 67000, 0);
     997           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float64, 67000, 0);
     998           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt16, 32767, 32767); /* clamp */
     999           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt32, 67000, 67500);
    1000           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat32, 67000, 67500);
    1001           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat64, 67000, 67500);
    1002           1 : }
    1003             : 
    1004           4 : TEST_F(TestCopyWords, GDT_CFloat32and64)
    1005             : {
    1006             :     /* GDT_CFloat32 and GDT_CFloat64 */
    1007           3 :     for (int i = 0; i < 2; i++)
    1008             :     {
    1009           2 :         GDALDataType intype = (i == 0) ? GDT_CFloat32 : GDT_CFloat64;
    1010          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
    1011          32 :              outtype = (GDALDataType)(outtype + 1))
    1012             :         {
    1013          32 :             if (IS_FLOAT(outtype))
    1014             :             {
    1015          12 :                 FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
    1016          12 :                 FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
    1017             :             }
    1018             :             else
    1019             :             {
    1020          20 :                 FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
    1021          20 :                 FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
    1022          20 :                 if (!IS_UNSIGNED(outtype))
    1023             :                 {
    1024          12 :                     FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
    1025             :                 }
    1026             :             }
    1027             :         }
    1028           2 :         FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
    1029           2 :         FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
    1030           2 :         FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
    1031           2 :         FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1032           2 :         FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1033           2 :         FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1034           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_Int32, INT_MIN, 0);
    1035           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_Int32, 2147483647,
    1036             :                0);
    1037           2 :         FROM_C(intype, -1, CST_5000000000, GDT_UInt32, 0, 0);
    1038           2 :         FROM_C(intype, CST_5000000000, -1, GDT_UInt32, 4294967295UL, 0);
    1039           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float32, CST_5000000000, 0);
    1040           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float64, CST_5000000000, 0);
    1041           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float32, -CST_5000000000, 0);
    1042           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float64, -CST_5000000000, 0);
    1043           2 :         FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1044           2 :         FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1045           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_CInt32, INT_MIN,
    1046             :                INT_MIN);
    1047           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_CInt32, 2147483647,
    1048             :                2147483647);
    1049           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat32,
    1050             :                CST_5000000000, -CST_5000000000);
    1051           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat64,
    1052             :                CST_5000000000, -CST_5000000000);
    1053             :     }
    1054           1 : }
    1055             : 
    1056           4 : TEST_F(TestCopyWords, GDT_CFloat16only)
    1057             : {
    1058           1 :     GDALDataType intype = GDT_CFloat16;
    1059          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
    1060          16 :          outtype = (GDALDataType)(outtype + 1))
    1061             :     {
    1062          16 :         if (IS_FLOAT(outtype))
    1063             :         {
    1064           6 :             FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
    1065           6 :             FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
    1066             :         }
    1067             :         else
    1068             :         {
    1069          10 :             FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
    1070          10 :             FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
    1071          10 :             if (!IS_UNSIGNED(outtype))
    1072             :             {
    1073           6 :                 FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
    1074             :             }
    1075             :         }
    1076             :     }
    1077           1 :     FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
    1078           1 :     FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
    1079           1 :     FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
    1080           1 :     FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1081           1 :     FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1082           1 :     FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1083           1 :     FROM_C(intype, -33000, -33000, GDT_Int32, -32992, 0);
    1084           1 :     FROM_C(intype, 33000, 33000, GDT_Int32, 32992, 0);
    1085           1 :     FROM_C(intype, -1, 33000, GDT_UInt32, 0, 0);
    1086           1 :     FROM_C(intype, 33000, -1, GDT_UInt32, 32992, 0);
    1087           1 :     FROM_C(intype, 33000, -1, GDT_Float32, 32992, 0);
    1088           1 :     FROM_C(intype, 33000, -1, GDT_Float64, 32992, 0);
    1089           1 :     FROM_C(intype, -33000, -1, GDT_Float32, -32992, 0);
    1090           1 :     FROM_C(intype, -33000, -1, GDT_Float64, -32992, 0);
    1091           1 :     FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1092           1 :     FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1093           1 :     FROM_C(intype, -33000, -33000, GDT_CInt32, -32992, -32992);
    1094           1 :     FROM_C(intype, 33000, 33000, GDT_CInt32, 32992, 32992);
    1095           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat32, 32992, -32992);
    1096           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat64, 32992, -32992);
    1097           1 : }
    1098             : 
    1099             : template <class Tin, class Tout>
    1100         121 : void CheckPackedGeneric(GDALDataType eIn, GDALDataType eOut)
    1101             : {
    1102         121 :     const int N = 64 + 7;
    1103         792 :     Tin arrayIn[N];
    1104         792 :     Tout arrayOut[N];
    1105        8712 :     for (int i = 0; i < N; i++)
    1106             :     {
    1107             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1108             :         {
    1109             :             // Test correct rounding
    1110         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1111          12 :                 arrayIn[i] = cpl::NumericLimits<Tin>::quiet_NaN();
    1112        1692 :             else if ((i % 2) != 0)
    1113         840 :                 arrayIn[i] = static_cast<Tin>(i + 0.4);
    1114             :             else
    1115         852 :                 arrayIn[i] = static_cast<Tin>(i + 0.6);
    1116             :         }
    1117             :         else
    1118             :         {
    1119        6887 :             arrayIn[i] = static_cast<Tin>(i + 1);
    1120             :         }
    1121        8591 :         arrayOut[i] = 0;
    1122             :     }
    1123         121 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1124             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1125         121 :     int numLine = 0;
    1126        8712 :     for (int i = 0; i < N; i++)
    1127             :     {
    1128             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1129             :         {
    1130         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1131             :             {
    1132          12 :                 MY_EXPECT(eIn, cpl::NumericLimits<Tin>::quiet_NaN(), eOut, 0,
    1133             :                           arrayOut[i]);
    1134             :             }
    1135        1692 :             else if ((i % 2) != 0)
    1136             :             {
    1137         840 :                 MY_EXPECT(eIn, i + 0.4, eOut, i, arrayOut[i]);
    1138             :             }
    1139             :             else
    1140             :             {
    1141         852 :                 MY_EXPECT(eIn, i + 0.6, eOut, i + 1, arrayOut[i]);
    1142             :             }
    1143             :         }
    1144             :         else
    1145             :         {
    1146        6887 :             MY_EXPECT(eIn, i + 1, eOut, i + 1, arrayOut[i]);
    1147             :         }
    1148             :     }
    1149         121 : }
    1150             : 
    1151             : template <class Tin, class Tout>
    1152         119 : void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1153             : {
    1154         119 :     CheckPackedGeneric<Tin, Tout>(eIn, eOut);
    1155         119 : }
    1156             : 
    1157             : template <>
    1158           1 : void CheckPacked<GUInt16, GByte>(GDALDataType eIn, GDALDataType eOut)
    1159             : {
    1160           1 :     CheckPackedGeneric<GUInt16, GByte>(eIn, eOut);
    1161             : 
    1162           1 :     const int N = 64 + 7;
    1163           1 :     GUInt16 arrayIn[N] = {0};
    1164           1 :     GByte arrayOut[N] = {0};
    1165          72 :     for (int i = 0; i < N; i++)
    1166             :     {
    1167         130 :         arrayIn[i] = (i % 6) == 0   ? 254
    1168          59 :                      : (i % 6) == 1 ? 255
    1169          47 :                      : (i % 4) == 2 ? 256
    1170          35 :                      : (i % 6) == 3 ? 32767
    1171          23 :                      : (i % 6) == 4 ? 32768
    1172             :                                     : 65535;
    1173             :     }
    1174           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1175             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1176           1 :     int numLine = 0;
    1177          72 :     for (int i = 0; i < N; i++)
    1178             :     {
    1179          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 6) == 0 ? 254 : 255,
    1180             :                   arrayOut[i]);
    1181             :     }
    1182           1 : }
    1183             : 
    1184             : template <>
    1185           1 : void CheckPacked<GUInt16, GInt16>(GDALDataType eIn, GDALDataType eOut)
    1186             : {
    1187           1 :     CheckPackedGeneric<GUInt16, GInt16>(eIn, eOut);
    1188             : 
    1189           1 :     const int N = 64 + 7;
    1190           1 :     GUInt16 arrayIn[N] = {0};
    1191           1 :     GInt16 arrayOut[N] = {0};
    1192          72 :     for (int i = 0; i < N; i++)
    1193             :     {
    1194          71 :         arrayIn[i] = 32766 + (i % 4);
    1195             :     }
    1196           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1197             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1198           1 :     int numLine = 0;
    1199          72 :     for (int i = 0; i < N; i++)
    1200             :     {
    1201          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 4) == 0 ? 32766 : 32767,
    1202             :                   arrayOut[i]);
    1203             :     }
    1204           1 : }
    1205             : 
    1206         121 : template <class Tin> void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1207             : {
    1208         121 :     switch (eOut)
    1209             :     {
    1210          11 :         case GDT_Byte:
    1211          11 :             CheckPacked<Tin, GByte>(eIn, eOut);
    1212          11 :             break;
    1213          11 :         case GDT_Int8:
    1214          11 :             CheckPacked<Tin, GInt8>(eIn, eOut);
    1215          11 :             break;
    1216          11 :         case GDT_UInt16:
    1217          11 :             CheckPacked<Tin, GUInt16>(eIn, eOut);
    1218          11 :             break;
    1219          11 :         case GDT_Int16:
    1220          11 :             CheckPacked<Tin, GInt16>(eIn, eOut);
    1221          11 :             break;
    1222          11 :         case GDT_UInt32:
    1223          11 :             CheckPacked<Tin, GUInt32>(eIn, eOut);
    1224          11 :             break;
    1225          11 :         case GDT_Int32:
    1226          11 :             CheckPacked<Tin, GInt32>(eIn, eOut);
    1227          11 :             break;
    1228          11 :         case GDT_UInt64:
    1229          11 :             CheckPacked<Tin, std::uint64_t>(eIn, eOut);
    1230          11 :             break;
    1231          11 :         case GDT_Int64:
    1232          11 :             CheckPacked<Tin, std::int64_t>(eIn, eOut);
    1233          11 :             break;
    1234          11 :         case GDT_Float16:
    1235          11 :             CheckPacked<Tin, GFloat16>(eIn, eOut);
    1236          11 :             break;
    1237          11 :         case GDT_Float32:
    1238          11 :             CheckPacked<Tin, float>(eIn, eOut);
    1239          11 :             break;
    1240          11 :         case GDT_Float64:
    1241          11 :             CheckPacked<Tin, double>(eIn, eOut);
    1242          11 :             break;
    1243           0 :         default:
    1244           0 :             CPLAssert(false);
    1245             :     }
    1246         121 : }
    1247             : 
    1248         121 : static void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1249             : {
    1250         121 :     switch (eIn)
    1251             :     {
    1252          11 :         case GDT_Byte:
    1253          11 :             CheckPacked<GByte>(eIn, eOut);
    1254          11 :             break;
    1255          11 :         case GDT_Int8:
    1256          11 :             CheckPacked<GInt8>(eIn, eOut);
    1257          11 :             break;
    1258          11 :         case GDT_UInt16:
    1259          11 :             CheckPacked<GUInt16>(eIn, eOut);
    1260          11 :             break;
    1261          11 :         case GDT_Int16:
    1262          11 :             CheckPacked<GInt16>(eIn, eOut);
    1263          11 :             break;
    1264          11 :         case GDT_UInt32:
    1265          11 :             CheckPacked<GUInt32>(eIn, eOut);
    1266          11 :             break;
    1267          11 :         case GDT_Int32:
    1268          11 :             CheckPacked<GInt32>(eIn, eOut);
    1269          11 :             break;
    1270          11 :         case GDT_UInt64:
    1271          11 :             CheckPacked<std::uint64_t>(eIn, eOut);
    1272          11 :             break;
    1273          11 :         case GDT_Int64:
    1274          11 :             CheckPacked<std::int64_t>(eIn, eOut);
    1275          11 :             break;
    1276          11 :         case GDT_Float16:
    1277          11 :             CheckPacked<GFloat16>(eIn, eOut);
    1278          11 :             break;
    1279          11 :         case GDT_Float32:
    1280          11 :             CheckPacked<float>(eIn, eOut);
    1281          11 :             break;
    1282          11 :         case GDT_Float64:
    1283          11 :             CheckPacked<double>(eIn, eOut);
    1284          11 :             break;
    1285           0 :         default:
    1286           0 :             CPLAssert(false);
    1287             :     }
    1288         121 : }
    1289             : 
    1290             : class TestCopyWordsCheckPackedFixture
    1291             :     : public TestCopyWords,
    1292             :       public ::testing::WithParamInterface<
    1293             :           std::tuple<GDALDataType, GDALDataType>>
    1294             : {
    1295             : };
    1296             : 
    1297         243 : TEST_P(TestCopyWordsCheckPackedFixture, CheckPacked)
    1298             : {
    1299         121 :     GDALDataType eIn = std::get<0>(GetParam());
    1300         121 :     GDALDataType eOut = std::get<1>(GetParam());
    1301         121 :     CheckPacked(eIn, eOut);
    1302         121 : }
    1303             : 
    1304             : static std::vector<std::tuple<GDALDataType, GDALDataType>>
    1305           1 : GetGDALDataTypeTupleValues()
    1306             : {
    1307           1 :     std::vector<std::tuple<GDALDataType, GDALDataType>> ret;
    1308          17 :     for (GDALDataType eIn = GDT_Byte; eIn < GDT_TypeCount;
    1309          16 :          eIn = static_cast<GDALDataType>(eIn + 1))
    1310             :     {
    1311          16 :         if (GDALDataTypeIsComplex(eIn))
    1312           5 :             continue;
    1313         187 :         for (GDALDataType eOut = GDT_Byte; eOut < GDT_TypeCount;
    1314         176 :              eOut = static_cast<GDALDataType>(eOut + 1))
    1315             :         {
    1316         176 :             if (GDALDataTypeIsComplex(eOut))
    1317          55 :                 continue;
    1318         121 :             ret.emplace_back(std::make_tuple(eIn, eOut));
    1319             :         }
    1320             :     }
    1321           1 :     return ret;
    1322             : }
    1323             : 
    1324         365 : INSTANTIATE_TEST_SUITE_P(
    1325             :     TestCopyWords, TestCopyWordsCheckPackedFixture,
    1326             :     ::testing::ValuesIn(GetGDALDataTypeTupleValues()),
    1327             :     [](const ::testing::TestParamInfo<
    1328             :         TestCopyWordsCheckPackedFixture::ParamType> &l_info)
    1329             :     {
    1330             :         GDALDataType eIn = std::get<0>(l_info.param);
    1331             :         GDALDataType eOut = std::get<1>(l_info.param);
    1332             :         return std::string(GDALGetDataTypeName(eIn)) + "_" +
    1333             :                GDALGetDataTypeName(eOut);
    1334             :     });
    1335             : 
    1336           4 : TEST_F(TestCopyWords, ByteToByte)
    1337             : {
    1338           3 :     for (int k = 0; k < 2; k++)
    1339             :     {
    1340           2 :         if (k == 1)
    1341           1 :             CPLSetConfigOption("GDAL_USE_SSSE3", "NO");
    1342             : 
    1343           8 :         for (int spacing = 2; spacing <= 4; spacing++)
    1344             :         {
    1345           6 :             memset(pIn, 0xff, 256);
    1346         108 :             for (int i = 0; i < 17; i++)
    1347             :             {
    1348         102 :                 pIn[spacing * i] = (GByte)(17 - i);
    1349             :             }
    1350           6 :             memset(pOut, 0xff, 256);
    1351           6 :             GDALCopyWords(pIn, GDT_Byte, spacing, pOut, GDT_Byte, 1, 17);
    1352         108 :             for (int i = 0; i < 17; i++)
    1353             :             {
    1354         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i],
    1355             :                           __LINE__);
    1356             :             }
    1357             : 
    1358           6 :             memset(pIn, 0xff, 256);
    1359           6 :             memset(pOut, 0xff, 256);
    1360         108 :             for (int i = 0; i < 17; i++)
    1361             :             {
    1362         102 :                 pIn[i] = (GByte)(17 - i);
    1363             :             }
    1364           6 :             GDALCopyWords(pIn, GDT_Byte, 1, pOut, GDT_Byte, spacing, 17);
    1365         108 :             for (int i = 0; i < 17; i++)
    1366             :             {
    1367         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i * spacing],
    1368             :                           __LINE__);
    1369         306 :                 for (int j = 1; j < spacing; j++)
    1370             :                 {
    1371         204 :                     AssertRes(GDT_Byte, 0xff, GDT_Byte, 0xff,
    1372         204 :                               pOut[i * spacing + j], __LINE__);
    1373             :                 }
    1374             :             }
    1375             :         }
    1376             :     }
    1377           1 :     CPLSetConfigOption("GDAL_USE_SSSE3", nullptr);
    1378           1 : }
    1379             : 
    1380           4 : TEST_F(TestCopyWords, Int16ToInt16)
    1381             : {
    1382           1 :     memset(pIn, 0xff, 256);
    1383           1 :     GInt16 *pInShort = (GInt16 *)pIn;
    1384           1 :     GInt16 *pOutShort = (GInt16 *)pOut;
    1385          10 :     for (int i = 0; i < 9; i++)
    1386             :     {
    1387           9 :         pInShort[2 * i + 0] = 0x1234;
    1388           9 :         pInShort[2 * i + 1] = 0x5678;
    1389             :     }
    1390           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1391             :     {
    1392           4 :         memset(pOut, 0xff, 256);
    1393           4 :         GDALCopyWords(pInShort, GDT_Int16, sizeof(short), pOutShort, GDT_Int16,
    1394           4 :                       (iSpacing + 1) * sizeof(short), 18);
    1395          40 :         for (int i = 0; i < 9; i++)
    1396             :         {
    1397          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 0], GDT_Int16,
    1398          36 :                       pInShort[2 * i + 0],
    1399          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 0)], __LINE__);
    1400          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 1], GDT_Int16,
    1401          36 :                       pInShort[2 * i + 1],
    1402          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 1)], __LINE__);
    1403             :         }
    1404             :     }
    1405           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1406             :     {
    1407           4 :         memset(pIn, 0xff, 256);
    1408           4 :         memset(pOut, 0xff, 256);
    1409          40 :         for (int i = 0; i < 9; i++)
    1410             :         {
    1411          36 :             pInShort[(iSpacing + 1) * (2 * i + 0)] = 0x1234;
    1412          36 :             pInShort[(iSpacing + 1) * (2 * i + 1)] = 0x5678;
    1413             :         }
    1414           4 :         GDALCopyWords(pInShort, GDT_Int16, (iSpacing + 1) * sizeof(short),
    1415             :                       pOutShort, GDT_Int16, sizeof(short), 18);
    1416          40 :         for (int i = 0; i < 9; i++)
    1417             :         {
    1418          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1419          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1420          36 :                       pOutShort[2 * i + 0], __LINE__);
    1421          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1422          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1423          36 :                       pOutShort[2 * i + 1], __LINE__);
    1424             :         }
    1425             :     }
    1426           1 : }
    1427             : 
    1428             : }  // namespace

Generated by: LCOV version 1.14