LCOV - code coverage report
Current view: top level - autotest/cpp - testcopywords.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 863 872 99.0 %
Date: 2025-07-08 21:33:46 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       59991 : void AssertRes(GDALDataType intype, CT1 inval, GDALDataType outtype,
      32             :                CT2 expected_outval, OutType outval, int numLine)
      33             : {
      34       62729 :     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       59991 : }
      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        1024 :     void Test(GDALDataType intype, ConstantType inval, ConstantType invali,
      75             :               GDALDataType outtype, ConstantType outval, ConstantType outvali,
      76             :               int numLine)
      77             :     {
      78        1024 :         memset(pIn, 0xff, 1024);
      79        1024 :         memset(pOut, 0xff, 1024);
      80             : 
      81        1024 :         *(InType *)(pIn) = (InType)inval;
      82        1024 :         *(InType *)(pIn + 32) = (InType)inval;
      83        1024 :         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        1024 :         GDALCopyWords(pIn, intype, 32, pOut, outtype, 32, 2);
      91             : 
      92             :         /* Test negative offsets */
      93        1024 :         GDALCopyWords(pIn + 32, intype, -32, pOut + 1024 - 16, outtype, -32, 2);
      94             : 
      95        1024 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut));
      96        1024 :         MY_EXPECT(intype, inval, outtype, outval, *(OutType *)(pOut + 32));
      97        1024 :         MY_EXPECT(intype, inval, outtype, outval,
      98             :                   *(OutType *)(pOut + 1024 - 16));
      99        1024 :         MY_EXPECT(intype, inval, outtype, outval,
     100             :                   *(OutType *)(pOut + 1024 - 16 - 32));
     101             : 
     102        1024 :         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         720 :             constexpr int N = 32 + 31;
     116       46080 :             for (int i = 0; i < N; ++i)
     117             :             {
     118       45360 :                 *(InType *)(pIn + i * GDALGetDataTypeSizeBytes(intype)) =
     119        8694 :                     (InType)inval;
     120             :             }
     121             : 
     122             :             /* Test packed offsets */
     123         720 :             GDALCopyWords(pIn, intype, GDALGetDataTypeSizeBytes(intype), pOut,
     124             :                           outtype, GDALGetDataTypeSizeBytes(outtype), N);
     125             : 
     126       46080 :             for (int i = 0; i < N; ++i)
     127             :             {
     128       45360 :                 MY_EXPECT(
     129             :                     intype, inval, outtype, outval,
     130             :                     *(OutType *)(pOut + i * GDALGetDataTypeSizeBytes(outtype)));
     131             :             }
     132             :         }
     133        1024 :     }
     134             : 
     135             :     template <class InType, class ConstantType>
     136        1024 :     void FromR_2(GDALDataType intype, ConstantType inval, ConstantType invali,
     137             :                  GDALDataType outtype, ConstantType outval,
     138             :                  ConstantType outvali, int numLine)
     139             :     {
     140        1024 :         if (outtype == GDT_Byte)
     141          77 :             Test<InType, GByte, ConstantType>(intype, inval, invali, outtype,
     142             :                                               outval, outvali, numLine);
     143         947 :         else if (outtype == GDT_Int8)
     144          61 :             Test<InType, GInt8, ConstantType>(intype, inval, invali, outtype,
     145             :                                               outval, outvali, numLine);
     146         886 :         else if (outtype == GDT_Int16)
     147          92 :             Test<InType, GInt16, ConstantType>(intype, inval, invali, outtype,
     148             :                                                outval, outvali, numLine);
     149         794 :         else if (outtype == GDT_UInt16)
     150          71 :             Test<InType, GUInt16, ConstantType>(intype, inval, invali, outtype,
     151             :                                                 outval, outvali, numLine);
     152         723 :         else if (outtype == GDT_Int32)
     153          87 :             Test<InType, GInt32, ConstantType>(intype, inval, invali, outtype,
     154             :                                                outval, outvali, numLine);
     155         636 :         else if (outtype == GDT_UInt32)
     156          66 :             Test<InType, GUInt32, ConstantType>(intype, inval, invali, outtype,
     157             :                                                 outval, outvali, numLine);
     158         570 :         else if (outtype == GDT_Int64)
     159          71 :             Test<InType, std::int64_t, ConstantType>(
     160             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     161         499 :         else if (outtype == GDT_UInt64)
     162          50 :             Test<InType, std::uint64_t, ConstantType>(
     163             :                 intype, inval, invali, outtype, outval, outvali, numLine);
     164         449 :         else if (outtype == GDT_Float16)
     165          34 :             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        1024 :     }
     189             : 
     190             :     template <class ConstantType>
     191        1024 :     void FromR(GDALDataType intype, ConstantType inval, ConstantType invali,
     192             :                GDALDataType outtype, ConstantType outval, ConstantType outvali,
     193             :                int numLine)
     194             :     {
     195        1024 :         if (intype == GDT_Byte)
     196          47 :             FromR_2<GByte, ConstantType>(intype, inval, invali, outtype, outval,
     197             :                                          outvali, numLine);
     198         977 :         else if (intype == GDT_Int8)
     199          46 :             FromR_2<GInt8, ConstantType>(intype, inval, invali, outtype, outval,
     200             :                                          outvali, numLine);
     201         931 :         else if (intype == GDT_Int16)
     202          42 :             FromR_2<GInt16, ConstantType>(intype, inval, invali, outtype,
     203             :                                           outval, outvali, numLine);
     204         889 :         else if (intype == GDT_UInt16)
     205          45 :             FromR_2<GUInt16, ConstantType>(intype, inval, invali, outtype,
     206             :                                            outval, outvali, numLine);
     207         844 :         else if (intype == GDT_Int32)
     208          45 :             FromR_2<GInt32, ConstantType>(intype, inval, invali, outtype,
     209             :                                           outval, outvali, numLine);
     210         799 :         else if (intype == GDT_UInt32)
     211          45 :             FromR_2<GUInt32, ConstantType>(intype, inval, invali, outtype,
     212             :                                            outval, outvali, numLine);
     213         754 :         else if (intype == GDT_Int64)
     214          39 :             FromR_2<std::int64_t, ConstantType>(intype, inval, invali, outtype,
     215             :                                                 outval, outvali, numLine);
     216         715 :         else if (intype == GDT_UInt64)
     217          45 :             FromR_2<std::uint64_t, ConstantType>(intype, inval, invali, outtype,
     218             :                                                  outval, outvali, numLine);
     219         670 :         else if (intype == GDT_Float16)
     220         135 :             FromR_2<GFloat16, ConstantType>(intype, inval, invali, outtype,
     221             :                                             outval, outvali, numLine);
     222         535 :         else if (intype == GDT_Float32)
     223         141 :             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        1024 :     }
     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>::max(), GDT_Float16,
     603             :              std::numeric_limits<double>::infinity());
     604           1 :     FROM_R_F(GDT_Float32, -std::numeric_limits<float>::max(), GDT_Float16,
     605             :              -std::numeric_limits<double>::infinity());
     606           1 :     FROM_R_F(GDT_Float32, std::numeric_limits<float>::quiet_NaN(), GDT_Float16,
     607             :              std::numeric_limits<double>::quiet_NaN());
     608             : 
     609           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::max(), GDT_Float16,
     610             :              std::numeric_limits<double>::infinity());
     611           1 :     FROM_R_F(GDT_Float64, -std::numeric_limits<double>::max(), GDT_Float16,
     612             :              -std::numeric_limits<double>::infinity());
     613           1 :     FROM_R_F(GDT_Float64, std::numeric_limits<double>::quiet_NaN(), GDT_Float16,
     614             :              std::numeric_limits<double>::quiet_NaN());
     615             : 
     616             :     // Float16 to Int64
     617             :     {
     618           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     619           1 :         int64_t out_value = 0;
     620           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_Int64, 0, 1);
     621           1 :         EXPECT_EQ(out_value, 0);
     622             :     }
     623             : 
     624             :     {
     625           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     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, INT64_MIN);
     629             :     }
     630             : 
     631             :     {
     632           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::max();
     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, -65504);
     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>::infinity();
     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, INT64_MAX);
     650             :     }
     651             : 
     652             :     // Float16 to UInt64
     653             :     {
     654           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::quiet_NaN();
     655           1 :         uint64_t out_value = 0;
     656           1 :         GDALCopyWords(&in_value, GDT_Float16, 0, &out_value, GDT_UInt64, 0, 1);
     657           1 :         EXPECT_EQ(out_value, 0);
     658             :     }
     659             : 
     660             :     {
     661           1 :         GFloat16 in_value = -cpl::NumericLimits<GFloat16>::infinity();
     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>::max();
     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, 65504);
     679             :     }
     680             : 
     681             :     {
     682           1 :         GFloat16 in_value = cpl::NumericLimits<GFloat16>::infinity();
     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, UINT64_MAX);
     686             :     }
     687           1 : }
     688             : 
     689           4 : TEST_F(TestCopyWords, GDT_Float32and64)
     690             : {
     691             :     /* GDT_Float32 and GDT_Float64 */
     692           3 :     for (int i = 0; i < 2; i++)
     693             :     {
     694           2 :         GDALDataType intype = (i == 0) ? GDT_Float32 : GDT_Float64;
     695          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     696          32 :              outtype = (GDALDataType)(outtype + 1))
     697             :         {
     698          32 :             if (IS_FLOAT(outtype))
     699             :             {
     700          12 :                 FROM_R_F(intype, 127.1, outtype, 127.1);
     701          12 :                 FROM_R_F(intype, -127.1, outtype, -127.1);
     702             :             }
     703             :             else
     704             :             {
     705          20 :                 FROM_R_F(intype, 125.1, outtype, 125);
     706          20 :                 FROM_R_F(intype, 125.9, outtype, 126);
     707             : 
     708          20 :                 FROM_R_F(intype, 0.4, outtype, 0);
     709          20 :                 FROM_R_F(intype, 0.5, outtype,
     710             :                          1); /* We could argue how to do this rounding */
     711          20 :                 FROM_R_F(intype, 0.6, outtype, 1);
     712          20 :                 FROM_R_F(intype, 126.5, outtype,
     713             :                          127); /* We could argue how to do this rounding */
     714             : 
     715          20 :                 if (!IS_UNSIGNED(outtype))
     716             :                 {
     717          12 :                     FROM_R_F(intype, -125.9, outtype, -126);
     718          12 :                     FROM_R_F(intype, -127.1, outtype, -127);
     719             : 
     720          12 :                     FROM_R_F(intype, -0.4, outtype, 0);
     721          12 :                     FROM_R_F(intype, -0.5, outtype,
     722             :                              -1); /* We could argue how to do this rounding */
     723          12 :                     FROM_R_F(intype, -0.6, outtype, -1);
     724          12 :                     FROM_R_F(intype, -127.5, outtype,
     725             :                              -128); /* We could argue how to do this rounding */
     726             :                 }
     727             :             }
     728             :         }
     729           2 :         FROM_R(intype, -CST_3000000000, GDT_Byte, 0);
     730           2 :         FROM_R(intype, -32768, GDT_Byte, 0);
     731           2 :         FROM_R(intype, -1, GDT_Byte, 0);
     732           2 :         FROM_R(intype, 256, GDT_Byte, 255);
     733           2 :         FROM_R(intype, 65536, GDT_Byte, 255);
     734           2 :         FROM_R(intype, CST_3000000000, GDT_Byte, 255);
     735           2 :         FROM_R(intype, -CST_3000000000, GDT_Int16, -32768);
     736           2 :         FROM_R(intype, -33000, GDT_Int16, -32768);
     737           2 :         FROM_R(intype, 33000, GDT_Int16, 32767);
     738           2 :         FROM_R(intype, CST_3000000000, GDT_Int16, 32767);
     739           2 :         FROM_R(intype, -CST_3000000000, GDT_UInt16, 0);
     740           2 :         FROM_R(intype, -1, GDT_UInt16, 0);
     741           2 :         FROM_R(intype, 66000, GDT_UInt16, 65535);
     742           2 :         FROM_R(intype, CST_3000000000, GDT_UInt16, 65535);
     743           2 :         FROM_R(intype, -CST_3000000000, GDT_Int32, INT_MIN);
     744           2 :         FROM_R(intype, CST_3000000000, GDT_Int32, 2147483647);
     745           2 :         FROM_R(intype, -1, GDT_UInt32, 0);
     746           2 :         FROM_R(intype, CST_5000000000, GDT_UInt32, 4294967295UL);
     747           2 :         FROM_R(intype, CST_5000000000, GDT_Float32, CST_5000000000);
     748           2 :         FROM_R(intype, -CST_5000000000, GDT_Float32, -CST_5000000000);
     749           2 :         FROM_R(intype, CST_5000000000, GDT_Float64, CST_5000000000);
     750           2 :         FROM_R(intype, -CST_5000000000, GDT_Float64, -CST_5000000000);
     751           2 :         FROM_R(intype, -33000, GDT_CInt16, -32768);
     752           2 :         FROM_R(intype, 33000, GDT_CInt16, 32767);
     753           2 :         FROM_R(intype, -CST_3000000000, GDT_CInt32, INT_MIN);
     754           2 :         FROM_R(intype, CST_3000000000, GDT_CInt32, 2147483647);
     755           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat32, CST_5000000000);
     756           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat32, -CST_5000000000);
     757           2 :         FROM_R(intype, CST_5000000000, GDT_CFloat64, CST_5000000000);
     758           2 :         FROM_R(intype, -CST_5000000000, GDT_CFloat64, -CST_5000000000);
     759             :     }
     760             : 
     761             :     // Float32 to Int64
     762             :     {
     763           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     764           1 :         int64_t out_value = 0;
     765           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_Int64, 0, 1);
     766           1 :         EXPECT_EQ(out_value, 0);
     767             :     }
     768             : 
     769             :     {
     770           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     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, INT64_MIN);
     774             :     }
     775             : 
     776             :     {
     777           1 :         float in_value = -cpl::NumericLimits<float>::max();
     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_MAX);
     788             :     }
     789             : 
     790             :     {
     791           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     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             :     // Float64 to Int64
     798             :     {
     799           1 :         double in_value = cpl::NumericLimits<double>::quiet_NaN();
     800           1 :         int64_t out_value = 0;
     801           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_Int64, 0, 1);
     802           1 :         EXPECT_EQ(out_value, 0);
     803             :     }
     804             : 
     805             :     {
     806           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     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, INT64_MIN);
     810             :     }
     811             : 
     812             :     {
     813           1 :         double in_value = -cpl::NumericLimits<double>::max();
     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_MAX);
     824             :     }
     825             : 
     826             :     {
     827           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     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             :     // Float32 to UInt64
     834             :     {
     835           1 :         float in_value = cpl::NumericLimits<float>::quiet_NaN();
     836           1 :         uint64_t out_value = 0;
     837           1 :         GDALCopyWords(&in_value, GDT_Float32, 0, &out_value, GDT_UInt64, 0, 1);
     838           1 :         EXPECT_EQ(out_value, 0);
     839             :     }
     840             : 
     841             :     {
     842           1 :         float in_value = -cpl::NumericLimits<float>::infinity();
     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>::max();
     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, UINT64_MAX);
     860             :     }
     861             : 
     862             :     {
     863           1 :         float in_value = cpl::NumericLimits<float>::infinity();
     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             :     // Float64 to UInt64
     870             :     {
     871           1 :         double in_value = -cpl::NumericLimits<double>::quiet_NaN();
     872           1 :         uint64_t out_value = 0;
     873           1 :         GDALCopyWords(&in_value, GDT_Float64, 0, &out_value, GDT_UInt64, 0, 1);
     874           1 :         EXPECT_EQ(out_value, 0);
     875             :     }
     876             : 
     877             :     {
     878           1 :         double in_value = -cpl::NumericLimits<double>::infinity();
     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>::max();
     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, UINT64_MAX);
     896             :     }
     897             : 
     898             :     {
     899           1 :         double in_value = cpl::NumericLimits<double>::infinity();
     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           1 : }
     905             : 
     906           4 : TEST_F(TestCopyWords, GDT_CInt16)
     907             : {
     908             :     /* GDT_CInt16 */
     909           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Byte, 0, 0); /* clamp */
     910           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int16, -32000, 0);
     911           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt16, 0, 0); /* clamp */
     912           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Int32, -32000, 0);
     913           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_UInt32, 0, 0); /* clamp */
     914           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float32, -32000, 0);
     915           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_Float64, -32000, 0);
     916           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt16, -32000, -32500);
     917           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt32, -32000, -32500);
     918           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat32, -32000, -32500);
     919           1 :     FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat64, -32000, -32500);
     920          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     921          16 :          outtype = (GDALDataType)(outtype + 1))
     922             :     {
     923          16 :         FROM_C(GDT_CInt16, 127, 128, outtype, 127, 128);
     924             :     }
     925             : 
     926           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Byte, 255, 0); /* clamp */
     927           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int16, 32000, 0);
     928           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt16, 32000, 0);
     929           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Int32, 32000, 0);
     930           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_UInt32, 32000, 0);
     931           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float32, 32000, 0);
     932           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_Float64, 32000, 0);
     933           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt16, 32000, 32500);
     934           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CInt32, 32000, 32500);
     935           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat32, 32000, 32500);
     936           1 :     FROM_C(GDT_CInt16, 32000, 32500, GDT_CFloat64, 32000, 32500);
     937           1 : }
     938             : 
     939           4 : TEST_F(TestCopyWords, GDT_CInt32)
     940             : {
     941             :     /* GDT_CInt32 */
     942           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Byte, 0, 0);       /* clamp */
     943           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int16, -32768, 0); /* clamp */
     944           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt16, 0, 0);     /* clamp */
     945           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Int32, -33000, 0);
     946           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_UInt32, 0, 0); /* clamp */
     947           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float32, -33000, 0);
     948           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_Float64, -33000, 0);
     949           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt16, -32768, -32768); /* clamp */
     950           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt32, -33000, -33500);
     951           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat32, -33000, -33500);
     952           1 :     FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat64, -33000, -33500);
     953          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     954          16 :          outtype = (GDALDataType)(outtype + 1))
     955             :     {
     956          16 :         FROM_C(GDT_CInt32, 127, 128, outtype, 127, 128);
     957             :     }
     958             : 
     959           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Byte, 255, 0);     /* clamp */
     960           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int16, 32767, 0);  /* clamp */
     961           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt16, 65535, 0); /* clamp */
     962           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Int32, 67000, 0);
     963           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_UInt32, 67000, 0);
     964           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float32, 67000, 0);
     965           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_Float64, 67000, 0);
     966           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt16, 32767, 32767); /* clamp */
     967           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CInt32, 67000, 67500);
     968           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat32, 67000, 67500);
     969           1 :     FROM_C(GDT_CInt32, 67000, 67500, GDT_CFloat64, 67000, 67500);
     970           1 : }
     971             : 
     972           4 : TEST_F(TestCopyWords, GDT_CFloat32and64)
     973             : {
     974             :     /* GDT_CFloat32 and GDT_CFloat64 */
     975           3 :     for (int i = 0; i < 2; i++)
     976             :     {
     977           2 :         GDALDataType intype = (i == 0) ? GDT_CFloat32 : GDT_CFloat64;
     978          34 :         for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
     979          32 :              outtype = (GDALDataType)(outtype + 1))
     980             :         {
     981          32 :             if (IS_FLOAT(outtype))
     982             :             {
     983          12 :                 FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
     984          12 :                 FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
     985             :             }
     986             :             else
     987             :             {
     988          20 :                 FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
     989          20 :                 FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
     990          20 :                 if (!IS_UNSIGNED(outtype))
     991             :                 {
     992          12 :                     FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
     993             :                 }
     994             :             }
     995             :         }
     996           2 :         FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
     997           2 :         FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
     998           2 :         FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
     999           2 :         FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1000           2 :         FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1001           2 :         FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1002           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_Int32, INT_MIN, 0);
    1003           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_Int32, 2147483647,
    1004             :                0);
    1005           2 :         FROM_C(intype, -1, CST_5000000000, GDT_UInt32, 0, 0);
    1006           2 :         FROM_C(intype, CST_5000000000, -1, GDT_UInt32, 4294967295UL, 0);
    1007           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float32, CST_5000000000, 0);
    1008           2 :         FROM_C(intype, CST_5000000000, -1, GDT_Float64, CST_5000000000, 0);
    1009           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float32, -CST_5000000000, 0);
    1010           2 :         FROM_C(intype, -CST_5000000000, -1, GDT_Float64, -CST_5000000000, 0);
    1011           2 :         FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1012           2 :         FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1013           2 :         FROM_C(intype, -CST_3000000000, -CST_3000000000, GDT_CInt32, INT_MIN,
    1014             :                INT_MIN);
    1015           2 :         FROM_C(intype, CST_3000000000, CST_3000000000, GDT_CInt32, 2147483647,
    1016             :                2147483647);
    1017           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat32,
    1018             :                CST_5000000000, -CST_5000000000);
    1019           2 :         FROM_C(intype, CST_5000000000, -CST_5000000000, GDT_CFloat64,
    1020             :                CST_5000000000, -CST_5000000000);
    1021             :     }
    1022           1 : }
    1023             : 
    1024           4 : TEST_F(TestCopyWords, GDT_CFloat16only)
    1025             : {
    1026           1 :     GDALDataType intype = GDT_CFloat16;
    1027          17 :     for (GDALDataType outtype = GDT_Byte; outtype < GDT_TypeCount;
    1028          16 :          outtype = (GDALDataType)(outtype + 1))
    1029             :     {
    1030          16 :         if (IS_FLOAT(outtype))
    1031             :         {
    1032           6 :             FROM_C_F(intype, 127.1, 127.9, outtype, 127.1, 127.9);
    1033           6 :             FROM_C_F(intype, -127.1, -127.9, outtype, -127.1, -127.9);
    1034             :         }
    1035             :         else
    1036             :         {
    1037          10 :             FROM_C_F(intype, 126.1, 150.9, outtype, 126, 151);
    1038          10 :             FROM_C_F(intype, 126.9, 150.1, outtype, 127, 150);
    1039          10 :             if (!IS_UNSIGNED(outtype))
    1040             :             {
    1041           6 :                 FROM_C_F(intype, -125.9, -127.1, outtype, -126, -127);
    1042             :             }
    1043             :         }
    1044             :     }
    1045           1 :     FROM_C(intype, -1, 256, GDT_Byte, 0, 0);
    1046           1 :     FROM_C(intype, 256, -1, GDT_Byte, 255, 0);
    1047           1 :     FROM_C(intype, -33000, 33000, GDT_Int16, -32768, 0);
    1048           1 :     FROM_C(intype, 33000, -33000, GDT_Int16, 32767, 0);
    1049           1 :     FROM_C(intype, -1, 66000, GDT_UInt16, 0, 0);
    1050           1 :     FROM_C(intype, 66000, -1, GDT_UInt16, 65535, 0);
    1051           1 :     FROM_C(intype, -33000, -33000, GDT_Int32, -32992, 0);
    1052           1 :     FROM_C(intype, 33000, 33000, GDT_Int32, 32992, 0);
    1053           1 :     FROM_C(intype, -1, 33000, GDT_UInt32, 0, 0);
    1054           1 :     FROM_C(intype, 33000, -1, GDT_UInt32, 32992, 0);
    1055           1 :     FROM_C(intype, 33000, -1, GDT_Float32, 32992, 0);
    1056           1 :     FROM_C(intype, 33000, -1, GDT_Float64, 32992, 0);
    1057           1 :     FROM_C(intype, -33000, -1, GDT_Float32, -32992, 0);
    1058           1 :     FROM_C(intype, -33000, -1, GDT_Float64, -32992, 0);
    1059           1 :     FROM_C(intype, -33000, 33000, GDT_CInt16, -32768, 32767);
    1060           1 :     FROM_C(intype, 33000, -33000, GDT_CInt16, 32767, -32768);
    1061           1 :     FROM_C(intype, -33000, -33000, GDT_CInt32, -32992, -32992);
    1062           1 :     FROM_C(intype, 33000, 33000, GDT_CInt32, 32992, 32992);
    1063           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat32, 32992, -32992);
    1064           1 :     FROM_C(intype, 33000, -33000, GDT_CFloat64, 32992, -32992);
    1065           1 : }
    1066             : 
    1067             : template <class Tin, class Tout>
    1068         121 : void CheckPackedGeneric(GDALDataType eIn, GDALDataType eOut)
    1069             : {
    1070         121 :     const int N = 64 + 7;
    1071         792 :     Tin arrayIn[N];
    1072         792 :     Tout arrayOut[N];
    1073        8712 :     for (int i = 0; i < N; i++)
    1074             :     {
    1075             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1076             :         {
    1077             :             // Test correct rounding
    1078         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1079          12 :                 arrayIn[i] = cpl::NumericLimits<Tin>::quiet_NaN();
    1080        1692 :             else if ((i % 2) != 0)
    1081         840 :                 arrayIn[i] = static_cast<Tin>(i + 0.4);
    1082             :             else
    1083         852 :                 arrayIn[i] = static_cast<Tin>(i + 0.6);
    1084             :         }
    1085             :         else
    1086             :         {
    1087        6887 :             arrayIn[i] = static_cast<Tin>(i + 1);
    1088             :         }
    1089        8591 :         arrayOut[i] = 0;
    1090             :     }
    1091         121 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1092             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1093         121 :     int numLine = 0;
    1094        8712 :     for (int i = 0; i < N; i++)
    1095             :     {
    1096             :         if constexpr (!std::is_integral_v<Tin> && std::is_integral_v<Tout>)
    1097             :         {
    1098         852 :             if (i == 0 && std::is_unsigned_v<Tout>)
    1099             :             {
    1100          12 :                 MY_EXPECT(eIn, cpl::NumericLimits<Tin>::quiet_NaN(), eOut, 0,
    1101             :                           arrayOut[i]);
    1102             :             }
    1103        1692 :             else if ((i % 2) != 0)
    1104             :             {
    1105         840 :                 MY_EXPECT(eIn, i + 0.4, eOut, i, arrayOut[i]);
    1106             :             }
    1107             :             else
    1108             :             {
    1109         852 :                 MY_EXPECT(eIn, i + 0.6, eOut, i + 1, arrayOut[i]);
    1110             :             }
    1111             :         }
    1112             :         else
    1113             :         {
    1114        6887 :             MY_EXPECT(eIn, i + 1, eOut, i + 1, arrayOut[i]);
    1115             :         }
    1116             :     }
    1117         121 : }
    1118             : 
    1119             : template <class Tin, class Tout>
    1120         119 : void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1121             : {
    1122         119 :     CheckPackedGeneric<Tin, Tout>(eIn, eOut);
    1123         119 : }
    1124             : 
    1125             : template <>
    1126           1 : void CheckPacked<GUInt16, GByte>(GDALDataType eIn, GDALDataType eOut)
    1127             : {
    1128           1 :     CheckPackedGeneric<GUInt16, GByte>(eIn, eOut);
    1129             : 
    1130           1 :     const int N = 64 + 7;
    1131           1 :     GUInt16 arrayIn[N] = {0};
    1132           1 :     GByte arrayOut[N] = {0};
    1133          72 :     for (int i = 0; i < N; i++)
    1134             :     {
    1135         130 :         arrayIn[i] = (i % 6) == 0   ? 254
    1136          59 :                      : (i % 6) == 1 ? 255
    1137          47 :                      : (i % 4) == 2 ? 256
    1138          35 :                      : (i % 6) == 3 ? 32767
    1139          23 :                      : (i % 6) == 4 ? 32768
    1140             :                                     : 65535;
    1141             :     }
    1142           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1143             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1144           1 :     int numLine = 0;
    1145          72 :     for (int i = 0; i < N; i++)
    1146             :     {
    1147          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 6) == 0 ? 254 : 255,
    1148             :                   arrayOut[i]);
    1149             :     }
    1150           1 : }
    1151             : 
    1152             : template <>
    1153           1 : void CheckPacked<GUInt16, GInt16>(GDALDataType eIn, GDALDataType eOut)
    1154             : {
    1155           1 :     CheckPackedGeneric<GUInt16, GInt16>(eIn, eOut);
    1156             : 
    1157           1 :     const int N = 64 + 7;
    1158           1 :     GUInt16 arrayIn[N] = {0};
    1159           1 :     GInt16 arrayOut[N] = {0};
    1160          72 :     for (int i = 0; i < N; i++)
    1161             :     {
    1162          71 :         arrayIn[i] = 32766 + (i % 4);
    1163             :     }
    1164           1 :     GDALCopyWords(arrayIn, eIn, GDALGetDataTypeSizeBytes(eIn), arrayOut, eOut,
    1165             :                   GDALGetDataTypeSizeBytes(eOut), N);
    1166           1 :     int numLine = 0;
    1167          72 :     for (int i = 0; i < N; i++)
    1168             :     {
    1169          71 :         MY_EXPECT(eIn, (int)arrayIn[i], eOut, (i % 4) == 0 ? 32766 : 32767,
    1170             :                   arrayOut[i]);
    1171             :     }
    1172           1 : }
    1173             : 
    1174         121 : template <class Tin> void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1175             : {
    1176         121 :     switch (eOut)
    1177             :     {
    1178          11 :         case GDT_Byte:
    1179          11 :             CheckPacked<Tin, GByte>(eIn, eOut);
    1180          11 :             break;
    1181          11 :         case GDT_Int8:
    1182          11 :             CheckPacked<Tin, GInt8>(eIn, eOut);
    1183          11 :             break;
    1184          11 :         case GDT_UInt16:
    1185          11 :             CheckPacked<Tin, GUInt16>(eIn, eOut);
    1186          11 :             break;
    1187          11 :         case GDT_Int16:
    1188          11 :             CheckPacked<Tin, GInt16>(eIn, eOut);
    1189          11 :             break;
    1190          11 :         case GDT_UInt32:
    1191          11 :             CheckPacked<Tin, GUInt32>(eIn, eOut);
    1192          11 :             break;
    1193          11 :         case GDT_Int32:
    1194          11 :             CheckPacked<Tin, GInt32>(eIn, eOut);
    1195          11 :             break;
    1196          11 :         case GDT_UInt64:
    1197          11 :             CheckPacked<Tin, std::uint64_t>(eIn, eOut);
    1198          11 :             break;
    1199          11 :         case GDT_Int64:
    1200          11 :             CheckPacked<Tin, std::int64_t>(eIn, eOut);
    1201          11 :             break;
    1202          11 :         case GDT_Float16:
    1203          11 :             CheckPacked<Tin, GFloat16>(eIn, eOut);
    1204          11 :             break;
    1205          11 :         case GDT_Float32:
    1206          11 :             CheckPacked<Tin, float>(eIn, eOut);
    1207          11 :             break;
    1208          11 :         case GDT_Float64:
    1209          11 :             CheckPacked<Tin, double>(eIn, eOut);
    1210          11 :             break;
    1211           0 :         default:
    1212           0 :             CPLAssert(false);
    1213             :     }
    1214         121 : }
    1215             : 
    1216         121 : static void CheckPacked(GDALDataType eIn, GDALDataType eOut)
    1217             : {
    1218         121 :     switch (eIn)
    1219             :     {
    1220          11 :         case GDT_Byte:
    1221          11 :             CheckPacked<GByte>(eIn, eOut);
    1222          11 :             break;
    1223          11 :         case GDT_Int8:
    1224          11 :             CheckPacked<GInt8>(eIn, eOut);
    1225          11 :             break;
    1226          11 :         case GDT_UInt16:
    1227          11 :             CheckPacked<GUInt16>(eIn, eOut);
    1228          11 :             break;
    1229          11 :         case GDT_Int16:
    1230          11 :             CheckPacked<GInt16>(eIn, eOut);
    1231          11 :             break;
    1232          11 :         case GDT_UInt32:
    1233          11 :             CheckPacked<GUInt32>(eIn, eOut);
    1234          11 :             break;
    1235          11 :         case GDT_Int32:
    1236          11 :             CheckPacked<GInt32>(eIn, eOut);
    1237          11 :             break;
    1238          11 :         case GDT_UInt64:
    1239          11 :             CheckPacked<std::uint64_t>(eIn, eOut);
    1240          11 :             break;
    1241          11 :         case GDT_Int64:
    1242          11 :             CheckPacked<std::int64_t>(eIn, eOut);
    1243          11 :             break;
    1244          11 :         case GDT_Float16:
    1245          11 :             CheckPacked<GFloat16>(eIn, eOut);
    1246          11 :             break;
    1247          11 :         case GDT_Float32:
    1248          11 :             CheckPacked<float>(eIn, eOut);
    1249          11 :             break;
    1250          11 :         case GDT_Float64:
    1251          11 :             CheckPacked<double>(eIn, eOut);
    1252          11 :             break;
    1253           0 :         default:
    1254           0 :             CPLAssert(false);
    1255             :     }
    1256         121 : }
    1257             : 
    1258             : class TestCopyWordsCheckPackedFixture
    1259             :     : public TestCopyWords,
    1260             :       public ::testing::WithParamInterface<
    1261             :           std::tuple<GDALDataType, GDALDataType>>
    1262             : {
    1263             : };
    1264             : 
    1265         243 : TEST_P(TestCopyWordsCheckPackedFixture, CheckPacked)
    1266             : {
    1267         121 :     GDALDataType eIn = std::get<0>(GetParam());
    1268         121 :     GDALDataType eOut = std::get<1>(GetParam());
    1269         121 :     CheckPacked(eIn, eOut);
    1270         121 : }
    1271             : 
    1272             : static std::vector<std::tuple<GDALDataType, GDALDataType>>
    1273           1 : GetGDALDataTypeTupleValues()
    1274             : {
    1275           1 :     std::vector<std::tuple<GDALDataType, GDALDataType>> ret;
    1276          17 :     for (GDALDataType eIn = GDT_Byte; eIn < GDT_TypeCount;
    1277          16 :          eIn = static_cast<GDALDataType>(eIn + 1))
    1278             :     {
    1279          16 :         if (GDALDataTypeIsComplex(eIn))
    1280           5 :             continue;
    1281         187 :         for (GDALDataType eOut = GDT_Byte; eOut < GDT_TypeCount;
    1282         176 :              eOut = static_cast<GDALDataType>(eOut + 1))
    1283             :         {
    1284         176 :             if (GDALDataTypeIsComplex(eOut))
    1285          55 :                 continue;
    1286         121 :             ret.emplace_back(std::make_tuple(eIn, eOut));
    1287             :         }
    1288             :     }
    1289           1 :     return ret;
    1290             : }
    1291             : 
    1292         365 : INSTANTIATE_TEST_SUITE_P(
    1293             :     TestCopyWords, TestCopyWordsCheckPackedFixture,
    1294             :     ::testing::ValuesIn(GetGDALDataTypeTupleValues()),
    1295             :     [](const ::testing::TestParamInfo<
    1296             :         TestCopyWordsCheckPackedFixture::ParamType> &l_info)
    1297             :     {
    1298             :         GDALDataType eIn = std::get<0>(l_info.param);
    1299             :         GDALDataType eOut = std::get<1>(l_info.param);
    1300             :         return std::string(GDALGetDataTypeName(eIn)) + "_" +
    1301             :                GDALGetDataTypeName(eOut);
    1302             :     });
    1303             : 
    1304           4 : TEST_F(TestCopyWords, ByteToByte)
    1305             : {
    1306           3 :     for (int k = 0; k < 2; k++)
    1307             :     {
    1308           2 :         if (k == 1)
    1309           1 :             CPLSetConfigOption("GDAL_USE_SSSE3", "NO");
    1310             : 
    1311           8 :         for (int spacing = 2; spacing <= 4; spacing++)
    1312             :         {
    1313           6 :             memset(pIn, 0xff, 256);
    1314         108 :             for (int i = 0; i < 17; i++)
    1315             :             {
    1316         102 :                 pIn[spacing * i] = (GByte)(17 - i);
    1317             :             }
    1318           6 :             memset(pOut, 0xff, 256);
    1319           6 :             GDALCopyWords(pIn, GDT_Byte, spacing, pOut, GDT_Byte, 1, 17);
    1320         108 :             for (int i = 0; i < 17; i++)
    1321             :             {
    1322         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i],
    1323             :                           __LINE__);
    1324             :             }
    1325             : 
    1326           6 :             memset(pIn, 0xff, 256);
    1327           6 :             memset(pOut, 0xff, 256);
    1328         108 :             for (int i = 0; i < 17; i++)
    1329             :             {
    1330         102 :                 pIn[i] = (GByte)(17 - i);
    1331             :             }
    1332           6 :             GDALCopyWords(pIn, GDT_Byte, 1, pOut, GDT_Byte, spacing, 17);
    1333         108 :             for (int i = 0; i < 17; i++)
    1334             :             {
    1335         102 :                 AssertRes(GDT_Byte, 17 - i, GDT_Byte, 17 - i, pOut[i * spacing],
    1336             :                           __LINE__);
    1337         306 :                 for (int j = 1; j < spacing; j++)
    1338             :                 {
    1339         204 :                     AssertRes(GDT_Byte, 0xff, GDT_Byte, 0xff,
    1340         204 :                               pOut[i * spacing + j], __LINE__);
    1341             :                 }
    1342             :             }
    1343             :         }
    1344             :     }
    1345           1 :     CPLSetConfigOption("GDAL_USE_SSSE3", nullptr);
    1346           1 : }
    1347             : 
    1348           4 : TEST_F(TestCopyWords, Int16ToInt16)
    1349             : {
    1350           1 :     memset(pIn, 0xff, 256);
    1351           1 :     GInt16 *pInShort = (GInt16 *)pIn;
    1352           1 :     GInt16 *pOutShort = (GInt16 *)pOut;
    1353          10 :     for (int i = 0; i < 9; i++)
    1354             :     {
    1355           9 :         pInShort[2 * i + 0] = 0x1234;
    1356           9 :         pInShort[2 * i + 1] = 0x5678;
    1357             :     }
    1358           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1359             :     {
    1360           4 :         memset(pOut, 0xff, 256);
    1361           4 :         GDALCopyWords(pInShort, GDT_Int16, sizeof(short), pOutShort, GDT_Int16,
    1362           4 :                       (iSpacing + 1) * sizeof(short), 18);
    1363          40 :         for (int i = 0; i < 9; i++)
    1364             :         {
    1365          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 0], GDT_Int16,
    1366          36 :                       pInShort[2 * i + 0],
    1367          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 0)], __LINE__);
    1368          36 :             AssertRes(GDT_Int16, pInShort[2 * i + 1], GDT_Int16,
    1369          36 :                       pInShort[2 * i + 1],
    1370          36 :                       pOutShort[(iSpacing + 1) * (2 * i + 1)], __LINE__);
    1371             :         }
    1372             :     }
    1373           5 :     for (int iSpacing = 0; iSpacing < 4; iSpacing++)
    1374             :     {
    1375           4 :         memset(pIn, 0xff, 256);
    1376           4 :         memset(pOut, 0xff, 256);
    1377          40 :         for (int i = 0; i < 9; i++)
    1378             :         {
    1379          36 :             pInShort[(iSpacing + 1) * (2 * i + 0)] = 0x1234;
    1380          36 :             pInShort[(iSpacing + 1) * (2 * i + 1)] = 0x5678;
    1381             :         }
    1382           4 :         GDALCopyWords(pInShort, GDT_Int16, (iSpacing + 1) * sizeof(short),
    1383             :                       pOutShort, GDT_Int16, sizeof(short), 18);
    1384          40 :         for (int i = 0; i < 9; i++)
    1385             :         {
    1386          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1387          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 0)],
    1388          36 :                       pOutShort[2 * i + 0], __LINE__);
    1389          36 :             AssertRes(GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1390          36 :                       GDT_Int16, pInShort[(iSpacing + 1) * (2 * i + 1)],
    1391          36 :                       pOutShort[2 * i + 1], __LINE__);
    1392             :         }
    1393             :     }
    1394           1 : }
    1395             : 
    1396             : }  // namespace

Generated by: LCOV version 1.14