LCOV - code coverage report
Current view: top level - autotest/cpp - testcopywords.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 868 877 99.0 %
Date: 2026-01-21 22:42:07 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       60326 : void AssertRes(GDALDataType intype, CT1 inval, GDALDataType outtype,
      32             :                CT2 expected_outval, OutType outval, int numLine)
      33             : {
      34       63064 :     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       60326 : }
      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        1029 :     void Test(GDALDataType intype, ConstantType inval, ConstantType invali,
      75             :               GDALDataType outtype, ConstantType outval, ConstantType outvali,
      76             :               int numLine)
      77             :     {
      78        1029 :         memset(pIn, 0xff, 1024);
      79        1029 :         memset(pOut, 0xff, 1024);
      80             : 
      81        1029 :         *(InType *)(pIn) = (InType)inval;
      82        1029 :         *(InType *)(pIn + 32) = (InType)inval;
      83        1029 :         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        1029 :         GDALCopyWords(pIn, intype, 32, pOut, outtype, 32, 2);
      91             : 
      92             :         /* Test negative offsets */
      93        1029 :         GDALCopyWords(pIn + 32, intype, -32, pOut + 1024 - 16, outtype, -32, 2);
      94             : 
      95        1029 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut));
      96        1029 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut + 32));
      97        1029 :         MY_EXPECT(intype, inval, outtype, outval,
      98             :                   *(OutType *)(pOut + 1024 - 16));
      99        1029 :         MY_EXPECT(intype, inval, outtype, outval,
     100             :                   *(OutType *)(pOut + 1024 - 16 - 32));
     101             : 
     102        1029 :         if (GDALDataTypeIsComplex(outtype))
     103             :         {
     104         304 :             MY_EXPECT(intype, invali, outtype, outvali, ((OutType *)(pOut))[1]);
     105         304 :             MY_EXPECT(intype, invali, outtype, outvali,
     106             :                       ((OutType *)(pOut + 32))[1]);
     107             : 
     108         304 :             MY_EXPECT(intype, invali, outtype, outvali,
     109             :                       ((OutType *)(pOut + 1024 - 16))[1]);
     110         304 :             MY_EXPECT(intype, invali, outtype, outvali,
     111             :                       ((OutType *)(pOut + 1024 - 16 - 32))[1]);
     112             :         }
     113             :         else
     114             :         {
     115         725 :             constexpr int N = 32 + 31;
     116       46400 :             for (int i = 0; i < N; ++i)
     117             :             {
     118       45675 :                 *(InType *)(pIn + i * GDALGetDataTypeSizeBytes(intype)) =
     119        9009 :                     (InType)inval;
     120             :             }
     121             : 
     122             :             /* Test packed offsets */
     123         725 :             GDALCopyWords(pIn, intype, GDALGetDataTypeSizeBytes(intype), pOut,
     124             :                           outtype, GDALGetDataTypeSizeBytes(outtype), N);
     125             : 
     126       46400 :             for (int i = 0; i < N; ++i)
     127             :             {
     128       45675 :                 MY_EXPECT(
     129             :                     intype, inval, outtype, outval,
     130             :                     *(OutType *)(pOut + i * GDALGetDataTypeSizeBytes(outtype)));
     131             :             }
     132             :         }
     133        1029 :     }
     134             : 
     135             :     template <class InType, class ConstantType>
     136        1029 :     void FromR_2(GDALDataType intype, ConstantType inval, ConstantType invali,
     137             :                  GDALDataType outtype, ConstantType outval,
     138             :                  ConstantType outvali, int numLine)
     139             :     {
     140        1029 :         if (outtype == GDT_Byte)
     141          77 :             Test<InType, GByte, ConstantType>(intype, inval, invali, outtype,
     142             :                                               outval, outvali, numLine);
     143         952 :         else if (outtype == GDT_Int8)
     144          61 :             Test<InType, GInt8, ConstantType>(intype, inval, invali, outtype,
     145             :                                               outval, outvali, numLine);
     146         891 :         else if (outtype == GDT_Int16)
     147          92 :             Test<InType, GInt16, ConstantType>(intype, inval, invali, outtype,
     148             :                                                outval, outvali, numLine);
     149         799 :         else if (outtype == GDT_UInt16)
     150          71 :             Test<InType, GUInt16, ConstantType>(intype, inval, invali, outtype,
     151             :                                                 outval, outvali, numLine);
     152         728 :         else if (outtype == GDT_Int32)
     153          87 :             Test<InType, GInt32, ConstantType>(intype, inval, invali, outtype,
     154             :                                                outval, outvali, numLine);
     155         641 :         else if (outtype == GDT_UInt32)
     156          66 :             Test<InType, GUInt32, ConstantType>(intype, inval, invali, outtype,
     157             :                                                 outval, outvali, numLine);
     158         575 :         else if (outtype == GDT_Int64)
     159          71 :             Test<InType, std::int64_t, ConstantType>(
     160             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     161         504 :         else if (outtype == GDT_UInt64)
     162          50 :             Test<InType, std::uint64_t, ConstantType>(
     163             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     164         454 :         else if (outtype == GDT_Float16)
     165          39 :             Test<InType, GFloat16, ConstantType>(intype, inval, invali, outtype,
     166             :                                                  outval, outvali, numLine);
     167         415 :         else if (outtype == GDT_Float32)
     168          57 :             Test<InType, float, ConstantType>(intype, inval, invali, outtype,
     169             :                                               outval, outvali, numLine);
     170         358 :         else if (outtype == GDT_Float64)
     171          54 :             Test<InType, double, ConstantType>(intype, inval, invali, outtype,
     172             :                                                outval, outvali, numLine);
     173         304 :         else if (outtype == GDT_CInt16)
     174          87 :             Test<InType, GInt16, ConstantType>(intype, inval, invali, outtype,
     175             :                                                outval, outvali, numLine);
     176         217 :         else if (outtype == GDT_CInt32)
     177          87 :             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        1029 :     }
     189             : 
     190             :     template <class ConstantType>
     191        1029 :     void FromR(GDALDataType intype, ConstantType inval, ConstantType invali,
     192             :                GDALDataType outtype, ConstantType outval, ConstantType outvali,
     193             :                int numLine)
     194             :     {
     195        1029 :         if (intype == GDT_Byte)
     196          47 :             FromR_2<GByte, ConstantType>(intype, inval, invali, outtype, outval,
     197             :                                          outvali, numLine);
     198         982 :         else if (intype == GDT_Int8)
     199          46 :             FromR_2<GInt8, ConstantType>(intype, inval, invali, outtype, outval,
     200             :                                          outvali, numLine);
     201         936 :         else if (intype == GDT_Int16)
     202          42 :             FromR_2<GInt16, ConstantType>(intype, inval, invali, outtype,
     203             :                                           outval, outvali, numLine);
     204         894 :         else if (intype == GDT_UInt16)
     205          45 :             FromR_2<GUInt16, ConstantType>(intype, inval, invali, outtype,
     206             :                                            outval, outvali, numLine);
     207         849 :         else if (intype == GDT_Int32)
     208          45 :             FromR_2<GInt32, ConstantType>(intype, inval, invali, outtype,
     209             :                                           outval, outvali, numLine);
     210         804 :         else if (intype == GDT_UInt32)
     211          45 :             FromR_2<GUInt32, ConstantType>(intype, inval, invali, outtype,
     212             :                                            outval, outvali, numLine);
     213         759 :         else if (intype == GDT_Int64)
     214          39 :             FromR_2<std::int64_t, ConstantType>(intype, inval, invali, outtype,
     215             :                                                 outval, outvali, numLine);
     216         720 :         else if (intype == GDT_UInt64)
     217          45 :             FromR_2<std::uint64_t, ConstantType>(intype, inval, invali, outtype,
     218             :                                                  outval, outvali, numLine);
     219         675 :         else if (intype == GDT_Float16)
     220         135 :             FromR_2<GFloat16, ConstantType>(intype, inval, invali, outtype,
     221             :                                             outval, outvali, numLine);
     222         540 :         else if (intype == GDT_Float32)
     223         146 :             FromR_2<float, ConstantType>(intype, inval, invali, outtype, outval,
     224             :                                          outvali, numLine);
     225         394 :         else if (intype == GDT_Float64)
     226         144 :             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        1029 :     }
     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           1 : }
     436             : 
     437           4 : TEST_F(TestCopyWords, GDT_UInt32)
     438             : {
     439             :     /* GDT_UInt32 */
     440          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     441          16 :          outtype = (GDALDataType)(outtype + 1))
     442             :     {
     443          16 :         FROM_R(GDT_UInt32, 0, outtype, 0);
     444          16 :         FROM_R(GDT_UInt32, 127, outtype, 127);
     445             :     }
     446             : 
     447           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Byte, 255);         /* clamp */
     448           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int16, 32767);      /* clamp */
     449           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt16, 65535);     /* clamp */
     450           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int32, 2147483647); /* clamp */
     451           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt32, 3000000000U);
     452           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Int64, 3000000000U);
     453           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_UInt64, 3000000000U);
     454           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Float32, 3000000000U);
     455           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_Float64, 3000000000U);
     456           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CInt16, 32767);      /* clamp */
     457           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CInt32, 2147483647); /* clamp */
     458           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CFloat32, 3000000000U);
     459           1 :     FROM_R(GDT_UInt32, 3000000000U, GDT_CFloat64, 3000000000U);
     460           1 : }
     461             : 
     462           4 : TEST_F(TestCopyWords, check_GDT_Int64)
     463             : {
     464             :     /* GDT_Int64 */
     465           1 :     FROM_R(GDT_Int64, -33000, GDT_Byte, 0);       /* clamp */
     466           1 :     FROM_R(GDT_Int64, -33000, GDT_Int16, -32768); /* clamp */
     467           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt16, 0);     /* clamp */
     468           1 :     FROM_R(GDT_Int64, -33000, GDT_Int32, -33000);
     469           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt32, 0); /* clamp */
     470           1 :     FROM_R(GDT_Int64, -33000, GDT_Int64, -33000);
     471           1 :     FROM_R(GDT_Int64, -33000, GDT_UInt64, 0); /* clamp */
     472           1 :     FROM_R(GDT_Int64, -33000, GDT_Float32, -33000);
     473           1 :     FROM_R(GDT_Int64, -33000, GDT_Float64, -33000);
     474           1 :     FROM_R(GDT_Int64, -33000, GDT_CInt16, -32768); /* clamp */
     475           1 :     FROM_R(GDT_Int64, -33000, GDT_CInt32, -33000);
     476           1 :     FROM_R(GDT_Int64, -33000, GDT_CFloat32, -33000);
     477           1 :     FROM_R(GDT_Int64, -33000, GDT_CFloat64, -33000);
     478          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     479          16 :          outtype = (GDALDataType)(outtype + 1))
     480             :     {
     481          16 :         FROM_R(GDT_Int64, 127, outtype, 127);
     482             :     }
     483             : 
     484           1 :     FROM_R(GDT_Int64, 67000, GDT_Byte, 255);     /* clamp */
     485           1 :     FROM_R(GDT_Int64, 67000, GDT_Int16, 32767);  /* clamp */
     486           1 :     FROM_R(GDT_Int32, 67000, GDT_UInt16, 65535); /* clamp */
     487           1 :     FROM_R(GDT_Int32, 67000, GDT_Int32, 67000);
     488           1 :     FROM_R(GDT_Int64, 67000, GDT_UInt32, 67000);
     489           1 :     FROM_R(GDT_Int32, 67000, GDT_Int64, 67000);
     490           1 :     FROM_R(GDT_Int64, 67000, GDT_UInt64, 67000);
     491           1 :     FROM_R(GDT_Int64, 67000, GDT_Float32, 67000);
     492           1 :     FROM_R(GDT_Int64, 67000, GDT_Float64, 67000);
     493           1 :     FROM_R(GDT_Int64, 67000, GDT_CInt16, 32767); /* clamp */
     494           1 :     FROM_R(GDT_Int64, 67000, GDT_CInt32, 67000);
     495           1 :     FROM_R(GDT_Int64, 67000, GDT_CFloat32, 67000);
     496           1 :     FROM_R(GDT_Int64, 67000, GDT_CFloat64, 67000);
     497           1 : }
     498             : 
     499           4 : TEST_F(TestCopyWords, GDT_UInt64)
     500             : {
     501             :     /* GDT_UInt64 */
     502          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     503          16 :          outtype = (GDALDataType)(outtype + 1))
     504             :     {
     505          16 :         FROM_R(GDT_UInt64, 0, outtype, 0);
     506          16 :         FROM_R(GDT_UInt64, 127, outtype, 127);
     507             :     }
     508             : 
     509           1 :     std::uint64_t nVal = static_cast<std::uint64_t>(3000000000) * 1000;
     510           1 :     FROM_R(GDT_UInt64, nVal, GDT_Byte, 255);           /* clamp */
     511           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int16, 32767);        /* clamp */
     512           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt16, 65535);       /* clamp */
     513           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int32, 2147483647);   /* clamp */
     514           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt32, 4294967295U); /* clamp */
     515           1 :     FROM_R(GDT_UInt64, nVal, GDT_Int64, nVal);
     516           1 :     FROM_R(GDT_UInt64, nVal, GDT_UInt64, nVal);
     517           1 :     FROM_R(GDT_UInt64, nVal, GDT_Float32,
     518             :            static_cast<uint64_t>(static_cast<float>(nVal)));
     519           1 :     FROM_R(GDT_UInt64, nVal, GDT_Float64, nVal);
     520           1 :     FROM_R(GDT_UInt64, nVal, GDT_CInt16, 32767);      /* clamp */
     521           1 :     FROM_R(GDT_UInt64, nVal, GDT_CInt32, 2147483647); /* clamp */
     522           1 :     FROM_R(GDT_UInt64, nVal, GDT_CFloat32,
     523             :            static_cast<uint64_t>(static_cast<float>(nVal)));
     524           1 :     FROM_R(GDT_UInt64, nVal, GDT_CFloat64, nVal);
     525           1 : }
     526             : 
     527           4 : TEST_F(TestCopyWords, GDT_Float64)
     528             : {
     529           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::max(), GDT_Float32,
     530             :              std::numeric_limits<double>::infinity());
     531           1 :     FROM_R_F(GDT_Float64, -std::numeric_limits<double>::max(), GDT_Float32,
     532             :              -std::numeric_limits<double>::infinity());
     533           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::quiet_NaN(), GDT_Float32,
     534             :              std::numeric_limits<double>::quiet_NaN());
     535           1 : }
     536             : 
     537           4 : TEST_F(TestCopyWords, GDT_Float16only)
     538             : {
     539           1 :     GDALDataType intype = GDT_Float16;
     540          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     541          16 :          outtype = (GDALDataType)(outtype + 1))
     542             :     {
     543          16 :         if (IS_FLOAT(outtype))
     544             :         {
     545           6 :             FROM_R_F(intype, 127.1, outtype, 127.1);
     546           6 :             FROM_R_F(intype, -127.1, outtype, -127.1);
     547             :         }
     548             :         else
     549             :         {
     550          10 :             FROM_R_F(intype, 125.1, outtype, 125);
     551          10 :             FROM_R_F(intype, 125.9, outtype, 126);
     552             : 
     553          10 :             FROM_R_F(intype, 0.4, outtype, 0);
     554          10 :             FROM_R_F(intype, 0.5, outtype,
     555             :                      1); /* We could argue how to do this rounding */
     556          10 :             FROM_R_F(intype, 0.6, outtype, 1);
     557          10 :             FROM_R_F(intype, 126.5, outtype,
     558             :                      127); /* We could argue how to do this rounding */
     559             : 
     560          10 :             if (!IS_UNSIGNED(outtype))
     561             :             {
     562           6 :                 FROM_R_F(intype, -125.9, outtype, -126);
     563           6 :                 FROM_R_F(intype, -127.1, outtype, -127);
     564             : 
     565           6 :                 FROM_R_F(intype, -0.4, outtype, 0);
     566           6 :                 FROM_R_F(intype, -0.5, outtype,
     567             :                          -1); /* We could argue how to do this rounding */
     568           6 :                 FROM_R_F(intype, -0.6, outtype, -1);
     569           6 :                 FROM_R_F(intype, -127.5, outtype,
     570             :                          -128); /* We could argue how to do this rounding */
     571             :             }
     572             :         }
     573             :     }
     574           1 :     FROM_R(intype, -30000, GDT_Byte, 0);
     575           1 :     FROM_R(intype, -32768, GDT_Byte, 0);
     576           1 :     FROM_R(intype, -1, GDT_Byte, 0);
     577           1 :     FROM_R(intype, 256, GDT_Byte, 255);
     578           1 :     FROM_R(intype, 30000, GDT_Byte, 255);
     579           1 :     FROM_R(intype, -330000, GDT_Int16, -32768);
     580           1 :     FROM_R(intype, -33000, GDT_Int16, -32768);
     581           1 :     FROM_R(intype, 33000, GDT_Int16, 32767);
     582           1 :     FROM_R(intype, -33000, GDT_UInt16, 0);
     583           1 :     FROM_R(intype, -1, GDT_UInt16, 0);
     584           1 :     FROM_R(intype, 60000, GDT_UInt16, 60000);
     585           1 :     FROM_R(intype, -33000, GDT_Int32, -32992);
     586           1 :     FROM_R(intype, 33000, GDT_Int32, 32992);
     587           1 :     FROM_R(intype, -1, GDT_UInt32, 0);
     588           1 :     FROM_R(intype, 60000, GDT_UInt32, 60000U);
     589           1 :     FROM_R(intype, 33000, GDT_Float32, 32992);
     590           1 :     FROM_R(intype, -33000, GDT_Float32, -32992);
     591           1 :     FROM_R(intype, 33000, GDT_Float64, 32992);
     592           1 :     FROM_R(intype, -33000, GDT_Float64, -32992);
     593           1 :     FROM_R(intype, -33000, GDT_CInt16, -32768);
     594           1 :     FROM_R(intype, 33000, GDT_CInt16, 32767);
     595           1 :     FROM_R(intype, -33000, GDT_CInt32, -32992);
     596           1 :     FROM_R(intype, 33000, GDT_CInt32, 32992);
     597           1 :     FROM_R(intype, 33000, GDT_CFloat32, 32992);
     598           1 :     FROM_R(intype, -33000, GDT_CFloat32, -32992);
     599           1 :     FROM_R(intype, 33000, GDT_CFloat64, 32992);
     600           1 :     FROM_R(intype, -33000, GDT_CFloat64, -32992);
     601             : 
     602           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::min(), GDT_Float16, 0);
     603           1 :     FROM_R_F(GDT_Float32, -std::numeric_limits<float>::min(), GDT_Float16, 0);
     604             :     // smallest positive subnormal float16 number
     605           1 :     FROM_R_F(GDT_Float32, 0.000000059604645f, GDT_Float16, 0.000000059604645f);
     606           1 :     FROM_R_F(GDT_Float32, 65504.0f, GDT_Float16, 65504.0f);
     607           1 :     FROM_R_F(GDT_Float32, 65535.0f, GDT_Float16,
     608             :              std::numeric_limits<double>::infinity());
     609           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::max(), GDT_Float16,
     610             :              std::numeric_limits<double>::infinity());
     611           1 :     FROM_R_F(GDT_Float32, -std::numeric_limits<float>::max(), GDT_Float16,
     612             :              -std::numeric_limits<double>::infinity());
     613           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::quiet_NaN(), GDT_Float16,
     614             :              std::numeric_limits<double>::quiet_NaN());
     615             : 
     616           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::max(), GDT_Float16,
     617             :              std::numeric_limits<double>::infinity());
     618           1 :     FROM_R_F(GDT_Float64, -std::numeric_limits<double>::max(), GDT_Float16,
     619             :              -std::numeric_limits<double>::infinity());
     620           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::quiet_NaN(), GDT_Float16,
     621             :              std::numeric_limits<double>::quiet_NaN());
     622             : 
     623             :     // Float16 to Int64
     624             :     {
     625           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     626           1 :         int64_t out_value = 0;
     627           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     628           1 :         EXPECT_EQ(out_value, 0);
     629             :     }
     630             : 
     631             :     {
     632           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     633           1 :         int64_t out_value = 0;
     634           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     635           1 :         EXPECT_EQ(out_value, INT64_MIN);
     636             :     }
     637             : 
     638             :     {
     639           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::max();
     640           1 :         int64_t out_value = 0;
     641           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     642           1 :         EXPECT_EQ(out_value, -65504);
     643             :     }
     644             : 
     645             :     {
     646           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::max();
     647           1 :         int64_t out_value = 0;
     648           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     649           1 :         EXPECT_EQ(out_value, 65504);
     650             :     }
     651             : 
     652             :     {
     653           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::infinity();
     654           1 :         int64_t out_value = 0;
     655           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     656           1 :         EXPECT_EQ(out_value, INT64_MAX);
     657             :     }
     658             : 
     659             :     // Float16 to UInt64
     660             :     {
     661           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     662           1 :         uint64_t out_value = 0;
     663           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     664           1 :         EXPECT_EQ(out_value, 0);
     665             :     }
     666             : 
     667             :     {
     668           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     669           1 :         uint64_t out_value = 0;
     670           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     671           1 :         EXPECT_EQ(out_value, 0);
     672             :     }
     673             : 
     674             :     {
     675           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::max();
     676           1 :         uint64_t out_value = 0;
     677           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     678           1 :         EXPECT_EQ(out_value, 0);
     679             :     }
     680             : 
     681             :     {
     682           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::max();
     683           1 :         uint64_t out_value = 0;
     684           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     685           1 :         EXPECT_EQ(out_value, 65504);
     686             :     }
     687             : 
     688             :     {
     689           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::infinity();
     690           1 :         uint64_t out_value = 0;
     691           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     692           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     693             :     }
     694           1 : }
     695             : 
     696           4 : TEST_F(TestCopyWords, GDT_Float32and64)
     697             : {
     698             :     /* GDT_Float32 and GDT_Float64 */
     699           3 :     for (int i = 0; i < 2; i++)
     700             :     {
     701           2 :         GDALDataType intype = (i == 0) ? GDT_Float32 : GDT_Float64;
     702          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     703          32 :              outtype = (GDALDataType)(outtype + 1))
     704             :         {
     705          32 :             if (IS_FLOAT(outtype))
     706             :             {
     707          12 :                 FROM_R_F(intype, 127.1, outtype, 127.1);
     708          12 :                 FROM_R_F(intype, -127.1, outtype, -127.1);
     709             :             }
     710             :             else
     711             :             {
     712          20 :                 FROM_R_F(intype, 125.1, outtype, 125);
     713          20 :                 FROM_R_F(intype, 125.9, outtype, 126);
     714             : 
     715          20 :                 FROM_R_F(intype, 0.4, outtype, 0);
     716          20 :                 FROM_R_F(intype, 0.5, outtype,
     717             :                          1); /* We could argue how to do this rounding */
     718          20 :                 FROM_R_F(intype, 0.6, outtype, 1);
     719          20 :                 FROM_R_F(intype, 126.5, outtype,
     720             :                          127); /* We could argue how to do this rounding */
     721             : 
     722          20 :                 if (!IS_UNSIGNED(outtype))
     723             :                 {
     724          12 :                     FROM_R_F(intype, -125.9, outtype, -126);
     725          12 :                     FROM_R_F(intype, -127.1, outtype, -127);
     726             : 
     727          12 :                     FROM_R_F(intype, -0.4, outtype, 0);
     728          12 :                     FROM_R_F(intype, -0.5, outtype,
     729             :                              -1); /* We could argue how to do this rounding */
     730          12 :                     FROM_R_F(intype, -0.6, outtype, -1);
     731          12 :                     FROM_R_F(intype, -127.5, outtype,
     732             :                              -128); /* We could argue how to do this rounding */
     733             :                 }
     734             :             }
     735             :         }
     736           2 :         FROM_R(intype, -CST_3000000000, GDT_Byte, 0);
     737           2 :         FROM_R(intype, -32768, GDT_Byte, 0);
     738           2 :         FROM_R(intype, -1, GDT_Byte, 0);
     739           2 :         FROM_R(intype, 256, GDT_Byte, 255);
     740           2 :         FROM_R(intype, 65536, GDT_Byte, 255);
     741           2 :         FROM_R(intype, CST_3000000000, GDT_Byte, 255);
     742           2 :         FROM_R(intype, -CST_3000000000, GDT_Int16, -32768);
     743           2 :         FROM_R(intype, -33000, GDT_Int16, -32768);
     744           2 :         FROM_R(intype, 33000, GDT_Int16, 32767);
     745           2 :         FROM_R(intype, CST_3000000000, GDT_Int16, 32767);
     746           2 :         FROM_R(intype, -CST_3000000000, GDT_UInt16, 0);
     747           2 :         FROM_R(intype, -1, GDT_UInt16, 0);
     748           2 :         FROM_R(intype, 66000, GDT_UInt16, 65535);
     749           2 :         FROM_R(intype, CST_3000000000, GDT_UInt16, 65535);
     750           2 :         FROM_R(intype, -CST_3000000000, GDT_Int32, INT_MIN);
     751           2 :         FROM_R(intype, CST_3000000000, GDT_Int32, 2147483647);
     752           2 :         FROM_R(intype, -1, GDT_UInt32, 0);
     753           2 :         FROM_R(intype, CST_5000000000, GDT_UInt32, 4294967295UL);
     754           2 :         FROM_R(intype, CST_5000000000, GDT_Float32, CST_5000000000);
     755           2 :         FROM_R(intype, -CST_5000000000, GDT_Float32, -CST_5000000000);
     756           2 :         FROM_R(intype, CST_5000000000, GDT_Float64, CST_5000000000);
     757           2 :         FROM_R(intype, -CST_5000000000, GDT_Float64, -CST_5000000000);
     758           2 :         FROM_R(intype, -33000, GDT_CInt16, -32768);
     759           2 :         FROM_R(intype, 33000, GDT_CInt16, 32767);
     760           2 :         FROM_R(intype, -CST_3000000000, GDT_CInt32, INT_MIN);
     761           2 :         FROM_R(intype, CST_3000000000, GDT_CInt32, 2147483647);
     762           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat32, CST_5000000000);
     763           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat32, -CST_5000000000);
     764           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat64, CST_5000000000);
     765           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat64, -CST_5000000000);
     766             :     }
     767             : 
     768             :     // Float32 to Int64
     769             :     {
     770           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     771           1 :         int64_t out_value = 0;
     772           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     773           1 :         EXPECT_EQ(out_value, 0);
     774             :     }
     775             : 
     776             :     {
     777           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     778           1 :         int64_t out_value = 0;
     779           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     780           1 :         EXPECT_EQ(out_value, INT64_MIN);
     781             :     }
     782             : 
     783             :     {
     784           1 :         float in_value = -cpl::NumericLimits<float>::max();
     785           1 :         int64_t out_value = 0;
     786           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     787           1 :         EXPECT_EQ(out_value, INT64_MIN);
     788             :     }
     789             : 
     790             :     {
     791           1 :         float in_value = cpl::NumericLimits<float>::max();
     792           1 :         int64_t out_value = 0;
     793           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     794           1 :         EXPECT_EQ(out_value, INT64_MAX);
     795             :     }
     796             : 
     797             :     {
     798           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     799           1 :         int64_t out_value = 0;
     800           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     801           1 :         EXPECT_EQ(out_value, INT64_MAX);
     802             :     }
     803             : 
     804             :     // Float64 to Int64
     805             :     {
     806           1 :         double in_value = cpl::NumericLimits<double>::quiet_NaN();
     807           1 :         int64_t out_value = 0;
     808           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     809           1 :         EXPECT_EQ(out_value, 0);
     810             :     }
     811             : 
     812             :     {
     813           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     814           1 :         int64_t out_value = 0;
     815           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     816           1 :         EXPECT_EQ(out_value, INT64_MIN);
     817             :     }
     818             : 
     819             :     {
     820           1 :         double in_value = -cpl::NumericLimits<double>::max();
     821           1 :         int64_t out_value = 0;
     822           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     823           1 :         EXPECT_EQ(out_value, INT64_MIN);
     824             :     }
     825             : 
     826             :     {
     827           1 :         double in_value = cpl::NumericLimits<double>::max();
     828           1 :         int64_t out_value = 0;
     829           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     830           1 :         EXPECT_EQ(out_value, INT64_MAX);
     831             :     }
     832             : 
     833             :     {
     834           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     835           1 :         int64_t out_value = 0;
     836           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     837           1 :         EXPECT_EQ(out_value, INT64_MAX);
     838             :     }
     839             : 
     840             :     // Float32 to UInt64
     841             :     {
     842           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     843           1 :         uint64_t out_value = 0;
     844           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     845           1 :         EXPECT_EQ(out_value, 0);
     846             :     }
     847             : 
     848             :     {
     849           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     850           1 :         uint64_t out_value = 0;
     851           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     852           1 :         EXPECT_EQ(out_value, 0);
     853             :     }
     854             : 
     855             :     {
     856           1 :         float in_value = -cpl::NumericLimits<float>::max();
     857           1 :         uint64_t out_value = 0;
     858           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     859           1 :         EXPECT_EQ(out_value, 0);
     860             :     }
     861             : 
     862             :     {
     863           1 :         float in_value = cpl::NumericLimits<float>::max();
     864           1 :         uint64_t out_value = 0;
     865           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     866           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     867             :     }
     868             : 
     869             :     {
     870           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     871           1 :         uint64_t out_value = 0;
     872           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     873           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     874             :     }
     875             : 
     876             :     // Float64 to UInt64
     877             :     {
     878           1 :         double in_value = -cpl::NumericLimits<double>::quiet_NaN();
     879           1 :         uint64_t out_value = 0;
     880           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     881           1 :         EXPECT_EQ(out_value, 0);
     882             :     }
     883             : 
     884             :     {
     885           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     886           1 :         uint64_t out_value = 0;
     887           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     888           1 :         EXPECT_EQ(out_value, 0);
     889             :     }
     890             : 
     891             :     {
     892           1 :         double in_value = -cpl::NumericLimits<double>::max();
     893           1 :         uint64_t out_value = 0;
     894           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     895           1 :         EXPECT_EQ(out_value, 0);
     896             :     }
     897             : 
     898             :     {
     899           1 :         double in_value = cpl::NumericLimits<double>::max();
     900           1 :         uint64_t out_value = 0;
     901           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     902           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     903             :     }
     904             : 
     905             :     {
     906           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     907           1 :         uint64_t out_value = 0;
     908           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     909           1 :         EXPECT_EQ(out_value, UINT64_MAX);
     910             :     }
     911           1 : }
     912             : 
     913           4 : TEST_F(TestCopyWords, GDT_CInt16)
     914             : {
     915             :     /* GDT_CInt16 */
     916           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Byte, 0, 0); /* clamp */
     917           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int16, -32000, 0);
     918           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt16, 0, 0); /* clamp */
     919           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int32, -32000, 0);
     920           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt32, 0, 0); /* clamp */
     921           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float32, -32000, 0);
     922           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float64, -32000, 0);
     923           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt16, -32000, -32500);
     924           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt32, -32000, -32500);
     925           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat32, -32000, -32500);
     926           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat64, -32000, -32500);
     927          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     928          16 :          outtype = (GDALDataType)(outtype + 1))
     929             :     {
     930          16 :         FROM_C(GDT_CInt16, 127, 128, outtype, 127, 128);
     931             :     }
     932             : 
     933           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Byte, 255, 0); /* clamp */
     934           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int16, 32000, 0);
     935           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt16, 32000, 0);
     936           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int32, 32000, 0);
     937           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt32, 32000, 0);
     938           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float32, 32000, 0);
     939           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float64, 32000, 0);
     940           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt16, 32000, 32500);
     941           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt32, 32000, 32500);
     942           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat32, 32000, 32500);
     943           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat64, 32000, 32500);
     944           1 : }
     945             : 
     946           4 : TEST_F(TestCopyWords, GDT_CInt32)
     947             : {
     948             :     /* GDT_CInt32 */
     949           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Byte, 0, 0);       /* clamp */
     950           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int16, -32768, 0); /* clamp */
     951           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt16, 0, 0);     /* clamp */
     952           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int32, -33000, 0);
     953           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt32, 0, 0); /* clamp */
     954           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float32, -33000, 0);
     955           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float64, -33000, 0);
     956           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt16, -32768, -32768); /* clamp */
     957           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt32, -33000, -33500);
     958           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat32, -33000, -33500);
     959           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat64, -33000, -33500);
     960          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     961          16 :          outtype = (GDALDataType)(outtype + 1))
     962             :     {
     963          16 :         FROM_C(GDT_CInt32, 127, 128, outtype, 127, 128);
     964             :     }
     965             : 
     966           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Byte, 255, 0);     /* clamp */
     967           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int16, 32767, 0);  /* clamp */
     968           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt16, 65535, 0); /* clamp */
     969           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int32, 67000, 0);
     970           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt32, 67000, 0);
     971           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float32, 67000, 0);
     972           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float64, 67000, 0);
     973           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt16, 32767, 32767); /* clamp */
     974           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt32, 67000, 67500);
     975           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat32, 67000, 67500);
     976           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat64, 67000, 67500);
     977           1 : }
     978             : 
     979           4 : TEST_F(TestCopyWords, GDT_CFloat32and64)
     980             : {
     981             :     /* GDT_CFloat32 and GDT_CFloat64 */
     982           3 :     for (int i = 0; i < 2; i++)
     983             :     {
     984           2 :         GDALDataType intype = (i == 0) ? GDT_CFloat32 : GDT_CFloat64;
     985          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     986          32 :              outtype = (GDALDataType)(outtype + 1))
     987             :         {
     988          32 :             if (IS_FLOAT(outtype))
     989             :             {
     990          12 :                 FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
     991          12 :                 FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
     992             :             }
     993             :             else
     994             :             {
     995          20 :                 FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
     996          20 :                 FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
     997          20 :                 if (!IS_UNSIGNED(outtype))
     998             :                 {
     999          12 :                     FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
    1000             :                 }
    1001             :             }
    1002             :         }
    1003           2 :         FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
    1004           2 :         FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
    1005           2 :         FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
    1006           2 :         FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1007           2 :         FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1008           2 :         FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1009           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_Int32, INT_MIN, 0);
    1010           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_Int32, 2147483647,
    1011             :                0);
    1012           2 :         FROM_C(intype, -1, CST_5000000000, GDT_UInt32, 0, 0);
    1013           2 :         FROM_C(intype, CST_5000000000, -1, GDT_UInt32, 4294967295UL, 0);
    1014           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float32, CST_5000000000, 0);
    1015           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float64, CST_5000000000, 0);
    1016           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float32, -CST_5000000000, 0);
    1017           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float64, -CST_5000000000, 0);
    1018           2 :         FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1019           2 :         FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1020           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_CInt32, INT_MIN,
    1021             :                INT_MIN);
    1022           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_CInt32, 2147483647,
    1023             :                2147483647);
    1024           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat32,
    1025             :                CST_5000000000, -CST_5000000000);
    1026           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat64,
    1027             :                CST_5000000000, -CST_5000000000);
    1028             :     }
    1029           1 : }
    1030             : 
    1031           4 : TEST_F(TestCopyWords, GDT_CFloat16only)
    1032             : {
    1033           1 :     GDALDataType intype = GDT_CFloat16;
    1034          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
    1035          16 :          outtype = (GDALDataType)(outtype + 1))
    1036             :     {
    1037          16 :         if (IS_FLOAT(outtype))
    1038             :         {
    1039           6 :             FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
    1040           6 :             FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
    1041             :         }
    1042             :         else
    1043             :         {
    1044          10 :             FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
    1045          10 :             FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
    1046          10 :             if (!IS_UNSIGNED(outtype))
    1047             :             {
    1048           6 :                 FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
    1049             :             }
    1050             :         }
    1051             :     }
    1052           1 :     FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
    1053           1 :     FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
    1054           1 :     FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
    1055           1 :     FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1056           1 :     FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1057           1 :     FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1058           1 :     FROM_C(intype, -33000, -33000, GDT_Int32, -32992, 0);
    1059           1 :     FROM_C(intype, 33000, 33000, GDT_Int32, 32992, 0);
    1060           1 :     FROM_C(intype, -1, 33000, GDT_UInt32, 0, 0);
    1061           1 :     FROM_C(intype, 33000, -1, GDT_UInt32, 32992, 0);
    1062           1 :     FROM_C(intype, 33000, -1, GDT_Float32, 32992, 0);
    1063           1 :     FROM_C(intype, 33000, -1, GDT_Float64, 32992, 0);
    1064           1 :     FROM_C(intype, -33000, -1, GDT_Float32, -32992, 0);
    1065           1 :     FROM_C(intype, -33000, -1, GDT_Float64, -32992, 0);
    1066           1 :     FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1067           1 :     FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1068           1 :     FROM_C(intype, -33000, -33000, GDT_CInt32, -32992, -32992);
    1069           1 :     FROM_C(intype, 33000, 33000, GDT_CInt32, 32992, 32992);
    1070           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat32, 32992, -32992);
    1071           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat64, 32992, -32992);
    1072           1 : }
    1073             : 
    1074             : template <class Tin, class Tout>
    1075         121 : void CheckPackedGeneric(GDALDataType eIn, GDALDataType eOut)
    1076             : {
    1077         121 :     const int N = 64 + 7;
    1078         792 :     Tin arrayIn[N];
    1079         792 :     Tout arrayOut[N];
    1080        8712 :     for (int i = 0; i < N; i++)
    1081             :     {
    1082             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1083             :         {
    1084             :             // Test correct rounding
    1085         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1086          12 :                 arrayIn[i] = cpl::NumericLimits<Tin>::quiet_NaN();
    1087        1692 :             else if ((i % 2) != 0)
    1088         840 :                 arrayIn[i] = static_cast<Tin>(i + 0.4);
    1089             :             else
    1090         852 :                 arrayIn[i] = static_cast<Tin>(i + 0.6);
    1091             :         }
    1092             :         else
    1093             :         {
    1094        6887 :             arrayIn[i] = static_cast<Tin>(i + 1);
    1095             :         }
    1096        8591 :         arrayOut[i] = 0;
    1097             :     }
    1098         121 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1099             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1100         121 :     int numLine = 0;
    1101        8712 :     for (int i = 0; i < N; i++)
    1102             :     {
    1103             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1104             :         {
    1105         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1106             :             {
    1107          12 :                 MY_EXPECT(eIn, cpl::NumericLimits<Tin>::quiet_NaN(), eOut, 0,
    1108             :                           arrayOut[i]);
    1109             :             }
    1110        1692 :             else if ((i % 2) != 0)
    1111             :             {
    1112         840 :                 MY_EXPECT(eIn, i + 0.4, eOut, i, arrayOut[i]);
    1113             :             }
    1114             :             else
    1115             :             {
    1116         852 :                 MY_EXPECT(eIn, i + 0.6, eOut, i + 1, arrayOut[i]);
    1117             :             }
    1118             :         }
    1119             :         else
    1120             :         {
    1121        6887 :             MY_EXPECT(eIn, i + 1, eOut, i + 1, arrayOut[i]);
    1122             :         }
    1123             :     }
    1124         121 : }
    1125             : 
    1126             : template <class Tin, class Tout>
    1127         119 : void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1128             : {
    1129         119 :     CheckPackedGeneric<Tin, Tout>(eIn, eOut);
    1130         119 : }
    1131             : 
    1132             : template <>
    1133           1 : void CheckPacked<GUInt16, GByte>(GDALDataType eIn, GDALDataType eOut)
    1134             : {
    1135           1 :     CheckPackedGeneric<GUInt16, GByte>(eIn, eOut);
    1136             : 
    1137           1 :     const int N = 64 + 7;
    1138           1 :     GUInt16 arrayIn[N] = {0};
    1139           1 :     GByte arrayOut[N] = {0};
    1140          72 :     for (int i = 0; i < N; i++)
    1141             :     {
    1142         130 :         arrayIn[i] = (i % 6) == 0   ? 254
    1143          59 :                      : (i % 6) == 1 ? 255
    1144          47 :                      : (i % 4) == 2 ? 256
    1145          35 :                      : (i % 6) == 3 ? 32767
    1146          23 :                      : (i % 6) == 4 ? 32768
    1147             :                                     : 65535;
    1148             :     }
    1149           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1150             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1151           1 :     int numLine = 0;
    1152          72 :     for (int i = 0; i < N; i++)
    1153             :     {
    1154          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 6) == 0 ? 254 : 255,
    1155             :                   arrayOut[i]);
    1156             :     }
    1157           1 : }
    1158             : 
    1159             : template <>
    1160           1 : void CheckPacked<GUInt16, GInt16>(GDALDataType eIn, GDALDataType eOut)
    1161             : {
    1162           1 :     CheckPackedGeneric<GUInt16, GInt16>(eIn, eOut);
    1163             : 
    1164           1 :     const int N = 64 + 7;
    1165           1 :     GUInt16 arrayIn[N] = {0};
    1166           1 :     GInt16 arrayOut[N] = {0};
    1167          72 :     for (int i = 0; i < N; i++)
    1168             :     {
    1169          71 :         arrayIn[i] = 32766 + (i % 4);
    1170             :     }
    1171           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1172             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1173           1 :     int numLine = 0;
    1174          72 :     for (int i = 0; i < N; i++)
    1175             :     {
    1176          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 4) == 0 ? 32766 : 32767,
    1177             :                   arrayOut[i]);
    1178             :     }
    1179           1 : }
    1180             : 
    1181         121 : template <class Tin> void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1182             : {
    1183         121 :     switch (eOut)
    1184             :     {
    1185          11 :         case GDT_Byte:
    1186          11 :             CheckPacked<Tin, GByte>(eIn, eOut);
    1187          11 :             break;
    1188          11 :         case GDT_Int8:
    1189          11 :             CheckPacked<Tin, GInt8>(eIn, eOut);
    1190          11 :             break;
    1191          11 :         case GDT_UInt16:
    1192          11 :             CheckPacked<Tin, GUInt16>(eIn, eOut);
    1193          11 :             break;
    1194          11 :         case GDT_Int16:
    1195          11 :             CheckPacked<Tin, GInt16>(eIn, eOut);
    1196          11 :             break;
    1197          11 :         case GDT_UInt32:
    1198          11 :             CheckPacked<Tin, GUInt32>(eIn, eOut);
    1199          11 :             break;
    1200          11 :         case GDT_Int32:
    1201          11 :             CheckPacked<Tin, GInt32>(eIn, eOut);
    1202          11 :             break;
    1203          11 :         case GDT_UInt64:
    1204          11 :             CheckPacked<Tin, std::uint64_t>(eIn, eOut);
    1205          11 :             break;
    1206          11 :         case GDT_Int64:
    1207          11 :             CheckPacked<Tin, std::int64_t>(eIn, eOut);
    1208          11 :             break;
    1209          11 :         case GDT_Float16:
    1210          11 :             CheckPacked<Tin, GFloat16>(eIn, eOut);
    1211          11 :             break;
    1212          11 :         case GDT_Float32:
    1213          11 :             CheckPacked<Tin, float>(eIn, eOut);
    1214          11 :             break;
    1215          11 :         case GDT_Float64:
    1216          11 :             CheckPacked<Tin, double>(eIn, eOut);
    1217          11 :             break;
    1218           0 :         default:
    1219           0 :             CPLAssert(false);
    1220             :     }
    1221         121 : }
    1222             : 
    1223         121 : static void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1224             : {
    1225         121 :     switch (eIn)
    1226             :     {
    1227          11 :         case GDT_Byte:
    1228          11 :             CheckPacked<GByte>(eIn, eOut);
    1229          11 :             break;
    1230          11 :         case GDT_Int8:
    1231          11 :             CheckPacked<GInt8>(eIn, eOut);
    1232          11 :             break;
    1233          11 :         case GDT_UInt16:
    1234          11 :             CheckPacked<GUInt16>(eIn, eOut);
    1235          11 :             break;
    1236          11 :         case GDT_Int16:
    1237          11 :             CheckPacked<GInt16>(eIn, eOut);
    1238          11 :             break;
    1239          11 :         case GDT_UInt32:
    1240          11 :             CheckPacked<GUInt32>(eIn, eOut);
    1241          11 :             break;
    1242          11 :         case GDT_Int32:
    1243          11 :             CheckPacked<GInt32>(eIn, eOut);
    1244          11 :             break;
    1245          11 :         case GDT_UInt64:
    1246          11 :             CheckPacked<std::uint64_t>(eIn, eOut);
    1247          11 :             break;
    1248          11 :         case GDT_Int64:
    1249          11 :             CheckPacked<std::int64_t>(eIn, eOut);
    1250          11 :             break;
    1251          11 :         case GDT_Float16:
    1252          11 :             CheckPacked<GFloat16>(eIn, eOut);
    1253          11 :             break;
    1254          11 :         case GDT_Float32:
    1255          11 :             CheckPacked<float>(eIn, eOut);
    1256          11 :             break;
    1257          11 :         case GDT_Float64:
    1258          11 :             CheckPacked<double>(eIn, eOut);
    1259          11 :             break;
    1260           0 :         default:
    1261           0 :             CPLAssert(false);
    1262             :     }
    1263         121 : }
    1264             : 
    1265             : class TestCopyWordsCheckPackedFixture
    1266             :     : public TestCopyWords,
    1267             :       public ::testing::WithParamInterface<
    1268             :           std::tuple<GDALDataType, GDALDataType>>
    1269             : {
    1270             : };
    1271             : 
    1272         243 : TEST_P(TestCopyWordsCheckPackedFixture, CheckPacked)
    1273             : {
    1274         121 :     GDALDataType eIn = std::get<0>(GetParam());
    1275         121 :     GDALDataType eOut = std::get<1>(GetParam());
    1276         121 :     CheckPacked(eIn, eOut);
    1277         121 : }
    1278             : 
    1279             : static std::vector<std::tuple<GDALDataType, GDALDataType>>
    1280           1 : GetGDALDataTypeTupleValues()
    1281             : {
    1282           1 :     std::vector<std::tuple<GDALDataType, GDALDataType>> ret;
    1283          17 :     for (GDALDataType eIn = GDT_Byte; eIn < GDT_TypeCount;
    1284          16 :          eIn = static_cast<GDALDataType>(eIn + 1))
    1285             :     {
    1286          16 :         if (GDALDataTypeIsComplex(eIn))
    1287           5 :             continue;
    1288         187 :         for (GDALDataType eOut = GDT_Byte; eOut < GDT_TypeCount;
    1289         176 :              eOut = static_cast<GDALDataType>(eOut + 1))
    1290             :         {
    1291         176 :             if (GDALDataTypeIsComplex(eOut))
    1292          55 :                 continue;
    1293         121 :             ret.emplace_back(std::make_tuple(eIn, eOut));
    1294             :         }
    1295             :     }
    1296           1 :     return ret;
    1297             : }
    1298             : 
    1299         365 : INSTANTIATE_TEST_SUITE_P(
    1300             :     TestCopyWords, TestCopyWordsCheckPackedFixture,
    1301             :     ::testing::ValuesIn(GetGDALDataTypeTupleValues()),
    1302             :     [](const ::testing::TestParamInfo<
    1303             :         TestCopyWordsCheckPackedFixture::ParamType> &l_info)
    1304             :     {
    1305             :         GDALDataType eIn = std::get<0>(l_info.param);
    1306             :         GDALDataType eOut = std::get<1>(l_info.param);
    1307             :         return std::string(GDALGetDataTypeName(eIn)) + "_" +
    1308             :                GDALGetDataTypeName(eOut);
    1309             :     });
    1310             : 
    1311           4 : TEST_F(TestCopyWords, ByteToByte)
    1312             : {
    1313           3 :     for (int k = 0; k < 2; k++)
    1314             :     {
    1315           2 :         if (k == 1)
    1316           1 :             CPLSetConfigOption("GDAL_USE_SSSE3", "NO");
    1317             : 
    1318           8 :         for (int spacing = 2; spacing <= 4; spacing++)
    1319             :         {
    1320           6 :             memset(pIn, 0xff, 256);
    1321         108 :             for (int i = 0; i < 17; i++)
    1322             :             {
    1323         102 :                 pIn[spacing * i] = (GByte)(17 - i);
    1324             :             }
    1325           6 :             memset(pOut, 0xff, 256);
    1326           6 :             GDALCopyWords(pIn, GDT_Byte, spacing, pOut, GDT_Byte, 1, 17);
    1327         108 :             for (int i = 0; i < 17; i++)
    1328             :             {
    1329         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i],
    1330             :                           __LINE__);
    1331             :             }
    1332             : 
    1333           6 :             memset(pIn, 0xff, 256);
    1334           6 :             memset(pOut, 0xff, 256);
    1335         108 :             for (int i = 0; i < 17; i++)
    1336             :             {
    1337         102 :                 pIn[i] = (GByte)(17 - i);
    1338             :             }
    1339           6 :             GDALCopyWords(pIn, GDT_Byte, 1, pOut, GDT_Byte, spacing, 17);
    1340         108 :             for (int i = 0; i < 17; i++)
    1341             :             {
    1342         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i * spacing],
    1343             :                           __LINE__);
    1344         306 :                 for (int j = 1; j < spacing; j++)
    1345             :                 {
    1346         204 :                     AssertRes(GDT_Byte, 0xff, GDT_Byte, 0xff,
    1347         204 :                               pOut[i * spacing + j], __LINE__);
    1348             :                 }
    1349             :             }
    1350             :         }
    1351             :     }
    1352           1 :     CPLSetConfigOption("GDAL_USE_SSSE3", nullptr);
    1353           1 : }
    1354             : 
    1355           4 : TEST_F(TestCopyWords, Int16ToInt16)
    1356             : {
    1357           1 :     memset(pIn, 0xff, 256);
    1358           1 :     GInt16 *pInShort = (GInt16 *)pIn;
    1359           1 :     GInt16 *pOutShort = (GInt16 *)pOut;
    1360          10 :     for (int i = 0; i < 9; i++)
    1361             :     {
    1362           9 :         pInShort[2 * i + 0] = 0x1234;
    1363           9 :         pInShort[2 * i + 1] = 0x5678;
    1364             :     }
    1365           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1366             :     {
    1367           4 :         memset(pOut, 0xff, 256);
    1368           4 :         GDALCopyWords(pInShort, GDT_Int16, sizeof(short), pOutShort, GDT_Int16,
    1369           4 :                       (iSpacing + 1) * sizeof(short), 18);
    1370          40 :         for (int i = 0; i < 9; i++)
    1371             :         {
    1372          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 0], GDT_Int16,
    1373          36 :                       pInShort[2 * i + 0],
    1374          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 0)], __LINE__);
    1375          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 1], GDT_Int16,
    1376          36 :                       pInShort[2 * i + 1],
    1377          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 1)], __LINE__);
    1378             :         }
    1379             :     }
    1380           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1381             :     {
    1382           4 :         memset(pIn, 0xff, 256);
    1383           4 :         memset(pOut, 0xff, 256);
    1384          40 :         for (int i = 0; i < 9; i++)
    1385             :         {
    1386          36 :             pInShort[(iSpacing + 1) * (2 * i + 0)] = 0x1234;
    1387          36 :             pInShort[(iSpacing + 1) * (2 * i + 1)] = 0x5678;
    1388             :         }
    1389           4 :         GDALCopyWords(pInShort, GDT_Int16, (iSpacing + 1) * sizeof(short),
    1390             :                       pOutShort, GDT_Int16, sizeof(short), 18);
    1391          40 :         for (int i = 0; i < 9; i++)
    1392             :         {
    1393          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1394          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1395          36 :                       pOutShort[2 * i + 0], __LINE__);
    1396          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1397          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1398          36 :                       pOutShort[2 * i + 1], __LINE__);
    1399             :         }
    1400             :     }
    1401           1 : }
    1402             : 
    1403             : }  // namespace

Generated by: LCOV version 1.14