Yet Another eXchange Tool 0.11.2
Loading...
Searching...
No Matches
xt_idxvec.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#ifdef HAVE_CONFIG_H
47#include <config.h>
48#endif
49
50#include <assert.h>
51#include <limits.h>
52#include <stdbool.h>
53#include <stdint.h>
54#include <stdlib.h>
55#include <stdio.h>
56#include <string.h>
57
58#include "xt/xt_core.h"
59#include "xt/xt_idxlist.h"
60#include "xt_idxlist_internal.h"
61#include "xt/xt_idxempty.h"
62#include "xt/xt_idxvec.h"
63#include "xt_idxvec_internal.h"
64#include "xt/xt_idxstripes.h"
66#include "xt/xt_mpi.h"
67#include "xt_idxlist_unpack.h"
68#include "core/ppm_xfuncs.h"
69#include "core/core.h"
70#include "xt_stripe_util.h"
71#include "xt/xt_sort.h"
72#include "xt_config_internal.h"
73#include "instr.h"
74
75#define MAX(a,b) (((a)>=(b))?(a):(b))
76#define MIN(a,b) (((a)<(b))?(a):(b))
77
78static void
80
81static size_t
83
84static void
85idxvec_pack(Xt_idxlist data, void *buffer, int buffer_size,
86 int *position, MPI_Comm comm);
87
88static Xt_idxlist
89idxvec_copy(Xt_idxlist idxlist);
90
91static Xt_idxlist
93
94static void
95idxvec_get_indices(Xt_idxlist idxlist, Xt_int *indices);
96
97static Xt_int const*
99
100static int
102
103static void
104idxvec_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe *stripes,
105 size_t num_stripes_alloc);
106
107static int
108idxvec_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int * index);
109
110static int
111idxvec_get_indices_at_positions(Xt_idxlist idxlist, const int *positions,
112 int num, Xt_int *index, Xt_int undef_idx);
113
114static int
115idxvec_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int * position);
116
117static int
119 int * position, int offset);
120
121static size_t
123 size_t num_indices, int *positions,
124 int single_match_only);
125
126static Xt_int
128
129static Xt_int
131
132static int
134
135static const struct xt_idxlist_vtable idxvec_vtable = {
136 .delete = idxvec_delete,
137 .get_pack_size = idxvec_get_pack_size,
138 .pack = idxvec_pack,
139 .copy = idxvec_copy,
140 .sorted_copy = idxvec_sorted_copy,
141 .get_indices = idxvec_get_indices,
142 .get_indices_const = idxvec_get_indices_const,
143 .get_num_index_stripes = idxvec_get_num_index_stripes,
144 .get_index_stripes = idxvec_get_index_stripes,
145 .get_index_at_position = idxvec_get_index_at_position,
146 .get_indices_at_positions = idxvec_get_indices_at_positions,
147 .get_position_of_index = idxvec_get_position_of_index,
148 .get_positions_of_indices = idxvec_get_positions_of_indices,
149 .get_position_of_index_off = idxvec_get_position_of_index_off,
150 .get_positions_of_indices_off = NULL,
151 .get_min_index = idxvec_get_min_index,
152 .get_max_index = idxvec_get_max_index,
153 .get_sorting = idxvec_get_sorting,
154 .get_bounding_box = NULL,
155 .idxlist_pack_code = VECTOR,
156};
157
158static const char filename[] = "xt_idxvec.c";
159
160
161typedef struct Xt_idxvec_ *Xt_idxvec;
162
163// index vector data structure
165
166 struct Xt_idxlist_ parent;
167 unsigned flags;
170
171 // internal array used to optimise access to vector data
172 const Xt_int *sorted_vector; // sorted version of vector
173 int *sorted_vec_positions; // original positions of the
174 // indices in sorted_vector
175 /*
176 we have the following relations:
177 sorted_vector[i-1] <= sorted_vector[i],
178 vector[sorted_vec_positions[i]] = sorted_vector[i]
179 iff sorted_vector != vector
180 */
181};
182
183static struct Xt_vec_alloc
184idxvec_alloc_no_init(int num_indices)
185{
186 size_t vector_size = (size_t)num_indices * sizeof (Xt_int),
187 header_size = ((sizeof (struct Xt_idxvec_) + sizeof (Xt_int) - 1)
188 /sizeof (Xt_int)) * sizeof (Xt_int);
189 struct Xt_idxvec_ *idxvec_obj = xmalloc(header_size + vector_size);
190 Xt_int *vector_assign
191 = (Xt_int *)(void *)((unsigned char *)idxvec_obj + header_size);
192 idxvec_obj->vector = vector_assign;
193 return (struct Xt_vec_alloc) { idxvec_obj, vector_assign };
194}
195
196static struct Xt_vec_alloc
197idxvec_alloc(int num_indices);
198
199struct Xt_vec_alloc
200xt_idxvec_alloc(int num_indices)
201{
202 return idxvec_alloc(num_indices);
203}
204
205static struct Xt_vec_alloc
206idxvec_alloc(int num_indices)
207{
208 struct Xt_vec_alloc vec_alloc = idxvec_alloc_no_init(num_indices);
209 Xt_idxlist_init(&vec_alloc.idxvec->parent, &idxvec_vtable, num_indices);
210 return vec_alloc;
211}
212
213Xt_idxlist xt_idxvec_new(const Xt_int *idxvec, int num_indices) {
214 INSTR_DEF(t_idxvec_new,"xt_idxvec_new")
215 // ensure that yaxt is initialized
216 assert(xt_initialized());
217
218 if (num_indices > 0)
219 ;
220 else if (num_indices == 0)
221 return xt_idxempty_new();
222 else
223 die("number of indices passed to xt_idxvec_new must not be negative!");
224
225 INSTR_START(t_idxvec_new);
226 struct Xt_vec_alloc vec_alloc = idxvec_alloc(num_indices);
227 Xt_int *restrict vector = vec_alloc.vector;
228 vector[0] = idxvec[0];
229 int ntrans_up=0, ntrans_dn=0;
230 Xt_int maxv = idxvec[0], minv = idxvec[0];
231 for (size_t i = 1; i < (size_t)num_indices; ++i) {
232 Xt_int v = idxvec[i];
233 vector[i] = v;
234 ntrans_up += idxvec[i-1] < v;
235 ntrans_dn += idxvec[i-1] > v;
236 maxv = MAX(v, maxv);
237 minv = MIN(v, minv);
238 }
239 vec_alloc.idxvec->max = maxv;
240 vec_alloc.idxvec->min = minv;
241 if (ntrans_dn == 0)
242 vec_alloc.idxvec->sorted_vector = vector;
243 else
244 vec_alloc.idxvec->sorted_vector = NULL;
245 vec_alloc.idxvec->sorted_vec_positions = NULL;
246 vec_alloc.idxvec->flags = XT_SORT_FLAGS(ntrans_up, ntrans_dn);
247 INSTR_STOP(t_idxvec_new);
248 return (void *)vec_alloc.idxvec;
249}
250
252{
253 unsigned flags;
255};
256
257static struct flags_min_max
258get_sort_flags(size_t num_indices, const Xt_int vector[num_indices])
259{
260 int ntrans_up=0, ntrans_dn=0;
261 Xt_int maxv = vector[0], minv = vector[0];
262 for (size_t i = 1; i < num_indices; ++i) {
263 Xt_int v = vector[i];
264 ntrans_up += vector[i-1] < v;
265 ntrans_dn += vector[i-1] > v;
266 maxv = MAX(v, maxv);
267 minv = MIN(v, minv);
268 }
269 unsigned flags = XT_SORT_FLAGS(ntrans_up, ntrans_dn);
270 /* icc 12 and 13 miscompile the above when it's a leaf function */
271#if defined __ICC && defined __OPTIMIZE__ \
272 && ( __INTEL_COMPILER_BUILD_DATE == 20110811 \
273 || __INTEL_COMPILER == 1300 )
274 if (num_indices == -1)
275 fprintf(stderr, "%s: ntrans_up=%d, ntrans_dn=%d, flags=%u\n",
276 filename, ntrans_up, ntrans_dn, flags);
277#else
278 (void)filename;
279#endif
280 return (struct flags_min_max){ .flags = flags, .min = minv, .max = maxv };
281}
282
285{
286 assert(vec_alloc.idxvec->vector == vec_alloc.vector);
287 Xt_idxlist idxlist;
288 Xt_idxvec idxvec = vec_alloc.idxvec;
289 size_t num_indices = (size_t)idxvec->parent.num_indices;
290 if (num_indices) {
291 struct flags_min_max fmm = get_sort_flags(num_indices, vec_alloc.vector);
292 unsigned flags = fmm.flags;
293 idxvec->min = fmm.min;
294 idxvec->max = fmm.max;
295 idxvec->flags = flags;
296 idxvec->sorted_vector = ((flags & sort_mask) == sort_asc
297 || (flags & sort_mask) == sort_idt)
298 ? vec_alloc.vector : NULL;
299 idxvec->sorted_vec_positions = NULL;
300 idxlist = &vec_alloc.idxvec->parent;
301 } else {
302 free(idxvec);
303 idxlist = xt_idxempty_new();
304 }
305 return idxlist;
306}
307
308Xt_idxlist xt_idxvec_prealloc_new(const Xt_int *idxvec, int num_indices)
309{
310 if (num_indices > 0)
311 ;
312 else if (num_indices == 0)
313 return xt_idxempty_new();
314 else
315 die("number of indices passed to xt_idxvec_new must not be negative!");
316 struct Xt_idxvec_ *restrict idxvec_obj = xmalloc(sizeof (*idxvec_obj));
317 Xt_idxlist_init(&idxvec_obj->parent, &idxvec_vtable, num_indices);
318 idxvec_obj->vector = idxvec;
319 return xt_idxvec_congeal((struct Xt_vec_alloc){
320 .idxvec = idxvec_obj, .vector = (void *)(intptr_t)idxvec });
321}
322
323static size_t
325 int * sorted_vec_pos, int pos_offset) {
326
327 Xt_int stride = stripe.stride, start;
328 int sign;
329 if (stride >= 0) {
330 sign = 1;
331 start = stripe.start;
332 } else {
333 sign = -1;
334 start = (Xt_int)(stripe.start + (Xt_int)(stripe.nstrides-1) * stride);
335 stride = (Xt_int)-stride;
336 pos_offset += stripe.nstrides-1;
337 }
338 for (int i = 0; i < stripe.nstrides; ++i) {
339 sorted_vector[i] = (Xt_int)(start + i * stride);
340 sorted_vec_pos[i] = pos_offset + i * sign;
341 }
342
343 return (size_t)stripe.nstrides;
344}
345
346static void
348 int num_stripes_,
349 Xt_idxvec idxvec,
350 Xt_config config)
351{
352 assert(num_stripes_ > 0);
353 size_t num_stripes = (size_t)num_stripes_,
354 num_indices = (size_t)xt_idxlist_get_num_indices(&idxvec->parent);
355 Xt_int *restrict sorted_vector_assign
356 = xmalloc(num_indices * sizeof(*(idxvec->sorted_vector)));
357 idxvec->sorted_vector = sorted_vector_assign;
359 = idxvec->sorted_vec_positions
360 = xmalloc(num_indices * sizeof(*sorted_vec_positions));
361
362 /* stripe_minmax[0][i] is the minimal index in stripe i at first,
363 * later of sorted stripe i, stripe_minmax[1][i] is the
364 * corresponding maximal index */
365 Xt_int (*restrict stripe_minmax)[num_stripes]
366 = xmalloc(2 * sizeof(*stripe_minmax));
367 int *restrict sorted_stripe_min_pos
368 = xmalloc(num_stripes * 3 * sizeof(*sorted_stripe_min_pos));
369
371 for(size_t i = 0; i < num_stripes; ++i) {
372 Xt_int ofs = (Xt_int)(stripes[i].stride * (stripes[i].nstrides - 1)),
373 mask = Xt_isign_mask(ofs);
374 Xt_int stripe_min = (Xt_int)(stripes[i].start + (ofs & mask));
375 stripe_minmax[0][i] = stripe_min;
376 min = MIN(min, stripe_min);
377 }
378 idxvec->min = min;
379
380 xt_assign_id_map_int(num_stripes, sorted_stripe_min_pos, 0);
381 config->sort_funcs->sort_xt_int_permutation(stripe_minmax[0], num_stripes,
382 sorted_stripe_min_pos);
383
384 int *restrict sorted_pos_prefix_sum = sorted_stripe_min_pos + num_stripes,
385 *restrict orig_pos_prefix_sum
386 = xmalloc(num_stripes * sizeof(*orig_pos_prefix_sum));
387
388 int accum = 0;
389 for (size_t i = 0; i < num_stripes; ++i) {
390 orig_pos_prefix_sum[i] = accum;
391 accum += stripes[i].nstrides;
392 }
393
395 for (size_t i = 0; i < num_stripes; ++i) {
396 int sorted_pos = sorted_stripe_min_pos[i];
397 sorted_pos_prefix_sum[i] = orig_pos_prefix_sum[sorted_pos];
398 Xt_int ofs = (Xt_int)(stripes[sorted_pos].stride
399 * (stripes[sorted_pos].nstrides - 1)),
400 mask = Xt_isign_mask(ofs);
401 Xt_int stripe_max = (Xt_int)(stripes[sorted_pos].start + (ofs & ~mask));
402 stripe_minmax[1][i] = stripe_max;
403 max = MAX(max, stripe_max);
404 }
405 idxvec->max = max;
406
407 free(orig_pos_prefix_sum);
408
409 /* i'th stripe overlaps with overlap_count[i] following stripes, or
410 * is part of a stretch of this many overlapping stripes, if
411 * overlap_count[i] is > 0, in case overlap_count[i] <= 0, this many
412 * non-overlapping stripes follow after negation + 1 */
413 int *restrict overlap_count
414 = sorted_stripe_min_pos + 2 * num_stripes;
415 for (size_t i = 0; i < num_stripes - 1; ++i) {
416 bool do_overlap = stripe_minmax[1][i] >= stripe_minmax[0][i + 1];
417 size_t j = i + 1;
418 if (do_overlap) {
419 /* range_max_idx is the maximal index encountered in a rage of
420 * overlapping stripes, only stop when a stripe starting at
421 * index larger than this is encountered */
422 Xt_int range_max_idx = MAX(stripe_minmax[1][i], stripe_minmax[1][i+1]);
423 while (j + 1 < num_stripes
424 && stripe_minmax[0][j + 1] <= range_max_idx) {
425 range_max_idx = MAX(range_max_idx, stripe_minmax[1][j+1]);
426 ++j;
427 }
428 overlap_count[i] = (int)(j - i);
429 i = j;
430 } else {
431 while (j + 1 < num_stripes
432 && stripe_minmax[0][j + 1] > stripe_minmax[1][j])
433 ++j;
434 overlap_count[i] = -(int)(j - i - 1);
435 i = j - 1;
436 }
437 }
438 overlap_count[num_stripes - 1] = 0;
439
440 size_t offset = 0;
441
442 size_t i = 0;
443 void (*sort_xt_int_permutation)(Xt_int a[], size_t n, int permutation[])
445 while (i < num_stripes) {
446
447 bool do_overlap = overlap_count[i] > 0;
448 size_t num_selection = (size_t)(abs(overlap_count[i])) + 1;
449 size_t sel_size = 0;
450
451 for (size_t j = 0; j < num_selection; ++j)
452 sel_size += decode_stripe(stripes[sorted_stripe_min_pos[i+j]],
453 sorted_vector_assign + offset + sel_size,
454 sorted_vec_positions + offset + sel_size,
455 sorted_pos_prefix_sum[i+j]);
456
457 if (do_overlap)
458 sort_xt_int_permutation(sorted_vector_assign + offset,
459 sel_size, sorted_vec_positions + offset);
460
461 offset += sel_size;
462 i += num_selection;
463 }
464
465 free(sorted_stripe_min_pos);
466 free(stripe_minmax);
467}
468
471 int num_stripes) {
472 // ensure that yaxt is initialized
473 assert(xt_initialized());
474 size_t num_stripes_ = (size_t)(num_stripes > 0 ? num_stripes : 0);
475 struct Xt_stripe_summary summa = xt_summarize_stripes(num_stripes_, stripes);
476 long long num_indices = summa.num_indices;
477 assert((sizeof (long long) > sizeof (int)) & (num_indices <= INT_MAX)
478 & (num_indices >= 0));
479
480 Xt_idxlist idxlist;
481 if (num_indices > 0) {
482 struct Xt_vec_alloc vec_alloc = idxvec_alloc((int)num_indices);
483 Xt_int *restrict indices = vec_alloc.vector;
484 size_t k = (size_t)-1;
485 for (int i = 0; i < num_stripes; ++i)
486 for (int j = 0; j < stripes[i].nstrides; ++j)
487 indices[++k] = (Xt_int)(stripes[i].start + j * stripes[i].stride);
488 vec_alloc.idxvec->flags = summa.flags;
489 generate_sorted_vector_from_stripes(stripes, num_stripes, vec_alloc.idxvec,
491 idxlist = (Xt_idxlist)vec_alloc.idxvec;
492 } else
493 idxlist = xt_idxempty_new();
494 return idxlist;
495}
496
497static void idxvec_delete(Xt_idxlist obj) {
498
499 Xt_idxvec vec_obj = (Xt_idxvec)obj;
500 if (vec_obj->sorted_vector != vec_obj->vector)
501 free((void *)(intptr_t)vec_obj->sorted_vector);
502 free(vec_obj->sorted_vec_positions);
503 free(obj);
504}
505
506enum {
509};
510
511static size_t idxvec_get_pack_size(Xt_idxlist obj, MPI_Comm comm) {
512
513 int size_xt_idx, size_header;
514
515 xt_mpi_call(MPI_Pack_size(pack_header_size, MPI_INT, comm, &size_header), comm);
516 xt_mpi_call(MPI_Pack_size(obj->num_indices, Xt_int_dt, comm,
517 &size_xt_idx), comm);
518
519 return (size_t)size_xt_idx + (size_t)size_header;
520}
521
522void idxvec_pack(Xt_idxlist obj, void *buffer, int buffer_size,
523 int *position, MPI_Comm comm) {
524
525 assert(obj && xt_idxlist_get_num_indices(obj) > 0);
527 int header[pack_header_size] = { VECTOR, xt_idxlist_get_num_indices(obj) };
528 xt_mpi_call(MPI_Pack(header, pack_header_size, MPI_INT, buffer,
529 buffer_size, position, comm), comm);
530 xt_mpi_call(MPI_Pack(CAST_MPI_SEND_BUF(idxvec->vector),
532 Xt_int_dt, buffer,
533 buffer_size, position, comm), comm);
534}
535
536Xt_idxlist xt_idxvec_unpack(void *buffer, int buffer_size, int *position,
537 MPI_Comm comm) {
538
539 int num_indices;
540 xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
541 &num_indices, 1, MPI_INT, comm), comm);
542 assert(num_indices > 0);
543 Xt_idxlist idxvec = NULL;
544 struct Xt_vec_alloc vec_alloc = idxvec_alloc(num_indices);
545 xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
546 vec_alloc.vector, num_indices,
547 Xt_int_dt, comm), comm);
548 struct flags_min_max fmm
549 = get_sort_flags((size_t)num_indices, vec_alloc.vector);
550 unsigned flags = fmm.flags;
551 vec_alloc.idxvec->sorted_vector
552 = ((flags & sort_mask) == sort_asc || (flags & sort_mask) == sort_idt)
553 ? vec_alloc.vector : NULL;
554 vec_alloc.idxvec->sorted_vec_positions = NULL;
555 vec_alloc.idxvec->flags = flags;
556 vec_alloc.idxvec->max = fmm.max;
557 vec_alloc.idxvec->min = fmm.min;
558 idxvec = (Xt_idxlist)vec_alloc.idxvec;
559 return idxvec;
560}
561
562static const Xt_int *
564
567{
568 return get_sorted_vector((Xt_idxvec)idxvec, config);
569}
570
571static const Xt_int *
573{
574 if (idxvec->sorted_vector)
575 return idxvec->sorted_vector;
576
577 size_t num_indices
578 = (size_t)xt_idxlist_get_num_indices(&idxvec->parent);
579
580 const Xt_int *restrict vector = idxvec->vector;
581 if ((idxvec->flags & sort_mask) == sort_asc
582 || (idxvec->flags & sort_mask) == sort_idt) {
583 /* we are done if vector is already sorted */
584 idxvec->sorted_vec_positions = NULL;
585 return idxvec->sorted_vector = vector;
586 }
587 if (XT_CONFIG_GET_FORCE_NOSORT(config))
588 return NULL;
589
590 size_t svec_size = num_indices * sizeof(Xt_int);
591 Xt_int *sorted_vector = xmalloc(svec_size);
592 idxvec->sorted_vec_positions = xmalloc(num_indices *
593 sizeof(*(idxvec->sorted_vec_positions)));
594
595 memcpy(sorted_vector, vector, svec_size);
596/* todo: accelerate for case when vector is sorted but descending */
597 xt_assign_id_map_int(num_indices, idxvec->sorted_vec_positions, 0);
599 sorted_vector, num_indices, idxvec->sorted_vec_positions);
600
601 return idxvec->sorted_vector = sorted_vector;
602}
603
606 Xt_config config)
607{
608
609 // both lists are index vectors:
610
611 Xt_idxvec idxvec_src = (Xt_idxvec)idxlist_src,
612 idxvec_dst = (Xt_idxvec)idxlist_dst;
613
614
615 size_t num_indices_inter = 0,
616 num_indices_src = (size_t)xt_idxlist_get_num_indices(idxlist_src),
617 num_indices_dst = (size_t)xt_idxlist_get_num_indices(idxlist_dst);
618
619 struct Xt_vec_alloc vec_alloc = idxvec_alloc_no_init((int)num_indices_dst);
620 Xt_idxvec inter_vector = vec_alloc.idxvec;
621 Xt_int *vector_assign = vec_alloc.vector;
622
623 struct Xt_config_ sort_config = *config;
624 XT_CONFIG_UNSET_FORCE_NOSORT(&sort_config);
625 // get sorted indices of source and destination
626 const Xt_int *restrict sorted_src_vector
627 = get_sorted_vector(idxvec_src, &sort_config),
628 *restrict sorted_dst_vector
629 = get_sorted_vector(idxvec_dst, &sort_config);
630
631 // compute the intersection
632 for (size_t i = 0, j = 0; i < num_indices_dst; ++i) {
633
634 while (j < num_indices_src
635 && sorted_src_vector[j] < sorted_dst_vector[i]) ++j;
636 if (j < num_indices_src) {
637 vector_assign[num_indices_inter] = sorted_dst_vector[i];
638 num_indices_inter += sorted_src_vector[j] == sorted_dst_vector[i];
639 } else
640 break;
641 }
642
643 if (num_indices_inter) {
644 size_t vector_size = num_indices_inter * sizeof (idxvec_dst->vector[0]),
645 header_size = ((sizeof (struct Xt_idxvec_) + sizeof (Xt_int) - 1)
646 /sizeof (Xt_int)) * sizeof (Xt_int);
647 inter_vector = xrealloc(inter_vector, header_size + vector_size);
648 inter_vector->vector
649 = (Xt_int *)(void *)((unsigned char *)inter_vector + header_size);
650 Xt_idxlist_init(&inter_vector->parent, &idxvec_vtable, (int)num_indices_inter);
651 inter_vector->sorted_vector = inter_vector->vector;
652 inter_vector->sorted_vec_positions = NULL;
653 inter_vector->flags = sort_asc;
654 inter_vector->min = inter_vector->vector[0];
655 inter_vector->max = inter_vector->vector[num_indices_inter-1];
656 } else {
657 free(inter_vector);
658 inter_vector = (Xt_idxvec)xt_idxempty_new();
659 }
660 return (Xt_idxlist)inter_vector;
661}
662
665{
666 assert(idxlist->vtable == &idxvec_vtable);
667 Xt_idxvec idxvec = (Xt_idxvec)idxlist;
668 size_t num_stripes = xt_indices_count_stripes(
669 (size_t)idxvec->parent.num_indices,
670 idxvec->vector);
671 struct Xt_stripes_alloc stripes_alloc
672 = xt_idxstripes_alloc(num_stripes);
674 (size_t)idxvec->parent.num_indices,
675 idxvec->vector,
676 num_stripes,
677 stripes_alloc.stripes);
678 return xt_idxstripes_congeal(stripes_alloc);
679}
680
681
684 Xt_idxlist idxlist_dst,
685 Xt_config config)
686{
687 /* destination is index stripes, source index vector */
688 assert(idxlist_dst->vtable->idxlist_pack_code == STRIPES
689 && idxlist_src->vtable == &idxvec_vtable);
690 Xt_idxvec vec_src = (Xt_idxvec)idxlist_src;
691 if (XT_CONFIG_GET_FORCE_NOSORT(config)) {
692 Xt_idxlist idxstripes_src = xt_idxvec_get_idxstripes(idxlist_src);
693 Xt_idxlist intersection
694 = xt_idxstripes_get_intersection(idxstripes_src, idxlist_dst, config);
695 xt_idxlist_delete(idxstripes_src);
696 return intersection;
697 }
698 const struct Xt_stripe *stripes_dst
700 const Xt_int *src_sorted = get_sorted_vector(vec_src, config);
701 Xt_int src_min = idxvec_get_min_index(idxlist_src),
702 src_max = idxvec_get_max_index(idxlist_src);
703 size_t nsrc = (size_t)idxlist_src->num_indices,
704 ndst = (size_t)idxlist_dst->num_indices;
709 struct Xt_vec_alloc vec_alloc = idxvec_alloc_no_init((int)ndst);
710 Xt_int *found_indices = vec_alloc.vector;
711 size_t ndst_stripes = xt_idxstripes_get_num_index_stripes(idxlist_dst),
712 num_indices_inter = 0, last_match_pos = 0;
713 for (size_t i = 0; i < ndst_stripes; ++i) {
714 size_t nstrides = (size_t)stripes_dst[i].nstrides;
715 Xt_int start = stripes_dst[i].start,
716 stride = stripes_dst[i].stride,
717 end = (Xt_int)(start + (int)(nstrides-1) * stride);
718 if (stride < 0) {
719 Xt_int temp = start;
720 start = end;
721 end = temp;
722 stride = (Xt_int)-stride;
723 }
724 if (start > src_max || end < src_min)
725 continue;
726 size_t adj_first = start >= src_min
727 ? (size_t)0 : (size_t)((src_min - start)/stride);
728 if (end > src_max) {
729 size_t adj_nstrides = (size_t)((end - src_max)/stride);
730 nstrides -= adj_nstrides;
731 }
732 for (size_t k = adj_first; k < nstrides; ++k) {
733 Xt_int dst_idx = (Xt_int)(start + stride * (Xt_int)k);
734 size_t lb = 0, ub = nsrc,
735 guess = last_match_pos;
736 do {
737 Xt_int src_val = src_sorted[guess];
738 if (src_val < dst_idx)
739 lb = guess+1;
740 else if (src_val > dst_idx)
741 ub = guess;
742 else { /* src_val == dst_idx */
743 found_indices[num_indices_inter++] = dst_idx;
744 last_match_pos = guess;
745 break;
746 }
747 guess = lb + (ub-lb)/2;
748 } while (lb < ub);
749 }
750 }
751 if (num_indices_inter) {
752 if (num_indices_inter != ndst) {
753 size_t vector_size = num_indices_inter * sizeof (found_indices[0]),
754 header_size = ((sizeof (struct Xt_idxvec_) + sizeof (Xt_int) - 1)
755 /sizeof (Xt_int)) * sizeof (Xt_int);
756 vec_alloc.idxvec = xrealloc(vec_alloc.idxvec, header_size + vector_size);
757 vec_alloc.idxvec->vector = vec_alloc.vector
758 = (Xt_int *)(void *)((unsigned char *)vec_alloc.idxvec + header_size);
759 }
760 } else {
761 free(vec_alloc.idxvec);
762 return xt_idxempty_new();
763 }
764 config->sort_funcs->sort_xt_int(vec_alloc.vector, num_indices_inter);
765 Xt_idxlist_init(&vec_alloc.idxvec->parent, &idxvec_vtable, (int)num_indices_inter);
766 vec_alloc.idxvec->sorted_vector = vec_alloc.idxvec->vector;
767 vec_alloc.idxvec->sorted_vec_positions = NULL;
768 vec_alloc.idxvec->flags = sort_asc;
769 return (Xt_idxlist)vec_alloc.idxvec;
770}
771
772
773static Xt_idxlist
775
776 return xt_idxvec_new(((Xt_idxvec)idxlist)->vector,
778}
779
780static Xt_idxlist
782
783 Xt_idxvec idxvec = (Xt_idxvec)idxlist;
784 struct Xt_config_ sort_config = *config;
785 XT_CONFIG_UNSET_FORCE_NOSORT(&sort_config);
786 const Xt_int *sorted_vector = get_sorted_vector(idxvec, &sort_config);
787 size_t num_indices = (size_t)xt_idxlist_get_num_indices(idxlist);
788 if ((int)num_indices > config->idxv_cnv_size) {
789 size_t num_stripes_alloc
790 = xt_indices_count_stripes(num_indices, sorted_vector);
791 struct Xt_stripes_alloc stripes_alloc
792 = xt_idxstripes_alloc(num_stripes_alloc);
793#ifndef NDEBUG
794 size_t num_stripes =
795#endif
797 num_indices, sorted_vector, num_stripes_alloc, stripes_alloc.stripes);
798 assert(num_stripes == num_stripes_alloc);
799 return xt_idxstripes_congeal(stripes_alloc);
800 } else {
801 /* fixme: use congeal */
802 return xt_idxvec_new(sorted_vector, (int)num_indices);
803 }
804}
805
806static void
808
809 memcpy(indices, ((Xt_idxvec)idxlist)->vector,
810 (size_t)xt_idxlist_get_num_indices(idxlist) * sizeof(*indices));
811}
812
813static Xt_int const*
815 Xt_idxvec idxvec = (Xt_idxvec)idxlist;
816
817 return idxvec->vector;
818}
819
820
821static int
823{
824 size_t num_stripes = xt_indices_count_stripes(
825 (size_t)xt_idxlist_get_num_indices(idxlist),
826 ((Xt_idxvec)idxlist)->vector);
827 assert(num_stripes <= INT_MAX);
828 return (int)num_stripes;
829}
830
831static void
833 size_t num_stripes_alloc) {
834
836 (size_t)xt_idxlist_get_num_indices(idxlist),
837 ((Xt_idxvec)idxlist)->vector, num_stripes_alloc, stripes);
838}
839
840static int
841idxvec_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int * index) {
842
843 if (position < 0 || position >= xt_idxlist_get_num_indices(idxlist))
844 return 1;
845
846 *index = ((Xt_idxvec)idxlist)->vector[position];
847
848 return 0;
849}
850
851static int
853 const int *restrict positions,
854 int num_pos_, Xt_int *index,
855 Xt_int undef_idx) {
856
857 Xt_idxvec idxvec = (Xt_idxvec)idxlist;
858 size_t num_indices = (size_t)idxvec->parent.num_indices;
859 const Xt_int *restrict v = idxvec->vector;
860
861 int undef_count = 0;
862 size_t num_pos = num_pos_ >= 0 ? (size_t)num_pos_ : (size_t)0;
863 for (size_t ip = 0; ip < num_pos; ip++) {
864 int p = positions[ip];
865 if (p >= 0 && (size_t)p < num_indices) {
866 index[ip] = v[p];
867 } else {
868 index[ip] = undef_idx;
869 undef_count++;
870 }
871 }
872
873 return undef_count;
874}
875
879static int
881 int * position, int offset) {
882
883 Xt_idxvec idxvec_obj = (Xt_idxvec)idxlist;
884
885 *position = -1;
886
887 size_t num_indices = (size_t)idxvec_obj->parent.num_indices;
888 if ((offset < 0) || ((size_t)offset >= num_indices))
889 return 1;
890
891 struct Xt_config_ sort_config = xt_default_config;
892 XT_CONFIG_UNSET_FORCE_NOSORT(&sort_config);
893
894 const Xt_int *sorted_vector
895 = get_sorted_vector(idxvec_obj, &sort_config);
896
897 if ((index < sorted_vector[0]) ||
898 (index > sorted_vector[num_indices-1]))
899 return 1;
900
901 // bisection to find one matching position:
902 size_t lb = 0;
903 size_t ub = num_indices - 1;
904
905 while (sorted_vector[lb] < index) {
906
907 size_t middle = (ub + lb + 1)/2;
908
909 if (sorted_vector[middle] <= index)
910 lb = middle;
911 else if (ub == middle)
912 return 1;
913 else
914 ub = middle;
915 }
916
917 // find left most match:
918 while (lb > 0 && sorted_vector[lb-1] == index) --lb;
919
920 // go forward until offset condition is satisfied:
921 const int *sorted_vec_positions = idxvec_obj->sorted_vec_positions;
922 if (sorted_vec_positions) {
923 while (lb < num_indices - 1 // boundary condition
924 && sorted_vec_positions[lb] < offset // ignore postions left of offset
925 && sorted_vector[lb] == index) ++lb; // check if index is valid
926 } else {
927 while (lb < num_indices - 1 // boundary condition
928 && (int)lb < offset // ignore postions left of offset
929 && sorted_vector[lb] == index) ++lb; // check if index is valid
930 }
931 // check if position is invalid:
932 if (lb >= num_indices || sorted_vector[lb] != index)
933 return 1; // failure
934
935 // result:
936 *position = sorted_vec_positions ? sorted_vec_positions[lb] : (int)lb;
937 return 0;
938}
939
940static int
941idxvec_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int * position) {
942
943 return idxvec_get_position_of_index_off(idxlist, index, position, 0);
944}
945
946static bool idx_vec_is_sorted(Xt_int const *idx, size_t n) {
947
948 if (n>=2)
949 for (size_t i = 1; i < n; i++)
950 if (idx[i] < idx[i-1]) return false;
951
952 return true;
953}
954
955static size_t
957 const Xt_int *selection_idx,
958 size_t num_selection, int *positions,
959 int single_match_only) {
960
961 bool selection_is_ordered = idx_vec_is_sorted(selection_idx, num_selection);
963
964 Xt_int const *sorted_selection;
965 int *sorted_selection_pos = NULL;
966 Xt_int *tmp_idx = NULL;
967
968 if (selection_is_ordered) {
969 sorted_selection = selection_idx;
970 } else {
971 size_t idx_memsize = num_selection * sizeof(*sorted_selection),
972 pos_memsize = num_selection * sizeof(*sorted_selection_pos),
973#if defined _CRAYC && _RELEASE_MAJOR < 9
974 pos_ofs_roundup = _MAXVL_8,
975#else
976 pos_ofs_roundup = sizeof(int),
977#endif
978 /* round pos_memsize up to next multiple of sizeof (int) */
979 pos_ofs = ((idx_memsize + pos_ofs_roundup - 1)
980 & ((size_t)-(ssize_t)(pos_ofs_roundup))),
981 /* compute size of merged allocation */
982 alloc_size = pos_ofs + pos_memsize;
983
984 tmp_idx = xmalloc(alloc_size);
985 memcpy(tmp_idx, selection_idx, idx_memsize);
986
987 sorted_selection_pos
988 = (void *)((unsigned char *)tmp_idx + pos_ofs);
989 xt_assign_id_map_int(num_selection, sorted_selection_pos, 0);
990 xt_default_config.sort_funcs->sort_xt_int_permutation(
991 tmp_idx, num_selection, sorted_selection_pos);
992 sorted_selection = tmp_idx;
993 }
994
995 /* motivation for usage of single_match_only:
996 * on the target side we want single_match_only,
997 * on the source side we don't
998 */
999 Xt_idxvec body_idxvec = (Xt_idxvec)body_idxlist;
1000 struct Xt_config_ sort_config = xt_default_config;
1001 XT_CONFIG_UNSET_FORCE_NOSORT(&sort_config);
1002 const Xt_int *sorted_body
1003 = get_sorted_vector(body_idxvec, &sort_config);
1004 const int *sorted_body_pos = body_idxvec->sorted_vec_positions;
1005 size_t search_end = (size_t)body_idxvec->parent.num_indices - 1;
1006 size_t num_unmatched = 0;
1007
1008 // after the match we will move on one step in order to avoid matching the same position again
1009 size_t post_match_step = single_match_only != 0;
1010
1011 size_t i=0;
1012 for (size_t search_start = 0, ub_guess_ofs = 1;
1013 i < num_selection && search_start<=search_end;
1014 ++i) {
1015 size_t selection_pos = selection_is_ordered ? i : (size_t)sorted_selection_pos[i];
1016 Xt_int isel = sorted_selection[i];
1017 // bisection to find one matching position:
1018 size_t ub = MIN(search_start + ub_guess_ofs, search_end);
1019 size_t lb = search_start;
1020 /* guess too low? */
1021 if (sorted_body[ub] < isel) {
1022 lb = MIN(ub + 1, search_end);
1023 ub = search_end;
1024 }
1025 /* dividing (ub-lb) by 2 gives 0 iff (ub-lb) < 2 but uses less
1026 * instructions than comparing to literal 1 */
1027 while ((ub-lb)/16) {
1028 size_t middle = (ub + lb + 1) / 2;
1029 /* todo: make branch free with mask/inv mask by predicate */
1030 if (sorted_body[middle] <= isel)
1031 lb = middle;
1032 else
1033 ub = middle;
1034 }
1035 /* use linear scan for last part of search */
1036 while (sorted_body[lb] < isel && lb < ub)
1037 ++lb;
1038 size_t match_pos;
1039 // search is now narrowed to two positions, select one of them:
1040 if (isel == sorted_body[lb]) {
1041 match_pos = lb;
1042 } else {
1043 num_unmatched++;
1044 positions[selection_pos] = -1;
1045 continue;
1046 }
1047
1048 // find left most match >= search_start (bisection can lead to any match >= search_start)
1049 while (match_pos > search_start && sorted_body[match_pos-1] == isel)
1050 --match_pos;
1051
1052 // result:
1053 // update positions and prepare next search:
1054 positions[selection_pos]
1055 = sorted_body_pos ? sorted_body_pos[match_pos] : (int)match_pos;
1056 ub_guess_ofs = match_pos - search_start;
1057 search_start = match_pos + post_match_step;
1058 }
1059 if (i < num_selection) {
1060 num_unmatched += num_selection - i;
1061 if (selection_is_ordered)
1062 do {
1063 positions[i] = -1;
1064 } while (++i < num_selection);
1065 else
1066 do {
1067 positions[sorted_selection_pos[i]] = -1;
1068 } while (++i < num_selection);
1069 }
1070 if (tmp_idx) free(tmp_idx);
1071
1072 return num_unmatched;
1073}
1074
1075static Xt_int
1077
1078 Xt_idxvec idxvec_obj = (Xt_idxvec)idxlist;
1079 return idxvec_obj->min;
1080}
1081
1082static Xt_int
1084
1085 Xt_idxvec idxvec_obj = (Xt_idxvec)idxlist;
1086
1087 return idxvec_obj->max;
1088}
1089
1090static int
1092{
1093 unsigned flags = ((Xt_idxvec)idxlist)->flags;
1094 return (int)(flags & sort_mask)-((flags & sort_mask) < 3);
1095}
1096
1097/*
1098 * Local Variables:
1099 * c-basic-offset: 2
1100 * coding: utf-8
1101 * indent-tabs-mode: nil
1102 * show-trailing-whitespace: t
1103 * require-trailing-newline: t
1104 * End:
1105 */
int MPI_Comm
Definition core.h:64
#define die(msg)
Definition core.h:131
#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
#define PPM_DSO_INTERNAL
add versions of standard API functions not returning on error
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:71
#define xmalloc(size)
Definition ppm_xfuncs.h:70
const struct Xt_sort_algo_funcptr * sort_funcs
const struct xt_idxlist_vtable * vtable
const Xt_int * sorted_vector
Definition xt_idxvec.c:172
unsigned flags
Definition xt_idxvec.c:167
Xt_int min
Definition xt_idxvec.c:168
struct Xt_idxlist_ parent
Definition xt_idxvec.c:166
int * sorted_vec_positions
Definition xt_idxvec.c:173
Xt_int max
Definition xt_idxvec.c:168
const Xt_int * vector
Definition xt_idxvec.c:169
void(* sort_xt_int_permutation)(Xt_int a[], size_t n, int permutation[])
void(* sort_xt_int)(Xt_int *a, size_t n)
Xt_int stride
Definition xt_stripe.h:56
int nstrides
Definition xt_stripe.h:57
Xt_int start
Definition xt_stripe.h:55
struct Xt_stripe * stripes
struct Xt_idxvec_ * idxvec
unsigned flags
Definition xt_idxvec.c:253
static Xt_int Xt_isign_mask(Xt_int x)
static const char filename[]
Definition xt_config.c:76
struct Xt_config_ xt_default_config
Definition xt_config.c:204
struct Xt_config_ * Xt_config
Definition xt_config.h:58
implementation of configuration object
#define XT_CONFIG_GET_FORCE_NOSORT(config)
#define XT_CONFIG_UNSET_FORCE_NOSORT(config)
base definitions header file
#define XT_INT_MIN
Definition xt_core.h:78
#define XT_INT_MAX
Definition xt_core.h:77
int xt_initialized(void)
#define Xt_int_dt
Definition xt_core.h:73
XT_INT Xt_int
Definition xt_core.h:72
struct Xt_idxlist_ * Xt_idxlist
Definition xt_core.h:84
Xt_idxlist xt_idxempty_new(void)
index list declaration
void xt_idxlist_delete(Xt_idxlist idxlist)
Definition xt_idxlist.c:75
Provide non-public declarations common to all index lists.
#define xt_idxlist_get_num_indices(idxlist)
static void Xt_idxlist_init(Xt_idxlist idxlist, const struct xt_idxlist_vtable *vtable, int num_indices)
@ VECTOR
@ STRIPES
const struct Xt_stripe * xt_idxstripes_get_index_stripes_const(Xt_idxlist idxlist)
struct Xt_stripes_alloc xt_idxstripes_alloc(size_t num_stripes)
Xt_idxlist xt_idxstripes_congeal(struct Xt_stripes_alloc stripes_alloc)
size_t xt_idxstripes_get_num_index_stripes(Xt_idxlist idxlist)
static Xt_int stripe_min(struct Xt_stripe stripe, int pfx_remove)
Xt_idxlist xt_idxstripes_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst, Xt_config config)
static Xt_int idxvec_get_min_index(Xt_idxlist idxlist)
Definition xt_idxvec.c:1076
Xt_idxlist xt_idxvec_prealloc_new(const Xt_int *idxvec, int num_indices)
Definition xt_idxvec.c:308
static const char filename[]
Definition xt_idxvec.c:158
static int idxvec_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int *position)
Definition xt_idxvec.c:941
static void idxvec_delete(Xt_idxlist data)
Definition xt_idxvec.c:497
static void idxvec_get_indices(Xt_idxlist idxlist, Xt_int *indices)
Definition xt_idxvec.c:807
Xt_idxlist xt_idxvec_new(const Xt_int *idxvec, int num_indices)
Definition xt_idxvec.c:213
#define MIN(a, b)
Definition xt_idxvec.c:76
static Xt_idxlist idxvec_copy(Xt_idxlist idxlist)
Definition xt_idxvec.c:774
static int idxvec_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
Definition xt_idxvec.c:841
static void idxvec_pack(Xt_idxlist data, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition xt_idxvec.c:522
static size_t idxvec_get_pack_size(Xt_idxlist data, MPI_Comm comm)
Definition xt_idxvec.c:511
static bool idx_vec_is_sorted(Xt_int const *idx, size_t n)
Definition xt_idxvec.c:946
static int idxvec_get_indices_at_positions(Xt_idxlist idxlist, const int *positions, int num, Xt_int *index, Xt_int undef_idx)
static int idxvec_get_sorting(Xt_idxlist idxlist)
Definition xt_idxvec.c:1091
static struct Xt_vec_alloc idxvec_alloc(int num_indices)
Definition xt_idxvec.c:206
static Xt_idxlist idxvec_sorted_copy(Xt_idxlist idxlist, Xt_config config)
Definition xt_idxvec.c:781
static int idxvec_get_position_of_index_off(Xt_idxlist idxlist, Xt_int index, int *position, int offset)
Definition xt_idxvec.c:880
static struct flags_min_max get_sort_flags(size_t num_indices, const Xt_int vector[num_indices])
Definition xt_idxvec.c:258
static const struct xt_idxlist_vtable idxvec_vtable
Definition xt_idxvec.c:135
static void idxvec_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe *stripes, size_t num_stripes_alloc)
Definition xt_idxvec.c:832
static struct Xt_vec_alloc idxvec_alloc_no_init(int num_indices)
Definition xt_idxvec.c:184
@ pack_header_size
Definition xt_idxvec.c:507
@ unpack_header_size
Definition xt_idxvec.c:508
static Xt_int const * idxvec_get_indices_const(Xt_idxlist idxlist)
Definition xt_idxvec.c:814
PPM_DSO_INTERNAL const Xt_int * xt_idxvec_get_sorted_vector(Xt_idxlist idxvec, Xt_config config)
Definition xt_idxvec.c:566
static const Xt_int * get_sorted_vector(Xt_idxvec idxvec, Xt_config config)
Definition xt_idxvec.c:572
Xt_idxlist xt_idxvec_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst, Xt_config config)
Definition xt_idxvec.c:605
struct Xt_idxvec_ * Xt_idxvec
Definition xt_idxvec.c:161
static void generate_sorted_vector_from_stripes(const struct Xt_stripe stripes[], int num_stripes_, Xt_idxvec idxvec, Xt_config config)
Definition xt_idxvec.c:347
PPM_DSO_INTERNAL Xt_idxlist xt_idxvec_get_idxstripes(Xt_idxlist idxlist)
Definition xt_idxvec.c:664
Xt_idxlist xt_idxvec_from_stripes_new(const struct Xt_stripe stripes[], int num_stripes)
Definition xt_idxvec.c:470
static Xt_int idxvec_get_max_index(Xt_idxlist idxlist)
Definition xt_idxvec.c:1083
PPM_DSO_INTERNAL Xt_idxlist xt_idxvec_get_idxstripes_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst, Xt_config config)
Definition xt_idxvec.c:683
static size_t decode_stripe(struct Xt_stripe stripe, Xt_int *sorted_vector, int *sorted_vec_pos, int pos_offset)
Definition xt_idxvec.c:324
static int idxvec_get_num_index_stripes(Xt_idxlist idxlist)
Definition xt_idxvec.c:822
struct Xt_vec_alloc xt_idxvec_alloc(int num_indices)
Definition xt_idxvec.c:200
Xt_idxlist xt_idxvec_congeal(struct Xt_vec_alloc vec_alloc)
Definition xt_idxvec.c:284
static size_t idxvec_get_positions_of_indices(Xt_idxlist idxlist, const Xt_int *indices, size_t num_indices, int *positions, int single_match_only)
Definition xt_idxvec.c:956
Xt_idxlist xt_idxvec_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition xt_idxvec.c:536
#define MAX(a, b)
Definition xt_idxvec.c:75
utility routines for MPI
#define xt_mpi_call(call, comm)
Definition xt_mpi.h:68
void xt_assign_id_map_int(size_t n, int *restrict a, int ofs)
Definition xt_sort.c:77
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_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
@ sort_mask
@ sort_asc
@ sort_idt
#define XT_SORT_FLAGS(ntrans_up, ntrans_dn)