Yet Another eXchange Tool 0.11.2
Loading...
Searching...
No Matches
xt_stripe.c
Go to the documentation of this file.
1
12/*
13 * Keywords:
14 * Maintainer: Jörg Behrens <behrens@dkrz.de>
15 * Moritz Hanke <hanke@dkrz.de>
16 * Thomas Jahns <jahns@dkrz.de>
17 * URL: https://dkrz-sw.gitlab-pages.dkrz.de/yaxt/
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met:
22 *
23 * Redistributions of source code must retain the above copyright notice,
24 * this list of conditions and the following disclaimer.
25 *
26 * Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 *
30 * Neither the name of the DKRZ GmbH nor the names of its contributors
31 * may be used to endorse or promote products derived from this software
32 * without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46
47#ifdef HAVE_CONFIG_H
48#include <config.h>
49#endif
50
51#include <assert.h>
52#include <stdbool.h>
53#include <stdlib.h>
54#include <string.h>
55
56#include "xt/xt_core.h"
57#include "xt/xt_stripe.h"
58#include "xt_stripe_util.h"
59
60#include "xt_stripe_util.h"
61#include "core/ppm_xfuncs.h"
62#include "instr.h"
63#include "ensure_array_size.h"
64
65void xt_convert_indices_to_stripes(const Xt_int *restrict indices,
66 int num_indices,
67 struct Xt_stripe **stripes,
68 int * num_stripes)
69{
70 *stripes = NULL;
71 *num_stripes = 0;
72 xt_convert_indices_to_stripes_keep_buf(indices, num_indices,
73 stripes, num_stripes);
74}
75
76size_t
77xt_indices_count_stripes(size_t num_indices,
78 const Xt_int indices[num_indices])
79{
80 size_t num_temp_stripes = 0;
81 if (num_indices > 0) {
82 size_t i = 0;
83
84 while(i < (size_t)num_indices) {
85 ++num_temp_stripes;
86
87 size_t j = 1;
88 Xt_int stride = 1, stripe_base_index = indices[i];
89 if (i + j < (size_t)num_indices) {
90 stride = (Xt_int)(indices[i + 1] - stripe_base_index);
91 do {
92 ++j;
93 } while ((i + j) < (size_t)num_indices
94 && stripe_base_index + (Xt_int)j * stride == indices[i + j]);
95 }
96 j-= ((i + j + 1 < (size_t)num_indices)
97 && ((indices[i + j - 1] == indices[i + j] - 1)
98 & (indices[i + j] == indices[i + j + 1] - 1)));
99 i += j;
100 }
101 }
102 return num_temp_stripes;
103}
104
105
107 int num_indices,
108 struct Xt_stripe **stripes,
109 int * num_stripes) {
110
111 INSTR_DEF(instr,"xt_idxstripes_convert_to_stripes")
112 INSTR_START(instr);
113
114 size_t num_indices_ = (size_t)(num_indices > 0 ? num_indices : 0);
115 size_t num_stripes_alloc = xt_indices_count_stripes(num_indices_, indices);
116 struct Xt_stripe *restrict temp_stripes
117 = *stripes = xrealloc(*stripes, num_stripes_alloc * sizeof(**stripes));
118 size_t num_stripes_
119 = xt_convert_indices_to_stripes_buf(num_indices_, indices,
120 num_stripes_alloc, temp_stripes);
121 *num_stripes = (int)num_stripes_;
122 INSTR_STOP(instr);
123}
124
125size_t
127 const Xt_int *restrict indices,
128 size_t num_stripes_alloc,
129 struct Xt_stripe *stripes)
130{
131 (void)num_stripes_alloc;
132 size_t num_stripes = 0;
133 if (num_indices > 0) {
134 size_t i = 0;
135
136 while(i < num_indices) {
137 size_t j = 1;
138
139 Xt_int stride = 1;
140 if (i + j < num_indices) {
141 stride = (Xt_int)(indices[i + 1] - indices[i]);
142 do {
143 ++j;
144 } while ((i + j) < num_indices
145 && indices[i] + (Xt_int)j * stride == indices[i + j]);
146 }
147 j-= ((i + j + 1 < num_indices)
148 && ((indices[i + j - 1] == indices[i + j] - 1)
149 & (indices[i + j] == indices[i + j + 1] - 1)));
150
151 stripes[num_stripes++]
152 = (struct Xt_stripe){ .start = indices[i], .stride = stride,
153 .nstrides = (int)j };
154 i += j;
155 }
156 }
157
158 assert(num_stripes <= num_stripes_alloc);
159 return num_stripes;
160}
161
162size_t
163xt_stripes_merge_copy(size_t num_stripes,
164 struct Xt_stripe *stripes_dst,
165 const struct Xt_stripe *stripes_src,
166 bool lookback)
167{
168 size_t skip = 1;
169 if (num_stripes) {
170 if (lookback) {
171 Xt_int stride = stripes_src[0].stride,
172 prev_stride = stripes_dst[-1].stride,
173 start = stripes_src[0].start,
174 prev_start = stripes_dst[-1].start;
175 if (stride == prev_stride
176 && start == prev_start + stride * (Xt_int)stripes_dst[-1].nstrides) {
177 /* merge perfectly aligned stripes */
178 stripes_dst[-1].nstrides += stripes_src[0].nstrides;
179 ++skip;
180 goto copy_loop;
181 }
182 }
183 stripes_dst[0] = stripes_src[0];
184 copy_loop:
185 if (num_stripes > 1)
186 for (size_t i = 1; i < num_stripes; ++i) {
187 Xt_int stride = stripes_src[i].stride,
188 prev_stride = stripes_dst[i-skip].stride,
189 start = stripes_src[i].start,
190 prev_start = stripes_dst[i-skip].start;
191 if (stride == prev_stride
192 && start == prev_start + stride * (Xt_int)stripes_dst[i-skip].nstrides) {
193 /* merge perfectly aligned stripes */
194 stripes_dst[i-skip].nstrides += stripes_src[i].nstrides;
195 ++skip;
196 } else
197 stripes_dst[i-skip+1] = stripes_src[i];
198 }
199 }
200 return num_stripes - (skip - 1);
201}
202
204xt_summarize_stripes(size_t num_stripes, const struct Xt_stripe stripes[num_stripes])
205{
206 int ntrans_up=0, ntrans_dn=0;
207 long long num_indices = 0;
208 if (num_stripes > 0) {
209 Xt_int prev_end;
210 {
211 int nstrides = stripes[0].nstrides;
212 Xt_int stride = stripes[0].stride;
213 prev_end = (Xt_int)(stripes[0].start
214 + stride * (nstrides-1));
215 ntrans_up += ((nstrides - 1) & ~((stride > 0)-1));
216 ntrans_dn += ((nstrides - 1) & ~((stride < 0)-1));
217 num_indices += nstrides;
218 }
219 for (size_t i = 1; i < num_stripes; ++i) {
220 int nstrides = stripes[i].nstrides;
221 Xt_int start = stripes[i].start, stride = stripes[i].stride;
222 num_indices += nstrides;
223 ntrans_up += (start > prev_end) + ((nstrides - 1) & ~((stride > 0)-1));
224 ntrans_dn += (start < prev_end) + ((nstrides - 1) & ~((stride < 0)-1));
225 prev_end = (Xt_int)(start + stride * (nstrides-1));
226 }
227 }
228 return (struct Xt_stripe_summary){
229 .num_indices = num_indices,
230 .flags = XT_SORT_FLAGS(ntrans_up, ntrans_dn),
231 };
232}
233
234#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
235
236bool
238 const struct Xt_stripe stripes[num_stripes],
239 struct Xt_minmax index_range)
240{
241 bool contains_duplicate = false;
242 if (num_stripes) {
243 Xt_int ofs = index_range.min;
244 enum {
245 block_max = 1 << 24,
246 size_t_bits = sizeof (size_t) * CHAR_BIT,
247 };
248 size_t bm_size = ((size_t)MIN(block_max, index_range.max - ofs + 1)
249 + size_t_bits - 1 ) / size_t_bits;
250 size_t *occupancy_bm = xcalloc(bm_size, sizeof (size_t));
251 size_t dup = 0;
252 do {
253 Xt_int current_range_size
254 = (Xt_int)MIN(block_max, index_range.max - ofs + 1);
255 struct Xt_minmax blk_range = (struct Xt_minmax){
256 ofs, (Xt_int)(ofs + current_range_size - 1)
257 };
258 for (size_t i = 0; i < num_stripes; ++i) {
259 struct Xt_stripe stripe_i = stripes[i];
260 if (stripe_i.stride < 0) {
261 stripe_i.start = (Xt_int)(stripe_i.start
262 + stripe_i.stride * (stripe_i.nstrides-1));
263 stripe_i.stride = XT_INT_ABS(stripe_i.stride);
264 } else if (stripe_i.stride == 0) {
265 if (stripe_i.nstrides > 1) {
266 free(occupancy_bm);
267 return true;
268 }
269 stripe_i.stride = 1;
270 }
271 struct Xt_minmax stripe_range = (struct Xt_minmax){
272 stripe_i.start, (Xt_int)(stripe_i.start
273 + stripe_i.stride * (stripe_i.nstrides-1))
274 };
275 if (stripe_range.max >= blk_range.min
276 && stripe_range.min <= blk_range.max)
277 {
278 Xt_int fstep
279 = (Xt_int)((Xt_doz(ofs, stripe_i.start) + stripe_i.stride - 1)
280 / stripe_i.stride);
281 for (Xt_int index
282 = (Xt_int)(stripe_i.start + fstep * stripe_i.stride);
283 index <= blk_range.max && fstep < stripe_i.nstrides;
284 ++fstep, index = (Xt_int)(index + stripe_i.stride))
285 {
286 size_t mask = (size_t)1 << ((size_t)(index - ofs)%size_t_bits),
287 mask_ofs = (size_t)(index - ofs)/size_t_bits;
288 dup |= mask & occupancy_bm[mask_ofs];
289 occupancy_bm[mask_ofs] |= mask;
290 }
291 }
292 }
293 Xt_uint remaining = (Xt_uint)((Xt_uint)index_range.max - (Xt_uint)ofs);
294 if (dup || remaining >= (Xt_uint)block_max)
295 break;
296 ofs = (Xt_int)(ofs + block_max);
297 memset(occupancy_bm, 0, bm_size * sizeof (size_t));
298 } while (true);
299 free(occupancy_bm);
300 contains_duplicate = dup;
301 }
302 return contains_duplicate;
303}
304
305/*
306 * Local Variables:
307 * c-basic-offset: 2
308 * coding: utf-8
309 * indent-tabs-mode: nil
310 * show-trailing-whitespace: t
311 * require-trailing-newline: t
312 * End:
313 */
#define INSTR_STOP(T)
Definition instr.h:69
#define INSTR_DEF(T, S)
Definition instr.h:66
#define INSTR_START(T)
Definition instr.h:68
add versions of standard API functions not returning on error
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:71
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:68
Xt_int stride
Definition xt_stripe.h:56
int nstrides
Definition xt_stripe.h:57
Xt_int start
Definition xt_stripe.h:55
static Xt_int Xt_doz(Xt_int a, Xt_int b)
base definitions header file
XT_INT Xt_int
Definition xt_core.h:72
unsigned XT_INT Xt_uint
Definition xt_core.h:74
size_t xt_indices_count_stripes(size_t num_indices, const Xt_int indices[num_indices])
Definition xt_stripe.c:77
struct Xt_stripe_summary xt_summarize_stripes(size_t num_stripes, const struct Xt_stripe stripes[num_stripes])
Definition xt_stripe.c:204
size_t xt_stripes_merge_copy(size_t num_stripes, struct Xt_stripe *stripes_dst, const struct Xt_stripe *stripes_src, bool lookback)
Definition xt_stripe.c:163
bool xt_stripes_detect_duplicate(size_t num_stripes, const struct Xt_stripe stripes[num_stripes], struct Xt_minmax index_range)
Definition xt_stripe.c:237
size_t xt_convert_indices_to_stripes_buf(size_t num_indices, const Xt_int *restrict indices, size_t num_stripes_alloc, struct Xt_stripe *stripes)
Definition xt_stripe.c:126
void xt_convert_indices_to_stripes(const Xt_int *restrict indices, int num_indices, struct Xt_stripe **stripes, int *num_stripes)
Definition xt_stripe.c:65
#define MIN(X, Y)
Definition xt_stripe.c:234
void xt_convert_indices_to_stripes_keep_buf(const Xt_int *restrict indices, int num_indices, struct Xt_stripe **stripes, int *num_stripes)
Definition xt_stripe.c:106
#define XT_SORT_FLAGS(ntrans_up, ntrans_dn)