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