Coverage Report

Created: 2026-11-12 08:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/gcore/rasterio.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL Core
4
 * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
5
 *           and supporting functions of broader utility.
6
 * Author:   Frank Warmerdam, warmerdam@pobox.com
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 1998, Frank Warmerdam
10
 * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com>
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#include "cpl_port.h"
16
#include "gdal.h"
17
#include "gdal_priv.h"
18
19
#include <cassert>
20
#include <climits>
21
#include <cmath>
22
#include <cstddef>
23
#include <cstdio>
24
#include <cstdlib>
25
#include <cstring>
26
27
#include <algorithm>
28
#include <limits>
29
#include <stdexcept>
30
#include <type_traits>
31
32
#include "cpl_conv.h"
33
#include "cpl_cpu_features.h"
34
#include "cpl_error.h"
35
#include "cpl_float.h"
36
#include "cpl_progress.h"
37
#include "cpl_string.h"
38
#include "cpl_vsi.h"
39
#include "gdal_priv_templates.hpp"
40
#include "gdal_vrt.h"
41
#include "gdalwarper.h"
42
#include "memdataset.h"
43
#include "vrtdataset.h"
44
45
#if defined(__x86_64) || defined(_M_X64)
46
#include <emmintrin.h>
47
#include <immintrin.h>
48
#define HAVE_SSE2
49
// AVX2 dispatch: compile AVX2 code with target attribute, detect at runtime
50
#if (defined(__GNUC__) || defined(__clang__)) &&                               \
51
    defined(HAVE_AVX2_AT_COMPILE_TIME)
52
#define HAVE_AVX2_DISPATCH
53
#elif defined(_MSC_VER)
54
#include <intrin.h>
55
#define HAVE_AVX2_DISPATCH
56
#endif
57
#elif defined(USE_NEON_OPTIMIZATIONS)
58
#include "include_sse2neon.h"
59
#define HAVE_SSE2
60
#endif
61
62
#ifdef HAVE_SSSE3_AT_COMPILE_TIME
63
#include "rasterio_ssse3.h"
64
#ifdef __SSSE3__
65
#include <tmmintrin.h>
66
#endif
67
#endif
68
69
#ifdef __SSE4_1__
70
#include <smmintrin.h>
71
#endif
72
73
#ifdef __GNUC__
74
#define CPL_NOINLINE __attribute__((noinline))
75
#else
76
#define CPL_NOINLINE
77
#endif
78
79
static void GDALFastCopyByte(const GByte *CPL_RESTRICT pSrcData,
80
                             int nSrcPixelStride, GByte *CPL_RESTRICT pDstData,
81
                             int nDstPixelStride, GPtrDiff_t nWordCount);
82
83
/************************************************************************/
84
/*                     DownsamplingIntegerXFactor()                     */
85
/************************************************************************/
86
87
template <bool bSameDataType, int DATA_TYPE_SIZE>
88
static bool DownsamplingIntegerXFactor(
89
    GDALRasterBand *poBand, int iSrcX, int nSrcXInc, GPtrDiff_t iSrcOffsetCst,
90
    GByte *CPL_RESTRICT pabyDstData, int nPixelSpace, int nBufXSize,
91
    GDALDataType eDataType, GDALDataType eBufType, int &nStartBlockX,
92
    int nBlockXSize, GDALRasterBlock *&poBlock, int nLBlockY)
93
218k
{
94
218k
    const int nBandDataSize =
95
218k
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
218k
    int nOuterLoopIters = nBufXSize - 1;
97
218k
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
218k
    const GByte *CPL_RESTRICT pabySrcData;
99
218k
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
218k
    if (iSrcX < nEndBlockX)
102
156k
    {
103
156k
        CPLAssert(poBlock);
104
156k
        goto no_reload_block;
105
156k
    }
106
61.6k
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
491k
    while (--nOuterLoopIters >= 1)
111
79.5k
    {
112
79.5k
        iSrcX += nSrcXInc;
113
79.5k
        pabySrcData += nIncSrcOffset;
114
79.5k
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
79.5k
        if (iSrcX >= nEndBlockX)
122
79.5k
        {
123
151k
        reload_block:
124
151k
        {
125
151k
            const int nLBlockX = iSrcX / nBlockXSize;
126
151k
            nStartBlockX = nLBlockX * nBlockXSize;
127
151k
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
151k
            if (poBlock != nullptr)
130
142k
                poBlock->DropLock();
131
132
151k
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
151k
            if (poBlock == nullptr)
134
929
            {
135
929
                return false;
136
929
            }
137
151k
        }
138
139
491k
        no_reload_block:
140
491k
            const GByte *pabySrcBlock =
141
491k
                static_cast<const GByte *>(poBlock->GetDataRef());
142
491k
            GPtrDiff_t iSrcOffset =
143
491k
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
491k
            pabySrcData = pabySrcBlock + iSrcOffset;
145
491k
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
491k
        const int nIters = std::min(
154
491k
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
491k
        if (bSameDataType)
156
346k
        {
157
346k
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
346k
            if (nIters > 1)
159
116k
            {
160
116k
                if (DATA_TYPE_SIZE == 1)
161
112k
                {
162
112k
                    pabySrcData += nIncSrcOffset;
163
112k
                    pabyDstData += nPixelSpace;
164
112k
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
112k
                                     nPixelSpace, nIters - 1);
166
112k
                    pabySrcData +=
167
112k
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
112k
                    pabyDstData +=
169
112k
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
112k
                }
171
4.48k
                else
172
4.48k
                {
173
16.9k
                    for (int i = 0; i < nIters - 1; i++)
174
12.4k
                    {
175
12.4k
                        pabySrcData += nIncSrcOffset;
176
12.4k
                        pabyDstData += nPixelSpace;
177
12.4k
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
12.4k
                    }
179
4.48k
                }
180
116k
                iSrcX += nSrcXInc * (nIters - 1);
181
116k
                nOuterLoopIters -= nIters - 1;
182
116k
            }
183
346k
        }
184
145k
        else
185
145k
        {
186
            // Type to type conversion ...
187
145k
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
145k
                            eBufType, nPixelSpace, std::max(1, nIters));
189
145k
            if (nIters > 1)
190
43.7k
            {
191
43.7k
                pabySrcData +=
192
43.7k
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
43.7k
                pabyDstData +=
194
43.7k
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
43.7k
                iSrcX += nSrcXInc * (nIters - 1);
196
43.7k
                nOuterLoopIters -= nIters - 1;
197
43.7k
            }
198
145k
        }
199
491k
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
411k
    if (nOuterLoopIters == 0)
203
194k
    {
204
194k
        const int nRasterXSize = poBand->GetXSize();
205
194k
        iSrcX =
206
194k
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
194k
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
194k
        pabyDstData += nPixelSpace;
209
194k
        if (iSrcX < nEndBlockX)
210
184k
        {
211
184k
            goto no_reload_block;
212
184k
        }
213
9.93k
        goto reload_block;
214
194k
    }
215
217k
    return true;
216
411k
}
rasterio.cpp:bool DownsamplingIntegerXFactor<true, 1>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
Line
Count
Source
93
140k
{
94
140k
    const int nBandDataSize =
95
140k
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
140k
    int nOuterLoopIters = nBufXSize - 1;
97
140k
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
140k
    const GByte *CPL_RESTRICT pabySrcData;
99
140k
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
140k
    if (iSrcX < nEndBlockX)
102
113k
    {
103
113k
        CPLAssert(poBlock);
104
113k
        goto no_reload_block;
105
113k
    }
106
26.2k
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
315k
    while (--nOuterLoopIters >= 1)
111
36.8k
    {
112
36.8k
        iSrcX += nSrcXInc;
113
36.8k
        pabySrcData += nIncSrcOffset;
114
36.8k
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
36.8k
        if (iSrcX >= nEndBlockX)
122
36.8k
        {
123
66.4k
        reload_block:
124
66.4k
        {
125
66.4k
            const int nLBlockX = iSrcX / nBlockXSize;
126
66.4k
            nStartBlockX = nLBlockX * nBlockXSize;
127
66.4k
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
66.4k
            if (poBlock != nullptr)
130
63.3k
                poBlock->DropLock();
131
132
66.4k
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
66.4k
            if (poBlock == nullptr)
134
350
            {
135
350
                return false;
136
350
            }
137
66.4k
        }
138
139
315k
        no_reload_block:
140
315k
            const GByte *pabySrcBlock =
141
315k
                static_cast<const GByte *>(poBlock->GetDataRef());
142
315k
            GPtrDiff_t iSrcOffset =
143
315k
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
315k
            pabySrcData = pabySrcBlock + iSrcOffset;
145
315k
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
315k
        const int nIters = std::min(
154
315k
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
315k
        if (bSameDataType)
156
315k
        {
157
315k
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
315k
            if (nIters > 1)
159
112k
            {
160
112k
                if (DATA_TYPE_SIZE == 1)
161
112k
                {
162
112k
                    pabySrcData += nIncSrcOffset;
163
112k
                    pabyDstData += nPixelSpace;
164
112k
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
112k
                                     nPixelSpace, nIters - 1);
166
112k
                    pabySrcData +=
167
112k
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
112k
                    pabyDstData +=
169
112k
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
112k
                }
171
0
                else
172
0
                {
173
0
                    for (int i = 0; i < nIters - 1; i++)
174
0
                    {
175
0
                        pabySrcData += nIncSrcOffset;
176
0
                        pabyDstData += nPixelSpace;
177
0
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
0
                    }
179
0
                }
180
112k
                iSrcX += nSrcXInc * (nIters - 1);
181
112k
                nOuterLoopIters -= nIters - 1;
182
112k
            }
183
315k
        }
184
0
        else
185
0
        {
186
            // Type to type conversion ...
187
0
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
0
                            eBufType, nPixelSpace, std::max(1, nIters));
189
0
            if (nIters > 1)
190
0
            {
191
0
                pabySrcData +=
192
0
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
0
                pabyDstData +=
194
0
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
0
                iSrcX += nSrcXInc * (nIters - 1);
196
0
                nOuterLoopIters -= nIters - 1;
197
0
            }
198
0
        }
199
315k
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
279k
    if (nOuterLoopIters == 0)
203
139k
    {
204
139k
        const int nRasterXSize = poBand->GetXSize();
205
139k
        iSrcX =
206
139k
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
139k
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
139k
        pabyDstData += nPixelSpace;
209
139k
        if (iSrcX < nEndBlockX)
210
135k
        {
211
135k
            goto no_reload_block;
212
135k
        }
213
3.34k
        goto reload_block;
214
139k
    }
215
139k
    return true;
216
279k
}
rasterio.cpp:bool DownsamplingIntegerXFactor<true, 2>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
Line
Count
Source
93
2.70k
{
94
2.70k
    const int nBandDataSize =
95
2.70k
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
2.70k
    int nOuterLoopIters = nBufXSize - 1;
97
2.70k
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
2.70k
    const GByte *CPL_RESTRICT pabySrcData;
99
2.70k
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
2.70k
    if (iSrcX < nEndBlockX)
102
884
    {
103
884
        CPLAssert(poBlock);
104
884
        goto no_reload_block;
105
884
    }
106
1.81k
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
5.40k
    while (--nOuterLoopIters >= 1)
111
0
    {
112
0
        iSrcX += nSrcXInc;
113
0
        pabySrcData += nIncSrcOffset;
114
0
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
0
        if (iSrcX >= nEndBlockX)
122
0
        {
123
3.61k
        reload_block:
124
3.61k
        {
125
3.61k
            const int nLBlockX = iSrcX / nBlockXSize;
126
3.61k
            nStartBlockX = nLBlockX * nBlockXSize;
127
3.61k
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
3.61k
            if (poBlock != nullptr)
130
3.60k
                poBlock->DropLock();
131
132
3.61k
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
3.61k
            if (poBlock == nullptr)
134
0
            {
135
0
                return false;
136
0
            }
137
3.61k
        }
138
139
5.40k
        no_reload_block:
140
5.40k
            const GByte *pabySrcBlock =
141
5.40k
                static_cast<const GByte *>(poBlock->GetDataRef());
142
5.40k
            GPtrDiff_t iSrcOffset =
143
5.40k
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
5.40k
            pabySrcData = pabySrcBlock + iSrcOffset;
145
5.40k
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
5.40k
        const int nIters = std::min(
154
5.40k
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
5.40k
        if (bSameDataType)
156
5.40k
        {
157
5.40k
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
5.40k
            if (nIters > 1)
159
2.70k
            {
160
2.70k
                if (DATA_TYPE_SIZE == 1)
161
0
                {
162
0
                    pabySrcData += nIncSrcOffset;
163
0
                    pabyDstData += nPixelSpace;
164
0
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
0
                                     nPixelSpace, nIters - 1);
166
0
                    pabySrcData +=
167
0
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
0
                    pabyDstData +=
169
0
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
0
                }
171
2.70k
                else
172
2.70k
                {
173
8.10k
                    for (int i = 0; i < nIters - 1; i++)
174
5.40k
                    {
175
5.40k
                        pabySrcData += nIncSrcOffset;
176
5.40k
                        pabyDstData += nPixelSpace;
177
5.40k
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
5.40k
                    }
179
2.70k
                }
180
2.70k
                iSrcX += nSrcXInc * (nIters - 1);
181
2.70k
                nOuterLoopIters -= nIters - 1;
182
2.70k
            }
183
5.40k
        }
184
0
        else
185
0
        {
186
            // Type to type conversion ...
187
0
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
0
                            eBufType, nPixelSpace, std::max(1, nIters));
189
0
            if (nIters > 1)
190
0
            {
191
0
                pabySrcData +=
192
0
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
0
                pabyDstData +=
194
0
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
0
                iSrcX += nSrcXInc * (nIters - 1);
196
0
                nOuterLoopIters -= nIters - 1;
197
0
            }
198
0
        }
199
5.40k
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
5.40k
    if (nOuterLoopIters == 0)
203
2.70k
    {
204
2.70k
        const int nRasterXSize = poBand->GetXSize();
205
2.70k
        iSrcX =
206
2.70k
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
2.70k
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
2.70k
        pabyDstData += nPixelSpace;
209
2.70k
        if (iSrcX < nEndBlockX)
210
902
        {
211
902
            goto no_reload_block;
212
902
        }
213
1.80k
        goto reload_block;
214
2.70k
    }
215
2.70k
    return true;
216
5.40k
}
rasterio.cpp:bool DownsamplingIntegerXFactor<true, 4>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
Line
Count
Source
93
46
{
94
46
    const int nBandDataSize =
95
46
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
46
    int nOuterLoopIters = nBufXSize - 1;
97
46
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
46
    const GByte *CPL_RESTRICT pabySrcData;
99
46
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
46
    if (iSrcX < nEndBlockX)
102
0
    {
103
0
        CPLAssert(poBlock);
104
0
        goto no_reload_block;
105
0
    }
106
46
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
78
    while (--nOuterLoopIters >= 1)
111
0
    {
112
0
        iSrcX += nSrcXInc;
113
0
        pabySrcData += nIncSrcOffset;
114
0
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
0
        if (iSrcX >= nEndBlockX)
122
0
        {
123
46
        reload_block:
124
46
        {
125
46
            const int nLBlockX = iSrcX / nBlockXSize;
126
46
            nStartBlockX = nLBlockX * nBlockXSize;
127
46
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
46
            if (poBlock != nullptr)
130
30
                poBlock->DropLock();
131
132
46
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
46
            if (poBlock == nullptr)
134
4
            {
135
4
                return false;
136
4
            }
137
46
        }
138
139
78
        no_reload_block:
140
78
            const GByte *pabySrcBlock =
141
78
                static_cast<const GByte *>(poBlock->GetDataRef());
142
78
            GPtrDiff_t iSrcOffset =
143
78
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
78
            pabySrcData = pabySrcBlock + iSrcOffset;
145
78
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
78
        const int nIters = std::min(
154
78
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
78
        if (bSameDataType)
156
78
        {
157
78
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
78
            if (nIters > 1)
159
36
            {
160
36
                if (DATA_TYPE_SIZE == 1)
161
0
                {
162
0
                    pabySrcData += nIncSrcOffset;
163
0
                    pabyDstData += nPixelSpace;
164
0
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
0
                                     nPixelSpace, nIters - 1);
166
0
                    pabySrcData +=
167
0
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
0
                    pabyDstData +=
169
0
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
0
                }
171
36
                else
172
36
                {
173
72
                    for (int i = 0; i < nIters - 1; i++)
174
36
                    {
175
36
                        pabySrcData += nIncSrcOffset;
176
36
                        pabyDstData += nPixelSpace;
177
36
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
36
                    }
179
36
                }
180
36
                iSrcX += nSrcXInc * (nIters - 1);
181
36
                nOuterLoopIters -= nIters - 1;
182
36
            }
183
78
        }
184
0
        else
185
0
        {
186
            // Type to type conversion ...
187
0
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
0
                            eBufType, nPixelSpace, std::max(1, nIters));
189
0
            if (nIters > 1)
190
0
            {
191
0
                pabySrcData +=
192
0
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
0
                pabyDstData +=
194
0
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
0
                iSrcX += nSrcXInc * (nIters - 1);
196
0
                nOuterLoopIters -= nIters - 1;
197
0
            }
198
0
        }
199
78
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
78
    if (nOuterLoopIters == 0)
203
36
    {
204
36
        const int nRasterXSize = poBand->GetXSize();
205
36
        iSrcX =
206
36
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
36
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
36
        pabyDstData += nPixelSpace;
209
36
        if (iSrcX < nEndBlockX)
210
36
        {
211
36
            goto no_reload_block;
212
36
        }
213
0
        goto reload_block;
214
36
    }
215
42
    return true;
216
78
}
rasterio.cpp:bool DownsamplingIntegerXFactor<true, 8>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
Line
Count
Source
93
22.9k
{
94
22.9k
    const int nBandDataSize =
95
22.9k
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
22.9k
    int nOuterLoopIters = nBufXSize - 1;
97
22.9k
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
22.9k
    const GByte *CPL_RESTRICT pabySrcData;
99
22.9k
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
22.9k
    if (iSrcX < nEndBlockX)
102
1
    {
103
1
        CPLAssert(poBlock);
104
1
        goto no_reload_block;
105
1
    }
106
22.9k
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
24.6k
    while (--nOuterLoopIters >= 1)
111
0
    {
112
0
        iSrcX += nSrcXInc;
113
0
        pabySrcData += nIncSrcOffset;
114
0
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
0
        if (iSrcX >= nEndBlockX)
122
0
        {
123
22.9k
        reload_block:
124
22.9k
        {
125
22.9k
            const int nLBlockX = iSrcX / nBlockXSize;
126
22.9k
            nStartBlockX = nLBlockX * nBlockXSize;
127
22.9k
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
22.9k
            if (poBlock != nullptr)
130
19.6k
                poBlock->DropLock();
131
132
22.9k
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
22.9k
            if (poBlock == nullptr)
134
43
            {
135
43
                return false;
136
43
            }
137
22.9k
        }
138
139
24.6k
        no_reload_block:
140
24.6k
            const GByte *pabySrcBlock =
141
24.6k
                static_cast<const GByte *>(poBlock->GetDataRef());
142
24.6k
            GPtrDiff_t iSrcOffset =
143
24.6k
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
24.6k
            pabySrcData = pabySrcBlock + iSrcOffset;
145
24.6k
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
24.6k
        const int nIters = std::min(
154
24.6k
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
24.6k
        if (bSameDataType)
156
24.6k
        {
157
24.6k
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
24.6k
            if (nIters > 1)
159
1.75k
            {
160
1.75k
                if (DATA_TYPE_SIZE == 1)
161
0
                {
162
0
                    pabySrcData += nIncSrcOffset;
163
0
                    pabyDstData += nPixelSpace;
164
0
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
0
                                     nPixelSpace, nIters - 1);
166
0
                    pabySrcData +=
167
0
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
0
                    pabyDstData +=
169
0
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
0
                }
171
1.75k
                else
172
1.75k
                {
173
8.75k
                    for (int i = 0; i < nIters - 1; i++)
174
7.00k
                    {
175
7.00k
                        pabySrcData += nIncSrcOffset;
176
7.00k
                        pabyDstData += nPixelSpace;
177
7.00k
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
7.00k
                    }
179
1.75k
                }
180
1.75k
                iSrcX += nSrcXInc * (nIters - 1);
181
1.75k
                nOuterLoopIters -= nIters - 1;
182
1.75k
            }
183
24.6k
        }
184
0
        else
185
0
        {
186
            // Type to type conversion ...
187
0
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
0
                            eBufType, nPixelSpace, std::max(1, nIters));
189
0
            if (nIters > 1)
190
0
            {
191
0
                pabySrcData +=
192
0
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
0
                pabyDstData +=
194
0
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
0
                iSrcX += nSrcXInc * (nIters - 1);
196
0
                nOuterLoopIters -= nIters - 1;
197
0
            }
198
0
        }
199
24.6k
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
24.6k
    if (nOuterLoopIters == 0)
203
1.75k
    {
204
1.75k
        const int nRasterXSize = poBand->GetXSize();
205
1.75k
        iSrcX =
206
1.75k
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
1.75k
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
1.75k
        pabyDstData += nPixelSpace;
209
1.75k
        if (iSrcX < nEndBlockX)
210
1.75k
        {
211
1.75k
            goto no_reload_block;
212
1.75k
        }
213
0
        goto reload_block;
214
1.75k
    }
215
22.8k
    return true;
216
24.6k
}
Unexecuted instantiation: rasterio.cpp:bool DownsamplingIntegerXFactor<true, 16>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
rasterio.cpp:bool DownsamplingIntegerXFactor<false, 0>(GDALRasterBand*, int, int, long long, unsigned char*, int, int, GDALDataType, GDALDataType, int&, int, GDALRasterBlock*&, int)
Line
Count
Source
93
52.4k
{
94
52.4k
    const int nBandDataSize =
95
52.4k
        bSameDataType ? DATA_TYPE_SIZE : GDALGetDataTypeSizeBytes(eDataType);
96
52.4k
    int nOuterLoopIters = nBufXSize - 1;
97
52.4k
    const int nIncSrcOffset = nSrcXInc * nBandDataSize;
98
52.4k
    const GByte *CPL_RESTRICT pabySrcData;
99
52.4k
    int nEndBlockX = nBlockXSize + nStartBlockX;
100
101
52.4k
    if (iSrcX < nEndBlockX)
102
41.8k
    {
103
41.8k
        CPLAssert(poBlock);
104
41.8k
        goto no_reload_block;
105
41.8k
    }
106
10.5k
    goto reload_block;
107
108
    // Don't do the last iteration in the loop, as iSrcX might go beyond
109
    // nRasterXSize - 1
110
145k
    while (--nOuterLoopIters >= 1)
111
42.7k
    {
112
42.7k
        iSrcX += nSrcXInc;
113
42.7k
        pabySrcData += nIncSrcOffset;
114
42.7k
        pabyDstData += nPixelSpace;
115
116
        /* --------------------------------------------------------------------
117
         */
118
        /*      Ensure we have the appropriate block loaded. */
119
        /* --------------------------------------------------------------------
120
         */
121
42.7k
        if (iSrcX >= nEndBlockX)
122
42.7k
        {
123
58.0k
        reload_block:
124
58.0k
        {
125
58.0k
            const int nLBlockX = iSrcX / nBlockXSize;
126
58.0k
            nStartBlockX = nLBlockX * nBlockXSize;
127
58.0k
            nEndBlockX = nStartBlockX + nBlockXSize;
128
129
58.0k
            if (poBlock != nullptr)
130
56.1k
                poBlock->DropLock();
131
132
58.0k
            poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
133
58.0k
            if (poBlock == nullptr)
134
532
            {
135
532
                return false;
136
532
            }
137
58.0k
        }
138
139
145k
        no_reload_block:
140
145k
            const GByte *pabySrcBlock =
141
145k
                static_cast<const GByte *>(poBlock->GetDataRef());
142
145k
            GPtrDiff_t iSrcOffset =
143
145k
                (iSrcX - nStartBlockX + iSrcOffsetCst) * nBandDataSize;
144
145k
            pabySrcData = pabySrcBlock + iSrcOffset;
145
145k
        }
146
147
        /* --------------------------------------------------------------------
148
         */
149
        /*      Copy the maximum run of pixels. */
150
        /* --------------------------------------------------------------------
151
         */
152
153
145k
        const int nIters = std::min(
154
145k
            (nEndBlockX - iSrcX + (nSrcXInc - 1)) / nSrcXInc, nOuterLoopIters);
155
145k
        if (bSameDataType)
156
0
        {
157
0
            memcpy(pabyDstData, pabySrcData, nBandDataSize);
158
0
            if (nIters > 1)
159
0
            {
160
0
                if (DATA_TYPE_SIZE == 1)
161
0
                {
162
0
                    pabySrcData += nIncSrcOffset;
163
0
                    pabyDstData += nPixelSpace;
164
0
                    GDALFastCopyByte(pabySrcData, nIncSrcOffset, pabyDstData,
165
0
                                     nPixelSpace, nIters - 1);
166
0
                    pabySrcData +=
167
0
                        static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 2);
168
0
                    pabyDstData +=
169
0
                        static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 2);
170
0
                }
171
0
                else
172
0
                {
173
0
                    for (int i = 0; i < nIters - 1; i++)
174
0
                    {
175
0
                        pabySrcData += nIncSrcOffset;
176
0
                        pabyDstData += nPixelSpace;
177
0
                        memcpy(pabyDstData, pabySrcData, nBandDataSize);
178
0
                    }
179
0
                }
180
0
                iSrcX += nSrcXInc * (nIters - 1);
181
0
                nOuterLoopIters -= nIters - 1;
182
0
            }
183
0
        }
184
145k
        else
185
145k
        {
186
            // Type to type conversion ...
187
145k
            GDALCopyWords64(pabySrcData, eDataType, nIncSrcOffset, pabyDstData,
188
145k
                            eBufType, nPixelSpace, std::max(1, nIters));
189
145k
            if (nIters > 1)
190
43.7k
            {
191
43.7k
                pabySrcData +=
192
43.7k
                    static_cast<GPtrDiff_t>(nIncSrcOffset) * (nIters - 1);
193
43.7k
                pabyDstData +=
194
43.7k
                    static_cast<GPtrDiff_t>(nPixelSpace) * (nIters - 1);
195
43.7k
                iSrcX += nSrcXInc * (nIters - 1);
196
43.7k
                nOuterLoopIters -= nIters - 1;
197
43.7k
            }
198
145k
        }
199
145k
    }
200
201
    // Deal with last iteration to avoid iSrcX to go beyond nRasterXSize - 1
202
102k
    if (nOuterLoopIters == 0)
203
50.5k
    {
204
50.5k
        const int nRasterXSize = poBand->GetXSize();
205
50.5k
        iSrcX =
206
50.5k
            static_cast<int>(std::min(static_cast<GInt64>(iSrcX) + nSrcXInc,
207
50.5k
                                      static_cast<GInt64>(nRasterXSize - 1)));
208
50.5k
        pabyDstData += nPixelSpace;
209
50.5k
        if (iSrcX < nEndBlockX)
210
45.7k
        {
211
45.7k
            goto no_reload_block;
212
45.7k
        }
213
4.78k
        goto reload_block;
214
50.5k
    }
215
51.8k
    return true;
216
102k
}
217
218
template <class A, class B>
219
CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW inline auto CPLUnsanitizedMul(A a, B b)
220
2.30M
{
221
2.30M
    return a * b;
222
2.30M
}
223
224
/************************************************************************/
225
/*                             IRasterIO()                              */
226
/*                                                                      */
227
/*      Default internal implementation of RasterIO() ... utilizes      */
228
/*      the Block access methods to satisfy the request.  This would    */
229
/*      normally only be overridden by formats with overviews.          */
230
/************************************************************************/
231
232
CPLErr GDALRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
233
                                 int nXSize, int nYSize, void *pData,
234
                                 int nBufXSize, int nBufYSize,
235
                                 GDALDataType eBufType, GSpacing nPixelSpace,
236
                                 GSpacing nLineSpace,
237
                                 GDALRasterIOExtraArg *psExtraArg)
238
239
17.4M
{
240
17.4M
    if (eRWFlag == GF_Write && eFlushBlockErr != CE_None)
241
0
    {
242
0
        CPLError(eFlushBlockErr, CPLE_AppDefined,
243
0
                 "An error occurred while writing a dirty block "
244
0
                 "from GDALRasterBand::IRasterIO");
245
0
        CPLErr eErr = eFlushBlockErr;
246
0
        eFlushBlockErr = CE_None;
247
0
        return eErr;
248
0
    }
249
17.4M
    if (nBlockXSize <= 0 || nBlockYSize <= 0)
250
0
    {
251
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size");
252
0
        return CE_Failure;
253
0
    }
254
255
17.4M
    const int nBandDataSize = GDALGetDataTypeSizeBytes(eDataType);
256
17.4M
    const int nBufDataSize = GDALGetDataTypeSizeBytes(eBufType);
257
17.4M
    GByte dummyBlock[2] = {0, 0};
258
17.4M
    GByte *pabySrcBlock =
259
17.4M
        dummyBlock; /* to avoid Coverity warning about nullptr dereference */
260
17.4M
    GDALRasterBlock *poBlock = nullptr;
261
17.4M
    const bool bUseIntegerRequestCoords =
262
17.4M
        (!psExtraArg->bFloatingPointWindowValidity ||
263
325k
         (nXOff == psExtraArg->dfXOff && nYOff == psExtraArg->dfYOff &&
264
194k
          nXSize == psExtraArg->dfXSize && nYSize == psExtraArg->dfYSize));
265
266
    /* ==================================================================== */
267
    /*      A common case is the data requested with the destination        */
268
    /*      is packed, and the block width is the raster width.             */
269
    /* ==================================================================== */
270
17.4M
    if (nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize &&
271
17.1M
        nBlockXSize == GetXSize() && nBufXSize == nXSize &&
272
16.6M
        nBufYSize == nYSize && bUseIntegerRequestCoords)
273
16.6M
    {
274
16.6M
        CPLErr eErr = CE_None;
275
16.6M
        int nLBlockY = -1;
276
277
41.0M
        for (int iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++)
278
24.5M
        {
279
24.5M
            const int iSrcY = iBufYOff + nYOff;
280
281
24.5M
            if (iSrcY < nLBlockY * nBlockYSize ||
282
24.5M
                iSrcY - nBlockYSize >= nLBlockY * nBlockYSize)
283
17.3M
            {
284
17.3M
                nLBlockY = iSrcY / nBlockYSize;
285
17.3M
                bool bJustInitialize =
286
17.3M
                    eRWFlag == GF_Write && nXOff == 0 &&
287
71.5k
                    nXSize == nBlockXSize && nYOff <= nLBlockY * nBlockYSize &&
288
50.5k
                    nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize;
289
290
                // Is this a partial tile at right and/or bottom edges of
291
                // the raster, and that is going to be completely written?
292
                // If so, do not load it from storage, but zero it so that
293
                // the content outsize of the validity area is initialized.
294
17.3M
                bool bMemZeroBuffer = false;
295
17.3M
                if (eRWFlag == GF_Write && !bJustInitialize && nXOff == 0 &&
296
31.7k
                    nXSize == nBlockXSize && nYOff <= nLBlockY * nBlockYSize &&
297
10.7k
                    nYOff + nYSize == GetYSize() &&
298
10.2k
                    nLBlockY * nBlockYSize > GetYSize() - nBlockYSize)
299
10.2k
                {
300
10.2k
                    bJustInitialize = true;
301
10.2k
                    bMemZeroBuffer = true;
302
10.2k
                }
303
304
17.3M
                if (poBlock)
305
697k
                    poBlock->DropLock();
306
307
17.3M
                const GUInt32 nErrorCounter = CPLGetErrorCounter();
308
17.3M
                poBlock = GetLockedBlockRef(0, nLBlockY, bJustInitialize);
309
17.3M
                if (poBlock == nullptr)
310
142k
                {
311
142k
                    if (strstr(CPLGetLastErrorMsg(), "IReadBlock failed") ==
312
142k
                        nullptr)
313
0
                    {
314
0
                        CPLError(CE_Failure, CPLE_AppDefined,
315
0
                                 "GetBlockRef failed at X block offset %d, "
316
0
                                 "Y block offset %d%s",
317
0
                                 0, nLBlockY,
318
0
                                 (nErrorCounter != CPLGetErrorCounter())
319
0
                                     ? CPLSPrintf(": %s", CPLGetLastErrorMsg())
320
0
                                     : "");
321
0
                    }
322
142k
                    eErr = CE_Failure;
323
142k
                    break;
324
142k
                }
325
326
17.1M
                if (eRWFlag == GF_Write)
327
71.5k
                    poBlock->MarkDirty();
328
329
17.1M
                pabySrcBlock = static_cast<GByte *>(poBlock->GetDataRef());
330
17.1M
                if (bMemZeroBuffer)
331
10.2k
                {
332
10.2k
                    memset(pabySrcBlock, 0,
333
10.2k
                           static_cast<GPtrDiff_t>(nBandDataSize) *
334
10.2k
                               nBlockXSize * nBlockYSize);
335
10.2k
                }
336
17.1M
            }
337
338
24.3M
            const auto nSrcByteOffset =
339
24.3M
                (static_cast<GPtrDiff_t>(iSrcY - nLBlockY * nBlockYSize) *
340
24.3M
                     nBlockXSize +
341
24.3M
                 nXOff) *
342
24.3M
                nBandDataSize;
343
344
24.3M
            if (eDataType == eBufType)
345
4.33M
            {
346
4.33M
                if (eRWFlag == GF_Read)
347
4.18M
                    memcpy(static_cast<GByte *>(pData) +
348
4.18M
                               static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
349
4.18M
                           pabySrcBlock + nSrcByteOffset,
350
4.18M
                           static_cast<size_t>(nLineSpace));
351
150k
                else
352
150k
                    memcpy(pabySrcBlock + nSrcByteOffset,
353
150k
                           static_cast<GByte *>(pData) +
354
150k
                               static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
355
150k
                           static_cast<size_t>(nLineSpace));
356
4.33M
            }
357
20.0M
            else
358
20.0M
            {
359
                // Type to type conversion.
360
20.0M
                if (eRWFlag == GF_Read)
361
20.0M
                    GDALCopyWords64(
362
20.0M
                        pabySrcBlock + nSrcByteOffset, eDataType, nBandDataSize,
363
20.0M
                        static_cast<GByte *>(pData) +
364
20.0M
                            static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
365
20.0M
                        eBufType, static_cast<int>(nPixelSpace), nBufXSize);
366
0
                else
367
0
                    GDALCopyWords64(static_cast<GByte *>(pData) +
368
0
                                        static_cast<GPtrDiff_t>(iBufYOff) *
369
0
                                            nLineSpace,
370
0
                                    eBufType, static_cast<int>(nPixelSpace),
371
0
                                    pabySrcBlock + nSrcByteOffset, eDataType,
372
0
                                    nBandDataSize, nBufXSize);
373
20.0M
            }
374
375
24.3M
            if (psExtraArg->pfnProgress != nullptr &&
376
103k
                !psExtraArg->pfnProgress(1.0 * (iBufYOff + 1) / nBufYSize, "",
377
103k
                                         psExtraArg->pProgressData))
378
0
            {
379
0
                eErr = CE_Failure;
380
0
                break;
381
0
            }
382
24.3M
        }
383
384
16.6M
        if (poBlock)
385
16.4M
            poBlock->DropLock();
386
387
16.6M
        return eErr;
388
16.6M
    }
389
390
    /* ==================================================================== */
391
    /*      Do we have overviews that would be appropriate to satisfy       */
392
    /*      this request?                                                   */
393
    /* ==================================================================== */
394
808k
    if ((nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 &&
395
28.0k
        eRWFlag == GF_Read)
396
28.0k
    {
397
28.0k
        GDALRasterIOExtraArg sExtraArg;
398
28.0k
        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
399
400
28.0k
        const int nOverview =
401
28.0k
            GDALBandGetBestOverviewLevel2(this, nXOff, nYOff, nXSize, nYSize,
402
28.0k
                                          nBufXSize, nBufYSize, &sExtraArg);
403
28.0k
        if (nOverview >= 0)
404
6.53k
        {
405
6.53k
            GDALRasterBand *poOverviewBand = GetOverview(nOverview);
406
6.53k
            if (poOverviewBand == nullptr)
407
0
                return CE_Failure;
408
409
6.53k
            return poOverviewBand->RasterIO(
410
6.53k
                eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
411
6.53k
                nBufYSize, eBufType, nPixelSpace, nLineSpace, &sExtraArg);
412
6.53k
        }
413
28.0k
    }
414
415
801k
    if (eRWFlag == GF_Read && nBufXSize < nXSize / 100 &&
416
6.05k
        nBufYSize < nYSize / 100 && nPixelSpace == nBufDataSize &&
417
1.12k
        nLineSpace == nPixelSpace * nBufXSize &&
418
1.12k
        CPLTestBool(CPLGetConfigOption("GDAL_NO_COSTLY_OVERVIEW", "NO")))
419
0
    {
420
0
        memset(pData, 0, static_cast<size_t>(nLineSpace * nBufYSize));
421
0
        return CE_None;
422
0
    }
423
424
    /* ==================================================================== */
425
    /*      The second case when we don't need subsample data but likely    */
426
    /*      need data type conversion.                                      */
427
    /* ==================================================================== */
428
801k
    if (  // nPixelSpace == nBufDataSize &&
429
801k
        nXSize == nBufXSize && nYSize == nBufYSize && bUseIntegerRequestCoords)
430
587k
    {
431
#if DEBUG_VERBOSE
432
        printf("IRasterIO(%d,%d,%d,%d) rw=%d case 2\n", /*ok*/
433
               nXOff, nYOff, nXSize, nYSize, static_cast<int>(eRWFlag));
434
#endif
435
436
        /* --------------------------------------------------------------------
437
         */
438
        /*      Loop over buffer computing source locations. */
439
        /* --------------------------------------------------------------------
440
         */
441
        // Calculate starting values out of loop
442
587k
        const int nLBlockXStart = nXOff / nBlockXSize;
443
587k
        const int nXSpanEnd = nBufXSize + nXOff;
444
445
587k
        int iBufYOff = 0;
446
587k
        int iSrcY = nYOff;
447
594k
        while (true)
448
594k
        {
449
594k
            GPtrDiff_t iBufOffset = static_cast<GPtrDiff_t>(iBufYOff) *
450
594k
                                    static_cast<GPtrDiff_t>(nLineSpace);
451
594k
            int nLBlockY = iSrcY / nBlockYSize;
452
594k
            int nLBlockX = nLBlockXStart;
453
594k
            int iSrcX = nXOff;
454
2.84M
            while (iSrcX < nXSpanEnd)
455
2.30M
            {
456
2.30M
                int nXSpan = nLBlockX * nBlockXSize;
457
2.30M
                if (nXSpan < INT_MAX - nBlockXSize)
458
2.30M
                    nXSpan += nBlockXSize;
459
0
                else
460
0
                    nXSpan = INT_MAX;
461
2.30M
                const int nXRight = nXSpan;
462
2.30M
                nXSpan = (nXSpan < nXSpanEnd ? nXSpan : nXSpanEnd) - iSrcX;
463
464
2.30M
                const size_t nXSpanSize =
465
2.30M
                    CPLUnsanitizedMul(nXSpan, static_cast<size_t>(nPixelSpace));
466
467
2.30M
                bool bJustInitialize =
468
2.30M
                    eRWFlag == GF_Write && nYOff <= nLBlockY * nBlockYSize &&
469
33.9k
                    nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize &&
470
7.12k
                    nXOff <= nLBlockX * nBlockXSize &&
471
7.12k
                    nXOff + nXSize >= nXRight;
472
473
                // Is this a partial tile at right and/or bottom edges of
474
                // the raster, and that is going to be completely written?
475
                // If so, do not load it from storage, but zero it so that
476
                // the content outsize of the validity area is initialized.
477
2.30M
                bool bMemZeroBuffer = false;
478
2.30M
                if (eRWFlag == GF_Write && !bJustInitialize &&
479
33.8k
                    nXOff <= nLBlockX * nBlockXSize &&
480
33.8k
                    nYOff <= nLBlockY * nBlockYSize &&
481
33.8k
                    (nXOff + nXSize >= nXRight ||
482
                     // cppcheck-suppress knownConditionTrueFalse
483
19.5k
                     (nXOff + nXSize == GetXSize() && nXRight > GetXSize())) &&
484
33.8k
                    (nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize ||
485
26.8k
                     (nYOff + nYSize == GetYSize() &&
486
26.8k
                      nLBlockY * nBlockYSize > GetYSize() - nBlockYSize)))
487
33.8k
                {
488
33.8k
                    bJustInitialize = true;
489
33.8k
                    bMemZeroBuffer = true;
490
33.8k
                }
491
492
                /* --------------------------------------------------------------------
493
                 */
494
                /*      Ensure we have the appropriate block loaded. */
495
                /* --------------------------------------------------------------------
496
                 */
497
2.30M
                const GUInt32 nErrorCounter = CPLGetErrorCounter();
498
2.30M
                poBlock =
499
2.30M
                    GetLockedBlockRef(nLBlockX, nLBlockY, bJustInitialize);
500
2.30M
                if (!poBlock)
501
46.9k
                {
502
46.9k
                    if (strstr(CPLGetLastErrorMsg(), "IReadBlock failed") ==
503
46.9k
                        nullptr)
504
0
                    {
505
0
                        CPLError(CE_Failure, CPLE_AppDefined,
506
0
                                 "GetBlockRef failed at X block offset %d, "
507
0
                                 "Y block offset %d%s",
508
0
                                 nLBlockX, nLBlockY,
509
0
                                 (nErrorCounter != CPLGetErrorCounter())
510
0
                                     ? CPLSPrintf(": %s", CPLGetLastErrorMsg())
511
0
                                     : "");
512
0
                    }
513
46.9k
                    return (CE_Failure);
514
46.9k
                }
515
516
2.25M
                if (eRWFlag == GF_Write)
517
33.9k
                    poBlock->MarkDirty();
518
519
2.25M
                pabySrcBlock = static_cast<GByte *>(poBlock->GetDataRef());
520
2.25M
                if (bMemZeroBuffer)
521
33.8k
                {
522
33.8k
                    memset(pabySrcBlock, 0,
523
33.8k
                           static_cast<GPtrDiff_t>(nBandDataSize) *
524
33.8k
                               nBlockXSize * nBlockYSize);
525
33.8k
                }
526
                /* --------------------------------------------------------------------
527
                 */
528
                /*      Copy over this chunk of data. */
529
                /* --------------------------------------------------------------------
530
                 */
531
2.25M
                GPtrDiff_t iSrcOffset =
532
2.25M
                    (static_cast<GPtrDiff_t>(iSrcX) -
533
2.25M
                     static_cast<GPtrDiff_t>(nLBlockX * nBlockXSize) +
534
2.25M
                     (static_cast<GPtrDiff_t>(iSrcY) -
535
2.25M
                      static_cast<GPtrDiff_t>(nLBlockY) * nBlockYSize) *
536
2.25M
                         nBlockXSize) *
537
2.25M
                    nBandDataSize;
538
                // Fill up as many rows as possible for the loaded block.
539
2.25M
                const int kmax = std::min(nBlockYSize - (iSrcY % nBlockYSize),
540
2.25M
                                          nBufYSize - iBufYOff);
541
178M
                for (int k = 0; k < kmax; k++)
542
176M
                {
543
176M
                    if (eDataType == eBufType && nPixelSpace == nBufDataSize)
544
2.10M
                    {
545
2.10M
                        if (eRWFlag == GF_Read)
546
1.37M
                            memcpy(static_cast<GByte *>(pData) + iBufOffset +
547
1.37M
                                       static_cast<GPtrDiff_t>(k) * nLineSpace,
548
1.37M
                                   pabySrcBlock + iSrcOffset, nXSpanSize);
549
729k
                        else
550
729k
                            memcpy(pabySrcBlock + iSrcOffset,
551
729k
                                   static_cast<GByte *>(pData) + iBufOffset +
552
729k
                                       static_cast<GPtrDiff_t>(k) * nLineSpace,
553
729k
                                   nXSpanSize);
554
2.10M
                    }
555
174M
                    else
556
174M
                    {
557
                        /* type to type conversion */
558
174M
                        if (eRWFlag == GF_Read)
559
174M
                            GDALCopyWords64(
560
174M
                                pabySrcBlock + iSrcOffset, eDataType,
561
174M
                                nBandDataSize,
562
174M
                                static_cast<GByte *>(pData) + iBufOffset +
563
174M
                                    static_cast<GPtrDiff_t>(k) * nLineSpace,
564
174M
                                eBufType, static_cast<int>(nPixelSpace),
565
174M
                                nXSpan);
566
0
                        else
567
0
                            GDALCopyWords64(
568
0
                                static_cast<GByte *>(pData) + iBufOffset +
569
0
                                    static_cast<GPtrDiff_t>(k) * nLineSpace,
570
0
                                eBufType, static_cast<int>(nPixelSpace),
571
0
                                pabySrcBlock + iSrcOffset, eDataType,
572
0
                                nBandDataSize, nXSpan);
573
174M
                    }
574
575
176M
                    iSrcOffset +=
576
176M
                        static_cast<GPtrDiff_t>(nBlockXSize) * nBandDataSize;
577
176M
                }
578
579
2.25M
                iBufOffset =
580
2.25M
                    CPLUnsanitizedAdd<GPtrDiff_t>(iBufOffset, nXSpanSize);
581
2.25M
                nLBlockX++;
582
2.25M
                iSrcX += nXSpan;
583
584
2.25M
                poBlock->DropLock();
585
2.25M
                poBlock = nullptr;
586
2.25M
            }
587
588
            /* Compute the increment to go on a block boundary */
589
547k
            const int nYInc = nBlockYSize - (iSrcY % nBlockYSize);
590
591
547k
            if (psExtraArg->pfnProgress != nullptr &&
592
614
                !psExtraArg->pfnProgress(
593
614
                    1.0 * std::min(nBufYSize, iBufYOff + nYInc) / nBufYSize, "",
594
614
                    psExtraArg->pProgressData))
595
0
            {
596
0
                return CE_Failure;
597
0
            }
598
599
547k
            iBufYOff += nYInc;
600
547k
            if (iBufYOff >= nBufYSize)
601
540k
                break;
602
            // Only increment iSrcY after above loop end check, to avoid
603
            // potential int overflow.
604
7.22k
            iSrcY += nYInc;
605
7.22k
        }
606
607
540k
        return CE_None;
608
587k
    }
609
610
    /* ==================================================================== */
611
    /*      Loop reading required source blocks to satisfy output           */
612
    /*      request.  This is the most general implementation.              */
613
    /* ==================================================================== */
614
615
214k
    double dfXOff = nXOff;
616
214k
    double dfYOff = nYOff;
617
214k
    double dfXSize = nXSize;
618
214k
    double dfYSize = nYSize;
619
214k
    if (psExtraArg->bFloatingPointWindowValidity)
620
214k
    {
621
214k
        dfXOff = psExtraArg->dfXOff;
622
214k
        dfYOff = psExtraArg->dfYOff;
623
214k
        dfXSize = psExtraArg->dfXSize;
624
214k
        dfYSize = psExtraArg->dfYSize;
625
214k
    }
626
627
    /* -------------------------------------------------------------------- */
628
    /*      Compute stepping increment.                                     */
629
    /* -------------------------------------------------------------------- */
630
214k
    const double dfSrcXInc = dfXSize / static_cast<double>(nBufXSize);
631
214k
    const double dfSrcYInc = dfYSize / static_cast<double>(nBufYSize);
632
214k
    CPLErr eErr = CE_None;
633
634
214k
    if (eRWFlag == GF_Write)
635
0
    {
636
        /* --------------------------------------------------------------------
637
         */
638
        /*    Write case */
639
        /*    Loop over raster window computing source locations in the buffer.
640
         */
641
        /* --------------------------------------------------------------------
642
         */
643
0
        GByte *pabyDstBlock = nullptr;
644
0
        int nLBlockX = -1;
645
0
        int nLBlockY = -1;
646
647
0
        for (int iDstY = nYOff; iDstY < nYOff + nYSize; iDstY++)
648
0
        {
649
0
            const int iBufYOff = static_cast<int>((iDstY - nYOff) / dfSrcYInc);
650
651
0
            for (int iDstX = nXOff; iDstX < nXOff + nXSize; iDstX++)
652
0
            {
653
0
                const int iBufXOff =
654
0
                    static_cast<int>((iDstX - nXOff) / dfSrcXInc);
655
0
                GPtrDiff_t iBufOffset =
656
0
                    static_cast<GPtrDiff_t>(iBufYOff) *
657
0
                        static_cast<GPtrDiff_t>(nLineSpace) +
658
0
                    iBufXOff * static_cast<GPtrDiff_t>(nPixelSpace);
659
660
                // FIXME: this code likely doesn't work if the dirty block gets
661
                // flushed to disk before being completely written.
662
                // In the meantime, bJustInitialize should probably be set to
663
                // FALSE even if it is not ideal performance wise, and for
664
                // lossy compression.
665
666
                /* --------------------------------------------------------------------
667
                 */
668
                /*      Ensure we have the appropriate block loaded. */
669
                /* --------------------------------------------------------------------
670
                 */
671
0
                if (iDstX < nLBlockX * nBlockXSize ||
672
0
                    iDstX - nBlockXSize >= nLBlockX * nBlockXSize ||
673
0
                    iDstY < nLBlockY * nBlockYSize ||
674
0
                    iDstY - nBlockYSize >= nLBlockY * nBlockYSize)
675
0
                {
676
0
                    nLBlockX = iDstX / nBlockXSize;
677
0
                    nLBlockY = iDstY / nBlockYSize;
678
679
0
                    const bool bJustInitialize =
680
0
                        nYOff <= nLBlockY * nBlockYSize &&
681
0
                        nYOff + nYSize - nBlockYSize >=
682
0
                            nLBlockY * nBlockYSize &&
683
0
                        nXOff <= nLBlockX * nBlockXSize &&
684
0
                        nXOff + nXSize - nBlockXSize >= nLBlockX * nBlockXSize;
685
                    /*bool bMemZeroBuffer = FALSE;
686
                    if( !bJustInitialize &&
687
                        nXOff <= nLBlockX * nBlockXSize &&
688
                        nYOff <= nLBlockY * nBlockYSize &&
689
                        (nXOff + nXSize >= (nLBlockX+1) * nBlockXSize ||
690
                         (nXOff + nXSize == GetXSize() &&
691
                         (nLBlockX+1) * nBlockXSize > GetXSize())) &&
692
                        (nYOff + nYSize >= (nLBlockY+1) * nBlockYSize ||
693
                         (nYOff + nYSize == GetYSize() &&
694
                         (nLBlockY+1) * nBlockYSize > GetYSize())) )
695
                    {
696
                        bJustInitialize = TRUE;
697
                        bMemZeroBuffer = TRUE;
698
                    }*/
699
0
                    if (poBlock != nullptr)
700
0
                        poBlock->DropLock();
701
702
0
                    poBlock =
703
0
                        GetLockedBlockRef(nLBlockX, nLBlockY, bJustInitialize);
704
0
                    if (poBlock == nullptr)
705
0
                    {
706
0
                        return (CE_Failure);
707
0
                    }
708
709
0
                    poBlock->MarkDirty();
710
711
0
                    pabyDstBlock = static_cast<GByte *>(poBlock->GetDataRef());
712
                    /*if( bMemZeroBuffer )
713
                    {
714
                        memset(pabyDstBlock, 0,
715
                            static_cast<GPtrDiff_t>(nBandDataSize) * nBlockXSize
716
                    * nBlockYSize);
717
                    }*/
718
0
                }
719
720
                // To make Coverity happy. Should not happen by design.
721
0
                if (pabyDstBlock == nullptr)
722
0
                {
723
0
                    CPLAssert(false);
724
0
                    eErr = CE_Failure;
725
0
                    break;
726
0
                }
727
728
                /* --------------------------------------------------------------------
729
                 */
730
                /*      Copy over this pixel of data. */
731
                /* --------------------------------------------------------------------
732
                 */
733
0
                GPtrDiff_t iDstOffset =
734
0
                    (static_cast<GPtrDiff_t>(iDstX) -
735
0
                     static_cast<GPtrDiff_t>(nLBlockX) * nBlockXSize +
736
0
                     (static_cast<GPtrDiff_t>(iDstY) -
737
0
                      static_cast<GPtrDiff_t>(nLBlockY) * nBlockYSize) *
738
0
                         nBlockXSize) *
739
0
                    nBandDataSize;
740
741
0
                if (eDataType == eBufType)
742
0
                {
743
0
                    memcpy(pabyDstBlock + iDstOffset,
744
0
                           static_cast<GByte *>(pData) + iBufOffset,
745
0
                           nBandDataSize);
746
0
                }
747
0
                else
748
0
                {
749
                    /* type to type conversion ... ouch, this is expensive way
750
                    of handling single words */
751
0
                    GDALCopyWords64(static_cast<GByte *>(pData) + iBufOffset,
752
0
                                    eBufType, 0, pabyDstBlock + iDstOffset,
753
0
                                    eDataType, 0, 1);
754
0
                }
755
0
            }
756
757
0
            if (psExtraArg->pfnProgress != nullptr &&
758
0
                !psExtraArg->pfnProgress(1.0 * (iDstY - nYOff + 1) / nYSize, "",
759
0
                                         psExtraArg->pProgressData))
760
0
            {
761
0
                eErr = CE_Failure;
762
0
                break;
763
0
            }
764
0
        }
765
0
    }
766
214k
    else
767
214k
    {
768
214k
        if (psExtraArg->eResampleAlg != GRIORA_NearestNeighbour)
769
42.6k
        {
770
42.6k
            if ((psExtraArg->eResampleAlg == GRIORA_Cubic ||
771
39.1k
                 psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
772
39.1k
                 psExtraArg->eResampleAlg == GRIORA_Bilinear ||
773
39.1k
                 psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
774
12.2k
                GetColorTable() != nullptr)
775
163
            {
776
163
                CPLError(CE_Warning, CPLE_NotSupported,
777
163
                         "Resampling method not supported on paletted band. "
778
163
                         "Falling back to nearest neighbour");
779
163
            }
780
42.5k
            else if (psExtraArg->eResampleAlg == GRIORA_Gauss &&
781
12.4k
                     GDALDataTypeIsComplex(eDataType))
782
0
            {
783
0
                CPLError(CE_Warning, CPLE_NotSupported,
784
0
                         "Resampling method not supported on complex data type "
785
0
                         "band. Falling back to nearest neighbour");
786
0
            }
787
42.5k
            else
788
42.5k
            {
789
42.5k
                return RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
790
42.5k
                                         pData, nBufXSize, nBufYSize, eBufType,
791
42.5k
                                         nPixelSpace, nLineSpace, psExtraArg);
792
42.5k
            }
793
42.6k
        }
794
795
171k
        int nLimitBlockY = 0;
796
171k
        const bool bByteCopy = eDataType == eBufType && nBandDataSize == 1;
797
171k
        int nStartBlockX = -nBlockXSize;
798
171k
        constexpr double EPS = 1e-10;
799
171k
        int nLBlockY = -1;
800
171k
        const double dfSrcXStart = 0.5 * dfSrcXInc + dfXOff + EPS;
801
171k
        const bool bIntegerXFactor =
802
171k
            bUseIntegerRequestCoords &&
803
44.4k
            static_cast<int>(dfSrcXInc) == dfSrcXInc &&
804
8.22k
            static_cast<int>(dfSrcXInc) < INT_MAX / nBandDataSize;
805
806
        /* --------------------------------------------------------------------
807
         */
808
        /*      Read case */
809
        /*      Loop over buffer computing source locations. */
810
        /* --------------------------------------------------------------------
811
         */
812
2.50M
        for (int iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++)
813
2.34M
        {
814
            // Add small epsilon to avoid some numeric precision issues.
815
2.34M
            const double dfSrcY = (iBufYOff + 0.5) * dfSrcYInc + dfYOff + EPS;
816
2.34M
            const int iSrcY = static_cast<int>(std::min(
817
2.34M
                std::max(0.0, dfSrcY), static_cast<double>(nRasterYSize - 1)));
818
819
2.34M
            GPtrDiff_t iBufOffset = static_cast<GPtrDiff_t>(iBufYOff) *
820
2.34M
                                    static_cast<GPtrDiff_t>(nLineSpace);
821
822
2.34M
            if (iSrcY >= nLimitBlockY)
823
706k
            {
824
706k
                nLBlockY = iSrcY / nBlockYSize;
825
706k
                nLimitBlockY = nLBlockY * nBlockYSize;
826
706k
                if (nLimitBlockY < INT_MAX - nBlockYSize)
827
706k
                    nLimitBlockY += nBlockYSize;
828
0
                else
829
0
                    nLimitBlockY = INT_MAX;
830
                // Make sure a new block is loaded.
831
706k
                nStartBlockX = -nBlockXSize;
832
706k
            }
833
1.64M
            else if (static_cast<int>(dfSrcXStart) < nStartBlockX)
834
281k
            {
835
                // Make sure a new block is loaded.
836
281k
                nStartBlockX = -nBlockXSize;
837
281k
            }
838
839
2.34M
            GPtrDiff_t iSrcOffsetCst = (iSrcY - nLBlockY * nBlockYSize) *
840
2.34M
                                       static_cast<GPtrDiff_t>(nBlockXSize);
841
842
2.34M
            if (bIntegerXFactor)
843
218k
            {
844
218k
                int iSrcX = static_cast<int>(dfSrcXStart);
845
218k
                const int nSrcXInc = static_cast<int>(dfSrcXInc);
846
218k
                GByte *pabyDstData = static_cast<GByte *>(pData) + iBufOffset;
847
218k
                bool bRet = false;
848
218k
                if (bByteCopy)
849
140k
                {
850
140k
                    bRet = DownsamplingIntegerXFactor<true, 1>(
851
140k
                        this, iSrcX, nSrcXInc, iSrcOffsetCst, pabyDstData,
852
140k
                        static_cast<int>(nPixelSpace), nBufXSize, GDT_UInt8,
853
140k
                        GDT_UInt8, nStartBlockX, nBlockXSize, poBlock,
854
140k
                        nLBlockY);
855
140k
                }
856
78.0k
                else if (eDataType == eBufType)
857
25.6k
                {
858
25.6k
                    switch (nBandDataSize)
859
25.6k
                    {
860
2.70k
                        case 2:
861
2.70k
                            bRet = DownsamplingIntegerXFactor<true, 2>(
862
2.70k
                                this, iSrcX, nSrcXInc, iSrcOffsetCst,
863
2.70k
                                pabyDstData, static_cast<int>(nPixelSpace),
864
2.70k
                                nBufXSize, eDataType, eDataType, nStartBlockX,
865
2.70k
                                nBlockXSize, poBlock, nLBlockY);
866
2.70k
                            break;
867
46
                        case 4:
868
46
                            bRet = DownsamplingIntegerXFactor<true, 4>(
869
46
                                this, iSrcX, nSrcXInc, iSrcOffsetCst,
870
46
                                pabyDstData, static_cast<int>(nPixelSpace),
871
46
                                nBufXSize, eDataType, eDataType, nStartBlockX,
872
46
                                nBlockXSize, poBlock, nLBlockY);
873
46
                            break;
874
22.9k
                        case 8:
875
22.9k
                            bRet = DownsamplingIntegerXFactor<true, 8>(
876
22.9k
                                this, iSrcX, nSrcXInc, iSrcOffsetCst,
877
22.9k
                                pabyDstData, static_cast<int>(nPixelSpace),
878
22.9k
                                nBufXSize, eDataType, eDataType, nStartBlockX,
879
22.9k
                                nBlockXSize, poBlock, nLBlockY);
880
22.9k
                            break;
881
0
                        case 16:
882
0
                            bRet = DownsamplingIntegerXFactor<true, 16>(
883
0
                                this, iSrcX, nSrcXInc, iSrcOffsetCst,
884
0
                                pabyDstData, static_cast<int>(nPixelSpace),
885
0
                                nBufXSize, eDataType, eDataType, nStartBlockX,
886
0
                                nBlockXSize, poBlock, nLBlockY);
887
0
                            break;
888
0
                        default:
889
0
                            CPLAssert(false);
890
0
                            break;
891
25.6k
                    }
892
25.6k
                }
893
52.4k
                else
894
52.4k
                {
895
52.4k
                    bRet = DownsamplingIntegerXFactor<false, 0>(
896
52.4k
                        this, iSrcX, nSrcXInc, iSrcOffsetCst, pabyDstData,
897
52.4k
                        static_cast<int>(nPixelSpace), nBufXSize, eDataType,
898
52.4k
                        eBufType, nStartBlockX, nBlockXSize, poBlock, nLBlockY);
899
52.4k
                }
900
218k
                if (!bRet)
901
929
                    eErr = CE_Failure;
902
218k
            }
903
2.12M
            else
904
2.12M
            {
905
2.12M
                double dfSrcX = dfSrcXStart;
906
26.6M
                for (int iBufXOff = 0; iBufXOff < nBufXSize;
907
24.4M
                     iBufXOff++, dfSrcX += dfSrcXInc)
908
24.5M
                {
909
                    // TODO?: try to avoid the clamping for most iterations
910
24.5M
                    const int iSrcX = static_cast<int>(
911
24.5M
                        std::min(std::max(0.0, dfSrcX),
912
24.5M
                                 static_cast<double>(nRasterXSize - 1)));
913
914
                    /* --------------------------------------------------------------------
915
                     */
916
                    /*      Ensure we have the appropriate block loaded. */
917
                    /* --------------------------------------------------------------------
918
                     */
919
24.5M
                    if (iSrcX >= nBlockXSize + nStartBlockX)
920
2.21M
                    {
921
2.21M
                        const int nLBlockX = iSrcX / nBlockXSize;
922
2.21M
                        nStartBlockX = nLBlockX * nBlockXSize;
923
924
2.21M
                        if (poBlock != nullptr)
925
2.05M
                            poBlock->DropLock();
926
927
2.21M
                        poBlock = GetLockedBlockRef(nLBlockX, nLBlockY, FALSE);
928
2.21M
                        if (poBlock == nullptr)
929
13.8k
                        {
930
13.8k
                            eErr = CE_Failure;
931
13.8k
                            break;
932
13.8k
                        }
933
934
2.20M
                        pabySrcBlock =
935
2.20M
                            static_cast<GByte *>(poBlock->GetDataRef());
936
2.20M
                    }
937
24.4M
                    const GPtrDiff_t nDiffX =
938
24.4M
                        static_cast<GPtrDiff_t>(iSrcX - nStartBlockX);
939
940
                    /* --------------------------------------------------------------------
941
                     */
942
                    /*      Copy over this pixel of data. */
943
                    /* --------------------------------------------------------------------
944
                     */
945
946
24.4M
                    if (bByteCopy)
947
12.2M
                    {
948
12.2M
                        GPtrDiff_t iSrcOffset = nDiffX + iSrcOffsetCst;
949
12.2M
                        static_cast<GByte *>(pData)[iBufOffset] =
950
12.2M
                            pabySrcBlock[iSrcOffset];
951
12.2M
                    }
952
12.1M
                    else if (eDataType == eBufType)
953
4.88M
                    {
954
4.88M
                        GPtrDiff_t iSrcOffset =
955
4.88M
                            (nDiffX + iSrcOffsetCst) * nBandDataSize;
956
4.88M
                        memcpy(static_cast<GByte *>(pData) + iBufOffset,
957
4.88M
                               pabySrcBlock + iSrcOffset, nBandDataSize);
958
4.88M
                    }
959
7.29M
                    else
960
7.29M
                    {
961
                        // Type to type conversion ...
962
7.29M
                        GPtrDiff_t iSrcOffset =
963
7.29M
                            (nDiffX + iSrcOffsetCst) * nBandDataSize;
964
7.29M
                        GDALCopyWords64(pabySrcBlock + iSrcOffset, eDataType, 0,
965
7.29M
                                        static_cast<GByte *>(pData) +
966
7.29M
                                            iBufOffset,
967
7.29M
                                        eBufType, 0, 1);
968
7.29M
                    }
969
970
24.4M
                    iBufOffset += static_cast<int>(nPixelSpace);
971
24.4M
                }
972
2.12M
            }
973
2.34M
            if (eErr == CE_Failure)
974
14.7k
                break;
975
976
2.33M
            if (psExtraArg->pfnProgress != nullptr &&
977
419k
                !psExtraArg->pfnProgress(1.0 * (iBufYOff + 1) / nBufYSize, "",
978
419k
                                         psExtraArg->pProgressData))
979
0
            {
980
0
                eErr = CE_Failure;
981
0
                break;
982
0
            }
983
2.33M
        }
984
171k
    }
985
986
171k
    if (poBlock != nullptr)
987
156k
        poBlock->DropLock();
988
989
171k
    return eErr;
990
214k
}
991
992
/************************************************************************/
993
/*                      GDALRasterIOTransformer()                       */
994
/************************************************************************/
995
996
struct GDALRasterIOTransformerStruct
997
{
998
    double dfXOff;
999
    double dfYOff;
1000
    double dfXRatioDstToSrc;
1001
    double dfYRatioDstToSrc;
1002
};
1003
1004
static int GDALRasterIOTransformer(void *pTransformerArg, int bDstToSrc,
1005
                                   int nPointCount, double *x, double *y,
1006
                                   double * /* z */, int *panSuccess)
1007
0
{
1008
0
    GDALRasterIOTransformerStruct *psParams =
1009
0
        static_cast<GDALRasterIOTransformerStruct *>(pTransformerArg);
1010
0
    if (bDstToSrc)
1011
0
    {
1012
0
        for (int i = 0; i < nPointCount; i++)
1013
0
        {
1014
0
            x[i] = x[i] * psParams->dfXRatioDstToSrc + psParams->dfXOff;
1015
0
            y[i] = y[i] * psParams->dfYRatioDstToSrc + psParams->dfYOff;
1016
0
            panSuccess[i] = TRUE;
1017
0
        }
1018
0
    }
1019
0
    else
1020
0
    {
1021
0
        for (int i = 0; i < nPointCount; i++)
1022
0
        {
1023
0
            x[i] = (x[i] - psParams->dfXOff) / psParams->dfXRatioDstToSrc;
1024
0
            y[i] = (y[i] - psParams->dfYOff) / psParams->dfYRatioDstToSrc;
1025
0
            panSuccess[i] = TRUE;
1026
0
        }
1027
0
    }
1028
0
    return TRUE;
1029
0
}
1030
1031
/************************************************************************/
1032
/*                         RasterIOResampled()                          */
1033
/************************************************************************/
1034
1035
//! @cond Doxygen_Suppress
1036
CPLErr GDALRasterBand::RasterIOResampled(
1037
    GDALRWFlag /* eRWFlag */, int nXOff, int nYOff, int nXSize, int nYSize,
1038
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
1039
    GSpacing nPixelSpace, GSpacing nLineSpace, GDALRasterIOExtraArg *psExtraArg)
1040
42.5k
{
1041
    // Determine if we use warping resampling or overview resampling
1042
42.5k
    const bool bUseWarp =
1043
42.5k
        (GDALDataTypeIsComplex(eDataType) &&
1044
0
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
1045
0
         psExtraArg->eResampleAlg != GRIORA_Mode);
1046
1047
42.5k
    double dfXOff = nXOff;
1048
42.5k
    double dfYOff = nYOff;
1049
42.5k
    double dfXSize = nXSize;
1050
42.5k
    double dfYSize = nYSize;
1051
42.5k
    if (psExtraArg->bFloatingPointWindowValidity)
1052
42.5k
    {
1053
42.5k
        dfXOff = psExtraArg->dfXOff;
1054
42.5k
        dfYOff = psExtraArg->dfYOff;
1055
42.5k
        dfXSize = psExtraArg->dfXSize;
1056
42.5k
        dfYSize = psExtraArg->dfYSize;
1057
42.5k
    }
1058
1059
42.5k
    const double dfXRatioDstToSrc = dfXSize / nBufXSize;
1060
42.5k
    const double dfYRatioDstToSrc = dfYSize / nBufYSize;
1061
1062
    // Determine the coordinates in the "virtual" output raster to see
1063
    // if there are not integers, in which case we will use them as a shift
1064
    // so that subwindow extracts give the exact same results as entire raster
1065
    // scaling.
1066
42.5k
    double dfDestXOff = dfXOff / dfXRatioDstToSrc;
1067
42.5k
    bool bHasXOffVirtual = false;
1068
42.5k
    int nDestXOffVirtual = 0;
1069
42.5k
    if (fabs(dfDestXOff - static_cast<int>(dfDestXOff + 0.5)) < 1e-8)
1070
42.1k
    {
1071
42.1k
        bHasXOffVirtual = true;
1072
42.1k
        dfXOff = nXOff;
1073
42.1k
        nDestXOffVirtual = static_cast<int>(dfDestXOff + 0.5);
1074
42.1k
    }
1075
1076
42.5k
    double dfDestYOff = dfYOff / dfYRatioDstToSrc;
1077
42.5k
    bool bHasYOffVirtual = false;
1078
42.5k
    int nDestYOffVirtual = 0;
1079
42.5k
    if (fabs(dfDestYOff - static_cast<int>(dfDestYOff + 0.5)) < 1e-8)
1080
40.2k
    {
1081
40.2k
        bHasYOffVirtual = true;
1082
40.2k
        dfYOff = nYOff;
1083
40.2k
        nDestYOffVirtual = static_cast<int>(dfDestYOff + 0.5);
1084
40.2k
    }
1085
1086
    // Create a MEM dataset that wraps the output buffer.
1087
42.5k
    GDALDataset *poMEMDS;
1088
42.5k
    void *pTempBuffer = nullptr;
1089
42.5k
    GSpacing nPSMem = nPixelSpace;
1090
42.5k
    GSpacing nLSMem = nLineSpace;
1091
42.5k
    void *pDataMem = pData;
1092
42.5k
    GDALDataType eDTMem = eBufType;
1093
42.5k
    if (eBufType != eDataType && !GDAL_GET_OPERATE_IN_BUF_TYPE(*psExtraArg))
1094
0
    {
1095
0
        nPSMem = GDALGetDataTypeSizeBytes(eDataType);
1096
0
        nLSMem = nPSMem * nBufXSize;
1097
0
        pTempBuffer =
1098
0
            VSI_MALLOC2_VERBOSE(nBufYSize, static_cast<size_t>(nLSMem));
1099
0
        if (pTempBuffer == nullptr)
1100
0
            return CE_Failure;
1101
0
        pDataMem = pTempBuffer;
1102
0
        eDTMem = eDataType;
1103
0
    }
1104
1105
42.5k
    poMEMDS =
1106
42.5k
        MEMDataset::Create("", nDestXOffVirtual + nBufXSize,
1107
42.5k
                           nDestYOffVirtual + nBufYSize, 0, eDTMem, nullptr);
1108
42.5k
    GByte *pabyData = static_cast<GByte *>(pDataMem) -
1109
42.5k
                      nPSMem * nDestXOffVirtual - nLSMem * nDestYOffVirtual;
1110
42.5k
    GDALRasterBandH hMEMBand = MEMCreateRasterBandEx(
1111
42.5k
        poMEMDS, 1, pabyData, eDTMem, nPSMem, nLSMem, false);
1112
42.5k
    poMEMDS->SetBand(1, GDALRasterBand::FromHandle(hMEMBand));
1113
1114
42.5k
    const char *pszNBITS =
1115
42.5k
        GetMetadataItem(GDALMD_NBITS, GDAL_MDD_IMAGE_STRUCTURE);
1116
42.5k
    const int nNBITS = pszNBITS ? atoi(pszNBITS) : 0;
1117
42.5k
    if (pszNBITS)
1118
1.07k
        GDALRasterBand::FromHandle(hMEMBand)->SetMetadataItem(
1119
1.07k
            GDALMD_NBITS, pszNBITS, GDAL_MDD_IMAGE_STRUCTURE);
1120
1121
42.5k
    CPLErr eErr = CE_None;
1122
1123
    // Do the resampling.
1124
42.5k
    if (bUseWarp)
1125
0
    {
1126
0
        int bHasNoData = FALSE;
1127
0
        double dfNoDataValue = GetNoDataValue(&bHasNoData);
1128
1129
0
        VRTDatasetH hVRTDS = nullptr;
1130
0
        GDALRasterBandH hVRTBand = nullptr;
1131
0
        if (GetDataset() == nullptr)
1132
0
        {
1133
            /* Create VRT dataset that wraps the whole dataset */
1134
0
            hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
1135
0
            VRTAddBand(hVRTDS, eDataType, nullptr);
1136
0
            hVRTBand = GDALGetRasterBand(hVRTDS, 1);
1137
0
            VRTAddSimpleSource(hVRTBand, this, 0, 0, nRasterXSize, nRasterYSize,
1138
0
                               0, 0, nRasterXSize, nRasterYSize, nullptr,
1139
0
                               VRT_NODATA_UNSET);
1140
1141
            /* Add a mask band if needed */
1142
0
            if (GetMaskFlags() != GMF_ALL_VALID)
1143
0
            {
1144
0
                GDALDataset::FromHandle(hVRTDS)->CreateMaskBand(0);
1145
0
                VRTSourcedRasterBand *poVRTMaskBand =
1146
0
                    reinterpret_cast<VRTSourcedRasterBand *>(
1147
0
                        reinterpret_cast<GDALRasterBand *>(hVRTBand)
1148
0
                            ->GetMaskBand());
1149
0
                poVRTMaskBand->AddMaskBandSource(this, 0, 0, nRasterXSize,
1150
0
                                                 nRasterYSize, 0, 0,
1151
0
                                                 nRasterXSize, nRasterYSize);
1152
0
            }
1153
0
        }
1154
1155
0
        GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();
1156
0
        switch (psExtraArg->eResampleAlg)
1157
0
        {
1158
0
            case GRIORA_NearestNeighbour:
1159
0
                psWarpOptions->eResampleAlg = GRA_NearestNeighbour;
1160
0
                break;
1161
0
            case GRIORA_Bilinear:
1162
0
                psWarpOptions->eResampleAlg = GRA_Bilinear;
1163
0
                break;
1164
0
            case GRIORA_Cubic:
1165
0
                psWarpOptions->eResampleAlg = GRA_Cubic;
1166
0
                break;
1167
0
            case GRIORA_CubicSpline:
1168
0
                psWarpOptions->eResampleAlg = GRA_CubicSpline;
1169
0
                break;
1170
0
            case GRIORA_Lanczos:
1171
0
                psWarpOptions->eResampleAlg = GRA_Lanczos;
1172
0
                break;
1173
0
            case GRIORA_Average:
1174
0
                psWarpOptions->eResampleAlg = GRA_Average;
1175
0
                break;
1176
0
            case GRIORA_RMS:
1177
0
                psWarpOptions->eResampleAlg = GRA_RMS;
1178
0
                break;
1179
0
            case GRIORA_Mode:
1180
0
                psWarpOptions->eResampleAlg = GRA_Mode;
1181
0
                break;
1182
0
            default:
1183
0
                CPLAssert(false);
1184
0
                psWarpOptions->eResampleAlg = GRA_NearestNeighbour;
1185
0
                break;
1186
0
        }
1187
0
        psWarpOptions->hSrcDS = hVRTDS ? hVRTDS : GetDataset();
1188
0
        psWarpOptions->hDstDS = poMEMDS;
1189
0
        psWarpOptions->nBandCount = 1;
1190
0
        int nSrcBandNumber = hVRTDS ? 1 : nBand;
1191
0
        int nDstBandNumber = 1;
1192
0
        psWarpOptions->panSrcBands = &nSrcBandNumber;
1193
0
        psWarpOptions->panDstBands = &nDstBandNumber;
1194
0
        psWarpOptions->pfnProgress = psExtraArg->pfnProgress
1195
0
                                         ? psExtraArg->pfnProgress
1196
0
                                         : GDALDummyProgress;
1197
0
        psWarpOptions->pProgressArg = psExtraArg->pProgressData;
1198
0
        psWarpOptions->pfnTransformer = GDALRasterIOTransformer;
1199
0
        if (bHasNoData)
1200
0
        {
1201
0
            psWarpOptions->papszWarpOptions = CSLSetNameValue(
1202
0
                psWarpOptions->papszWarpOptions, "INIT_DEST", "NO_DATA");
1203
0
            if (psWarpOptions->padfSrcNoDataReal == nullptr)
1204
0
            {
1205
0
                psWarpOptions->padfSrcNoDataReal =
1206
0
                    static_cast<double *>(CPLMalloc(sizeof(double)));
1207
0
                psWarpOptions->padfSrcNoDataReal[0] = dfNoDataValue;
1208
0
            }
1209
1210
0
            if (psWarpOptions->padfDstNoDataReal == nullptr)
1211
0
            {
1212
0
                psWarpOptions->padfDstNoDataReal =
1213
0
                    static_cast<double *>(CPLMalloc(sizeof(double)));
1214
0
                psWarpOptions->padfDstNoDataReal[0] = dfNoDataValue;
1215
0
            }
1216
0
        }
1217
1218
0
        GDALRasterIOTransformerStruct sTransformer;
1219
0
        sTransformer.dfXOff = bHasXOffVirtual ? 0 : dfXOff;
1220
0
        sTransformer.dfYOff = bHasYOffVirtual ? 0 : dfYOff;
1221
0
        sTransformer.dfXRatioDstToSrc = dfXRatioDstToSrc;
1222
0
        sTransformer.dfYRatioDstToSrc = dfYRatioDstToSrc;
1223
0
        psWarpOptions->pTransformerArg = &sTransformer;
1224
1225
0
        GDALWarpOperationH hWarpOperation =
1226
0
            GDALCreateWarpOperation(psWarpOptions);
1227
0
        eErr = GDALChunkAndWarpImage(hWarpOperation, nDestXOffVirtual,
1228
0
                                     nDestYOffVirtual, nBufXSize, nBufYSize);
1229
0
        GDALDestroyWarpOperation(hWarpOperation);
1230
1231
0
        psWarpOptions->panSrcBands = nullptr;
1232
0
        psWarpOptions->panDstBands = nullptr;
1233
0
        GDALDestroyWarpOptions(psWarpOptions);
1234
1235
0
        if (hVRTDS)
1236
0
            GDALClose(hVRTDS);
1237
0
    }
1238
42.5k
    else
1239
42.5k
    {
1240
42.5k
        const char *pszResampling =
1241
42.5k
            GDALRasterIOGetResampleAlg(psExtraArg->eResampleAlg);
1242
42.5k
        int nKernelRadius = 0;
1243
42.5k
        GDALResampleFunction pfnResampleFunc =
1244
42.5k
            GDALGetResampleFunction(pszResampling, &nKernelRadius);
1245
42.5k
        CPLAssert(pfnResampleFunc);
1246
42.5k
        GDALDataType eWrkDataType =
1247
42.5k
            GDALGetOvrWorkDataType(pszResampling, eDataType);
1248
42.5k
        int nHasNoData = 0;
1249
42.5k
        double dfNoDataValue = GetNoDataValue(&nHasNoData);
1250
42.5k
        const bool bHasNoData = CPL_TO_BOOL(nHasNoData);
1251
42.5k
        if (!bHasNoData)
1252
29.5k
            dfNoDataValue = 0.0;
1253
1254
42.5k
        int nDstBlockXSize = nBufXSize;
1255
42.5k
        int nDstBlockYSize = nBufYSize;
1256
42.5k
        int nFullResXChunk = 0;
1257
42.5k
        int nFullResYChunk = 0;
1258
42.5k
        while (true)
1259
42.5k
        {
1260
42.5k
            nFullResXChunk = static_cast<int>(std::min<double>(
1261
42.5k
                3 + nDstBlockXSize * dfXRatioDstToSrc, nRasterXSize));
1262
42.5k
            nFullResYChunk = static_cast<int>(std::min<double>(
1263
42.5k
                3 + nDstBlockYSize * dfYRatioDstToSrc, nRasterYSize));
1264
42.5k
            if ((nDstBlockXSize == 1 && nDstBlockYSize == 1) ||
1265
39.5k
                (static_cast<GIntBig>(nFullResXChunk) * nFullResYChunk <=
1266
39.5k
                 1024 * 1024))
1267
42.5k
                break;
1268
            // When operating on the full width of a raster whose block width is
1269
            // the raster width, prefer doing chunks in height.
1270
0
            if (nFullResXChunk >= nXSize && nXSize == nBlockXSize &&
1271
0
                nDstBlockYSize > 1)
1272
0
                nDstBlockYSize /= 2;
1273
            /* Otherwise cut the maximal dimension */
1274
0
            else if (nDstBlockXSize > 1 &&
1275
0
                     (nFullResXChunk > nFullResYChunk || nDstBlockYSize == 1))
1276
0
                nDstBlockXSize /= 2;
1277
0
            else
1278
0
                nDstBlockYSize /= 2;
1279
0
        }
1280
1281
42.5k
        const int nOvrXFactor =
1282
42.5k
            std::max(1, static_cast<int>(0.5 + dfXRatioDstToSrc));
1283
42.5k
        const int nOvrYFactor =
1284
42.5k
            std::max(1, static_cast<int>(0.5 + dfYRatioDstToSrc));
1285
42.5k
        const int nFullResXSizeQueried = static_cast<int>(
1286
42.5k
            std::min<int64_t>(nFullResXChunk + static_cast<int64_t>(2) *
1287
42.5k
                                                   nKernelRadius * nOvrXFactor,
1288
42.5k
                              nRasterXSize));
1289
42.5k
        const int nFullResYSizeQueried = static_cast<int>(
1290
42.5k
            std::min<int64_t>(nFullResYChunk + static_cast<int64_t>(2) *
1291
42.5k
                                                   nKernelRadius * nOvrYFactor,
1292
42.5k
                              nRasterYSize));
1293
1294
42.5k
        void *pChunk =
1295
42.5k
            VSI_MALLOC3_VERBOSE(GDALGetDataTypeSizeBytes(eWrkDataType),
1296
42.5k
                                nFullResXSizeQueried, nFullResYSizeQueried);
1297
42.5k
        GByte *pabyChunkNoDataMask = nullptr;
1298
1299
42.5k
        GDALRasterBand *poMaskBand = GetMaskBand();
1300
42.5k
        int l_nMaskFlags = GetMaskFlags();
1301
1302
42.5k
        bool bUseNoDataMask = ((l_nMaskFlags & GMF_ALL_VALID) == 0);
1303
42.5k
        if (bUseNoDataMask)
1304
21.9k
        {
1305
21.9k
            pabyChunkNoDataMask = static_cast<GByte *>(VSI_MALLOC2_VERBOSE(
1306
21.9k
                nFullResXSizeQueried, nFullResYSizeQueried));
1307
21.9k
        }
1308
42.5k
        if (pChunk == nullptr ||
1309
42.5k
            (bUseNoDataMask && pabyChunkNoDataMask == nullptr))
1310
0
        {
1311
0
            GDALClose(poMEMDS);
1312
0
            CPLFree(pChunk);
1313
0
            CPLFree(pabyChunkNoDataMask);
1314
0
            VSIFree(pTempBuffer);
1315
0
            return CE_Failure;
1316
0
        }
1317
1318
42.5k
        const int64_t nTotalBlocks =
1319
42.5k
            static_cast<int64_t>(cpl::div_round_up(nBufXSize, nDstBlockXSize)) *
1320
42.5k
            cpl::div_round_up(nBufYSize, nDstBlockYSize);
1321
42.5k
        int64_t nBlocksDone = 0;
1322
1323
85.0k
        for (int nDstYOff = 0; nDstYOff < nBufYSize && eErr == CE_None;
1324
42.5k
             nDstYOff += nDstBlockYSize)
1325
42.5k
        {
1326
42.5k
            int nDstYCount;
1327
42.5k
            if (nDstYOff + nDstBlockYSize <= nBufYSize)
1328
42.5k
                nDstYCount = nDstBlockYSize;
1329
0
            else
1330
0
                nDstYCount = nBufYSize - nDstYOff;
1331
1332
42.5k
            int nChunkYOff =
1333
42.5k
                nYOff + static_cast<int>(nDstYOff * dfYRatioDstToSrc);
1334
42.5k
            int nChunkYOff2 = nYOff + 1 +
1335
42.5k
                              static_cast<int>(ceil((nDstYOff + nDstYCount) *
1336
42.5k
                                                    dfYRatioDstToSrc));
1337
42.5k
            if (nChunkYOff2 > nRasterYSize)
1338
11.6k
                nChunkYOff2 = nRasterYSize;
1339
42.5k
            int nYCount = nChunkYOff2 - nChunkYOff;
1340
42.5k
            CPLAssert(nYCount <= nFullResYChunk);
1341
1342
42.5k
            int nChunkYOffQueried = nChunkYOff - nKernelRadius * nOvrYFactor;
1343
42.5k
            int nChunkYSizeQueried = nYCount + 2 * nKernelRadius * nOvrYFactor;
1344
42.5k
            if (nChunkYOffQueried < 0)
1345
13.2k
            {
1346
13.2k
                nChunkYSizeQueried += nChunkYOffQueried;
1347
13.2k
                nChunkYOffQueried = 0;
1348
13.2k
            }
1349
42.5k
            if (nChunkYSizeQueried + nChunkYOffQueried > nRasterYSize)
1350
11.7k
                nChunkYSizeQueried = nRasterYSize - nChunkYOffQueried;
1351
42.5k
            CPLAssert(nChunkYSizeQueried <= nFullResYSizeQueried);
1352
1353
42.5k
            int nDstXOff = 0;
1354
85.0k
            for (nDstXOff = 0; nDstXOff < nBufXSize && eErr == CE_None;
1355
42.5k
                 nDstXOff += nDstBlockXSize)
1356
42.5k
            {
1357
42.5k
                int nDstXCount = 0;
1358
42.5k
                if (nDstXOff + nDstBlockXSize <= nBufXSize)
1359
42.5k
                    nDstXCount = nDstBlockXSize;
1360
0
                else
1361
0
                    nDstXCount = nBufXSize - nDstXOff;
1362
1363
42.5k
                int nChunkXOff =
1364
42.5k
                    nXOff + static_cast<int>(nDstXOff * dfXRatioDstToSrc);
1365
42.5k
                int nChunkXOff2 =
1366
42.5k
                    nXOff + 1 +
1367
42.5k
                    static_cast<int>(
1368
42.5k
                        ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc));
1369
42.5k
                if (nChunkXOff2 > nRasterXSize)
1370
39.4k
                    nChunkXOff2 = nRasterXSize;
1371
42.5k
                int nXCount = nChunkXOff2 - nChunkXOff;
1372
42.5k
                CPLAssert(nXCount <= nFullResXChunk);
1373
1374
42.5k
                int nChunkXOffQueried =
1375
42.5k
                    nChunkXOff - nKernelRadius * nOvrXFactor;
1376
42.5k
                int nChunkXSizeQueried =
1377
42.5k
                    nXCount + 2 * nKernelRadius * nOvrXFactor;
1378
42.5k
                if (nChunkXOffQueried < 0)
1379
23.2k
                {
1380
23.2k
                    nChunkXSizeQueried += nChunkXOffQueried;
1381
23.2k
                    nChunkXOffQueried = 0;
1382
23.2k
                }
1383
42.5k
                if (nChunkXSizeQueried + nChunkXOffQueried > nRasterXSize)
1384
21.4k
                    nChunkXSizeQueried = nRasterXSize - nChunkXOffQueried;
1385
42.5k
                CPLAssert(nChunkXSizeQueried <= nFullResXSizeQueried);
1386
1387
                // Read the source buffers.
1388
42.5k
                eErr = RasterIO(GF_Read, nChunkXOffQueried, nChunkYOffQueried,
1389
42.5k
                                nChunkXSizeQueried, nChunkYSizeQueried, pChunk,
1390
42.5k
                                nChunkXSizeQueried, nChunkYSizeQueried,
1391
42.5k
                                eWrkDataType, 0, 0, nullptr);
1392
1393
42.5k
                bool bSkipResample = false;
1394
42.5k
                bool bNoDataMaskFullyOpaque = false;
1395
42.5k
                if (eErr == CE_None && bUseNoDataMask)
1396
21.9k
                {
1397
21.9k
                    eErr = poMaskBand->RasterIO(
1398
21.9k
                        GF_Read, nChunkXOffQueried, nChunkYOffQueried,
1399
21.9k
                        nChunkXSizeQueried, nChunkYSizeQueried,
1400
21.9k
                        pabyChunkNoDataMask, nChunkXSizeQueried,
1401
21.9k
                        nChunkYSizeQueried, GDT_UInt8, 0, 0, nullptr);
1402
1403
                    /* Optimizations if mask if fully opaque or transparent */
1404
21.9k
                    int nPixels = nChunkXSizeQueried * nChunkYSizeQueried;
1405
21.9k
                    GByte bVal = pabyChunkNoDataMask[0];
1406
21.9k
                    int i = 1;
1407
12.5M
                    for (; i < nPixels; i++)
1408
12.5M
                    {
1409
12.5M
                        if (pabyChunkNoDataMask[i] != bVal)
1410
6.16k
                            break;
1411
12.5M
                    }
1412
21.9k
                    if (i == nPixels)
1413
15.7k
                    {
1414
15.7k
                        if (bVal == 0)
1415
2.01k
                        {
1416
4.14k
                            for (int j = 0; j < nDstYCount; j++)
1417
2.13k
                            {
1418
2.13k
                                GDALCopyWords64(&dfNoDataValue, GDT_Float64, 0,
1419
2.13k
                                                static_cast<GByte *>(pDataMem) +
1420
2.13k
                                                    nLSMem * (j + nDstYOff) +
1421
2.13k
                                                    nDstXOff * nPSMem,
1422
2.13k
                                                eDTMem,
1423
2.13k
                                                static_cast<int>(nPSMem),
1424
2.13k
                                                nDstXCount);
1425
2.13k
                            }
1426
2.01k
                            bSkipResample = true;
1427
2.01k
                        }
1428
13.7k
                        else
1429
13.7k
                        {
1430
13.7k
                            bNoDataMaskFullyOpaque = true;
1431
13.7k
                        }
1432
15.7k
                    }
1433
21.9k
                }
1434
1435
42.5k
                if (!bSkipResample && eErr == CE_None)
1436
40.3k
                {
1437
40.3k
                    const bool bPropagateNoData = false;
1438
40.3k
                    void *pDstBuffer = nullptr;
1439
40.3k
                    GDALDataType eDstBufferDataType = GDT_Unknown;
1440
40.3k
                    GDALRasterBand *poMEMBand =
1441
40.3k
                        GDALRasterBand::FromHandle(hMEMBand);
1442
40.3k
                    GDALOverviewResampleArgs args;
1443
40.3k
                    args.eSrcDataType = eDataType;
1444
40.3k
                    args.eOvrDataType = poMEMBand->GetRasterDataType();
1445
40.3k
                    args.nOvrXSize = poMEMBand->GetXSize();
1446
40.3k
                    args.nOvrYSize = poMEMBand->GetYSize();
1447
40.3k
                    args.nOvrNBITS = nNBITS;
1448
40.3k
                    args.dfXRatioDstToSrc = dfXRatioDstToSrc;
1449
40.3k
                    args.dfYRatioDstToSrc = dfYRatioDstToSrc;
1450
40.3k
                    args.dfSrcXDelta =
1451
40.3k
                        dfXOff - nXOff; /* == 0 if bHasXOffVirtual */
1452
40.3k
                    args.dfSrcYDelta =
1453
40.3k
                        dfYOff - nYOff; /* == 0 if bHasYOffVirtual */
1454
40.3k
                    args.eWrkDataType = eWrkDataType;
1455
40.3k
                    args.pabyChunkNodataMask =
1456
40.3k
                        bNoDataMaskFullyOpaque ? nullptr : pabyChunkNoDataMask;
1457
40.3k
                    args.nChunkXOff =
1458
40.3k
                        nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff);
1459
40.3k
                    args.nChunkXSize = nChunkXSizeQueried;
1460
40.3k
                    args.nChunkYOff =
1461
40.3k
                        nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff);
1462
40.3k
                    args.nChunkYSize = nChunkYSizeQueried;
1463
40.3k
                    args.nDstXOff = nDstXOff + nDestXOffVirtual;
1464
40.3k
                    args.nDstXOff2 = nDstXOff + nDestXOffVirtual + nDstXCount;
1465
40.3k
                    args.nDstYOff = nDstYOff + nDestYOffVirtual;
1466
40.3k
                    args.nDstYOff2 = nDstYOff + nDestYOffVirtual + nDstYCount;
1467
40.3k
                    args.pszResampling = pszResampling;
1468
40.3k
                    args.bHasNoData = bHasNoData;
1469
40.3k
                    args.dfNoDataValue = dfNoDataValue;
1470
40.3k
                    args.poColorTable = GetColorTable();
1471
40.3k
                    args.bPropagateNoData = bPropagateNoData;
1472
40.3k
                    eErr = pfnResampleFunc(args, pChunk, &pDstBuffer,
1473
40.3k
                                           &eDstBufferDataType);
1474
40.3k
                    if (eErr == CE_None)
1475
40.3k
                    {
1476
40.3k
                        eErr = poMEMBand->RasterIO(
1477
40.3k
                            GF_Write, nDstXOff + nDestXOffVirtual,
1478
40.3k
                            nDstYOff + nDestYOffVirtual, nDstXCount, nDstYCount,
1479
40.3k
                            pDstBuffer, nDstXCount, nDstYCount,
1480
40.3k
                            eDstBufferDataType, 0, 0, nullptr);
1481
40.3k
                    }
1482
40.3k
                    CPLFree(pDstBuffer);
1483
40.3k
                }
1484
1485
42.5k
                nBlocksDone++;
1486
42.5k
                if (eErr == CE_None && psExtraArg->pfnProgress != nullptr &&
1487
1.74k
                    !psExtraArg->pfnProgress(
1488
1.74k
                        static_cast<double>(nBlocksDone) /
1489
1.74k
                            static_cast<double>(nTotalBlocks),
1490
1.74k
                        "", psExtraArg->pProgressData))
1491
0
                {
1492
0
                    eErr = CE_Failure;
1493
0
                }
1494
42.5k
            }
1495
42.5k
        }
1496
1497
42.5k
        CPLFree(pChunk);
1498
42.5k
        CPLFree(pabyChunkNoDataMask);
1499
42.5k
    }
1500
1501
42.5k
    if (pTempBuffer)
1502
0
    {
1503
0
        CPL_IGNORE_RET_VAL(poMEMDS->GetRasterBand(1)->RasterIO(
1504
0
            GF_Read, nDestXOffVirtual, nDestYOffVirtual, nBufXSize, nBufYSize,
1505
0
            pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace,
1506
0
            nullptr));
1507
0
    }
1508
42.5k
    GDALClose(poMEMDS);
1509
42.5k
    VSIFree(pTempBuffer);
1510
1511
42.5k
    return eErr;
1512
42.5k
}
1513
1514
/************************************************************************/
1515
/*                         RasterIOResampled()                          */
1516
/************************************************************************/
1517
1518
CPLErr GDALDataset::RasterIOResampled(
1519
    GDALRWFlag /* eRWFlag */, int nXOff, int nYOff, int nXSize, int nYSize,
1520
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
1521
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
1522
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
1523
1524
4
{
1525
#if 0
1526
    // Determine if we use warping resampling or overview resampling
1527
    bool bUseWarp = false;
1528
    if( GDALDataTypeIsComplex( eDataType ) )
1529
        bUseWarp = true;
1530
#endif
1531
1532
4
    double dfXOff = nXOff;
1533
4
    double dfYOff = nYOff;
1534
4
    double dfXSize = nXSize;
1535
4
    double dfYSize = nYSize;
1536
4
    if (psExtraArg->bFloatingPointWindowValidity)
1537
4
    {
1538
4
        dfXOff = psExtraArg->dfXOff;
1539
4
        dfYOff = psExtraArg->dfYOff;
1540
4
        dfXSize = psExtraArg->dfXSize;
1541
4
        dfYSize = psExtraArg->dfYSize;
1542
4
    }
1543
1544
4
    const double dfXRatioDstToSrc = dfXSize / nBufXSize;
1545
4
    const double dfYRatioDstToSrc = dfYSize / nBufYSize;
1546
1547
    // Determine the coordinates in the "virtual" output raster to see
1548
    // if there are not integers, in which case we will use them as a shift
1549
    // so that subwindow extracts give the exact same results as entire raster
1550
    // scaling.
1551
4
    double dfDestXOff = dfXOff / dfXRatioDstToSrc;
1552
4
    bool bHasXOffVirtual = false;
1553
4
    int nDestXOffVirtual = 0;
1554
4
    if (fabs(dfDestXOff - static_cast<int>(dfDestXOff + 0.5)) < 1e-8)
1555
4
    {
1556
4
        bHasXOffVirtual = true;
1557
4
        dfXOff = nXOff;
1558
4
        nDestXOffVirtual = static_cast<int>(dfDestXOff + 0.5);
1559
4
    }
1560
1561
4
    double dfDestYOff = dfYOff / dfYRatioDstToSrc;
1562
4
    bool bHasYOffVirtual = false;
1563
4
    int nDestYOffVirtual = 0;
1564
4
    if (fabs(dfDestYOff - static_cast<int>(dfDestYOff + 0.5)) < 1e-8)
1565
4
    {
1566
4
        bHasYOffVirtual = true;
1567
4
        dfYOff = nYOff;
1568
4
        nDestYOffVirtual = static_cast<int>(dfDestYOff + 0.5);
1569
4
    }
1570
1571
    // Create a MEM dataset that wraps the output buffer.
1572
4
    std::unique_ptr<void, VSIFreeReleaser> pTempBuffer;
1573
4
    GSpacing nPSMem = nPixelSpace;
1574
4
    GSpacing nLSMem = nLineSpace;
1575
4
    GSpacing nBandSpaceMEM = nBandSpace;
1576
4
    void *pDataMem = pData;
1577
4
    GDALDataType eDTMem = eBufType;
1578
4
    GDALRasterBand *poFirstSrcBand = GetRasterBand(panBandMap[0]);
1579
4
    const GDALDataType eDataType = poFirstSrcBand->GetRasterDataType();
1580
4
    if (eBufType != eDataType && !GDAL_GET_OPERATE_IN_BUF_TYPE(*psExtraArg))
1581
0
    {
1582
0
        nPSMem = GDALGetDataTypeSizeBytes(eDataType);
1583
0
        nLSMem = nPSMem * nBufXSize;
1584
0
        nBandSpaceMEM = nLSMem * nBandCount;
1585
0
        pTempBuffer.reset(VSI_MALLOC3_VERBOSE(nBandCount, nBufYSize,
1586
0
                                              static_cast<size_t>(nLSMem)));
1587
0
        if (pTempBuffer == nullptr)
1588
0
            return CE_Failure;
1589
0
        pDataMem = pTempBuffer.get();
1590
0
        eDTMem = eDataType;
1591
0
    }
1592
1593
4
    auto poMEMDS = std::unique_ptr<GDALDataset>(
1594
4
        MEMDataset::Create("", nDestXOffVirtual + nBufXSize,
1595
4
                           nDestYOffVirtual + nBufYSize, 0, eDTMem, nullptr));
1596
#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
1597
    std::vector<GDALRasterBand *> apoDstBands(nBandCount);
1598
#endif
1599
4
    int nNBITS = 0;
1600
17
    for (int i = 0; i < nBandCount; i++)
1601
13
    {
1602
13
        GByte *const pBandData = static_cast<GByte *>(pDataMem) -
1603
13
                                 nPSMem * nDestXOffVirtual -
1604
13
                                 nLSMem * nDestYOffVirtual + nBandSpaceMEM * i;
1605
13
        auto poMEMBand = GDALRasterBand::FromHandle(MEMCreateRasterBandEx(
1606
13
            poMEMDS.get(), i + 1, pBandData, eDTMem, nPSMem, nLSMem, false));
1607
13
        poMEMDS->SetBand(i + 1, poMEMBand);
1608
1609
13
        GDALRasterBand *poSrcBand = GetRasterBand(panBandMap[i]);
1610
#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
1611
        apoDstBands[i] = poMEMBand;
1612
#endif
1613
13
        const char *pszNBITS =
1614
13
            poSrcBand->GetMetadataItem(GDALMD_NBITS, GDAL_MDD_IMAGE_STRUCTURE);
1615
13
        if (pszNBITS)
1616
0
        {
1617
0
            nNBITS = atoi(pszNBITS);
1618
0
            poMEMDS->GetRasterBand(i + 1)->SetMetadataItem(
1619
0
                GDALMD_NBITS, pszNBITS, GDAL_MDD_IMAGE_STRUCTURE);
1620
0
        }
1621
13
    }
1622
1623
4
    CPLErr eErr = CE_None;
1624
1625
    // TODO(schwehr): Why disabled?  Why not just delete?
1626
    // Looks like this code was initially added as disable by copying
1627
    // from RasterIO here:
1628
    // https://trac.osgeo.org/gdal/changeset/29572
1629
#if 0
1630
    // Do the resampling.
1631
    if( bUseWarp )
1632
    {
1633
        VRTDatasetH hVRTDS = nullptr;
1634
        GDALRasterBandH hVRTBand = nullptr;
1635
        if( GetDataset() == nullptr )
1636
        {
1637
            /* Create VRT dataset that wraps the whole dataset */
1638
            hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
1639
            VRTAddBand( hVRTDS, eDataType, nullptr );
1640
            hVRTBand = GDALGetRasterBand(hVRTDS, 1);
1641
            VRTAddSimpleSource( (VRTSourcedRasterBandH)hVRTBand,
1642
                                (GDALRasterBandH)this,
1643
                                0, 0,
1644
                                nRasterXSize, nRasterYSize,
1645
                                0, 0,
1646
                                nRasterXSize, nRasterYSize,
1647
                                nullptr, VRT_NODATA_UNSET );
1648
1649
            /* Add a mask band if needed */
1650
            if( GetMaskFlags() != GMF_ALL_VALID )
1651
            {
1652
                ((GDALDataset*)hVRTDS)->CreateMaskBand(0);
1653
                VRTSourcedRasterBand* poVRTMaskBand =
1654
                    (VRTSourcedRasterBand*)(((GDALRasterBand*)hVRTBand)->GetMaskBand());
1655
                poVRTMaskBand->
1656
                    AddMaskBandSource( this,
1657
                                    0, 0,
1658
                                    nRasterXSize, nRasterYSize,
1659
                                    0, 0,
1660
                                    nRasterXSize, nRasterYSize);
1661
            }
1662
        }
1663
1664
        GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
1665
        psWarpOptions->eResampleAlg = (GDALResampleAlg)psExtraArg->eResampleAlg;
1666
        psWarpOptions->hSrcDS = (GDALDatasetH) (hVRTDS ? hVRTDS : GetDataset());
1667
        psWarpOptions->hDstDS = (GDALDatasetH) poMEMDS;
1668
        psWarpOptions->nBandCount = 1;
1669
        int nSrcBandNumber = (hVRTDS ? 1 : nBand);
1670
        int nDstBandNumber = 1;
1671
        psWarpOptions->panSrcBands = &nSrcBandNumber;
1672
        psWarpOptions->panDstBands = &nDstBandNumber;
1673
        psWarpOptions->pfnProgress = psExtraArg->pfnProgress ?
1674
                    psExtraArg->pfnProgress : GDALDummyProgress;
1675
        psWarpOptions->pProgressArg = psExtraArg->pProgressData;
1676
        psWarpOptions->pfnTransformer = GDALRasterIOTransformer;
1677
        GDALRasterIOTransformerStruct sTransformer;
1678
        sTransformer.dfXOff = bHasXOffVirtual ? 0 : dfXOff;
1679
        sTransformer.dfYOff = bHasYOffVirtual ? 0 : dfYOff;
1680
        sTransformer.dfXRatioDstToSrc = dfXRatioDstToSrc;
1681
        sTransformer.dfYRatioDstToSrc = dfYRatioDstToSrc;
1682
        psWarpOptions->pTransformerArg = &sTransformer;
1683
1684
        GDALWarpOperationH hWarpOperation = GDALCreateWarpOperation(psWarpOptions);
1685
        eErr = GDALChunkAndWarpImage( hWarpOperation,
1686
                                      nDestXOffVirtual, nDestYOffVirtual,
1687
                                      nBufXSize, nBufYSize );
1688
        GDALDestroyWarpOperation( hWarpOperation );
1689
1690
        psWarpOptions->panSrcBands = nullptr;
1691
        psWarpOptions->panDstBands = nullptr;
1692
        GDALDestroyWarpOptions( psWarpOptions );
1693
1694
        if( hVRTDS )
1695
            GDALClose(hVRTDS);
1696
    }
1697
    else
1698
#endif
1699
4
    {
1700
4
        const char *pszResampling =
1701
4
            GDALRasterIOGetResampleAlg(psExtraArg->eResampleAlg);
1702
1703
4
        int nBlockXSize, nBlockYSize;
1704
4
        poFirstSrcBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
1705
1706
4
        int nKernelRadius;
1707
4
        GDALResampleFunction pfnResampleFunc =
1708
4
            GDALGetResampleFunction(pszResampling, &nKernelRadius);
1709
4
        CPLAssert(pfnResampleFunc);
1710
#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
1711
        GDALResampleFunctionMultiBands pfnResampleFuncMultiBands =
1712
            GDALGetResampleFunctionMultiBands(pszResampling, &nKernelRadius);
1713
#endif
1714
4
        GDALDataType eWrkDataType =
1715
4
            GDALGetOvrWorkDataType(pszResampling, eDataType);
1716
1717
4
        int nDstBlockXSize = nBufXSize;
1718
4
        int nDstBlockYSize = nBufYSize;
1719
4
        int nFullResXChunk, nFullResYChunk;
1720
4
        while (true)
1721
4
        {
1722
4
            nFullResXChunk = static_cast<int>(std::min<double>(
1723
4
                3 + nDstBlockXSize * dfXRatioDstToSrc, nRasterXSize));
1724
4
            nFullResYChunk = static_cast<int>(std::min<double>(
1725
4
                3 + nDstBlockYSize * dfYRatioDstToSrc, nRasterYSize));
1726
4
            if ((nDstBlockXSize == 1 && nDstBlockYSize == 1) ||
1727
4
                (static_cast<GIntBig>(nFullResXChunk) * nFullResYChunk <=
1728
4
                 1024 * 1024))
1729
4
                break;
1730
            // When operating on the full width of a raster whose block width is
1731
            // the raster width, prefer doing chunks in height.
1732
0
            if (nFullResXChunk >= nXSize && nXSize == nBlockXSize &&
1733
0
                nDstBlockYSize > 1)
1734
0
                nDstBlockYSize /= 2;
1735
            /* Otherwise cut the maximal dimension */
1736
0
            else if (nDstBlockXSize > 1 &&
1737
0
                     (nFullResXChunk > nFullResYChunk || nDstBlockYSize == 1))
1738
0
                nDstBlockXSize /= 2;
1739
0
            else
1740
0
                nDstBlockYSize /= 2;
1741
0
        }
1742
1743
4
        const int nOvrFactor =
1744
4
            std::max(1, std::max(static_cast<int>(0.5 + dfXRatioDstToSrc),
1745
4
                                 static_cast<int>(0.5 + dfYRatioDstToSrc)));
1746
4
        const int nFullResXSizeQueried = static_cast<int>(
1747
4
            std::min<int64_t>(nFullResXChunk + static_cast<int64_t>(2) *
1748
4
                                                   nKernelRadius * nOvrFactor,
1749
4
                              nRasterXSize));
1750
4
        const int nFullResYSizeQueried = static_cast<int>(
1751
4
            std::min<int64_t>(nFullResYChunk + static_cast<int64_t>(2) *
1752
4
                                                   nKernelRadius * nOvrFactor,
1753
4
                              nRasterYSize));
1754
1755
4
        void *pChunk = VSI_MALLOC3_VERBOSE(
1756
4
            cpl::fits_on<int>(GDALGetDataTypeSizeBytes(eWrkDataType) *
1757
4
                              nBandCount),
1758
4
            nFullResXSizeQueried, nFullResYSizeQueried);
1759
4
        GByte *pabyChunkNoDataMask = nullptr;
1760
1761
4
        GDALRasterBand *poMaskBand = poFirstSrcBand->GetMaskBand();
1762
4
        int nMaskFlags = poFirstSrcBand->GetMaskFlags();
1763
1764
4
        bool bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
1765
4
        if (bUseNoDataMask)
1766
3
        {
1767
3
            pabyChunkNoDataMask = static_cast<GByte *>(VSI_MALLOC2_VERBOSE(
1768
3
                nFullResXSizeQueried, nFullResYSizeQueried));
1769
3
        }
1770
4
        if (pChunk == nullptr ||
1771
4
            (bUseNoDataMask && pabyChunkNoDataMask == nullptr))
1772
0
        {
1773
0
            CPLFree(pChunk);
1774
0
            CPLFree(pabyChunkNoDataMask);
1775
0
            return CE_Failure;
1776
0
        }
1777
1778
4
        const int64_t nTotalBlocks =
1779
4
            static_cast<int64_t>(cpl::div_round_up(nBufXSize, nDstBlockXSize)) *
1780
4
            cpl::div_round_up(nBufYSize, nDstBlockYSize);
1781
4
        int64_t nBlocksDone = 0;
1782
1783
8
        for (int nDstYOff = 0; nDstYOff < nBufYSize && eErr == CE_None;
1784
4
             nDstYOff += nDstBlockYSize)
1785
4
        {
1786
4
            int nDstYCount;
1787
4
            if (nDstYOff + nDstBlockYSize <= nBufYSize)
1788
4
                nDstYCount = nDstBlockYSize;
1789
0
            else
1790
0
                nDstYCount = nBufYSize - nDstYOff;
1791
1792
4
            int nChunkYOff =
1793
4
                nYOff + static_cast<int>(nDstYOff * dfYRatioDstToSrc);
1794
4
            int nChunkYOff2 = nYOff + 1 +
1795
4
                              static_cast<int>(ceil((nDstYOff + nDstYCount) *
1796
4
                                                    dfYRatioDstToSrc));
1797
4
            if (nChunkYOff2 > nRasterYSize)
1798
4
                nChunkYOff2 = nRasterYSize;
1799
4
            int nYCount = nChunkYOff2 - nChunkYOff;
1800
4
            CPLAssert(nYCount <= nFullResYChunk);
1801
1802
4
            int nChunkYOffQueried = nChunkYOff - nKernelRadius * nOvrFactor;
1803
4
            int nChunkYSizeQueried = nYCount + 2 * nKernelRadius * nOvrFactor;
1804
4
            if (nChunkYOffQueried < 0)
1805
4
            {
1806
4
                nChunkYSizeQueried += nChunkYOffQueried;
1807
4
                nChunkYOffQueried = 0;
1808
4
            }
1809
4
            if (nChunkYSizeQueried + nChunkYOffQueried > nRasterYSize)
1810
4
                nChunkYSizeQueried = nRasterYSize - nChunkYOffQueried;
1811
4
            CPLAssert(nChunkYSizeQueried <= nFullResYSizeQueried);
1812
1813
4
            int nDstXOff;
1814
8
            for (nDstXOff = 0; nDstXOff < nBufXSize && eErr == CE_None;
1815
4
                 nDstXOff += nDstBlockXSize)
1816
4
            {
1817
4
                int nDstXCount;
1818
4
                if (nDstXOff + nDstBlockXSize <= nBufXSize)
1819
4
                    nDstXCount = nDstBlockXSize;
1820
0
                else
1821
0
                    nDstXCount = nBufXSize - nDstXOff;
1822
1823
4
                int nChunkXOff =
1824
4
                    nXOff + static_cast<int>(nDstXOff * dfXRatioDstToSrc);
1825
4
                int nChunkXOff2 =
1826
4
                    nXOff + 1 +
1827
4
                    static_cast<int>(
1828
4
                        ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc));
1829
4
                if (nChunkXOff2 > nRasterXSize)
1830
4
                    nChunkXOff2 = nRasterXSize;
1831
4
                int nXCount = nChunkXOff2 - nChunkXOff;
1832
4
                CPLAssert(nXCount <= nFullResXChunk);
1833
1834
4
                int nChunkXOffQueried = nChunkXOff - nKernelRadius * nOvrFactor;
1835
4
                int nChunkXSizeQueried =
1836
4
                    nXCount + 2 * nKernelRadius * nOvrFactor;
1837
4
                if (nChunkXOffQueried < 0)
1838
4
                {
1839
4
                    nChunkXSizeQueried += nChunkXOffQueried;
1840
4
                    nChunkXOffQueried = 0;
1841
4
                }
1842
4
                if (nChunkXSizeQueried + nChunkXOffQueried > nRasterXSize)
1843
4
                    nChunkXSizeQueried = nRasterXSize - nChunkXOffQueried;
1844
4
                CPLAssert(nChunkXSizeQueried <= nFullResXSizeQueried);
1845
1846
4
                bool bSkipResample = false;
1847
4
                bool bNoDataMaskFullyOpaque = false;
1848
4
                if (eErr == CE_None && bUseNoDataMask)
1849
3
                {
1850
3
                    eErr = poMaskBand->RasterIO(
1851
3
                        GF_Read, nChunkXOffQueried, nChunkYOffQueried,
1852
3
                        nChunkXSizeQueried, nChunkYSizeQueried,
1853
3
                        pabyChunkNoDataMask, nChunkXSizeQueried,
1854
3
                        nChunkYSizeQueried, GDT_UInt8, 0, 0, nullptr);
1855
1856
                    /* Optimizations if mask if fully opaque or transparent */
1857
3
                    const int nPixels = nChunkXSizeQueried * nChunkYSizeQueried;
1858
3
                    const GByte bVal = pabyChunkNoDataMask[0];
1859
3
                    int i = 1;  // Used after for.
1860
68.1k
                    for (; i < nPixels; i++)
1861
68.1k
                    {
1862
68.1k
                        if (pabyChunkNoDataMask[i] != bVal)
1863
2
                            break;
1864
68.1k
                    }
1865
3
                    if (i == nPixels)
1866
1
                    {
1867
1
                        if (bVal == 0)
1868
0
                        {
1869
0
                            GByte abyZero[16] = {0};
1870
0
                            for (int iBand = 0; iBand < nBandCount; iBand++)
1871
0
                            {
1872
0
                                for (int j = 0; j < nDstYCount; j++)
1873
0
                                {
1874
0
                                    GDALCopyWords64(
1875
0
                                        abyZero, GDT_UInt8, 0,
1876
0
                                        static_cast<GByte *>(pDataMem) +
1877
0
                                            iBand * nBandSpaceMEM +
1878
0
                                            nLSMem * (j + nDstYOff) +
1879
0
                                            nDstXOff * nPSMem,
1880
0
                                        eBufType, static_cast<int>(nPSMem),
1881
0
                                        nDstXCount);
1882
0
                                }
1883
0
                            }
1884
0
                            bSkipResample = true;
1885
0
                        }
1886
1
                        else
1887
1
                        {
1888
1
                            bNoDataMaskFullyOpaque = true;
1889
1
                        }
1890
1
                    }
1891
3
                }
1892
1893
4
                if (!bSkipResample && eErr == CE_None)
1894
2
                {
1895
                    /* Read the source buffers */
1896
2
                    eErr = RasterIO(
1897
2
                        GF_Read, nChunkXOffQueried, nChunkYOffQueried,
1898
2
                        nChunkXSizeQueried, nChunkYSizeQueried, pChunk,
1899
2
                        nChunkXSizeQueried, nChunkYSizeQueried, eWrkDataType,
1900
2
                        nBandCount, panBandMap, 0, 0, 0, nullptr);
1901
2
                }
1902
1903
#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
1904
                if (pfnResampleFuncMultiBands && !bSkipResample &&
1905
                    eErr == CE_None)
1906
                {
1907
                    eErr = pfnResampleFuncMultiBands(
1908
                        dfXRatioDstToSrc, dfYRatioDstToSrc,
1909
                        dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
1910
                        dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
1911
                        eWrkDataType, (GByte *)pChunk, nBandCount,
1912
                        bNoDataMaskFullyOpaque ? nullptr : pabyChunkNoDataMask,
1913
                        nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff),
1914
                        nChunkXSizeQueried,
1915
                        nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff),
1916
                        nChunkYSizeQueried, nDstXOff + nDestXOffVirtual,
1917
                        nDstXOff + nDestXOffVirtual + nDstXCount,
1918
                        nDstYOff + nDestYOffVirtual,
1919
                        nDstYOff + nDestYOffVirtual + nDstYCount,
1920
                        apoDstBands.data(), pszResampling, FALSE /*bHasNoData*/,
1921
                        0.0 /* dfNoDataValue */, nullptr /* color table*/,
1922
                        eDataType);
1923
                }
1924
                else
1925
#endif
1926
4
                {
1927
4
                    size_t nChunkBandOffset =
1928
4
                        static_cast<size_t>(nChunkXSizeQueried) *
1929
4
                        nChunkYSizeQueried *
1930
4
                        GDALGetDataTypeSizeBytes(eWrkDataType);
1931
4
                    for (int i = 0;
1932
9
                         i < nBandCount && !bSkipResample && eErr == CE_None;
1933
5
                         i++)
1934
5
                    {
1935
5
                        const bool bPropagateNoData = false;
1936
5
                        void *pDstBuffer = nullptr;
1937
5
                        GDALDataType eDstBufferDataType = GDT_Unknown;
1938
5
                        GDALRasterBand *poMEMBand =
1939
5
                            poMEMDS->GetRasterBand(i + 1);
1940
5
                        GDALOverviewResampleArgs args;
1941
5
                        args.eSrcDataType = eDataType;
1942
5
                        args.eOvrDataType = poMEMBand->GetRasterDataType();
1943
5
                        args.nOvrXSize = poMEMBand->GetXSize();
1944
5
                        args.nOvrYSize = poMEMBand->GetYSize();
1945
5
                        args.nOvrNBITS = nNBITS;
1946
5
                        args.dfXRatioDstToSrc = dfXRatioDstToSrc;
1947
5
                        args.dfYRatioDstToSrc = dfYRatioDstToSrc;
1948
5
                        args.dfSrcXDelta =
1949
5
                            dfXOff - nXOff; /* == 0 if bHasXOffVirtual */
1950
5
                        args.dfSrcYDelta =
1951
5
                            dfYOff - nYOff; /* == 0 if bHasYOffVirtual */
1952
5
                        args.eWrkDataType = eWrkDataType;
1953
5
                        args.pabyChunkNodataMask = bNoDataMaskFullyOpaque
1954
5
                                                       ? nullptr
1955
5
                                                       : pabyChunkNoDataMask;
1956
5
                        args.nChunkXOff =
1957
5
                            nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff);
1958
5
                        args.nChunkXSize = nChunkXSizeQueried;
1959
5
                        args.nChunkYOff =
1960
5
                            nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff);
1961
5
                        args.nChunkYSize = nChunkYSizeQueried;
1962
5
                        args.nDstXOff = nDstXOff + nDestXOffVirtual;
1963
5
                        args.nDstXOff2 =
1964
5
                            nDstXOff + nDestXOffVirtual + nDstXCount;
1965
5
                        args.nDstYOff = nDstYOff + nDestYOffVirtual;
1966
5
                        args.nDstYOff2 =
1967
5
                            nDstYOff + nDestYOffVirtual + nDstYCount;
1968
5
                        args.pszResampling = pszResampling;
1969
5
                        args.bHasNoData = false;
1970
5
                        args.dfNoDataValue = 0.0;
1971
5
                        args.poColorTable = nullptr;
1972
5
                        args.bPropagateNoData = bPropagateNoData;
1973
1974
5
                        eErr =
1975
5
                            pfnResampleFunc(args,
1976
5
                                            reinterpret_cast<GByte *>(pChunk) +
1977
5
                                                i * nChunkBandOffset,
1978
5
                                            &pDstBuffer, &eDstBufferDataType);
1979
5
                        if (eErr == CE_None)
1980
5
                        {
1981
5
                            eErr = poMEMBand->RasterIO(
1982
5
                                GF_Write, nDstXOff + nDestXOffVirtual,
1983
5
                                nDstYOff + nDestYOffVirtual, nDstXCount,
1984
5
                                nDstYCount, pDstBuffer, nDstXCount, nDstYCount,
1985
5
                                eDstBufferDataType, 0, 0, nullptr);
1986
5
                        }
1987
5
                        CPLFree(pDstBuffer);
1988
5
                    }
1989
4
                }
1990
1991
4
                nBlocksDone++;
1992
4
                if (eErr == CE_None && psExtraArg->pfnProgress != nullptr &&
1993
1
                    !psExtraArg->pfnProgress(
1994
1
                        static_cast<double>(nBlocksDone) /
1995
1
                            static_cast<double>(nTotalBlocks),
1996
1
                        "", psExtraArg->pProgressData))
1997
0
                {
1998
0
                    eErr = CE_Failure;
1999
0
                }
2000
4
            }
2001
4
        }
2002
2003
4
        CPLFree(pChunk);
2004
4
        CPLFree(pabyChunkNoDataMask);
2005
4
    }
2006
2007
4
    if (pTempBuffer)
2008
0
    {
2009
0
        CPL_IGNORE_RET_VAL(poMEMDS->RasterIO(
2010
0
            GF_Read, nDestXOffVirtual, nDestYOffVirtual, nBufXSize, nBufYSize,
2011
0
            pData, nBufXSize, nBufYSize, eBufType, nBandCount, nullptr,
2012
0
            nPixelSpace, nLineSpace, nBandSpace, nullptr));
2013
0
    }
2014
2015
4
    return eErr;
2016
4
}
2017
2018
//! @endcond
2019
2020
/************************************************************************/
2021
/*                           GDALSwapWords()                            */
2022
/************************************************************************/
2023
2024
/**
2025
 * Byte swap words in-place.
2026
 *
2027
 * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
2028
 * a memory array.  No assumption is made that the words being swapped are
2029
 * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
2030
 * to determine if the current platform is big endian or little endian.  Use
2031
 * The macros like CPL_SWAP32() to byte swap single values without the overhead
2032
 * of a function call.
2033
 *
2034
 * @param pData pointer to start of data buffer.
2035
 * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
2036
 * @param nWordCount the number of words to be swapped in this call.
2037
 * @param nWordSkip the byte offset from the start of one word to the start of
2038
 * the next. For packed buffers this is the same as nWordSize.
2039
 */
2040
2041
void CPL_STDCALL GDALSwapWords(void *pData, int nWordSize, int nWordCount,
2042
                               int nWordSkip)
2043
2044
961k
{
2045
961k
    if (nWordCount > 0)
2046
961k
        VALIDATE_POINTER0(pData, "GDALSwapWords");
2047
2048
961k
    GByte *pabyData = static_cast<GByte *>(pData);
2049
2050
961k
    switch (nWordSize)
2051
961k
    {
2052
6.77k
        case 1:
2053
6.77k
            break;
2054
2055
825k
        case 2:
2056
825k
            CPLAssert(nWordSkip >= 2 || nWordCount == 1);
2057
14.8M
            for (int i = 0; i < nWordCount; i++)
2058
14.0M
            {
2059
14.0M
                CPL_SWAP16PTR(pabyData);
2060
14.0M
                pabyData += nWordSkip;
2061
14.0M
            }
2062
825k
            break;
2063
2064
85.5k
        case 4:
2065
85.5k
            CPLAssert(nWordSkip >= 4 || nWordCount == 1);
2066
85.5k
            if (CPL_IS_ALIGNED(pabyData, 4) && (nWordSkip % 4) == 0)
2067
85.5k
            {
2068
1.50M
                for (int i = 0; i < nWordCount; i++)
2069
1.41M
                {
2070
1.41M
                    *reinterpret_cast<GUInt32 *>(pabyData) = CPL_SWAP32(
2071
1.41M
                        *reinterpret_cast<const GUInt32 *>(pabyData));
2072
1.41M
                    pabyData += nWordSkip;
2073
1.41M
                }
2074
85.5k
            }
2075
0
            else
2076
0
            {
2077
0
                for (int i = 0; i < nWordCount; i++)
2078
0
                {
2079
0
                    CPL_SWAP32PTR(pabyData);
2080
0
                    pabyData += nWordSkip;
2081
0
                }
2082
0
            }
2083
85.5k
            break;
2084
2085
42.8k
        case 8:
2086
42.8k
            CPLAssert(nWordSkip >= 8 || nWordCount == 1);
2087
42.8k
            if (CPL_IS_ALIGNED(pabyData, 8) && (nWordSkip % 8) == 0)
2088
42.8k
            {
2089
349k
                for (int i = 0; i < nWordCount; i++)
2090
306k
                {
2091
306k
                    *reinterpret_cast<GUInt64 *>(pabyData) = CPL_SWAP64(
2092
306k
                        *reinterpret_cast<const GUInt64 *>(pabyData));
2093
306k
                    pabyData += nWordSkip;
2094
306k
                }
2095
42.8k
            }
2096
0
            else
2097
0
            {
2098
0
                for (int i = 0; i < nWordCount; i++)
2099
0
                {
2100
0
                    CPL_SWAP64PTR(pabyData);
2101
0
                    pabyData += nWordSkip;
2102
0
                }
2103
0
            }
2104
42.8k
            break;
2105
2106
0
        default:
2107
0
            CPLAssert(false);
2108
961k
    }
2109
961k
}
2110
2111
/************************************************************************/
2112
/*                          GDALSwapWordsEx()                           */
2113
/************************************************************************/
2114
2115
/**
2116
 * Byte swap words in-place.
2117
 *
2118
 * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
2119
 * a memory array.  No assumption is made that the words being swapped are
2120
 * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
2121
 * to determine if the current platform is big endian or little endian.  Use
2122
 * The macros like CPL_SWAP32() to byte swap single values without the overhead
2123
 * of a function call.
2124
 *
2125
 * @param pData pointer to start of data buffer.
2126
 * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
2127
 * @param nWordCount the number of words to be swapped in this call.
2128
 * @param nWordSkip the byte offset from the start of one word to the start of
2129
 * the next. For packed buffers this is the same as nWordSize.
2130
 */
2131
void CPL_STDCALL GDALSwapWordsEx(void *pData, int nWordSize, size_t nWordCount,
2132
                                 int nWordSkip)
2133
946k
{
2134
946k
    GByte *pabyData = static_cast<GByte *>(pData);
2135
1.89M
    while (nWordCount)
2136
946k
    {
2137
        // Pick-up a multiple of 8 as max chunk size.
2138
946k
        const int nWordCountSmall =
2139
946k
            (nWordCount > (1 << 30)) ? (1 << 30) : static_cast<int>(nWordCount);
2140
946k
        GDALSwapWords(pabyData, nWordSize, nWordCountSmall, nWordSkip);
2141
946k
        pabyData += static_cast<size_t>(nWordSkip) * nWordCountSmall;
2142
946k
        nWordCount -= nWordCountSmall;
2143
946k
    }
2144
946k
}
2145
2146
// Place the new GDALCopyWords helpers in an anonymous namespace
2147
namespace
2148
{
2149
2150
/************************************************************************/
2151
/*                           GDALCopyWordsT()                           */
2152
/************************************************************************/
2153
/**
2154
 * Template function, used to copy data from pSrcData into buffer
2155
 * pDstData, with stride nSrcPixelStride in the source data and
2156
 * stride nDstPixelStride in the destination data. This template can
2157
 * deal with the case where the input data type is real or complex and
2158
 * the output is real.
2159
 *
2160
 * @param pSrcData the source data buffer
2161
 * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
2162
 *                      of interest.
2163
 * @param pDstData the destination buffer.
2164
 * @param nDstPixelStride the stride in the buffer pDstData for pixels of
2165
 *                      interest.
2166
 * @param nWordCount the total number of pixel words to copy
2167
 *
2168
 * @code
2169
 * // Assume an input buffer of type GUInt16 named pBufferIn
2170
 * GByte *pBufferOut = new GByte[numBytesOut];
2171
 * GDALCopyWordsT<GUInt16, GByte>(pSrcData, 2, pDstData, 1, numBytesOut);
2172
 * @endcode
2173
 * @note
2174
 * This is a private function, and should not be exposed outside of
2175
 * rasterio.cpp. External users should call the GDALCopyWords driver function.
2176
 */
2177
2178
template <class Tin, class Tout>
2179
static void inline GDALCopyWordsGenericT(const Tin *const CPL_RESTRICT pSrcData,
2180
                                         int nSrcPixelStride,
2181
                                         Tout *const CPL_RESTRICT pDstData,
2182
                                         int nDstPixelStride,
2183
                                         GPtrDiff_t nWordCount)
2184
24.8M
{
2185
24.8M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
24.8M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
24.8M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
531M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
506M
    {
2191
506M
        const Tin tValue =
2192
506M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
506M
        Tout *const pOutPixel =
2194
506M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
506M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
506M
        nDstOffset += nDstPixelStride;
2199
506M
    }
2200
24.8M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, unsigned char>(unsigned char const*, int, unsigned char*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, signed char>(unsigned char const*, int, signed char*, int, long long)
Line
Count
Source
2184
22
{
2185
22
    decltype(nWordCount) nDstOffset = 0;
2186
2187
22
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
22
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
44
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
22
    {
2191
22
        const Tin tValue =
2192
22
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
22
        Tout *const pOutPixel =
2194
22
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
22
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
22
        nDstOffset += nDstPixelStride;
2199
22
    }
2200
22
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, unsigned short>(unsigned char const*, int, unsigned short*, int, long long)
Line
Count
Source
2184
79.5k
{
2185
79.5k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
79.5k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
79.5k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
159k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
79.5k
    {
2191
79.5k
        const Tin tValue =
2192
79.5k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
79.5k
        Tout *const pOutPixel =
2194
79.5k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
79.5k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
79.5k
        nDstOffset += nDstPixelStride;
2199
79.5k
    }
2200
79.5k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, short>(unsigned char const*, int, short*, int, long long)
Line
Count
Source
2184
322k
{
2185
322k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
322k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
322k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
645k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
322k
    {
2191
322k
        const Tin tValue =
2192
322k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
322k
        Tout *const pOutPixel =
2194
322k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
322k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
322k
        nDstOffset += nDstPixelStride;
2199
322k
    }
2200
322k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, unsigned int>(unsigned char const*, int, unsigned int*, int, long long)
Line
Count
Source
2184
3.33k
{
2185
3.33k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
3.33k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
3.33k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
6.66k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
3.33k
    {
2191
3.33k
        const Tin tValue =
2192
3.33k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
3.33k
        Tout *const pOutPixel =
2194
3.33k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
3.33k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
3.33k
        nDstOffset += nDstPixelStride;
2199
3.33k
    }
2200
3.33k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, int>(unsigned char const*, int, int*, int, long long)
Line
Count
Source
2184
215k
{
2185
215k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
215k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
215k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
9.90M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
9.69M
    {
2191
9.69M
        const Tin tValue =
2192
9.69M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
9.69M
        Tout *const pOutPixel =
2194
9.69M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
9.69M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
9.69M
        nDstOffset += nDstPixelStride;
2199
9.69M
    }
2200
215k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, unsigned long>(unsigned char const*, int, unsigned long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, long>(unsigned char const*, int, long*, int, long long)
Line
Count
Source
2184
4.50k
{
2185
4.50k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
4.50k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
4.50k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
9.00k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
4.50k
    {
2191
4.50k
        const Tin tValue =
2192
4.50k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
4.50k
        Tout *const pOutPixel =
2194
4.50k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
4.50k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
4.50k
        nDstOffset += nDstPixelStride;
2199
4.50k
    }
2200
4.50k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, cpl::Float16>(unsigned char const*, int, cpl::Float16*, int, long long)
Line
Count
Source
2184
1.35k
{
2185
1.35k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
1.35k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
1.35k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
2.70k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
1.35k
    {
2191
1.35k
        const Tin tValue =
2192
1.35k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
1.35k
        Tout *const pOutPixel =
2194
1.35k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
1.35k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
1.35k
        nDstOffset += nDstPixelStride;
2199
1.35k
    }
2200
1.35k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, float>(unsigned char const*, int, float*, int, long long)
Line
Count
Source
2184
3.91M
{
2185
3.91M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
3.91M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
3.91M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
7.87M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
3.96M
    {
2191
3.96M
        const Tin tValue =
2192
3.96M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
3.96M
        Tout *const pOutPixel =
2194
3.96M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
3.96M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
3.96M
        nDstOffset += nDstPixelStride;
2199
3.96M
    }
2200
3.91M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned char, double>(unsigned char const*, int, double*, int, long long)
Line
Count
Source
2184
122k
{
2185
122k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
122k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
122k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
245k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
122k
    {
2191
122k
        const Tin tValue =
2192
122k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
122k
        Tout *const pOutPixel =
2194
122k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
122k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
122k
        nDstOffset += nDstPixelStride;
2199
122k
    }
2200
122k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, unsigned char>(signed char const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
14.7k
{
2185
14.7k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
14.7k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
14.7k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
46.3k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
31.6k
    {
2191
31.6k
        const Tin tValue =
2192
31.6k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
31.6k
        Tout *const pOutPixel =
2194
31.6k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
31.6k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
31.6k
        nDstOffset += nDstPixelStride;
2199
31.6k
    }
2200
14.7k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, signed char>(signed char const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, unsigned short>(signed char const*, int, unsigned short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, short>(signed char const*, int, short*, int, long long)
Line
Count
Source
2184
299k
{
2185
299k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
299k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
299k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
963k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
664k
    {
2191
664k
        const Tin tValue =
2192
664k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
664k
        Tout *const pOutPixel =
2194
664k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
664k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
664k
        nDstOffset += nDstPixelStride;
2199
664k
    }
2200
299k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, unsigned int>(signed char const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, int>(signed char const*, int, int*, int, long long)
Line
Count
Source
2184
5.45M
{
2185
5.45M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
5.45M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
5.45M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
61.5M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
56.1M
    {
2191
56.1M
        const Tin tValue =
2192
56.1M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
56.1M
        Tout *const pOutPixel =
2194
56.1M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
56.1M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
56.1M
        nDstOffset += nDstPixelStride;
2199
56.1M
    }
2200
5.45M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, unsigned long>(signed char const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, long>(signed char const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, cpl::Float16>(signed char const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, float>(signed char const*, int, float*, int, long long)
Line
Count
Source
2184
165k
{
2185
165k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
165k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
165k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
891k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
725k
    {
2191
725k
        const Tin tValue =
2192
725k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
725k
        Tout *const pOutPixel =
2194
725k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
725k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
725k
        nDstOffset += nDstPixelStride;
2199
725k
    }
2200
165k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<signed char, double>(signed char const*, int, double*, int, long long)
Line
Count
Source
2184
4.59k
{
2185
4.59k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
4.59k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
4.59k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
621k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
616k
    {
2191
616k
        const Tin tValue =
2192
616k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
616k
        Tout *const pOutPixel =
2194
616k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
616k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
616k
        nDstOffset += nDstPixelStride;
2199
616k
    }
2200
4.59k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, unsigned char>(unsigned short const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
228k
{
2185
228k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
228k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
228k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
465k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
237k
    {
2191
237k
        const Tin tValue =
2192
237k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
237k
        Tout *const pOutPixel =
2194
237k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
237k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
237k
        nDstOffset += nDstPixelStride;
2199
237k
    }
2200
228k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, signed char>(unsigned short const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, unsigned short>(unsigned short const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, short>(unsigned short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, unsigned int>(unsigned short const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, int>(unsigned short const*, int, int*, int, long long)
Line
Count
Source
2184
2.36M
{
2185
2.36M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2.36M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2.36M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
314M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
312M
    {
2191
312M
        const Tin tValue =
2192
312M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
312M
        Tout *const pOutPixel =
2194
312M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
312M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
312M
        nDstOffset += nDstPixelStride;
2199
312M
    }
2200
2.36M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, unsigned long>(unsigned short const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, long>(unsigned short const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, cpl::Float16>(unsigned short const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, float>(unsigned short const*, int, float*, int, long long)
Line
Count
Source
2184
2.74M
{
2185
2.74M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2.74M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2.74M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
5.56M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
2.81M
    {
2191
2.81M
        const Tin tValue =
2192
2.81M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
2.81M
        Tout *const pOutPixel =
2194
2.81M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
2.81M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
2.81M
        nDstOffset += nDstPixelStride;
2199
2.81M
    }
2200
2.74M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned short, double>(unsigned short const*, int, double*, int, long long)
Line
Count
Source
2184
206k
{
2185
206k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
206k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
206k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
7.42M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
7.21M
    {
2191
7.21M
        const Tin tValue =
2192
7.21M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
7.21M
        Tout *const pOutPixel =
2194
7.21M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
7.21M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
7.21M
        nDstOffset += nDstPixelStride;
2199
7.21M
    }
2200
206k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, unsigned char>(short const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
2.06k
{
2185
2.06k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2.06k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2.06k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
4.13k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
2.06k
    {
2191
2.06k
        const Tin tValue =
2192
2.06k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
2.06k
        Tout *const pOutPixel =
2194
2.06k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
2.06k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
2.06k
        nDstOffset += nDstPixelStride;
2199
2.06k
    }
2200
2.06k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, signed char>(short const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, unsigned short>(short const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, short>(short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, unsigned int>(short const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, int>(short const*, int, int*, int, long long)
Line
Count
Source
2184
3.09M
{
2185
3.09M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
3.09M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
3.09M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
67.1M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
64.0M
    {
2191
64.0M
        const Tin tValue =
2192
64.0M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
64.0M
        Tout *const pOutPixel =
2194
64.0M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
64.0M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
64.0M
        nDstOffset += nDstPixelStride;
2199
64.0M
    }
2200
3.09M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, unsigned long>(short const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, long>(short const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, cpl::Float16>(short const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, float>(short const*, int, float*, int, long long)
Line
Count
Source
2184
361k
{
2185
361k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
361k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
361k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
724k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
363k
    {
2191
363k
        const Tin tValue =
2192
363k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
363k
        Tout *const pOutPixel =
2194
363k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
363k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
363k
        nDstOffset += nDstPixelStride;
2199
363k
    }
2200
361k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<short, double>(short const*, int, double*, int, long long)
Line
Count
Source
2184
2
{
2185
2
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
4
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
2
    {
2191
2
        const Tin tValue =
2192
2
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
2
        Tout *const pOutPixel =
2194
2
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
2
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
2
        nDstOffset += nDstPixelStride;
2199
2
    }
2200
2
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, unsigned char>(unsigned int const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
3.43k
{
2185
3.43k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
3.43k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
3.43k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
6.87k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
3.43k
    {
2191
3.43k
        const Tin tValue =
2192
3.43k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
3.43k
        Tout *const pOutPixel =
2194
3.43k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
3.43k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
3.43k
        nDstOffset += nDstPixelStride;
2199
3.43k
    }
2200
3.43k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, signed char>(unsigned int const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, unsigned short>(unsigned int const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, short>(unsigned int const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, unsigned int>(unsigned int const*, int, unsigned int*, int, long long)
Line
Count
Source
2184
60.5k
{
2185
60.5k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
60.5k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
60.5k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
7.88M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
7.82M
    {
2191
7.82M
        const Tin tValue =
2192
7.82M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
7.82M
        Tout *const pOutPixel =
2194
7.82M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
7.82M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
7.82M
        nDstOffset += nDstPixelStride;
2199
7.82M
    }
2200
60.5k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, int>(unsigned int const*, int, int*, int, long long)
Line
Count
Source
2184
34.2k
{
2185
34.2k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
34.2k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
34.2k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
270k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
235k
    {
2191
235k
        const Tin tValue =
2192
235k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
235k
        Tout *const pOutPixel =
2194
235k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
235k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
235k
        nDstOffset += nDstPixelStride;
2199
235k
    }
2200
34.2k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, unsigned long>(unsigned int const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, long>(unsigned int const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, cpl::Float16>(unsigned int const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, float>(unsigned int const*, int, float*, int, long long)
Line
Count
Source
2184
19.9k
{
2185
19.9k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
19.9k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
19.9k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
59.9k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
39.9k
    {
2191
39.9k
        const Tin tValue =
2192
39.9k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
39.9k
        Tout *const pOutPixel =
2194
39.9k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
39.9k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
39.9k
        nDstOffset += nDstPixelStride;
2199
39.9k
    }
2200
19.9k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned int, double>(unsigned int const*, int, double*, int, long long)
Line
Count
Source
2184
14.1k
{
2185
14.1k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
14.1k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
14.1k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
273k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
259k
    {
2191
259k
        const Tin tValue =
2192
259k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
259k
        Tout *const pOutPixel =
2194
259k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
259k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
259k
        nDstOffset += nDstPixelStride;
2199
259k
    }
2200
14.1k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, unsigned char>(int const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
2.30k
{
2185
2.30k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2.30k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2.30k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
41.4k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
39.1k
    {
2191
39.1k
        const Tin tValue =
2192
39.1k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
39.1k
        Tout *const pOutPixel =
2194
39.1k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
39.1k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
39.1k
        nDstOffset += nDstPixelStride;
2199
39.1k
    }
2200
2.30k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, signed char>(int const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, unsigned short>(int const*, int, unsigned short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, short>(int const*, int, short*, int, long long)
Line
Count
Source
2184
313
{
2185
313
    decltype(nWordCount) nDstOffset = 0;
2186
2187
313
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
313
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
626
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
313
    {
2191
313
        const Tin tValue =
2192
313
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
313
        Tout *const pOutPixel =
2194
313
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
313
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
313
        nDstOffset += nDstPixelStride;
2199
313
    }
2200
313
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, unsigned int>(int const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, int>(int const*, int, int*, int, long long)
Line
Count
Source
2184
81.5k
{
2185
81.5k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
81.5k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
81.5k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
2.13M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
2.05M
    {
2191
2.05M
        const Tin tValue =
2192
2.05M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
2.05M
        Tout *const pOutPixel =
2194
2.05M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
2.05M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
2.05M
        nDstOffset += nDstPixelStride;
2199
2.05M
    }
2200
81.5k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, unsigned long>(int const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, long>(int const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, cpl::Float16>(int const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, float>(int const*, int, float*, int, long long)
Line
Count
Source
2184
1.45k
{
2185
1.45k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
1.45k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
1.45k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
2.90k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
1.45k
    {
2191
1.45k
        const Tin tValue =
2192
1.45k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
1.45k
        Tout *const pOutPixel =
2194
1.45k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
1.45k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
1.45k
        nDstOffset += nDstPixelStride;
2199
1.45k
    }
2200
1.45k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<int, double>(int const*, int, double*, int, long long)
Line
Count
Source
2184
288k
{
2185
288k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
288k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
288k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
747k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
458k
    {
2191
458k
        const Tin tValue =
2192
458k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
458k
        Tout *const pOutPixel =
2194
458k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
458k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
458k
        nDstOffset += nDstPixelStride;
2199
458k
    }
2200
288k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, unsigned char>(unsigned long const*, int, unsigned char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, signed char>(unsigned long const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, unsigned short>(unsigned long const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, short>(unsigned long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, unsigned int>(unsigned long const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, int>(unsigned long const*, int, int*, int, long long)
Line
Count
Source
2184
197k
{
2185
197k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
197k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
197k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
8.61M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
8.41M
    {
2191
8.41M
        const Tin tValue =
2192
8.41M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
8.41M
        Tout *const pOutPixel =
2194
8.41M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
8.41M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
8.41M
        nDstOffset += nDstPixelStride;
2199
8.41M
    }
2200
197k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, unsigned long>(unsigned long const*, int, unsigned long*, int, long long)
Line
Count
Source
2184
60.0k
{
2185
60.0k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
60.0k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
60.0k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
745k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
685k
    {
2191
685k
        const Tin tValue =
2192
685k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
685k
        Tout *const pOutPixel =
2194
685k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
685k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
685k
        nDstOffset += nDstPixelStride;
2199
685k
    }
2200
60.0k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, long>(unsigned long const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, cpl::Float16>(unsigned long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, float>(unsigned long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<unsigned long, double>(unsigned long const*, int, double*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, unsigned char>(long const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
3.46k
{
2185
3.46k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
3.46k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
3.46k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
19.1k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
15.7k
    {
2191
15.7k
        const Tin tValue =
2192
15.7k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
15.7k
        Tout *const pOutPixel =
2194
15.7k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
15.7k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
15.7k
        nDstOffset += nDstPixelStride;
2199
15.7k
    }
2200
3.46k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, signed char>(long const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, unsigned short>(long const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, short>(long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, unsigned int>(long const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, int>(long const*, int, int*, int, long long)
Line
Count
Source
2184
140k
{
2185
140k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
140k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
140k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
16.2M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
16.1M
    {
2191
16.1M
        const Tin tValue =
2192
16.1M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
16.1M
        Tout *const pOutPixel =
2194
16.1M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
16.1M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
16.1M
        nDstOffset += nDstPixelStride;
2199
16.1M
    }
2200
140k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, unsigned long>(long const*, int, unsigned long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, long>(long const*, int, long*, int, long long)
Line
Count
Source
2184
31.8k
{
2185
31.8k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
31.8k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
31.8k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
1.04M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
1.01M
    {
2191
1.01M
        const Tin tValue =
2192
1.01M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
1.01M
        Tout *const pOutPixel =
2194
1.01M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
1.01M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
1.01M
        nDstOffset += nDstPixelStride;
2199
1.01M
    }
2200
31.8k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, cpl::Float16>(long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, float>(long const*, int, float*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<long, double>(long const*, int, double*, int, long long)
Line
Count
Source
2184
192k
{
2185
192k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
192k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
192k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
408k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
216k
    {
2191
216k
        const Tin tValue =
2192
216k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
216k
        Tout *const pOutPixel =
2194
216k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
216k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
216k
        nDstOffset += nDstPixelStride;
2199
216k
    }
2200
192k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, unsigned char>(cpl::Float16 const*, int, unsigned char*, int, long long)
Line
Count
Source
2184
18.9k
{
2185
18.9k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
18.9k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
18.9k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
37.9k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
18.9k
    {
2191
18.9k
        const Tin tValue =
2192
18.9k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
18.9k
        Tout *const pOutPixel =
2194
18.9k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
18.9k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
18.9k
        nDstOffset += nDstPixelStride;
2199
18.9k
    }
2200
18.9k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, signed char>(cpl::Float16 const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, unsigned short>(cpl::Float16 const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, short>(cpl::Float16 const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, unsigned int>(cpl::Float16 const*, int, unsigned int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, int>(cpl::Float16 const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, unsigned long>(cpl::Float16 const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, long>(cpl::Float16 const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<cpl::Float16, cpl::Float16>(cpl::Float16 const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<float, unsigned int>(float const*, int, unsigned int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<float, unsigned long>(float const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<float, long>(float const*, int, long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<float, float>(float const*, int, float*, int, long long)
Line
Count
Source
2184
20.5k
{
2185
20.5k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
20.5k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
20.5k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
3.28M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
3.26M
    {
2191
3.26M
        const Tin tValue =
2192
3.26M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
3.26M
        Tout *const pOutPixel =
2194
3.26M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
3.26M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
3.26M
        nDstOffset += nDstPixelStride;
2199
3.26M
    }
2200
20.5k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, signed char>(double const*, int, signed char*, int, long long)
Line
Count
Source
2184
193k
{
2185
193k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
193k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
193k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
1.20M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
1.00M
    {
2191
1.00M
        const Tin tValue =
2192
1.00M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
1.00M
        Tout *const pOutPixel =
2194
1.00M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
1.00M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
1.00M
        nDstOffset += nDstPixelStride;
2199
1.00M
    }
2200
193k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, short>(double const*, int, short*, int, long long)
Line
Count
Source
2184
139k
{
2185
139k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
139k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
139k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
287k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
148k
    {
2191
148k
        const Tin tValue =
2192
148k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
148k
        Tout *const pOutPixel =
2194
148k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
148k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
148k
        nDstOffset += nDstPixelStride;
2199
148k
    }
2200
139k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, unsigned int>(double const*, int, unsigned int*, int, long long)
Line
Count
Source
2184
2.58M
{
2185
2.58M
    decltype(nWordCount) nDstOffset = 0;
2186
2187
2.58M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
2.58M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
5.17M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
2.59M
    {
2191
2.59M
        const Tin tValue =
2192
2.59M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
2.59M
        Tout *const pOutPixel =
2194
2.59M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
2.59M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
2.59M
        nDstOffset += nDstPixelStride;
2199
2.59M
    }
2200
2.58M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, int>(double const*, int, int*, int, long long)
Line
Count
Source
2184
634k
{
2185
634k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
634k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
634k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
1.43M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
805k
    {
2191
805k
        const Tin tValue =
2192
805k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
805k
        Tout *const pOutPixel =
2194
805k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
805k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
805k
        nDstOffset += nDstPixelStride;
2199
805k
    }
2200
634k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, unsigned long>(double const*, int, unsigned long*, int, long long)
Line
Count
Source
2184
342k
{
2185
342k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
342k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
342k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
684k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
342k
    {
2191
342k
        const Tin tValue =
2192
342k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
342k
        Tout *const pOutPixel =
2194
342k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
342k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
342k
        nDstOffset += nDstPixelStride;
2199
342k
    }
2200
342k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, long>(double const*, int, long*, int, long long)
Line
Count
Source
2184
34.7k
{
2185
34.7k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
34.7k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
34.7k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
73.1k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
38.3k
    {
2191
38.3k
        const Tin tValue =
2192
38.3k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
38.3k
        Tout *const pOutPixel =
2194
38.3k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
38.3k
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
38.3k
        nDstOffset += nDstPixelStride;
2199
38.3k
    }
2200
34.7k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsGenericT<double, double>(double const*, int, double*, int, long long)
Line
Count
Source
2184
146k
{
2185
146k
    decltype(nWordCount) nDstOffset = 0;
2186
2187
146k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2188
146k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2189
1.66M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
2190
1.51M
    {
2191
1.51M
        const Tin tValue =
2192
1.51M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2193
1.51M
        Tout *const pOutPixel =
2194
1.51M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2195
2196
1.51M
        GDALCopyWord(tValue, *pOutPixel);
2197
2198
1.51M
        nDstOffset += nDstPixelStride;
2199
1.51M
    }
2200
146k
}
2201
2202
template <class Tin, class Tout>
2203
static void CPL_NOINLINE GDALCopyWordsT(const Tin *const CPL_RESTRICT pSrcData,
2204
                                        int nSrcPixelStride,
2205
                                        Tout *const CPL_RESTRICT pDstData,
2206
                                        int nDstPixelStride,
2207
                                        GPtrDiff_t nWordCount)
2208
16.6M
{
2209
16.6M
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
16.6M
                          nWordCount);
2211
16.6M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned char, unsigned char>(unsigned char const*, int, unsigned char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned char, unsigned long>(unsigned char const*, int, unsigned long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned char, long>(unsigned char const*, int, long*, int, long long)
Line
Count
Source
2208
4.50k
{
2209
4.50k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
4.50k
                          nWordCount);
2211
4.50k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned char, cpl::Float16>(unsigned char const*, int, cpl::Float16*, int, long long)
Line
Count
Source
2208
1.35k
{
2209
1.35k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
1.35k
                          nWordCount);
2211
1.35k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, signed char>(signed char const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, unsigned short>(signed char const*, int, unsigned short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, short>(signed char const*, int, short*, int, long long)
Line
Count
Source
2208
299k
{
2209
299k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
299k
                          nWordCount);
2211
299k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, unsigned int>(signed char const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, int>(signed char const*, int, int*, int, long long)
Line
Count
Source
2208
5.45M
{
2209
5.45M
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
5.45M
                          nWordCount);
2211
5.45M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, unsigned long>(signed char const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, long>(signed char const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, cpl::Float16>(signed char const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, float>(signed char const*, int, float*, int, long long)
Line
Count
Source
2208
165k
{
2209
165k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
165k
                          nWordCount);
2211
165k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<signed char, double>(signed char const*, int, double*, int, long long)
Line
Count
Source
2208
4.59k
{
2209
4.59k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
4.59k
                          nWordCount);
2211
4.59k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, signed char>(unsigned short const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, unsigned short>(unsigned short const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, unsigned int>(unsigned short const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, int>(unsigned short const*, int, int*, int, long long)
Line
Count
Source
2208
2.36M
{
2209
2.36M
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
2.36M
                          nWordCount);
2211
2.36M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, unsigned long>(unsigned short const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, long>(unsigned short const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned short, cpl::Float16>(unsigned short const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, signed char>(short const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, short>(short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, unsigned int>(short const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, int>(short const*, int, int*, int, long long)
Line
Count
Source
2208
3.09M
{
2209
3.09M
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
3.09M
                          nWordCount);
2211
3.09M
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, unsigned long>(short const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, long>(short const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<short, cpl::Float16>(short const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, unsigned char>(unsigned int const*, int, unsigned char*, int, long long)
Line
Count
Source
2208
3.43k
{
2209
3.43k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
3.43k
                          nWordCount);
2211
3.43k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, signed char>(unsigned int const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, unsigned short>(unsigned int const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, short>(unsigned int const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, unsigned int>(unsigned int const*, int, unsigned int*, int, long long)
Line
Count
Source
2208
60.5k
{
2209
60.5k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
60.5k
                          nWordCount);
2211
60.5k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, unsigned long>(unsigned int const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, long>(unsigned int const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, cpl::Float16>(unsigned int const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, float>(unsigned int const*, int, float*, int, long long)
Line
Count
Source
2208
19.9k
{
2209
19.9k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
19.9k
                          nWordCount);
2211
19.9k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned int, double>(unsigned int const*, int, double*, int, long long)
Line
Count
Source
2208
14.1k
{
2209
14.1k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
14.1k
                          nWordCount);
2211
14.1k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, signed char>(int const*, int, signed char*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, int>(int const*, int, int*, int, long long)
Line
Count
Source
2208
81.5k
{
2209
81.5k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
81.5k
                          nWordCount);
2211
81.5k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, unsigned long>(int const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, long>(int const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, cpl::Float16>(int const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, float>(int const*, int, float*, int, long long)
Line
Count
Source
2208
1.45k
{
2209
1.45k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
1.45k
                          nWordCount);
2211
1.45k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<int, double>(int const*, int, double*, int, long long)
Line
Count
Source
2208
288k
{
2209
288k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
288k
                          nWordCount);
2211
288k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, unsigned char>(unsigned long const*, int, unsigned char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, signed char>(unsigned long const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, unsigned short>(unsigned long const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, short>(unsigned long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, unsigned int>(unsigned long const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, int>(unsigned long const*, int, int*, int, long long)
Line
Count
Source
2208
197k
{
2209
197k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
197k
                          nWordCount);
2211
197k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, unsigned long>(unsigned long const*, int, unsigned long*, int, long long)
Line
Count
Source
2208
60.0k
{
2209
60.0k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
60.0k
                          nWordCount);
2211
60.0k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, long>(unsigned long const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, cpl::Float16>(unsigned long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, float>(unsigned long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<unsigned long, double>(unsigned long const*, int, double*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, unsigned char>(long const*, int, unsigned char*, int, long long)
Line
Count
Source
2208
3.46k
{
2209
3.46k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
3.46k
                          nWordCount);
2211
3.46k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, signed char>(long const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, unsigned short>(long const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, short>(long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, unsigned int>(long const*, int, unsigned int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, int>(long const*, int, int*, int, long long)
Line
Count
Source
2208
140k
{
2209
140k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
140k
                          nWordCount);
2211
140k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, unsigned long>(long const*, int, unsigned long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, long>(long const*, int, long*, int, long long)
Line
Count
Source
2208
31.8k
{
2209
31.8k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
31.8k
                          nWordCount);
2211
31.8k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, cpl::Float16>(long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, float>(long const*, int, float*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<long, double>(long const*, int, double*, int, long long)
Line
Count
Source
2208
192k
{
2209
192k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
192k
                          nWordCount);
2211
192k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, unsigned char>(cpl::Float16 const*, int, unsigned char*, int, long long)
Line
Count
Source
2208
18.9k
{
2209
18.9k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
18.9k
                          nWordCount);
2211
18.9k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, signed char>(cpl::Float16 const*, int, signed char*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, unsigned short>(cpl::Float16 const*, int, unsigned short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, short>(cpl::Float16 const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, unsigned int>(cpl::Float16 const*, int, unsigned int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, int>(cpl::Float16 const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, unsigned long>(cpl::Float16 const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, long>(cpl::Float16 const*, int, long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<cpl::Float16, cpl::Float16>(cpl::Float16 const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<float, unsigned int>(float const*, int, unsigned int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<float, unsigned long>(float const*, int, unsigned long*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<float, long>(float const*, int, long*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<float, float>(float const*, int, float*, int, long long)
Line
Count
Source
2208
20.5k
{
2209
20.5k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
20.5k
                          nWordCount);
2211
20.5k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, signed char>(double const*, int, signed char*, int, long long)
Line
Count
Source
2208
193k
{
2209
193k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
193k
                          nWordCount);
2211
193k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, short>(double const*, int, short*, int, long long)
Line
Count
Source
2208
139k
{
2209
139k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
139k
                          nWordCount);
2211
139k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, unsigned int>(double const*, int, unsigned int*, int, long long)
Line
Count
Source
2208
2.58M
{
2209
2.58M
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
2.58M
                          nWordCount);
2211
2.58M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, int>(double const*, int, int*, int, long long)
Line
Count
Source
2208
634k
{
2209
634k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
634k
                          nWordCount);
2211
634k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, unsigned long>(double const*, int, unsigned long*, int, long long)
Line
Count
Source
2208
342k
{
2209
342k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
342k
                          nWordCount);
2211
342k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, long>(double const*, int, long*, int, long long)
Line
Count
Source
2208
34.7k
{
2209
34.7k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
34.7k
                          nWordCount);
2211
34.7k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT<double, double>(double const*, int, double*, int, long long)
Line
Count
Source
2208
146k
{
2209
146k
    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData, nDstPixelStride,
2210
146k
                          nWordCount);
2211
146k
}
2212
2213
template <class Tin, class Tout>
2214
static void inline GDALCopyWordsT_8atatime(
2215
    const Tin *const CPL_RESTRICT pSrcData, int nSrcPixelStride,
2216
    Tout *const CPL_RESTRICT pDstData, int nDstPixelStride,
2217
    GPtrDiff_t nWordCount)
2218
55.8M
{
2219
55.8M
    decltype(nWordCount) nDstOffset = 0;
2220
2221
55.8M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
55.8M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
55.8M
    decltype(nWordCount) n = 0;
2224
55.8M
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
25.0M
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
25.0M
    {
2227
40.0M
        for (; n < nWordCount - 7; n += 8)
2228
15.0M
        {
2229
15.0M
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
15.0M
                pSrcDataPtr + (n * nSrcPixelStride));
2231
15.0M
            Tout *const pOutPixels =
2232
15.0M
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
15.0M
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
15.0M
            nDstOffset += 8 * nDstPixelStride;
2237
15.0M
        }
2238
25.0M
    }
2239
178M
    for (; n < nWordCount; n++)
2240
122M
    {
2241
122M
        const Tin tValue =
2242
122M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
122M
        Tout *const pOutPixel =
2244
122M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
122M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
122M
        nDstOffset += nDstPixelStride;
2249
122M
    }
2250
55.8M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<cpl::Float16, float>(cpl::Float16 const*, int, float*, int, long long)
Line
Count
Source
2218
1.58M
{
2219
1.58M
    decltype(nWordCount) nDstOffset = 0;
2220
2221
1.58M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
1.58M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
1.58M
    decltype(nWordCount) n = 0;
2224
1.58M
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
17.4k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
17.4k
    {
2227
17.4k
        for (; n < nWordCount - 7; n += 8)
2228
0
        {
2229
0
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
0
                pSrcDataPtr + (n * nSrcPixelStride));
2231
0
            Tout *const pOutPixels =
2232
0
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
0
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
0
            nDstOffset += 8 * nDstPixelStride;
2237
0
        }
2238
17.4k
    }
2239
3.17M
    for (; n < nWordCount; n++)
2240
1.58M
    {
2241
1.58M
        const Tin tValue =
2242
1.58M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
1.58M
        Tout *const pOutPixel =
2244
1.58M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
1.58M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
1.58M
        nDstOffset += nDstPixelStride;
2249
1.58M
    }
2250
1.58M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<cpl::Float16, double>(cpl::Float16 const*, int, double*, int, long long)
Line
Count
Source
2218
277k
{
2219
277k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
277k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
277k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
277k
    decltype(nWordCount) n = 0;
2224
277k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
277k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
277k
    {
2227
557k
        for (; n < nWordCount - 7; n += 8)
2228
280k
        {
2229
280k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
280k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
280k
            Tout *const pOutPixels =
2232
280k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
280k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
280k
            nDstOffset += 8 * nDstPixelStride;
2237
280k
        }
2238
277k
    }
2239
673k
    for (; n < nWordCount; n++)
2240
396k
    {
2241
396k
        const Tin tValue =
2242
396k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
396k
        Tout *const pOutPixel =
2244
396k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
396k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
396k
        nDstOffset += nDstPixelStride;
2249
396k
    }
2250
277k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, unsigned char>(float const*, int, unsigned char*, int, long long)
Line
Count
Source
2218
7.09k
{
2219
7.09k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
7.09k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
7.09k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
7.09k
    decltype(nWordCount) n = 0;
2224
7.09k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
7.09k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
4.83k
    {
2227
202k
        for (; n < nWordCount - 7; n += 8)
2228
197k
        {
2229
197k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
197k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
197k
            Tout *const pOutPixels =
2232
197k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
197k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
197k
            nDstOffset += 8 * nDstPixelStride;
2237
197k
        }
2238
4.83k
    }
2239
433k
    for (; n < nWordCount; n++)
2240
426k
    {
2241
426k
        const Tin tValue =
2242
426k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
426k
        Tout *const pOutPixel =
2244
426k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
426k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
426k
        nDstOffset += nDstPixelStride;
2249
426k
    }
2250
7.09k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, signed char>(float const*, int, signed char*, int, long long)
Line
Count
Source
2218
1.98k
{
2219
1.98k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
1.98k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
1.98k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
1.98k
    decltype(nWordCount) n = 0;
2224
1.98k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
1.98k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
1.98k
    {
2227
64.9k
        for (; n < nWordCount - 7; n += 8)
2228
62.9k
        {
2229
62.9k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
62.9k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
62.9k
            Tout *const pOutPixels =
2232
62.9k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
62.9k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
62.9k
            nDstOffset += 8 * nDstPixelStride;
2237
62.9k
        }
2238
1.98k
    }
2239
7.82k
    for (; n < nWordCount; n++)
2240
5.83k
    {
2241
5.83k
        const Tin tValue =
2242
5.83k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
5.83k
        Tout *const pOutPixel =
2244
5.83k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
5.83k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
5.83k
        nDstOffset += nDstPixelStride;
2249
5.83k
    }
2250
1.98k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, unsigned short>(float const*, int, unsigned short*, int, long long)
Line
Count
Source
2218
1.08k
{
2219
1.08k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
1.08k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
1.08k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
1.08k
    decltype(nWordCount) n = 0;
2224
1.08k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
1.08k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
1.08k
    {
2227
52.2k
        for (; n < nWordCount - 7; n += 8)
2228
51.1k
        {
2229
51.1k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
51.1k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
51.1k
            Tout *const pOutPixels =
2232
51.1k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
51.1k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
51.1k
            nDstOffset += 8 * nDstPixelStride;
2237
51.1k
        }
2238
1.08k
    }
2239
4.57k
    for (; n < nWordCount; n++)
2240
3.48k
    {
2241
3.48k
        const Tin tValue =
2242
3.48k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
3.48k
        Tout *const pOutPixel =
2244
3.48k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
3.48k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
3.48k
        nDstOffset += nDstPixelStride;
2249
3.48k
    }
2250
1.08k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, short>(float const*, int, short*, int, long long)
Line
Count
Source
2218
31.4k
{
2219
31.4k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
31.4k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
31.4k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
31.4k
    decltype(nWordCount) n = 0;
2224
31.4k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
31.4k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
31.4k
    {
2227
36.0k
        for (; n < nWordCount - 7; n += 8)
2228
4.61k
        {
2229
4.61k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
4.61k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
4.61k
            Tout *const pOutPixels =
2232
4.61k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
4.61k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
4.61k
            nDstOffset += 8 * nDstPixelStride;
2237
4.61k
        }
2238
31.4k
    }
2239
124k
    for (; n < nWordCount; n++)
2240
93.0k
    {
2241
93.0k
        const Tin tValue =
2242
93.0k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
93.0k
        Tout *const pOutPixel =
2244
93.0k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
93.0k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
93.0k
        nDstOffset += nDstPixelStride;
2249
93.0k
    }
2250
31.4k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, int>(float const*, int, int*, int, long long)
Line
Count
Source
2218
484
{
2219
484
    decltype(nWordCount) nDstOffset = 0;
2220
2221
484
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
484
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
484
    decltype(nWordCount) n = 0;
2224
484
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
212
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
212
    {
2227
212
        for (; n < nWordCount - 7; n += 8)
2228
0
        {
2229
0
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
0
                pSrcDataPtr + (n * nSrcPixelStride));
2231
0
            Tout *const pOutPixels =
2232
0
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
0
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
0
            nDstOffset += 8 * nDstPixelStride;
2237
0
        }
2238
212
    }
2239
1.80k
    for (; n < nWordCount; n++)
2240
1.32k
    {
2241
1.32k
        const Tin tValue =
2242
1.32k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
1.32k
        Tout *const pOutPixel =
2244
1.32k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
1.32k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
1.32k
        nDstOffset += nDstPixelStride;
2249
1.32k
    }
2250
484
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, cpl::Float16>(float const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<float, double>(float const*, int, double*, int, long long)
Line
Count
Source
2218
24.1M
{
2219
24.1M
    decltype(nWordCount) nDstOffset = 0;
2220
2221
24.1M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
24.1M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
24.1M
    decltype(nWordCount) n = 0;
2224
24.1M
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
24.1M
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
24.1M
    {
2227
38.3M
        for (; n < nWordCount - 7; n += 8)
2228
14.1M
        {
2229
14.1M
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
14.1M
                pSrcDataPtr + (n * nSrcPixelStride));
2231
14.1M
            Tout *const pOutPixels =
2232
14.1M
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
14.1M
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
14.1M
            nDstOffset += 8 * nDstPixelStride;
2237
14.1M
        }
2238
24.1M
    }
2239
113M
    for (; n < nWordCount; n++)
2240
89.2M
    {
2241
89.2M
        const Tin tValue =
2242
89.2M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
89.2M
        Tout *const pOutPixel =
2244
89.2M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
89.2M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
89.2M
        nDstOffset += nDstPixelStride;
2249
89.2M
    }
2250
24.1M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<double, unsigned char>(double const*, int, unsigned char*, int, long long)
Line
Count
Source
2218
14.6M
{
2219
14.6M
    decltype(nWordCount) nDstOffset = 0;
2220
2221
14.6M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
14.6M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
14.6M
    decltype(nWordCount) n = 0;
2224
14.6M
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
10.4k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
3.86k
    {
2227
55.2k
        for (; n < nWordCount - 7; n += 8)
2228
51.4k
        {
2229
51.4k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
51.4k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
51.4k
            Tout *const pOutPixels =
2232
51.4k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
51.4k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
51.4k
            nDstOffset += 8 * nDstPixelStride;
2237
51.4k
        }
2238
3.86k
    }
2239
29.6M
    for (; n < nWordCount; n++)
2240
15.0M
    {
2241
15.0M
        const Tin tValue =
2242
15.0M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
15.0M
        Tout *const pOutPixel =
2244
15.0M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
15.0M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
15.0M
        nDstOffset += nDstPixelStride;
2249
15.0M
    }
2250
14.6M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<double, unsigned short>(double const*, int, unsigned short*, int, long long)
Line
Count
Source
2218
14.2M
{
2219
14.2M
    decltype(nWordCount) nDstOffset = 0;
2220
2221
14.2M
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
14.2M
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
14.2M
    decltype(nWordCount) n = 0;
2224
14.2M
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
357k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
357k
    {
2227
359k
        for (; n < nWordCount - 7; n += 8)
2228
1.33k
        {
2229
1.33k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
1.33k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
1.33k
            Tout *const pOutPixels =
2232
1.33k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
1.33k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
1.33k
            nDstOffset += 8 * nDstPixelStride;
2237
1.33k
        }
2238
357k
    }
2239
28.6M
    for (; n < nWordCount; n++)
2240
14.3M
    {
2241
14.3M
        const Tin tValue =
2242
14.3M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
14.3M
        Tout *const pOutPixel =
2244
14.3M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
14.3M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
14.3M
        nDstOffset += nDstPixelStride;
2249
14.3M
    }
2250
14.2M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<double, cpl::Float16>(double const*, int, cpl::Float16*, int, long long)
Line
Count
Source
2218
20.9k
{
2219
20.9k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
20.9k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
20.9k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
20.9k
    decltype(nWordCount) n = 0;
2224
20.9k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
0
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
0
    {
2227
0
        for (; n < nWordCount - 7; n += 8)
2228
0
        {
2229
0
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
0
                pSrcDataPtr + (n * nSrcPixelStride));
2231
0
            Tout *const pOutPixels =
2232
0
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
0
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
0
            nDstOffset += 8 * nDstPixelStride;
2237
0
        }
2238
0
    }
2239
41.9k
    for (; n < nWordCount; n++)
2240
20.9k
    {
2241
20.9k
        const Tin tValue =
2242
20.9k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
20.9k
        Tout *const pOutPixel =
2244
20.9k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
20.9k
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
20.9k
        nDstOffset += nDstPixelStride;
2249
20.9k
    }
2250
20.9k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsT_8atatime<double, float>(double const*, int, float*, int, long long)
Line
Count
Source
2218
859k
{
2219
859k
    decltype(nWordCount) nDstOffset = 0;
2220
2221
859k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
2222
859k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
2223
859k
    decltype(nWordCount) n = 0;
2224
859k
    if (nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
2225
214k
        nDstPixelStride == static_cast<int>(sizeof(Tout)))
2226
214k
    {
2227
405k
        for (; n < nWordCount - 7; n += 8)
2228
191k
        {
2229
191k
            const Tin *pInValues = reinterpret_cast<const Tin *>(
2230
191k
                pSrcDataPtr + (n * nSrcPixelStride));
2231
191k
            Tout *const pOutPixels =
2232
191k
                reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2233
2234
191k
            GDALCopy8Words(pInValues, pOutPixels);
2235
2236
191k
            nDstOffset += 8 * nDstPixelStride;
2237
191k
        }
2238
214k
    }
2239
1.98M
    for (; n < nWordCount; n++)
2240
1.12M
    {
2241
1.12M
        const Tin tValue =
2242
1.12M
            *reinterpret_cast<const Tin *>(pSrcDataPtr + (n * nSrcPixelStride));
2243
1.12M
        Tout *const pOutPixel =
2244
1.12M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
2245
2246
1.12M
        GDALCopyWord(tValue, *pOutPixel);
2247
2248
1.12M
        nDstOffset += nDstPixelStride;
2249
1.12M
    }
2250
859k
}
2251
2252
#ifdef HAVE_SSE2
2253
2254
template <class Tout>
2255
void GDALCopyWordsByteTo16Bit(const GByte *const CPL_RESTRICT pSrcData,
2256
                              int nSrcPixelStride,
2257
                              Tout *const CPL_RESTRICT pDstData,
2258
                              int nDstPixelStride, GPtrDiff_t nWordCount)
2259
427k
{
2260
427k
    static_assert(std::is_integral<Tout>::value &&
2261
427k
                      sizeof(Tout) == sizeof(uint16_t),
2262
427k
                  "Bad Tout");
2263
427k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2264
25.6k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2265
25.6k
    {
2266
25.6k
        decltype(nWordCount) n = 0;
2267
25.6k
        const __m128i xmm_zero = _mm_setzero_si128();
2268
25.6k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2269
25.6k
            reinterpret_cast<GByte *>(pDstData);
2270
33.6k
        for (; n < nWordCount - 15; n += 16)
2271
7.94k
        {
2272
7.94k
            __m128i xmm = _mm_loadu_si128(
2273
7.94k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2274
7.94k
            __m128i xmm0 = _mm_unpacklo_epi8(xmm, xmm_zero);
2275
7.94k
            __m128i xmm1 = _mm_unpackhi_epi8(xmm, xmm_zero);
2276
7.94k
            _mm_storeu_si128(
2277
7.94k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2), xmm0);
2278
7.94k
            _mm_storeu_si128(
2279
7.94k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2 + 16), xmm1);
2280
7.94k
        }
2281
25.6k
#if defined(__clang__)
2282
25.6k
#pragma clang loop vectorize(disable)
2283
25.6k
#endif
2284
269k
        for (; n < nWordCount; n++)
2285
243k
        {
2286
243k
            pDstData[n] = pSrcData[n];
2287
243k
        }
2288
25.6k
    }
2289
402k
    else
2290
402k
    {
2291
402k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2292
402k
                              nDstPixelStride, nWordCount);
2293
402k
    }
2294
427k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsByteTo16Bit<unsigned short>(unsigned char const*, int, unsigned short*, int, long long)
Line
Count
Source
2259
81.3k
{
2260
81.3k
    static_assert(std::is_integral<Tout>::value &&
2261
81.3k
                      sizeof(Tout) == sizeof(uint16_t),
2262
81.3k
                  "Bad Tout");
2263
81.3k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2264
1.81k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2265
1.81k
    {
2266
1.81k
        decltype(nWordCount) n = 0;
2267
1.81k
        const __m128i xmm_zero = _mm_setzero_si128();
2268
1.81k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2269
1.81k
            reinterpret_cast<GByte *>(pDstData);
2270
7.28k
        for (; n < nWordCount - 15; n += 16)
2271
5.46k
        {
2272
5.46k
            __m128i xmm = _mm_loadu_si128(
2273
5.46k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2274
5.46k
            __m128i xmm0 = _mm_unpacklo_epi8(xmm, xmm_zero);
2275
5.46k
            __m128i xmm1 = _mm_unpackhi_epi8(xmm, xmm_zero);
2276
5.46k
            _mm_storeu_si128(
2277
5.46k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2), xmm0);
2278
5.46k
            _mm_storeu_si128(
2279
5.46k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2 + 16), xmm1);
2280
5.46k
        }
2281
1.81k
#if defined(__clang__)
2282
1.81k
#pragma clang loop vectorize(disable)
2283
1.81k
#endif
2284
27.0k
        for (; n < nWordCount; n++)
2285
25.2k
        {
2286
25.2k
            pDstData[n] = pSrcData[n];
2287
25.2k
        }
2288
1.81k
    }
2289
79.5k
    else
2290
79.5k
    {
2291
79.5k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2292
79.5k
                              nDstPixelStride, nWordCount);
2293
79.5k
    }
2294
81.3k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsByteTo16Bit<short>(unsigned char const*, int, short*, int, long long)
Line
Count
Source
2259
346k
{
2260
346k
    static_assert(std::is_integral<Tout>::value &&
2261
346k
                      sizeof(Tout) == sizeof(uint16_t),
2262
346k
                  "Bad Tout");
2263
346k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2264
23.8k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2265
23.8k
    {
2266
23.8k
        decltype(nWordCount) n = 0;
2267
23.8k
        const __m128i xmm_zero = _mm_setzero_si128();
2268
23.8k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2269
23.8k
            reinterpret_cast<GByte *>(pDstData);
2270
26.3k
        for (; n < nWordCount - 15; n += 16)
2271
2.48k
        {
2272
2.48k
            __m128i xmm = _mm_loadu_si128(
2273
2.48k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2274
2.48k
            __m128i xmm0 = _mm_unpacklo_epi8(xmm, xmm_zero);
2275
2.48k
            __m128i xmm1 = _mm_unpackhi_epi8(xmm, xmm_zero);
2276
2.48k
            _mm_storeu_si128(
2277
2.48k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2), xmm0);
2278
2.48k
            _mm_storeu_si128(
2279
2.48k
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 2 + 16), xmm1);
2280
2.48k
        }
2281
23.8k
#if defined(__clang__)
2282
23.8k
#pragma clang loop vectorize(disable)
2283
23.8k
#endif
2284
242k
        for (; n < nWordCount; n++)
2285
218k
        {
2286
218k
            pDstData[n] = pSrcData[n];
2287
218k
        }
2288
23.8k
    }
2289
322k
    else
2290
322k
    {
2291
322k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2292
322k
                              nDstPixelStride, nWordCount);
2293
322k
    }
2294
346k
}
2295
2296
template <>
2297
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2298
                                 int nSrcPixelStride,
2299
                                 GUInt16 *const CPL_RESTRICT pDstData,
2300
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2301
81.3k
{
2302
81.3k
    GDALCopyWordsByteTo16Bit(pSrcData, nSrcPixelStride, pDstData,
2303
81.3k
                             nDstPixelStride, nWordCount);
2304
81.3k
}
2305
2306
template <>
2307
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2308
                                 int nSrcPixelStride,
2309
                                 GInt16 *const CPL_RESTRICT pDstData,
2310
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2311
346k
{
2312
346k
    GDALCopyWordsByteTo16Bit(pSrcData, nSrcPixelStride, pDstData,
2313
346k
                             nDstPixelStride, nWordCount);
2314
346k
}
2315
2316
template <class Tout>
2317
void GDALCopyWordsByteTo32Bit(const GByte *const CPL_RESTRICT pSrcData,
2318
                              int nSrcPixelStride,
2319
                              Tout *const CPL_RESTRICT pDstData,
2320
                              int nDstPixelStride, GPtrDiff_t nWordCount)
2321
172M
{
2322
172M
    static_assert(std::is_integral<Tout>::value &&
2323
172M
                      sizeof(Tout) == sizeof(uint32_t),
2324
172M
                  "Bad Tout");
2325
172M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2326
172M
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2327
172M
    {
2328
172M
        decltype(nWordCount) n = 0;
2329
172M
        const __m128i xmm_zero = _mm_setzero_si128();
2330
172M
        GByte *CPL_RESTRICT pabyDstDataPtr =
2331
172M
            reinterpret_cast<GByte *>(pDstData);
2332
954M
        for (; n < nWordCount - 15; n += 16)
2333
782M
        {
2334
782M
            __m128i xmm = _mm_loadu_si128(
2335
782M
                reinterpret_cast<const __m128i *>(pSrcData + n));
2336
782M
            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
2337
782M
            __m128i xmm_high = _mm_unpackhi_epi8(xmm, xmm_zero);
2338
782M
            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
2339
782M
            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
2340
782M
            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
2341
782M
            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
2342
782M
            _mm_storeu_si128(
2343
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4), xmm0);
2344
782M
            _mm_storeu_si128(
2345
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 16), xmm1);
2346
782M
            _mm_storeu_si128(
2347
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 32), xmm2);
2348
782M
            _mm_storeu_si128(
2349
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 48), xmm3);
2350
782M
        }
2351
172M
#if defined(__clang__)
2352
172M
#pragma clang loop vectorize(disable)
2353
172M
#endif
2354
744M
        for (; n < nWordCount; n++)
2355
572M
        {
2356
572M
            pDstData[n] = pSrcData[n];
2357
572M
        }
2358
172M
    }
2359
218k
    else
2360
218k
    {
2361
218k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2362
218k
                              nDstPixelStride, nWordCount);
2363
218k
    }
2364
172M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsByteTo32Bit<unsigned int>(unsigned char const*, int, unsigned int*, int, long long)
Line
Count
Source
2321
3.33k
{
2322
3.33k
    static_assert(std::is_integral<Tout>::value &&
2323
3.33k
                      sizeof(Tout) == sizeof(uint32_t),
2324
3.33k
                  "Bad Tout");
2325
3.33k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2326
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2327
0
    {
2328
0
        decltype(nWordCount) n = 0;
2329
0
        const __m128i xmm_zero = _mm_setzero_si128();
2330
0
        GByte *CPL_RESTRICT pabyDstDataPtr =
2331
0
            reinterpret_cast<GByte *>(pDstData);
2332
0
        for (; n < nWordCount - 15; n += 16)
2333
0
        {
2334
0
            __m128i xmm = _mm_loadu_si128(
2335
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
2336
0
            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
2337
0
            __m128i xmm_high = _mm_unpackhi_epi8(xmm, xmm_zero);
2338
0
            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
2339
0
            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
2340
0
            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
2341
0
            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
2342
0
            _mm_storeu_si128(
2343
0
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4), xmm0);
2344
0
            _mm_storeu_si128(
2345
0
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 16), xmm1);
2346
0
            _mm_storeu_si128(
2347
0
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 32), xmm2);
2348
0
            _mm_storeu_si128(
2349
0
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 48), xmm3);
2350
0
        }
2351
0
#if defined(__clang__)
2352
0
#pragma clang loop vectorize(disable)
2353
0
#endif
2354
0
        for (; n < nWordCount; n++)
2355
0
        {
2356
0
            pDstData[n] = pSrcData[n];
2357
0
        }
2358
0
    }
2359
3.33k
    else
2360
3.33k
    {
2361
3.33k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2362
3.33k
                              nDstPixelStride, nWordCount);
2363
3.33k
    }
2364
3.33k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsByteTo32Bit<int>(unsigned char const*, int, int*, int, long long)
Line
Count
Source
2321
172M
{
2322
172M
    static_assert(std::is_integral<Tout>::value &&
2323
172M
                      sizeof(Tout) == sizeof(uint32_t),
2324
172M
                  "Bad Tout");
2325
172M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2326
172M
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2327
172M
    {
2328
172M
        decltype(nWordCount) n = 0;
2329
172M
        const __m128i xmm_zero = _mm_setzero_si128();
2330
172M
        GByte *CPL_RESTRICT pabyDstDataPtr =
2331
172M
            reinterpret_cast<GByte *>(pDstData);
2332
954M
        for (; n < nWordCount - 15; n += 16)
2333
782M
        {
2334
782M
            __m128i xmm = _mm_loadu_si128(
2335
782M
                reinterpret_cast<const __m128i *>(pSrcData + n));
2336
782M
            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
2337
782M
            __m128i xmm_high = _mm_unpackhi_epi8(xmm, xmm_zero);
2338
782M
            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
2339
782M
            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
2340
782M
            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
2341
782M
            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
2342
782M
            _mm_storeu_si128(
2343
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4), xmm0);
2344
782M
            _mm_storeu_si128(
2345
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 16), xmm1);
2346
782M
            _mm_storeu_si128(
2347
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 32), xmm2);
2348
782M
            _mm_storeu_si128(
2349
782M
                reinterpret_cast<__m128i *>(pabyDstDataPtr + n * 4 + 48), xmm3);
2350
782M
        }
2351
172M
#if defined(__clang__)
2352
172M
#pragma clang loop vectorize(disable)
2353
172M
#endif
2354
744M
        for (; n < nWordCount; n++)
2355
572M
        {
2356
572M
            pDstData[n] = pSrcData[n];
2357
572M
        }
2358
172M
    }
2359
215k
    else
2360
215k
    {
2361
215k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2362
215k
                              nDstPixelStride, nWordCount);
2363
215k
    }
2364
172M
}
2365
2366
template <>
2367
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2368
                                 int nSrcPixelStride,
2369
                                 GUInt32 *const CPL_RESTRICT pDstData,
2370
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2371
3.33k
{
2372
3.33k
    GDALCopyWordsByteTo32Bit(pSrcData, nSrcPixelStride, pDstData,
2373
3.33k
                             nDstPixelStride, nWordCount);
2374
3.33k
}
2375
2376
template <>
2377
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2378
                                 int nSrcPixelStride,
2379
                                 GInt32 *const CPL_RESTRICT pDstData,
2380
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2381
172M
{
2382
172M
    GDALCopyWordsByteTo32Bit(pSrcData, nSrcPixelStride, pDstData,
2383
172M
                             nDstPixelStride, nWordCount);
2384
172M
}
2385
2386
template <>
2387
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2388
                                 int nSrcPixelStride,
2389
                                 float *const CPL_RESTRICT pDstData,
2390
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2391
3.94M
{
2392
3.94M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2393
29.0k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2394
29.0k
    {
2395
29.0k
        decltype(nWordCount) n = 0;
2396
29.0k
        const __m128i xmm_zero = _mm_setzero_si128();
2397
29.0k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2398
29.0k
            reinterpret_cast<GByte *>(pDstData);
2399
121k
        for (; n < nWordCount - 15; n += 16)
2400
92.6k
        {
2401
92.6k
            __m128i xmm = _mm_loadu_si128(
2402
92.6k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2403
92.6k
            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
2404
92.6k
            __m128i xmm_high = _mm_unpackhi_epi8(xmm, xmm_zero);
2405
92.6k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
2406
92.6k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
2407
92.6k
            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
2408
92.6k
            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
2409
92.6k
            __m128 xmm0_f = _mm_cvtepi32_ps(xmm0);
2410
92.6k
            __m128 xmm1_f = _mm_cvtepi32_ps(xmm1);
2411
92.6k
            __m128 xmm2_f = _mm_cvtepi32_ps(xmm2);
2412
92.6k
            __m128 xmm3_f = _mm_cvtepi32_ps(xmm3);
2413
92.6k
            _mm_storeu_ps(reinterpret_cast<float *>(pabyDstDataPtr + n * 4),
2414
92.6k
                          xmm0_f);
2415
92.6k
            _mm_storeu_ps(
2416
92.6k
                reinterpret_cast<float *>(pabyDstDataPtr + n * 4 + 16), xmm1_f);
2417
92.6k
            _mm_storeu_ps(
2418
92.6k
                reinterpret_cast<float *>(pabyDstDataPtr + n * 4 + 32), xmm2_f);
2419
92.6k
            _mm_storeu_ps(
2420
92.6k
                reinterpret_cast<float *>(pabyDstDataPtr + n * 4 + 48), xmm3_f);
2421
92.6k
        }
2422
29.0k
#if defined(__clang__)
2423
29.0k
#pragma clang loop vectorize(disable)
2424
29.0k
#endif
2425
155k
        for (; n < nWordCount; n++)
2426
126k
        {
2427
126k
            pDstData[n] = pSrcData[n];
2428
126k
        }
2429
29.0k
    }
2430
3.91M
    else
2431
3.91M
    {
2432
3.91M
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2433
3.91M
                              nDstPixelStride, nWordCount);
2434
3.91M
    }
2435
3.94M
}
2436
2437
template <>
2438
CPL_NOINLINE void GDALCopyWordsT(const GByte *const CPL_RESTRICT pSrcData,
2439
                                 int nSrcPixelStride,
2440
                                 double *const CPL_RESTRICT pDstData,
2441
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2442
146k
{
2443
146k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2444
23.9k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2445
23.9k
    {
2446
23.9k
        decltype(nWordCount) n = 0;
2447
23.9k
        const __m128i xmm_zero = _mm_setzero_si128();
2448
23.9k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2449
23.9k
            reinterpret_cast<GByte *>(pDstData);
2450
89.0k
        for (; n < nWordCount - 15; n += 16)
2451
65.1k
        {
2452
65.1k
            __m128i xmm = _mm_loadu_si128(
2453
65.1k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2454
65.1k
            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
2455
65.1k
            __m128i xmm_high = _mm_unpackhi_epi8(xmm, xmm_zero);
2456
65.1k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
2457
65.1k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
2458
65.1k
            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
2459
65.1k
            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
2460
2461
#if defined(__AVX2__) && defined(slightly_slower_than_SSE2)
2462
            _mm256_storeu_pd(reinterpret_cast<double *>(pabyDstDataPtr + n * 8),
2463
                             _mm256_cvtepi32_pd(xmm0));
2464
            _mm256_storeu_pd(
2465
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 32),
2466
                _mm256_cvtepi32_pd(xmm1));
2467
            _mm256_storeu_pd(
2468
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 64),
2469
                _mm256_cvtepi32_pd(xmm2));
2470
            _mm256_storeu_pd(
2471
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 96),
2472
                _mm256_cvtepi32_pd(xmm3));
2473
#else
2474
65.1k
            __m128d xmm0_low_d = _mm_cvtepi32_pd(xmm0);
2475
65.1k
            __m128d xmm1_low_d = _mm_cvtepi32_pd(xmm1);
2476
65.1k
            __m128d xmm2_low_d = _mm_cvtepi32_pd(xmm2);
2477
65.1k
            __m128d xmm3_low_d = _mm_cvtepi32_pd(xmm3);
2478
65.1k
            xmm0 = _mm_srli_si128(xmm0, 8);
2479
65.1k
            xmm1 = _mm_srli_si128(xmm1, 8);
2480
65.1k
            xmm2 = _mm_srli_si128(xmm2, 8);
2481
65.1k
            xmm3 = _mm_srli_si128(xmm3, 8);
2482
65.1k
            __m128d xmm0_high_d = _mm_cvtepi32_pd(xmm0);
2483
65.1k
            __m128d xmm1_high_d = _mm_cvtepi32_pd(xmm1);
2484
65.1k
            __m128d xmm2_high_d = _mm_cvtepi32_pd(xmm2);
2485
65.1k
            __m128d xmm3_high_d = _mm_cvtepi32_pd(xmm3);
2486
2487
65.1k
            _mm_storeu_pd(reinterpret_cast<double *>(pabyDstDataPtr + n * 8),
2488
65.1k
                          xmm0_low_d);
2489
65.1k
            _mm_storeu_pd(
2490
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 16),
2491
65.1k
                xmm0_high_d);
2492
65.1k
            _mm_storeu_pd(
2493
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 32),
2494
65.1k
                xmm1_low_d);
2495
65.1k
            _mm_storeu_pd(
2496
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 48),
2497
65.1k
                xmm1_high_d);
2498
65.1k
            _mm_storeu_pd(
2499
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 64),
2500
65.1k
                xmm2_low_d);
2501
65.1k
            _mm_storeu_pd(
2502
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 80),
2503
65.1k
                xmm2_high_d);
2504
65.1k
            _mm_storeu_pd(
2505
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 96),
2506
65.1k
                xmm3_low_d);
2507
65.1k
            _mm_storeu_pd(
2508
65.1k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 112),
2509
65.1k
                xmm3_high_d);
2510
65.1k
#endif
2511
65.1k
        }
2512
23.9k
#if defined(__clang__)
2513
23.9k
#pragma clang loop vectorize(disable)
2514
23.9k
#endif
2515
262k
        for (; n < nWordCount; n++)
2516
238k
        {
2517
238k
            pDstData[n] = pSrcData[n];
2518
238k
        }
2519
23.9k
    }
2520
122k
    else
2521
122k
    {
2522
122k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2523
122k
                              nDstPixelStride, nWordCount);
2524
122k
    }
2525
146k
}
2526
2527
template <>
2528
CPL_NOINLINE void GDALCopyWordsT(const uint8_t *const CPL_RESTRICT pSrcData,
2529
                                 int nSrcPixelStride,
2530
                                 int8_t *const CPL_RESTRICT pDstData,
2531
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2532
103
{
2533
103
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2534
81
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2535
81
    {
2536
81
        decltype(nWordCount) n = 0;
2537
81
        const __m128i xmm_127 = _mm_set1_epi8(127);
2538
656
        for (; n < nWordCount - 31; n += 32)
2539
575
        {
2540
575
            __m128i xmm0 = _mm_loadu_si128(
2541
575
                reinterpret_cast<const __m128i *>(pSrcData + n));
2542
575
            __m128i xmm1 = _mm_loadu_si128(
2543
575
                reinterpret_cast<const __m128i *>(pSrcData + n + 16));
2544
575
            xmm0 = _mm_min_epu8(xmm0, xmm_127);
2545
575
            xmm1 = _mm_min_epu8(xmm1, xmm_127);
2546
575
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2547
575
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 16),
2548
575
                             xmm1);
2549
575
        }
2550
81
#if defined(__clang__)
2551
81
#pragma clang loop vectorize(disable)
2552
81
#endif
2553
1.17k
        for (; n < nWordCount; n++)
2554
1.09k
        {
2555
1.09k
            pDstData[n] = static_cast<int8_t>(std::min<int>(pSrcData[n], 127));
2556
1.09k
        }
2557
81
    }
2558
22
    else
2559
22
    {
2560
22
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2561
22
                              nDstPixelStride, nWordCount);
2562
22
    }
2563
103
}
2564
2565
template <>
2566
CPL_NOINLINE void GDALCopyWordsT(const int8_t *const CPL_RESTRICT pSrcData,
2567
                                 int nSrcPixelStride,
2568
                                 uint8_t *const CPL_RESTRICT pDstData,
2569
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2570
14.7k
{
2571
14.7k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2572
8
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2573
8
    {
2574
8
        decltype(nWordCount) n = 0;
2575
8
#if !(defined(__SSE4_1__) || defined(__AVX__) ||                               \
2576
8
      defined(USE_NEON_OPTIMIZATIONS))
2577
8
        const __m128i xmm_INT8_to_UINT8 = _mm_set1_epi8(-128);
2578
8
#endif
2579
24
        for (; n < nWordCount - 31; n += 32)
2580
16
        {
2581
16
            __m128i xmm0 = _mm_loadu_si128(
2582
16
                reinterpret_cast<const __m128i *>(pSrcData + n));
2583
16
            __m128i xmm1 = _mm_loadu_si128(
2584
16
                reinterpret_cast<const __m128i *>(pSrcData + n + 16));
2585
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2586
            xmm0 = _mm_max_epi8(xmm0, _mm_setzero_si128());
2587
            xmm1 = _mm_max_epi8(xmm1, _mm_setzero_si128());
2588
#else
2589
16
            xmm0 = _mm_add_epi8(xmm0, xmm_INT8_to_UINT8);
2590
16
            xmm1 = _mm_add_epi8(xmm1, xmm_INT8_to_UINT8);
2591
16
            xmm0 = _mm_max_epu8(xmm0, xmm_INT8_to_UINT8);
2592
16
            xmm1 = _mm_max_epu8(xmm1, xmm_INT8_to_UINT8);
2593
16
            xmm0 = _mm_sub_epi8(xmm0, xmm_INT8_to_UINT8);
2594
16
            xmm1 = _mm_sub_epi8(xmm1, xmm_INT8_to_UINT8);
2595
16
#endif
2596
16
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2597
16
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 16),
2598
16
                             xmm1);
2599
16
        }
2600
8
#if defined(__clang__)
2601
8
#pragma clang loop vectorize(disable)
2602
8
#endif
2603
156
        for (; n < nWordCount; n++)
2604
148
        {
2605
148
            pDstData[n] = static_cast<uint8_t>(std::max<int>(pSrcData[n], 0));
2606
148
        }
2607
8
    }
2608
14.7k
    else
2609
14.7k
    {
2610
14.7k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2611
14.7k
                              nDstPixelStride, nWordCount);
2612
14.7k
    }
2613
14.7k
}
2614
2615
template <>
2616
CPL_NOINLINE void GDALCopyWordsT(const uint16_t *const CPL_RESTRICT pSrcData,
2617
                                 int nSrcPixelStride,
2618
                                 uint8_t *const CPL_RESTRICT pDstData,
2619
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2620
235k
{
2621
235k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2622
7.94k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2623
7.29k
    {
2624
7.29k
        decltype(nWordCount) n = 0;
2625
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2626
        const auto xmm_MAX_INT16 = _mm_set1_epi16(32767);
2627
#else
2628
        // In SSE2, min_epu16 does not exist, so shift from
2629
        // UInt16 to SInt16 to be able to use min_epi16
2630
7.29k
        const __m128i xmm_UINT16_to_INT16 = _mm_set1_epi16(-32768);
2631
7.29k
        const __m128i xmm_m255_shifted = _mm_set1_epi16(255 - 32768);
2632
7.29k
#endif
2633
123k
        for (; n < nWordCount - 15; n += 16)
2634
116k
        {
2635
116k
            __m128i xmm0 = _mm_loadu_si128(
2636
116k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2637
116k
            __m128i xmm1 = _mm_loadu_si128(
2638
116k
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
2639
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2640
            xmm0 = _mm_min_epu16(xmm0, xmm_MAX_INT16);
2641
            xmm1 = _mm_min_epu16(xmm1, xmm_MAX_INT16);
2642
#else
2643
116k
            xmm0 = _mm_add_epi16(xmm0, xmm_UINT16_to_INT16);
2644
116k
            xmm1 = _mm_add_epi16(xmm1, xmm_UINT16_to_INT16);
2645
116k
            xmm0 = _mm_min_epi16(xmm0, xmm_m255_shifted);
2646
116k
            xmm1 = _mm_min_epi16(xmm1, xmm_m255_shifted);
2647
116k
            xmm0 = _mm_sub_epi16(xmm0, xmm_UINT16_to_INT16);
2648
116k
            xmm1 = _mm_sub_epi16(xmm1, xmm_UINT16_to_INT16);
2649
116k
#endif
2650
116k
            xmm0 = _mm_packus_epi16(xmm0, xmm1);
2651
116k
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2652
116k
        }
2653
7.29k
#if defined(__clang__)
2654
7.29k
#pragma clang loop vectorize(disable)
2655
7.29k
#endif
2656
15.6k
        for (; n < nWordCount; n++)
2657
8.36k
        {
2658
8.36k
            pDstData[n] = static_cast<uint8_t>(std::min<int>(pSrcData[n], 255));
2659
8.36k
        }
2660
7.29k
    }
2661
228k
    else
2662
228k
    {
2663
228k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2664
228k
                              nDstPixelStride, nWordCount);
2665
228k
    }
2666
235k
}
2667
2668
template <>
2669
CPL_NOINLINE void GDALCopyWordsT(const uint16_t *const CPL_RESTRICT pSrcData,
2670
                                 int nSrcPixelStride,
2671
                                 int16_t *const CPL_RESTRICT pDstData,
2672
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2673
0
{
2674
0
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2675
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2676
0
    {
2677
0
        decltype(nWordCount) n = 0;
2678
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2679
        const __m128i xmm_MAX_INT16 = _mm_set1_epi16(32767);
2680
#else
2681
        // In SSE2, min_epu16 does not exist, so shift from
2682
        // UInt16 to SInt16 to be able to use min_epi16
2683
0
        const __m128i xmm_UINT16_to_INT16 = _mm_set1_epi16(-32768);
2684
0
        const __m128i xmm_32767_shifted = _mm_set1_epi16(32767 - 32768);
2685
0
#endif
2686
0
        for (; n < nWordCount - 15; n += 16)
2687
0
        {
2688
0
            __m128i xmm0 = _mm_loadu_si128(
2689
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
2690
0
            __m128i xmm1 = _mm_loadu_si128(
2691
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
2692
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2693
            xmm0 = _mm_min_epu16(xmm0, xmm_MAX_INT16);
2694
            xmm1 = _mm_min_epu16(xmm1, xmm_MAX_INT16);
2695
#else
2696
0
            xmm0 = _mm_add_epi16(xmm0, xmm_UINT16_to_INT16);
2697
0
            xmm1 = _mm_add_epi16(xmm1, xmm_UINT16_to_INT16);
2698
0
            xmm0 = _mm_min_epi16(xmm0, xmm_32767_shifted);
2699
0
            xmm1 = _mm_min_epi16(xmm1, xmm_32767_shifted);
2700
0
            xmm0 = _mm_sub_epi16(xmm0, xmm_UINT16_to_INT16);
2701
0
            xmm1 = _mm_sub_epi16(xmm1, xmm_UINT16_to_INT16);
2702
0
#endif
2703
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2704
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 8),
2705
0
                             xmm1);
2706
0
        }
2707
0
#if defined(__clang__)
2708
0
#pragma clang loop vectorize(disable)
2709
0
#endif
2710
0
        for (; n < nWordCount; n++)
2711
0
        {
2712
0
            pDstData[n] =
2713
0
                static_cast<int16_t>(std::min<int>(pSrcData[n], 32767));
2714
0
        }
2715
0
    }
2716
0
    else
2717
0
    {
2718
0
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2719
0
                              nDstPixelStride, nWordCount);
2720
0
    }
2721
0
}
2722
2723
template <>
2724
CPL_NOINLINE void GDALCopyWordsT(const int16_t *const CPL_RESTRICT pSrcData,
2725
                                 int nSrcPixelStride,
2726
                                 uint16_t *const CPL_RESTRICT pDstData,
2727
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2728
0
{
2729
0
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2730
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2731
0
    {
2732
0
        decltype(nWordCount) n = 0;
2733
0
        const __m128i xmm_zero = _mm_setzero_si128();
2734
0
        for (; n < nWordCount - 15; n += 16)
2735
0
        {
2736
0
            __m128i xmm0 = _mm_loadu_si128(
2737
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
2738
0
            __m128i xmm1 = _mm_loadu_si128(
2739
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
2740
0
            xmm0 = _mm_max_epi16(xmm0, xmm_zero);
2741
0
            xmm1 = _mm_max_epi16(xmm1, xmm_zero);
2742
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2743
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 8),
2744
0
                             xmm1);
2745
0
        }
2746
0
#if defined(__clang__)
2747
0
#pragma clang loop vectorize(disable)
2748
0
#endif
2749
0
        for (; n < nWordCount; n++)
2750
0
        {
2751
0
            pDstData[n] = static_cast<uint16_t>(std::max<int>(pSrcData[n], 0));
2752
0
        }
2753
0
    }
2754
0
    else
2755
0
    {
2756
0
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2757
0
                              nDstPixelStride, nWordCount);
2758
0
    }
2759
0
}
2760
2761
template <>
2762
CPL_NOINLINE void GDALCopyWordsT(const uint32_t *const CPL_RESTRICT pSrcData,
2763
                                 int nSrcPixelStride,
2764
                                 int32_t *const CPL_RESTRICT pDstData,
2765
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2766
1.73M
{
2767
1.73M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2768
1.70M
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2769
1.70M
    {
2770
1.70M
        decltype(nWordCount) n = 0;
2771
1.70M
        const __m128i xmm_MAX_INT = _mm_set1_epi32(INT_MAX);
2772
1.70M
        [[maybe_unused]] const __m128i bias = _mm_set1_epi32(INT_MIN);
2773
1.70M
        [[maybe_unused]] const __m128i xmm_MAX_INT_biased =
2774
1.70M
            _mm_xor_si128(xmm_MAX_INT, bias);
2775
7.11M
        for (; n < nWordCount - 7; n += 8)
2776
5.41M
        {
2777
5.41M
            __m128i xmm0 = _mm_loadu_si128(
2778
5.41M
                reinterpret_cast<const __m128i *>(pSrcData + n));
2779
5.41M
            __m128i xmm1 = _mm_loadu_si128(
2780
5.41M
                reinterpret_cast<const __m128i *>(pSrcData + n + 4));
2781
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2782
            xmm0 = _mm_min_epu32(xmm0, xmm_MAX_INT);
2783
            xmm1 = _mm_min_epu32(xmm1, xmm_MAX_INT);
2784
#else
2785
5.41M
            const __m128i xmm0_biased = _mm_xor_si128(xmm0, bias);
2786
5.41M
            const __m128i mask0 =
2787
5.41M
                _mm_cmplt_epi32(xmm0_biased, xmm_MAX_INT_biased);
2788
5.41M
            xmm0 = GDALIfThenElse(mask0, xmm0, xmm_MAX_INT);
2789
2790
5.41M
            const __m128i xmm1_biased = _mm_xor_si128(xmm1, bias);
2791
5.41M
            const __m128i mask1 =
2792
5.41M
                _mm_cmplt_epi32(xmm1_biased, xmm_MAX_INT_biased);
2793
5.41M
            xmm1 = GDALIfThenElse(mask1, xmm1, xmm_MAX_INT);
2794
5.41M
#endif
2795
5.41M
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2796
5.41M
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 4),
2797
5.41M
                             xmm1);
2798
5.41M
        }
2799
1.70M
#if defined(__clang__)
2800
1.70M
#pragma clang loop vectorize(disable)
2801
1.70M
#endif
2802
4.54M
        for (; n < nWordCount; n++)
2803
2.83M
        {
2804
2.83M
            pDstData[n] =
2805
2.83M
                static_cast<int32_t>(std::min<uint32_t>(pSrcData[n], INT_MAX));
2806
2.83M
        }
2807
1.70M
    }
2808
34.2k
    else
2809
34.2k
    {
2810
34.2k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2811
34.2k
                              nDstPixelStride, nWordCount);
2812
34.2k
    }
2813
1.73M
}
2814
2815
template <>
2816
CPL_NOINLINE void GDALCopyWordsT(const int32_t *const CPL_RESTRICT pSrcData,
2817
                                 int nSrcPixelStride,
2818
                                 uint32_t *const CPL_RESTRICT pDstData,
2819
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2820
0
{
2821
0
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2822
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2823
0
    {
2824
0
        decltype(nWordCount) n = 0;
2825
0
        const __m128i xmm_zero = _mm_setzero_si128();
2826
0
        for (; n < nWordCount - 7; n += 8)
2827
0
        {
2828
0
            __m128i xmm0 = _mm_loadu_si128(
2829
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
2830
0
            __m128i xmm1 = _mm_loadu_si128(
2831
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 4));
2832
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
2833
            xmm0 = _mm_max_epi32(xmm0, xmm_zero);
2834
            xmm1 = _mm_max_epi32(xmm1, xmm_zero);
2835
#else
2836
0
            const __m128i mask0 = _mm_cmpgt_epi32(xmm0, xmm_zero);
2837
0
            const __m128i mask1 = _mm_cmpgt_epi32(xmm1, xmm_zero);
2838
0
            xmm0 = _mm_and_si128(xmm0, mask0);
2839
0
            xmm1 = _mm_and_si128(xmm1, mask1);
2840
0
#endif
2841
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), xmm0);
2842
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 4),
2843
0
                             xmm1);
2844
0
        }
2845
0
#if defined(__clang__)
2846
0
#pragma clang loop vectorize(disable)
2847
0
#endif
2848
0
        for (; n < nWordCount; n++)
2849
0
        {
2850
0
            pDstData[n] = static_cast<uint32_t>(std::max(pSrcData[n], 0));
2851
0
        }
2852
0
    }
2853
0
    else
2854
0
    {
2855
0
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2856
0
                              nDstPixelStride, nWordCount);
2857
0
    }
2858
0
}
2859
2860
template <>
2861
CPL_NOINLINE void GDALCopyWordsT(const uint16_t *const CPL_RESTRICT pSrcData,
2862
                                 int nSrcPixelStride,
2863
                                 float *const CPL_RESTRICT pDstData,
2864
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2865
2.77M
{
2866
2.77M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2867
28.6k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2868
28.6k
    {
2869
28.6k
        decltype(nWordCount) n = 0;
2870
28.6k
        const __m128i xmm_zero = _mm_setzero_si128();
2871
28.6k
        GByte *CPL_RESTRICT pabyDstDataPtr =
2872
28.6k
            reinterpret_cast<GByte *>(pDstData);
2873
318k
        for (; n < nWordCount - 7; n += 8)
2874
290k
        {
2875
290k
            __m128i xmm = _mm_loadu_si128(
2876
290k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2877
290k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm, xmm_zero);
2878
290k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm, xmm_zero);
2879
290k
            __m128 xmm0_f = _mm_cvtepi32_ps(xmm0);
2880
290k
            __m128 xmm1_f = _mm_cvtepi32_ps(xmm1);
2881
290k
            _mm_storeu_ps(reinterpret_cast<float *>(pabyDstDataPtr + n * 4),
2882
290k
                          xmm0_f);
2883
290k
            _mm_storeu_ps(
2884
290k
                reinterpret_cast<float *>(pabyDstDataPtr + n * 4 + 16), xmm1_f);
2885
290k
        }
2886
28.6k
#if defined(__clang__)
2887
28.6k
#pragma clang loop vectorize(disable)
2888
28.6k
#endif
2889
147k
        for (; n < nWordCount; n++)
2890
119k
        {
2891
119k
            pDstData[n] = pSrcData[n];
2892
119k
        }
2893
28.6k
    }
2894
2.74M
    else
2895
2.74M
    {
2896
2.74M
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2897
2.74M
                              nDstPixelStride, nWordCount);
2898
2.74M
    }
2899
2.77M
}
2900
2901
template <>
2902
CPL_NOINLINE void GDALCopyWordsT(const int16_t *const CPL_RESTRICT pSrcData,
2903
                                 int nSrcPixelStride,
2904
                                 float *const CPL_RESTRICT pDstData,
2905
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2906
1.78M
{
2907
1.78M
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2908
1.42M
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2909
1.42M
    {
2910
1.42M
        decltype(nWordCount) n = 0;
2911
1.42M
        GByte *CPL_RESTRICT pabyDstDataPtr =
2912
1.42M
            reinterpret_cast<GByte *>(pDstData);
2913
1.92M
        for (; n < nWordCount - 7; n += 8)
2914
502k
        {
2915
502k
            __m128i xmm = _mm_loadu_si128(
2916
502k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2917
502k
            const auto sign = _mm_srai_epi16(xmm, 15);
2918
502k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm, sign);
2919
502k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm, sign);
2920
502k
            __m128 xmm0_f = _mm_cvtepi32_ps(xmm0);
2921
502k
            __m128 xmm1_f = _mm_cvtepi32_ps(xmm1);
2922
502k
            _mm_storeu_ps(reinterpret_cast<float *>(pabyDstDataPtr + n * 4),
2923
502k
                          xmm0_f);
2924
502k
            _mm_storeu_ps(
2925
502k
                reinterpret_cast<float *>(pabyDstDataPtr + n * 4 + 16), xmm1_f);
2926
502k
        }
2927
1.42M
#if defined(__clang__)
2928
1.42M
#pragma clang loop vectorize(disable)
2929
1.42M
#endif
2930
4.48M
        for (; n < nWordCount; n++)
2931
3.06M
        {
2932
3.06M
            pDstData[n] = pSrcData[n];
2933
3.06M
        }
2934
1.42M
    }
2935
361k
    else
2936
361k
    {
2937
361k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2938
361k
                              nDstPixelStride, nWordCount);
2939
361k
    }
2940
1.78M
}
2941
2942
template <>
2943
CPL_NOINLINE void GDALCopyWordsT(const uint16_t *const CPL_RESTRICT pSrcData,
2944
                                 int nSrcPixelStride,
2945
                                 double *const CPL_RESTRICT pDstData,
2946
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
2947
207k
{
2948
207k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
2949
983
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
2950
983
    {
2951
983
        decltype(nWordCount) n = 0;
2952
983
        const __m128i xmm_zero = _mm_setzero_si128();
2953
983
        GByte *CPL_RESTRICT pabyDstDataPtr =
2954
983
            reinterpret_cast<GByte *>(pDstData);
2955
49.5k
        for (; n < nWordCount - 7; n += 8)
2956
48.5k
        {
2957
48.5k
            __m128i xmm = _mm_loadu_si128(
2958
48.5k
                reinterpret_cast<const __m128i *>(pSrcData + n));
2959
48.5k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm, xmm_zero);
2960
48.5k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm, xmm_zero);
2961
2962
48.5k
            __m128d xmm0_low_d = _mm_cvtepi32_pd(xmm0);
2963
48.5k
            __m128d xmm1_low_d = _mm_cvtepi32_pd(xmm1);
2964
48.5k
            xmm0 = _mm_srli_si128(xmm0, 8);
2965
48.5k
            xmm1 = _mm_srli_si128(xmm1, 8);
2966
48.5k
            __m128d xmm0_high_d = _mm_cvtepi32_pd(xmm0);
2967
48.5k
            __m128d xmm1_high_d = _mm_cvtepi32_pd(xmm1);
2968
2969
48.5k
            _mm_storeu_pd(reinterpret_cast<double *>(pabyDstDataPtr + n * 8),
2970
48.5k
                          xmm0_low_d);
2971
48.5k
            _mm_storeu_pd(
2972
48.5k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 16),
2973
48.5k
                xmm0_high_d);
2974
48.5k
            _mm_storeu_pd(
2975
48.5k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 32),
2976
48.5k
                xmm1_low_d);
2977
48.5k
            _mm_storeu_pd(
2978
48.5k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 48),
2979
48.5k
                xmm1_high_d);
2980
48.5k
        }
2981
983
#if defined(__clang__)
2982
983
#pragma clang loop vectorize(disable)
2983
983
#endif
2984
2.02k
        for (; n < nWordCount; n++)
2985
1.04k
        {
2986
1.04k
            pDstData[n] = pSrcData[n];
2987
1.04k
        }
2988
983
    }
2989
206k
    else
2990
206k
    {
2991
206k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
2992
206k
                              nDstPixelStride, nWordCount);
2993
206k
    }
2994
207k
}
2995
2996
template <>
2997
CPL_NOINLINE void GDALCopyWordsT(const int16_t *const CPL_RESTRICT pSrcData,
2998
                                 int nSrcPixelStride,
2999
                                 double *const CPL_RESTRICT pDstData,
3000
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3001
35.2k
{
3002
35.2k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
3003
35.2k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
3004
35.2k
    {
3005
35.2k
        decltype(nWordCount) n = 0;
3006
35.2k
        GByte *CPL_RESTRICT pabyDstDataPtr =
3007
35.2k
            reinterpret_cast<GByte *>(pDstData);
3008
100k
        for (; n < nWordCount - 7; n += 8)
3009
65.3k
        {
3010
65.3k
            __m128i xmm = _mm_loadu_si128(
3011
65.3k
                reinterpret_cast<const __m128i *>(pSrcData + n));
3012
65.3k
            const auto sign = _mm_srai_epi16(xmm, 15);
3013
65.3k
            __m128i xmm0 = _mm_unpacklo_epi16(xmm, sign);
3014
65.3k
            __m128i xmm1 = _mm_unpackhi_epi16(xmm, sign);
3015
3016
65.3k
            __m128d xmm0_low_d = _mm_cvtepi32_pd(xmm0);
3017
65.3k
            __m128d xmm1_low_d = _mm_cvtepi32_pd(xmm1);
3018
65.3k
            xmm0 = _mm_srli_si128(xmm0, 8);
3019
65.3k
            xmm1 = _mm_srli_si128(xmm1, 8);
3020
65.3k
            __m128d xmm0_high_d = _mm_cvtepi32_pd(xmm0);
3021
65.3k
            __m128d xmm1_high_d = _mm_cvtepi32_pd(xmm1);
3022
3023
65.3k
            _mm_storeu_pd(reinterpret_cast<double *>(pabyDstDataPtr + n * 8),
3024
65.3k
                          xmm0_low_d);
3025
65.3k
            _mm_storeu_pd(
3026
65.3k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 16),
3027
65.3k
                xmm0_high_d);
3028
65.3k
            _mm_storeu_pd(
3029
65.3k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 32),
3030
65.3k
                xmm1_low_d);
3031
65.3k
            _mm_storeu_pd(
3032
65.3k
                reinterpret_cast<double *>(pabyDstDataPtr + n * 8 + 48),
3033
65.3k
                xmm1_high_d);
3034
65.3k
        }
3035
35.2k
#if defined(__clang__)
3036
35.2k
#pragma clang loop vectorize(disable)
3037
35.2k
#endif
3038
105k
        for (; n < nWordCount; n++)
3039
70.6k
        {
3040
70.6k
            pDstData[n] = pSrcData[n];
3041
70.6k
        }
3042
35.2k
    }
3043
2
    else
3044
2
    {
3045
2
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
3046
2
                              nDstPixelStride, nWordCount);
3047
2
    }
3048
35.2k
}
3049
3050
// ---- AVX2 helpers for int32 narrowing (runtime dispatch) ----
3051
3052
#if defined(HAVE_AVX2_DISPATCH)
3053
#if !defined(_MSC_VER)
3054
__attribute__((target("avx2")))
3055
#endif
3056
static void GDALCopyWordsInt32ToUInt8_AVX2(const int32_t *CPL_RESTRICT pSrc,
3057
                                           uint8_t *CPL_RESTRICT pDst,
3058
                                           GPtrDiff_t nWordCount)
3059
156k
{
3060
156k
    const __m256i permuteIdx = _mm256_setr_epi32(0, 4, 1, 5, 2, 6, 3, 7);
3061
156k
    GPtrDiff_t n = 0;
3062
156k
    for (; n < nWordCount - 31; n += 32)
3063
0
    {
3064
0
        __m256i v0 =
3065
0
            _mm256_loadu_si256(reinterpret_cast<const __m256i *>(pSrc + n));
3066
0
        __m256i v1 =
3067
0
            _mm256_loadu_si256(reinterpret_cast<const __m256i *>(pSrc + n + 8));
3068
0
        __m256i v2 = _mm256_loadu_si256(
3069
0
            reinterpret_cast<const __m256i *>(pSrc + n + 16));
3070
0
        __m256i v3 = _mm256_loadu_si256(
3071
0
            reinterpret_cast<const __m256i *>(pSrc + n + 24));
3072
        // Clamp to [0, 255]
3073
        // Pack int32 -> int16 -> uint8, then fix cross-lane ordering
3074
0
        __m256i ab16 = _mm256_packs_epi32(v0, v1);
3075
0
        __m256i cd16 = _mm256_packs_epi32(v2, v3);
3076
0
        __m256i bytes = _mm256_packus_epi16(ab16, cd16);
3077
0
        bytes = _mm256_permutevar8x32_epi32(bytes, permuteIdx);
3078
0
        _mm256_storeu_si256(reinterpret_cast<__m256i *>(pDst + n), bytes);
3079
0
    }
3080
156k
#if defined(__clang__)
3081
156k
#pragma clang loop vectorize(disable)
3082
156k
#endif
3083
350k
    for (; n < nWordCount; n++)
3084
193k
    {
3085
193k
        pDst[n] = static_cast<uint8_t>(std::clamp(pSrc[n], 0, 255));
3086
193k
    }
3087
156k
}
3088
3089
#if !defined(_MSC_VER)
3090
__attribute__((target("avx2")))
3091
#endif
3092
static void GDALCopyWordsInt32ToUInt16_AVX2(const int32_t *CPL_RESTRICT pSrc,
3093
                                            uint16_t *CPL_RESTRICT pDst,
3094
                                            GPtrDiff_t nWordCount)
3095
0
{
3096
    // _mm256_packus_epi32(v0, v1) produces per-lane interleaved result:
3097
    //   [v0_lo4, v1_lo4, v0_hi4, v1_hi4] (in uint16 pairs per 32-bit lane)
3098
    // Permute to deinterleave: all v0 values first, then all v1 values
3099
0
    const __m256i permuteIdx = _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7);
3100
0
    GPtrDiff_t n = 0;
3101
0
    for (; n < nWordCount - 15; n += 16)
3102
0
    {
3103
0
        __m256i v0 =
3104
0
            _mm256_loadu_si256(reinterpret_cast<const __m256i *>(pSrc + n));
3105
0
        __m256i v1 =
3106
0
            _mm256_loadu_si256(reinterpret_cast<const __m256i *>(pSrc + n + 8));
3107
        // Clamp to [0, 65535]: _mm256_packus_epi32 saturates uint
3108
0
        __m256i packed = _mm256_packus_epi32(v0, v1);
3109
        // Fix cross-lane interleave from packus
3110
0
        packed = _mm256_permutevar8x32_epi32(packed, permuteIdx);
3111
0
        _mm256_storeu_si256(reinterpret_cast<__m256i *>(pDst + n), packed);
3112
0
    }
3113
0
#if defined(__clang__)
3114
0
#pragma clang loop vectorize(disable)
3115
0
#endif
3116
0
    for (; n < nWordCount; n++)
3117
0
    {
3118
0
        pDst[n] = static_cast<uint16_t>(std::clamp(pSrc[n], 0, 65535));
3119
0
    }
3120
0
}
3121
#endif  // HAVE_AVX2_DISPATCH
3122
3123
// ---- int32 -> uint8 with clamping to [0, 255] ----
3124
template <>
3125
CPL_NOINLINE void GDALCopyWordsT(const int32_t *const CPL_RESTRICT pSrcData,
3126
                                 int nSrcPixelStride,
3127
                                 uint8_t *const CPL_RESTRICT pDstData,
3128
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3129
159k
{
3130
159k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
3131
159k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
3132
156k
    {
3133
156k
#if defined(HAVE_AVX2_DISPATCH)
3134
156k
        if (CPLHaveRuntimeAVX2())
3135
156k
        {
3136
156k
            GDALCopyWordsInt32ToUInt8_AVX2(pSrcData, pDstData, nWordCount);
3137
156k
            return;
3138
156k
        }
3139
0
#endif
3140
3141
        // SSE2 path: 16 pixels per iteration
3142
0
        decltype(nWordCount) n = 0;
3143
0
        for (; n < nWordCount - 15; n += 16)
3144
0
        {
3145
0
            __m128i v0 = _mm_loadu_si128(
3146
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
3147
0
            __m128i v1 = _mm_loadu_si128(
3148
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 4));
3149
0
            __m128i v2 = _mm_loadu_si128(
3150
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
3151
0
            __m128i v3 = _mm_loadu_si128(
3152
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 12));
3153
            // Pack int32->int16 with signed saturation to [-32768,32767] range
3154
0
            __m128i lo16 = _mm_packs_epi32(v0, v1);
3155
0
            __m128i hi16 = _mm_packs_epi32(v2, v3);
3156
            // Pack int16->uint8 with unsigned saturation to [0,255] range
3157
0
            __m128i bytes = _mm_packus_epi16(lo16, hi16);
3158
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n), bytes);
3159
0
        }
3160
0
#if defined(__clang__)
3161
0
#pragma clang loop vectorize(disable)
3162
0
#endif
3163
0
        for (; n < nWordCount; n++)
3164
0
        {
3165
0
            pDstData[n] = static_cast<uint8_t>(std::clamp(pSrcData[n], 0, 255));
3166
0
        }
3167
0
    }
3168
2.30k
    else
3169
2.30k
    {
3170
2.30k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
3171
2.30k
                              nDstPixelStride, nWordCount);
3172
2.30k
    }
3173
159k
}
3174
3175
// ---- int32 -> uint16 with clamping to [0, 65535] ----
3176
template <>
3177
CPL_NOINLINE void GDALCopyWordsT(const int32_t *const CPL_RESTRICT pSrcData,
3178
                                 int nSrcPixelStride,
3179
                                 uint16_t *const CPL_RESTRICT pDstData,
3180
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3181
0
{
3182
0
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
3183
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
3184
0
    {
3185
0
#if defined(HAVE_AVX2_DISPATCH)
3186
0
        if (CPLHaveRuntimeAVX2())
3187
0
        {
3188
0
            GDALCopyWordsInt32ToUInt16_AVX2(pSrcData, pDstData, nWordCount);
3189
0
            return;
3190
0
        }
3191
0
#endif
3192
0
        decltype(nWordCount) n = 0;
3193
0
        for (; n < nWordCount - 15; n += 16)
3194
0
        {
3195
0
            __m128i v0 = _mm_loadu_si128(
3196
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
3197
0
            __m128i v1 = _mm_loadu_si128(
3198
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 4));
3199
0
            __m128i v2 = _mm_loadu_si128(
3200
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
3201
0
            __m128i v3 = _mm_loadu_si128(
3202
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 12));
3203
0
            const auto packed_lo = GDAL_mm_packus_epi32(v0, v1);
3204
0
            const auto packed_hi = GDAL_mm_packus_epi32(v2, v3);
3205
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n),
3206
0
                             packed_lo);
3207
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 8),
3208
0
                             packed_hi);
3209
0
        }
3210
0
#if defined(__clang__)
3211
0
#pragma clang loop vectorize(disable)
3212
0
#endif
3213
0
        for (; n < nWordCount; n++)
3214
0
        {
3215
0
            pDstData[n] =
3216
0
                static_cast<uint16_t>(std::clamp(pSrcData[n], 0, 65535));
3217
0
        }
3218
0
    }
3219
0
    else
3220
0
    {
3221
0
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
3222
0
                              nDstPixelStride, nWordCount);
3223
0
    }
3224
0
}
3225
3226
// ---- int32 -> int16 with clamping to [-32768, 32767] ----
3227
template <>
3228
CPL_NOINLINE void GDALCopyWordsT(const int32_t *const CPL_RESTRICT pSrcData,
3229
                                 int nSrcPixelStride,
3230
                                 int16_t *const CPL_RESTRICT pDstData,
3231
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3232
313
{
3233
313
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
3234
0
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
3235
0
    {
3236
        // SSE2 path: 16 pixels per iteration
3237
0
        decltype(nWordCount) n = 0;
3238
0
        for (; n < nWordCount - 15; n += 16)
3239
0
        {
3240
0
            __m128i v0 = _mm_loadu_si128(
3241
0
                reinterpret_cast<const __m128i *>(pSrcData + n));
3242
0
            __m128i v1 = _mm_loadu_si128(
3243
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 4));
3244
0
            __m128i v2 = _mm_loadu_si128(
3245
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
3246
0
            __m128i v3 = _mm_loadu_si128(
3247
0
                reinterpret_cast<const __m128i *>(pSrcData + n + 12));
3248
            // Pack int32->int16 with signed saturation to [-32768,32767] range
3249
0
            __m128i packed_lo = _mm_packs_epi32(v0, v1);
3250
0
            __m128i packed_hi = _mm_packs_epi32(v2, v3);
3251
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n),
3252
0
                             packed_lo);
3253
0
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 8),
3254
0
                             packed_hi);
3255
0
        }
3256
0
#if defined(__clang__)
3257
0
#pragma clang loop vectorize(disable)
3258
0
#endif
3259
0
        for (; n < nWordCount; n++)
3260
0
        {
3261
0
            pDstData[n] =
3262
0
                static_cast<int16_t>(std::clamp(pSrcData[n], -32768, 32767));
3263
0
        }
3264
0
    }
3265
313
    else
3266
313
    {
3267
313
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
3268
313
                              nDstPixelStride, nWordCount);
3269
313
    }
3270
313
}
3271
3272
// ---- int16 -> uint8 with clamping to [0, 255] ----
3273
template <>
3274
CPL_NOINLINE void GDALCopyWordsT(const int16_t *const CPL_RESTRICT pSrcData,
3275
                                 int nSrcPixelStride,
3276
                                 uint8_t *const CPL_RESTRICT pDstData,
3277
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3278
3.34k
{
3279
3.34k
    if (nSrcPixelStride == static_cast<int>(sizeof(*pSrcData)) &&
3280
3.30k
        nDstPixelStride == static_cast<int>(sizeof(*pDstData)))
3281
1.28k
    {
3282
        // SSE2 path: 32 pixels per iteration
3283
1.28k
        decltype(nWordCount) n = 0;
3284
1.51k
        for (; n < nWordCount - 31; n += 32)
3285
238
        {
3286
238
            __m128i v0 = _mm_loadu_si128(
3287
238
                reinterpret_cast<const __m128i *>(pSrcData + n));
3288
238
            __m128i v1 = _mm_loadu_si128(
3289
238
                reinterpret_cast<const __m128i *>(pSrcData + n + 8));
3290
238
            __m128i v2 = _mm_loadu_si128(
3291
238
                reinterpret_cast<const __m128i *>(pSrcData + n + 16));
3292
238
            __m128i v3 = _mm_loadu_si128(
3293
238
                reinterpret_cast<const __m128i *>(pSrcData + n + 24));
3294
            // Pack int16->uint8 with unsigned saturation to [0, 255] range
3295
238
            __m128i packed_lo = _mm_packus_epi16(v0, v1);
3296
238
            __m128i packed_hi = _mm_packus_epi16(v2, v3);
3297
238
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n),
3298
238
                             packed_lo);
3299
238
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDstData + n + 16),
3300
238
                             packed_hi);
3301
238
        }
3302
1.28k
#if defined(__clang__)
3303
1.28k
#pragma clang loop vectorize(disable)
3304
1.28k
#endif
3305
7.65k
        for (; n < nWordCount; n++)
3306
6.37k
        {
3307
6.37k
            pDstData[n] =
3308
6.37k
                static_cast<uint8_t>(std::clamp<int>(pSrcData[n], 0, 255));
3309
6.37k
        }
3310
1.28k
    }
3311
2.06k
    else
3312
2.06k
    {
3313
2.06k
        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride, pDstData,
3314
2.06k
                              nDstPixelStride, nWordCount);
3315
2.06k
    }
3316
3.34k
}
3317
3318
#endif  // HAVE_SSE2
3319
3320
template <>
3321
CPL_NOINLINE void GDALCopyWordsT(const double *const CPL_RESTRICT pSrcData,
3322
                                 int nSrcPixelStride,
3323
                                 GByte *const CPL_RESTRICT pDstData,
3324
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3325
14.6M
{
3326
14.6M
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3327
14.6M
                            nDstPixelStride, nWordCount);
3328
14.6M
}
3329
3330
template <>
3331
CPL_NOINLINE void GDALCopyWordsT(const double *const CPL_RESTRICT pSrcData,
3332
                                 int nSrcPixelStride,
3333
                                 GUInt16 *const CPL_RESTRICT pDstData,
3334
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3335
14.2M
{
3336
14.2M
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3337
14.2M
                            nDstPixelStride, nWordCount);
3338
14.2M
}
3339
3340
template <>
3341
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3342
                                 int nSrcPixelStride,
3343
                                 double *const CPL_RESTRICT pDstData,
3344
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3345
24.1M
{
3346
24.1M
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3347
24.1M
                            nDstPixelStride, nWordCount);
3348
24.1M
}
3349
3350
template <>
3351
CPL_NOINLINE void GDALCopyWordsT(const double *const CPL_RESTRICT pSrcData,
3352
                                 int nSrcPixelStride,
3353
                                 float *const CPL_RESTRICT pDstData,
3354
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3355
859k
{
3356
859k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3357
859k
                            nDstPixelStride, nWordCount);
3358
859k
}
3359
3360
template <>
3361
CPL_NOINLINE void GDALCopyWordsT(const GFloat16 *const CPL_RESTRICT pSrcData,
3362
                                 int nSrcPixelStride,
3363
                                 float *const CPL_RESTRICT pDstData,
3364
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3365
1.58M
{
3366
1.58M
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3367
1.58M
                            nDstPixelStride, nWordCount);
3368
1.58M
}
3369
3370
template <>
3371
CPL_NOINLINE void GDALCopyWordsT(const GFloat16 *const CPL_RESTRICT pSrcData,
3372
                                 int nSrcPixelStride,
3373
                                 double *const CPL_RESTRICT pDstData,
3374
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3375
277k
{
3376
277k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3377
277k
                            nDstPixelStride, nWordCount);
3378
277k
}
3379
3380
template <>
3381
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3382
                                 int nSrcPixelStride,
3383
                                 GByte *const CPL_RESTRICT pDstData,
3384
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3385
7.09k
{
3386
7.09k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3387
7.09k
                            nDstPixelStride, nWordCount);
3388
7.09k
}
3389
3390
template <>
3391
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3392
                                 int nSrcPixelStride,
3393
                                 GInt8 *const CPL_RESTRICT pDstData,
3394
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3395
1.98k
{
3396
1.98k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3397
1.98k
                            nDstPixelStride, nWordCount);
3398
1.98k
}
3399
3400
template <>
3401
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3402
                                 int nSrcPixelStride,
3403
                                 GInt16 *const CPL_RESTRICT pDstData,
3404
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3405
31.4k
{
3406
31.4k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3407
31.4k
                            nDstPixelStride, nWordCount);
3408
31.4k
}
3409
3410
template <>
3411
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3412
                                 int nSrcPixelStride,
3413
                                 GUInt16 *const CPL_RESTRICT pDstData,
3414
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3415
1.08k
{
3416
1.08k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3417
1.08k
                            nDstPixelStride, nWordCount);
3418
1.08k
}
3419
3420
template <>
3421
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3422
                                 int nSrcPixelStride,
3423
                                 GInt32 *const CPL_RESTRICT pDstData,
3424
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3425
484
{
3426
484
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3427
484
                            nDstPixelStride, nWordCount);
3428
484
}
3429
3430
template <>
3431
CPL_NOINLINE void GDALCopyWordsT(const float *const CPL_RESTRICT pSrcData,
3432
                                 int nSrcPixelStride,
3433
                                 GFloat16 *const CPL_RESTRICT pDstData,
3434
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3435
0
{
3436
0
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3437
0
                            nDstPixelStride, nWordCount);
3438
0
}
3439
3440
template <>
3441
CPL_NOINLINE void GDALCopyWordsT(const double *const CPL_RESTRICT pSrcData,
3442
                                 int nSrcPixelStride,
3443
                                 GFloat16 *const CPL_RESTRICT pDstData,
3444
                                 int nDstPixelStride, GPtrDiff_t nWordCount)
3445
20.9k
{
3446
20.9k
    GDALCopyWordsT_8atatime(pSrcData, nSrcPixelStride, pDstData,
3447
20.9k
                            nDstPixelStride, nWordCount);
3448
20.9k
}
3449
3450
/************************************************************************/
3451
/*                       GDALCopyWordsComplexT()                        */
3452
/************************************************************************/
3453
/**
3454
 * Template function, used to copy data from pSrcData into buffer
3455
 * pDstData, with stride nSrcPixelStride in the source data and
3456
 * stride nDstPixelStride in the destination data. Deals with the
3457
 * complex case, where input is complex and output is complex.
3458
 *
3459
 * @param pSrcData the source data buffer
3460
 * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
3461
 *                      of interest.
3462
 * @param pDstData the destination buffer.
3463
 * @param nDstPixelStride the stride in the buffer pDstData for pixels of
3464
 *                      interest.
3465
 * @param nWordCount the total number of pixel words to copy
3466
 *
3467
 */
3468
template <class Tin, class Tout>
3469
inline void GDALCopyWordsComplexT(const Tin *const CPL_RESTRICT pSrcData,
3470
                                  int nSrcPixelStride,
3471
                                  Tout *const CPL_RESTRICT pDstData,
3472
                                  int nDstPixelStride, GPtrDiff_t nWordCount)
3473
360k
{
3474
360k
    decltype(nWordCount) nDstOffset = 0;
3475
360k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
360k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
15.9M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
15.6M
    {
3480
15.6M
        const Tin *const pPixelIn =
3481
15.6M
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
15.6M
        Tout *const pPixelOut =
3483
15.6M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
15.6M
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
15.6M
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
15.6M
        nDstOffset += nDstPixelStride;
3489
15.6M
    }
3490
360k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned char, short>(unsigned char const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned char, int>(unsigned char const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned char, cpl::Float16>(unsigned char const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned char, float>(unsigned char const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned char, double>(unsigned char const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<signed char, short>(signed char const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<signed char, int>(signed char const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<signed char, cpl::Float16>(signed char const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<signed char, float>(signed char const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<signed char, double>(signed char const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned short, short>(unsigned short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned short, int>(unsigned short const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned short, cpl::Float16>(unsigned short const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned short, float>(unsigned short const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned short, double>(unsigned short const*, int, double*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<short, short>(short const*, int, short*, int, long long)
Line
Count
Source
3473
8.36k
{
3474
8.36k
    decltype(nWordCount) nDstOffset = 0;
3475
8.36k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
8.36k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
206k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
198k
    {
3480
198k
        const Tin *const pPixelIn =
3481
198k
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
198k
        Tout *const pPixelOut =
3483
198k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
198k
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
198k
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
198k
        nDstOffset += nDstPixelStride;
3489
198k
    }
3490
8.36k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<short, int>(short const*, int, int*, int, long long)
Line
Count
Source
3473
119k
{
3474
119k
    decltype(nWordCount) nDstOffset = 0;
3475
119k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
119k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
8.85M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
8.73M
    {
3480
8.73M
        const Tin *const pPixelIn =
3481
8.73M
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
8.73M
        Tout *const pPixelOut =
3483
8.73M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
8.73M
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
8.73M
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
8.73M
        nDstOffset += nDstPixelStride;
3489
8.73M
    }
3490
119k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<short, cpl::Float16>(short const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<short, float>(short const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<short, double>(short const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned int, short>(unsigned int const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned int, int>(unsigned int const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned int, cpl::Float16>(unsigned int const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned int, float>(unsigned int const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned int, double>(unsigned int const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<int, short>(int const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<int, int>(int const*, int, int*, int, long long)
Line
Count
Source
3473
5.68k
{
3474
5.68k
    decltype(nWordCount) nDstOffset = 0;
3475
5.68k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
5.68k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
53.5k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
47.8k
    {
3480
47.8k
        const Tin *const pPixelIn =
3481
47.8k
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
47.8k
        Tout *const pPixelOut =
3483
47.8k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
47.8k
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
47.8k
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
47.8k
        nDstOffset += nDstPixelStride;
3489
47.8k
    }
3490
5.68k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<int, cpl::Float16>(int const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<int, float>(int const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<int, double>(int const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned long, short>(unsigned long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned long, int>(unsigned long const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned long, cpl::Float16>(unsigned long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned long, float>(unsigned long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<unsigned long, double>(unsigned long const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<long, short>(long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<long, int>(long const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<long, cpl::Float16>(long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<long, float>(long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<long, double>(long const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<cpl::Float16, short>(cpl::Float16 const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<cpl::Float16, int>(cpl::Float16 const*, int, int*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<cpl::Float16, cpl::Float16>(cpl::Float16 const*, int, cpl::Float16*, int, long long)
Line
Count
Source
3473
4.39k
{
3474
4.39k
    decltype(nWordCount) nDstOffset = 0;
3475
4.39k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
4.39k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
231k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
227k
    {
3480
227k
        const Tin *const pPixelIn =
3481
227k
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
227k
        Tout *const pPixelOut =
3483
227k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
227k
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
227k
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
227k
        nDstOffset += nDstPixelStride;
3489
227k
    }
3490
4.39k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<cpl::Float16, float>(cpl::Float16 const*, int, float*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<cpl::Float16, double>(cpl::Float16 const*, int, double*, int, long long)
Line
Count
Source
3473
53.2k
{
3474
53.2k
    decltype(nWordCount) nDstOffset = 0;
3475
53.2k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
53.2k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
2.09M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
2.04M
    {
3480
2.04M
        const Tin *const pPixelIn =
3481
2.04M
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
2.04M
        Tout *const pPixelOut =
3483
2.04M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
2.04M
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
2.04M
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
2.04M
        nDstOffset += nDstPixelStride;
3489
2.04M
    }
3490
53.2k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<float, short>(float const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<float, int>(float const*, int, int*, int, long long)
Line
Count
Source
3473
20
{
3474
20
    decltype(nWordCount) nDstOffset = 0;
3475
20
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
20
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
40
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
20
    {
3480
20
        const Tin *const pPixelIn =
3481
20
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
20
        Tout *const pPixelOut =
3483
20
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
20
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
20
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
20
        nDstOffset += nDstPixelStride;
3489
20
    }
3490
20
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<float, cpl::Float16>(float const*, int, cpl::Float16*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<float, float>(float const*, int, float*, int, long long)
Line
Count
Source
3473
39.5k
{
3474
39.5k
    decltype(nWordCount) nDstOffset = 0;
3475
39.5k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
39.5k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
487k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
448k
    {
3480
448k
        const Tin *const pPixelIn =
3481
448k
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
448k
        Tout *const pPixelOut =
3483
448k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
448k
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
448k
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
448k
        nDstOffset += nDstPixelStride;
3489
448k
    }
3490
39.5k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<float, double>(float const*, int, double*, int, long long)
Line
Count
Source
3473
109k
{
3474
109k
    decltype(nWordCount) nDstOffset = 0;
3475
109k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
109k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
3.78M
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
3.67M
    {
3480
3.67M
        const Tin *const pPixelIn =
3481
3.67M
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
3.67M
        Tout *const pPixelOut =
3483
3.67M
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
3.67M
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
3.67M
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
3.67M
        nDstOffset += nDstPixelStride;
3489
3.67M
    }
3490
109k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<double, short>(double const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<double, int>(double const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<double, cpl::Float16>(double const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<double, float>(double const*, int, float*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexT<double, double>(double const*, int, double*, int, long long)
Line
Count
Source
3473
20.0k
{
3474
20.0k
    decltype(nWordCount) nDstOffset = 0;
3475
20.0k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3476
20.0k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3477
3478
265k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3479
245k
    {
3480
245k
        const Tin *const pPixelIn =
3481
245k
            reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3482
245k
        Tout *const pPixelOut =
3483
245k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3484
3485
245k
        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
3486
245k
        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
3487
3488
245k
        nDstOffset += nDstPixelStride;
3489
245k
    }
3490
20.0k
}
3491
3492
/************************************************************************/
3493
/*                      GDALCopyWordsComplexOutT()                      */
3494
/************************************************************************/
3495
/**
3496
 * Template function, used to copy data from pSrcData into buffer
3497
 * pDstData, with stride nSrcPixelStride in the source data and
3498
 * stride nDstPixelStride in the destination data. Deals with the
3499
 * case where the value is real coming in, but complex going out.
3500
 *
3501
 * @param pSrcData the source data buffer
3502
 * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
3503
 *                      of interest, in bytes.
3504
 * @param pDstData the destination buffer.
3505
 * @param nDstPixelStride the stride in the buffer pDstData for pixels of
3506
 *                      interest, in bytes.
3507
 * @param nWordCount the total number of pixel words to copy
3508
 *
3509
 */
3510
template <class Tin, class Tout>
3511
inline void GDALCopyWordsComplexOutT(const Tin *const CPL_RESTRICT pSrcData,
3512
                                     int nSrcPixelStride,
3513
                                     Tout *const CPL_RESTRICT pDstData,
3514
                                     int nDstPixelStride, GPtrDiff_t nWordCount)
3515
68.3k
{
3516
68.3k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
68.3k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
68.3k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
68.3k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
433k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
364k
    {
3525
364k
        const Tin tValue =
3526
364k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
364k
        Tout *const pPixelOut =
3528
364k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
364k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
364k
        pPixelOut[1] = tOutZero;
3532
3533
364k
        nDstOffset += nDstPixelStride;
3534
364k
    }
3535
68.3k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned char, short>(unsigned char const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned char, int>(unsigned char const*, int, int*, int, long long)
Line
Count
Source
3515
10
{
3516
10
    decltype(nWordCount) nDstOffset = 0;
3517
3518
10
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
10
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
10
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
20
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
10
    {
3525
10
        const Tin tValue =
3526
10
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
10
        Tout *const pPixelOut =
3528
10
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
10
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
10
        pPixelOut[1] = tOutZero;
3532
3533
10
        nDstOffset += nDstPixelStride;
3534
10
    }
3535
10
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned char, cpl::Float16>(unsigned char const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned char, float>(unsigned char const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned char, double>(unsigned char const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<signed char, short>(signed char const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<signed char, int>(signed char const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<signed char, cpl::Float16>(signed char const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<signed char, float>(signed char const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<signed char, double>(signed char const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned short, short>(unsigned short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned short, int>(unsigned short const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned short, cpl::Float16>(unsigned short const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned short, float>(unsigned short const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned short, double>(unsigned short const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<short, short>(short const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<short, int>(short const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<short, cpl::Float16>(short const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<short, float>(short const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<short, double>(short const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned int, short>(unsigned int const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned int, int>(unsigned int const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned int, cpl::Float16>(unsigned int const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned int, float>(unsigned int const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned int, double>(unsigned int const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<int, short>(int const*, int, short*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<int, int>(int const*, int, int*, int, long long)
Line
Count
Source
3515
23
{
3516
23
    decltype(nWordCount) nDstOffset = 0;
3517
3518
23
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
23
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
23
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
46
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
23
    {
3525
23
        const Tin tValue =
3526
23
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
23
        Tout *const pPixelOut =
3528
23
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
23
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
23
        pPixelOut[1] = tOutZero;
3532
3533
23
        nDstOffset += nDstPixelStride;
3534
23
    }
3535
23
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<int, cpl::Float16>(int const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<int, float>(int const*, int, float*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<int, double>(int const*, int, double*, int, long long)
Line
Count
Source
3515
1.27k
{
3516
1.27k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
1.27k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
1.27k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
1.27k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
299k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
297k
    {
3525
297k
        const Tin tValue =
3526
297k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
297k
        Tout *const pPixelOut =
3528
297k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
297k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
297k
        pPixelOut[1] = tOutZero;
3532
3533
297k
        nDstOffset += nDstPixelStride;
3534
297k
    }
3535
1.27k
}
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned long, short>(unsigned long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned long, int>(unsigned long const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned long, cpl::Float16>(unsigned long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned long, float>(unsigned long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<unsigned long, double>(unsigned long const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<long, short>(long const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<long, int>(long const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<long, cpl::Float16>(long const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<long, float>(long const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<long, double>(long const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<cpl::Float16, short>(cpl::Float16 const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<cpl::Float16, int>(cpl::Float16 const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<cpl::Float16, cpl::Float16>(cpl::Float16 const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<cpl::Float16, float>(cpl::Float16 const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<cpl::Float16, double>(cpl::Float16 const*, int, double*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<float, short>(float const*, int, short*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<float, int>(float const*, int, int*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<float, cpl::Float16>(float const*, int, cpl::Float16*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<float, float>(float const*, int, float*, int, long long)
Unexecuted instantiation: rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<float, double>(float const*, int, double*, int, long long)
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<double, short>(double const*, int, short*, int, long long)
Line
Count
Source
3515
25.4k
{
3516
25.4k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
25.4k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
25.4k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
25.4k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
50.9k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
25.4k
    {
3525
25.4k
        const Tin tValue =
3526
25.4k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
25.4k
        Tout *const pPixelOut =
3528
25.4k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
25.4k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
25.4k
        pPixelOut[1] = tOutZero;
3532
3533
25.4k
        nDstOffset += nDstPixelStride;
3534
25.4k
    }
3535
25.4k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<double, int>(double const*, int, int*, int, long long)
Line
Count
Source
3515
26.3k
{
3516
26.3k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
26.3k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
26.3k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
26.3k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
52.6k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
26.3k
    {
3525
26.3k
        const Tin tValue =
3526
26.3k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
26.3k
        Tout *const pPixelOut =
3528
26.3k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
26.3k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
26.3k
        pPixelOut[1] = tOutZero;
3532
3533
26.3k
        nDstOffset += nDstPixelStride;
3534
26.3k
    }
3535
26.3k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<double, cpl::Float16>(double const*, int, cpl::Float16*, int, long long)
Line
Count
Source
3515
8.86k
{
3516
8.86k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
8.86k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
8.86k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
8.86k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
17.7k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
8.86k
    {
3525
8.86k
        const Tin tValue =
3526
8.86k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
8.86k
        Tout *const pPixelOut =
3528
8.86k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
8.86k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
8.86k
        pPixelOut[1] = tOutZero;
3532
3533
8.86k
        nDstOffset += nDstPixelStride;
3534
8.86k
    }
3535
8.86k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<double, float>(double const*, int, float*, int, long long)
Line
Count
Source
3515
2.40k
{
3516
2.40k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
2.40k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
2.40k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
2.40k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
4.80k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
2.40k
    {
3525
2.40k
        const Tin tValue =
3526
2.40k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
2.40k
        Tout *const pPixelOut =
3528
2.40k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
2.40k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
2.40k
        pPixelOut[1] = tOutZero;
3532
3533
2.40k
        nDstOffset += nDstPixelStride;
3534
2.40k
    }
3535
2.40k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsComplexOutT<double, double>(double const*, int, double*, int, long long)
Line
Count
Source
3515
4.01k
{
3516
4.01k
    decltype(nWordCount) nDstOffset = 0;
3517
3518
4.01k
    const Tout tOutZero = static_cast<Tout>(0);
3519
3520
4.01k
    const char *const pSrcDataPtr = reinterpret_cast<const char *>(pSrcData);
3521
4.01k
    char *const pDstDataPtr = reinterpret_cast<char *>(pDstData);
3522
3523
8.03k
    for (decltype(nWordCount) n = 0; n < nWordCount; n++)
3524
4.01k
    {
3525
4.01k
        const Tin tValue =
3526
4.01k
            *reinterpret_cast<const Tin *>(pSrcDataPtr + n * nSrcPixelStride);
3527
4.01k
        Tout *const pPixelOut =
3528
4.01k
            reinterpret_cast<Tout *>(pDstDataPtr + nDstOffset);
3529
4.01k
        GDALCopyWord(tValue, *pPixelOut);
3530
3531
4.01k
        pPixelOut[1] = tOutZero;
3532
3533
4.01k
        nDstOffset += nDstPixelStride;
3534
4.01k
    }
3535
4.01k
}
3536
3537
/************************************************************************/
3538
/*                         GDALCopyWordsFromT()                         */
3539
/************************************************************************/
3540
/**
3541
 * Template driver function. Given the input type T, call the appropriate
3542
 * GDALCopyWordsT function template for the desired output type. You should
3543
 * never call this function directly (call GDALCopyWords instead).
3544
 *
3545
 * @param pSrcData source data buffer
3546
 * @param nSrcPixelStride pixel stride in input buffer, in pixel words
3547
 * @param bInComplex input is complex
3548
 * @param pDstData destination data buffer
3549
 * @param eDstType destination data type
3550
 * @param nDstPixelStride pixel stride in output buffer, in pixel words
3551
 * @param nWordCount number of pixel words to be copied
3552
 */
3553
template <class T>
3554
inline void GDALCopyWordsFromT(const T *const CPL_RESTRICT pSrcData,
3555
                               int nSrcPixelStride, bool bInComplex,
3556
                               void *CPL_RESTRICT pDstData,
3557
                               GDALDataType eDstType, int nDstPixelStride,
3558
                               GPtrDiff_t nWordCount)
3559
256M
{
3560
256M
    switch (eDstType)
3561
256M
    {
3562
15.0M
        case GDT_UInt8:
3563
15.0M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
15.0M
                           static_cast<unsigned char *>(pDstData),
3565
15.0M
                           nDstPixelStride, nWordCount);
3566
15.0M
            break;
3567
195k
        case GDT_Int8:
3568
195k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
195k
                           static_cast<signed char *>(pDstData),
3570
195k
                           nDstPixelStride, nWordCount);
3571
195k
            break;
3572
14.3M
        case GDT_UInt16:
3573
14.3M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
14.3M
                           static_cast<unsigned short *>(pDstData),
3575
14.3M
                           nDstPixelStride, nWordCount);
3576
14.3M
            break;
3577
817k
        case GDT_Int16:
3578
817k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
817k
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
817k
                           nWordCount);
3581
817k
            break;
3582
2.65M
        case GDT_UInt32:
3583
2.65M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
2.65M
                           static_cast<unsigned int *>(pDstData),
3585
2.65M
                           nDstPixelStride, nWordCount);
3586
2.65M
            break;
3587
186M
        case GDT_Int32:
3588
186M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
186M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
186M
                           nWordCount);
3591
186M
            break;
3592
402k
        case GDT_UInt64:
3593
402k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
402k
                           static_cast<std::uint64_t *>(pDstData),
3595
402k
                           nDstPixelStride, nWordCount);
3596
402k
            break;
3597
71.0k
        case GDT_Int64:
3598
71.0k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
71.0k
                           static_cast<std::int64_t *>(pDstData),
3600
71.0k
                           nDstPixelStride, nWordCount);
3601
71.0k
            break;
3602
22.3k
        case GDT_Float16:
3603
22.3k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
22.3k
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
22.3k
                           nWordCount);
3606
22.3k
            break;
3607
11.1M
        case GDT_Float32:
3608
11.1M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
11.1M
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
11.1M
                           nWordCount);
3611
11.1M
            break;
3612
25.4M
        case GDT_Float64:
3613
25.4M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
25.4M
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
25.4M
                           nWordCount);
3616
25.4M
            break;
3617
33.8k
        case GDT_CInt16:
3618
33.8k
            if (bInComplex)
3619
8.36k
            {
3620
8.36k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
8.36k
                                      static_cast<short *>(pDstData),
3622
8.36k
                                      nDstPixelStride, nWordCount);
3623
8.36k
            }
3624
25.4k
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
25.4k
            {
3627
25.4k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
25.4k
                                         static_cast<short *>(pDstData),
3629
25.4k
                                         nDstPixelStride, nWordCount);
3630
25.4k
            }
3631
33.8k
            break;
3632
151k
        case GDT_CInt32:
3633
151k
            if (bInComplex)
3634
124k
            {
3635
124k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
124k
                                      static_cast<int *>(pDstData),
3637
124k
                                      nDstPixelStride, nWordCount);
3638
124k
            }
3639
26.3k
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
26.3k
            {
3642
26.3k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
26.3k
                                         static_cast<int *>(pDstData),
3644
26.3k
                                         nDstPixelStride, nWordCount);
3645
26.3k
            }
3646
151k
            break;
3647
13.2k
        case GDT_CFloat16:
3648
13.2k
            if (bInComplex)
3649
4.39k
            {
3650
4.39k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
4.39k
                                      static_cast<GFloat16 *>(pDstData),
3652
4.39k
                                      nDstPixelStride, nWordCount);
3653
4.39k
            }
3654
8.86k
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
8.86k
            {
3657
8.86k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
8.86k
                                         static_cast<GFloat16 *>(pDstData),
3659
8.86k
                                         nDstPixelStride, nWordCount);
3660
8.86k
            }
3661
13.2k
            break;
3662
41.9k
        case GDT_CFloat32:
3663
41.9k
            if (bInComplex)
3664
39.5k
            {
3665
39.5k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
39.5k
                                      static_cast<float *>(pDstData),
3667
39.5k
                                      nDstPixelStride, nWordCount);
3668
39.5k
            }
3669
2.40k
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
2.40k
            {
3672
2.40k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
2.40k
                                         static_cast<float *>(pDstData),
3674
2.40k
                                         nDstPixelStride, nWordCount);
3675
2.40k
            }
3676
41.9k
            break;
3677
188k
        case GDT_CFloat64:
3678
188k
            if (bInComplex)
3679
183k
            {
3680
183k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
183k
                                      static_cast<double *>(pDstData),
3682
183k
                                      nDstPixelStride, nWordCount);
3683
183k
            }
3684
5.29k
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
5.29k
            {
3687
5.29k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
5.29k
                                         static_cast<double *>(pDstData),
3689
5.29k
                                         nDstPixelStride, nWordCount);
3690
5.29k
            }
3691
188k
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
256M
    }
3696
256M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<unsigned char>(unsigned char const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
176M
{
3560
176M
    switch (eDstType)
3561
176M
    {
3562
0
        case GDT_UInt8:
3563
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
0
                           static_cast<unsigned char *>(pDstData),
3565
0
                           nDstPixelStride, nWordCount);
3566
0
            break;
3567
103
        case GDT_Int8:
3568
103
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
103
                           static_cast<signed char *>(pDstData),
3570
103
                           nDstPixelStride, nWordCount);
3571
103
            break;
3572
81.3k
        case GDT_UInt16:
3573
81.3k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
81.3k
                           static_cast<unsigned short *>(pDstData),
3575
81.3k
                           nDstPixelStride, nWordCount);
3576
81.3k
            break;
3577
346k
        case GDT_Int16:
3578
346k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
346k
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
346k
                           nWordCount);
3581
346k
            break;
3582
3.33k
        case GDT_UInt32:
3583
3.33k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
3.33k
                           static_cast<unsigned int *>(pDstData),
3585
3.33k
                           nDstPixelStride, nWordCount);
3586
3.33k
            break;
3587
172M
        case GDT_Int32:
3588
172M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
172M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
172M
                           nWordCount);
3591
172M
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
4.50k
        case GDT_Int64:
3598
4.50k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
4.50k
                           static_cast<std::int64_t *>(pDstData),
3600
4.50k
                           nDstPixelStride, nWordCount);
3601
4.50k
            break;
3602
1.35k
        case GDT_Float16:
3603
1.35k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
1.35k
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
1.35k
                           nWordCount);
3606
1.35k
            break;
3607
3.94M
        case GDT_Float32:
3608
3.94M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
3.94M
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
3.94M
                           nWordCount);
3611
3.94M
            break;
3612
146k
        case GDT_Float64:
3613
146k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
146k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
146k
                           nWordCount);
3616
146k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
10
        case GDT_CInt32:
3633
10
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
10
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
10
            {
3642
10
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
10
                                         static_cast<int *>(pDstData),
3644
10
                                         nDstPixelStride, nWordCount);
3645
10
            }
3646
10
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
176M
    }
3696
176M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<signed char>(signed char const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
5.93M
{
3560
5.93M
    switch (eDstType)
3561
5.93M
    {
3562
14.7k
        case GDT_UInt8:
3563
14.7k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
14.7k
                           static_cast<unsigned char *>(pDstData),
3565
14.7k
                           nDstPixelStride, nWordCount);
3566
14.7k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
299k
        case GDT_Int16:
3578
299k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
299k
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
299k
                           nWordCount);
3581
299k
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
5.45M
        case GDT_Int32:
3588
5.45M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
5.45M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
5.45M
                           nWordCount);
3591
5.45M
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
165k
        case GDT_Float32:
3608
165k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
165k
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
165k
                           nWordCount);
3611
165k
            break;
3612
4.59k
        case GDT_Float64:
3613
4.59k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
4.59k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
4.59k
                           nWordCount);
3616
4.59k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
5.93M
    }
3696
5.93M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<unsigned short>(unsigned short const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
5.58M
{
3560
5.58M
    switch (eDstType)
3561
5.58M
    {
3562
235k
        case GDT_UInt8:
3563
235k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
235k
                           static_cast<unsigned char *>(pDstData),
3565
235k
                           nDstPixelStride, nWordCount);
3566
235k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
2.36M
        case GDT_Int32:
3588
2.36M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
2.36M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
2.36M
                           nWordCount);
3591
2.36M
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
2.77M
        case GDT_Float32:
3608
2.77M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
2.77M
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
2.77M
                           nWordCount);
3611
2.77M
            break;
3612
207k
        case GDT_Float64:
3613
207k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
207k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
207k
                           nWordCount);
3616
207k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
5.58M
    }
3696
5.58M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<short>(short const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
5.04M
{
3560
5.04M
    switch (eDstType)
3561
5.04M
    {
3562
3.34k
        case GDT_UInt8:
3563
3.34k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
3.34k
                           static_cast<unsigned char *>(pDstData),
3565
3.34k
                           nDstPixelStride, nWordCount);
3566
3.34k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
3.09M
        case GDT_Int32:
3588
3.09M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
3.09M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
3.09M
                           nWordCount);
3591
3.09M
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
1.78M
        case GDT_Float32:
3608
1.78M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
1.78M
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
1.78M
                           nWordCount);
3611
1.78M
            break;
3612
35.2k
        case GDT_Float64:
3613
35.2k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
35.2k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
35.2k
                           nWordCount);
3616
35.2k
            break;
3617
8.36k
        case GDT_CInt16:
3618
8.36k
            if (bInComplex)
3619
8.36k
            {
3620
8.36k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
8.36k
                                      static_cast<short *>(pDstData),
3622
8.36k
                                      nDstPixelStride, nWordCount);
3623
8.36k
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
8.36k
            break;
3632
119k
        case GDT_CInt32:
3633
119k
            if (bInComplex)
3634
119k
            {
3635
119k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
119k
                                      static_cast<int *>(pDstData),
3637
119k
                                      nDstPixelStride, nWordCount);
3638
119k
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
119k
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
5.04M
    }
3696
5.04M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<unsigned int>(unsigned int const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
1.83M
{
3560
1.83M
    switch (eDstType)
3561
1.83M
    {
3562
3.43k
        case GDT_UInt8:
3563
3.43k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
3.43k
                           static_cast<unsigned char *>(pDstData),
3565
3.43k
                           nDstPixelStride, nWordCount);
3566
3.43k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
60.5k
        case GDT_UInt32:
3583
60.5k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
60.5k
                           static_cast<unsigned int *>(pDstData),
3585
60.5k
                           nDstPixelStride, nWordCount);
3586
60.5k
            break;
3587
1.73M
        case GDT_Int32:
3588
1.73M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
1.73M
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
1.73M
                           nWordCount);
3591
1.73M
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
19.9k
        case GDT_Float32:
3608
19.9k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
19.9k
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
19.9k
                           nWordCount);
3611
19.9k
            break;
3612
14.1k
        case GDT_Float64:
3613
14.1k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
14.1k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
14.1k
                           nWordCount);
3616
14.1k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
1.83M
    }
3696
1.83M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<int>(int const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
538k
{
3560
538k
    switch (eDstType)
3561
538k
    {
3562
159k
        case GDT_UInt8:
3563
159k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
159k
                           static_cast<unsigned char *>(pDstData),
3565
159k
                           nDstPixelStride, nWordCount);
3566
159k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
313
        case GDT_Int16:
3578
313
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
313
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
313
                           nWordCount);
3581
313
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
81.5k
        case GDT_Int32:
3588
81.5k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
81.5k
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
81.5k
                           nWordCount);
3591
81.5k
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
1.45k
        case GDT_Float32:
3608
1.45k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
1.45k
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
1.45k
                           nWordCount);
3611
1.45k
            break;
3612
288k
        case GDT_Float64:
3613
288k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
288k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
288k
                           nWordCount);
3616
288k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
5.70k
        case GDT_CInt32:
3633
5.70k
            if (bInComplex)
3634
5.68k
            {
3635
5.68k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
5.68k
                                      static_cast<int *>(pDstData),
3637
5.68k
                                      nDstPixelStride, nWordCount);
3638
5.68k
            }
3639
23
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
23
            {
3642
23
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
23
                                         static_cast<int *>(pDstData),
3644
23
                                         nDstPixelStride, nWordCount);
3645
23
            }
3646
5.70k
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
1.27k
        case GDT_CFloat64:
3678
1.27k
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
1.27k
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
1.27k
            {
3687
1.27k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
1.27k
                                         static_cast<double *>(pDstData),
3689
1.27k
                                         nDstPixelStride, nWordCount);
3690
1.27k
            }
3691
1.27k
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
538k
    }
3696
538k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<unsigned long>(unsigned long const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
257k
{
3560
257k
    switch (eDstType)
3561
257k
    {
3562
0
        case GDT_UInt8:
3563
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
0
                           static_cast<unsigned char *>(pDstData),
3565
0
                           nDstPixelStride, nWordCount);
3566
0
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
197k
        case GDT_Int32:
3588
197k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
197k
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
197k
                           nWordCount);
3591
197k
            break;
3592
60.0k
        case GDT_UInt64:
3593
60.0k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
60.0k
                           static_cast<std::uint64_t *>(pDstData),
3595
60.0k
                           nDstPixelStride, nWordCount);
3596
60.0k
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
0
        case GDT_Float32:
3608
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
0
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
0
                           nWordCount);
3611
0
            break;
3612
0
        case GDT_Float64:
3613
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
0
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
0
                           nWordCount);
3616
0
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
257k
    }
3696
257k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<long>(long const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
367k
{
3560
367k
    switch (eDstType)
3561
367k
    {
3562
3.46k
        case GDT_UInt8:
3563
3.46k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
3.46k
                           static_cast<unsigned char *>(pDstData),
3565
3.46k
                           nDstPixelStride, nWordCount);
3566
3.46k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
140k
        case GDT_Int32:
3588
140k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
140k
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
140k
                           nWordCount);
3591
140k
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
31.8k
        case GDT_Int64:
3598
31.8k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
31.8k
                           static_cast<std::int64_t *>(pDstData),
3600
31.8k
                           nDstPixelStride, nWordCount);
3601
31.8k
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
0
        case GDT_Float32:
3608
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
0
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
0
                           nWordCount);
3611
0
            break;
3612
192k
        case GDT_Float64:
3613
192k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
192k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
192k
                           nWordCount);
3616
192k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
0
        case GDT_CFloat64:
3678
0
            if (bInComplex)
3679
0
            {
3680
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
0
                                      static_cast<double *>(pDstData),
3682
0
                                      nDstPixelStride, nWordCount);
3683
0
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
0
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
367k
    }
3696
367k
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<cpl::Float16>(cpl::Float16 const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
1.93M
{
3560
1.93M
    switch (eDstType)
3561
1.93M
    {
3562
18.9k
        case GDT_UInt8:
3563
18.9k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
18.9k
                           static_cast<unsigned char *>(pDstData),
3565
18.9k
                           nDstPixelStride, nWordCount);
3566
18.9k
            break;
3567
0
        case GDT_Int8:
3568
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
0
                           static_cast<signed char *>(pDstData),
3570
0
                           nDstPixelStride, nWordCount);
3571
0
            break;
3572
0
        case GDT_UInt16:
3573
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
0
                           static_cast<unsigned short *>(pDstData),
3575
0
                           nDstPixelStride, nWordCount);
3576
0
            break;
3577
0
        case GDT_Int16:
3578
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
0
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
0
                           nWordCount);
3581
0
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
0
        case GDT_Int32:
3588
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
0
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
0
                           nWordCount);
3591
0
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
1.58M
        case GDT_Float32:
3608
1.58M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
1.58M
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
1.58M
                           nWordCount);
3611
1.58M
            break;
3612
277k
        case GDT_Float64:
3613
277k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
277k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
277k
                           nWordCount);
3616
277k
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
0
        case GDT_CInt32:
3633
0
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
0
            break;
3647
4.39k
        case GDT_CFloat16:
3648
4.39k
            if (bInComplex)
3649
4.39k
            {
3650
4.39k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
4.39k
                                      static_cast<GFloat16 *>(pDstData),
3652
4.39k
                                      nDstPixelStride, nWordCount);
3653
4.39k
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
4.39k
            break;
3662
0
        case GDT_CFloat32:
3663
0
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
0
            break;
3677
53.2k
        case GDT_CFloat64:
3678
53.2k
            if (bInComplex)
3679
53.2k
            {
3680
53.2k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
53.2k
                                      static_cast<double *>(pDstData),
3682
53.2k
                                      nDstPixelStride, nWordCount);
3683
53.2k
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
53.2k
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
1.93M
    }
3696
1.93M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<float>(float const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
24.3M
{
3560
24.3M
    switch (eDstType)
3561
24.3M
    {
3562
7.09k
        case GDT_UInt8:
3563
7.09k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
7.09k
                           static_cast<unsigned char *>(pDstData),
3565
7.09k
                           nDstPixelStride, nWordCount);
3566
7.09k
            break;
3567
1.98k
        case GDT_Int8:
3568
1.98k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
1.98k
                           static_cast<signed char *>(pDstData),
3570
1.98k
                           nDstPixelStride, nWordCount);
3571
1.98k
            break;
3572
1.08k
        case GDT_UInt16:
3573
1.08k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
1.08k
                           static_cast<unsigned short *>(pDstData),
3575
1.08k
                           nDstPixelStride, nWordCount);
3576
1.08k
            break;
3577
31.4k
        case GDT_Int16:
3578
31.4k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
31.4k
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
31.4k
                           nWordCount);
3581
31.4k
            break;
3582
0
        case GDT_UInt32:
3583
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
0
                           static_cast<unsigned int *>(pDstData),
3585
0
                           nDstPixelStride, nWordCount);
3586
0
            break;
3587
484
        case GDT_Int32:
3588
484
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
484
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
484
                           nWordCount);
3591
484
            break;
3592
0
        case GDT_UInt64:
3593
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
0
                           static_cast<std::uint64_t *>(pDstData),
3595
0
                           nDstPixelStride, nWordCount);
3596
0
            break;
3597
0
        case GDT_Int64:
3598
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
0
                           static_cast<std::int64_t *>(pDstData),
3600
0
                           nDstPixelStride, nWordCount);
3601
0
            break;
3602
0
        case GDT_Float16:
3603
0
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
0
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
0
                           nWordCount);
3606
0
            break;
3607
20.5k
        case GDT_Float32:
3608
20.5k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
20.5k
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
20.5k
                           nWordCount);
3611
20.5k
            break;
3612
24.1M
        case GDT_Float64:
3613
24.1M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
24.1M
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
24.1M
                           nWordCount);
3616
24.1M
            break;
3617
0
        case GDT_CInt16:
3618
0
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
0
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
0
            {
3627
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
0
                                         static_cast<short *>(pDstData),
3629
0
                                         nDstPixelStride, nWordCount);
3630
0
            }
3631
0
            break;
3632
20
        case GDT_CInt32:
3633
20
            if (bInComplex)
3634
20
            {
3635
20
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
20
                                      static_cast<int *>(pDstData),
3637
20
                                      nDstPixelStride, nWordCount);
3638
20
            }
3639
0
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
0
            {
3642
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
0
                                         static_cast<int *>(pDstData),
3644
0
                                         nDstPixelStride, nWordCount);
3645
0
            }
3646
20
            break;
3647
0
        case GDT_CFloat16:
3648
0
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
0
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
0
            {
3657
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
0
                                         static_cast<GFloat16 *>(pDstData),
3659
0
                                         nDstPixelStride, nWordCount);
3660
0
            }
3661
0
            break;
3662
39.5k
        case GDT_CFloat32:
3663
39.5k
            if (bInComplex)
3664
39.5k
            {
3665
39.5k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
39.5k
                                      static_cast<float *>(pDstData),
3667
39.5k
                                      nDstPixelStride, nWordCount);
3668
39.5k
            }
3669
0
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
0
            {
3672
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
0
                                         static_cast<float *>(pDstData),
3674
0
                                         nDstPixelStride, nWordCount);
3675
0
            }
3676
39.5k
            break;
3677
109k
        case GDT_CFloat64:
3678
109k
            if (bInComplex)
3679
109k
            {
3680
109k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
109k
                                      static_cast<double *>(pDstData),
3682
109k
                                      nDstPixelStride, nWordCount);
3683
109k
            }
3684
0
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
0
            {
3687
0
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
0
                                         static_cast<double *>(pDstData),
3689
0
                                         nDstPixelStride, nWordCount);
3690
0
            }
3691
109k
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
24.3M
    }
3696
24.3M
}
rasterio.cpp:void (anonymous namespace)::GDALCopyWordsFromT<double>(double const*, int, bool, void*, GDALDataType, int, long long)
Line
Count
Source
3559
33.9M
{
3560
33.9M
    switch (eDstType)
3561
33.9M
    {
3562
14.6M
        case GDT_UInt8:
3563
14.6M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3564
14.6M
                           static_cast<unsigned char *>(pDstData),
3565
14.6M
                           nDstPixelStride, nWordCount);
3566
14.6M
            break;
3567
193k
        case GDT_Int8:
3568
193k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3569
193k
                           static_cast<signed char *>(pDstData),
3570
193k
                           nDstPixelStride, nWordCount);
3571
193k
            break;
3572
14.2M
        case GDT_UInt16:
3573
14.2M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3574
14.2M
                           static_cast<unsigned short *>(pDstData),
3575
14.2M
                           nDstPixelStride, nWordCount);
3576
14.2M
            break;
3577
139k
        case GDT_Int16:
3578
139k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3579
139k
                           static_cast<short *>(pDstData), nDstPixelStride,
3580
139k
                           nWordCount);
3581
139k
            break;
3582
2.58M
        case GDT_UInt32:
3583
2.58M
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3584
2.58M
                           static_cast<unsigned int *>(pDstData),
3585
2.58M
                           nDstPixelStride, nWordCount);
3586
2.58M
            break;
3587
634k
        case GDT_Int32:
3588
634k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3589
634k
                           static_cast<int *>(pDstData), nDstPixelStride,
3590
634k
                           nWordCount);
3591
634k
            break;
3592
342k
        case GDT_UInt64:
3593
342k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3594
342k
                           static_cast<std::uint64_t *>(pDstData),
3595
342k
                           nDstPixelStride, nWordCount);
3596
342k
            break;
3597
34.7k
        case GDT_Int64:
3598
34.7k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3599
34.7k
                           static_cast<std::int64_t *>(pDstData),
3600
34.7k
                           nDstPixelStride, nWordCount);
3601
34.7k
            break;
3602
20.9k
        case GDT_Float16:
3603
20.9k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3604
20.9k
                           static_cast<GFloat16 *>(pDstData), nDstPixelStride,
3605
20.9k
                           nWordCount);
3606
20.9k
            break;
3607
859k
        case GDT_Float32:
3608
859k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3609
859k
                           static_cast<float *>(pDstData), nDstPixelStride,
3610
859k
                           nWordCount);
3611
859k
            break;
3612
146k
        case GDT_Float64:
3613
146k
            GDALCopyWordsT(pSrcData, nSrcPixelStride,
3614
146k
                           static_cast<double *>(pDstData), nDstPixelStride,
3615
146k
                           nWordCount);
3616
146k
            break;
3617
25.4k
        case GDT_CInt16:
3618
25.4k
            if (bInComplex)
3619
0
            {
3620
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3621
0
                                      static_cast<short *>(pDstData),
3622
0
                                      nDstPixelStride, nWordCount);
3623
0
            }
3624
25.4k
            else  // input is not complex, so we need to promote to a complex
3625
                  // buffer
3626
25.4k
            {
3627
25.4k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3628
25.4k
                                         static_cast<short *>(pDstData),
3629
25.4k
                                         nDstPixelStride, nWordCount);
3630
25.4k
            }
3631
25.4k
            break;
3632
26.3k
        case GDT_CInt32:
3633
26.3k
            if (bInComplex)
3634
0
            {
3635
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3636
0
                                      static_cast<int *>(pDstData),
3637
0
                                      nDstPixelStride, nWordCount);
3638
0
            }
3639
26.3k
            else  // input is not complex, so we need to promote to a complex
3640
                  // buffer
3641
26.3k
            {
3642
26.3k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3643
26.3k
                                         static_cast<int *>(pDstData),
3644
26.3k
                                         nDstPixelStride, nWordCount);
3645
26.3k
            }
3646
26.3k
            break;
3647
8.86k
        case GDT_CFloat16:
3648
8.86k
            if (bInComplex)
3649
0
            {
3650
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3651
0
                                      static_cast<GFloat16 *>(pDstData),
3652
0
                                      nDstPixelStride, nWordCount);
3653
0
            }
3654
8.86k
            else  // input is not complex, so we need to promote to a complex
3655
                  // buffer
3656
8.86k
            {
3657
8.86k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3658
8.86k
                                         static_cast<GFloat16 *>(pDstData),
3659
8.86k
                                         nDstPixelStride, nWordCount);
3660
8.86k
            }
3661
8.86k
            break;
3662
2.40k
        case GDT_CFloat32:
3663
2.40k
            if (bInComplex)
3664
0
            {
3665
0
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3666
0
                                      static_cast<float *>(pDstData),
3667
0
                                      nDstPixelStride, nWordCount);
3668
0
            }
3669
2.40k
            else  // input is not complex, so we need to promote to a complex
3670
                  // buffer
3671
2.40k
            {
3672
2.40k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3673
2.40k
                                         static_cast<float *>(pDstData),
3674
2.40k
                                         nDstPixelStride, nWordCount);
3675
2.40k
            }
3676
2.40k
            break;
3677
24.0k
        case GDT_CFloat64:
3678
24.0k
            if (bInComplex)
3679
20.0k
            {
3680
20.0k
                GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
3681
20.0k
                                      static_cast<double *>(pDstData),
3682
20.0k
                                      nDstPixelStride, nWordCount);
3683
20.0k
            }
3684
4.01k
            else  // input is not complex, so we need to promote to a complex
3685
                  // buffer
3686
4.01k
            {
3687
4.01k
                GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
3688
4.01k
                                         static_cast<double *>(pDstData),
3689
4.01k
                                         nDstPixelStride, nWordCount);
3690
4.01k
            }
3691
24.0k
            break;
3692
0
        case GDT_Unknown:
3693
0
        case GDT_TypeCount:
3694
0
            CPLAssert(false);
3695
33.9M
    }
3696
33.9M
}
3697
3698
}  // end anonymous namespace
3699
3700
/************************************************************************/
3701
/*                         GDALReplicateWord()                          */
3702
/************************************************************************/
3703
3704
template <class T>
3705
inline void GDALReplicateWordT(void *pDstData, int nDstPixelStride,
3706
                               GPtrDiff_t nWordCount)
3707
11.3M
{
3708
11.3M
    const T valSet = *static_cast<const T *>(pDstData);
3709
11.3M
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
11.3M
    {
3711
11.3M
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
180M
        while (nWordCount >= 4)
3713
169M
        {
3714
169M
            nWordCount -= 4;
3715
169M
            pDstPtr[0] = valSet;
3716
169M
            pDstPtr[1] = valSet;
3717
169M
            pDstPtr[2] = valSet;
3718
169M
            pDstPtr[3] = valSet;
3719
169M
            pDstPtr += 4;
3720
169M
        }
3721
32.5M
        while (nWordCount > 0)
3722
21.1M
        {
3723
21.1M
            --nWordCount;
3724
21.1M
            *pDstPtr = valSet;
3725
21.1M
            pDstPtr++;
3726
21.1M
        }
3727
11.3M
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
11.3M
}
void GDALReplicateWordT<unsigned short>(void*, int, long long)
Line
Count
Source
3707
6.91M
{
3708
6.91M
    const T valSet = *static_cast<const T *>(pDstData);
3709
6.91M
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
6.91M
    {
3711
6.91M
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
49.5M
        while (nWordCount >= 4)
3713
42.6M
        {
3714
42.6M
            nWordCount -= 4;
3715
42.6M
            pDstPtr[0] = valSet;
3716
42.6M
            pDstPtr[1] = valSet;
3717
42.6M
            pDstPtr[2] = valSet;
3718
42.6M
            pDstPtr[3] = valSet;
3719
42.6M
            pDstPtr += 4;
3720
42.6M
        }
3721
21.0M
        while (nWordCount > 0)
3722
14.1M
        {
3723
14.1M
            --nWordCount;
3724
14.1M
            *pDstPtr = valSet;
3725
14.1M
            pDstPtr++;
3726
14.1M
        }
3727
6.91M
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
6.91M
}
void GDALReplicateWordT<short>(void*, int, long long)
Line
Count
Source
3707
224k
{
3708
224k
    const T valSet = *static_cast<const T *>(pDstData);
3709
224k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
224k
    {
3711
224k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
35.7M
        while (nWordCount >= 4)
3713
35.5M
        {
3714
35.5M
            nWordCount -= 4;
3715
35.5M
            pDstPtr[0] = valSet;
3716
35.5M
            pDstPtr[1] = valSet;
3717
35.5M
            pDstPtr[2] = valSet;
3718
35.5M
            pDstPtr[3] = valSet;
3719
35.5M
            pDstPtr += 4;
3720
35.5M
        }
3721
579k
        while (nWordCount > 0)
3722
354k
        {
3723
354k
            --nWordCount;
3724
354k
            *pDstPtr = valSet;
3725
354k
            pDstPtr++;
3726
354k
        }
3727
224k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
224k
}
void GDALReplicateWordT<unsigned int>(void*, int, long long)
Line
Count
Source
3707
2.58M
{
3708
2.58M
    const T valSet = *static_cast<const T *>(pDstData);
3709
2.58M
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
2.58M
    {
3711
2.58M
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
21.8M
        while (nWordCount >= 4)
3713
19.3M
        {
3714
19.3M
            nWordCount -= 4;
3715
19.3M
            pDstPtr[0] = valSet;
3716
19.3M
            pDstPtr[1] = valSet;
3717
19.3M
            pDstPtr[2] = valSet;
3718
19.3M
            pDstPtr[3] = valSet;
3719
19.3M
            pDstPtr += 4;
3720
19.3M
        }
3721
6.57M
        while (nWordCount > 0)
3722
3.98M
        {
3723
3.98M
            --nWordCount;
3724
3.98M
            *pDstPtr = valSet;
3725
3.98M
            pDstPtr++;
3726
3.98M
        }
3727
2.58M
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
2.58M
}
void GDALReplicateWordT<int>(void*, int, long long)
Line
Count
Source
3707
538k
{
3708
538k
    const T valSet = *static_cast<const T *>(pDstData);
3709
538k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
538k
    {
3711
538k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
19.9M
        while (nWordCount >= 4)
3713
19.4M
        {
3714
19.4M
            nWordCount -= 4;
3715
19.4M
            pDstPtr[0] = valSet;
3716
19.4M
            pDstPtr[1] = valSet;
3717
19.4M
            pDstPtr[2] = valSet;
3718
19.4M
            pDstPtr[3] = valSet;
3719
19.4M
            pDstPtr += 4;
3720
19.4M
        }
3721
1.50M
        while (nWordCount > 0)
3722
962k
        {
3723
962k
            --nWordCount;
3724
962k
            *pDstPtr = valSet;
3725
962k
            pDstPtr++;
3726
962k
        }
3727
538k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
538k
}
void GDALReplicateWordT<unsigned long>(void*, int, long long)
Line
Count
Source
3707
304k
{
3708
304k
    const T valSet = *static_cast<const T *>(pDstData);
3709
304k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
304k
    {
3711
304k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
13.0M
        while (nWordCount >= 4)
3713
12.7M
        {
3714
12.7M
            nWordCount -= 4;
3715
12.7M
            pDstPtr[0] = valSet;
3716
12.7M
            pDstPtr[1] = valSet;
3717
12.7M
            pDstPtr[2] = valSet;
3718
12.7M
            pDstPtr[3] = valSet;
3719
12.7M
            pDstPtr += 4;
3720
12.7M
        }
3721
784k
        while (nWordCount > 0)
3722
479k
        {
3723
479k
            --nWordCount;
3724
479k
            *pDstPtr = valSet;
3725
479k
            pDstPtr++;
3726
479k
        }
3727
304k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
304k
}
void GDALReplicateWordT<long>(void*, int, long long)
Line
Count
Source
3707
67.8k
{
3708
67.8k
    const T valSet = *static_cast<const T *>(pDstData);
3709
67.8k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
67.8k
    {
3711
67.8k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
13.1M
        while (nWordCount >= 4)
3713
13.0M
        {
3714
13.0M
            nWordCount -= 4;
3715
13.0M
            pDstPtr[0] = valSet;
3716
13.0M
            pDstPtr[1] = valSet;
3717
13.0M
            pDstPtr[2] = valSet;
3718
13.0M
            pDstPtr[3] = valSet;
3719
13.0M
            pDstPtr += 4;
3720
13.0M
        }
3721
176k
        while (nWordCount > 0)
3722
108k
        {
3723
108k
            --nWordCount;
3724
108k
            *pDstPtr = valSet;
3725
108k
            pDstPtr++;
3726
108k
        }
3727
67.8k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
67.8k
}
void GDALReplicateWordT<cpl::Float16>(void*, int, long long)
Line
Count
Source
3707
19.2k
{
3708
19.2k
    const T valSet = *static_cast<const T *>(pDstData);
3709
19.2k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
19.2k
    {
3711
19.2k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
955k
        while (nWordCount >= 4)
3713
936k
        {
3714
936k
            nWordCount -= 4;
3715
936k
            pDstPtr[0] = valSet;
3716
936k
            pDstPtr[1] = valSet;
3717
936k
            pDstPtr[2] = valSet;
3718
936k
            pDstPtr[3] = valSet;
3719
936k
            pDstPtr += 4;
3720
936k
        }
3721
38.9k
        while (nWordCount > 0)
3722
19.6k
        {
3723
19.6k
            --nWordCount;
3724
19.6k
            *pDstPtr = valSet;
3725
19.6k
            pDstPtr++;
3726
19.6k
        }
3727
19.2k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
19.2k
}
void GDALReplicateWordT<float>(void*, int, long long)
Line
Count
Source
3707
642k
{
3708
642k
    const T valSet = *static_cast<const T *>(pDstData);
3709
642k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
642k
    {
3711
642k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
20.3M
        while (nWordCount >= 4)
3713
19.6M
        {
3714
19.6M
            nWordCount -= 4;
3715
19.6M
            pDstPtr[0] = valSet;
3716
19.6M
            pDstPtr[1] = valSet;
3717
19.6M
            pDstPtr[2] = valSet;
3718
19.6M
            pDstPtr[3] = valSet;
3719
19.6M
            pDstPtr += 4;
3720
19.6M
        }
3721
1.69M
        while (nWordCount > 0)
3722
1.05M
        {
3723
1.05M
            --nWordCount;
3724
1.05M
            *pDstPtr = valSet;
3725
1.05M
            pDstPtr++;
3726
1.05M
        }
3727
642k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
642k
}
void GDALReplicateWordT<double>(void*, int, long long)
Line
Count
Source
3707
64.3k
{
3708
64.3k
    const T valSet = *static_cast<const T *>(pDstData);
3709
64.3k
    if (nDstPixelStride == static_cast<int>(sizeof(T)))
3710
64.3k
    {
3711
64.3k
        T *pDstPtr = static_cast<T *>(pDstData) + 1;
3712
5.88M
        while (nWordCount >= 4)
3713
5.82M
        {
3714
5.82M
            nWordCount -= 4;
3715
5.82M
            pDstPtr[0] = valSet;
3716
5.82M
            pDstPtr[1] = valSet;
3717
5.82M
            pDstPtr[2] = valSet;
3718
5.82M
            pDstPtr[3] = valSet;
3719
5.82M
            pDstPtr += 4;
3720
5.82M
        }
3721
160k
        while (nWordCount > 0)
3722
96.3k
        {
3723
96.3k
            --nWordCount;
3724
96.3k
            *pDstPtr = valSet;
3725
96.3k
            pDstPtr++;
3726
96.3k
        }
3727
64.3k
    }
3728
0
    else
3729
0
    {
3730
0
        GByte *pabyDstPtr = static_cast<GByte *>(pDstData) + nDstPixelStride;
3731
0
        while (nWordCount > 0)
3732
0
        {
3733
0
            --nWordCount;
3734
0
            *reinterpret_cast<T *>(pabyDstPtr) = valSet;
3735
0
            pabyDstPtr += nDstPixelStride;
3736
0
        }
3737
0
    }
3738
64.3k
}
3739
3740
static void GDALReplicateWord(const void *CPL_RESTRICT pSrcData,
3741
                              GDALDataType eSrcType,
3742
                              void *CPL_RESTRICT pDstData,
3743
                              GDALDataType eDstType, int nDstPixelStride,
3744
                              GPtrDiff_t nWordCount)
3745
26.7M
{
3746
    /* -----------------------------------------------------------------------
3747
     */
3748
    /* Special case when the source data is always the same value */
3749
    /* (for VRTSourcedRasterBand::IRasterIO and
3750
     * VRTDerivedRasterBand::IRasterIO*/
3751
    /*  for example) */
3752
    /* -----------------------------------------------------------------------
3753
     */
3754
    // Let the general translation case do the necessary conversions
3755
    // on the first destination element.
3756
26.7M
    GDALCopyWords64(pSrcData, eSrcType, 0, pDstData, eDstType, 0, 1);
3757
3758
    // Now copy the first element to the nWordCount - 1 following destination
3759
    // elements.
3760
26.7M
    nWordCount--;
3761
26.7M
    GByte *pabyDstWord = reinterpret_cast<GByte *>(pDstData) + nDstPixelStride;
3762
3763
26.7M
    switch (eDstType)
3764
26.7M
    {
3765
15.1M
        case GDT_UInt8:
3766
15.3M
        case GDT_Int8:
3767
15.3M
        {
3768
15.3M
            if (nDstPixelStride == 1)
3769
15.2M
            {
3770
15.2M
                if (nWordCount > 0)
3771
15.2M
                    memset(pabyDstWord,
3772
15.2M
                           *reinterpret_cast<const GByte *>(pDstData),
3773
15.2M
                           nWordCount);
3774
15.2M
            }
3775
22.7k
            else
3776
22.7k
            {
3777
22.7k
                GByte valSet = *reinterpret_cast<const GByte *>(pDstData);
3778
397k
                while (nWordCount > 0)
3779
374k
                {
3780
374k
                    --nWordCount;
3781
374k
                    *pabyDstWord = valSet;
3782
374k
                    pabyDstWord += nDstPixelStride;
3783
374k
                }
3784
22.7k
            }
3785
15.3M
            break;
3786
15.1M
        }
3787
3788
0
#define CASE_DUPLICATE_SIMPLE(enum_type, c_type)                               \
3789
11.3M
    case enum_type:                                                            \
3790
11.3M
    {                                                                          \
3791
11.3M
        GDALReplicateWordT<c_type>(pDstData, nDstPixelStride, nWordCount);     \
3792
11.3M
        break;                                                                 \
3793
11.3M
    }
3794
3795
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_UInt16, GUInt16)
3796
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Int16, GInt16)
3797
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_UInt32, GUInt32)
3798
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Int32, GInt32)
3799
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_UInt64, std::uint64_t)
3800
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Int64, std::int64_t)
3801
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Float16, GFloat16)
3802
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Float32, float)
3803
15.1M
            CASE_DUPLICATE_SIMPLE(GDT_Float64, double)
3804
3805
0
#define CASE_DUPLICATE_COMPLEX(enum_type, c_type)                              \
3806
54.5k
    case enum_type:                                                            \
3807
54.5k
    {                                                                          \
3808
54.5k
        c_type valSet1 = reinterpret_cast<const c_type *>(pDstData)[0];        \
3809
54.5k
        c_type valSet2 = reinterpret_cast<const c_type *>(pDstData)[1];        \
3810
67.2M
        while (nWordCount > 0)                                                 \
3811
67.2M
        {                                                                      \
3812
67.2M
            --nWordCount;                                                      \
3813
67.2M
            reinterpret_cast<c_type *>(pabyDstWord)[0] = valSet1;              \
3814
67.2M
            reinterpret_cast<c_type *>(pabyDstWord)[1] = valSet2;              \
3815
67.2M
            pabyDstWord += nDstPixelStride;                                    \
3816
67.2M
        }                                                                      \
3817
54.5k
        break;                                                                 \
3818
54.5k
    }
3819
3820
15.1M
            CASE_DUPLICATE_COMPLEX(GDT_CInt16, GInt16)
3821
15.1M
            CASE_DUPLICATE_COMPLEX(GDT_CInt32, GInt32)
3822
15.1M
            CASE_DUPLICATE_COMPLEX(GDT_CFloat16, GFloat16)
3823
15.1M
            CASE_DUPLICATE_COMPLEX(GDT_CFloat32, float)
3824
15.1M
            CASE_DUPLICATE_COMPLEX(GDT_CFloat64, double)
3825
3826
0
        case GDT_Unknown:
3827
0
        case GDT_TypeCount:
3828
0
            CPLAssert(false);
3829
26.7M
    }
3830
26.7M
}
3831
3832
/************************************************************************/
3833
/*                          GDALUnrolledCopy()                          */
3834
/************************************************************************/
3835
3836
template <class T, int srcStride, int dstStride>
3837
#if defined(__GNUC__) && defined(__AVX2__)
3838
__attribute__((optimize("tree-vectorize")))
3839
#endif
3840
static inline void GDALUnrolledCopyGeneric(T *CPL_RESTRICT pDest,
3841
                                           const T *CPL_RESTRICT pSrc,
3842
                                           GPtrDiff_t nIters)
3843
363k
{
3844
363k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
363k
    if (nIters >= 16)
3846
141k
    {
3847
4.30M
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
4.16M
        {
3849
4.16M
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
4.16M
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
4.16M
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
4.16M
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
4.16M
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
4.16M
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
4.16M
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
4.16M
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
4.16M
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
4.16M
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
4.16M
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
4.16M
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
4.16M
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
4.16M
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
4.16M
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
4.16M
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
4.16M
            pDest += 16 * dstStride;
3866
4.16M
            pSrc += 16 * srcStride;
3867
4.16M
        }
3868
141k
        nIters = nIters % 16;
3869
141k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
1.63M
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
1.26M
    {
3875
1.26M
        pDest[i * dstStride] = *pSrc;
3876
1.26M
        pSrc += srcStride;
3877
1.26M
    }
3878
363k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<unsigned char, 1, 2>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3843
82
{
3844
82
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
82
    if (nIters >= 16)
3846
68
    {
3847
3.40k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
3.34k
        {
3849
3.34k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
3.34k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
3.34k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
3.34k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
3.34k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
3.34k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
3.34k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
3.34k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
3.34k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
3.34k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
3.34k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
3.34k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
3.34k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
3.34k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
3.34k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
3.34k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
3.34k
            pDest += 16 * dstStride;
3866
3.34k
            pSrc += 16 * srcStride;
3867
3.34k
        }
3868
68
        nIters = nIters % 16;
3869
68
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
868
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
786
    {
3875
786
        pDest[i * dstStride] = *pSrc;
3876
786
        pSrc += srcStride;
3877
786
    }
3878
82
}
rasterio.cpp:void GDALUnrolledCopyGeneric<unsigned char, 1, 3>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3843
53.3k
{
3844
53.3k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
53.3k
    if (nIters >= 16)
3846
52.8k
    {
3847
389k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
336k
        {
3849
336k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
336k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
336k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
336k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
336k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
336k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
336k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
336k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
336k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
336k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
336k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
336k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
336k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
336k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
336k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
336k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
336k
            pDest += 16 * dstStride;
3866
336k
            pSrc += 16 * srcStride;
3867
336k
        }
3868
52.8k
        nIters = nIters % 16;
3869
52.8k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
110k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
56.6k
    {
3875
56.6k
        pDest[i * dstStride] = *pSrc;
3876
56.6k
        pSrc += srcStride;
3877
56.6k
    }
3878
53.3k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<unsigned char, 1, 4>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3843
2.15k
{
3844
2.15k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
2.15k
    if (nIters >= 16)
3846
740
    {
3847
14.8k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
14.0k
        {
3849
14.0k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
14.0k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
14.0k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
14.0k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
14.0k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
14.0k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
14.0k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
14.0k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
14.0k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
14.0k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
14.0k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
14.0k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
14.0k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
14.0k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
14.0k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
14.0k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
14.0k
            pDest += 16 * dstStride;
3866
14.0k
            pSrc += 16 * srcStride;
3867
14.0k
        }
3868
740
        nIters = nIters % 16;
3869
740
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
8.54k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
6.38k
    {
3875
6.38k
        pDest[i * dstStride] = *pSrc;
3876
6.38k
        pSrc += srcStride;
3877
6.38k
    }
3878
2.15k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 2, 1>(short*, short const*, long long)
Line
Count
Source
3843
18.7k
{
3844
18.7k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
18.7k
    if (nIters >= 16)
3846
16.8k
    {
3847
125k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
108k
        {
3849
108k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
108k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
108k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
108k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
108k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
108k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
108k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
108k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
108k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
108k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
108k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
108k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
108k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
108k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
108k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
108k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
108k
            pDest += 16 * dstStride;
3866
108k
            pSrc += 16 * srcStride;
3867
108k
        }
3868
16.8k
        nIters = nIters % 16;
3869
16.8k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
60.9k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
42.1k
    {
3875
42.1k
        pDest[i * dstStride] = *pSrc;
3876
42.1k
        pSrc += srcStride;
3877
42.1k
    }
3878
18.7k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 3, 1>(short*, short const*, long long)
Line
Count
Source
3843
239k
{
3844
239k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
239k
    if (nIters >= 16)
3846
47.7k
    {
3847
3.46M
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
3.41M
        {
3849
3.41M
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
3.41M
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
3.41M
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
3.41M
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
3.41M
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
3.41M
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
3.41M
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
3.41M
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
3.41M
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
3.41M
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
3.41M
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
3.41M
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
3.41M
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
3.41M
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
3.41M
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
3.41M
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
3.41M
            pDest += 16 * dstStride;
3866
3.41M
            pSrc += 16 * srcStride;
3867
3.41M
        }
3868
47.7k
        nIters = nIters % 16;
3869
47.7k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
1.10M
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
869k
    {
3875
869k
        pDest[i * dstStride] = *pSrc;
3876
869k
        pSrc += srcStride;
3877
869k
    }
3878
239k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 4, 1>(short*, short const*, long long)
Line
Count
Source
3843
29.1k
{
3844
29.1k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
29.1k
    if (nIters >= 16)
3846
20.6k
    {
3847
256k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
236k
        {
3849
236k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
236k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
236k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
236k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
236k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
236k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
236k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
236k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
236k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
236k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
236k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
236k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
236k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
236k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
236k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
236k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
236k
            pDest += 16 * dstStride;
3866
236k
            pSrc += 16 * srcStride;
3867
236k
        }
3868
20.6k
        nIters = nIters % 16;
3869
20.6k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
211k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
182k
    {
3875
182k
        pDest[i * dstStride] = *pSrc;
3876
182k
        pSrc += srcStride;
3877
182k
    }
3878
29.1k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 1, 2>(short*, short const*, long long)
Line
Count
Source
3843
2.12k
{
3844
2.12k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
2.12k
    if (nIters >= 16)
3846
510
    {
3847
2.42k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
1.91k
        {
3849
1.91k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
1.91k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
1.91k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
1.91k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
1.91k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
1.91k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
1.91k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
1.91k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
1.91k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
1.91k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
1.91k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
1.91k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
1.91k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
1.91k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
1.91k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
1.91k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
1.91k
            pDest += 16 * dstStride;
3866
1.91k
            pSrc += 16 * srcStride;
3867
1.91k
        }
3868
510
        nIters = nIters % 16;
3869
510
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
5.58k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
3.46k
    {
3875
3.46k
        pDest[i * dstStride] = *pSrc;
3876
3.46k
        pSrc += srcStride;
3877
3.46k
    }
3878
2.12k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 1, 3>(short*, short const*, long long)
Line
Count
Source
3843
17.5k
{
3844
17.5k
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
17.5k
    if (nIters >= 16)
3846
2.15k
    {
3847
44.7k
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
42.6k
        {
3849
42.6k
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
42.6k
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
42.6k
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
42.6k
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
42.6k
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
42.6k
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
42.6k
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
42.6k
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
42.6k
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
42.6k
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
42.6k
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
42.6k
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
42.6k
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
42.6k
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
42.6k
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
42.6k
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
42.6k
            pDest += 16 * dstStride;
3866
42.6k
            pSrc += 16 * srcStride;
3867
42.6k
        }
3868
2.15k
        nIters = nIters % 16;
3869
2.15k
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
119k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
101k
    {
3875
101k
        pDest[i * dstStride] = *pSrc;
3876
101k
        pSrc += srcStride;
3877
101k
    }
3878
17.5k
}
rasterio.cpp:void GDALUnrolledCopyGeneric<short, 1, 4>(short*, short const*, long long)
Line
Count
Source
3843
900
{
3844
900
#if !(defined(__GNUC__) && defined(__AVX2__))
3845
900
    if (nIters >= 16)
3846
0
    {
3847
0
        for (GPtrDiff_t i = nIters / 16; i != 0; i--)
3848
0
        {
3849
0
            pDest[0 * dstStride] = pSrc[0 * srcStride];
3850
0
            pDest[1 * dstStride] = pSrc[1 * srcStride];
3851
0
            pDest[2 * dstStride] = pSrc[2 * srcStride];
3852
0
            pDest[3 * dstStride] = pSrc[3 * srcStride];
3853
0
            pDest[4 * dstStride] = pSrc[4 * srcStride];
3854
0
            pDest[5 * dstStride] = pSrc[5 * srcStride];
3855
0
            pDest[6 * dstStride] = pSrc[6 * srcStride];
3856
0
            pDest[7 * dstStride] = pSrc[7 * srcStride];
3857
0
            pDest[8 * dstStride] = pSrc[8 * srcStride];
3858
0
            pDest[9 * dstStride] = pSrc[9 * srcStride];
3859
0
            pDest[10 * dstStride] = pSrc[10 * srcStride];
3860
0
            pDest[11 * dstStride] = pSrc[11 * srcStride];
3861
0
            pDest[12 * dstStride] = pSrc[12 * srcStride];
3862
0
            pDest[13 * dstStride] = pSrc[13 * srcStride];
3863
0
            pDest[14 * dstStride] = pSrc[14 * srcStride];
3864
0
            pDest[15 * dstStride] = pSrc[15 * srcStride];
3865
0
            pDest += 16 * dstStride;
3866
0
            pSrc += 16 * srcStride;
3867
0
        }
3868
0
        nIters = nIters % 16;
3869
0
    }
3870
#else
3871
#pragma GCC unroll 4
3872
#endif
3873
4.50k
    for (GPtrDiff_t i = 0; i < nIters; i++)
3874
3.60k
    {
3875
3.60k
        pDest[i * dstStride] = *pSrc;
3876
3.60k
        pSrc += srcStride;
3877
3.60k
    }
3878
900
}
3879
3880
template <class T, int srcStride, int dstStride>
3881
static inline void GDALUnrolledCopy(T *CPL_RESTRICT pDest,
3882
                                    const T *CPL_RESTRICT pSrc,
3883
                                    GPtrDiff_t nIters)
3884
363k
{
3885
363k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
363k
}
rasterio.cpp:void GDALUnrolledCopy<unsigned char, 1, 2>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3884
82
{
3885
82
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
82
}
rasterio.cpp:void GDALUnrolledCopy<unsigned char, 1, 3>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3884
53.3k
{
3885
53.3k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
53.3k
}
rasterio.cpp:void GDALUnrolledCopy<unsigned char, 1, 4>(unsigned char*, unsigned char const*, long long)
Line
Count
Source
3884
2.15k
{
3885
2.15k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
2.15k
}
rasterio.cpp:void GDALUnrolledCopy<short, 2, 1>(short*, short const*, long long)
Line
Count
Source
3884
18.7k
{
3885
18.7k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
18.7k
}
rasterio.cpp:void GDALUnrolledCopy<short, 3, 1>(short*, short const*, long long)
Line
Count
Source
3884
239k
{
3885
239k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
239k
}
rasterio.cpp:void GDALUnrolledCopy<short, 4, 1>(short*, short const*, long long)
Line
Count
Source
3884
29.1k
{
3885
29.1k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
29.1k
}
rasterio.cpp:void GDALUnrolledCopy<short, 1, 2>(short*, short const*, long long)
Line
Count
Source
3884
2.12k
{
3885
2.12k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
2.12k
}
rasterio.cpp:void GDALUnrolledCopy<short, 1, 3>(short*, short const*, long long)
Line
Count
Source
3884
17.5k
{
3885
17.5k
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
17.5k
}
rasterio.cpp:void GDALUnrolledCopy<short, 1, 4>(short*, short const*, long long)
Line
Count
Source
3884
900
{
3885
900
    GDALUnrolledCopyGeneric<T, srcStride, dstStride>(pDest, pSrc, nIters);
3886
900
}
3887
3888
#if defined(__AVX2__) && defined(HAVE_SSSE3_AT_COMPILE_TIME) &&                \
3889
    (defined(__x86_64) || defined(_M_X64) || defined(USE_NEON_OPTIMIZATIONS))
3890
3891
template <>
3892
void GDALUnrolledCopy<GByte, 3, 1>(GByte *CPL_RESTRICT pDest,
3893
                                   const GByte *CPL_RESTRICT pSrc,
3894
                                   GPtrDiff_t nIters)
3895
{
3896
    if (nIters > 16)
3897
    {
3898
        // The SSSE3 variant is slightly faster than what the gcc autovectorizer
3899
        // generates
3900
        GDALUnrolledCopy_GByte_3_1_SSSE3(pDest, pSrc, nIters);
3901
    }
3902
    else
3903
    {
3904
        for (GPtrDiff_t i = 0; i < nIters; i++)
3905
        {
3906
            pDest[i] = *pSrc;
3907
            pSrc += 3;
3908
        }
3909
    }
3910
}
3911
3912
#elif defined(HAVE_SSE2) && !(defined(__GNUC__) && defined(__AVX2__))
3913
3914
template <>
3915
void GDALUnrolledCopy<GByte, 2, 1>(GByte *CPL_RESTRICT pDest,
3916
                                   const GByte *CPL_RESTRICT pSrc,
3917
                                   GPtrDiff_t nIters)
3918
22.8k
{
3919
22.8k
    decltype(nIters) i = 0;
3920
22.8k
    if (nIters > 16)
3921
21.6k
    {
3922
21.6k
        const __m128i xmm_mask = _mm_set1_epi16(0xff);
3923
        // If we were sure that there would always be 1 trailing byte, we could
3924
        // check against nIters - 15
3925
943k
        for (; i < nIters - 16; i += 16)
3926
921k
        {
3927
921k
            __m128i xmm0 =
3928
921k
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 0));
3929
921k
            __m128i xmm1 =
3930
921k
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 16));
3931
            // Set higher 8bit of each int16 packed word to 0
3932
921k
            xmm0 = _mm_and_si128(xmm0, xmm_mask);
3933
921k
            xmm1 = _mm_and_si128(xmm1, xmm_mask);
3934
            // Pack int16 to uint8 and merge back both vector
3935
921k
            xmm0 = _mm_packus_epi16(xmm0, xmm1);
3936
3937
            // Store result
3938
921k
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDest + i), xmm0);
3939
3940
921k
            pSrc += 2 * 16;
3941
921k
        }
3942
21.6k
    }
3943
191k
    for (; i < nIters; i++)
3944
169k
    {
3945
169k
        pDest[i] = *pSrc;
3946
169k
        pSrc += 2;
3947
169k
    }
3948
22.8k
}
3949
3950
static void GDALUnrolledCopy_GByte_3_1_SSE2(GByte *CPL_RESTRICT pDest,
3951
                                            const GByte *CPL_RESTRICT pSrc,
3952
                                            GPtrDiff_t nIters)
3953
0
{
3954
0
    decltype(nIters) i = 0;
3955
0
    const __m128i xmm_mask_ori = _mm_set_epi32(0, 0, 0, 255);
3956
    // If we were sure that there would always be 2 trailing bytes, we could
3957
    // check against nIters - 15
3958
0
    for (; i < nIters - 16; i += 16)
3959
0
    {
3960
0
        __m128i xmm0 =
3961
0
            _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 0));
3962
0
        __m128i xmm1 =
3963
0
            _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 16));
3964
0
        __m128i xmm2 =
3965
0
            _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 32));
3966
3967
0
        auto xmm_mask0 = xmm_mask_ori;
3968
0
        auto xmm_mask1 = _mm_slli_si128(xmm_mask_ori, 6);
3969
0
        auto xmm_mask2 = _mm_slli_si128(xmm_mask_ori, 11);
3970
3971
0
        auto xmm = _mm_and_si128(xmm0, xmm_mask0);
3972
0
        auto xmm_res1 = _mm_and_si128(_mm_slli_si128(xmm1, 4), xmm_mask1);
3973
3974
0
        xmm_mask0 = _mm_slli_si128(xmm_mask0, 1);
3975
0
        xmm_mask1 = _mm_slli_si128(xmm_mask1, 1);
3976
0
        xmm0 = _mm_srli_si128(xmm0, 2);
3977
0
        xmm = _mm_or_si128(xmm, _mm_and_si128(xmm0, xmm_mask0));
3978
0
        xmm_res1 = _mm_or_si128(
3979
0
            xmm_res1, _mm_and_si128(_mm_slli_si128(xmm1, 2), xmm_mask1));
3980
3981
0
        xmm_mask0 = _mm_slli_si128(xmm_mask0, 1);
3982
0
        xmm_mask1 = _mm_slli_si128(xmm_mask1, 1);
3983
0
        xmm0 = _mm_srli_si128(xmm0, 2);
3984
0
        xmm = _mm_or_si128(xmm, _mm_and_si128(xmm0, xmm_mask0));
3985
0
        xmm_res1 = _mm_or_si128(xmm_res1, _mm_and_si128(xmm1, xmm_mask1));
3986
3987
0
        xmm_mask0 = _mm_slli_si128(xmm_mask0, 1);
3988
0
        xmm_mask1 = _mm_slli_si128(xmm_mask1, 1);
3989
0
        xmm0 = _mm_srli_si128(xmm0, 2);
3990
0
        xmm = _mm_or_si128(xmm, _mm_and_si128(xmm0, xmm_mask0));
3991
0
        xmm_res1 = _mm_or_si128(
3992
0
            xmm_res1, _mm_and_si128(_mm_srli_si128(xmm1, 2), xmm_mask1));
3993
3994
0
        xmm_mask0 = _mm_slli_si128(xmm_mask0, 1);
3995
0
        xmm_mask1 = _mm_slli_si128(xmm_mask1, 1);
3996
0
        xmm0 = _mm_srli_si128(xmm0, 2);
3997
0
        xmm = _mm_or_si128(xmm, _mm_and_si128(xmm0, xmm_mask0));
3998
0
        xmm_res1 = _mm_or_si128(
3999
0
            xmm_res1, _mm_and_si128(_mm_srli_si128(xmm1, 4), xmm_mask1));
4000
0
        xmm = _mm_or_si128(xmm, xmm_res1);
4001
4002
0
        xmm_mask0 = _mm_slli_si128(xmm_mask0, 1);
4003
0
        xmm0 = _mm_srli_si128(xmm0, 2);
4004
0
        xmm = _mm_or_si128(xmm, _mm_and_si128(xmm0, xmm_mask0));
4005
4006
0
        xmm = _mm_or_si128(xmm,
4007
0
                           _mm_and_si128(_mm_slli_si128(xmm2, 10), xmm_mask2));
4008
4009
0
        xmm_mask2 = _mm_slli_si128(xmm_mask2, 1);
4010
0
        xmm = _mm_or_si128(xmm,
4011
0
                           _mm_and_si128(_mm_slli_si128(xmm2, 8), xmm_mask2));
4012
4013
0
        xmm_mask2 = _mm_slli_si128(xmm_mask2, 1);
4014
0
        xmm = _mm_or_si128(xmm,
4015
0
                           _mm_and_si128(_mm_slli_si128(xmm2, 6), xmm_mask2));
4016
4017
0
        xmm_mask2 = _mm_slli_si128(xmm_mask2, 1);
4018
0
        xmm = _mm_or_si128(xmm,
4019
0
                           _mm_and_si128(_mm_slli_si128(xmm2, 4), xmm_mask2));
4020
4021
0
        xmm_mask2 = _mm_slli_si128(xmm_mask2, 1);
4022
0
        xmm = _mm_or_si128(xmm,
4023
0
                           _mm_and_si128(_mm_slli_si128(xmm2, 2), xmm_mask2));
4024
4025
0
        _mm_storeu_si128(reinterpret_cast<__m128i *>(pDest + i), xmm);
4026
4027
0
        pSrc += 3 * 16;
4028
0
    }
4029
0
    for (; i < nIters; i++)
4030
0
    {
4031
0
        pDest[i] = *pSrc;
4032
0
        pSrc += 3;
4033
0
    }
4034
0
}
4035
4036
#ifdef HAVE_SSSE3_AT_COMPILE_TIME
4037
4038
template <>
4039
void GDALUnrolledCopy<GByte, 3, 1>(GByte *CPL_RESTRICT pDest,
4040
                                   const GByte *CPL_RESTRICT pSrc,
4041
                                   GPtrDiff_t nIters)
4042
140k
{
4043
140k
    if (nIters > 16)
4044
135k
    {
4045
135k
        if (CPLHaveRuntimeSSSE3())
4046
135k
        {
4047
135k
            GDALUnrolledCopy_GByte_3_1_SSSE3(pDest, pSrc, nIters);
4048
135k
        }
4049
0
        else
4050
0
        {
4051
0
            GDALUnrolledCopy_GByte_3_1_SSE2(pDest, pSrc, nIters);
4052
0
        }
4053
135k
    }
4054
5.01k
    else
4055
5.01k
    {
4056
37.6k
        for (GPtrDiff_t i = 0; i < nIters; i++)
4057
32.6k
        {
4058
32.6k
            pDest[i] = *pSrc;
4059
32.6k
            pSrc += 3;
4060
32.6k
        }
4061
5.01k
    }
4062
140k
}
4063
4064
#else
4065
4066
template <>
4067
void GDALUnrolledCopy<GByte, 3, 1>(GByte *CPL_RESTRICT pDest,
4068
                                   const GByte *CPL_RESTRICT pSrc,
4069
                                   GPtrDiff_t nIters)
4070
{
4071
    GDALUnrolledCopy_GByte_3_1_SSE2(pDest, pSrc, nIters);
4072
}
4073
#endif
4074
4075
template <>
4076
void GDALUnrolledCopy<GByte, 4, 1>(GByte *CPL_RESTRICT pDest,
4077
                                   const GByte *CPL_RESTRICT pSrc,
4078
                                   GPtrDiff_t nIters)
4079
102M
{
4080
102M
    decltype(nIters) i = 0;
4081
102M
    if (nIters > 16)
4082
10.0M
    {
4083
10.0M
        const __m128i xmm_mask = _mm_set1_epi32(0xff);
4084
        // If we were sure that there would always be 3 trailing bytes, we could
4085
        // check against nIters - 15
4086
89.5M
        for (; i < nIters - 16; i += 16)
4087
79.5M
        {
4088
79.5M
            __m128i xmm0 =
4089
79.5M
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 0));
4090
79.5M
            __m128i xmm1 =
4091
79.5M
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 16));
4092
79.5M
            __m128i xmm2 =
4093
79.5M
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 32));
4094
79.5M
            __m128i xmm3 =
4095
79.5M
                _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + 48));
4096
            // Set higher 24bit of each int32 packed word to 0
4097
79.5M
            xmm0 = _mm_and_si128(xmm0, xmm_mask);
4098
79.5M
            xmm1 = _mm_and_si128(xmm1, xmm_mask);
4099
79.5M
            xmm2 = _mm_and_si128(xmm2, xmm_mask);
4100
79.5M
            xmm3 = _mm_and_si128(xmm3, xmm_mask);
4101
            // Pack int32 to int16
4102
79.5M
            xmm0 = _mm_packs_epi32(xmm0, xmm1);
4103
79.5M
            xmm2 = _mm_packs_epi32(xmm2, xmm3);
4104
            // Pack int16 to uint8
4105
79.5M
            xmm0 = _mm_packus_epi16(xmm0, xmm2);
4106
4107
            // Store result
4108
79.5M
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pDest + i), xmm0);
4109
4110
79.5M
            pSrc += 4 * 16;
4111
79.5M
        }
4112
10.0M
    }
4113
412M
    for (; i < nIters; i++)
4114
310M
    {
4115
310M
        pDest[i] = *pSrc;
4116
310M
        pSrc += 4;
4117
310M
    }
4118
102M
}
4119
#endif  // HAVE_SSE2
4120
4121
/************************************************************************/
4122
/*                            GDALFastCopy()                            */
4123
/************************************************************************/
4124
4125
template <class T>
4126
static inline void GDALFastCopy(T *CPL_RESTRICT pDest, int nDestStride,
4127
                                const T *CPL_RESTRICT pSrc, int nSrcStride,
4128
                                GPtrDiff_t nIters)
4129
125M
{
4130
125M
    constexpr int sizeofT = static_cast<int>(sizeof(T));
4131
125M
    if (nIters == 1)
4132
19.5M
    {
4133
19.5M
        *pDest = *pSrc;
4134
19.5M
    }
4135
105M
    else if (nDestStride == sizeofT)
4136
104M
    {
4137
104M
        if (nSrcStride == sizeofT)
4138
1.31M
        {
4139
1.31M
            memcpy(pDest, pSrc, nIters * sizeof(T));
4140
1.31M
        }
4141
103M
        else if (nSrcStride == 2 * sizeofT)
4142
41.6k
        {
4143
41.6k
            GDALUnrolledCopy<T, 2, 1>(pDest, pSrc, nIters);
4144
41.6k
        }
4145
103M
        else if (nSrcStride == 3 * sizeofT)
4146
379k
        {
4147
379k
            GDALUnrolledCopy<T, 3, 1>(pDest, pSrc, nIters);
4148
379k
        }
4149
102M
        else if (nSrcStride == 4 * sizeofT)
4150
102M
        {
4151
102M
            GDALUnrolledCopy<T, 4, 1>(pDest, pSrc, nIters);
4152
102M
        }
4153
400k
        else
4154
400k
        {
4155
286M
            while (nIters-- > 0)
4156
286M
            {
4157
286M
                *pDest = *pSrc;
4158
286M
                pSrc += nSrcStride / sizeofT;
4159
286M
                pDest++;
4160
286M
            }
4161
400k
        }
4162
104M
    }
4163
1.22M
    else if (nSrcStride == sizeofT)
4164
1.22M
    {
4165
1.22M
        if (nDestStride == 2 * sizeofT)
4166
2.20k
        {
4167
2.20k
            GDALUnrolledCopy<T, 1, 2>(pDest, pSrc, nIters);
4168
2.20k
        }
4169
1.21M
        else if (nDestStride == 3 * sizeofT)
4170
70.9k
        {
4171
70.9k
            GDALUnrolledCopy<T, 1, 3>(pDest, pSrc, nIters);
4172
70.9k
        }
4173
1.14M
        else if (nDestStride == 4 * sizeofT)
4174
3.05k
        {
4175
3.05k
            GDALUnrolledCopy<T, 1, 4>(pDest, pSrc, nIters);
4176
3.05k
        }
4177
1.14M
        else
4178
1.14M
        {
4179
10.1M
            while (nIters-- > 0)
4180
8.97M
            {
4181
8.97M
                *pDest = *pSrc;
4182
8.97M
                pSrc++;
4183
8.97M
                pDest += nDestStride / sizeofT;
4184
8.97M
            }
4185
1.14M
        }
4186
1.22M
    }
4187
0
    else
4188
0
    {
4189
0
        while (nIters-- > 0)
4190
0
        {
4191
0
            *pDest = *pSrc;
4192
0
            pSrc += nSrcStride / sizeofT;
4193
0
            pDest += nDestStride / sizeofT;
4194
0
        }
4195
0
    }
4196
125M
}
rasterio.cpp:void GDALFastCopy<unsigned char>(unsigned char*, int, unsigned char const*, int, long long)
Line
Count
Source
4129
116M
{
4130
116M
    constexpr int sizeofT = static_cast<int>(sizeof(T));
4131
116M
    if (nIters == 1)
4132
12.2M
    {
4133
12.2M
        *pDest = *pSrc;
4134
12.2M
    }
4135
104M
    else if (nDestStride == sizeofT)
4136
103M
    {
4137
103M
        if (nSrcStride == sizeofT)
4138
820k
        {
4139
820k
            memcpy(pDest, pSrc, nIters * sizeof(T));
4140
820k
        }
4141
102M
        else if (nSrcStride == 2 * sizeofT)
4142
22.8k
        {
4143
22.8k
            GDALUnrolledCopy<T, 2, 1>(pDest, pSrc, nIters);
4144
22.8k
        }
4145
102M
        else if (nSrcStride == 3 * sizeofT)
4146
140k
        {
4147
140k
            GDALUnrolledCopy<T, 3, 1>(pDest, pSrc, nIters);
4148
140k
        }
4149
102M
        else if (nSrcStride == 4 * sizeofT)
4150
102M
        {
4151
102M
            GDALUnrolledCopy<T, 4, 1>(pDest, pSrc, nIters);
4152
102M
        }
4153
289k
        else
4154
289k
        {
4155
281M
            while (nIters-- > 0)
4156
280M
            {
4157
280M
                *pDest = *pSrc;
4158
280M
                pSrc += nSrcStride / sizeofT;
4159
280M
                pDest++;
4160
280M
            }
4161
289k
        }
4162
103M
    }
4163
556k
    else if (nSrcStride == sizeofT)
4164
556k
    {
4165
556k
        if (nDestStride == 2 * sizeofT)
4166
82
        {
4167
82
            GDALUnrolledCopy<T, 1, 2>(pDest, pSrc, nIters);
4168
82
        }
4169
556k
        else if (nDestStride == 3 * sizeofT)
4170
53.3k
        {
4171
53.3k
            GDALUnrolledCopy<T, 1, 3>(pDest, pSrc, nIters);
4172
53.3k
        }
4173
503k
        else if (nDestStride == 4 * sizeofT)
4174
2.15k
        {
4175
2.15k
            GDALUnrolledCopy<T, 1, 4>(pDest, pSrc, nIters);
4176
2.15k
        }
4177
500k
        else
4178
500k
        {
4179
5.28M
            while (nIters-- > 0)
4180
4.78M
            {
4181
4.78M
                *pDest = *pSrc;
4182
4.78M
                pSrc++;
4183
4.78M
                pDest += nDestStride / sizeofT;
4184
4.78M
            }
4185
500k
        }
4186
556k
    }
4187
0
    else
4188
0
    {
4189
0
        while (nIters-- > 0)
4190
0
        {
4191
0
            *pDest = *pSrc;
4192
0
            pSrc += nSrcStride / sizeofT;
4193
0
            pDest += nDestStride / sizeofT;
4194
0
        }
4195
0
    }
4196
116M
}
rasterio.cpp:void GDALFastCopy<short>(short*, int, short const*, int, long long)
Line
Count
Source
4129
8.82M
{
4130
8.82M
    constexpr int sizeofT = static_cast<int>(sizeof(T));
4131
8.82M
    if (nIters == 1)
4132
7.27M
    {
4133
7.27M
        *pDest = *pSrc;
4134
7.27M
    }
4135
1.55M
    else if (nDestStride == sizeofT)
4136
889k
    {
4137
889k
        if (nSrcStride == sizeofT)
4138
491k
        {
4139
491k
            memcpy(pDest, pSrc, nIters * sizeof(T));
4140
491k
        }
4141
398k
        else if (nSrcStride == 2 * sizeofT)
4142
18.7k
        {
4143
18.7k
            GDALUnrolledCopy<T, 2, 1>(pDest, pSrc, nIters);
4144
18.7k
        }
4145
379k
        else if (nSrcStride == 3 * sizeofT)
4146
239k
        {
4147
239k
            GDALUnrolledCopy<T, 3, 1>(pDest, pSrc, nIters);
4148
239k
        }
4149
140k
        else if (nSrcStride == 4 * sizeofT)
4150
29.1k
        {
4151
29.1k
            GDALUnrolledCopy<T, 4, 1>(pDest, pSrc, nIters);
4152
29.1k
        }
4153
111k
        else
4154
111k
        {
4155
5.45M
            while (nIters-- > 0)
4156
5.34M
            {
4157
5.34M
                *pDest = *pSrc;
4158
5.34M
                pSrc += nSrcStride / sizeofT;
4159
5.34M
                pDest++;
4160
5.34M
            }
4161
111k
        }
4162
889k
    }
4163
664k
    else if (nSrcStride == sizeofT)
4164
664k
    {
4165
664k
        if (nDestStride == 2 * sizeofT)
4166
2.12k
        {
4167
2.12k
            GDALUnrolledCopy<T, 1, 2>(pDest, pSrc, nIters);
4168
2.12k
        }
4169
662k
        else if (nDestStride == 3 * sizeofT)
4170
17.5k
        {
4171
17.5k
            GDALUnrolledCopy<T, 1, 3>(pDest, pSrc, nIters);
4172
17.5k
        }
4173
644k
        else if (nDestStride == 4 * sizeofT)
4174
900
        {
4175
900
            GDALUnrolledCopy<T, 1, 4>(pDest, pSrc, nIters);
4176
900
        }
4177
643k
        else
4178
643k
        {
4179
4.83M
            while (nIters-- > 0)
4180
4.18M
            {
4181
4.18M
                *pDest = *pSrc;
4182
4.18M
                pSrc++;
4183
4.18M
                pDest += nDestStride / sizeofT;
4184
4.18M
            }
4185
643k
        }
4186
664k
    }
4187
0
    else
4188
0
    {
4189
0
        while (nIters-- > 0)
4190
0
        {
4191
0
            *pDest = *pSrc;
4192
0
            pSrc += nSrcStride / sizeofT;
4193
0
            pDest += nDestStride / sizeofT;
4194
0
        }
4195
0
    }
4196
8.82M
}
4197
4198
/************************************************************************/
4199
/*                          GDALFastCopyByte()                          */
4200
/************************************************************************/
4201
4202
static void GDALFastCopyByte(const GByte *CPL_RESTRICT pSrcData,
4203
                             int nSrcPixelStride, GByte *CPL_RESTRICT pDstData,
4204
                             int nDstPixelStride, GPtrDiff_t nWordCount)
4205
112k
{
4206
112k
    GDALFastCopy(pDstData, nDstPixelStride, pSrcData, nSrcPixelStride,
4207
112k
                 nWordCount);
4208
112k
}
4209
4210
/************************************************************************/
4211
/*                           GDALCopyWords()                            */
4212
/************************************************************************/
4213
4214
/**
4215
 * Copy pixel words from buffer to buffer.
4216
 *
4217
 * @see GDALCopyWords64()
4218
 */
4219
void CPL_STDCALL GDALCopyWords(const void *CPL_RESTRICT pSrcData,
4220
                               GDALDataType eSrcType, int nSrcPixelStride,
4221
                               void *CPL_RESTRICT pDstData,
4222
                               GDALDataType eDstType, int nDstPixelStride,
4223
                               int nWordCount)
4224
124M
{
4225
124M
    GDALCopyWords64(pSrcData, eSrcType, nSrcPixelStride, pDstData, eDstType,
4226
124M
                    nDstPixelStride, nWordCount);
4227
124M
}
4228
4229
/************************************************************************/
4230
/*                          GDALCopyWords64()                           */
4231
/************************************************************************/
4232
4233
/**
4234
 * Copy pixel words from buffer to buffer.
4235
 *
4236
 * This function is used to copy pixel word values from one memory buffer
4237
 * to another, with support for conversion between data types, and differing
4238
 * step factors. The data type conversion is done using the following
4239
 * rules:
4240
 * <ul>
4241
 * <li>Values assigned to a lower range integer type are clipped. For
4242
 * instance assigning GDT_Int16 values to a GDT_UInt8 buffer will cause values
4243
 * less the 0 to be set to 0, and values larger than 255 to be set to 255.
4244
 * </li>
4245
 * <li>
4246
 * Assignment from floating point to integer rounds to closest integer.
4247
 * +Infinity is mapped to the largest integer. -Infinity is mapped to the
4248
 * smallest integer. NaN is mapped to 0.
4249
 * </li>
4250
 * <li>
4251
 * Assignment from non-complex to complex will result in the imaginary part
4252
 * being set to zero on output.
4253
 * </li>
4254
 * <li> Assignment from complex to
4255
 * non-complex will result in the complex portion being lost and the real
4256
 * component being preserved (<i>not magnitude!</i>).
4257
 * </li>
4258
 * </ul>
4259
 *
4260
 * No assumptions are made about the source or destination words occurring
4261
 * on word boundaries.  It is assumed that all values are in native machine
4262
 * byte order.
4263
 *
4264
 * @param pSrcData Pointer to source data to be converted.
4265
 * @param eSrcType the source data type (see GDALDataType enum)
4266
 * @param nSrcPixelStride Source pixel stride (i.e. distance between 2 words),
4267
 * in bytes
4268
 * @param pDstData Pointer to buffer where destination data should go
4269
 * @param eDstType the destination data type (see GDALDataType enum)
4270
 * @param nDstPixelStride Destination pixel stride (i.e. distance between 2
4271
 * words), in bytes
4272
 * @param nWordCount number of words to be copied
4273
 *
4274
 * @note
4275
 * When adding a new data type to GDAL, you must do the following to
4276
 * support it properly within the GDALCopyWords function:
4277
 * 1. Add the data type to the switch on eSrcType in GDALCopyWords.
4278
 *    This should invoke the appropriate GDALCopyWordsFromT wrapper.
4279
 * 2. Add the data type to the switch on eDstType in GDALCopyWordsFromT.
4280
 *    This should call the appropriate GDALCopyWordsT template.
4281
 * 3. If appropriate, overload the appropriate CopyWord template in the
4282
 *    above namespace. This will ensure that any conversion issues are
4283
 *    handled (cases like the float -> int32 case, where the min/max)
4284
 *    values are subject to roundoff error.
4285
 */
4286
4287
void CPL_STDCALL GDALCopyWords64(const void *CPL_RESTRICT pSrcData,
4288
                                 GDALDataType eSrcType, int nSrcPixelStride,
4289
                                 void *CPL_RESTRICT pDstData,
4290
                                 GDALDataType eDstType, int nDstPixelStride,
4291
                                 GPtrDiff_t nWordCount)
4292
4293
410M
{
4294
    // On platforms where alignment matters, be careful
4295
410M
    const int nSrcDataTypeSize = GDALGetDataTypeSizeBytes(eSrcType);
4296
410M
    const int nDstDataTypeSize = GDALGetDataTypeSizeBytes(eDstType);
4297
410M
    if (CPL_UNLIKELY(nSrcDataTypeSize == 0 || nDstDataTypeSize == 0))
4298
0
    {
4299
0
        CPLError(CE_Failure, CPLE_NotSupported,
4300
0
                 "GDALCopyWords64(): unsupported GDT_Unknown/GDT_TypeCount "
4301
0
                 "argument");
4302
0
        return;
4303
0
    }
4304
410M
    if (!(eSrcType == eDstType && nSrcPixelStride == nDstPixelStride) &&
4305
399M
        ((reinterpret_cast<uintptr_t>(pSrcData) % nSrcDataTypeSize) != 0 ||
4306
399M
         (reinterpret_cast<uintptr_t>(pDstData) % nDstDataTypeSize) != 0 ||
4307
399M
         (nSrcPixelStride % nSrcDataTypeSize) != 0 ||
4308
399M
         (nDstPixelStride % nDstDataTypeSize) != 0))
4309
0
    {
4310
0
        if (eSrcType == eDstType)
4311
0
        {
4312
0
            for (decltype(nWordCount) i = 0; i < nWordCount; i++)
4313
0
            {
4314
0
                memcpy(static_cast<GByte *>(pDstData) + nDstPixelStride * i,
4315
0
                       static_cast<const GByte *>(pSrcData) +
4316
0
                           nSrcPixelStride * i,
4317
0
                       nDstDataTypeSize);
4318
0
            }
4319
0
        }
4320
0
        else
4321
0
        {
4322
0
            const auto getAlignedPtr = [](GByte *ptr, int align)
4323
0
            {
4324
0
                return ptr +
4325
0
                       ((align - (reinterpret_cast<uintptr_t>(ptr) % align)) %
4326
0
                        align);
4327
0
            };
4328
4329
            // The largest we need is for CFloat64 (16 bytes), so 32 bytes to
4330
            // be sure to get correctly aligned pointer.
4331
0
            constexpr size_t SIZEOF_CFLOAT64 = 2 * sizeof(double);
4332
0
            GByte abySrcBuffer[2 * SIZEOF_CFLOAT64];
4333
0
            GByte abyDstBuffer[2 * SIZEOF_CFLOAT64];
4334
0
            GByte *pabySrcBuffer =
4335
0
                getAlignedPtr(abySrcBuffer, nSrcDataTypeSize);
4336
0
            GByte *pabyDstBuffer =
4337
0
                getAlignedPtr(abyDstBuffer, nDstDataTypeSize);
4338
0
            for (decltype(nWordCount) i = 0; i < nWordCount; i++)
4339
0
            {
4340
0
                memcpy(pabySrcBuffer,
4341
0
                       static_cast<const GByte *>(pSrcData) +
4342
0
                           nSrcPixelStride * i,
4343
0
                       nSrcDataTypeSize);
4344
0
                GDALCopyWords64(pabySrcBuffer, eSrcType, 0, pabyDstBuffer,
4345
0
                                eDstType, 0, 1);
4346
0
                memcpy(static_cast<GByte *>(pDstData) + nDstPixelStride * i,
4347
0
                       pabyDstBuffer, nDstDataTypeSize);
4348
0
            }
4349
0
        }
4350
0
        return;
4351
0
    }
4352
4353
    // Deal with the case where we're replicating a single word into the
4354
    // provided buffer
4355
410M
    if (nSrcPixelStride == 0 && nWordCount > 1)
4356
26.7M
    {
4357
26.7M
        GDALReplicateWord(pSrcData, eSrcType, pDstData, eDstType,
4358
26.7M
                          nDstPixelStride, nWordCount);
4359
26.7M
        return;
4360
26.7M
    }
4361
4362
383M
    if (eSrcType == eDstType)
4363
127M
    {
4364
127M
        if (eSrcType == GDT_UInt8 || eSrcType == GDT_Int8)
4365
116M
        {
4366
116M
            GDALFastCopy(static_cast<GByte *>(pDstData), nDstPixelStride,
4367
116M
                         static_cast<const GByte *>(pSrcData), nSrcPixelStride,
4368
116M
                         nWordCount);
4369
116M
            return;
4370
116M
        }
4371
4372
11.3M
        if (nSrcDataTypeSize == 2 && (nSrcPixelStride % 2) == 0 &&
4373
8.82M
            (nDstPixelStride % 2) == 0)
4374
8.82M
        {
4375
8.82M
            GDALFastCopy(static_cast<short *>(pDstData), nDstPixelStride,
4376
8.82M
                         static_cast<const short *>(pSrcData), nSrcPixelStride,
4377
8.82M
                         nWordCount);
4378
8.82M
            return;
4379
8.82M
        }
4380
4381
2.52M
        if (nWordCount == 1)
4382
1.52M
        {
4383
#if defined(CSA_BUILD) || defined(__COVERITY__)
4384
            // Avoid false positives...
4385
            memcpy(pDstData, pSrcData, nSrcDataTypeSize);
4386
#else
4387
1.52M
            if (nSrcDataTypeSize == 2)
4388
0
                memcpy(pDstData, pSrcData, 2);
4389
1.52M
            else if (nSrcDataTypeSize == 4)
4390
691k
                memcpy(pDstData, pSrcData, 4);
4391
831k
            else if (nSrcDataTypeSize == 8)
4392
794k
                memcpy(pDstData, pSrcData, 8);
4393
37.6k
            else /* if( eSrcType == GDT_CFloat64 ) */
4394
37.6k
                memcpy(pDstData, pSrcData, 16);
4395
1.52M
#endif
4396
1.52M
            return;
4397
1.52M
        }
4398
4399
        // Let memcpy() handle the case where we're copying a packed buffer
4400
        // of pixels.
4401
997k
        if (nSrcPixelStride == nDstPixelStride)
4402
517k
        {
4403
517k
            if (nSrcPixelStride == nSrcDataTypeSize)
4404
517k
            {
4405
517k
                memcpy(pDstData, pSrcData, nWordCount * nSrcDataTypeSize);
4406
517k
                return;
4407
517k
            }
4408
517k
        }
4409
997k
    }
4410
4411
    // Handle the more general case -- deals with conversion of data types
4412
    // directly.
4413
256M
    switch (eSrcType)
4414
256M
    {
4415
176M
        case GDT_UInt8:
4416
176M
            GDALCopyWordsFromT<unsigned char>(
4417
176M
                static_cast<const unsigned char *>(pSrcData), nSrcPixelStride,
4418
176M
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4419
176M
            break;
4420
5.93M
        case GDT_Int8:
4421
5.93M
            GDALCopyWordsFromT<signed char>(
4422
5.93M
                static_cast<const signed char *>(pSrcData), nSrcPixelStride,
4423
5.93M
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4424
5.93M
            break;
4425
5.58M
        case GDT_UInt16:
4426
5.58M
            GDALCopyWordsFromT<unsigned short>(
4427
5.58M
                static_cast<const unsigned short *>(pSrcData), nSrcPixelStride,
4428
5.58M
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4429
5.58M
            break;
4430
4.92M
        case GDT_Int16:
4431
4.92M
            GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData),
4432
4.92M
                                      nSrcPixelStride, false, pDstData,
4433
4.92M
                                      eDstType, nDstPixelStride, nWordCount);
4434
4.92M
            break;
4435
1.83M
        case GDT_UInt32:
4436
1.83M
            GDALCopyWordsFromT<unsigned int>(
4437
1.83M
                static_cast<const unsigned int *>(pSrcData), nSrcPixelStride,
4438
1.83M
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4439
1.83M
            break;
4440
532k
        case GDT_Int32:
4441
532k
            GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData),
4442
532k
                                    nSrcPixelStride, false, pDstData, eDstType,
4443
532k
                                    nDstPixelStride, nWordCount);
4444
532k
            break;
4445
257k
        case GDT_UInt64:
4446
257k
            GDALCopyWordsFromT<std::uint64_t>(
4447
257k
                static_cast<const std::uint64_t *>(pSrcData), nSrcPixelStride,
4448
257k
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4449
257k
            break;
4450
367k
        case GDT_Int64:
4451
367k
            GDALCopyWordsFromT<std::int64_t>(
4452
367k
                static_cast<const std::int64_t *>(pSrcData), nSrcPixelStride,
4453
367k
                false, pDstData, eDstType, nDstPixelStride, nWordCount);
4454
367k
            break;
4455
1.88M
        case GDT_Float16:
4456
1.88M
            GDALCopyWordsFromT<GFloat16>(
4457
1.88M
                static_cast<const GFloat16 *>(pSrcData), nSrcPixelStride, false,
4458
1.88M
                pDstData, eDstType, nDstPixelStride, nWordCount);
4459
1.88M
            break;
4460
24.2M
        case GDT_Float32:
4461
24.2M
            GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData),
4462
24.2M
                                      nSrcPixelStride, false, pDstData,
4463
24.2M
                                      eDstType, nDstPixelStride, nWordCount);
4464
24.2M
            break;
4465
33.9M
        case GDT_Float64:
4466
33.9M
            GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData),
4467
33.9M
                                       nSrcPixelStride, false, pDstData,
4468
33.9M
                                       eDstType, nDstPixelStride, nWordCount);
4469
33.9M
            break;
4470
127k
        case GDT_CInt16:
4471
127k
            GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData),
4472
127k
                                      nSrcPixelStride, true, pDstData, eDstType,
4473
127k
                                      nDstPixelStride, nWordCount);
4474
127k
            break;
4475
5.70k
        case GDT_CInt32:
4476
5.70k
            GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData),
4477
5.70k
                                    nSrcPixelStride, true, pDstData, eDstType,
4478
5.70k
                                    nDstPixelStride, nWordCount);
4479
5.70k
            break;
4480
57.6k
        case GDT_CFloat16:
4481
57.6k
            GDALCopyWordsFromT<GFloat16>(
4482
57.6k
                static_cast<const GFloat16 *>(pSrcData), nSrcPixelStride, true,
4483
57.6k
                pDstData, eDstType, nDstPixelStride, nWordCount);
4484
57.6k
            break;
4485
149k
        case GDT_CFloat32:
4486
149k
            GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData),
4487
149k
                                      nSrcPixelStride, true, pDstData, eDstType,
4488
149k
                                      nDstPixelStride, nWordCount);
4489
149k
            break;
4490
20.1k
        case GDT_CFloat64:
4491
20.1k
            GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData),
4492
20.1k
                                       nSrcPixelStride, true, pDstData,
4493
20.1k
                                       eDstType, nDstPixelStride, nWordCount);
4494
20.1k
            break;
4495
0
        case GDT_Unknown:
4496
0
        case GDT_TypeCount:
4497
0
            CPLAssert(false);
4498
256M
    }
4499
256M
}
4500
4501
/************************************************************************/
4502
/*                            GDALCopyBits()                            */
4503
/************************************************************************/
4504
4505
/**
4506
 * Bitwise word copying.
4507
 *
4508
 * A function for moving sets of partial bytes around.  Loosely
4509
 * speaking this is a bitwise analog to GDALCopyWords().
4510
 *
4511
 * It copies nStepCount "words" where each word is nBitCount bits long.
4512
 * The nSrcStep and nDstStep are the number of bits from the start of one
4513
 * word to the next (same as nBitCount if they are packed).  The nSrcOffset
4514
 * and nDstOffset are the offset into the source and destination buffers
4515
 * to start at, also measured in bits.
4516
 *
4517
 * All bit offsets are assumed to start from the high order bit in a byte
4518
 * (i.e. most significant bit first).  Currently this function is not very
4519
 * optimized, but it may be improved for some common cases in the future
4520
 * as needed.
4521
 *
4522
 * @param pabySrcData the source data buffer.
4523
 * @param nSrcOffset the offset (in bits) in pabySrcData to the start of the
4524
 * first word to copy.
4525
 * @param nSrcStep the offset in bits from the start one source word to the
4526
 * start of the next.
4527
 * @param pabyDstData the destination data buffer.
4528
 * @param nDstOffset the offset (in bits) in pabyDstData to the start of the
4529
 * first word to copy over.
4530
 * @param nDstStep the offset in bits from the start one word to the
4531
 * start of the next.
4532
 * @param nBitCount the number of bits in a word to be copied.
4533
 * @param nStepCount the number of words to copy.
4534
 */
4535
4536
void GDALCopyBits(const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
4537
                  GByte *pabyDstData, int nDstOffset, int nDstStep,
4538
                  int nBitCount, int nStepCount)
4539
4540
0
{
4541
0
    VALIDATE_POINTER0(pabySrcData, "GDALCopyBits");
4542
4543
0
    for (int iStep = 0; iStep < nStepCount; iStep++)
4544
0
    {
4545
0
        for (int iBit = 0; iBit < nBitCount; iBit++)
4546
0
        {
4547
0
            if (pabySrcData[nSrcOffset >> 3] & (0x80 >> (nSrcOffset & 7)))
4548
0
                pabyDstData[nDstOffset >> 3] |= (0x80 >> (nDstOffset & 7));
4549
0
            else
4550
0
                pabyDstData[nDstOffset >> 3] &= ~(0x80 >> (nDstOffset & 7));
4551
4552
0
            nSrcOffset++;
4553
0
            nDstOffset++;
4554
0
        }
4555
4556
0
        nSrcOffset += (nSrcStep - nBitCount);
4557
0
        nDstOffset += (nDstStep - nBitCount);
4558
0
    }
4559
0
}
4560
4561
/************************************************************************/
4562
/*                    GDALBandGetBestOverviewLevel()                    */
4563
/************************************************************************/
4564
4565
int GDALBandGetBestOverviewLevel(GDALRasterBand *poBand,
4566
                                 double dfTargetDownsamplingRatio,
4567
                                 double dfOversamplingThreshold)
4568
42.5k
{
4569
42.5k
    int iBestOvr = -1;
4570
42.5k
    double dfBestRatio = 0;
4571
42.5k
    const int nOvCount = poBand->GetOverviewCount();
4572
42.5k
    constexpr double EPSILON = 1e-1;
4573
117k
    for (int iOvr = -1; iOvr < nOvCount; iOvr++)
4574
78.3k
    {
4575
78.3k
        double dfOvrRatio = 1.0;
4576
78.3k
        GDALRasterBand *poOvrBand = nullptr;
4577
78.3k
        if (iOvr >= 0)
4578
35.8k
        {
4579
35.8k
            poOvrBand = poBand->GetOverview(iOvr);
4580
35.8k
            if (poOvrBand == nullptr ||
4581
35.8k
                poOvrBand->GetXSize() > poBand->GetXSize() ||
4582
34.9k
                poOvrBand->GetYSize() > poBand->GetYSize())
4583
2.97k
            {
4584
2.97k
                continue;
4585
2.97k
            }
4586
32.8k
            dfOvrRatio = std::min(static_cast<double>(poBand->GetXSize()) /
4587
32.8k
                                      poOvrBand->GetXSize(),
4588
32.8k
                                  static_cast<double>(poBand->GetYSize()) /
4589
32.8k
                                      poOvrBand->GetYSize());
4590
32.8k
        }
4591
4592
        // Is it nearly the requested factor and better (lower) than
4593
        // the current best factor?
4594
        // Use an epsilon because of numerical instability.
4595
75.4k
        if (dfOvrRatio >=
4596
75.4k
                dfTargetDownsamplingRatio * dfOversamplingThreshold + EPSILON ||
4597
74.1k
            dfOvrRatio <= dfBestRatio)
4598
20.1k
        {
4599
20.1k
            continue;
4600
20.1k
        }
4601
4602
55.2k
        if (poOvrBand)
4603
13.3k
        {
4604
            // Ignore AVERAGE_BIT2GRAYSCALE overviews.
4605
13.3k
            const char *pszResampling =
4606
13.3k
                poOvrBand->GetMetadataItem("RESAMPLING");
4607
13.3k
            if (pszResampling != nullptr &&
4608
0
                STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2"))
4609
0
            {
4610
0
                continue;
4611
0
            }
4612
13.3k
        }
4613
4614
55.2k
        iBestOvr = iOvr;
4615
55.2k
        dfBestRatio = dfOvrRatio;
4616
55.2k
        if (std::abs(dfTargetDownsamplingRatio - dfOvrRatio) < EPSILON)
4617
3.73k
        {
4618
3.73k
            break;
4619
3.73k
        }
4620
55.2k
    }
4621
42.5k
    return iBestOvr;
4622
42.5k
}
4623
4624
/************************************************************************/
4625
/*                    GDALGetBestOverviewLevel()                        */
4626
/*                                                                      */
4627
/* Returns the best overview level to satisfy the query or -1 if none   */
4628
/* Also updates nXOff, nYOff, nXSize, nYSize and psExtraArg when        */
4629
/* returning a valid overview level                                     */
4630
/************************************************************************/
4631
4632
int GDALBandGetBestOverviewLevel(GDALRasterBand *poBand, int &nXOff, int &nYOff,
4633
                                 int &nXSize, int &nYSize, int nBufXSize,
4634
                                 int nBufYSize)
4635
0
{
4636
0
    return GDALBandGetBestOverviewLevel2(poBand, nXOff, nYOff, nXSize, nYSize,
4637
0
                                         nBufXSize, nBufYSize, nullptr);
4638
0
}
4639
4640
int GDALBandGetBestOverviewLevel2(GDALRasterBand *poBand, int &nXOff,
4641
                                  int &nYOff, int &nXSize, int &nYSize,
4642
                                  int nBufXSize, int nBufYSize,
4643
                                  GDALRasterIOExtraArg *psExtraArg)
4644
42.5k
{
4645
42.5k
    if (psExtraArg != nullptr && psExtraArg->nVersion > 1 &&
4646
42.5k
        psExtraArg->bUseOnlyThisScale)
4647
0
        return -1;
4648
    /* -------------------------------------------------------------------- */
4649
    /*      Compute the desired downsampling factor.  It is                 */
4650
    /*      based on the least reduced axis, and represents the number      */
4651
    /*      of source pixels to one destination pixel.                      */
4652
    /* -------------------------------------------------------------------- */
4653
42.5k
    const double dfDesiredDownsamplingFactor =
4654
42.5k
        ((nXSize / static_cast<double>(nBufXSize)) <
4655
42.5k
             (nYSize / static_cast<double>(nBufYSize)) ||
4656
36.4k
         nBufYSize == 1)
4657
42.5k
            ? nXSize / static_cast<double>(nBufXSize)
4658
42.5k
            : nYSize / static_cast<double>(nBufYSize);
4659
4660
    /* -------------------------------------------------------------------- */
4661
    /*      Find the overview level that largest downsampling factor (most  */
4662
    /*      downsampled) that is still less than (or only a little more)    */
4663
    /*      downsampled than the request.                                   */
4664
    /* -------------------------------------------------------------------- */
4665
4666
42.5k
    const char *pszOversampligThreshold =
4667
42.5k
        CPLGetConfigOption("GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD", nullptr);
4668
4669
    // Cf https://github.com/OSGeo/gdal/pull/9040#issuecomment-1898524693
4670
42.5k
    const double dfOversamplingThreshold =
4671
42.5k
        pszOversampligThreshold ? CPLAtof(pszOversampligThreshold)
4672
42.5k
        : psExtraArg && psExtraArg->eResampleAlg != GRIORA_NearestNeighbour
4673
42.5k
            ? 1.0
4674
42.5k
            : 1.2;
4675
42.5k
    const int iBestOvrLevel = GDALBandGetBestOverviewLevel(
4676
42.5k
        poBand, dfDesiredDownsamplingFactor, dfOversamplingThreshold);
4677
4678
    /* -------------------------------------------------------------------- */
4679
    /*      If we didn't find an overview that helps us, just return        */
4680
    /*      indicating failure and the full resolution image will be used.  */
4681
    /* -------------------------------------------------------------------- */
4682
42.5k
    if (iBestOvrLevel < 0)
4683
31.6k
        return -1;
4684
10.8k
    const GDALRasterBand *poBestOverview = poBand->GetOverview(iBestOvrLevel);
4685
4686
    /* -------------------------------------------------------------------- */
4687
    /*      Recompute the source window in terms of the selected            */
4688
    /*      overview.                                                       */
4689
    /* -------------------------------------------------------------------- */
4690
10.8k
    const double dfXFactor =
4691
10.8k
        poBand->GetXSize() / static_cast<double>(poBestOverview->GetXSize());
4692
10.8k
    const double dfYFactor =
4693
10.8k
        poBand->GetYSize() / static_cast<double>(poBestOverview->GetYSize());
4694
10.8k
    CPLDebug("GDAL", "Selecting overview %d x %d", poBestOverview->GetXSize(),
4695
10.8k
             poBestOverview->GetYSize());
4696
4697
10.8k
    const int nOXOff = std::min(poBestOverview->GetXSize() - 1,
4698
10.8k
                                static_cast<int>(nXOff / dfXFactor + 0.5));
4699
10.8k
    const int nOYOff = std::min(poBestOverview->GetYSize() - 1,
4700
10.8k
                                static_cast<int>(nYOff / dfYFactor + 0.5));
4701
10.8k
    int nOXSize = std::max(1, static_cast<int>(nXSize / dfXFactor + 0.5));
4702
10.8k
    int nOYSize = std::max(1, static_cast<int>(nYSize / dfYFactor + 0.5));
4703
10.8k
    if (nOXOff + nOXSize > poBestOverview->GetXSize())
4704
0
        nOXSize = poBestOverview->GetXSize() - nOXOff;
4705
10.8k
    if (nOYOff + nOYSize > poBestOverview->GetYSize())
4706
0
        nOYSize = poBestOverview->GetYSize() - nOYOff;
4707
4708
10.8k
    if (psExtraArg)
4709
10.8k
    {
4710
10.8k
        if (psExtraArg->bFloatingPointWindowValidity)
4711
10.8k
        {
4712
10.8k
            psExtraArg->dfXOff /= dfXFactor;
4713
10.8k
            psExtraArg->dfXSize /= dfXFactor;
4714
10.8k
            psExtraArg->dfYOff /= dfYFactor;
4715
10.8k
            psExtraArg->dfYSize /= dfYFactor;
4716
10.8k
        }
4717
0
        else if (psExtraArg->eResampleAlg != GRIORA_NearestNeighbour)
4718
0
        {
4719
0
            psExtraArg->bFloatingPointWindowValidity = true;
4720
0
            psExtraArg->dfXOff = nXOff / dfXFactor;
4721
0
            psExtraArg->dfXSize = nXSize / dfXFactor;
4722
0
            psExtraArg->dfYOff = nYOff / dfYFactor;
4723
0
            psExtraArg->dfYSize = nYSize / dfYFactor;
4724
0
        }
4725
10.8k
    }
4726
4727
10.8k
    nXOff = nOXOff;
4728
10.8k
    nYOff = nOYOff;
4729
10.8k
    nXSize = nOXSize;
4730
10.8k
    nYSize = nOYSize;
4731
4732
10.8k
    return iBestOvrLevel;
4733
42.5k
}
4734
4735
/************************************************************************/
4736
/*                          OverviewRasterIO()                          */
4737
/*                                                                      */
4738
/*      Special work function to utilize available overviews to         */
4739
/*      more efficiently satisfy downsampled requests.  It will         */
4740
/*      return CE_Failure if there are no appropriate overviews         */
4741
/*      available but it doesn't emit any error messages.               */
4742
/************************************************************************/
4743
4744
//! @cond Doxygen_Suppress
4745
CPLErr GDALRasterBand::OverviewRasterIO(
4746
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
4747
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
4748
    GSpacing nPixelSpace, GSpacing nLineSpace, GDALRasterIOExtraArg *psExtraArg)
4749
4750
109
{
4751
109
    GDALRasterIOExtraArg sExtraArg;
4752
109
    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
4753
4754
109
    const int nOverview = GDALBandGetBestOverviewLevel2(
4755
109
        this, nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, &sExtraArg);
4756
109
    if (nOverview < 0)
4757
13
        return CE_Failure;
4758
4759
    /* -------------------------------------------------------------------- */
4760
    /*      Recast the call in terms of the new raster layer.               */
4761
    /* -------------------------------------------------------------------- */
4762
96
    GDALRasterBand *poOverviewBand = GetOverview(nOverview);
4763
96
    if (poOverviewBand == nullptr)
4764
0
        return CE_Failure;
4765
4766
96
    return poOverviewBand->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
4767
96
                                    pData, nBufXSize, nBufYSize, eBufType,
4768
96
                                    nPixelSpace, nLineSpace, &sExtraArg);
4769
96
}
4770
4771
/************************************************************************/
4772
/*                        TryOverviewRasterIO()                         */
4773
/************************************************************************/
4774
4775
CPLErr GDALRasterBand::TryOverviewRasterIO(
4776
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
4777
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
4778
    GSpacing nPixelSpace, GSpacing nLineSpace, GDALRasterIOExtraArg *psExtraArg,
4779
    int *pbTried)
4780
12.2k
{
4781
12.2k
    int nXOffMod = nXOff;
4782
12.2k
    int nYOffMod = nYOff;
4783
12.2k
    int nXSizeMod = nXSize;
4784
12.2k
    int nYSizeMod = nYSize;
4785
12.2k
    GDALRasterIOExtraArg sExtraArg;
4786
4787
12.2k
    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
4788
4789
12.2k
    int iOvrLevel = GDALBandGetBestOverviewLevel2(
4790
12.2k
        this, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod, nBufXSize, nBufYSize,
4791
12.2k
        &sExtraArg);
4792
4793
12.2k
    if (iOvrLevel >= 0)
4794
4.22k
    {
4795
4.22k
        GDALRasterBand *poOverviewBand = GetOverview(iOvrLevel);
4796
4.22k
        if (poOverviewBand)
4797
4.22k
        {
4798
4.22k
            *pbTried = TRUE;
4799
4.22k
            return poOverviewBand->RasterIO(
4800
4.22k
                eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod, pData,
4801
4.22k
                nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace,
4802
4.22k
                &sExtraArg);
4803
4.22k
        }
4804
4.22k
    }
4805
4806
8.03k
    *pbTried = FALSE;
4807
8.03k
    return CE_None;
4808
12.2k
}
4809
4810
/************************************************************************/
4811
/*                        TryOverviewRasterIO()                         */
4812
/************************************************************************/
4813
4814
CPLErr GDALDataset::TryOverviewRasterIO(
4815
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
4816
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
4817
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
4818
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg,
4819
    int *pbTried)
4820
2.13k
{
4821
2.13k
    int nXOffMod = nXOff;
4822
2.13k
    int nYOffMod = nYOff;
4823
2.13k
    int nXSizeMod = nXSize;
4824
2.13k
    int nYSizeMod = nYSize;
4825
2.13k
    GDALRasterIOExtraArg sExtraArg;
4826
2.13k
    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
4827
4828
2.13k
    int iOvrLevel = GDALBandGetBestOverviewLevel2(
4829
2.13k
        papoBands[0], nXOffMod, nYOffMod, nXSizeMod, nYSizeMod, nBufXSize,
4830
2.13k
        nBufYSize, &sExtraArg);
4831
4832
2.13k
    if (iOvrLevel >= 0 && papoBands[0]->GetOverview(iOvrLevel) != nullptr &&
4833
41
        papoBands[0]->GetOverview(iOvrLevel)->GetDataset() != nullptr)
4834
41
    {
4835
41
        *pbTried = TRUE;
4836
41
        return papoBands[0]->GetOverview(iOvrLevel)->GetDataset()->RasterIO(
4837
41
            eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod, pData, nBufXSize,
4838
41
            nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
4839
41
            nLineSpace, nBandSpace, &sExtraArg);
4840
41
    }
4841
2.09k
    else
4842
2.09k
    {
4843
2.09k
        *pbTried = FALSE;
4844
2.09k
        return CE_None;
4845
2.09k
    }
4846
2.13k
}
4847
4848
/************************************************************************/
4849
/*                        GetBestOverviewLevel()                        */
4850
/*                                                                      */
4851
/* Returns the best overview level to satisfy the query or -1 if none   */
4852
/* Also updates nXOff, nYOff, nXSize, nYSize when returning a valid     */
4853
/* overview level                                                       */
4854
/************************************************************************/
4855
4856
static int GDALDatasetGetBestOverviewLevel(GDALDataset *poDS, int &nXOff,
4857
                                           int &nYOff, int &nXSize, int &nYSize,
4858
                                           int nBufXSize, int nBufYSize,
4859
                                           int nBandCount,
4860
                                           const int *panBandMap,
4861
                                           GDALRasterIOExtraArg *psExtraArg)
4862
1
{
4863
1
    int nOverviewCount = 0;
4864
1
    GDALRasterBand *poFirstBand = nullptr;
4865
4866
    /* -------------------------------------------------------------------- */
4867
    /* Check that all bands have the same number of overviews and           */
4868
    /* that they have all the same size and block dimensions                */
4869
    /* -------------------------------------------------------------------- */
4870
4
    for (int iBand = 0; iBand < nBandCount; iBand++)
4871
3
    {
4872
3
        GDALRasterBand *poBand = poDS->GetRasterBand(panBandMap[iBand]);
4873
3
        if (poBand == nullptr)
4874
0
            return -1;
4875
3
        if (iBand == 0)
4876
1
        {
4877
1
            poFirstBand = poBand;
4878
1
            nOverviewCount = poBand->GetOverviewCount();
4879
1
        }
4880
2
        else if (nOverviewCount != poBand->GetOverviewCount())
4881
0
        {
4882
0
            CPLDebug("GDAL", "GDALDataset::GetBestOverviewLevel() ... "
4883
0
                             "mismatched overview count, use std method.");
4884
0
            return -1;
4885
0
        }
4886
2
        else
4887
2
        {
4888
2
            for (int iOverview = 0; iOverview < nOverviewCount; iOverview++)
4889
0
            {
4890
0
                GDALRasterBand *poOvrBand = poBand->GetOverview(iOverview);
4891
0
                GDALRasterBand *poOvrFirstBand =
4892
0
                    poFirstBand->GetOverview(iOverview);
4893
0
                if (poOvrBand == nullptr || poOvrFirstBand == nullptr)
4894
0
                    continue;
4895
4896
0
                if (poOvrFirstBand->GetXSize() != poOvrBand->GetXSize() ||
4897
0
                    poOvrFirstBand->GetYSize() != poOvrBand->GetYSize())
4898
0
                {
4899
0
                    CPLDebug("GDAL",
4900
0
                             "GDALDataset::GetBestOverviewLevel() ... "
4901
0
                             "mismatched overview sizes, use std method.");
4902
0
                    return -1;
4903
0
                }
4904
0
                int nBlockXSizeFirst = 0;
4905
0
                int nBlockYSizeFirst = 0;
4906
0
                poOvrFirstBand->GetBlockSize(&nBlockXSizeFirst,
4907
0
                                             &nBlockYSizeFirst);
4908
4909
0
                int nBlockXSizeCurrent = 0;
4910
0
                int nBlockYSizeCurrent = 0;
4911
0
                poOvrBand->GetBlockSize(&nBlockXSizeCurrent,
4912
0
                                        &nBlockYSizeCurrent);
4913
4914
0
                if (nBlockXSizeFirst != nBlockXSizeCurrent ||
4915
0
                    nBlockYSizeFirst != nBlockYSizeCurrent)
4916
0
                {
4917
0
                    CPLDebug("GDAL", "GDALDataset::GetBestOverviewLevel() ... "
4918
0
                                     "mismatched block sizes, use std method.");
4919
0
                    return -1;
4920
0
                }
4921
0
            }
4922
2
        }
4923
3
    }
4924
1
    if (poFirstBand == nullptr)
4925
0
        return -1;
4926
4927
1
    return GDALBandGetBestOverviewLevel2(poFirstBand, nXOff, nYOff, nXSize,
4928
1
                                         nYSize, nBufXSize, nBufYSize,
4929
1
                                         psExtraArg);
4930
1
}
4931
4932
/************************************************************************/
4933
/*                         BlockBasedRasterIO()                         */
4934
/*                                                                      */
4935
/*      This convenience function implements a dataset level            */
4936
/*      RasterIO() interface based on calling down to fetch blocks,     */
4937
/*      much like the GDALRasterBand::IRasterIO(), but it handles       */
4938
/*      all bands at once, so that a format driver that handles a       */
4939
/*      request for different bands of the same block efficiently       */
4940
/*      (i.e. without re-reading interleaved data) will efficiently.    */
4941
/*                                                                      */
4942
/*      This method is intended to be called by an overridden           */
4943
/*      IRasterIO() method in the driver specific GDALDataset           */
4944
/*      derived class.                                                  */
4945
/*                                                                      */
4946
/*      Default internal implementation of RasterIO() ... utilizes      */
4947
/*      the Block access methods to satisfy the request.  This would    */
4948
/*      normally only be overridden by formats with overviews.          */
4949
/*                                                                      */
4950
/*      To keep things relatively simple, this method does not          */
4951
/*      currently take advantage of some special cases addressed in     */
4952
/*      GDALRasterBand::IRasterIO(), so it is likely best to only       */
4953
/*      call it when you know it will help.  That is in cases where     */
4954
/*      data is at 1:1 to the buffer, and you know the driver is        */
4955
/*      implementing interleaved IO efficiently on a block by block     */
4956
/*      basis. Overviews will be used when possible.                    */
4957
/************************************************************************/
4958
4959
CPLErr GDALDataset::BlockBasedRasterIO(
4960
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
4961
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
4962
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
4963
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
4964
4965
830
{
4966
830
    CPLAssert(nullptr != pData);
4967
4968
830
    GByte **papabySrcBlock = nullptr;
4969
830
    GDALRasterBlock *poBlock = nullptr;
4970
830
    GDALRasterBlock **papoBlocks = nullptr;
4971
830
    int nLBlockX = -1;
4972
830
    int nLBlockY = -1;
4973
830
    int iBufYOff;
4974
830
    int iBufXOff;
4975
830
    int nBlockXSize = 1;
4976
830
    int nBlockYSize = 1;
4977
830
    CPLErr eErr = CE_None;
4978
830
    GDALDataType eDataType = GDT_UInt8;
4979
4980
830
    const bool bUseIntegerRequestCoords =
4981
830
        (!psExtraArg->bFloatingPointWindowValidity ||
4982
41
         (nXOff == psExtraArg->dfXOff && nYOff == psExtraArg->dfYOff &&
4983
41
          nXSize == psExtraArg->dfXSize && nYSize == psExtraArg->dfYSize));
4984
4985
    /* -------------------------------------------------------------------- */
4986
    /*      Ensure that all bands share a common block size and data type.  */
4987
    /* -------------------------------------------------------------------- */
4988
38.0k
    for (int iBand = 0; iBand < nBandCount; iBand++)
4989
37.2k
    {
4990
37.2k
        GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
4991
4992
37.2k
        if (iBand == 0)
4993
830
        {
4994
830
            poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
4995
830
            eDataType = poBand->GetRasterDataType();
4996
830
        }
4997
36.4k
        else
4998
36.4k
        {
4999
36.4k
            int nThisBlockXSize = 0;
5000
36.4k
            int nThisBlockYSize = 0;
5001
36.4k
            poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
5002
36.4k
            if (nThisBlockXSize != nBlockXSize ||
5003
36.4k
                nThisBlockYSize != nBlockYSize)
5004
0
            {
5005
0
                CPLDebug("GDAL", "GDALDataset::BlockBasedRasterIO() ... "
5006
0
                                 "mismatched block sizes, use std method.");
5007
0
                return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
5008
0
                                         pData, nBufXSize, nBufYSize, eBufType,
5009
0
                                         nBandCount, panBandMap, nPixelSpace,
5010
0
                                         nLineSpace, nBandSpace, psExtraArg);
5011
0
            }
5012
5013
36.4k
            if (eDataType != poBand->GetRasterDataType() &&
5014
626
                (nXSize != nBufXSize || nYSize != nBufYSize))
5015
0
            {
5016
0
                CPLDebug("GDAL", "GDALDataset::BlockBasedRasterIO() ... "
5017
0
                                 "mismatched band data types, use std method.");
5018
0
                return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
5019
0
                                         pData, nBufXSize, nBufYSize, eBufType,
5020
0
                                         nBandCount, panBandMap, nPixelSpace,
5021
0
                                         nLineSpace, nBandSpace, psExtraArg);
5022
0
            }
5023
36.4k
        }
5024
37.2k
    }
5025
5026
    /* ==================================================================== */
5027
    /*      In this special case at full resolution we step through in      */
5028
    /*      blocks, turning the request over to the per-band                */
5029
    /*      IRasterIO(), but ensuring that all bands of one block are       */
5030
    /*      called before proceeding to the next.                           */
5031
    /* ==================================================================== */
5032
5033
830
    if (nXSize == nBufXSize && nYSize == nBufYSize && bUseIntegerRequestCoords)
5034
829
    {
5035
829
        GDALRasterIOExtraArg sDummyExtraArg;
5036
829
        INIT_RASTERIO_EXTRA_ARG(sDummyExtraArg);
5037
5038
829
        int nChunkYSize = 0;
5039
829
        int nChunkXSize = 0;
5040
5041
16.6k
        for (iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff += nChunkYSize)
5042
15.9k
        {
5043
15.9k
            const int nChunkYOff = iBufYOff + nYOff;
5044
15.9k
            nChunkYSize = std::min(nBlockYSize - (nChunkYOff % nBlockYSize),
5045
15.9k
                                   (nYOff + nYSize) - nChunkYOff);
5046
5047
32.5k
            for (iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff += nChunkXSize)
5048
16.7k
            {
5049
16.7k
                const int nChunkXOff = iBufXOff + nXOff;
5050
16.7k
                nChunkXSize = std::min(nBlockXSize - (nChunkXOff % nBlockXSize),
5051
16.7k
                                       (nXOff + nXSize) - nChunkXOff);
5052
5053
16.7k
                GByte *pabyChunkData =
5054
16.7k
                    static_cast<GByte *>(pData) + iBufXOff * nPixelSpace +
5055
16.7k
                    static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace;
5056
5057
122k
                for (int iBand = 0; iBand < nBandCount; iBand++)
5058
105k
                {
5059
105k
                    GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
5060
5061
105k
                    eErr = poBand->IRasterIO(
5062
105k
                        eRWFlag, nChunkXOff, nChunkYOff, nChunkXSize,
5063
105k
                        nChunkYSize,
5064
105k
                        pabyChunkData +
5065
105k
                            static_cast<GPtrDiff_t>(iBand) * nBandSpace,
5066
105k
                        nChunkXSize, nChunkYSize, eBufType, nPixelSpace,
5067
105k
                        nLineSpace, &sDummyExtraArg);
5068
105k
                    if (eErr != CE_None)
5069
210
                        return eErr;
5070
105k
                }
5071
16.7k
            }
5072
5073
15.7k
            if (psExtraArg->pfnProgress != nullptr &&
5074
923
                !psExtraArg->pfnProgress(
5075
923
                    1.0 * std::min(nBufYSize, iBufYOff + nChunkYSize) /
5076
923
                        nBufYSize,
5077
923
                    "", psExtraArg->pProgressData))
5078
0
            {
5079
0
                return CE_Failure;
5080
0
            }
5081
15.7k
        }
5082
5083
619
        return CE_None;
5084
829
    }
5085
5086
    /* Below code is not compatible with that case. It would need a complete */
5087
    /* separate code like done in GDALRasterBand::IRasterIO. */
5088
1
    if (eRWFlag == GF_Write && (nBufXSize < nXSize || nBufYSize < nYSize))
5089
0
    {
5090
0
        return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
5091
0
                                 nBufXSize, nBufYSize, eBufType, nBandCount,
5092
0
                                 panBandMap, nPixelSpace, nLineSpace,
5093
0
                                 nBandSpace, psExtraArg);
5094
0
    }
5095
5096
    /* We could have a smarter implementation, but that will do for now */
5097
1
    if (psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
5098
0
        (nBufXSize != nXSize || nBufYSize != nYSize))
5099
0
    {
5100
0
        return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
5101
0
                                 nBufXSize, nBufYSize, eBufType, nBandCount,
5102
0
                                 panBandMap, nPixelSpace, nLineSpace,
5103
0
                                 nBandSpace, psExtraArg);
5104
0
    }
5105
5106
    /* ==================================================================== */
5107
    /*      Loop reading required source blocks to satisfy output           */
5108
    /*      request.  This is the most general implementation.              */
5109
    /* ==================================================================== */
5110
5111
1
    const int nBandDataSize = GDALGetDataTypeSizeBytes(eDataType);
5112
5113
1
    papabySrcBlock =
5114
1
        static_cast<GByte **>(CPLCalloc(sizeof(GByte *), nBandCount));
5115
1
    papoBlocks =
5116
1
        static_cast<GDALRasterBlock **>(CPLCalloc(sizeof(void *), nBandCount));
5117
5118
    /* -------------------------------------------------------------------- */
5119
    /*      Select an overview level if appropriate.                        */
5120
    /* -------------------------------------------------------------------- */
5121
5122
1
    GDALRasterIOExtraArg sExtraArg;
5123
1
    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
5124
1
    const int nOverviewLevel = GDALDatasetGetBestOverviewLevel(
5125
1
        this, nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount,
5126
1
        panBandMap, &sExtraArg);
5127
1
    if (nOverviewLevel >= 0)
5128
0
    {
5129
0
        GetRasterBand(panBandMap[0])
5130
0
            ->GetOverview(nOverviewLevel)
5131
0
            ->GetBlockSize(&nBlockXSize, &nBlockYSize);
5132
0
    }
5133
5134
1
    double dfXOff = nXOff;
5135
1
    double dfYOff = nYOff;
5136
1
    double dfXSize = nXSize;
5137
1
    double dfYSize = nYSize;
5138
1
    if (sExtraArg.bFloatingPointWindowValidity)
5139
1
    {
5140
1
        dfXOff = sExtraArg.dfXOff;
5141
1
        dfYOff = sExtraArg.dfYOff;
5142
1
        dfXSize = sExtraArg.dfXSize;
5143
1
        dfYSize = sExtraArg.dfYSize;
5144
1
    }
5145
5146
    /* -------------------------------------------------------------------- */
5147
    /*      Compute stepping increment.                                     */
5148
    /* -------------------------------------------------------------------- */
5149
1
    const double dfSrcXInc = dfXSize / static_cast<double>(nBufXSize);
5150
1
    const double dfSrcYInc = dfYSize / static_cast<double>(nBufYSize);
5151
5152
1
    constexpr double EPS = 1e-10;
5153
    /* -------------------------------------------------------------------- */
5154
    /*      Loop over buffer computing source locations.                    */
5155
    /* -------------------------------------------------------------------- */
5156
2
    for (iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++)
5157
1
    {
5158
1
        GPtrDiff_t iSrcOffset;
5159
5160
        // Add small epsilon to avoid some numeric precision issues.
5161
1
        const double dfSrcY = (iBufYOff + 0.5) * dfSrcYInc + dfYOff + EPS;
5162
1
        const int iSrcY = static_cast<int>(std::min(
5163
1
            std::max(0.0, dfSrcY), static_cast<double>(nRasterYSize - 1)));
5164
5165
1
        GPtrDiff_t iBufOffset = static_cast<GPtrDiff_t>(iBufYOff) *
5166
1
                                static_cast<GPtrDiff_t>(nLineSpace);
5167
5168
4.55k
        for (iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++)
5169
4.55k
        {
5170
4.55k
            const double dfSrcX = (iBufXOff + 0.5) * dfSrcXInc + dfXOff + EPS;
5171
4.55k
            const int iSrcX = static_cast<int>(std::min(
5172
4.55k
                std::max(0.0, dfSrcX), static_cast<double>(nRasterXSize - 1)));
5173
5174
            // FIXME: this code likely doesn't work if the dirty block gets
5175
            // flushed to disk before being completely written. In the meantime,
5176
            // bJustInitialize should probably be set to FALSE even if it is not
5177
            // ideal performance wise, and for lossy compression
5178
5179
            /* --------------------------------------------------------------------
5180
             */
5181
            /*      Ensure we have the appropriate block loaded. */
5182
            /* --------------------------------------------------------------------
5183
             */
5184
4.55k
            if (iSrcX < nLBlockX * nBlockXSize ||
5185
4.55k
                iSrcX - nBlockXSize >= nLBlockX * nBlockXSize ||
5186
4.55k
                iSrcY < nLBlockY * nBlockYSize ||
5187
4.55k
                iSrcY - nBlockYSize >= nLBlockY * nBlockYSize)
5188
1
            {
5189
1
                nLBlockX = iSrcX / nBlockXSize;
5190
1
                nLBlockY = iSrcY / nBlockYSize;
5191
5192
1
                const bool bJustInitialize =
5193
1
                    eRWFlag == GF_Write && nYOff <= nLBlockY * nBlockYSize &&
5194
0
                    nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize &&
5195
0
                    nXOff <= nLBlockX * nBlockXSize &&
5196
0
                    nXOff + nXSize - nBlockXSize >= nLBlockX * nBlockXSize;
5197
                /*bool bMemZeroBuffer = FALSE;
5198
                if( eRWFlag == GF_Write && !bJustInitialize &&
5199
                    nXOff <= nLBlockX * nBlockXSize &&
5200
                    nYOff <= nLBlockY * nBlockYSize &&
5201
                    (nXOff + nXSize >= (nLBlockX+1) * nBlockXSize ||
5202
                     (nXOff + nXSize == GetRasterXSize() &&
5203
                     (nLBlockX+1) * nBlockXSize > GetRasterXSize())) &&
5204
                    (nYOff + nYSize >= (nLBlockY+1) * nBlockYSize ||
5205
                     (nYOff + nYSize == GetRasterYSize() &&
5206
                     (nLBlockY+1) * nBlockYSize > GetRasterYSize())) )
5207
                {
5208
                    bJustInitialize = TRUE;
5209
                    bMemZeroBuffer = TRUE;
5210
                }*/
5211
4
                for (int iBand = 0; iBand < nBandCount; iBand++)
5212
3
                {
5213
3
                    GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
5214
3
                    if (nOverviewLevel >= 0)
5215
0
                        poBand = poBand->GetOverview(nOverviewLevel);
5216
3
                    poBlock = poBand->GetLockedBlockRef(nLBlockX, nLBlockY,
5217
3
                                                        bJustInitialize);
5218
3
                    if (poBlock == nullptr)
5219
0
                    {
5220
0
                        eErr = CE_Failure;
5221
0
                        goto CleanupAndReturn;
5222
0
                    }
5223
5224
3
                    if (eRWFlag == GF_Write)
5225
0
                        poBlock->MarkDirty();
5226
5227
3
                    if (papoBlocks[iBand] != nullptr)
5228
0
                        papoBlocks[iBand]->DropLock();
5229
5230
3
                    papoBlocks[iBand] = poBlock;
5231
5232
3
                    papabySrcBlock[iBand] =
5233
3
                        static_cast<GByte *>(poBlock->GetDataRef());
5234
                    /*if( bMemZeroBuffer )
5235
                    {
5236
                        memset(papabySrcBlock[iBand], 0,
5237
                            static_cast<GPtrDiff_t>(nBandDataSize) * nBlockXSize
5238
                    * nBlockYSize);
5239
                    }*/
5240
3
                }
5241
1
            }
5242
5243
            /* --------------------------------------------------------------------
5244
             */
5245
            /*      Copy over this pixel of data. */
5246
            /* --------------------------------------------------------------------
5247
             */
5248
4.55k
            iSrcOffset = (static_cast<GPtrDiff_t>(iSrcX) -
5249
4.55k
                          static_cast<GPtrDiff_t>(nLBlockX) * nBlockXSize +
5250
4.55k
                          (static_cast<GPtrDiff_t>(iSrcY) -
5251
4.55k
                           static_cast<GPtrDiff_t>(nLBlockY) * nBlockYSize) *
5252
4.55k
                              nBlockXSize) *
5253
4.55k
                         nBandDataSize;
5254
5255
18.2k
            for (int iBand = 0; iBand < nBandCount; iBand++)
5256
13.6k
            {
5257
13.6k
                GByte *pabySrcBlock = papabySrcBlock[iBand];
5258
13.6k
                GPtrDiff_t iBandBufOffset =
5259
13.6k
                    iBufOffset + static_cast<GPtrDiff_t>(iBand) *
5260
13.6k
                                     static_cast<GPtrDiff_t>(nBandSpace);
5261
5262
13.6k
                if (eDataType == eBufType)
5263
13.6k
                {
5264
13.6k
                    if (eRWFlag == GF_Read)
5265
13.6k
                        memcpy(static_cast<GByte *>(pData) + iBandBufOffset,
5266
13.6k
                               pabySrcBlock + iSrcOffset, nBandDataSize);
5267
0
                    else
5268
0
                        memcpy(pabySrcBlock + iSrcOffset,
5269
0
                               static_cast<const GByte *>(pData) +
5270
0
                                   iBandBufOffset,
5271
0
                               nBandDataSize);
5272
13.6k
                }
5273
0
                else
5274
0
                {
5275
                    /* type to type conversion ... ouch, this is expensive way
5276
                       of handling single words */
5277
5278
0
                    if (eRWFlag == GF_Read)
5279
0
                        GDALCopyWords64(pabySrcBlock + iSrcOffset, eDataType, 0,
5280
0
                                        static_cast<GByte *>(pData) +
5281
0
                                            iBandBufOffset,
5282
0
                                        eBufType, 0, 1);
5283
0
                    else
5284
0
                        GDALCopyWords64(static_cast<const GByte *>(pData) +
5285
0
                                            iBandBufOffset,
5286
0
                                        eBufType, 0, pabySrcBlock + iSrcOffset,
5287
0
                                        eDataType, 0, 1);
5288
0
                }
5289
13.6k
            }
5290
5291
4.55k
            iBufOffset += static_cast<int>(nPixelSpace);
5292
4.55k
        }
5293
1
    }
5294
5295
    /* -------------------------------------------------------------------- */
5296
    /*      CleanupAndReturn.                                               */
5297
    /* -------------------------------------------------------------------- */
5298
1
CleanupAndReturn:
5299
1
    CPLFree(papabySrcBlock);
5300
1
    if (papoBlocks != nullptr)
5301
1
    {
5302
4
        for (int iBand = 0; iBand < nBandCount; iBand++)
5303
3
        {
5304
3
            if (papoBlocks[iBand] != nullptr)
5305
3
                papoBlocks[iBand]->DropLock();
5306
3
        }
5307
1
        CPLFree(papoBlocks);
5308
1
    }
5309
5310
1
    return eErr;
5311
1
}
5312
5313
//! @endcond
5314
5315
/************************************************************************/
5316
/*                  GDALCopyWholeRasterGetSwathSize()                   */
5317
/************************************************************************/
5318
5319
static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
5320
                                            GDALRasterBand *poDstPrototypeBand,
5321
                                            int nBandCount,
5322
                                            int bDstIsCompressed,
5323
                                            int bInterleave, int *pnSwathCols,
5324
                                            int *pnSwathLines)
5325
1.15k
{
5326
1.15k
    GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
5327
1.15k
    int nSrcBlockXSize = 0;
5328
1.15k
    int nSrcBlockYSize = 0;
5329
1.15k
    int nBlockXSize = 0;
5330
1.15k
    int nBlockYSize = 0;
5331
5332
1.15k
    int nXSize = poSrcPrototypeBand->GetXSize();
5333
1.15k
    int nYSize = poSrcPrototypeBand->GetYSize();
5334
5335
1.15k
    poSrcPrototypeBand->GetBlockSize(&nSrcBlockXSize, &nSrcBlockYSize);
5336
1.15k
    poDstPrototypeBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
5337
5338
1.15k
    const int nMaxBlockXSize = std::max(nBlockXSize, nSrcBlockXSize);
5339
1.15k
    const int nMaxBlockYSize = std::max(nBlockYSize, nSrcBlockYSize);
5340
5341
1.15k
    int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
5342
1.15k
    if (bInterleave)
5343
571
        nPixelSize *= nBandCount;
5344
5345
    // aim for one row of blocks.  Do not settle for less.
5346
1.15k
    int nSwathCols = nXSize;
5347
1.15k
    int nSwathLines = nMaxBlockYSize;
5348
5349
1.15k
    const char *pszSrcCompression = poSrcPrototypeBand->GetMetadataItem(
5350
1.15k
        GDALMD_COMPRESSION, GDAL_MDD_IMAGE_STRUCTURE);
5351
1.15k
    if (pszSrcCompression == nullptr)
5352
1.15k
    {
5353
1.15k
        auto poSrcDS = poSrcPrototypeBand->GetDataset();
5354
1.15k
        if (poSrcDS)
5355
1.15k
            pszSrcCompression = poSrcDS->GetMetadataItem(
5356
1.15k
                GDALMD_COMPRESSION, GDAL_MDD_IMAGE_STRUCTURE);
5357
1.15k
    }
5358
5359
    /* -------------------------------------------------------------------- */
5360
    /*      What will our swath size be?                                    */
5361
    /* -------------------------------------------------------------------- */
5362
    // When writing interleaved data in a compressed format, we want to be sure
5363
    // that each block will only be written once, so the swath size must not be
5364
    // greater than the block cache.
5365
1.15k
    const char *pszSwathSize = CPLGetConfigOption("GDAL_SWATH_SIZE", nullptr);
5366
1.15k
    int nTargetSwathSize;
5367
1.15k
    if (pszSwathSize != nullptr)
5368
0
        nTargetSwathSize = static_cast<int>(
5369
0
            std::min(GIntBig(INT_MAX), CPLAtoGIntBig(pszSwathSize)));
5370
1.15k
    else
5371
1.15k
    {
5372
        // As a default, take one 1/4 of the cache size.
5373
1.15k
        nTargetSwathSize = static_cast<int>(
5374
1.15k
            std::min(GIntBig(INT_MAX), GDALGetCacheMax64() / 4));
5375
5376
        // but if the minimum idal swath buf size is less, then go for it to
5377
        // avoid unnecessarily abusing RAM usage.
5378
        // but try to use 10 MB at least.
5379
1.15k
        GIntBig nIdealSwathBufSize =
5380
1.15k
            static_cast<GIntBig>(nSwathCols) * nSwathLines * nPixelSize;
5381
1.15k
        int nMinTargetSwathSize = 10 * 1000 * 1000;
5382
5383
1.15k
        if ((poSrcPrototypeBand->GetSuggestedBlockAccessPattern() &
5384
1.15k
             GSBAP_LARGEST_CHUNK_POSSIBLE) != 0)
5385
0
        {
5386
0
            nMinTargetSwathSize = nTargetSwathSize;
5387
0
        }
5388
5389
1.15k
        if (nIdealSwathBufSize < nTargetSwathSize &&
5390
1.15k
            nIdealSwathBufSize < nMinTargetSwathSize)
5391
1.14k
        {
5392
1.14k
            nIdealSwathBufSize = nMinTargetSwathSize;
5393
1.14k
        }
5394
5395
1.15k
        if (pszSrcCompression != nullptr &&
5396
224
            EQUAL(pszSrcCompression, "JPEG2000") &&
5397
0
            (!bDstIsCompressed || ((nSrcBlockXSize % nBlockXSize) == 0 &&
5398
0
                                   (nSrcBlockYSize % nBlockYSize) == 0)))
5399
0
        {
5400
0
            nIdealSwathBufSize =
5401
0
                std::max(nIdealSwathBufSize, static_cast<GIntBig>(nSwathCols) *
5402
0
                                                 nSrcBlockYSize * nPixelSize);
5403
0
        }
5404
1.15k
        if (nTargetSwathSize > nIdealSwathBufSize)
5405
1.15k
            nTargetSwathSize = static_cast<int>(
5406
1.15k
                std::min(GIntBig(INT_MAX), nIdealSwathBufSize));
5407
1.15k
    }
5408
5409
1.15k
    if (nTargetSwathSize < 1000000)
5410
0
        nTargetSwathSize = 1000000;
5411
5412
    /* But let's check that  */
5413
1.15k
    if (bDstIsCompressed && bInterleave &&
5414
0
        nTargetSwathSize > GDALGetCacheMax64())
5415
0
    {
5416
0
        CPLError(CE_Warning, CPLE_AppDefined,
5417
0
                 "When translating into a compressed interleave format, "
5418
0
                 "the block cache size (" CPL_FRMT_GIB ") "
5419
0
                 "should be at least the size of the swath (%d) "
5420
0
                 "(GDAL_SWATH_SIZE config. option)",
5421
0
                 GDALGetCacheMax64(), nTargetSwathSize);
5422
0
    }
5423
5424
5.37k
#define IS_DIVIDER_OF(x, y) ((y) % (x) == 0)
5425
1.15k
#define ROUND_TO(x, y) (((x) / (y)) * (y))
5426
5427
    // if both input and output datasets are tiled, that the tile dimensions
5428
    // are "compatible", try to stick  to a swath dimension that is a multiple
5429
    // of input and output block dimensions.
5430
1.15k
    if (nBlockXSize != nXSize && nSrcBlockXSize != nXSize &&
5431
132
        IS_DIVIDER_OF(nBlockXSize, nMaxBlockXSize) &&
5432
129
        IS_DIVIDER_OF(nSrcBlockXSize, nMaxBlockXSize) &&
5433
124
        IS_DIVIDER_OF(nBlockYSize, nMaxBlockYSize) &&
5434
120
        IS_DIVIDER_OF(nSrcBlockYSize, nMaxBlockYSize))
5435
84
    {
5436
84
        if (static_cast<GIntBig>(nMaxBlockXSize) * nMaxBlockYSize *
5437
84
                nPixelSize <=
5438
84
            static_cast<GIntBig>(nTargetSwathSize))
5439
84
        {
5440
84
            nSwathCols = nTargetSwathSize / (nMaxBlockYSize * nPixelSize);
5441
84
            nSwathCols = ROUND_TO(nSwathCols, nMaxBlockXSize);
5442
84
            if (nSwathCols == 0)
5443
0
                nSwathCols = nMaxBlockXSize;
5444
84
            if (nSwathCols > nXSize)
5445
78
                nSwathCols = nXSize;
5446
84
            nSwathLines = nMaxBlockYSize;
5447
5448
84
            if (static_cast<GIntBig>(nSwathCols) * nSwathLines * nPixelSize >
5449
84
                static_cast<GIntBig>(nTargetSwathSize))
5450
0
            {
5451
0
                nSwathCols = nXSize;
5452
0
                nSwathLines = nBlockYSize;
5453
0
            }
5454
84
        }
5455
84
    }
5456
5457
1.15k
    const GIntBig nMemoryPerCol = static_cast<GIntBig>(nSwathCols) * nPixelSize;
5458
1.15k
    const GIntBig nSwathBufSize = nMemoryPerCol * nSwathLines;
5459
1.15k
    if (nSwathBufSize > static_cast<GIntBig>(nTargetSwathSize))
5460
0
    {
5461
0
        nSwathLines = static_cast<int>(nTargetSwathSize / nMemoryPerCol);
5462
0
        if (nSwathLines == 0)
5463
0
            nSwathLines = 1;
5464
5465
0
        CPLDebug(
5466
0
            "GDAL",
5467
0
            "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
5468
0
            "since requirement (" CPL_FRMT_GIB " bytes) exceed target swath "
5469
0
            "size (%d bytes) (GDAL_SWATH_SIZE config. option)",
5470
0
            nSwathLines, nBlockYSize * nMemoryPerCol, nTargetSwathSize);
5471
0
    }
5472
    // If we are processing single scans, try to handle several at once.
5473
    // If we are handling swaths already, only grow the swath if a row
5474
    // of blocks is substantially less than our target buffer size.
5475
1.15k
    else if (nSwathLines == 1 ||
5476
1.03k
             nMemoryPerCol * nSwathLines <
5477
1.03k
                 static_cast<GIntBig>(nTargetSwathSize) / 10)
5478
1.09k
    {
5479
1.09k
        nSwathLines = std::min(
5480
1.09k
            nYSize,
5481
1.09k
            std::max(1, static_cast<int>(nTargetSwathSize / nMemoryPerCol)));
5482
5483
        /* If possible try to align to source and target block height */
5484
1.09k
        if ((nSwathLines % nMaxBlockYSize) != 0 &&
5485
312
            nSwathLines > nMaxBlockYSize &&
5486
185
            IS_DIVIDER_OF(nBlockYSize, nMaxBlockYSize) &&
5487
132
            IS_DIVIDER_OF(nSrcBlockYSize, nMaxBlockYSize))
5488
107
            nSwathLines = ROUND_TO(nSwathLines, nMaxBlockYSize);
5489
1.09k
    }
5490
5491
1.15k
    if (pszSrcCompression != nullptr && EQUAL(pszSrcCompression, "JPEG2000") &&
5492
0
        (!bDstIsCompressed || (IS_DIVIDER_OF(nBlockXSize, nSrcBlockXSize) &&
5493
0
                               IS_DIVIDER_OF(nBlockYSize, nSrcBlockYSize))))
5494
0
    {
5495
        // Typical use case: converting from Pleaiades that is 2048x2048 tiled.
5496
0
        if (nSwathLines < nSrcBlockYSize)
5497
0
        {
5498
0
            nSwathLines = nSrcBlockYSize;
5499
5500
            // Number of pixels that can be read/write simultaneously.
5501
0
            nSwathCols = nTargetSwathSize / (nSrcBlockXSize * nPixelSize);
5502
0
            nSwathCols = ROUND_TO(nSwathCols, nSrcBlockXSize);
5503
0
            if (nSwathCols == 0)
5504
0
                nSwathCols = nSrcBlockXSize;
5505
0
            if (nSwathCols > nXSize)
5506
0
                nSwathCols = nXSize;
5507
5508
0
            CPLDebug(
5509
0
                "GDAL",
5510
0
                "GDALCopyWholeRasterGetSwathSize(): because of compression and "
5511
0
                "too high block, "
5512
0
                "use partial width at one time");
5513
0
        }
5514
0
        else if ((nSwathLines % nSrcBlockYSize) != 0)
5515
0
        {
5516
            /* Round on a multiple of nSrcBlockYSize */
5517
0
            nSwathLines = ROUND_TO(nSwathLines, nSrcBlockYSize);
5518
0
            CPLDebug(
5519
0
                "GDAL",
5520
0
                "GDALCopyWholeRasterGetSwathSize(): because of compression, "
5521
0
                "round nSwathLines to block height : %d",
5522
0
                nSwathLines);
5523
0
        }
5524
0
    }
5525
1.15k
    else if (bDstIsCompressed)
5526
67
    {
5527
67
        if (nSwathLines < nBlockYSize)
5528
9
        {
5529
9
            nSwathLines = nBlockYSize;
5530
5531
            // Number of pixels that can be read/write simultaneously.
5532
9
            nSwathCols = nTargetSwathSize / (nSwathLines * nPixelSize);
5533
9
            nSwathCols = ROUND_TO(nSwathCols, nBlockXSize);
5534
9
            if (nSwathCols == 0)
5535
0
                nSwathCols = nBlockXSize;
5536
9
            if (nSwathCols > nXSize)
5537
9
                nSwathCols = nXSize;
5538
5539
9
            CPLDebug(
5540
9
                "GDAL",
5541
9
                "GDALCopyWholeRasterGetSwathSize(): because of compression and "
5542
9
                "too high block, "
5543
9
                "use partial width at one time");
5544
9
        }
5545
58
        else if ((nSwathLines % nBlockYSize) != 0)
5546
7
        {
5547
            // Round on a multiple of nBlockYSize.
5548
7
            nSwathLines = ROUND_TO(nSwathLines, nBlockYSize);
5549
7
            CPLDebug(
5550
7
                "GDAL",
5551
7
                "GDALCopyWholeRasterGetSwathSize(): because of compression, "
5552
7
                "round nSwathLines to block height : %d",
5553
7
                nSwathLines);
5554
7
        }
5555
67
    }
5556
5557
1.15k
    *pnSwathCols = nSwathCols;
5558
1.15k
    *pnSwathLines = nSwathLines;
5559
1.15k
}
5560
5561
/************************************************************************/
5562
/*                     GDALDatasetCopyWholeRaster()                     */
5563
/************************************************************************/
5564
5565
/**
5566
 * \brief Copy all dataset raster data.
5567
 *
5568
 * This function copies the complete raster contents of one dataset to
5569
 * another similarly configured dataset.  The source and destination
5570
 * dataset must have the same number of bands, and the same width
5571
 * and height.  The bands do not have to have the same data type.
5572
 *
5573
 * This function is primarily intended to support implementation of
5574
 * driver specific CreateCopy() functions.  It implements efficient copying,
5575
 * in particular "chunking" the copy in substantial blocks and, if appropriate,
5576
 * performing the transfer in a pixel interleaved fashion.
5577
 *
5578
 * Currently the only papszOptions value supported are :
5579
 * <ul>
5580
 * <li>"INTERLEAVE=PIXEL/BAND" to force pixel (resp. band) interleaved read and
5581
 * write access pattern (this does not modify the layout of the destination
5582
 * data)</li>
5583
 * <li>"COMPRESSED=YES" to force alignment on target dataset block
5584
 * sizes to achieve best compression.</li>
5585
 * <li>"SKIP_HOLES=YES" to skip chunks
5586
 * for which GDALGetDataCoverageStatus() returns GDAL_DATA_COVERAGE_STATUS_EMPTY
5587
 * (GDAL &gt;= 2.2)</li>
5588
 * </ul>
5589
 * More options may be supported in the future.
5590
 *
5591
 * @param hSrcDS the source dataset
5592
 * @param hDstDS the destination dataset
5593
 * @param papszOptions transfer hints in "StringList" Name=Value format.
5594
 * @param pfnProgress progress reporting function.
5595
 * @param pProgressData callback data for progress function.
5596
 *
5597
 * @return CE_None on success, or CE_Failure on failure.
5598
 */
5599
5600
CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(GDALDatasetH hSrcDS,
5601
                                              GDALDatasetH hDstDS,
5602
                                              CSLConstList papszOptions,
5603
                                              GDALProgressFunc pfnProgress,
5604
                                              void *pProgressData)
5605
5606
1.08k
{
5607
1.08k
    VALIDATE_POINTER1(hSrcDS, "GDALDatasetCopyWholeRaster", CE_Failure);
5608
1.08k
    VALIDATE_POINTER1(hDstDS, "GDALDatasetCopyWholeRaster", CE_Failure);
5609
5610
1.08k
    GDALDataset *poSrcDS = GDALDataset::FromHandle(hSrcDS);
5611
1.08k
    GDALDataset *poDstDS = GDALDataset::FromHandle(hDstDS);
5612
5613
1.08k
    if (pfnProgress == nullptr)
5614
0
        pfnProgress = GDALDummyProgress;
5615
5616
    /* -------------------------------------------------------------------- */
5617
    /*      Confirm the datasets match in size and band counts.             */
5618
    /* -------------------------------------------------------------------- */
5619
1.08k
    const int nXSize = poDstDS->GetRasterXSize();
5620
1.08k
    const int nYSize = poDstDS->GetRasterYSize();
5621
1.08k
    const int nBandCount = poDstDS->GetRasterCount();
5622
5623
1.08k
    if (poSrcDS->GetRasterXSize() != nXSize ||
5624
1.08k
        poSrcDS->GetRasterYSize() != nYSize ||
5625
1.08k
        poSrcDS->GetRasterCount() != nBandCount)
5626
0
    {
5627
0
        CPLError(CE_Failure, CPLE_AppDefined,
5628
0
                 "Input and output dataset sizes or band counts do not\n"
5629
0
                 "match in GDALDatasetCopyWholeRaster()");
5630
0
        return CE_Failure;
5631
0
    }
5632
5633
    /* -------------------------------------------------------------------- */
5634
    /*      Report preliminary (0) progress.                                */
5635
    /* -------------------------------------------------------------------- */
5636
1.08k
    if (!pfnProgress(0.0, nullptr, pProgressData))
5637
0
    {
5638
0
        CPLError(CE_Failure, CPLE_UserInterrupt,
5639
0
                 "User terminated CreateCopy()");
5640
0
        return CE_Failure;
5641
0
    }
5642
5643
    /* -------------------------------------------------------------------- */
5644
    /*      Get our prototype band, and assume the others are similarly     */
5645
    /*      configured.                                                     */
5646
    /* -------------------------------------------------------------------- */
5647
1.08k
    if (nBandCount == 0)
5648
0
        return CE_None;
5649
5650
1.08k
    GDALRasterBand *poSrcPrototypeBand = poSrcDS->GetRasterBand(1);
5651
1.08k
    GDALRasterBand *poDstPrototypeBand = poDstDS->GetRasterBand(1);
5652
1.08k
    GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
5653
5654
    /* -------------------------------------------------------------------- */
5655
    /*      Do we want to try and do the operation in a pixel               */
5656
    /*      interleaved fashion?                                            */
5657
    /* -------------------------------------------------------------------- */
5658
1.08k
    bool bInterleave = false;
5659
1.08k
    const char *pszInterleave =
5660
1.08k
        poSrcDS->GetMetadataItem(GDALMD_INTERLEAVE, GDAL_MDD_IMAGE_STRUCTURE);
5661
1.08k
    if (pszInterleave != nullptr &&
5662
414
        (EQUAL(pszInterleave, "PIXEL") || EQUAL(pszInterleave, "LINE")))
5663
245
        bInterleave = true;
5664
5665
1.08k
    pszInterleave =
5666
1.08k
        poDstDS->GetMetadataItem(GDALMD_INTERLEAVE, GDAL_MDD_IMAGE_STRUCTURE);
5667
1.08k
    if (pszInterleave != nullptr &&
5668
897
        (EQUAL(pszInterleave, "PIXEL") || EQUAL(pszInterleave, "LINE")))
5669
493
        bInterleave = true;
5670
5671
1.08k
    pszInterleave = CSLFetchNameValue(papszOptions, GDALMD_INTERLEAVE);
5672
1.08k
    if (pszInterleave != nullptr && EQUAL(pszInterleave, "PIXEL"))
5673
0
        bInterleave = true;
5674
1.08k
    else if (pszInterleave != nullptr && EQUAL(pszInterleave, "BAND"))
5675
0
        bInterleave = false;
5676
    // attributes is specific to the TileDB driver
5677
1.08k
    else if (pszInterleave != nullptr && EQUAL(pszInterleave, "ATTRIBUTES"))
5678
0
        bInterleave = true;
5679
1.08k
    else if (pszInterleave != nullptr)
5680
0
    {
5681
0
        CPLError(CE_Warning, CPLE_NotSupported,
5682
0
                 "Unsupported value for option INTERLEAVE");
5683
0
    }
5684
5685
    // If the destination is compressed, we must try to write blocks just once,
5686
    // to save disk space (GTiff case for example), and to avoid data loss
5687
    // (JPEG compression for example).
5688
1.08k
    bool bDstIsCompressed = false;
5689
1.08k
    const char *pszDstCompressed =
5690
1.08k
        CSLFetchNameValue(papszOptions, "COMPRESSED");
5691
1.08k
    if (pszDstCompressed != nullptr && CPLTestBool(pszDstCompressed))
5692
0
        bDstIsCompressed = true;
5693
5694
    /* -------------------------------------------------------------------- */
5695
    /*      What will our swath size be?                                    */
5696
    /* -------------------------------------------------------------------- */
5697
5698
1.08k
    int nSwathCols = 0;
5699
1.08k
    int nSwathLines = 0;
5700
1.08k
    GDALCopyWholeRasterGetSwathSize(poSrcPrototypeBand, poDstPrototypeBand,
5701
1.08k
                                    nBandCount, bDstIsCompressed, bInterleave,
5702
1.08k
                                    &nSwathCols, &nSwathLines);
5703
5704
1.08k
    int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
5705
1.08k
    if (bInterleave)
5706
571
        nPixelSize *= nBandCount;
5707
5708
1.08k
    void *pSwathBuf = VSI_MALLOC3_VERBOSE(nSwathCols, nSwathLines, nPixelSize);
5709
1.08k
    if (pSwathBuf == nullptr)
5710
0
    {
5711
0
        return CE_Failure;
5712
0
    }
5713
5714
1.08k
    CPLDebug("GDAL",
5715
1.08k
             "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d",
5716
1.08k
             nSwathCols, nSwathLines, static_cast<int>(bInterleave));
5717
5718
    // Advise the source raster that we are going to read it completely
5719
    // Note: this might already have been done by GDALCreateCopy() in the
5720
    // likely case this function is indirectly called by it
5721
1.08k
    poSrcDS->AdviseRead(0, 0, nXSize, nYSize, nXSize, nYSize, eDT, nBandCount,
5722
1.08k
                        nullptr, nullptr);
5723
5724
    /* ==================================================================== */
5725
    /*      Band oriented (uninterleaved) case.                             */
5726
    /* ==================================================================== */
5727
1.08k
    CPLErr eErr = CE_None;
5728
1.08k
    const bool bCheckHoles =
5729
1.08k
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_HOLES", "NO"));
5730
5731
1.08k
    if (!bInterleave)
5732
515
    {
5733
515
        GDALRasterIOExtraArg sExtraArg;
5734
515
        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
5735
515
        CPL_IGNORE_RET_VAL(sExtraArg.pfnProgress);  // to make cppcheck happy
5736
5737
515
        const GIntBig nTotalBlocks = static_cast<GIntBig>(nBandCount) *
5738
515
                                     DIV_ROUND_UP(nYSize, nSwathLines) *
5739
515
                                     DIV_ROUND_UP(nXSize, nSwathCols);
5740
515
        GIntBig nBlocksDone = 0;
5741
5742
32.7k
        for (int iBand = 0; iBand < nBandCount && eErr == CE_None; iBand++)
5743
32.2k
        {
5744
32.2k
            int nBand = iBand + 1;
5745
5746
67.3k
            for (int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines)
5747
35.0k
            {
5748
35.0k
                int nThisLines = nSwathLines;
5749
5750
35.0k
                if (iY + nThisLines > nYSize)
5751
2.77k
                    nThisLines = nYSize - iY;
5752
5753
70.0k
                for (int iX = 0; iX < nXSize && eErr == CE_None;
5754
35.0k
                     iX += nSwathCols)
5755
35.0k
                {
5756
35.0k
                    int nThisCols = nSwathCols;
5757
5758
35.0k
                    if (iX + nThisCols > nXSize)
5759
0
                        nThisCols = nXSize - iX;
5760
5761
35.0k
                    int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
5762
35.0k
                    if (bCheckHoles)
5763
4.86k
                    {
5764
4.86k
                        nStatus = poSrcDS->GetRasterBand(nBand)
5765
4.86k
                                      ->GetDataCoverageStatus(
5766
4.86k
                                          iX, iY, nThisCols, nThisLines,
5767
4.86k
                                          GDAL_DATA_COVERAGE_STATUS_DATA);
5768
4.86k
                    }
5769
35.0k
                    if (nStatus & GDAL_DATA_COVERAGE_STATUS_DATA)
5770
35.0k
                    {
5771
35.0k
                        sExtraArg.pfnProgress = GDALScaledProgress;
5772
35.0k
                        sExtraArg.pProgressData = GDALCreateScaledProgress(
5773
35.0k
                            nBlocksDone / static_cast<double>(nTotalBlocks),
5774
35.0k
                            (nBlocksDone + 0.5) /
5775
35.0k
                                static_cast<double>(nTotalBlocks),
5776
35.0k
                            pfnProgress, pProgressData);
5777
35.0k
                        if (sExtraArg.pProgressData == nullptr)
5778
30.1k
                            sExtraArg.pfnProgress = nullptr;
5779
5780
35.0k
                        eErr = poSrcDS->RasterIO(GF_Read, iX, iY, nThisCols,
5781
35.0k
                                                 nThisLines, pSwathBuf,
5782
35.0k
                                                 nThisCols, nThisLines, eDT, 1,
5783
35.0k
                                                 &nBand, 0, 0, 0, &sExtraArg);
5784
5785
35.0k
                        GDALDestroyScaledProgress(sExtraArg.pProgressData);
5786
5787
35.0k
                        if (eErr == CE_None)
5788
34.9k
                            eErr = poDstDS->RasterIO(
5789
34.9k
                                GF_Write, iX, iY, nThisCols, nThisLines,
5790
34.9k
                                pSwathBuf, nThisCols, nThisLines, eDT, 1,
5791
34.9k
                                &nBand, 0, 0, 0, nullptr);
5792
35.0k
                    }
5793
5794
35.0k
                    nBlocksDone++;
5795
35.0k
                    if (eErr == CE_None &&
5796
34.9k
                        !pfnProgress(nBlocksDone /
5797
34.9k
                                         static_cast<double>(nTotalBlocks),
5798
34.9k
                                     nullptr, pProgressData))
5799
0
                    {
5800
0
                        eErr = CE_Failure;
5801
0
                        CPLError(CE_Failure, CPLE_UserInterrupt,
5802
0
                                 "User terminated CreateCopy()");
5803
0
                    }
5804
35.0k
                }
5805
35.0k
            }
5806
32.2k
        }
5807
515
    }
5808
5809
    /* ==================================================================== */
5810
    /*      Pixel interleaved case.                                         */
5811
    /* ==================================================================== */
5812
571
    else /* if( bInterleave ) */
5813
571
    {
5814
571
        GDALRasterIOExtraArg sExtraArg;
5815
571
        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
5816
571
        CPL_IGNORE_RET_VAL(sExtraArg.pfnProgress);  // to make cppcheck happy
5817
5818
571
        const GIntBig nTotalBlocks =
5819
571
            static_cast<GIntBig>(DIV_ROUND_UP(nYSize, nSwathLines)) *
5820
571
            DIV_ROUND_UP(nXSize, nSwathCols);
5821
571
        GIntBig nBlocksDone = 0;
5822
5823
1.17k
        for (int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines)
5824
604
        {
5825
604
            int nThisLines = nSwathLines;
5826
5827
604
            if (iY + nThisLines > nYSize)
5828
91
                nThisLines = nYSize - iY;
5829
5830
1.20k
            for (int iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols)
5831
605
            {
5832
605
                int nThisCols = nSwathCols;
5833
5834
605
                if (iX + nThisCols > nXSize)
5835
1
                    nThisCols = nXSize - iX;
5836
5837
605
                int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
5838
605
                if (bCheckHoles)
5839
509
                {
5840
509
                    nStatus = 0;
5841
513
                    for (int iBand = 0; iBand < nBandCount; iBand++)
5842
511
                    {
5843
511
                        nStatus |= poSrcDS->GetRasterBand(iBand + 1)
5844
511
                                       ->GetDataCoverageStatus(
5845
511
                                           iX, iY, nThisCols, nThisLines,
5846
511
                                           GDAL_DATA_COVERAGE_STATUS_DATA);
5847
511
                        if (nStatus & GDAL_DATA_COVERAGE_STATUS_DATA)
5848
507
                            break;
5849
511
                    }
5850
509
                }
5851
605
                if (nStatus & GDAL_DATA_COVERAGE_STATUS_DATA)
5852
603
                {
5853
603
                    sExtraArg.pfnProgress = GDALScaledProgress;
5854
603
                    sExtraArg.pProgressData = GDALCreateScaledProgress(
5855
603
                        nBlocksDone / static_cast<double>(nTotalBlocks),
5856
603
                        (nBlocksDone + 0.5) / static_cast<double>(nTotalBlocks),
5857
603
                        pfnProgress, pProgressData);
5858
603
                    if (sExtraArg.pProgressData == nullptr)
5859
96
                        sExtraArg.pfnProgress = nullptr;
5860
5861
603
                    eErr = poSrcDS->RasterIO(GF_Read, iX, iY, nThisCols,
5862
603
                                             nThisLines, pSwathBuf, nThisCols,
5863
603
                                             nThisLines, eDT, nBandCount,
5864
603
                                             nullptr, 0, 0, 0, &sExtraArg);
5865
5866
603
                    GDALDestroyScaledProgress(sExtraArg.pProgressData);
5867
5868
603
                    if (eErr == CE_None)
5869
353
                        eErr = poDstDS->RasterIO(
5870
353
                            GF_Write, iX, iY, nThisCols, nThisLines, pSwathBuf,
5871
353
                            nThisCols, nThisLines, eDT, nBandCount, nullptr, 0,
5872
353
                            0, 0, nullptr);
5873
603
                }
5874
5875
605
                nBlocksDone++;
5876
605
                if (eErr == CE_None &&
5877
355
                    !pfnProgress(nBlocksDone /
5878
355
                                     static_cast<double>(nTotalBlocks),
5879
355
                                 nullptr, pProgressData))
5880
0
                {
5881
0
                    eErr = CE_Failure;
5882
0
                    CPLError(CE_Failure, CPLE_UserInterrupt,
5883
0
                             "User terminated CreateCopy()");
5884
0
                }
5885
605
            }
5886
604
        }
5887
571
    }
5888
5889
    /* -------------------------------------------------------------------- */
5890
    /*      Cleanup                                                         */
5891
    /* -------------------------------------------------------------------- */
5892
1.08k
    CPLFree(pSwathBuf);
5893
5894
1.08k
    return eErr;
5895
1.08k
}
5896
5897
/************************************************************************/
5898
/*                   GDALRasterBandCopyWholeRaster()                    */
5899
/************************************************************************/
5900
5901
/**
5902
 * \brief Copy a whole raster band
5903
 *
5904
 * This function copies the complete raster contents of one band to
5905
 * another similarly configured band.  The source and destination
5906
 * bands must have the same width and height.  The bands do not have
5907
 * to have the same data type.
5908
 *
5909
 * It implements efficient copying, in particular "chunking" the copy in
5910
 * substantial blocks.
5911
 *
5912
 * Currently the only papszOptions value supported are :
5913
 * <ul>
5914
 * <li>"COMPRESSED=YES" to force alignment on target dataset block sizes to
5915
 * achieve best compression.</li>
5916
 * <li>"SKIP_HOLES=YES" to skip chunks for which GDALGetDataCoverageStatus()
5917
 * returns GDAL_DATA_COVERAGE_STATUS_EMPTY (GDAL &gt;= 2.2)</li>
5918
 * </ul>
5919
 *
5920
 * @param hSrcBand the source band
5921
 * @param hDstBand the destination band
5922
 * @param papszOptions transfer hints in "StringList" Name=Value format.
5923
 * @param pfnProgress progress reporting function.
5924
 * @param pProgressData callback data for progress function.
5925
 *
5926
 * @return CE_None on success, or CE_Failure on failure.
5927
 */
5928
5929
CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
5930
    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand,
5931
    const char *const *const papszOptions, GDALProgressFunc pfnProgress,
5932
    void *pProgressData)
5933
5934
67
{
5935
67
    VALIDATE_POINTER1(hSrcBand, "GDALRasterBandCopyWholeRaster", CE_Failure);
5936
67
    VALIDATE_POINTER1(hDstBand, "GDALRasterBandCopyWholeRaster", CE_Failure);
5937
5938
67
    GDALRasterBand *poSrcBand = GDALRasterBand::FromHandle(hSrcBand);
5939
67
    GDALRasterBand *poDstBand = GDALRasterBand::FromHandle(hDstBand);
5940
67
    CPLErr eErr = CE_None;
5941
5942
67
    if (pfnProgress == nullptr)
5943
0
        pfnProgress = GDALDummyProgress;
5944
5945
    /* -------------------------------------------------------------------- */
5946
    /*      Confirm the datasets match in size and band counts.             */
5947
    /* -------------------------------------------------------------------- */
5948
67
    int nXSize = poSrcBand->GetXSize();
5949
67
    int nYSize = poSrcBand->GetYSize();
5950
5951
67
    if (poDstBand->GetXSize() != nXSize || poDstBand->GetYSize() != nYSize)
5952
0
    {
5953
0
        CPLError(CE_Failure, CPLE_AppDefined,
5954
0
                 "Input and output band sizes do not\n"
5955
0
                 "match in GDALRasterBandCopyWholeRaster()");
5956
0
        return CE_Failure;
5957
0
    }
5958
5959
    /* -------------------------------------------------------------------- */
5960
    /*      Report preliminary (0) progress.                                */
5961
    /* -------------------------------------------------------------------- */
5962
67
    if (!pfnProgress(0.0, nullptr, pProgressData))
5963
0
    {
5964
0
        CPLError(CE_Failure, CPLE_UserInterrupt,
5965
0
                 "User terminated CreateCopy()");
5966
0
        return CE_Failure;
5967
0
    }
5968
5969
67
    GDALDataType eDT = poDstBand->GetRasterDataType();
5970
5971
    // If the destination is compressed, we must try to write blocks just once,
5972
    // to save disk space (GTiff case for example), and to avoid data loss
5973
    // (JPEG compression for example).
5974
67
    bool bDstIsCompressed = false;
5975
67
    const char *pszDstCompressed =
5976
67
        CSLFetchNameValue(const_cast<char **>(papszOptions), "COMPRESSED");
5977
67
    if (pszDstCompressed != nullptr && CPLTestBool(pszDstCompressed))
5978
67
        bDstIsCompressed = true;
5979
5980
    /* -------------------------------------------------------------------- */
5981
    /*      What will our swath size be?                                    */
5982
    /* -------------------------------------------------------------------- */
5983
5984
67
    int nSwathCols = 0;
5985
67
    int nSwathLines = 0;
5986
67
    GDALCopyWholeRasterGetSwathSize(poSrcBand, poDstBand, 1, bDstIsCompressed,
5987
67
                                    FALSE, &nSwathCols, &nSwathLines);
5988
5989
67
    const int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
5990
5991
67
    void *pSwathBuf = VSI_MALLOC3_VERBOSE(nSwathCols, nSwathLines, nPixelSize);
5992
67
    if (pSwathBuf == nullptr)
5993
0
    {
5994
0
        return CE_Failure;
5995
0
    }
5996
5997
67
    CPLDebug("GDAL", "GDALRasterBandCopyWholeRaster(): %d*%d swaths",
5998
67
             nSwathCols, nSwathLines);
5999
6000
67
    const bool bCheckHoles =
6001
67
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_HOLES", "NO"));
6002
6003
    // Advise the source raster that we are going to read it completely
6004
67
    poSrcBand->AdviseRead(0, 0, nXSize, nYSize, nXSize, nYSize, eDT, nullptr);
6005
6006
    /* ==================================================================== */
6007
    /*      Band oriented (uninterleaved) case.                             */
6008
    /* ==================================================================== */
6009
6010
154
    for (int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines)
6011
87
    {
6012
87
        int nThisLines = nSwathLines;
6013
6014
87
        if (iY + nThisLines > nYSize)
6015
29
            nThisLines = nYSize - iY;
6016
6017
174
        for (int iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols)
6018
87
        {
6019
87
            int nThisCols = nSwathCols;
6020
6021
87
            if (iX + nThisCols > nXSize)
6022
0
                nThisCols = nXSize - iX;
6023
6024
87
            int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
6025
87
            if (bCheckHoles)
6026
0
            {
6027
0
                nStatus = poSrcBand->GetDataCoverageStatus(
6028
0
                    iX, iY, nThisCols, nThisLines,
6029
0
                    GDAL_DATA_COVERAGE_STATUS_DATA);
6030
0
            }
6031
87
            if (nStatus & GDAL_DATA_COVERAGE_STATUS_DATA)
6032
87
            {
6033
87
                eErr = poSrcBand->RasterIO(GF_Read, iX, iY, nThisCols,
6034
87
                                           nThisLines, pSwathBuf, nThisCols,
6035
87
                                           nThisLines, eDT, 0, 0, nullptr);
6036
6037
87
                if (eErr == CE_None)
6038
87
                    eErr = poDstBand->RasterIO(GF_Write, iX, iY, nThisCols,
6039
87
                                               nThisLines, pSwathBuf, nThisCols,
6040
87
                                               nThisLines, eDT, 0, 0, nullptr);
6041
87
            }
6042
6043
87
            if (eErr == CE_None && !pfnProgress(double(iY + nThisLines) /
6044
87
                                                    static_cast<double>(nYSize),
6045
87
                                                nullptr, pProgressData))
6046
0
            {
6047
0
                eErr = CE_Failure;
6048
0
                CPLError(CE_Failure, CPLE_UserInterrupt,
6049
0
                         "User terminated CreateCopy()");
6050
0
            }
6051
87
        }
6052
87
    }
6053
6054
    /* -------------------------------------------------------------------- */
6055
    /*      Cleanup                                                         */
6056
    /* -------------------------------------------------------------------- */
6057
67
    CPLFree(pSwathBuf);
6058
6059
67
    return eErr;
6060
67
}
6061
6062
/************************************************************************/
6063
/*                     GDALCopyRasterIOExtraArg ()                      */
6064
/************************************************************************/
6065
6066
void GDALCopyRasterIOExtraArg(GDALRasterIOExtraArg *psDestArg,
6067
                              const GDALRasterIOExtraArg *psSrcArg)
6068
152k
{
6069
152k
    INIT_RASTERIO_EXTRA_ARG(*psDestArg);
6070
152k
    if (psSrcArg)
6071
152k
    {
6072
152k
        psDestArg->eResampleAlg = psSrcArg->eResampleAlg;
6073
152k
        psDestArg->pfnProgress = psSrcArg->pfnProgress;
6074
152k
        psDestArg->pProgressData = psSrcArg->pProgressData;
6075
152k
        psDestArg->bFloatingPointWindowValidity =
6076
152k
            psSrcArg->bFloatingPointWindowValidity;
6077
152k
        if (psSrcArg->bFloatingPointWindowValidity)
6078
152k
        {
6079
152k
            psDestArg->dfXOff = psSrcArg->dfXOff;
6080
152k
            psDestArg->dfYOff = psSrcArg->dfYOff;
6081
152k
            psDestArg->dfXSize = psSrcArg->dfXSize;
6082
152k
            psDestArg->dfYSize = psSrcArg->dfYSize;
6083
152k
        }
6084
152k
        if (psSrcArg->nVersion >= 2)
6085
152k
        {
6086
152k
            psDestArg->bUseOnlyThisScale = psSrcArg->bUseOnlyThisScale;
6087
152k
        }
6088
152k
        if (psSrcArg->nVersion >= 3)
6089
152k
        {
6090
152k
            psDestArg->bOperateInBufType = psSrcArg->bOperateInBufType;
6091
152k
        }
6092
152k
    }
6093
152k
}
6094
6095
/************************************************************************/
6096
/*                           HasOnlyNoData()                            */
6097
/************************************************************************/
6098
6099
template <class T> static inline bool IsEqualToNoData(T value, T noDataValue)
6100
313k
{
6101
313k
    return value == noDataValue;
6102
313k
}
rasterio.cpp:bool IsEqualToNoData<unsigned char>(unsigned char, unsigned char)
Line
Count
Source
6100
308k
{
6101
308k
    return value == noDataValue;
6102
308k
}
rasterio.cpp:bool IsEqualToNoData<unsigned short>(unsigned short, unsigned short)
Line
Count
Source
6100
4.17k
{
6101
4.17k
    return value == noDataValue;
6102
4.17k
}
rasterio.cpp:bool IsEqualToNoData<unsigned int>(unsigned int, unsigned int)
Line
Count
Source
6100
6
{
6101
6
    return value == noDataValue;
6102
6
}
Unexecuted instantiation: rasterio.cpp:bool IsEqualToNoData<unsigned long>(unsigned long, unsigned long)
6103
6104
template <> bool IsEqualToNoData<GFloat16>(GFloat16 value, GFloat16 noDataValue)
6105
0
{
6106
0
    using std::isnan;
6107
0
    return isnan(noDataValue) ? isnan(value) : value == noDataValue;
6108
0
}
6109
6110
template <> bool IsEqualToNoData<float>(float value, float noDataValue)
6111
0
{
6112
0
    return std::isnan(noDataValue) ? std::isnan(value) : value == noDataValue;
6113
0
}
6114
6115
template <> bool IsEqualToNoData<double>(double value, double noDataValue)
6116
1.00k
{
6117
1.00k
    return std::isnan(noDataValue) ? std::isnan(value) : value == noDataValue;
6118
1.00k
}
6119
6120
template <class T>
6121
static bool HasOnlyNoDataT(const T *pBuffer, T noDataValue, size_t nWidth,
6122
                           size_t nHeight, size_t nLineStride,
6123
                           size_t nComponents)
6124
111
{
6125
    // Fast test: check the 4 corners and the middle pixel.
6126
11.9k
    for (size_t iBand = 0; iBand < nComponents; iBand++)
6127
11.8k
    {
6128
11.8k
        if (!(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
6129
11.8k
              IsEqualToNoData(pBuffer[(nWidth - 1) * nComponents + iBand],
6130
11.8k
                              noDataValue) &&
6131
11.8k
              IsEqualToNoData(
6132
11.8k
                  pBuffer[((nHeight - 1) / 2 * nLineStride + (nWidth - 1) / 2) *
6133
11.8k
                              nComponents +
6134
11.8k
                          iBand],
6135
11.8k
                  noDataValue) &&
6136
11.8k
              IsEqualToNoData(
6137
11.8k
                  pBuffer[(nHeight - 1) * nLineStride * nComponents + iBand],
6138
11.8k
                  noDataValue) &&
6139
11.8k
              IsEqualToNoData(
6140
11.8k
                  pBuffer[((nHeight - 1) * nLineStride + nWidth - 1) *
6141
11.8k
                              nComponents +
6142
11.8k
                          iBand],
6143
11.8k
                  noDataValue)))
6144
32
        {
6145
32
            return false;
6146
32
        }
6147
11.8k
    }
6148
6149
    // Test all pixels.
6150
175
    for (size_t iY = 0; iY < nHeight; iY++)
6151
125
    {
6152
125
        const T *pBufferLine = pBuffer + iY * nLineStride * nComponents;
6153
254k
        for (size_t iX = 0; iX < nWidth * nComponents; iX++)
6154
254k
        {
6155
254k
            if (!IsEqualToNoData(pBufferLine[iX], noDataValue))
6156
29
            {
6157
29
                return false;
6158
29
            }
6159
254k
        }
6160
125
    }
6161
50
    return true;
6162
79
}
rasterio.cpp:bool HasOnlyNoDataT<unsigned char>(unsigned char const*, unsigned char, unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
6124
94
{
6125
    // Fast test: check the 4 corners and the middle pixel.
6126
11.9k
    for (size_t iBand = 0; iBand < nComponents; iBand++)
6127
11.8k
    {
6128
11.8k
        if (!(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
6129
11.8k
              IsEqualToNoData(pBuffer[(nWidth - 1) * nComponents + iBand],
6130
11.8k
                              noDataValue) &&
6131
11.8k
              IsEqualToNoData(
6132
11.8k
                  pBuffer[((nHeight - 1) / 2 * nLineStride + (nWidth - 1) / 2) *
6133
11.8k
                              nComponents +
6134
11.8k
                          iBand],
6135
11.8k
                  noDataValue) &&
6136
11.8k
              IsEqualToNoData(
6137
11.8k
                  pBuffer[(nHeight - 1) * nLineStride * nComponents + iBand],
6138
11.8k
                  noDataValue) &&
6139
11.8k
              IsEqualToNoData(
6140
11.8k
                  pBuffer[((nHeight - 1) * nLineStride + nWidth - 1) *
6141
11.8k
                              nComponents +
6142
11.8k
                          iBand],
6143
11.8k
                  noDataValue)))
6144
27
        {
6145
27
            return false;
6146
27
        }
6147
11.8k
    }
6148
6149
    // Test all pixels.
6150
135
    for (size_t iY = 0; iY < nHeight; iY++)
6151
88
    {
6152
88
        const T *pBufferLine = pBuffer + iY * nLineStride * nComponents;
6153
249k
        for (size_t iX = 0; iX < nWidth * nComponents; iX++)
6154
249k
        {
6155
249k
            if (!IsEqualToNoData(pBufferLine[iX], noDataValue))
6156
20
            {
6157
20
                return false;
6158
20
            }
6159
249k
        }
6160
88
    }
6161
47
    return true;
6162
67
}
rasterio.cpp:bool HasOnlyNoDataT<unsigned short>(unsigned short const*, unsigned short, unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
6124
15
{
6125
    // Fast test: check the 4 corners and the middle pixel.
6126
38
    for (size_t iBand = 0; iBand < nComponents; iBand++)
6127
27
    {
6128
27
        if (!(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
6129
27
              IsEqualToNoData(pBuffer[(nWidth - 1) * nComponents + iBand],
6130
27
                              noDataValue) &&
6131
24
              IsEqualToNoData(
6132
24
                  pBuffer[((nHeight - 1) / 2 * nLineStride + (nWidth - 1) / 2) *
6133
24
                              nComponents +
6134
24
                          iBand],
6135
24
                  noDataValue) &&
6136
23
              IsEqualToNoData(
6137
23
                  pBuffer[(nHeight - 1) * nLineStride * nComponents + iBand],
6138
23
                  noDataValue) &&
6139
23
              IsEqualToNoData(
6140
23
                  pBuffer[((nHeight - 1) * nLineStride + nWidth - 1) *
6141
23
                              nComponents +
6142
23
                          iBand],
6143
23
                  noDataValue)))
6144
4
        {
6145
4
            return false;
6146
4
        }
6147
27
    }
6148
6149
    // Test all pixels.
6150
19
    for (size_t iY = 0; iY < nHeight; iY++)
6151
17
    {
6152
17
        const T *pBufferLine = pBuffer + iY * nLineStride * nComponents;
6153
4.05k
        for (size_t iX = 0; iX < nWidth * nComponents; iX++)
6154
4.04k
        {
6155
4.04k
            if (!IsEqualToNoData(pBufferLine[iX], noDataValue))
6156
9
            {
6157
9
                return false;
6158
9
            }
6159
4.04k
        }
6160
17
    }
6161
2
    return true;
6162
11
}
rasterio.cpp:bool HasOnlyNoDataT<unsigned int>(unsigned int const*, unsigned int, unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
6124
1
{
6125
    // Fast test: check the 4 corners and the middle pixel.
6126
2
    for (size_t iBand = 0; iBand < nComponents; iBand++)
6127
2
    {
6128
2
        if (!(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
6129
1
              IsEqualToNoData(pBuffer[(nWidth - 1) * nComponents + iBand],
6130
1
                              noDataValue) &&
6131
1
              IsEqualToNoData(
6132
1
                  pBuffer[((nHeight - 1) / 2 * nLineStride + (nWidth - 1) / 2) *
6133
1
                              nComponents +
6134
1
                          iBand],
6135
1
                  noDataValue) &&
6136
1
              IsEqualToNoData(
6137
1
                  pBuffer[(nHeight - 1) * nLineStride * nComponents + iBand],
6138
1
                  noDataValue) &&
6139
1
              IsEqualToNoData(
6140
1
                  pBuffer[((nHeight - 1) * nLineStride + nWidth - 1) *
6141
1
                              nComponents +
6142
1
                          iBand],
6143
1
                  noDataValue)))
6144
1
        {
6145
1
            return false;
6146
1
        }
6147
2
    }
6148
6149
    // Test all pixels.
6150
0
    for (size_t iY = 0; iY < nHeight; iY++)
6151
0
    {
6152
0
        const T *pBufferLine = pBuffer + iY * nLineStride * nComponents;
6153
0
        for (size_t iX = 0; iX < nWidth * nComponents; iX++)
6154
0
        {
6155
0
            if (!IsEqualToNoData(pBufferLine[iX], noDataValue))
6156
0
            {
6157
0
                return false;
6158
0
            }
6159
0
        }
6160
0
    }
6161
0
    return true;
6162
0
}
Unexecuted instantiation: rasterio.cpp:bool HasOnlyNoDataT<unsigned long>(unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:bool HasOnlyNoDataT<cpl::Float16>(cpl::Float16 const*, cpl::Float16, unsigned long, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:bool HasOnlyNoDataT<float>(float const*, float, unsigned long, unsigned long, unsigned long, unsigned long)
rasterio.cpp:bool HasOnlyNoDataT<double>(double const*, double, unsigned long, unsigned long, unsigned long, unsigned long)
Line
Count
Source
6124
1
{
6125
    // Fast test: check the 4 corners and the middle pixel.
6126
2
    for (size_t iBand = 0; iBand < nComponents; iBand++)
6127
1
    {
6128
1
        if (!(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
6129
1
              IsEqualToNoData(pBuffer[(nWidth - 1) * nComponents + iBand],
6130
1
                              noDataValue) &&
6131
1
              IsEqualToNoData(
6132
1
                  pBuffer[((nHeight - 1) / 2 * nLineStride + (nWidth - 1) / 2) *
6133
1
                              nComponents +
6134
1
                          iBand],
6135
1
                  noDataValue) &&
6136
1
              IsEqualToNoData(
6137
1
                  pBuffer[(nHeight - 1) * nLineStride * nComponents + iBand],
6138
1
                  noDataValue) &&
6139
1
              IsEqualToNoData(
6140
1
                  pBuffer[((nHeight - 1) * nLineStride + nWidth - 1) *
6141
1
                              nComponents +
6142
1
                          iBand],
6143
1
                  noDataValue)))
6144
0
        {
6145
0
            return false;
6146
0
        }
6147
1
    }
6148
6149
    // Test all pixels.
6150
21
    for (size_t iY = 0; iY < nHeight; iY++)
6151
20
    {
6152
20
        const T *pBufferLine = pBuffer + iY * nLineStride * nComponents;
6153
1.02k
        for (size_t iX = 0; iX < nWidth * nComponents; iX++)
6154
1.00k
        {
6155
1.00k
            if (!IsEqualToNoData(pBufferLine[iX], noDataValue))
6156
0
            {
6157
0
                return false;
6158
0
            }
6159
1.00k
        }
6160
20
    }
6161
1
    return true;
6162
1
}
6163
6164
/************************************************************************/
6165
/*                      GDALBufferHasOnlyNoData()                       */
6166
/************************************************************************/
6167
6168
bool GDALBufferHasOnlyNoData(const void *pBuffer, double dfNoDataValue,
6169
                             size_t nWidth, size_t nHeight, size_t nLineStride,
6170
                             size_t nComponents, int nBitsPerSample,
6171
                             GDALBufferSampleFormat nSampleFormat)
6172
5.97k
{
6173
    // In the case where the nodata is 0, we can compare several bytes at
6174
    // once. Select the largest natural integer type for the architecture.
6175
5.97k
    if (dfNoDataValue == 0.0 && nWidth == nLineStride &&
6176
        // Do not use this optimized code path for floating point numbers,
6177
        // as it can't detect negative zero.
6178
5.86k
        nSampleFormat != GSF_FLOATING_POINT)
6179
5.67k
    {
6180
5.67k
        const GByte *pabyBuffer = static_cast<const GByte *>(pBuffer);
6181
5.67k
        const size_t nSize =
6182
5.67k
            static_cast<size_t>((static_cast<uint64_t>(nWidth) * nHeight *
6183
5.67k
                                     nComponents * nBitsPerSample +
6184
5.67k
                                 7) /
6185
5.67k
                                8);
6186
5.67k
#ifdef HAVE_SSE2
6187
5.67k
        size_t n = nSize;
6188
        // Align to 16 bytes
6189
5.68k
        while ((reinterpret_cast<uintptr_t>(pabyBuffer) & 15) != 0 && n > 0)
6190
18
        {
6191
18
            --n;
6192
18
            if (*pabyBuffer)
6193
6
                return false;
6194
12
            pabyBuffer++;
6195
12
        }
6196
6197
5.66k
        const auto zero = _mm_setzero_si128();
6198
5.66k
        constexpr int UNROLLING = 4;
6199
93.6k
        while (n >= UNROLLING * sizeof(zero))
6200
90.6k
        {
6201
90.6k
            const auto v0 = _mm_load_si128(reinterpret_cast<const __m128i *>(
6202
90.6k
                pabyBuffer + 0 * sizeof(zero)));
6203
90.6k
            const auto v1 = _mm_load_si128(reinterpret_cast<const __m128i *>(
6204
90.6k
                pabyBuffer + 1 * sizeof(zero)));
6205
90.6k
            const auto v2 = _mm_load_si128(reinterpret_cast<const __m128i *>(
6206
90.6k
                pabyBuffer + 2 * sizeof(zero)));
6207
90.6k
            const auto v3 = _mm_load_si128(reinterpret_cast<const __m128i *>(
6208
90.6k
                pabyBuffer + 3 * sizeof(zero)));
6209
90.6k
            const auto v =
6210
90.6k
                _mm_or_si128(_mm_or_si128(v0, v1), _mm_or_si128(v2, v3));
6211
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
6212
            if (!_mm_test_all_zeros(v, v))
6213
#else
6214
90.6k
            if (_mm_movemask_epi8(_mm_cmpeq_epi8(v, zero)) != 0xFFFF)
6215
2.66k
#endif
6216
2.66k
            {
6217
2.66k
                return false;
6218
2.66k
            }
6219
88.0k
            pabyBuffer += UNROLLING * sizeof(zero);
6220
88.0k
            n -= UNROLLING * sizeof(zero);
6221
88.0k
        }
6222
6223
110k
        while (n > 0)
6224
107k
        {
6225
107k
            --n;
6226
107k
            if (*pabyBuffer)
6227
163
                return false;
6228
107k
            pabyBuffer++;
6229
107k
        }
6230
#else
6231
#if SIZEOF_VOIDP >= 8 || defined(__x86_64__)
6232
        // We test __x86_64__ for x32 arch where SIZEOF_VOIDP == 4
6233
        typedef std::uint64_t WordType;
6234
#else
6235
        typedef std::uint32_t WordType;
6236
#endif
6237
6238
        const size_t nInitialIters =
6239
            std::min(sizeof(WordType) -
6240
                         static_cast<size_t>(
6241
                             reinterpret_cast<std::uintptr_t>(pabyBuffer) %
6242
                             sizeof(WordType)),
6243
                     nSize);
6244
        size_t i = 0;
6245
        for (; i < nInitialIters; i++)
6246
        {
6247
            if (pabyBuffer[i])
6248
                return false;
6249
        }
6250
        for (; i + sizeof(WordType) - 1 < nSize; i += sizeof(WordType))
6251
        {
6252
            if (*(reinterpret_cast<const WordType *>(pabyBuffer + i)))
6253
                return false;
6254
        }
6255
        for (; i < nSize; i++)
6256
        {
6257
            if (pabyBuffer[i])
6258
                return false;
6259
        }
6260
#endif
6261
2.84k
        return true;
6262
3.00k
    }
6263
6264
299
#ifdef HAVE_SSE2
6265
299
    else if (dfNoDataValue == 0.0 && nWidth == nLineStride &&
6266
188
             nBitsPerSample == 32 && nSampleFormat == GSF_FLOATING_POINT)
6267
23
    {
6268
23
        const auto signMask = _mm_set1_epi32(0x7FFFFFFF);
6269
23
        const auto zero = _mm_setzero_si128();
6270
23
        const GByte *pabyBuffer = static_cast<const GByte *>(pBuffer);
6271
23
        const size_t n = nWidth * nHeight * nComponents;
6272
6273
23
        size_t i = 0;
6274
23
        constexpr int UNROLLING = 4;
6275
23
        constexpr size_t VALUES_PER_ITER =
6276
23
            UNROLLING * sizeof(zero) / sizeof(float);
6277
11.3k
        for (; i + VALUES_PER_ITER <= n; i += VALUES_PER_ITER)
6278
11.3k
        {
6279
11.3k
            const auto v0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6280
11.3k
                pabyBuffer + 0 * sizeof(zero)));
6281
11.3k
            const auto v1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6282
11.3k
                pabyBuffer + 1 * sizeof(zero)));
6283
11.3k
            const auto v2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6284
11.3k
                pabyBuffer + 2 * sizeof(zero)));
6285
11.3k
            const auto v3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6286
11.3k
                pabyBuffer + 3 * sizeof(zero)));
6287
11.3k
            auto v = _mm_or_si128(_mm_or_si128(v0, v1), _mm_or_si128(v2, v3));
6288
            // Clear the sign bit (makes -0.0 become +0.0)
6289
11.3k
            v = _mm_and_si128(v, signMask);
6290
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
6291
            if (!_mm_test_all_zeros(v, v))
6292
#else
6293
11.3k
            if (_mm_movemask_epi8(_mm_cmpeq_epi8(v, zero)) != 0xFFFF)
6294
21
#endif
6295
21
            {
6296
21
                return false;
6297
21
            }
6298
11.3k
            pabyBuffer += UNROLLING * sizeof(zero);
6299
11.3k
        }
6300
6301
17
        for (; i < n; i++)
6302
15
        {
6303
15
            uint32_t bits;
6304
15
            memcpy(&bits, pabyBuffer, sizeof(bits));
6305
15
            pabyBuffer += sizeof(bits);
6306
15
            if ((bits & 0x7FFFFFFF) != 0)
6307
0
                return false;
6308
15
        }
6309
6310
2
        return true;
6311
2
    }
6312
6313
276
    else if (dfNoDataValue == 0.0 && nWidth == nLineStride &&
6314
165
             nBitsPerSample == 64 && nSampleFormat == GSF_FLOATING_POINT)
6315
165
    {
6316
165
        const auto signMask = _mm_set1_epi64x(0x7FFFFFFFFFFFFFFFLL);
6317
165
        const auto zero = _mm_setzero_si128();
6318
165
        const GByte *pabyBuffer = static_cast<const GByte *>(pBuffer);
6319
165
        const size_t n = nWidth * nHeight * nComponents;
6320
6321
165
        size_t i = 0;
6322
165
        constexpr int UNROLLING = 4;
6323
165
        constexpr size_t VALUES_PER_ITER =
6324
165
            UNROLLING * sizeof(zero) / sizeof(double);
6325
54.3k
        for (; i + VALUES_PER_ITER <= n; i += VALUES_PER_ITER)
6326
54.3k
        {
6327
54.3k
            const auto v0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6328
54.3k
                pabyBuffer + 0 * sizeof(zero)));
6329
54.3k
            const auto v1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6330
54.3k
                pabyBuffer + 1 * sizeof(zero)));
6331
54.3k
            const auto v2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6332
54.3k
                pabyBuffer + 2 * sizeof(zero)));
6333
54.3k
            const auto v3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(
6334
54.3k
                pabyBuffer + 3 * sizeof(zero)));
6335
54.3k
            auto v = _mm_or_si128(_mm_or_si128(v0, v1), _mm_or_si128(v2, v3));
6336
            // Clear the sign bit (makes -0.0 become +0.0)
6337
54.3k
            v = _mm_and_si128(v, signMask);
6338
#if defined(__SSE4_1__) || defined(__AVX__) || defined(USE_NEON_OPTIMIZATIONS)
6339
            if (!_mm_test_all_zeros(v, v))
6340
#else
6341
54.3k
            if (_mm_movemask_epi8(_mm_cmpeq_epi8(v, zero)) != 0xFFFF)
6342
162
#endif
6343
162
            {
6344
162
                return false;
6345
162
            }
6346
54.2k
            pabyBuffer += UNROLLING * sizeof(zero);
6347
54.2k
        }
6348
6349
13
        for (; i < n; i++)
6350
10
        {
6351
10
            uint64_t bits;
6352
10
            memcpy(&bits, pabyBuffer, sizeof(bits));
6353
10
            pabyBuffer += sizeof(bits);
6354
10
            if ((bits & 0x7FFFFFFFFFFFFFFFULL) != 0)
6355
0
                return false;
6356
10
        }
6357
6358
3
        return true;
6359
3
    }
6360
111
#endif
6361
6362
111
    if (nBitsPerSample == 8 && nSampleFormat == GSF_UNSIGNED_INT)
6363
47
    {
6364
47
        return GDALIsValueInRange<uint8_t>(dfNoDataValue) &&
6365
47
               HasOnlyNoDataT(static_cast<const uint8_t *>(pBuffer),
6366
47
                              static_cast<uint8_t>(dfNoDataValue), nWidth,
6367
47
                              nHeight, nLineStride, nComponents);
6368
47
    }
6369
64
    if (nBitsPerSample == 8 && nSampleFormat == GSF_SIGNED_INT)
6370
47
    {
6371
        // Use unsigned implementation by converting the nodatavalue to
6372
        // unsigned
6373
47
        return GDALIsValueInRange<int8_t>(dfNoDataValue) &&
6374
47
               HasOnlyNoDataT(
6375
47
                   static_cast<const uint8_t *>(pBuffer),
6376
47
                   static_cast<uint8_t>(static_cast<int8_t>(dfNoDataValue)),
6377
47
                   nWidth, nHeight, nLineStride, nComponents);
6378
47
    }
6379
17
    if (nBitsPerSample == 16 && nSampleFormat == GSF_UNSIGNED_INT)
6380
3
    {
6381
3
        return GDALIsValueInRange<uint16_t>(dfNoDataValue) &&
6382
3
               HasOnlyNoDataT(static_cast<const uint16_t *>(pBuffer),
6383
3
                              static_cast<uint16_t>(dfNoDataValue), nWidth,
6384
3
                              nHeight, nLineStride, nComponents);
6385
3
    }
6386
14
    if (nBitsPerSample == 16 && nSampleFormat == GSF_SIGNED_INT)
6387
12
    {
6388
        // Use unsigned implementation by converting the nodatavalue to
6389
        // unsigned
6390
12
        return GDALIsValueInRange<int16_t>(dfNoDataValue) &&
6391
12
               HasOnlyNoDataT(
6392
12
                   static_cast<const uint16_t *>(pBuffer),
6393
12
                   static_cast<uint16_t>(static_cast<int16_t>(dfNoDataValue)),
6394
12
                   nWidth, nHeight, nLineStride, nComponents);
6395
12
    }
6396
2
    if (nBitsPerSample == 32 && nSampleFormat == GSF_UNSIGNED_INT)
6397
0
    {
6398
0
        return GDALIsValueInRange<uint32_t>(dfNoDataValue) &&
6399
0
               HasOnlyNoDataT(static_cast<const uint32_t *>(pBuffer),
6400
0
                              static_cast<uint32_t>(dfNoDataValue), nWidth,
6401
0
                              nHeight, nLineStride, nComponents);
6402
0
    }
6403
2
    if (nBitsPerSample == 32 && nSampleFormat == GSF_SIGNED_INT)
6404
1
    {
6405
        // Use unsigned implementation by converting the nodatavalue to
6406
        // unsigned
6407
1
        return GDALIsValueInRange<int32_t>(dfNoDataValue) &&
6408
1
               HasOnlyNoDataT(
6409
1
                   static_cast<const uint32_t *>(pBuffer),
6410
1
                   static_cast<uint32_t>(static_cast<int32_t>(dfNoDataValue)),
6411
1
                   nWidth, nHeight, nLineStride, nComponents);
6412
1
    }
6413
1
    if (nBitsPerSample == 64 && nSampleFormat == GSF_UNSIGNED_INT)
6414
0
    {
6415
0
        return GDALIsValueInRange<uint64_t>(dfNoDataValue) &&
6416
0
               HasOnlyNoDataT(static_cast<const uint64_t *>(pBuffer),
6417
0
                              static_cast<uint64_t>(dfNoDataValue), nWidth,
6418
0
                              nHeight, nLineStride, nComponents);
6419
0
    }
6420
1
    if (nBitsPerSample == 64 && nSampleFormat == GSF_SIGNED_INT)
6421
0
    {
6422
        // Use unsigned implementation by converting the nodatavalue to
6423
        // unsigned
6424
0
        return GDALIsValueInRange<int64_t>(dfNoDataValue) &&
6425
0
               HasOnlyNoDataT(
6426
0
                   static_cast<const uint64_t *>(pBuffer),
6427
0
                   static_cast<uint64_t>(static_cast<int64_t>(dfNoDataValue)),
6428
0
                   nWidth, nHeight, nLineStride, nComponents);
6429
0
    }
6430
1
    if (nBitsPerSample == 16 && nSampleFormat == GSF_FLOATING_POINT)
6431
0
    {
6432
0
        return (std::isnan(dfNoDataValue) ||
6433
0
                GDALIsValueInRange<GFloat16>(dfNoDataValue)) &&
6434
0
               HasOnlyNoDataT(static_cast<const GFloat16 *>(pBuffer),
6435
0
                              static_cast<GFloat16>(dfNoDataValue), nWidth,
6436
0
                              nHeight, nLineStride, nComponents);
6437
0
    }
6438
1
    if (nBitsPerSample == 32 && nSampleFormat == GSF_FLOATING_POINT)
6439
0
    {
6440
0
        return (std::isnan(dfNoDataValue) ||
6441
0
                GDALIsValueInRange<float>(dfNoDataValue)) &&
6442
0
               HasOnlyNoDataT(static_cast<const float *>(pBuffer),
6443
0
                              static_cast<float>(dfNoDataValue), nWidth,
6444
0
                              nHeight, nLineStride, nComponents);
6445
0
    }
6446
1
    if (nBitsPerSample == 64 && nSampleFormat == GSF_FLOATING_POINT)
6447
1
    {
6448
1
        return HasOnlyNoDataT(static_cast<const double *>(pBuffer),
6449
1
                              dfNoDataValue, nWidth, nHeight, nLineStride,
6450
1
                              nComponents);
6451
1
    }
6452
0
    return false;
6453
1
}
6454
6455
#ifdef HAVE_SSE2
6456
6457
/************************************************************************/
6458
/*                       GDALDeinterleave3Byte()                        */
6459
/************************************************************************/
6460
6461
#if defined(__GNUC__) && !defined(__clang__)
6462
__attribute__((optimize("no-tree-vectorize")))
6463
#endif
6464
static void GDALDeinterleave3Byte(const GByte *CPL_RESTRICT pabySrc,
6465
                                  GByte *CPL_RESTRICT pabyDest0,
6466
                                  GByte *CPL_RESTRICT pabyDest1,
6467
                                  GByte *CPL_RESTRICT pabyDest2, size_t nIters)
6468
#ifdef USE_NEON_OPTIMIZATIONS
6469
{
6470
    return GDALDeinterleave3Byte_SSSE3(pabySrc, pabyDest0, pabyDest1, pabyDest2,
6471
                                       nIters);
6472
}
6473
#else
6474
7.35k
{
6475
7.35k
#ifdef HAVE_SSSE3_AT_COMPILE_TIME
6476
7.35k
    if (CPLHaveRuntimeSSSE3())
6477
7.35k
    {
6478
7.35k
        return GDALDeinterleave3Byte_SSSE3(pabySrc, pabyDest0, pabyDest1,
6479
7.35k
                                           pabyDest2, nIters);
6480
7.35k
    }
6481
0
#endif
6482
6483
0
    size_t i = 0;
6484
0
    if (((reinterpret_cast<uintptr_t>(pabySrc) |
6485
0
          reinterpret_cast<uintptr_t>(pabyDest0) |
6486
0
          reinterpret_cast<uintptr_t>(pabyDest1) |
6487
0
          reinterpret_cast<uintptr_t>(pabyDest2)) %
6488
0
         sizeof(unsigned int)) == 0)
6489
0
    {
6490
        // Slightly better than GCC autovectorizer
6491
0
        for (size_t j = 0; i + 3 < nIters; i += 4, ++j)
6492
0
        {
6493
0
            unsigned int word0 =
6494
0
                *reinterpret_cast<const unsigned int *>(pabySrc + 3 * i);
6495
0
            unsigned int word1 =
6496
0
                *reinterpret_cast<const unsigned int *>(pabySrc + 3 * i + 4);
6497
0
            unsigned int word2 =
6498
0
                *reinterpret_cast<const unsigned int *>(pabySrc + 3 * i + 8);
6499
0
            reinterpret_cast<unsigned int *>(pabyDest0)[j] =
6500
0
                (word0 & 0xff) | ((word0 >> 24) << 8) | (word1 & 0x00ff0000) |
6501
0
                ((word2 >> 8) << 24);
6502
0
            reinterpret_cast<unsigned int *>(pabyDest1)[j] =
6503
0
                ((word0 >> 8) & 0xff) | ((word1 & 0xff) << 8) |
6504
0
                (((word1 >> 24)) << 16) | ((word2 >> 16) << 24);
6505
0
            pabyDest2[j * 4] = static_cast<GByte>(word0 >> 16);
6506
0
            pabyDest2[j * 4 + 1] = static_cast<GByte>(word1 >> 8);
6507
0
            pabyDest2[j * 4 + 2] = static_cast<GByte>(word2);
6508
0
            pabyDest2[j * 4 + 3] = static_cast<GByte>(word2 >> 24);
6509
0
        }
6510
0
    }
6511
0
#if defined(__clang__)
6512
0
#pragma clang loop vectorize(disable)
6513
0
#endif
6514
0
    for (; i < nIters; ++i)
6515
0
    {
6516
0
        pabyDest0[i] = pabySrc[3 * i + 0];
6517
0
        pabyDest1[i] = pabySrc[3 * i + 1];
6518
0
        pabyDest2[i] = pabySrc[3 * i + 2];
6519
0
    }
6520
0
}
6521
#endif
6522
6523
/************************************************************************/
6524
/*                       GDALDeinterleave4Byte()                        */
6525
/************************************************************************/
6526
6527
#if !defined(__GNUC__) || defined(__clang__)
6528
6529
/************************************************************************/
6530
/*                            deinterleave()                            */
6531
/************************************************************************/
6532
6533
template <bool SHIFT, bool MASK>
6534
inline __m128i deinterleave(__m128i &xmm0_ori, __m128i &xmm1_ori,
6535
                            __m128i &xmm2_ori, __m128i &xmm3_ori)
6536
0
{
6537
    // Set higher 24bit of each int32 packed word to 0
6538
0
    if (SHIFT)
6539
0
    {
6540
0
        xmm0_ori = _mm_srli_epi32(xmm0_ori, 8);
6541
0
        xmm1_ori = _mm_srli_epi32(xmm1_ori, 8);
6542
0
        xmm2_ori = _mm_srli_epi32(xmm2_ori, 8);
6543
0
        xmm3_ori = _mm_srli_epi32(xmm3_ori, 8);
6544
0
    }
6545
0
    __m128i xmm0;
6546
0
    __m128i xmm1;
6547
0
    __m128i xmm2;
6548
0
    __m128i xmm3;
6549
0
    if (MASK)
6550
0
    {
6551
0
        const __m128i xmm_mask = _mm_set1_epi32(0xff);
6552
0
        xmm0 = _mm_and_si128(xmm0_ori, xmm_mask);
6553
0
        xmm1 = _mm_and_si128(xmm1_ori, xmm_mask);
6554
0
        xmm2 = _mm_and_si128(xmm2_ori, xmm_mask);
6555
0
        xmm3 = _mm_and_si128(xmm3_ori, xmm_mask);
6556
0
    }
6557
0
    else
6558
0
    {
6559
0
        xmm0 = xmm0_ori;
6560
0
        xmm1 = xmm1_ori;
6561
0
        xmm2 = xmm2_ori;
6562
0
        xmm3 = xmm3_ori;
6563
0
    }
6564
    // Pack int32 to int16
6565
0
    xmm0 = _mm_packs_epi32(xmm0, xmm1);
6566
0
    xmm2 = _mm_packs_epi32(xmm2, xmm3);
6567
    // Pack int16 to uint8
6568
0
    xmm0 = _mm_packus_epi16(xmm0, xmm2);
6569
0
    return xmm0;
6570
0
}
Unexecuted instantiation: long long __vector(2) deinterleave<false, true>(long long __vector(2)&, long long __vector(2)&, long long __vector(2)&, long long __vector(2)&)
Unexecuted instantiation: long long __vector(2) deinterleave<true, true>(long long __vector(2)&, long long __vector(2)&, long long __vector(2)&, long long __vector(2)&)
Unexecuted instantiation: long long __vector(2) deinterleave<true, false>(long long __vector(2)&, long long __vector(2)&, long long __vector(2)&, long long __vector(2)&)
6571
6572
static void GDALDeinterleave4Byte(const GByte *CPL_RESTRICT pabySrc,
6573
                                  GByte *CPL_RESTRICT pabyDest0,
6574
                                  GByte *CPL_RESTRICT pabyDest1,
6575
                                  GByte *CPL_RESTRICT pabyDest2,
6576
                                  GByte *CPL_RESTRICT pabyDest3, size_t nIters)
6577
#ifdef USE_NEON_OPTIMIZATIONS
6578
{
6579
    return GDALDeinterleave4Byte_SSSE3(pabySrc, pabyDest0, pabyDest1, pabyDest2,
6580
                                       pabyDest3, nIters);
6581
}
6582
#else
6583
36.4k
{
6584
36.4k
#ifdef HAVE_SSSE3_AT_COMPILE_TIME
6585
36.4k
    if (CPLHaveRuntimeSSSE3())
6586
36.4k
    {
6587
36.4k
        return GDALDeinterleave4Byte_SSSE3(pabySrc, pabyDest0, pabyDest1,
6588
36.4k
                                           pabyDest2, pabyDest3, nIters);
6589
36.4k
    }
6590
0
#endif
6591
6592
    // Not the optimal SSE2-only code, as gcc auto-vectorizer manages to
6593
    // do something slightly better.
6594
0
    size_t i = 0;
6595
0
    for (; i + 15 < nIters; i += 16)
6596
0
    {
6597
0
        __m128i xmm0_ori = _mm_loadu_si128(
6598
0
            reinterpret_cast<__m128i const *>(pabySrc + 4 * i + 0));
6599
0
        __m128i xmm1_ori = _mm_loadu_si128(
6600
0
            reinterpret_cast<__m128i const *>(pabySrc + 4 * i + 16));
6601
0
        __m128i xmm2_ori = _mm_loadu_si128(
6602
0
            reinterpret_cast<__m128i const *>(pabySrc + 4 * i + 32));
6603
0
        __m128i xmm3_ori = _mm_loadu_si128(
6604
0
            reinterpret_cast<__m128i const *>(pabySrc + 4 * i + 48));
6605
6606
0
        _mm_storeu_si128(
6607
0
            reinterpret_cast<__m128i *>(pabyDest0 + i),
6608
0
            deinterleave<false, true>(xmm0_ori, xmm1_ori, xmm2_ori, xmm3_ori));
6609
0
        _mm_storeu_si128(
6610
0
            reinterpret_cast<__m128i *>(pabyDest1 + i),
6611
0
            deinterleave<true, true>(xmm0_ori, xmm1_ori, xmm2_ori, xmm3_ori));
6612
0
        _mm_storeu_si128(
6613
0
            reinterpret_cast<__m128i *>(pabyDest2 + i),
6614
0
            deinterleave<true, true>(xmm0_ori, xmm1_ori, xmm2_ori, xmm3_ori));
6615
0
        _mm_storeu_si128(
6616
0
            reinterpret_cast<__m128i *>(pabyDest3 + i),
6617
0
            deinterleave<true, false>(xmm0_ori, xmm1_ori, xmm2_ori, xmm3_ori));
6618
0
    }
6619
6620
0
#if defined(__clang__)
6621
0
#pragma clang loop vectorize(disable)
6622
0
#endif
6623
0
    for (; i < nIters; ++i)
6624
0
    {
6625
0
        pabyDest0[i] = pabySrc[4 * i + 0];
6626
0
        pabyDest1[i] = pabySrc[4 * i + 1];
6627
0
        pabyDest2[i] = pabySrc[4 * i + 2];
6628
0
        pabyDest3[i] = pabySrc[4 * i + 3];
6629
0
    }
6630
0
}
6631
#endif
6632
#else
6633
// GCC autovectorizer does an excellent job
6634
__attribute__((optimize("tree-vectorize"))) static void GDALDeinterleave4Byte(
6635
    const GByte *CPL_RESTRICT pabySrc, GByte *CPL_RESTRICT pabyDest0,
6636
    GByte *CPL_RESTRICT pabyDest1, GByte *CPL_RESTRICT pabyDest2,
6637
    GByte *CPL_RESTRICT pabyDest3, size_t nIters)
6638
{
6639
    for (size_t i = 0; i < nIters; ++i)
6640
    {
6641
        pabyDest0[i] = pabySrc[4 * i + 0];
6642
        pabyDest1[i] = pabySrc[4 * i + 1];
6643
        pabyDest2[i] = pabySrc[4 * i + 2];
6644
        pabyDest3[i] = pabySrc[4 * i + 3];
6645
    }
6646
}
6647
#endif
6648
6649
#else
6650
6651
/************************************************************************/
6652
/*                       GDALDeinterleave3Byte()                        */
6653
/************************************************************************/
6654
6655
// TODO: Enabling below could help on non-Intel architectures where GCC knows
6656
// how to auto-vectorize
6657
// #if defined(__GNUC__)
6658
//__attribute__((optimize("tree-vectorize")))
6659
// #endif
6660
static void GDALDeinterleave3Byte(const GByte *CPL_RESTRICT pabySrc,
6661
                                  GByte *CPL_RESTRICT pabyDest0,
6662
                                  GByte *CPL_RESTRICT pabyDest1,
6663
                                  GByte *CPL_RESTRICT pabyDest2, size_t nIters)
6664
{
6665
    for (size_t i = 0; i < nIters; ++i)
6666
    {
6667
        pabyDest0[i] = pabySrc[3 * i + 0];
6668
        pabyDest1[i] = pabySrc[3 * i + 1];
6669
        pabyDest2[i] = pabySrc[3 * i + 2];
6670
    }
6671
}
6672
6673
/************************************************************************/
6674
/*                       GDALDeinterleave4Byte()                        */
6675
/************************************************************************/
6676
6677
// TODO: Enabling below could help on non-Intel architectures where gcc knows
6678
// how to auto-vectorize
6679
// #if defined(__GNUC__)
6680
//__attribute__((optimize("tree-vectorize")))
6681
// #endif
6682
static void GDALDeinterleave4Byte(const GByte *CPL_RESTRICT pabySrc,
6683
                                  GByte *CPL_RESTRICT pabyDest0,
6684
                                  GByte *CPL_RESTRICT pabyDest1,
6685
                                  GByte *CPL_RESTRICT pabyDest2,
6686
                                  GByte *CPL_RESTRICT pabyDest3, size_t nIters)
6687
{
6688
    for (size_t i = 0; i < nIters; ++i)
6689
    {
6690
        pabyDest0[i] = pabySrc[4 * i + 0];
6691
        pabyDest1[i] = pabySrc[4 * i + 1];
6692
        pabyDest2[i] = pabySrc[4 * i + 2];
6693
        pabyDest3[i] = pabySrc[4 * i + 3];
6694
    }
6695
}
6696
6697
#endif
6698
6699
/************************************************************************/
6700
/*                          GDALDeinterleave()                          */
6701
/************************************************************************/
6702
6703
/*! Copy values from a pixel-interleave buffer to multiple per-component
6704
    buffers.
6705
6706
    In pseudo-code
6707
    \verbatim
6708
    for(size_t i = 0; i < nIters; ++i)
6709
        for(int iComp = 0; iComp < nComponents; iComp++ )
6710
            ppDestBuffer[iComp][i] = pSourceBuffer[nComponents * i + iComp]
6711
    \endverbatim
6712
6713
    The implementation is optimized for a few cases, like de-interleaving
6714
    of 3 or 4-components Byte buffers.
6715
6716
    \since GDAL 3.6
6717
 */
6718
void GDALDeinterleave(const void *pSourceBuffer, GDALDataType eSourceDT,
6719
                      int nComponents, void **ppDestBuffer,
6720
                      GDALDataType eDestDT, size_t nIters)
6721
49.8k
{
6722
49.8k
    if (eSourceDT == eDestDT)
6723
49.8k
    {
6724
49.8k
        if (eSourceDT == GDT_UInt8 || eSourceDT == GDT_Int8)
6725
43.8k
        {
6726
43.8k
            if (nComponents == 3)
6727
7.35k
            {
6728
7.35k
                const GByte *CPL_RESTRICT pabySrc =
6729
7.35k
                    static_cast<const GByte *>(pSourceBuffer);
6730
7.35k
                GByte *CPL_RESTRICT pabyDest0 =
6731
7.35k
                    static_cast<GByte *>(ppDestBuffer[0]);
6732
7.35k
                GByte *CPL_RESTRICT pabyDest1 =
6733
7.35k
                    static_cast<GByte *>(ppDestBuffer[1]);
6734
7.35k
                GByte *CPL_RESTRICT pabyDest2 =
6735
7.35k
                    static_cast<GByte *>(ppDestBuffer[2]);
6736
7.35k
                GDALDeinterleave3Byte(pabySrc, pabyDest0, pabyDest1, pabyDest2,
6737
7.35k
                                      nIters);
6738
7.35k
                return;
6739
7.35k
            }
6740
36.4k
            else if (nComponents == 4)
6741
36.4k
            {
6742
36.4k
                const GByte *CPL_RESTRICT pabySrc =
6743
36.4k
                    static_cast<const GByte *>(pSourceBuffer);
6744
36.4k
                GByte *CPL_RESTRICT pabyDest0 =
6745
36.4k
                    static_cast<GByte *>(ppDestBuffer[0]);
6746
36.4k
                GByte *CPL_RESTRICT pabyDest1 =
6747
36.4k
                    static_cast<GByte *>(ppDestBuffer[1]);
6748
36.4k
                GByte *CPL_RESTRICT pabyDest2 =
6749
36.4k
                    static_cast<GByte *>(ppDestBuffer[2]);
6750
36.4k
                GByte *CPL_RESTRICT pabyDest3 =
6751
36.4k
                    static_cast<GByte *>(ppDestBuffer[3]);
6752
36.4k
                GDALDeinterleave4Byte(pabySrc, pabyDest0, pabyDest1, pabyDest2,
6753
36.4k
                                      pabyDest3, nIters);
6754
36.4k
                return;
6755
36.4k
            }
6756
43.8k
        }
6757
#if ((defined(__GNUC__) && !defined(__clang__)) ||                             \
6758
     defined(__INTEL_CLANG_COMPILER)) &&                                       \
6759
    defined(HAVE_SSE2) && defined(HAVE_SSSE3_AT_COMPILE_TIME)
6760
        else if ((eSourceDT == GDT_Int16 || eSourceDT == GDT_UInt16) &&
6761
                 CPLHaveRuntimeSSSE3())
6762
        {
6763
            if (nComponents == 3)
6764
            {
6765
                const GUInt16 *CPL_RESTRICT panSrc =
6766
                    static_cast<const GUInt16 *>(pSourceBuffer);
6767
                GUInt16 *CPL_RESTRICT panDest0 =
6768
                    static_cast<GUInt16 *>(ppDestBuffer[0]);
6769
                GUInt16 *CPL_RESTRICT panDest1 =
6770
                    static_cast<GUInt16 *>(ppDestBuffer[1]);
6771
                GUInt16 *CPL_RESTRICT panDest2 =
6772
                    static_cast<GUInt16 *>(ppDestBuffer[2]);
6773
                GDALDeinterleave3UInt16_SSSE3(panSrc, panDest0, panDest1,
6774
                                              panDest2, nIters);
6775
                return;
6776
            }
6777
#if !defined(__INTEL_CLANG_COMPILER)
6778
            // ICC autovectorizer doesn't do a good job, at least with icx
6779
            // 2022.1.0.20220316
6780
            else if (nComponents == 4)
6781
            {
6782
                const GUInt16 *CPL_RESTRICT panSrc =
6783
                    static_cast<const GUInt16 *>(pSourceBuffer);
6784
                GUInt16 *CPL_RESTRICT panDest0 =
6785
                    static_cast<GUInt16 *>(ppDestBuffer[0]);
6786
                GUInt16 *CPL_RESTRICT panDest1 =
6787
                    static_cast<GUInt16 *>(ppDestBuffer[1]);
6788
                GUInt16 *CPL_RESTRICT panDest2 =
6789
                    static_cast<GUInt16 *>(ppDestBuffer[2]);
6790
                GUInt16 *CPL_RESTRICT panDest3 =
6791
                    static_cast<GUInt16 *>(ppDestBuffer[3]);
6792
                GDALDeinterleave4UInt16_SSSE3(panSrc, panDest0, panDest1,
6793
                                              panDest2, panDest3, nIters);
6794
                return;
6795
            }
6796
#endif
6797
        }
6798
#endif
6799
49.8k
    }
6800
6801
6.07k
    const int nSourceDTSize = GDALGetDataTypeSizeBytes(eSourceDT);
6802
6.07k
    const int nDestDTSize = GDALGetDataTypeSizeBytes(eDestDT);
6803
28.2k
    for (int iComp = 0; iComp < nComponents; iComp++)
6804
22.1k
    {
6805
22.1k
        GDALCopyWords64(static_cast<const GByte *>(pSourceBuffer) +
6806
22.1k
                            iComp * nSourceDTSize,
6807
22.1k
                        eSourceDT, nComponents * nSourceDTSize,
6808
22.1k
                        ppDestBuffer[iComp], eDestDT, nDestDTSize, nIters);
6809
22.1k
    }
6810
6.07k
}
6811
6812
/************************************************************************/
6813
/*                   GDALTranspose2DSingleToSingle()                    */
6814
/************************************************************************/
6815
/**
6816
 * Transpose a 2D array of non-complex values, in a efficient (cache-oblivious) way.
6817
 *
6818
 * @param pSrc Source array of height = nSrcHeight and width = nSrcWidth.
6819
 * @param pDst Destination transposed array of height = nSrcWidth and width = nSrcHeight.
6820
 * @param nSrcWidth Width of pSrc array.
6821
 * @param nSrcHeight Height of pSrc array.
6822
 */
6823
6824
template <class DST, class SRC>
6825
void GDALTranspose2DSingleToSingle(const SRC *CPL_RESTRICT pSrc,
6826
                                   DST *CPL_RESTRICT pDst, size_t nSrcWidth,
6827
                                   size_t nSrcHeight)
6828
0
{
6829
0
    constexpr size_t blocksize = 32;
6830
0
    for (size_t i = 0; i < nSrcHeight; i += blocksize)
6831
0
    {
6832
0
        const size_t max_k = std::min(i + blocksize, nSrcHeight);
6833
0
        for (size_t j = 0; j < nSrcWidth; j += blocksize)
6834
0
        {
6835
            // transpose the block beginning at [i,j]
6836
0
            const size_t max_l = std::min(j + blocksize, nSrcWidth);
6837
0
            for (size_t k = i; k < max_k; ++k)
6838
0
            {
6839
0
                for (size_t l = j; l < max_l; ++l)
6840
0
                {
6841
0
                    GDALCopyWord(pSrc[l + k * nSrcWidth],
6842
0
                                 pDst[k + l * nSrcHeight]);
6843
0
                }
6844
0
            }
6845
0
        }
6846
0
    }
6847
0
}
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, unsigned char>(unsigned char const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, signed char>(signed char const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, unsigned short>(unsigned short const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, short>(short const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, unsigned int>(unsigned int const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, int>(int const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, unsigned long>(unsigned long const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, long>(long const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, cpl::Float16>(cpl::Float16 const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, float>(float const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned char, double>(double const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, unsigned char>(unsigned char const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, signed char>(signed char const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, unsigned short>(unsigned short const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, short>(short const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, unsigned int>(unsigned int const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, int>(int const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, unsigned long>(unsigned long const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, long>(long const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, cpl::Float16>(cpl::Float16 const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, float>(float const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<signed char, double>(double const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, unsigned char>(unsigned char const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, signed char>(signed char const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, unsigned short>(unsigned short const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, short>(short const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, unsigned int>(unsigned int const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, int>(int const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, unsigned long>(unsigned long const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, long>(long const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, cpl::Float16>(cpl::Float16 const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, float>(float const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned short, double>(double const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, unsigned char>(unsigned char const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, signed char>(signed char const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, unsigned short>(unsigned short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, short>(short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, unsigned int>(unsigned int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, int>(int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, unsigned long>(unsigned long const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, long>(long const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, cpl::Float16>(cpl::Float16 const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, float>(float const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<short, double>(double const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, unsigned char>(unsigned char const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, signed char>(signed char const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, unsigned short>(unsigned short const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, short>(short const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, unsigned int>(unsigned int const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, int>(int const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, unsigned long>(unsigned long const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, long>(long const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, cpl::Float16>(cpl::Float16 const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, float>(float const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned int, double>(double const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, unsigned char>(unsigned char const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, signed char>(signed char const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, unsigned short>(unsigned short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, short>(short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, unsigned int>(unsigned int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, int>(int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, unsigned long>(unsigned long const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, long>(long const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, cpl::Float16>(cpl::Float16 const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, float>(float const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<int, double>(double const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, unsigned char>(unsigned char const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, signed char>(signed char const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, unsigned short>(unsigned short const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, short>(short const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, unsigned int>(unsigned int const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, int>(int const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, unsigned long>(unsigned long const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, long>(long const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, cpl::Float16>(cpl::Float16 const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, float>(float const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<unsigned long, double>(double const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, unsigned char>(unsigned char const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, signed char>(signed char const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, unsigned short>(unsigned short const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, short>(short const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, unsigned int>(unsigned int const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, int>(int const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, unsigned long>(unsigned long const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, long>(long const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, cpl::Float16>(cpl::Float16 const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, float>(float const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<long, double>(double const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, unsigned char>(unsigned char const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, signed char>(signed char const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, unsigned short>(unsigned short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, short>(short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, unsigned int>(unsigned int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, int>(int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, unsigned long>(unsigned long const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, long>(long const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, cpl::Float16>(cpl::Float16 const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, float>(float const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<cpl::Float16, double>(double const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, unsigned char>(unsigned char const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, signed char>(signed char const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, unsigned short>(unsigned short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, short>(short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, unsigned int>(unsigned int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, int>(int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, unsigned long>(unsigned long const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, long>(long const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, cpl::Float16>(cpl::Float16 const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, float>(float const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<float, double>(double const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, unsigned char>(unsigned char const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, signed char>(signed char const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, unsigned short>(unsigned short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, short>(short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, unsigned int>(unsigned int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, int>(int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, unsigned long>(unsigned long const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, long>(long const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, cpl::Float16>(cpl::Float16 const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, float>(float const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToSingle<double, double>(double const*, double*, unsigned long, unsigned long)
6848
6849
/************************************************************************/
6850
/*                  GDALTranspose2DComplexToComplex()                   */
6851
/************************************************************************/
6852
/**
6853
 * Transpose a 2D array of complex values into an array of complex values,
6854
 * in a efficient (cache-oblivious) way.
6855
 *
6856
 * @param pSrc Source array of height = nSrcHeight and width = nSrcWidth.
6857
 * @param pDst Destination transposed array of height = nSrcWidth and width = nSrcHeight.
6858
 * @param nSrcWidth Width of pSrc array.
6859
 * @param nSrcHeight Height of pSrc array.
6860
 */
6861
template <class DST, class SRC>
6862
void GDALTranspose2DComplexToComplex(const SRC *CPL_RESTRICT pSrc,
6863
                                     DST *CPL_RESTRICT pDst, size_t nSrcWidth,
6864
                                     size_t nSrcHeight)
6865
0
{
6866
0
    constexpr size_t blocksize = 32;
6867
0
    for (size_t i = 0; i < nSrcHeight; i += blocksize)
6868
0
    {
6869
0
        const size_t max_k = std::min(i + blocksize, nSrcHeight);
6870
0
        for (size_t j = 0; j < nSrcWidth; j += blocksize)
6871
0
        {
6872
            // transpose the block beginning at [i,j]
6873
0
            const size_t max_l = std::min(j + blocksize, nSrcWidth);
6874
0
            for (size_t k = i; k < max_k; ++k)
6875
0
            {
6876
0
                for (size_t l = j; l < max_l; ++l)
6877
0
                {
6878
0
                    GDALCopyWord(pSrc[2 * (l + k * nSrcWidth) + 0],
6879
0
                                 pDst[2 * (k + l * nSrcHeight) + 0]);
6880
0
                    GDALCopyWord(pSrc[2 * (l + k * nSrcWidth) + 1],
6881
0
                                 pDst[2 * (k + l * nSrcHeight) + 1]);
6882
0
                }
6883
0
            }
6884
0
        }
6885
0
    }
6886
0
}
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<short, short>(short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<short, int>(int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<short, cpl::Float16>(cpl::Float16 const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<short, float>(float const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<short, double>(double const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<int, short>(short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<int, int>(int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<int, cpl::Float16>(cpl::Float16 const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<int, float>(float const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<int, double>(double const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<cpl::Float16, short>(short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<cpl::Float16, int>(int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<cpl::Float16, cpl::Float16>(cpl::Float16 const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<cpl::Float16, float>(float const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<cpl::Float16, double>(double const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<float, short>(short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<float, int>(int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<float, cpl::Float16>(cpl::Float16 const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<float, float>(float const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<float, double>(double const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<double, short>(short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<double, int>(int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<double, cpl::Float16>(cpl::Float16 const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<double, float>(float const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToComplex<double, double>(double const*, double*, unsigned long, unsigned long)
6887
6888
/************************************************************************/
6889
/*                   GDALTranspose2DComplexToSingle()                   */
6890
/************************************************************************/
6891
/**
6892
 * Transpose a 2D array of complex values into an array of non-complex values,
6893
 * in a efficient (cache-oblivious) way.
6894
 *
6895
 * @param pSrc Source array of height = nSrcHeight and width = nSrcWidth.
6896
 * @param pDst Destination transposed array of height = nSrcWidth and width = nSrcHeight.
6897
 * @param nSrcWidth Width of pSrc array.
6898
 * @param nSrcHeight Height of pSrc array.
6899
 */
6900
template <class DST, class SRC>
6901
void GDALTranspose2DComplexToSingle(const SRC *CPL_RESTRICT pSrc,
6902
                                    DST *CPL_RESTRICT pDst, size_t nSrcWidth,
6903
                                    size_t nSrcHeight)
6904
0
{
6905
0
    constexpr size_t blocksize = 32;
6906
0
    for (size_t i = 0; i < nSrcHeight; i += blocksize)
6907
0
    {
6908
0
        const size_t max_k = std::min(i + blocksize, nSrcHeight);
6909
0
        for (size_t j = 0; j < nSrcWidth; j += blocksize)
6910
0
        {
6911
            // transpose the block beginning at [i,j]
6912
0
            const size_t max_l = std::min(j + blocksize, nSrcWidth);
6913
0
            for (size_t k = i; k < max_k; ++k)
6914
0
            {
6915
0
                for (size_t l = j; l < max_l; ++l)
6916
0
                {
6917
0
                    GDALCopyWord(pSrc[2 * (l + k * nSrcWidth) + 0],
6918
0
                                 pDst[k + l * nSrcHeight]);
6919
0
                }
6920
0
            }
6921
0
        }
6922
0
    }
6923
0
}
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned char, short>(short const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned char, int>(int const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned char, cpl::Float16>(cpl::Float16 const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned char, float>(float const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned char, double>(double const*, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<signed char, short>(short const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<signed char, int>(int const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<signed char, cpl::Float16>(cpl::Float16 const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<signed char, float>(float const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<signed char, double>(double const*, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned short, short>(short const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned short, int>(int const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned short, cpl::Float16>(cpl::Float16 const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned short, float>(float const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned short, double>(double const*, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<short, short>(short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<short, int>(int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<short, cpl::Float16>(cpl::Float16 const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<short, float>(float const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<short, double>(double const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned int, short>(short const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned int, int>(int const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned int, cpl::Float16>(cpl::Float16 const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned int, float>(float const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned int, double>(double const*, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<int, short>(short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<int, int>(int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<int, cpl::Float16>(cpl::Float16 const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<int, float>(float const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<int, double>(double const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned long, short>(short const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned long, int>(int const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned long, cpl::Float16>(cpl::Float16 const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned long, float>(float const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<unsigned long, double>(double const*, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<long, short>(short const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<long, int>(int const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<long, cpl::Float16>(cpl::Float16 const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<long, float>(float const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<long, double>(double const*, long*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<cpl::Float16, short>(short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<cpl::Float16, int>(int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<cpl::Float16, cpl::Float16>(cpl::Float16 const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<cpl::Float16, float>(float const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<cpl::Float16, double>(double const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<float, short>(short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<float, int>(int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<float, cpl::Float16>(cpl::Float16 const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<float, float>(float const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<float, double>(double const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<double, short>(short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<double, int>(int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<double, cpl::Float16>(cpl::Float16 const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<double, float>(float const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DComplexToSingle<double, double>(double const*, double*, unsigned long, unsigned long)
6924
6925
/************************************************************************/
6926
/*                   GDALTranspose2DSingleToComplex()                   */
6927
/************************************************************************/
6928
/**
6929
 * Transpose a 2D array of non-complex values into an array of complex values,
6930
 * in a efficient (cache-oblivious) way.
6931
 *
6932
 * @param pSrc Source array of height = nSrcHeight and width = nSrcWidth.
6933
 * @param pDst Destination transposed array of height = nSrcWidth and width = nSrcHeight.
6934
 * @param nSrcWidth Width of pSrc array.
6935
 * @param nSrcHeight Height of pSrc array.
6936
 */
6937
template <class DST, class SRC>
6938
void GDALTranspose2DSingleToComplex(const SRC *CPL_RESTRICT pSrc,
6939
                                    DST *CPL_RESTRICT pDst, size_t nSrcWidth,
6940
                                    size_t nSrcHeight)
6941
0
{
6942
0
    constexpr size_t blocksize = 32;
6943
0
    for (size_t i = 0; i < nSrcHeight; i += blocksize)
6944
0
    {
6945
0
        const size_t max_k = std::min(i + blocksize, nSrcHeight);
6946
0
        for (size_t j = 0; j < nSrcWidth; j += blocksize)
6947
0
        {
6948
            // transpose the block beginning at [i,j]
6949
0
            const size_t max_l = std::min(j + blocksize, nSrcWidth);
6950
0
            for (size_t k = i; k < max_k; ++k)
6951
0
            {
6952
0
                for (size_t l = j; l < max_l; ++l)
6953
0
                {
6954
0
                    GDALCopyWord(pSrc[l + k * nSrcWidth],
6955
0
                                 pDst[2 * (k + l * nSrcHeight) + 0]);
6956
0
                    pDst[2 * (k + l * nSrcHeight) + 1] = 0;
6957
0
                }
6958
0
            }
6959
0
        }
6960
0
    }
6961
0
}
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, unsigned char>(unsigned char const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, signed char>(signed char const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, unsigned short>(unsigned short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, short>(short const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, unsigned int>(unsigned int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, int>(int const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, unsigned long>(unsigned long const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, long>(long const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, cpl::Float16>(cpl::Float16 const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, float>(float const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<short, double>(double const*, short*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, unsigned char>(unsigned char const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, signed char>(signed char const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, unsigned short>(unsigned short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, short>(short const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, unsigned int>(unsigned int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, int>(int const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, unsigned long>(unsigned long const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, long>(long const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, cpl::Float16>(cpl::Float16 const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, float>(float const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<int, double>(double const*, int*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, unsigned char>(unsigned char const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, signed char>(signed char const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, unsigned short>(unsigned short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, short>(short const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, unsigned int>(unsigned int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, int>(int const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, unsigned long>(unsigned long const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, long>(long const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, cpl::Float16>(cpl::Float16 const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, float>(float const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<cpl::Float16, double>(double const*, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, unsigned char>(unsigned char const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, signed char>(signed char const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, unsigned short>(unsigned short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, short>(short const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, unsigned int>(unsigned int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, int>(int const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, unsigned long>(unsigned long const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, long>(long const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, cpl::Float16>(cpl::Float16 const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, float>(float const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<float, double>(double const*, float*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, unsigned char>(unsigned char const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, signed char>(signed char const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, unsigned short>(unsigned short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, short>(short const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, unsigned int>(unsigned int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, int>(int const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, unsigned long>(unsigned long const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, long>(long const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, cpl::Float16>(cpl::Float16 const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, float>(float const*, double*, unsigned long, unsigned long)
Unexecuted instantiation: void GDALTranspose2DSingleToComplex<double, double>(double const*, double*, unsigned long, unsigned long)
6962
6963
/************************************************************************/
6964
/*                          GDALTranspose2D()                           */
6965
/************************************************************************/
6966
6967
template <class DST, bool DST_IS_COMPLEX>
6968
static void GDALTranspose2D(const void *pSrc, GDALDataType eSrcType, DST *pDst,
6969
                            size_t nSrcWidth, size_t nSrcHeight)
6970
0
{
6971
0
#define CALL_GDALTranspose2D_internal(SRC_TYPE)                                \
6972
0
    do                                                                         \
6973
0
    {                                                                          \
6974
0
        if constexpr (DST_IS_COMPLEX)                                          \
6975
0
        {                                                                      \
6976
0
            GDALTranspose2DSingleToComplex(                                    \
6977
0
                static_cast<const SRC_TYPE *>(pSrc), pDst, nSrcWidth,          \
6978
0
                nSrcHeight);                                                   \
6979
0
        }                                                                      \
6980
0
        else                                                                   \
6981
0
        {                                                                      \
6982
0
            GDALTranspose2DSingleToSingle(static_cast<const SRC_TYPE *>(pSrc), \
6983
0
                                          pDst, nSrcWidth, nSrcHeight);        \
6984
0
        }                                                                      \
6985
0
    } while (0)
6986
6987
0
#define CALL_GDALTranspose2DComplex_internal(SRC_TYPE)                         \
6988
0
    do                                                                         \
6989
0
    {                                                                          \
6990
0
        if constexpr (DST_IS_COMPLEX)                                          \
6991
0
        {                                                                      \
6992
0
            GDALTranspose2DComplexToComplex(                                   \
6993
0
                static_cast<const SRC_TYPE *>(pSrc), pDst, nSrcWidth,          \
6994
0
                nSrcHeight);                                                   \
6995
0
        }                                                                      \
6996
0
        else                                                                   \
6997
0
        {                                                                      \
6998
0
            GDALTranspose2DComplexToSingle(                                    \
6999
0
                static_cast<const SRC_TYPE *>(pSrc), pDst, nSrcWidth,          \
7000
0
                nSrcHeight);                                                   \
7001
0
        }                                                                      \
7002
0
    } while (0)
7003
7004
    // clang-format off
7005
0
    switch (eSrcType)
7006
0
    {
7007
0
        case GDT_UInt8:     CALL_GDALTranspose2D_internal(uint8_t); break;
7008
0
        case GDT_Int8:     CALL_GDALTranspose2D_internal(int8_t); break;
7009
0
        case GDT_UInt16:   CALL_GDALTranspose2D_internal(uint16_t); break;
7010
0
        case GDT_Int16:    CALL_GDALTranspose2D_internal(int16_t); break;
7011
0
        case GDT_UInt32:   CALL_GDALTranspose2D_internal(uint32_t); break;
7012
0
        case GDT_Int32:    CALL_GDALTranspose2D_internal(int32_t); break;
7013
0
        case GDT_UInt64:   CALL_GDALTranspose2D_internal(uint64_t); break;
7014
0
        case GDT_Int64:    CALL_GDALTranspose2D_internal(int64_t); break;
7015
0
        case GDT_Float16:  CALL_GDALTranspose2D_internal(GFloat16); break;
7016
0
        case GDT_Float32:  CALL_GDALTranspose2D_internal(float); break;
7017
0
        case GDT_Float64:  CALL_GDALTranspose2D_internal(double); break;
7018
0
        case GDT_CInt16:   CALL_GDALTranspose2DComplex_internal(int16_t); break;
7019
0
        case GDT_CInt32:   CALL_GDALTranspose2DComplex_internal(int32_t); break;
7020
0
        case GDT_CFloat16: CALL_GDALTranspose2DComplex_internal(GFloat16); break;
7021
0
        case GDT_CFloat32: CALL_GDALTranspose2DComplex_internal(float); break;
7022
0
        case GDT_CFloat64: CALL_GDALTranspose2DComplex_internal(double); break;
7023
0
        case GDT_Unknown:
7024
0
        case GDT_TypeCount:
7025
0
            break;
7026
0
    }
7027
        // clang-format on
7028
7029
0
#undef CALL_GDALTranspose2D_internal
7030
0
#undef CALL_GDALTranspose2DComplex_internal
7031
0
}
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<unsigned char, false>(void const*, GDALDataType, unsigned char*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<signed char, false>(void const*, GDALDataType, signed char*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<unsigned short, false>(void const*, GDALDataType, unsigned short*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<short, false>(void const*, GDALDataType, short*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<unsigned int, false>(void const*, GDALDataType, unsigned int*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<int, false>(void const*, GDALDataType, int*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<unsigned long, false>(void const*, GDALDataType, unsigned long*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<long, false>(void const*, GDALDataType, long*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<cpl::Float16, false>(void const*, GDALDataType, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<float, false>(void const*, GDALDataType, float*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<double, false>(void const*, GDALDataType, double*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<short, true>(void const*, GDALDataType, short*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<int, true>(void const*, GDALDataType, int*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<cpl::Float16, true>(void const*, GDALDataType, cpl::Float16*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<float, true>(void const*, GDALDataType, float*, unsigned long, unsigned long)
Unexecuted instantiation: rasterio.cpp:void GDALTranspose2D<double, true>(void const*, GDALDataType, double*, unsigned long, unsigned long)
7032
7033
/************************************************************************/
7034
/*                        GDALInterleave2Byte()                         */
7035
/************************************************************************/
7036
7037
#if defined(HAVE_SSE2) &&                                                      \
7038
    (!defined(__GNUC__) || defined(__INTEL_CLANG_COMPILER))
7039
7040
// ICC autovectorizer doesn't do a good job at generating good SSE code,
7041
// at least with icx 2024.0.2.20231213, but it nicely unrolls the below loop.
7042
#if defined(__GNUC__)
7043
__attribute__((noinline))
7044
#endif
7045
static void GDALInterleave2Byte(const uint8_t *CPL_RESTRICT pSrc,
7046
                                uint8_t *CPL_RESTRICT pDst, size_t nIters)
7047
{
7048
    size_t i = 0;
7049
    constexpr size_t VALS_PER_ITER = 16;
7050
    for (i = 0; i + VALS_PER_ITER <= nIters; i += VALS_PER_ITER)
7051
    {
7052
        __m128i xmm0 =
7053
            _mm_loadu_si128(reinterpret_cast<__m128i const *>(pSrc + i));
7054
        __m128i xmm1 = _mm_loadu_si128(
7055
            reinterpret_cast<__m128i const *>(pSrc + i + nIters));
7056
        _mm_storeu_si128(reinterpret_cast<__m128i *>(pDst + 2 * i),
7057
                         _mm_unpacklo_epi8(xmm0, xmm1));
7058
        _mm_storeu_si128(
7059
            reinterpret_cast<__m128i *>(pDst + 2 * i + VALS_PER_ITER),
7060
            _mm_unpackhi_epi8(xmm0, xmm1));
7061
    }
7062
#if defined(__clang__)
7063
#pragma clang loop vectorize(disable)
7064
#endif
7065
    for (; i < nIters; ++i)
7066
    {
7067
        pDst[2 * i + 0] = pSrc[i + 0 * nIters];
7068
        pDst[2 * i + 1] = pSrc[i + 1 * nIters];
7069
    }
7070
}
7071
7072
#else
7073
7074
#if defined(__GNUC__) && !defined(__clang__)
7075
__attribute__((optimize("tree-vectorize")))
7076
#endif
7077
#if defined(__GNUC__)
7078
__attribute__((noinline))
7079
#endif
7080
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7081
// clang++ -O2 -fsanitize=undefined fails to vectorize, ignore that warning
7082
#pragma clang diagnostic push
7083
#pragma clang diagnostic ignored "-Wpass-failed"
7084
#endif
7085
static void GDALInterleave2Byte(const uint8_t *CPL_RESTRICT pSrc,
7086
                                uint8_t *CPL_RESTRICT pDst, size_t nIters)
7087
0
{
7088
0
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7089
0
#pragma clang loop vectorize(enable)
7090
0
#endif
7091
0
    for (size_t i = 0; i < nIters; ++i)
7092
0
    {
7093
0
        pDst[2 * i + 0] = pSrc[i + 0 * nIters];
7094
0
        pDst[2 * i + 1] = pSrc[i + 1 * nIters];
7095
0
    }
7096
0
}
7097
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7098
#pragma clang diagnostic pop
7099
#endif
7100
7101
#endif
7102
7103
/************************************************************************/
7104
/*                        GDALInterleave4Byte()                         */
7105
/************************************************************************/
7106
7107
#if defined(HAVE_SSE2) &&                                                      \
7108
    (!defined(__GNUC__) || defined(__INTEL_CLANG_COMPILER))
7109
7110
// ICC autovectorizer doesn't do a good job at generating good SSE code,
7111
// at least with icx 2024.0.2.20231213, but it nicely unrolls the below loop.
7112
#if defined(__GNUC__)
7113
__attribute__((noinline))
7114
#endif
7115
static void GDALInterleave4Byte(const uint8_t *CPL_RESTRICT pSrc,
7116
                                uint8_t *CPL_RESTRICT pDst, size_t nIters)
7117
{
7118
    size_t i = 0;
7119
    constexpr size_t VALS_PER_ITER = 16;
7120
    for (i = 0; i + VALS_PER_ITER <= nIters; i += VALS_PER_ITER)
7121
    {
7122
        __m128i xmm0 = _mm_loadu_si128(
7123
            reinterpret_cast<__m128i const *>(pSrc + i + 0 * nIters));
7124
        __m128i xmm1 = _mm_loadu_si128(
7125
            reinterpret_cast<__m128i const *>(pSrc + i + 1 * nIters));
7126
        __m128i xmm2 = _mm_loadu_si128(
7127
            reinterpret_cast<__m128i const *>(pSrc + i + 2 * nIters));
7128
        __m128i xmm3 = _mm_loadu_si128(
7129
            reinterpret_cast<__m128i const *>(pSrc + i + 3 * nIters));
7130
        auto tmp0 = _mm_unpacklo_epi8(
7131
            xmm0,
7132
            xmm1);  // (xmm0_0, xmm1_0, xmm0_1, xmm1_1, xmm0_2, xmm1_2, ...)
7133
        auto tmp1 = _mm_unpackhi_epi8(
7134
            xmm0,
7135
            xmm1);  // (xmm0_8, xmm1_8, xmm0_9, xmm1_9, xmm0_10, xmm1_10, ...)
7136
        auto tmp2 = _mm_unpacklo_epi8(
7137
            xmm2,
7138
            xmm3);  // (xmm2_0, xmm3_0, xmm2_1, xmm3_1, xmm2_2, xmm3_2, ...)
7139
        auto tmp3 = _mm_unpackhi_epi8(
7140
            xmm2,
7141
            xmm3);  // (xmm2_8, xmm3_8, xmm2_9, xmm3_9, xmm2_10, xmm3_10, ...)
7142
        auto tmp2_0 = _mm_unpacklo_epi16(
7143
            tmp0,
7144
            tmp2);  // (xmm0_0, xmm1_0, xmm2_0, xmm3_0, xmm0_1, xmm1_1, xmm2_1, xmm3_1, ...)
7145
        auto tmp2_1 = _mm_unpackhi_epi16(tmp0, tmp2);
7146
        auto tmp2_2 = _mm_unpacklo_epi16(tmp1, tmp3);
7147
        auto tmp2_3 = _mm_unpackhi_epi16(tmp1, tmp3);
7148
        _mm_storeu_si128(
7149
            reinterpret_cast<__m128i *>(pDst + 4 * i + 0 * VALS_PER_ITER),
7150
            tmp2_0);
7151
        _mm_storeu_si128(
7152
            reinterpret_cast<__m128i *>(pDst + 4 * i + 1 * VALS_PER_ITER),
7153
            tmp2_1);
7154
        _mm_storeu_si128(
7155
            reinterpret_cast<__m128i *>(pDst + 4 * i + 2 * VALS_PER_ITER),
7156
            tmp2_2);
7157
        _mm_storeu_si128(
7158
            reinterpret_cast<__m128i *>(pDst + 4 * i + 3 * VALS_PER_ITER),
7159
            tmp2_3);
7160
    }
7161
#if defined(__clang__)
7162
#pragma clang loop vectorize(disable)
7163
#endif
7164
    for (; i < nIters; ++i)
7165
    {
7166
        pDst[4 * i + 0] = pSrc[i + 0 * nIters];
7167
        pDst[4 * i + 1] = pSrc[i + 1 * nIters];
7168
        pDst[4 * i + 2] = pSrc[i + 2 * nIters];
7169
        pDst[4 * i + 3] = pSrc[i + 3 * nIters];
7170
    }
7171
}
7172
7173
#else
7174
7175
#if defined(__GNUC__) && !defined(__clang__)
7176
__attribute__((optimize("tree-vectorize")))
7177
#endif
7178
#if defined(__GNUC__)
7179
__attribute__((noinline))
7180
#endif
7181
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7182
// clang++ -O2 -fsanitize=undefined fails to vectorize, ignore that warning
7183
#pragma clang diagnostic push
7184
#pragma clang diagnostic ignored "-Wpass-failed"
7185
#endif
7186
static void GDALInterleave4Byte(const uint8_t *CPL_RESTRICT pSrc,
7187
                                uint8_t *CPL_RESTRICT pDst, size_t nIters)
7188
0
{
7189
0
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7190
0
#pragma clang loop vectorize(enable)
7191
0
#endif
7192
0
    for (size_t i = 0; i < nIters; ++i)
7193
0
    {
7194
0
        pDst[4 * i + 0] = pSrc[i + 0 * nIters];
7195
0
        pDst[4 * i + 1] = pSrc[i + 1 * nIters];
7196
0
        pDst[4 * i + 2] = pSrc[i + 2 * nIters];
7197
0
        pDst[4 * i + 3] = pSrc[i + 3 * nIters];
7198
0
    }
7199
0
}
7200
#if defined(__clang__) && !defined(__INTEL_CLANG_COMPILER)
7201
#pragma clang diagnostic pop
7202
#endif
7203
7204
#endif
7205
7206
/************************************************************************/
7207
/*                          GDALTranspose2D()                           */
7208
/************************************************************************/
7209
7210
/**
7211
 * Transpose a 2D array in a efficient (cache-oblivious) way.
7212
 *
7213
 * @param pSrc Source array of width = nSrcWidth and height = nSrcHeight.
7214
 * @param eSrcType Data type of pSrc.
7215
 * @param pDst Destination transposed array of width = nSrcHeight and height = nSrcWidth.
7216
 * @param eDstType Data type of pDst.
7217
 * @param nSrcWidth Width of pSrc array.
7218
 * @param nSrcHeight Height of pSrc array.
7219
 * @since GDAL 3.11
7220
 */
7221
7222
void GDALTranspose2D(const void *pSrc, GDALDataType eSrcType, void *pDst,
7223
                     GDALDataType eDstType, size_t nSrcWidth, size_t nSrcHeight)
7224
0
{
7225
0
    if (eSrcType == eDstType && (eSrcType == GDT_UInt8 || eSrcType == GDT_Int8))
7226
0
    {
7227
0
        if (nSrcHeight == 2)
7228
0
        {
7229
0
            GDALInterleave2Byte(static_cast<const uint8_t *>(pSrc),
7230
0
                                static_cast<uint8_t *>(pDst), nSrcWidth);
7231
0
            return;
7232
0
        }
7233
0
        if (nSrcHeight == 4)
7234
0
        {
7235
0
            GDALInterleave4Byte(static_cast<const uint8_t *>(pSrc),
7236
0
                                static_cast<uint8_t *>(pDst), nSrcWidth);
7237
0
            return;
7238
0
        }
7239
0
#if (defined(HAVE_SSSE3_AT_COMPILE_TIME) &&                                    \
7240
0
     (defined(__x86_64) || defined(_M_X64)))
7241
0
        if (CPLHaveRuntimeSSSE3())
7242
0
        {
7243
0
            GDALTranspose2D_Byte_SSSE3(static_cast<const uint8_t *>(pSrc),
7244
0
                                       static_cast<uint8_t *>(pDst), nSrcWidth,
7245
0
                                       nSrcHeight);
7246
0
            return;
7247
0
        }
7248
#elif defined(USE_NEON_OPTIMIZATIONS)
7249
        {
7250
            GDALTranspose2D_Byte_SSSE3(static_cast<const uint8_t *>(pSrc),
7251
                                       static_cast<uint8_t *>(pDst), nSrcWidth,
7252
                                       nSrcHeight);
7253
            return;
7254
        }
7255
#endif
7256
0
    }
7257
7258
0
#define CALL_GDALTranspose2D_internal(DST_TYPE, DST_IS_COMPLEX)                \
7259
0
    GDALTranspose2D<DST_TYPE, DST_IS_COMPLEX>(                                 \
7260
0
        pSrc, eSrcType, static_cast<DST_TYPE *>(pDst), nSrcWidth, nSrcHeight)
7261
7262
    // clang-format off
7263
0
    switch (eDstType)
7264
0
    {
7265
0
        case GDT_UInt8:     CALL_GDALTranspose2D_internal(uint8_t, false); break;
7266
0
        case GDT_Int8:     CALL_GDALTranspose2D_internal(int8_t, false); break;
7267
0
        case GDT_UInt16:   CALL_GDALTranspose2D_internal(uint16_t, false); break;
7268
0
        case GDT_Int16:    CALL_GDALTranspose2D_internal(int16_t, false); break;
7269
0
        case GDT_UInt32:   CALL_GDALTranspose2D_internal(uint32_t, false); break;
7270
0
        case GDT_Int32:    CALL_GDALTranspose2D_internal(int32_t, false); break;
7271
0
        case GDT_UInt64:   CALL_GDALTranspose2D_internal(uint64_t, false); break;
7272
0
        case GDT_Int64:    CALL_GDALTranspose2D_internal(int64_t, false); break;
7273
0
        case GDT_Float16:  CALL_GDALTranspose2D_internal(GFloat16, false); break;
7274
0
        case GDT_Float32:  CALL_GDALTranspose2D_internal(float, false); break;
7275
0
        case GDT_Float64:  CALL_GDALTranspose2D_internal(double, false); break;
7276
0
        case GDT_CInt16:   CALL_GDALTranspose2D_internal(int16_t, true); break;
7277
0
        case GDT_CInt32:   CALL_GDALTranspose2D_internal(int32_t, true); break;
7278
0
        case GDT_CFloat16: CALL_GDALTranspose2D_internal(GFloat16, true); break;
7279
0
        case GDT_CFloat32: CALL_GDALTranspose2D_internal(float, true); break;
7280
0
        case GDT_CFloat64: CALL_GDALTranspose2D_internal(double, true); break;
7281
0
        case GDT_Unknown:
7282
0
        case GDT_TypeCount:
7283
0
            break;
7284
0
    }
7285
        // clang-format on
7286
7287
0
#undef CALL_GDALTranspose2D_internal
7288
0
}
7289
7290
/************************************************************************/
7291
/*                     ExtractBitAndConvertTo255()                      */
7292
/************************************************************************/
7293
7294
#if defined(__GNUC__) || defined(_MSC_VER)
7295
// Signedness of char implementation dependent, so be explicit.
7296
// Assumes 2-complement integer types and sign extension of right shifting
7297
// GCC guarantees such:
7298
// https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation
7299
static inline GByte ExtractBitAndConvertTo255(GByte byVal, int nBit)
7300
3.87M
{
7301
3.87M
    return static_cast<GByte>(static_cast<signed char>(byVal << (7 - nBit)) >>
7302
3.87M
                              7);
7303
3.87M
}
7304
#else
7305
// Portable way
7306
static inline GByte ExtractBitAndConvertTo255(GByte byVal, int nBit)
7307
{
7308
    return (byVal & (1 << nBit)) ? 255 : 0;
7309
}
7310
#endif
7311
7312
/************************************************************************/
7313
/*                  ExpandEightPackedBitsToByteAt255()                  */
7314
/************************************************************************/
7315
7316
static inline void ExpandEightPackedBitsToByteAt255(GByte byVal,
7317
                                                    GByte abyOutput[8])
7318
450k
{
7319
450k
    abyOutput[0] = ExtractBitAndConvertTo255(byVal, 7);
7320
450k
    abyOutput[1] = ExtractBitAndConvertTo255(byVal, 6);
7321
450k
    abyOutput[2] = ExtractBitAndConvertTo255(byVal, 5);
7322
450k
    abyOutput[3] = ExtractBitAndConvertTo255(byVal, 4);
7323
450k
    abyOutput[4] = ExtractBitAndConvertTo255(byVal, 3);
7324
450k
    abyOutput[5] = ExtractBitAndConvertTo255(byVal, 2);
7325
450k
    abyOutput[6] = ExtractBitAndConvertTo255(byVal, 1);
7326
450k
    abyOutput[7] = ExtractBitAndConvertTo255(byVal, 0);
7327
450k
}
7328
7329
/************************************************************************/
7330
/*                 GDALExpandPackedBitsToByteAt0Or255()                 */
7331
/************************************************************************/
7332
7333
/** Expand packed-bits (ordered from most-significant bit to least one)
7334
  into a byte each, where a bit at 0 is expanded to a byte at 0, and a bit
7335
  at 1 to a byte at 255.
7336
7337
 The function does (in a possibly more optimized way) the following:
7338
 \code{.cpp}
7339
 for (size_t i = 0; i < nInputBits; ++i )
7340
 {
7341
     pabyOutput[i] = (pabyInput[i / 8] & (1 << (7 - (i % 8)))) ? 255 : 0;
7342
 }
7343
 \endcode
7344
7345
 @param pabyInput Input array of (nInputBits + 7) / 8 bytes.
7346
 @param pabyOutput Output array of nInputBits bytes.
7347
 @param nInputBits Number of valid bits in pabyInput.
7348
7349
 @since 3.11
7350
*/
7351
7352
void GDALExpandPackedBitsToByteAt0Or255(const GByte *CPL_RESTRICT pabyInput,
7353
                                        GByte *CPL_RESTRICT pabyOutput,
7354
                                        size_t nInputBits)
7355
163k
{
7356
163k
    const size_t nInputWholeBytes = nInputBits / 8;
7357
163k
    size_t iByte = 0;
7358
7359
163k
#ifdef HAVE_SSE2
7360
    // Mask to isolate each bit
7361
163k
    const __m128i bit_mask = _mm_set_epi8(1, 2, 4, 8, 16, 32, 64, -128, 1, 2, 4,
7362
163k
                                          8, 16, 32, 64, -128);
7363
163k
    const __m128i zero = _mm_setzero_si128();
7364
163k
    const __m128i all_ones = _mm_set1_epi8(-1);
7365
#ifdef __SSSE3__
7366
    const __m128i dispatch_two_bytes =
7367
        _mm_set_epi8(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
7368
#endif
7369
163k
    constexpr size_t SSE_REG_SIZE = sizeof(bit_mask);
7370
712k
    for (; iByte + SSE_REG_SIZE <= nInputWholeBytes; iByte += SSE_REG_SIZE)
7371
549k
    {
7372
549k
        __m128i reg_ori = _mm_loadu_si128(
7373
549k
            reinterpret_cast<const __m128i *>(pabyInput + iByte));
7374
7375
549k
        constexpr int NUM_PROCESSED_BYTES_PER_REG = 2;
7376
4.94M
        for (size_t k = 0; k < SSE_REG_SIZE / NUM_PROCESSED_BYTES_PER_REG; ++k)
7377
4.39M
        {
7378
            // Given reg_ori = (A, B, ... 14 other bytes ...),
7379
            // expand to (A, A, A, A, A, A, A, A, B, B, B, B, B, B, B, B)
7380
#ifdef __SSSE3__
7381
            __m128i reg = _mm_shuffle_epi8(reg_ori, dispatch_two_bytes);
7382
#else
7383
4.39M
            __m128i reg = _mm_unpacklo_epi8(reg_ori, reg_ori);
7384
4.39M
            reg = _mm_unpacklo_epi16(reg, reg);
7385
4.39M
            reg = _mm_unpacklo_epi32(reg, reg);
7386
4.39M
#endif
7387
7388
            // Test if bits of interest are set
7389
4.39M
            reg = _mm_and_si128(reg, bit_mask);
7390
7391
            // Now test if those bits are set, by comparing to zero. So the
7392
            // result will be that bytes where bits are set will be at 0, and
7393
            // ones where they are cleared will be at 0xFF. So the inverse of
7394
            // the end result we want!
7395
4.39M
            reg = _mm_cmpeq_epi8(reg, zero);
7396
7397
            // Invert the result
7398
4.39M
            reg = _mm_andnot_si128(reg, all_ones);
7399
7400
4.39M
            _mm_storeu_si128(reinterpret_cast<__m128i *>(pabyOutput), reg);
7401
7402
4.39M
            pabyOutput += SSE_REG_SIZE;
7403
7404
            // Right-shift of 2 bytes
7405
4.39M
            reg_ori = _mm_bsrli_si128(reg_ori, NUM_PROCESSED_BYTES_PER_REG);
7406
4.39M
        }
7407
549k
    }
7408
7409
163k
#endif  // HAVE_SSE2
7410
7411
613k
    for (; iByte < nInputWholeBytes; ++iByte)
7412
450k
    {
7413
450k
        ExpandEightPackedBitsToByteAt255(pabyInput[iByte], pabyOutput);
7414
450k
        pabyOutput += 8;
7415
450k
    }
7416
440k
    for (int iBit = 0; iBit < static_cast<int>(nInputBits % 8); ++iBit)
7417
277k
    {
7418
277k
        *pabyOutput = ExtractBitAndConvertTo255(pabyInput[iByte], 7 - iBit);
7419
277k
        ++pabyOutput;
7420
277k
    }
7421
163k
}
7422
7423
/************************************************************************/
7424
/*                   ExpandEightPackedBitsToByteAt1()                   */
7425
/************************************************************************/
7426
7427
static inline void ExpandEightPackedBitsToByteAt1(GByte byVal,
7428
                                                  GByte abyOutput[8])
7429
1.39G
{
7430
1.39G
    abyOutput[0] = (byVal >> 7) & 0x1;
7431
1.39G
    abyOutput[1] = (byVal >> 6) & 0x1;
7432
1.39G
    abyOutput[2] = (byVal >> 5) & 0x1;
7433
1.39G
    abyOutput[3] = (byVal >> 4) & 0x1;
7434
1.39G
    abyOutput[4] = (byVal >> 3) & 0x1;
7435
1.39G
    abyOutput[5] = (byVal >> 2) & 0x1;
7436
1.39G
    abyOutput[6] = (byVal >> 1) & 0x1;
7437
1.39G
    abyOutput[7] = (byVal >> 0) & 0x1;
7438
1.39G
}
7439
7440
/************************************************************************/
7441
/*                  GDALExpandPackedBitsToByteAt0Or1()                  */
7442
/************************************************************************/
7443
7444
/** Expand packed-bits (ordered from most-significant bit to least one)
7445
  into a byte each, where a bit at 0 is expanded to a byte at 0, and a bit
7446
  at 1 to a byte at 1.
7447
7448
 The function does (in a possibly more optimized way) the following:
7449
 \code{.cpp}
7450
 for (size_t i = 0; i < nInputBits; ++i )
7451
 {
7452
     pabyOutput[i] = (pabyInput[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
7453
 }
7454
 \endcode
7455
7456
 @param pabyInput Input array of (nInputBits + 7) / 8 bytes.
7457
 @param pabyOutput Output array of nInputBits bytes.
7458
 @param nInputBits Number of valid bits in pabyInput.
7459
7460
 @since 3.11
7461
*/
7462
7463
void GDALExpandPackedBitsToByteAt0Or1(const GByte *CPL_RESTRICT pabyInput,
7464
                                      GByte *CPL_RESTRICT pabyOutput,
7465
                                      size_t nInputBits)
7466
1.05G
{
7467
1.05G
    const size_t nInputWholeBytes = nInputBits / 8;
7468
1.05G
    size_t iByte = 0;
7469
2.45G
    for (; iByte < nInputWholeBytes; ++iByte)
7470
1.39G
    {
7471
1.39G
        ExpandEightPackedBitsToByteAt1(pabyInput[iByte], pabyOutput);
7472
1.39G
        pabyOutput += 8;
7473
1.39G
    }
7474
2.26G
    for (int iBit = 0; iBit < static_cast<int>(nInputBits % 8); ++iBit)
7475
1.21G
    {
7476
1.21G
        *pabyOutput = (pabyInput[iByte] >> (7 - iBit)) & 0x1;
7477
1.21G
        ++pabyOutput;
7478
1.21G
    }
7479
1.05G
}