72 #define MIN(a,b) (((a)<(b))?(a):(b)) 109 int * position,
int offset);
113 int num_indices,
int *positions,
114 int single_match_only);
135 .get_positions_of_indices_off = NULL,
138 .get_bounding_box = NULL,
139 .idxlist_pack_code =
VECTOR,
167 else if (num_indices == 0)
170 die(
"number of indices passed to xt_idxvec_new must not be negative!");
173 size_t vector_size = (size_t)num_indices *
sizeof (idxvec[0]),
174 header_size = ((
sizeof (
struct Xt_idxvec_) + sizeof (Xt_int) - 1)
175 /sizeof (Xt_int)) *
sizeof (
Xt_int);
179 Xt_int *vector_assign = (Xt_int *)(
void *)((
unsigned char *)idxvec_obj + header_size);
180 idxvec_obj->
vector = vector_assign;
181 memcpy(vector_assign, idxvec, vector_size);
182 idxvec_obj->sorted_vector = NULL;
183 idxvec_obj->sorted_vec_positions = NULL;
186 return (
void *)idxvec_obj;
193 else if (num_indices == 0)
196 die(
"number of indices passed to xt_idxvec_new must not be negative!");
199 idxvec_obj->vector = idxvec;
200 idxvec_obj->sorted_vector = NULL;
201 idxvec_obj->sorted_vec_positions = NULL;
202 return (
void *)idxvec_obj;
207 int * sorted_vec_pos,
int pos_offset) {
210 for (
int i = 0; i < stripe.
nstrides; ++i) {
212 sorted_vec_pos[i] = pos_offset + i;
215 for (
int i = 0; i < stripe.
nstrides; ++i) {
218 sorted_vec_pos[j] = pos_offset + i;
225 #define MAX(a,b) ((a) >= (b) ? (a) : (b)) 232 if (num_stripes_ <= 0) {
238 size_t num_stripes = (size_t)num_stripes_;
239 Xt_int *restrict sorted_vector_assign
250 Xt_int (*restrict stripe_minmax)[num_stripes]
251 =
xmalloc(2 *
sizeof(*stripe_minmax));
252 int *restrict sorted_stripe_min_pos
253 =
xmalloc(num_stripes * 3 *
sizeof(*sorted_stripe_min_pos));
255 for(
size_t i = 0; i < num_stripes; ++i) {
256 Xt_int ofs = (
Xt_int)(stripes[i].stride * (stripes[i].nstrides - 1)),
258 stripe_minmax[0][i] = (
Xt_int)(stripes[i].start + (ofs & mask));
262 sorted_stripe_min_pos, 1);
264 int *restrict sorted_pos_prefix_sum, *restrict orig_pos_prefix_sum;
266 sorted_pos_prefix_sum
267 = sorted_stripe_min_pos + num_stripes;
269 =
xmalloc(num_stripes *
sizeof(*orig_pos_prefix_sum));
271 orig_pos_prefix_sum[0] = 0;
272 for (
size_t i = 1; i < num_stripes; ++i)
273 orig_pos_prefix_sum[i] = orig_pos_prefix_sum[i-1] + stripes[i-1].nstrides;
275 for (
size_t i = 0; i < num_stripes; ++i) {
276 sorted_pos_prefix_sum[i] = orig_pos_prefix_sum[sorted_stripe_min_pos[i]];
277 int sorted_pos = sorted_stripe_min_pos[i];
279 * (stripes[sorted_pos].nstrides - 1)),
281 stripe_minmax[1][i] = (
Xt_int)(stripes[sorted_pos].start + (ofs & ~mask));
284 free(orig_pos_prefix_sum);
290 int *restrict overlap_count
291 = sorted_stripe_min_pos + 2 * num_stripes;
292 for (
size_t i = 0; i < num_stripes - 1; ++i) {
293 bool do_overlap = stripe_minmax[1][i] >= stripe_minmax[0][i + 1];
299 Xt_int range_max_idx =
MAX(stripe_minmax[1][i], stripe_minmax[1][i+1]);
300 while (j + 1 < num_stripes
301 && stripe_minmax[0][j + 1] <= range_max_idx) {
302 range_max_idx =
MAX(range_max_idx, stripe_minmax[1][j+1]);
305 overlap_count[i] = (int)(j - i);
308 while (j + 1 < num_stripes
309 && stripe_minmax[0][j + 1] > stripe_minmax[1][j])
311 overlap_count[i] = -(int)(j - i - 1);
315 overlap_count[num_stripes - 1] = 0;
320 while (i < num_stripes) {
322 bool do_overlap = overlap_count[i] > 0;
323 size_t num_selection = (size_t)(abs(overlap_count[i])) + 1;
326 for (
size_t j = 0; j < num_selection; ++j)
330 sorted_vector_assign + offset
334 sorted_pos_prefix_sum[i+j]));
340 offset = (
Xt_int)(offset + curr_offset);
344 free(sorted_stripe_min_pos);
352 long long num_indices = 0;
354 for (
int i = 0; i < num_stripes; ++i)
355 num_indices += stripes[i].nstrides;
356 assert((
sizeof (
long long) >
sizeof (
int)) & (num_indices <= INT_MAX)
357 & (num_indices >= 0));
359 size_t vector_size = (size_t)num_indices *
sizeof (
Xt_int),
360 header_size = ((
sizeof (
struct Xt_idxvec_) + sizeof (Xt_int) - 1)
361 /sizeof (Xt_int)) *
sizeof (
Xt_int);
362 Xt_idxvec idxvec_obj =
xmalloc(header_size + vector_size);
364 Xt_int *restrict indices
365 = (Xt_int *)(
void *)((
unsigned char *)idxvec_obj + header_size);
366 idxvec_obj->
vector = indices;
368 size_t k = (size_t)-1;
369 for (
int i = 0; i < num_stripes; ++i)
370 for (
int j = 0; j < stripes[i].
nstrides; ++j)
371 indices[++k] = (Xt_int)(stripes[i].
start + j * stripes[i].
stride);
392 int size_xt_idx, size_int_type;
394 xt_mpi_call(MPI_Pack_size(2, MPI_INT, comm, &size_int_type), comm);
396 &size_xt_idx), comm);
398 return (
size_t)size_xt_idx + (size_t)size_int_type;
409 buffer_size, position, comm), comm);
411 buffer_size, position, comm), comm);
415 buffer_size, position, comm), comm);
423 xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
424 &num_indices, 1, MPI_INT, comm), comm);
426 size_t vector_size = (size_t)num_indices *
sizeof (
Xt_int),
427 header_size = ((
sizeof (
struct Xt_idxvec_) + sizeof (Xt_int) - 1)
428 /sizeof (Xt_int)) *
sizeof (
Xt_int);
429 Xt_idxvec idxvec =
xmalloc(header_size + vector_size);
432 Xt_int *vector_assign = (Xt_int *)(
void *)((
unsigned char *)idxvec + header_size);
433 idxvec->
vector = vector_assign;
434 if (num_indices != 0) {
435 xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
436 vector_assign, num_indices,
439 fputs(
"warning: implementation generated empty vector!\n", stderr);
462 for (
size_t i = 1; i < num_indices; ++i)
468 for (
size_t i = 0; i < num_indices; ++i)
473 =
xmalloc((
size_t)num_indices *
sizeof(*sorted_vector));
475 memcpy(sorted_vector, idxvec->
vector,
476 (
size_t)num_indices *
sizeof(*sorted_vector));
491 Xt_idxvec idxvec_src = (
Xt_idxvec)idxlist_src,
492 idxvec_dst = (Xt_idxvec)idxlist_dst;
495 size_t num_indices_inter = 0,
497 num_indices_dst = (
size_t)idxvec_dst->parent.num_indices;
499 size_t vector_size = num_indices_dst *
sizeof (idxvec_dst->vector[0]),
503 Xt_idxvec inter_vector =
xmalloc(header_size + vector_size);
506 = (
Xt_int *)(
void *)((
unsigned char *)inter_vector + header_size);
507 inter_vector->
vector = vector_assign;
509 const Xt_int *restrict sorted_src_vector, *restrict sorted_dst_vector;
518 for (
size_t i = 0, j = 0; i < num_indices_dst; ++i) {
520 while (j < num_indices_src &&
521 sorted_src_vector[j] < sorted_dst_vector[i]) ++j;
522 if (j >= num_indices_src)
break;
523 if (sorted_src_vector[j] == sorted_dst_vector[i])
524 vector_assign[num_indices_inter++] = sorted_dst_vector[i];
527 if (num_indices_inter) {
528 vector_size = (size_t)num_indices_inter *
sizeof (idxvec_dst->vector[0]);
529 inter_vector =
xrealloc(inter_vector, header_size + vector_size);
531 = (
Xt_int *)(
void *)((
unsigned char *)inter_vector + header_size);
547 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
555 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
557 memcpy(indices, idxvec_obj->
vector,
573 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
577 stripes, num_stripes);
583 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
588 *index = idxvec_obj->
vector[position];
595 const int *restrict positions,
596 int num_pos_,
Xt_int *index,
604 size_t num_pos = num_pos_ >= 0 ? (
size_t)num_pos_ : (size_t)0;
605 for (
size_t ip = 0; ip < num_pos; ip++) {
606 int p = positions[ip];
607 if (p >= 0 && (
size_t)p < num_indices) {
610 index[ip] = undef_idx;
623 int * position,
int offset) {
625 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
630 if ((offset < 0) || ((size_t)offset >= num_indices))
635 if ((index < sorted_vector[0]) ||
636 (index > sorted_vector[num_indices-1]))
641 size_t ub = num_indices - 1;
643 while (sorted_vector[lb] < index) {
645 size_t middle = (ub + lb + 1)/2;
647 if (sorted_vector[middle] <= index)
649 else if (ub == middle)
656 while (lb > 0 && sorted_vector[lb-1] == index) --lb;
659 while (lb < num_indices - 1 &&
661 sorted_vector[lb] == index) ++lb;
664 if (lb >= num_indices || sorted_vector[lb] != index)
681 for (
size_t i = 1; i < n; i++)
682 if (idx[i] < idx[i-1])
return false;
689 const Xt_int *selection_idx,
690 int num_selection,
int *positions,
691 int single_match_only) {
693 if (num_selection <= 0)
return 0;
695 bool selection_is_ordered =
idx_vec_is_sorted(selection_idx, (
size_t)num_selection);
698 Xt_int const *sorted_selection;
699 int *sorted_selection_pos = NULL;
702 if (selection_is_ordered) {
703 sorted_selection = selection_idx;
705 size_t idx_memsize = (size_t)num_selection *
sizeof(*sorted_selection),
706 pos_memsize = (size_t)num_selection *
sizeof(*sorted_selection_pos),
708 pos_ofs = ((idx_memsize +
sizeof (int) - 1)
709 & ((size_t)-(ssize_t)(
sizeof(int)))),
711 alloc_size = pos_ofs + pos_memsize;
714 memcpy(tmp_idx, selection_idx, idx_memsize);
717 = (
void *)((
unsigned char *)tmp_idx + pos_ofs);
719 sorted_selection = tmp_idx;
726 Xt_idxvec body_idxvec = (
Xt_idxvec)body_idxlist;
730 int num_unmatched = 0;
733 size_t post_match_step = single_match_only != 0;
736 for (
size_t search_start = 0, ub_guess_ofs = 1;
737 i < (size_t)num_selection && search_start<=search_end;
739 size_t selection_pos = selection_is_ordered ? i : (size_t)sorted_selection_pos[i];
740 Xt_int isel = sorted_selection[i];
742 size_t ub =
MIN(search_start + ub_guess_ofs, search_end);
743 size_t lb = search_start;
745 if (sorted_body[ub] < isel) {
746 lb =
MIN(ub + 1, search_end);
752 size_t middle = (ub + lb + 1) / 2;
754 if (sorted_body[middle] <= isel)
760 while (sorted_body[lb] < isel && lb < ub)
764 if (isel == sorted_body[lb]) {
768 positions[selection_pos] = -1;
773 while (match_pos > search_start && sorted_body[match_pos-1] == isel)
778 positions[selection_pos] = sorted_body_pos[match_pos];
779 ub_guess_ofs = match_pos - search_start;
780 search_start = match_pos + post_match_step;
782 if (i < (
size_t)num_selection) {
783 num_unmatched += (int)((
size_t)num_selection - i);
784 if (selection_is_ordered)
787 }
while (++i < (
size_t)num_selection);
790 positions[sorted_selection_pos[i]] = -1;
791 }
while (++i < (
size_t)num_selection);
793 if (tmp_idx) free(tmp_idx);
795 return num_unmatched;
801 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
804 die(
"idxvec_get_min_index: empty index vector");
812 Xt_idxvec idxvec_obj = (
Xt_idxvec)idxlist;
815 die(
"idxvec_get_max_index: empty index vector");
struct Xt_idxlist_ parent
base definitions header file
static int idxvec_get_position_of_index_off(Xt_idxlist idxlist, Xt_int index, int *position, int offset)
const Xt_int * sorted_vector
static void idxvec_delete(Xt_idxlist data)
add versions of standard API functions not returning on error
static void idxvec_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
static size_t idxvec_get_pack_size(Xt_idxlist data, MPI_Comm comm)
Xt_idxlist xt_idxvec_from_stripes_new(const struct Xt_stripe stripes[], int num_stripes)
int * sorted_vec_positions
#define xrealloc(ptr, size)
void xt_convert_indices_to_stripes(const Xt_int *indices, int num_indices, struct Xt_stripe **stripes, int *num_stripes)
static void idxvec_get_indices(Xt_idxlist idxlist, Xt_int *indices)
static Xt_int idxvec_get_min_index(Xt_idxlist idxlist)
Xt_idxlist xt_idxempty_new(void)
static const Xt_int * get_sorted_vector(Xt_idxvec idxvec)
static bool idx_vec_is_sorted(Xt_int const *idx, size_t n)
static void generate_sorted_vector_from_stripes(const struct Xt_stripe stripes[], int num_stripes_, Xt_idxvec idxvec)
Provide non-public declarations common to all index lists.
static Xt_int Xt_isign_mask(Xt_int x)
struct Xt_idxvec_ * Xt_idxvec
void xt_quicksort_index(Xt_int *v_idx, int n, int *v_pos, int reset_pos)
static void Xt_idxlist_init(Xt_idxlist idxlist, const struct xt_idxlist_vtable *vtable, int num_indices)
static void idxvec_pack(Xt_idxlist data, void *buffer, int buffer_size, int *position, MPI_Comm comm)
static const struct xt_idxlist_vtable idxvec_vtable
static int decode_stripe(struct Xt_stripe stripe, Xt_int *sorted_vector, int *sorted_vec_pos, int pos_offset)
static Xt_idxlist idxvec_copy(Xt_idxlist idxlist)
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_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
void(* delete)(Xt_idxlist)
static int idxvec_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int *position)
Xt_idxlist xt_idxvec_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
Xt_idxlist xt_idxvec_new(const Xt_int *idxvec, int num_indices)
#define xt_mpi_call(call, comm)
Xt_idxlist xt_idxvec_prealloc_new(const Xt_int *idxvec, int num_indices)
Xt_idxlist xt_idxvec_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst)
static int idxvec_get_positions_of_indices(Xt_idxlist idxlist, const Xt_int *indices, int num_indices, int *positions, int single_match_only)
static Xt_int const * idxvec_get_indices_const(Xt_idxlist idxlist)
static Xt_int idxvec_get_max_index(Xt_idxlist idxlist)