Coverage Report

Created: 2024-07-27 06:20

/src/c-blosc2/blosc/b2nd_utils.c
Line
Count
Source (jump to first uncovered line)
1
/*********************************************************************
2
  Blosc - Blocked Shuffling and Compression Library
3
4
  Copyright (c) 2021  Blosc Development Team <blosc@blosc.org>
5
  https://blosc.org
6
  License: BSD 3-Clause (see LICENSE.txt)
7
8
  See LICENSE.txt for details about copyright and rights to use.
9
**********************************************************************/
10
11
#include "b2nd.h"
12
13
#include <stdint.h>
14
#include <string.h>
15
16
// copyNdim where N = {2-8} - specializations of copy loops to be used by b2nd_copy_buffer
17
// since we don't have c++ templates, substitute manual specializations for up to known B2ND_MAX_DIM (8)
18
// it's not pretty, but it substantially reduces overhead vs. the generic method
19
void copy8dim(const uint8_t itemsize,
20
              const int64_t *copy_shape,
21
              const uint8_t *bsrc, const int64_t *src_strides,
22
0
              uint8_t *bdst, const int64_t *dst_strides) {
23
0
  int64_t copy_nbytes = copy_shape[7] * itemsize;
24
0
  int64_t copy_start[7] = {0};
25
0
  do {
26
0
    do {
27
0
      do {
28
0
        do {
29
0
          do {
30
0
            do {
31
0
              do {
32
0
                int64_t src_copy_start = 0;
33
0
                int64_t dst_copy_start = 0;
34
0
                for (int j = 0; j < 7; ++j) {
35
0
                  src_copy_start += copy_start[j] * src_strides[j];
36
0
                  dst_copy_start += copy_start[j] * dst_strides[j];
37
0
                }
38
0
                memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
39
0
                ++copy_start[6];
40
0
              } while (copy_start[6] < copy_shape[6]);
41
0
              ++copy_start[5];
42
0
              copy_start[6] = 0;
43
0
            } while (copy_start[5] < copy_shape[5]);
44
0
            ++copy_start[4];
45
0
            copy_start[5] = 0;
46
0
          } while (copy_start[4] < copy_shape[4]);
47
0
          ++copy_start[3];
48
0
          copy_start[4] = 0;
49
0
        } while (copy_start[3] < copy_shape[3]);
50
0
        ++copy_start[2];
51
0
        copy_start[3] = 0;
52
0
      } while (copy_start[2] < copy_shape[2]);
53
0
      ++copy_start[1];
54
0
      copy_start[2] = 0;
55
0
    } while (copy_start[1] < copy_shape[1]);
56
0
    ++copy_start[0];
57
0
    copy_start[1] = 0;
58
0
  } while (copy_start[0] < copy_shape[0]);
59
0
}
60
61
void copy7dim(const uint8_t itemsize,
62
              const int64_t *copy_shape,
63
              const uint8_t *bsrc, const int64_t *src_strides,
64
0
              uint8_t *bdst, const int64_t *dst_strides) {
65
0
  int64_t copy_nbytes = copy_shape[6] * itemsize;
66
0
  int64_t copy_start[6] = {0};
67
0
  do {
68
0
    do {
69
0
      do {
70
0
        do {
71
0
          do {
72
0
            do {
73
0
              int64_t src_copy_start = 0;
74
0
              int64_t dst_copy_start = 0;
75
0
              for (int j = 0; j < 6; ++j) {
76
0
                src_copy_start += copy_start[j] * src_strides[j];
77
0
                dst_copy_start += copy_start[j] * dst_strides[j];
78
0
              }
79
0
              memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
80
0
              ++copy_start[5];
81
0
            } while (copy_start[5] < copy_shape[5]);
82
0
            ++copy_start[4];
83
0
            copy_start[5] = 0;
84
0
          } while (copy_start[4] < copy_shape[4]);
85
0
          ++copy_start[3];
86
0
          copy_start[4] = 0;
87
0
        } while (copy_start[3] < copy_shape[3]);
88
0
        ++copy_start[2];
89
0
        copy_start[3] = 0;
90
0
      } while (copy_start[2] < copy_shape[2]);
91
0
      ++copy_start[1];
92
0
      copy_start[2] = 0;
93
0
    } while (copy_start[1] < copy_shape[1]);
94
0
    ++copy_start[0];
95
0
    copy_start[1] = 0;
96
0
  } while (copy_start[0] < copy_shape[0]);
97
0
}
98
99
void copy6dim(const uint8_t itemsize,
100
              const int64_t *copy_shape,
101
              const uint8_t *bsrc, const int64_t *src_strides,
102
0
              uint8_t *bdst, const int64_t *dst_strides) {
103
0
  int64_t copy_nbytes = copy_shape[5] * itemsize;
104
0
  int64_t copy_start[5] = {0};
105
0
  do {
106
0
    do {
107
0
      do {
108
0
        do {
109
0
          do {
110
0
            int64_t src_copy_start = 0;
111
0
            int64_t dst_copy_start = 0;
112
0
            for (int j = 0; j < 5; ++j) {
113
0
              src_copy_start += copy_start[j] * src_strides[j];
114
0
              dst_copy_start += copy_start[j] * dst_strides[j];
115
0
            }
116
0
            memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
117
0
            ++copy_start[4];
118
0
          } while (copy_start[4] < copy_shape[4]);
119
0
          ++copy_start[3];
120
0
          copy_start[4] = 0;
121
0
        } while (copy_start[3] < copy_shape[3]);
122
0
        ++copy_start[2];
123
0
        copy_start[3] = 0;
124
0
      } while (copy_start[2] < copy_shape[2]);
125
0
      ++copy_start[1];
126
0
      copy_start[2] = 0;
127
0
    } while (copy_start[1] < copy_shape[1]);
128
0
    ++copy_start[0];
129
0
    copy_start[1] = 0;
130
0
  } while (copy_start[0] < copy_shape[0]);
131
0
}
132
133
void copy5dim(const uint8_t itemsize,
134
              const int64_t *copy_shape,
135
              const uint8_t *bsrc, const int64_t *src_strides,
136
0
              uint8_t *bdst, const int64_t *dst_strides) {
137
0
  int64_t copy_nbytes = copy_shape[4] * itemsize;
138
0
  int64_t copy_start[4] = {0};
139
0
  do {
140
0
    do {
141
0
      do {
142
0
        do {
143
0
          int64_t src_copy_start = 0;
144
0
          int64_t dst_copy_start = 0;
145
0
          for (int j = 0; j < 4; ++j) {
146
0
            src_copy_start += copy_start[j] * src_strides[j];
147
0
            dst_copy_start += copy_start[j] * dst_strides[j];
148
0
          }
149
0
          memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
150
0
          ++copy_start[3];
151
0
        } while (copy_start[3] < copy_shape[3]);
152
0
        ++copy_start[2];
153
0
        copy_start[3] = 0;
154
0
      } while (copy_start[2] < copy_shape[2]);
155
0
      ++copy_start[1];
156
0
      copy_start[2] = 0;
157
0
    } while (copy_start[1] < copy_shape[1]);
158
0
    ++copy_start[0];
159
0
    copy_start[1] = 0;
160
0
  } while (copy_start[0] < copy_shape[0]);
161
0
}
162
163
void copy4dim(const uint8_t itemsize,
164
              const int64_t *copy_shape,
165
              const uint8_t *bsrc, const int64_t *src_strides,
166
0
              uint8_t *bdst, const int64_t *dst_strides) {
167
0
  int64_t copy_nbytes = copy_shape[3] * itemsize;
168
0
  int64_t copy_start[3] = {0};
169
0
  do {
170
0
    do {
171
0
      do {
172
0
        int64_t src_copy_start = 0;
173
0
        int64_t dst_copy_start = 0;
174
0
        for (int j = 0; j < 3; ++j) {
175
0
          src_copy_start += copy_start[j] * src_strides[j];
176
0
          dst_copy_start += copy_start[j] * dst_strides[j];
177
0
        }
178
0
        memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
179
0
        ++copy_start[2];
180
0
      } while (copy_start[2] < copy_shape[2]);
181
0
      ++copy_start[1];
182
0
      copy_start[2] = 0;
183
0
    } while (copy_start[1] < copy_shape[1]);
184
0
    ++copy_start[0];
185
0
    copy_start[1] = 0;
186
0
  } while (copy_start[0] < copy_shape[0]);
187
0
}
188
189
void copy3dim(const uint8_t itemsize,
190
              const int64_t *copy_shape,
191
              const uint8_t *bsrc, const int64_t *src_strides,
192
0
              uint8_t *bdst, const int64_t *dst_strides) {
193
0
  int64_t copy_nbytes = copy_shape[2] * itemsize;
194
0
  int64_t copy_start[2] = {0};
195
0
  do {
196
0
    do {
197
0
      int64_t src_copy_start = 0;
198
0
      int64_t dst_copy_start = 0;
199
0
      for (int j = 0; j < 2; ++j) {
200
0
        src_copy_start += copy_start[j] * src_strides[j];
201
0
        dst_copy_start += copy_start[j] * dst_strides[j];
202
0
      }
203
0
      memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
204
0
      ++copy_start[1];
205
0
    } while (copy_start[1] < copy_shape[1]);
206
0
    ++copy_start[0];
207
0
    copy_start[1] = 0;
208
0
  } while (copy_start[0] < copy_shape[0]);
209
0
}
210
211
void copy2dim(const uint8_t itemsize,
212
              const int64_t *copy_shape,
213
              const uint8_t *bsrc, const int64_t *src_strides,
214
0
              uint8_t *bdst, const int64_t *dst_strides) {
215
0
  int64_t copy_nbytes = copy_shape[1] * itemsize;
216
0
  int64_t copy_start = 0;
217
0
  do {
218
0
    int64_t src_copy_start = copy_start * src_strides[0];
219
0
    int64_t dst_copy_start = copy_start * dst_strides[0];
220
0
    memcpy(&bdst[dst_copy_start * itemsize], &bsrc[src_copy_start * itemsize], copy_nbytes);
221
0
    ++copy_start;
222
0
  } while (copy_start < copy_shape[0]);
223
0
}
224
225
226
void copy_ndim_fallback(const int8_t ndim,
227
                        const uint8_t itemsize,
228
                        int64_t *copy_shape,
229
                        const uint8_t *bsrc, int64_t *src_strides,
230
0
                        uint8_t *bdst, int64_t *dst_strides) {
231
0
  int64_t copy_nbytes = copy_shape[ndim - 1] * itemsize;
232
0
  int64_t number_of_copies = 1;
233
0
  for (int i = 0; i < ndim - 1; ++i) {
234
0
    number_of_copies *= copy_shape[i];
235
0
  }
236
0
  for (int ncopy = 0; ncopy < number_of_copies; ++ncopy) {
237
    // Compute the start of the copy
238
0
    int64_t copy_start[B2ND_MAX_DIM] = {0};
239
0
    blosc2_unidim_to_multidim((int8_t) (ndim - 1), copy_shape, ncopy, copy_start);
240
241
    // Translate this index to the src buffer
242
0
    int64_t src_copy_start;
243
0
    blosc2_multidim_to_unidim(copy_start, (int8_t) (ndim - 1), src_strides, &src_copy_start);
244
245
    // Translate this index to the dst buffer
246
0
    int64_t dst_copy_start;
247
0
    blosc2_multidim_to_unidim(copy_start, (int8_t) (ndim - 1), dst_strides, &dst_copy_start);
248
249
    // Perform the copy
250
0
    memcpy(&bdst[dst_copy_start * itemsize],
251
0
           &bsrc[src_copy_start * itemsize],
252
0
           copy_nbytes);
253
0
  }
254
0
}
255
256
int b2nd_copy_buffer(int8_t ndim,
257
                     uint8_t itemsize,
258
                     const void *src, const int64_t *src_pad_shape,
259
                     const int64_t *src_start, const int64_t *src_stop,
260
                     void *dst, const int64_t *dst_pad_shape,
261
0
                     const int64_t *dst_start) {
262
  // Compute the shape of the copy
263
0
  int64_t copy_shape[B2ND_MAX_DIM] = {0};
264
0
  for (int i = 0; i < ndim; ++i) {
265
0
    copy_shape[i] = src_stop[i] - src_start[i];
266
0
    if (copy_shape[i] == 0) {
267
0
      return BLOSC2_ERROR_SUCCESS;
268
0
    }
269
0
  }
270
271
  // Compute the strides
272
0
  int64_t src_strides[B2ND_MAX_DIM];
273
0
  src_strides[ndim - 1] = 1;
274
0
  for (int i = ndim - 2; i >= 0; --i) {
275
0
    src_strides[i] = src_strides[i + 1] * src_pad_shape[i + 1];
276
0
  }
277
278
0
  int64_t dst_strides[B2ND_MAX_DIM];
279
0
  dst_strides[ndim - 1] = 1;
280
0
  for (int i = ndim - 2; i >= 0; --i) {
281
0
    dst_strides[i] = dst_strides[i + 1] * dst_pad_shape[i + 1];
282
0
  }
283
284
  // Align the buffers removing unnecessary data
285
0
  int64_t src_start_n;
286
0
  blosc2_multidim_to_unidim(src_start, ndim, src_strides, &src_start_n);
287
0
  uint8_t *bsrc = (uint8_t *) src;
288
0
  bsrc = &bsrc[src_start_n * itemsize];
289
290
0
  int64_t dst_start_n;
291
0
  blosc2_multidim_to_unidim(dst_start, ndim, dst_strides, &dst_start_n);
292
0
  uint8_t *bdst = (uint8_t *) dst;
293
0
  bdst = &bdst[dst_start_n * itemsize];
294
295
0
  switch (ndim) {
296
0
    case 1:
297
0
      memcpy(&bdst[0], &bsrc[0], copy_shape[0] * itemsize);
298
0
      break;
299
0
    case 2:
300
0
      copy2dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
301
0
      break;
302
0
    case 3:
303
0
      copy3dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
304
0
      break;
305
0
    case 4:
306
0
      copy4dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
307
0
      break;
308
0
    case 5:
309
0
      copy5dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
310
0
      break;
311
0
    case 6:
312
0
      copy6dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
313
0
      break;
314
0
    case 7:
315
0
      copy7dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
316
0
      break;
317
0
    case 8:
318
0
      copy8dim(itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
319
0
      break;
320
0
    default:
321
      // guard against potential future increase to B2ND_MAX_DIM
322
0
      copy_ndim_fallback(ndim, itemsize, copy_shape, bsrc, src_strides, bdst, dst_strides);
323
0
      break;
324
0
  }
325
326
0
  return BLOSC2_ERROR_SUCCESS;
327
0
}