Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_idxsection.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://doc.redmine.dkrz.de/yaxt/html/
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 <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55 
56 #include "xt_arithmetic_util.h"
57 #include "xt/xt_idxlist.h"
58 #include "xt_idxlist_internal.h"
59 #include "xt/xt_idxempty.h"
60 #include "xt/xt_idxvec.h"
61 #include "xt/xt_idxsection.h"
62 #include "xt_idxsection_internal.h"
63 #include "xt/xt_mpi.h"
64 #include "xt/mergesort.h"
65 #include "xt/quicksort.h"
66 #include "xt_idxlist_unpack.h"
67 #include "core/ppm_xfuncs.h"
68 #include "core/core.h"
69 #include "instr.h"
70 
71 static void
73 
74 static size_t
76 
77 static void
78 idxsection_pack(Xt_idxlist data, void *buffer, int buffer_size,
79  int *position, MPI_Comm comm);
80 
81 static Xt_idxlist
83 
84 static void
85 idxsection_get_indices(Xt_idxlist idxlist, Xt_int *indices);
86 
87 static const Xt_int *
89 
90 static void
91 idxsection_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe ** stripes,
92  int * num_stripes);
93 
94 static int
95 idxsection_get_index_at_position(Xt_idxlist idxlist, int position,
96  Xt_int * index);
97 
98 static int
100  int * position);
101 
102 static int
104  int * position, int offset);
105 static int
106 idxsection_get_positions_of_indices(Xt_idxlist body_idxlist, Xt_int const * selection_idx,
107  int num_selection, int *positions,
108  int single_match_only);
109 
110 static Xt_int
112 
113 static Xt_int
115 
116 static const struct xt_idxlist_vtable idxsection_vtable = {
118  .get_pack_size = idxsection_get_pack_size,
119  .pack = idxsection_pack,
120  .copy = idxsection_copy,
121  .get_indices = idxsection_get_indices,
122  .get_indices_const = idxsection_get_indices_const,
123  .get_index_stripes = idxsection_get_index_stripes,
124  .get_index_at_position = idxsection_get_index_at_position,
125  .get_indices_at_positions = NULL,
126  .get_position_of_index = idxsection_get_position_of_index,
127  .get_positions_of_indices = idxsection_get_positions_of_indices,
128  .get_position_of_index_off = idxsection_get_position_of_index_off,
129  .get_positions_of_indices_off = NULL,
130  .get_min_index = idxsection_get_min_index,
131  .get_max_index = idxsection_get_max_index,
132  .get_bounding_box = NULL,
133  .idxlist_pack_code = SECTION,
134 };
135 
136 /* descriptor for per-dimension extent and stride */
137 struct dim_desc
138 {
141 };
142 
143 static MPI_Datatype dim_desc_dt;
144 
145 
147 
149 
150  struct Xt_idxlist_ parent;
151 
154 
156 
159  int ndim;
160  struct dim_desc dims[];
161 };
162 
163 static int
164 idxsection_get_num_indices(Xt_idxsection section);
165 
166 void
168 {
169  struct dim_desc dim_desc;
170 
171  MPI_Aint base_address, local_size_address;
172 
173  MPI_Get_address(&dim_desc, &base_address);
174  MPI_Get_address(&dim_desc.local_size, &local_size_address);
175 
176  enum { num_dt_components = 2 };
177  int block_lengths[num_dt_components] = { 4, 1 };
178  MPI_Aint displacements[num_dt_components]
179  = {0, local_size_address - base_address };
180  MPI_Datatype types[num_dt_components]
181  = { Xt_int_dt, MPI_INT },
182  dim_desc_dt_unaligned;
183  xt_mpi_call(MPI_Type_create_struct(num_dt_components,
184  block_lengths, displacements, types,
185  &dim_desc_dt_unaligned), Xt_default_comm);
186  xt_mpi_call(MPI_Type_create_resized(dim_desc_dt_unaligned, 0,
187  (MPI_Aint)sizeof(dim_desc),
188  &dim_desc_dt), Xt_default_comm);
189  xt_mpi_call(MPI_Type_free(&dim_desc_dt_unaligned), Xt_default_comm);
190  xt_mpi_call(MPI_Type_commit(&dim_desc_dt), Xt_default_comm);
191 }
192 
193 void
195 {
196  xt_mpi_call(MPI_Type_free(&dim_desc_dt), Xt_default_comm);
197 }
198 
199 Xt_idxlist xt_idxsection_new(Xt_int start, int num_dimensions,
200  const Xt_int global_size[num_dimensions],
201  const int local_size[num_dimensions],
202  const Xt_int local_start[num_dimensions]) {
203 
204  INSTR_DEF(instr,"xt_idxsection_new")
205  INSTR_START(instr);
206 
207  if (num_dimensions <= 0)
208  return xt_idxempty_new();
209  Xt_idxsection idxsection = xmalloc(sizeof (*idxsection)
210  + (size_t)num_dimensions *
211  sizeof (idxsection->dims[0]));
212 
213  idxsection->global_start_index = start;
214  idxsection->ndim = num_dimensions;
215 
216  idxsection->index_array_cache = NULL;
217 
218  for (int i = 0; i < num_dimensions; ++i) {
219  idxsection->dims[i].global_size = global_size[i];
220  idxsection->dims[i].local_size = local_size[i];
221  idxsection->dims[i].local_start = local_start[i];
222  }
223 
224  int num_indices = idxsection_get_num_indices(idxsection);
225  Xt_idxlist_init(&idxsection->parent, &idxsection_vtable, num_indices);
226  idxsection->local_start_index = start;
227  idxsection->dims[num_dimensions - 1].global_stride =
228  (Xt_int)(Xt_isign(global_size[num_dimensions - 1]) *
229  isign(local_size[num_dimensions - 1]));
230  idxsection->dims[num_dimensions - 1].local_stride = 1;
231 
232  // compute local and global stride
233  // (local stride is always positive, global stride can be negative)
234  for (int i = num_dimensions - 2; i >= 0; --i) {
235  idxsection->dims[i].global_stride
236  = (Xt_int)(idxsection->dims[i+1].global_stride * global_size[i + 1]
237  * Xt_isign((Xt_int)(idxsection->dims[i+1].global_stride
238  * global_size[i + 1]))
240  * (Xt_int)isign(local_size[i]))));
241  idxsection->dims[i].local_stride
242  = (Xt_int)(idxsection->dims[i + 1].local_stride * local_size[i + 1]
243  * Xt_isign((Xt_int)(idxsection->dims[i + 1].local_stride
244  * (Xt_int)local_size[i + 1])));
245  }
246 
247  // compute the local start index
248  // depends on global size and sign of local and global size
249  for (int i = num_dimensions - 1; i >= 0; --i) {
250  if (global_size[i] > 0)
251  idxsection->local_start_index
252  = (Xt_int)(idxsection->local_start_index
253  + (XT_INT_ABS(idxsection->dims[i].global_stride)
254  * local_start[i]));
255  else
256  idxsection->local_start_index
257  = (Xt_int)(idxsection->local_start_index
258  - (XT_INT_ABS(idxsection->dims[i].global_stride)
259  * (global_size[i] + local_start[i] + 1)));
260  if (local_size[i] < 0)
261  idxsection->local_start_index
262  = (Xt_int)(idxsection->local_start_index
263  - (XT_INT_ABS(idxsection->dims[i].global_stride)
264  * (local_size[i] + 1)
265  * Xt_isign(global_size[i])));
266  }
267 
268  // due the possibility of negative local and global sizes, the minimum and
269  // maximum can be in any corner of the n-dimensional section
270  idxsection->min_index_cache = idxsection->local_start_index;
271  idxsection->max_index_cache = idxsection->local_start_index;
272  for (int i = 0; i < num_dimensions; ++i) {
273 
274  // if either local and global size are negative
275  if ((global_size[i] < 0) ^ (local_size[i] < 0))
276  idxsection->min_index_cache
277  = (Xt_int)(idxsection->min_index_cache
278  + (Xt_int)(idxsection->dims[i].global_stride *
279  (Xt_int)(abs(local_size[i]) - 1)));
280  else // if local and global size are both positive or negative
281  idxsection->max_index_cache
282  = (Xt_int)(idxsection->max_index_cache
283  + (Xt_int)(idxsection->dims[i].global_stride *
284  (Xt_int)(abs(local_size[i]) - 1)));
285  }
286 
287  INSTR_STOP(instr);
288 
289  return (Xt_idxlist)idxsection;
290 }
291 
292 static void
294 
295  if (data == NULL) return;
296 
297  Xt_idxsection section = (Xt_idxsection)data;
298 
299  free(section->index_array_cache);
300  free(section);
301 }
302 
303 static size_t
305 
306  Xt_idxsection section = (Xt_idxsection)data;
307 
308  int size_int_type, size_ndim, size_dim_descs, size_xt_int;
309 
310  xt_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &size_int_type), comm);
311  xt_mpi_call(MPI_Pack_size(2, Xt_int_dt, comm, &size_xt_int), comm);
312  xt_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &size_ndim), comm);
313  xt_mpi_call(MPI_Pack_size(section->ndim, dim_desc_dt,
314  comm, &size_dim_descs), comm);
315 
316  return (size_t)size_int_type + (size_t)size_ndim + (size_t)size_dim_descs
317  + (size_t)size_xt_int;
318 }
319 
320 static void
321 idxsection_pack(Xt_idxlist data, void *buffer, int buffer_size,
322  int *position, MPI_Comm comm) {
323 
324  INSTR_DEF(instr,"idxsection_pack")
325  INSTR_START(instr);
326 
327  assert(data);
328  Xt_idxsection section = (Xt_idxsection)data;
329  int type = SECTION;
330 
331  xt_mpi_call(MPI_Pack(&(type), 1, MPI_INT, buffer,
332  buffer_size, position, comm), comm);
333  xt_mpi_call(MPI_Pack(&(section->global_start_index), 1,
334  Xt_int_dt, buffer,
335  buffer_size, position, comm), comm);
336  xt_mpi_call(MPI_Pack(&(section->local_start_index), 1,
337  Xt_int_dt, buffer,
338  buffer_size, position, comm), comm);
339  xt_mpi_call(MPI_Pack(&(section->ndim), 1, MPI_INT, buffer,
340  buffer_size, position, comm), comm);
341  xt_mpi_call(MPI_Pack(section->dims, section->ndim, dim_desc_dt,
342  buffer, buffer_size, position, comm), comm);
343  INSTR_STOP(instr);
344 }
345 
346 Xt_idxlist xt_idxsection_unpack(void *buffer, int buffer_size, int *position,
347  MPI_Comm comm) {
348 
349  INSTR_DEF(instr,"xt_idxsection_unpack")
350  INSTR_START(instr);
351 
352  Xt_idxsection section;
353  int ndim;
354  {
355  Xt_int global_start_index, local_start_index;
356  xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
357  &global_start_index, 1, Xt_int_dt, comm), comm);
358  xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
359  &local_start_index, 1, Xt_int_dt, comm), comm);
360  xt_mpi_call(MPI_Unpack(buffer, buffer_size, position, &ndim, 1, MPI_INT,
361  comm), comm);
362  assert(ndim > 0);
363 
364  section = xmalloc(sizeof (*section)
365  + (size_t)ndim * sizeof(section->dims[0]));
366  section->index_array_cache = NULL;
367  section->global_start_index = global_start_index;
368  section->local_start_index = local_start_index;
369  section->ndim = ndim;
370  }
371 
372  xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
373  section->dims, ndim, dim_desc_dt,
374  comm),comm);
375 
376  // due to the possibility of negative local and global sizes, the minimum and
377  // maximum can be in any corner of the n-dimensional section
378  section->min_index_cache = section->local_start_index;
379  section->max_index_cache = section->local_start_index;
380  for (int i = 0; i < ndim; ++i) {
381 
382  // if either local or global size is negative
383  if ((section->dims[i].global_size < 0) ^ (section->dims[i].local_size < 0))
384  section->min_index_cache =
385  (Xt_int)(section->min_index_cache + section->dims[i].global_stride
386  * (abs(section->dims[i].local_size) - 1));
387  else // if local and global size are both positive or negative
388  section->max_index_cache
389  = (Xt_int)(section->max_index_cache
390  + (Xt_int)(section->dims[i].global_stride
391  * (Xt_int)(abs(section->dims[i].local_size)
392  - 1)));
393  }
394  int num_indices = idxsection_get_num_indices(section);
395  Xt_idxlist_init(&section->parent, &idxsection_vtable, num_indices);
396  INSTR_STOP(instr);
397  return (Xt_idxlist)section;
398 }
399 
402  Xt_idxlist dst_idxlist) {
403 
404  // intersection between an idxsection and a general idxlist:
405  //
406  // performance picture:
407  // - src_idxsection is treated as too big for elemental transforms/access
408  // - dst_idxlist is considered to be small enough (subdomain like) for elemental usage
409 
410  INSTR_DEF(instr,"idxsection_get_intersection_with_other_idxlist")
411  INSTR_START(instr);
412 
413  int num_dst_idx = xt_idxlist_get_num_indices(dst_idxlist);
414 
415  Xt_int const* dst_idx = xt_idxlist_get_indices_const(dst_idxlist);
416  int * pos;
417  int single_match_only = 0;
418  int i, j;
419 
420  for (i = 1; i < num_dst_idx; ++i)
421  if (dst_idx[i] < dst_idx[i-1])
422  break;
423 
424  Xt_int const * sorted_dst_idx;
425  Xt_int * temp_dst_idx = NULL;
426 
427  // if the destination indices are not sorted
428  if (num_dst_idx > 1 && i != num_dst_idx) {
429 
430  temp_dst_idx = xmalloc((size_t)num_dst_idx * sizeof(*temp_dst_idx));
431  memcpy(temp_dst_idx, dst_idx, (size_t)num_dst_idx * sizeof(*temp_dst_idx));
432 
433  xt_mergesort_index(temp_dst_idx, num_dst_idx, NULL, 0);
434 
435  sorted_dst_idx = temp_dst_idx;
436  } else
437  sorted_dst_idx = dst_idx;
438 
439  pos = xmalloc((size_t)num_dst_idx * sizeof(*pos));
440  int num_unmatched = idxsection_get_positions_of_indices(
441  src_idxsection, sorted_dst_idx, num_dst_idx, pos,
442  single_match_only);
443  int num_inter_idx = num_dst_idx - num_unmatched;
444  Xt_idxlist result;
445  if (num_inter_idx != 0) {
446  Xt_int *intersection = xmalloc((size_t)num_inter_idx
447  * sizeof(*intersection));
448 
449  for(i = 0, j = 0; i < num_dst_idx && j < num_inter_idx; i++) {
450  intersection[j] = sorted_dst_idx[i];
451  j += (pos[i] >= 0);
452  }
453 
454  result = xt_idxvec_new(intersection, num_inter_idx);
455  free(intersection);
456  } else {
457  result = xt_idxempty_new();
458  }
459 
460  free(temp_dst_idx);
461  free(pos);
462 
463  INSTR_STOP(instr);
464  return result;
465  // return xt_idxvec_pinned_new(intersection, num_inter_idx);
466 }
467 
470  INSTR_DEF(instr,"idxsection_get_intersection.part")
471 
472  // both lists are index section:
473 
474  Xt_idxsection idxsection_src, idxsection_dst;
475 
476  idxsection_src = (Xt_idxsection)idxlist_src;
477  idxsection_dst = (Xt_idxsection)idxlist_dst;
478 
479  if (idxsection_src->ndim != idxsection_dst->ndim ||
480  idxsection_src->global_start_index != idxsection_dst->global_start_index)
481  return xt_default_isect(idxlist_src, idxlist_dst);
482 
483  int i;
484 
485  // the size of first global dimension is irrelevant,
486  // the others have to be identically
487  for (i = 1; i < idxsection_src->ndim; ++i)
488  if (XT_INT_ABS(idxsection_src->dims[i].global_size)
489  != XT_INT_ABS(idxsection_dst->dims[i].global_size))
491  idxlist_src, idxlist_dst);
492 
494  int *local_size;
495 
496  INSTR_START(instr);
497 
498  // dimension information for the intersection
499  local_start = xmalloc((size_t)idxsection_src->ndim * sizeof(*local_start));
500  local_size = xmalloc((size_t)idxsection_src->ndim * sizeof(*local_size));
501  global_size = xmalloc((size_t)idxsection_src->ndim * sizeof(*global_size));
502 
503  // indices in an intersection have to be sorted in ascending order. therefore,
504  // local and global sizes of the intersection have to be positive
505 
506  for (i = 0; i < idxsection_src->ndim; ++i) {
507 
508  Xt_int src_start, src_end, dst_start, dst_end, local_end;
509 
510  // the start value is the minmum position in the current dimension (with positive
511  // size)
512  // in case the global size of src or dst is negative the start value has be be
513  // adjusted accordingly
514 
515  if (idxsection_src->dims[i].global_size >= 0)
516  src_start = idxsection_src->dims[i].local_start;
517  else
518  src_start = (Xt_int)(-idxsection_src->dims[i].global_size
519  - abs(idxsection_src->dims[i].local_size)
520  - idxsection_src->dims[i].local_start);
521 
522  if (idxsection_dst->dims[i].global_size >= 0)
523  dst_start = idxsection_dst->dims[i].local_start;
524  else
525  dst_start = (Xt_int)(-idxsection_dst->dims[i].global_size
526  - abs(idxsection_dst->dims[i].local_size)
527  - idxsection_dst->dims[i].local_start);
528 
529  src_end = (Xt_int)(src_start
530  + (Xt_int)abs(idxsection_src->dims[i].local_size));
531  dst_end = (Xt_int)(dst_start
532  + (Xt_int)abs(idxsection_dst->dims[i].local_size));
533 
534  local_start[i] = (src_start > dst_start)?src_start:dst_start;
535  local_end = (src_end > dst_end)?dst_end:src_end;
536 
537  if (local_end <= local_start[i]) {
538  free(global_size);
539  free(local_size);
540  free(local_start);
541  INSTR_STOP(instr);
542  return xt_idxempty_new();
543  }
544 
545  local_size[i] = (int)(local_end - local_start[i]);
546  global_size[i] = XT_INT_ABS(idxsection_src->dims[i].global_size);
547  }
548 
549  Xt_idxlist intersection
550  = xt_idxsection_new(idxsection_src->global_start_index,
551  idxsection_src->ndim, global_size,
552  local_size, local_start);
553 
554  free(global_size);
555  free(local_size);
556  free(local_start);
557 
558  INSTR_STOP(instr);
559  return intersection;
560 }
561 
562 static Xt_idxlist
564 
565  Xt_idxsection src = (Xt_idxsection)idxlist;
566 
567  int num_dimensions = src->ndim;
568 
569  Xt_idxsection idxsection = xmalloc(sizeof (*idxsection)
570  + (size_t)num_dimensions
571  * sizeof (idxsection->dims[0]));
572  *idxsection = *src;
573  idxsection->index_array_cache = NULL;
574 
575  memcpy(idxsection->dims, src->dims, (size_t)num_dimensions *
576  sizeof (src->dims[0]));
577 
578  return (Xt_idxlist)idxsection;
579 }
580 
581 static int
582 idxsection_get_num_indices(Xt_idxsection section) {
583 
584  int i;
585  long long size = 1;
586 
587  for (i = 0; i < section->ndim; ++i)
588  size *= abs(section->dims[i].local_size);
589  assert(size <= INT_MAX);
590 
591  return (int)size;
592 }
593 
594 
595 static int
597  int ndim, struct dim_desc dims[ndim])
598 {
599 
600  int abs_local_size = abs(dims[0].local_size);
601 
602  if (ndim == 1)
603  {
604  if (dims[0].global_stride > 0)
605  for (int i = 0; i < abs_local_size; ++i)
606  indices[i] = (Xt_int)(start_index + i);
607  else
608  for (int i = 0; i < abs_local_size; ++i)
609  indices[i] = (Xt_int)(start_index - i);
610  return abs_local_size;
611  }
612  else
613  {
614  int indices_written = 0, overflow = 0;
615  assert(ndim > 1);
616  for (int dim_ofs = 0; dim_ofs < abs_local_size; ++dim_ofs)
617  {
618  int indices_written_temp
620  (Xt_int)(start_index
621  + dim_ofs * dims[0].global_stride),
622  indices + indices_written,
623  ndim - 1, dims + 1);
624  overflow |= (indices_written_temp > INT_MAX - indices_written);
625  indices_written += indices_written_temp;
626  }
627  assert(!overflow);
628  return indices_written;
629  }
630 }
631 
632 static void
634  INSTR_DEF(instr,"idxsection_get_indices")
635  INSTR_START(instr);
636  Xt_idxsection section = (Xt_idxsection)idxlist;
637 
638  int num_indices = idxlist->num_indices;
639 
640  if (num_indices > 0) {
641 
642  // if the indices are already computed
643  if (section->index_array_cache != NULL) {
644  memcpy(indices, section->index_array_cache,
645  (size_t)num_indices * sizeof(*indices));
646  goto fun_exit;
647  } else
648  section->index_array_cache
649  = xmalloc((size_t)num_indices * sizeof(*(section->index_array_cache)));
650 
651  // if this routine was called by idxsection_get_indices_const
652  if (indices == NULL)
653  indices = section->index_array_cache;
654 
656  section->ndim, section->dims);
657 
658  if (section->index_array_cache != indices)
659  memcpy(section->index_array_cache, indices,
660  (size_t)num_indices * sizeof(*indices));
661  }
662  fun_exit: ;
663  INSTR_STOP(instr);
664 }
665 
666 static Xt_int const*
668 
669  Xt_idxsection idxsection = (Xt_idxsection)idxlist;
670 
671  if (idxsection->index_array_cache == NULL)
672  idxsection_get_indices(idxlist, NULL);
673 
674  return idxsection->index_array_cache;
675 }
676 
677 
678 static void
680  int * num_stripes) {
681 
682  INSTR_DEF(instr,"idxsection_get_index_stripes.part")
683 
684  Xt_idxsection section = (Xt_idxsection)idxlist;
685 
686  size_t nstripes;
687 
688  if (section->dims[section->ndim-1].local_size == 0)
689  nstripes = 0;
690  else
691  nstripes = 1;
692 
693  for (int i = 0; i < section->ndim-1; ++i)
694  nstripes *= (size_t)abs(section->dims[i].local_size);
695 
696  if (nstripes == 0) {
697  *num_stripes = (int)nstripes;
698  *stripes = NULL;
699  return;
700  }
701 
702  INSTR_START(instr);
703 
704  struct Xt_stripe *p = xmalloc(nstripes * sizeof(**stripes));
705 
706  Xt_int *curr_local_position;
707 
708  curr_local_position = xcalloc((size_t)(section->ndim-1),
709  sizeof(*curr_local_position));
710 
711  for (size_t i = 0; i < nstripes; ++i) {
712 
713  p[i].start = section->local_start_index;
714  p[i].nstrides = abs(section->dims[section->ndim-1].local_size);
715  p[i].stride = 1;
716 
717  for (int j = 0; j < section->ndim - 1; ++j)
718  p[i].start = (Xt_int)(p[i].start
719  + curr_local_position[j]
720  * section->dims[j].global_stride);
721 
722  for (int j = section->ndim - 2; j >= 0; --j)
723  if (curr_local_position[j] < abs(section->dims[j].local_size) - 1) {
724  curr_local_position[j]++;
725  break;
726  } else
727  curr_local_position[j] = 0;
728  }
729  *stripes = p;
730  *num_stripes = (int)nstripes;
731  free(curr_local_position);
732 
733  INSTR_STOP(instr);
734 }
735 
736 static int
738  Xt_int * index) {
739 
740  Xt_idxsection section = (Xt_idxsection)idxlist;
741 
742  if (position < 0) return 1;
743 
744  Xt_int temp_index;
745 
746  temp_index = section->local_start_index;
747 
748  int dim;
749  Xt_int curr_local_position;
750  long long pos = (long long)position;
751 
752  for (dim = 0; dim < section->ndim; ++dim) {
753 
754  curr_local_position = (Xt_int)(pos / (long long)section->dims[dim].local_stride);
755 
756  if (curr_local_position >= abs(section->dims[dim].local_size))
757  return 1;
758 
759  temp_index = (Xt_int)(temp_index
760  + curr_local_position
761  * section->dims[dim].global_stride);
762  /* FIXME: assert(section->dims[dim].local_stride is in [-INT_MAX,INT_MAX]) */
763  pos %= (long long)section->dims[dim].local_stride;
764  }
765 
766  *index = temp_index;
767 
768  return 0;
769 }
770 
771 static int
773  int * position) {
774 
775  INSTR_DEF(instr,"idxsection_get_position_of_index.part")
776 
777  Xt_idxsection section = (Xt_idxsection)idxlist;
778  *position = -1;
779 
780  if (index < section->min_index_cache || index > section->max_index_cache)
781  return 1;
782 
783  int retval = 1;
784 
785  INSTR_START(instr);
786 
787  // normalise index (global start of indices at 0)
788  index = (Xt_int)(index - section->global_start_index);
789 
790  int i;
791  int temp_position = 0;
792 
793  for (i = 0; i < section->ndim; ++i) {
794 
795  Xt_int abs_global_stride
796  = XT_INT_ABS(section->dims[i].global_stride);
797 
798  Xt_int curr_global_position
799  = (Xt_int)(index / abs_global_stride);
800 
801  // in case the global size is negative, we have to adjust the global position,
802  // because the ordering of indices in this dimension is inverted
803  if (section->dims[i].global_size < 0)
804  curr_global_position
805  = (Xt_int)(-section->dims[i].global_size - curr_global_position - 1);
806 
807  index = (Xt_int)(index % abs_global_stride);
808 
809  if (curr_global_position < section->dims[i].local_start)
810  goto fun_exit;
811 
812  Xt_int curr_local_position
813  = (Xt_int)(curr_global_position - section->dims[i].local_start);
814 
815  // same adjustment for local position as for the global one before
816  if (section->dims[i].local_size < 0)
817  curr_local_position
818  = (Xt_int)(-section->dims[i].local_size - curr_local_position - 1);
819 
820  if (curr_local_position >= abs(section->dims[i].local_size))
821  goto fun_exit;
822 
823  temp_position += (int)(curr_local_position * section->dims[i].local_stride);
824  }
825 
826  *position = temp_position;
827 
828  retval = 0;
829 
830  fun_exit: ;
831  INSTR_STOP(instr);
832  return retval;
833 }
834 
835 static int
837  const Xt_int selection_idx[],
838  int num_selection,
839  int positions[],
840  int single_match_only) {
841 
842  INSTR_DEF(instr,"idxsection_get_positions_of_indices_v1.part")
843 
844  if (num_selection < 1) return 0; //nothing to do
845 
846  if (num_selection == 1)
847  return idxsection_get_position_of_index(body_idxlist, *selection_idx,
848  positions);
849 
850  int num_unmatched = 0;
851 
852  if (!single_match_only) {
853  // this is the easy case, we don't care about multiple uses of the same position
854  for (int i = 0; i < num_selection; ++i)
855  num_unmatched
856  += idxsection_get_position_of_index(body_idxlist, selection_idx[i],
857  &positions[i]);
858  return num_unmatched;
859  }
860 
861  INSTR_START(instr);
862 
863  for (size_t i = 1; i < (size_t)num_selection; ++i)
864  if (selection_idx[i] < selection_idx[i-1])
865  goto unsorted;
866 
867  // indices are sorted
868  {
869  // we need an index that is different from the current one
870  Xt_int prev_index = (Xt_int)(selection_idx[0] - 1);
871 
872  for (size_t i = 0; i < (size_t)num_selection; i++) {
873 
874  Xt_int curr_index = selection_idx[i];
875 
876  if (prev_index != curr_index) {
877 
878  num_unmatched
879  += idxsection_get_position_of_index(body_idxlist, curr_index,
880  positions + i);
881  prev_index = curr_index;
882 
883  } else {
884  // for an idxsection there is a unique map from indices to positions,
885  // we got the same index again, so there is no match left:
886  positions[i] = -1;
887  num_unmatched++;
888  }
889  }
890  }
891  goto end;
892  // indices are not sorted
893 unsorted:
894  {
895  // the remaining (single_match_only) case follows:
896  idxpos_type *v = xmalloc((size_t)num_selection * sizeof(*v) );
897  for (size_t i = 0; i < (size_t)num_selection; i++) {
898  v[i].idx = selection_idx[i];
899  v[i].pos = (int)i;
900  }
901  xt_mergesort_idxpos(v, (size_t)num_selection);
902  Xt_int last_jx = (Xt_int)(v[0].idx - 1); // any index that does not equal v[0].idx will do
903  for (size_t i = 0; i < (size_t)num_selection; i++) {
904  int j = v[i].pos;
905  Xt_int jx = v[i].idx;
906  if (jx != last_jx) {
907  num_unmatched
908  += idxsection_get_position_of_index(body_idxlist, jx, &positions[j]);
909  last_jx = jx;
910  } else {
911  // for an idxsection there is a unique map from indices to positions,
912  // we got the same index again, so there is no match left:
913  positions[j] = -1;
914  num_unmatched++;
915  }
916  }
917  free(v);
918  }
919 end:
920  INSTR_STOP(instr);
921  return num_unmatched;
922 }
923 
924 static
926  const Xt_int selection_idx[],
927  int num_selection, int positions[],
928  int single_match_only) {
929 
930  INSTR_DEF(instr,"idxsection_get_positions_of_indices_v2.part")
931 
932  if (num_selection < 1) return 0; //nothing to do
933 
934  if (num_selection == 1)
935  return idxsection_get_position_of_index(body_idxlist, *selection_idx, positions);
936 
937  INSTR_START(instr);
938 
939  Xt_int * temp_selection_idx = NULL;
940  const Xt_int *restrict sorted_selection_idx;
941  int * selection_pos = NULL;
942 
943  size_t i;
944  for (i = 1; i < (size_t)num_selection; ++i)
945  if (selection_idx[i] < selection_idx[i-1])
946  goto unsorted;
947 
948  sorted_selection_idx = selection_idx;
949  goto sorted;
950 unsorted:
951  // the indices are not sorted
952  temp_selection_idx
953  = xmalloc((size_t)num_selection * sizeof(*temp_selection_idx));
954  memcpy(temp_selection_idx, selection_idx,
955  (size_t)num_selection * sizeof(*temp_selection_idx));
956  selection_pos = xmalloc((size_t)num_selection * sizeof(*selection_pos));
957 
958  xt_quicksort_index(temp_selection_idx, num_selection, selection_pos, 1);
959  sorted_selection_idx = temp_selection_idx;
960 
961 sorted: ;
962  const Xt_int *body_indices = idxsection_get_indices_const(body_idxlist);
963  size_t num_body_indices = (size_t)xt_idxlist_get_num_indices(body_idxlist);
964 
965  // Xt_int last_idx = sorted_selection_idx[0] - 1;
966  //
967  // for (i = 0, j = 0; i < num_selection && j < num_body_indices; ++i) {
968  //
969  // while(j < num_body_indices && body_indices[j] < sorted_selection_idx[i]) ++j;
970  //
971  // if (j >= num_body_indices) break;
972  //
973  // if (!single_match_only)
974  // positions[(selection_pos == NULL)?i:selection_pos[i]] =
975  // (body_indices[j] == sorted_selection_idx[i])?j:-1;
976  // else
977  // positions[selection_pos[i]] =
978  // ((last_idx == sorted_selection_idx[i]) ||
979  // (body_indices[j] != sorted_selection_idx[i]))?-1:j;
980  // }
981 
982  // the following loops are an unrolled version of the one above
983 
984  if (!single_match_only) {
985 
986  if (selection_pos == NULL) {
987  i = 0;
988  for (size_t j = 0; i < (size_t)num_selection && j < num_body_indices; ++i) {
989 
990  while(j < num_body_indices && body_indices[j] < sorted_selection_idx[i]) ++j;
991 
992  if (j >= num_body_indices) break;
993 
994  positions[i] = (body_indices[j] == sorted_selection_idx[i])?(int)j:-1;
995  }
996  } else {
997  i = 0;
998  for (size_t j = 0; i < (size_t)num_selection && j < num_body_indices; ++i) {
999 
1000  while(j < num_body_indices && body_indices[j] < sorted_selection_idx[i]) ++j;
1001 
1002  if (j >= num_body_indices) break;
1003 
1004  positions[selection_pos[i]] = (body_indices[j] == sorted_selection_idx[i])?(int)j:-1;
1005  }
1006  }
1007  } else {
1008 
1009  Xt_int last_idx = (Xt_int)(sorted_selection_idx[0] - 1);
1010 
1011  if (selection_pos == NULL) {
1012  i = 0;
1013  for (size_t j = 0; i < (size_t)num_selection && j < num_body_indices; ++i) {
1014 
1015  while(j < num_body_indices && body_indices[j] < sorted_selection_idx[i]) ++j;
1016 
1017  if (j >= num_body_indices) break;
1018 
1019  positions[i] = ((last_idx == sorted_selection_idx[i]) ||
1020  (body_indices[j] != sorted_selection_idx[i]))?-1:(int)j;
1021 
1022  last_idx = sorted_selection_idx[i];
1023  }
1024  } else {
1025  i = 0;
1026  for (size_t j = 0; i < (size_t)num_selection && j < num_body_indices; ++i) {
1027 
1028  while(j < num_body_indices && body_indices[j] < sorted_selection_idx[i]) ++j;
1029 
1030  if (j >= num_body_indices) break;
1031 
1032  positions[selection_pos[i]] = ((last_idx == sorted_selection_idx[i]) ||
1033  (body_indices[j] != sorted_selection_idx[i]))?-1:(int)j;
1034 
1035  last_idx = sorted_selection_idx[i];
1036  }
1037  }
1038  }
1039 
1040  // process indices that were not handled by the loop above
1041  if (selection_pos == NULL)
1042  for (; i < (size_t)num_selection; ++i)
1043  positions[i] = -1;
1044  else
1045  for (; i < (size_t)num_selection; ++i)
1046  positions[selection_pos[i]] = -1;
1047 
1048  free(temp_selection_idx);
1049  free(selection_pos);
1050 
1051  int num_unmatched = 0;
1052 
1053  // count the number of unmachted indices
1054  for (size_t j = 0; j < (size_t)num_selection; ++j)
1055  num_unmatched += positions[j] == -1;
1056 
1057  INSTR_STOP(instr);
1058  return num_unmatched;
1059 }
1060 
1061 static size_t
1063  int position_offset,
1064  const Xt_int indices[],
1065  size_t num_indices,
1066  int positions[],
1067  int ndim,
1068  struct dim_desc dims[ndim])
1069 {
1070  size_t num_processed = 0;
1071 
1072  Xt_int abs_global_size = XT_INT_ABS(dims[0].global_size);
1073  int abs_local_size = abs(dims[0].local_size);
1074  Xt_int abs_global_stride = XT_INT_ABS(dims[0].global_stride);
1075  Xt_int abs_local_stride = XT_INT_ABS(dims[0].local_stride);
1076 
1077  if (ndim == 1)
1078  {
1079 
1080  Xt_int curr_position;
1081 
1082  Xt_int tmp_local_start = dims[0].local_start;
1083 
1084  // we want to work on ascending indices in the lowest dimension -> have to
1085  // adjust in case of negative global size
1086  if (dims[0].global_size < 0)
1087  tmp_local_start = (Xt_int)(-dims[0].global_size - tmp_local_start -
1088  abs_local_size);
1089 
1090  Xt_int min_index = (Xt_int)(index_offset + tmp_local_start * abs_global_stride);
1091 
1092  // set all indices that are smaller than the minimum to "not found"
1093  while ((num_processed < num_indices)
1094  && (indices[num_processed] < min_index))
1095  positions[num_processed++] = -1;
1096 
1097  // if either the local or the global dimension is negative
1098  if ((dims[0].global_stride < 0) ^ (dims[0].local_stride < 0)) {
1099 
1100  // for as long as we are in the range local section of the current
1101  // global dimension
1102  while ((num_processed < num_indices) &&
1103  ((curr_position = (Xt_int)(indices[num_processed] - min_index)) <
1104  abs_local_size)) {
1105 
1106  positions[num_processed++] = position_offset
1107  + (int)(abs_local_size - curr_position - 1);
1108  }
1109  } else { // if the local and global dimension are both negative or positive
1110 
1111  // for as long as we are in the range local section of the current
1112  // global dimension
1113  while ((num_processed < num_indices) &&
1114  ((curr_position = (Xt_int)(indices[num_processed] - min_index)) <
1115  abs_local_size)) {
1116 
1117  positions[num_processed++] = position_offset + (int)curr_position;
1118  }
1119  }
1120 
1121  // for all remaining indices that are in the current global dimension but not
1122  // within the local section
1123  while ((num_processed < num_indices) &&
1124  (indices[num_processed] < index_offset + abs_global_size))
1125  positions[num_processed++] = -1;
1126 
1127  } else {
1128 
1129  assert(ndim > 1);
1130 
1131  Xt_int tmp_local_start = dims[0].local_start;
1132 
1133  // we want to work on ascending indices in the lowest dimension -> have to
1134  // adjust in case of negative global size
1135  if (dims[0].global_size < 0)
1136  tmp_local_start = (Xt_int)(-dims[0].global_size - tmp_local_start -
1137  abs_local_size);
1138 
1139  Xt_int min_index
1140  = (Xt_int)(index_offset + tmp_local_start * abs_global_stride);
1141 
1142  // set all indices that are smaller than the minimum to "not found"
1143  while ((num_processed < num_indices)
1144  && (indices[num_processed] < min_index))
1145  positions[num_processed++] = -1;
1146 
1147  // while there are indices that have not yet been processed
1148  while (num_processed < num_indices) {
1149 
1150  Xt_int curr_global_position, curr_local_position;
1151 
1152  // compute global position of the smallest index that has not yet been processed
1153  curr_global_position = (Xt_int)((indices[num_processed] - index_offset) /
1154  abs_global_stride);
1155 
1156  // if the position is outside of the range of the current dimension
1157  if (curr_global_position >= tmp_local_start + abs_local_size)
1158  break;
1159 
1160  // if either the local or the global dimension is negative
1161  if ((dims[0].global_size < 0) ^ (dims[0].local_size < 0))
1162 
1163  curr_local_position = (Xt_int)(abs_local_size - curr_global_position
1164  + tmp_local_start - 1);
1165  else // if the local and global dimension are both negative or positive
1166  curr_local_position = (Xt_int)(curr_global_position - tmp_local_start);
1167 
1168  Xt_int curr_index_offset
1169  = (Xt_int)(index_offset + curr_global_position * abs_global_stride);
1170  /* FIXME: no guarantee curr_local_position * abs_local_stride
1171  * <= INT_MAX */
1172  int position_offset_ = (int)(curr_local_position * abs_local_stride);
1173 
1175  curr_index_offset, position_offset_, indices + num_processed,
1176  num_indices - num_processed, positions + num_processed, ndim-1,
1177  dims + 1);
1178  }
1179  }
1180 
1181  return num_processed;
1182 }
1183 
1184 static int
1186  const Xt_int *restrict selection_idx,
1187  int num_selection,
1188  int *restrict positions,
1189  int single_match_only) {
1190 
1191  INSTR_DEF(instr,"idxsection_get_positions_of_indices_v3.part")
1192  INSTR_DEF(instr2,"idxsection_get_positions_of_indices_recursive")
1193 
1194  Xt_idxsection section = (Xt_idxsection)body_idxlist;
1195 
1196  if (num_selection < 1) return 0; //nothing to do
1197 
1198  if (num_selection == 1)
1199  return idxsection_get_position_of_index(body_idxlist, *selection_idx, positions);
1200 
1201  INSTR_START(instr);
1202 
1203  const Xt_int * restrict sorted_selection_idx;
1204  Xt_int *temp_selection_idx = NULL;
1205  int *sorted_positions;
1206  int *selection_pos = NULL;
1207 
1208  for (size_t i = 1; i < (size_t)num_selection; ++i)
1209  if (selection_idx[i] < selection_idx[i-1])
1210  goto unsorted_selection;
1211 
1212  sorted_selection_idx = selection_idx;
1213  sorted_positions = positions;
1214  goto sorted_selection;
1215  // if the selection is not sorted
1216 unsorted_selection:
1217  temp_selection_idx
1218  = xmalloc((size_t)num_selection * sizeof(*temp_selection_idx));
1219  sorted_positions
1220  = xmalloc((size_t)num_selection * sizeof(*sorted_positions) * 2);
1221  selection_pos = sorted_positions + num_selection;
1222  memcpy(temp_selection_idx, selection_idx,
1223  (size_t)num_selection * sizeof(*temp_selection_idx));
1224 
1225  xt_quicksort_index(temp_selection_idx, num_selection, selection_pos, 1);
1226  sorted_selection_idx = temp_selection_idx;
1227 sorted_selection:
1228 
1229  INSTR_START(instr2);
1230 
1231  size_t num_processed
1233  section->global_start_index,
1234  0, sorted_selection_idx, (size_t)num_selection,
1235  sorted_positions, section->ndim,
1236  section->dims);
1237 
1238  INSTR_STOP(instr2);
1239 
1240  // set remaining index positions to -1
1241  for (size_t i = num_processed; i < (size_t)num_selection; ++i)
1242  sorted_positions[i] = -1;
1243 
1244  // apply single match only rule
1245  if (single_match_only)
1246  for (size_t i = 1; i < num_processed; ++i)
1247  if (sorted_selection_idx[i] == sorted_selection_idx[i-1])
1248  sorted_positions[i] = -1;
1249 
1250  // convert positions if unsorted
1251  if (sorted_selection_idx != selection_idx) {
1252 
1253  for (size_t i = 0; i < (size_t)num_selection; ++i)
1254  positions[i] = sorted_positions[selection_pos[i]];
1255 
1256  free(sorted_positions);
1257  free(temp_selection_idx);
1258  }
1259 
1260  // count the number of unmached indices
1261  size_t num_unmatched = (size_t)num_selection - num_processed;
1262 
1263  for (size_t i = 0; i < num_processed; ++i)
1264  num_unmatched += positions[i] == -1;
1265 
1266  INSTR_STOP(instr);
1267 
1268  return (int)num_unmatched;
1269 }
1270 
1271 static int
1273  const Xt_int *selection_idx,
1274  int num_selection, int * positions,
1275  int single_match_only) {
1276 
1277  INSTR_DEF(instr,"idxsection_get_positions_of_indices")
1278  Xt_idxsection section = (Xt_idxsection)body_idxlist;
1279  int retval = 0;
1280 
1281 
1282  INSTR_START(instr);
1283 
1284  // if any dimension of the body index list is negative we have to use the
1285  // v3 version, because the other version cannot handle negative sizes
1286  for (int i = 0; i < section->ndim; ++i)
1287  if ((section->dims[i].local_size < 0) || (section->dims[i].global_size < 0)) {
1288  retval = idxsection_get_positions_of_indices_v3(body_idxlist, selection_idx,
1289  num_selection, positions,
1290  single_match_only);
1291  goto fun_exit;
1292  }
1293 
1294  {
1295  int num_section_indices = xt_idxlist_get_num_indices(body_idxlist);
1296 
1297  /*
1298  * if the indices are already cached or (if the caching would not
1299  * consume too much memory and the number of selection indices are
1300  * sufficient to justify the use of cached indices)
1301  */
1302  if ((section->index_array_cache != NULL) ||
1303  (((size_t)num_section_indices * sizeof(Xt_int)
1304  <= (size_t)128 * 1024U * 1024U)
1305  && ((Xt_int)num_section_indices <= 1000 * num_selection))) {
1306  retval = idxsection_get_positions_of_indices_v2(body_idxlist, selection_idx,
1307  num_selection, positions,
1308  single_match_only);
1309  goto fun_exit;
1310  }
1311  else {
1312  retval = idxsection_get_positions_of_indices_v1(body_idxlist, selection_idx,
1313  num_selection, positions,
1314  single_match_only);
1315  goto fun_exit;
1316  }
1317  }
1318 
1319  fun_exit: ;
1320  INSTR_STOP(instr);
1321  return retval;
1322 }
1323 
1324 static int
1326  int * position, int offset) {
1327 
1328  int temp_position;
1329  // we make use of the uniqueness of the index-to-position relation:
1330  if (idxsection_get_position_of_index(idxlist, index, &temp_position))
1331  return 1;
1332 
1333  if (temp_position < offset)
1334  return 1;
1335 
1336  *position = temp_position;
1337 
1338  return 0;
1339 }
1340 
1341 static Xt_int
1343 
1344  Xt_idxsection section = (Xt_idxsection)idxlist;
1345  return section->min_index_cache;
1346 }
1347 
1348 static Xt_int
1350 
1351  Xt_idxsection section = (Xt_idxsection)idxlist;
1352  return section->max_index_cache;
1353 }
1354 
1355 /*
1356  * Local Variables:
1357  * c-basic-offset: 2
1358  * coding: utf-8
1359  * indent-tabs-mode: nil
1360  * show-trailing-whitespace: t
1361  * require-trailing-newline: t
1362  * End:
1363  */
Xt_idxlist xt_default_isect(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst)
int xt_idxlist_get_num_indices(Xt_idxlist idxlist)
Definition: xt_idxlist.c:97
static const struct xt_idxlist_vtable idxsection_vtable
Xt_int * index_array_cache
struct dim_desc dims[]
#define INSTR_START(T)
Definition: instr.h:68
static MPI_Datatype dim_desc_dt
static int idxsection_get_positions_of_indices_v1(Xt_idxlist body_idxlist, const Xt_int selection_idx[], int num_selection, int positions[], int single_match_only)
add versions of standard API functions not returning on error
static int isign(int x)
static int idxsection_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
Xt_int local_stride
Xt_int min_index_cache
static size_t idxsection_get_pack_size(Xt_idxlist data, MPI_Comm comm)
static int idxsection_get_position_of_index_off(Xt_idxlist idxlist, Xt_int index, int *position, int offset)
Xt_int max_index_cache
Xt_idxlist xt_idxsection_new(Xt_int start, int num_dimensions, const Xt_int global_size[num_dimensions], const int local_size[num_dimensions], const Xt_int local_start[num_dimensions])
struct Xt_idxsection_ * Xt_idxsection
Xt_int global_stride
static void idxsection_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
int nstrides
Definition: xt_stripe.h:57
static int idxsection_get_indices_any(Xt_int start_index, Xt_int *indices, int ndim, struct dim_desc dims[ndim])
Xt_idxlist xt_idxempty_new(void)
Definition: xt_idxempty.c:165
struct Xt_idxlist_ parent
static Xt_int idxsection_get_min_index(Xt_idxlist idxlist)
static size_t idxsection_get_positions_of_indices_recursive(Xt_int index_offset, int position_offset, const Xt_int indices[], size_t num_indices, int positions[], int ndim, struct dim_desc dims[ndim])
void xt_mergesort_index(Xt_int *val, int n, int *pos, int reset_pos)
Definition: mergesort.c:195
XT_INT Xt_int
Definition: xt_core.h:68
#define xcalloc(nmemb, size)
Definition: ppm_xfuncs.h:64
static int idxsection_get_num_indices(Xt_idxsection section)
Provide non-public declarations common to all index lists.
Xt_int global_start_index
Xt_idxlist xt_idxsection_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
void xt_quicksort_index(Xt_int *v_idx, int n, int *v_pos, int reset_pos)
Definition: quicksort.c:77
static void Xt_idxlist_init(Xt_idxlist idxlist, const struct xt_idxlist_vtable *vtable, int num_indices)
Xt_int stride
Definition: xt_stripe.h:56
static int idxsection_get_positions_of_indices_v2(Xt_idxlist body_idxlist, const Xt_int selection_idx[], int num_selection, int positions[], int single_match_only)
void xt_idxsection_finalize(void)
void xt_mergesort_idxpos(idxpos_type *restrict v, size_t n)
Definition: mergesort.c:186
int local_size
quicksort declaration
static Xt_int idxsection_get_max_index(Xt_idxlist idxlist)
static Xt_int Xt_isign(Xt_int x)
static void idxsection_get_indices(Xt_idxlist idxlist, Xt_int *indices)
#define Xt_int_dt
Definition: xt_core.h:69
#define INSTR_DEF(T, S)
Definition: instr.h:66
Xt_idxlist xt_idxvec_new(const Xt_int *idxlist, int num_indices)
Definition: xt_idxvec.c:163
void(* delete)(Xt_idxlist)
static const Xt_int * idxsection_get_indices_const(Xt_idxlist idxlist)
Xt_int local_start_index
Xt_int global_size
Xt_int start
Definition: xt_stripe.h:55
static int idxsection_get_positions_of_indices_v3(Xt_idxlist body_idxlist, const Xt_int *restrict selection_idx, int num_selection, int *restrict positions, int single_match_only)
merge sort declaration
static Xt_idxlist idxsection_copy(Xt_idxlist idxlist)
Xt_idxlist xt_idxsection_get_intersection_with_other_idxlist(Xt_idxlist src_idxsection, Xt_idxlist dst_idxlist)
static void idxsection_delete(Xt_idxlist data)
static int idxsection_get_positions_of_indices(Xt_idxlist body_idxlist, Xt_int const *selection_idx, int num_selection, int *positions, int single_match_only)
static int idxsection_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int *position)
Xt_idxlist xt_idxsection_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst)
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
#define INSTR_STOP(T)
Definition: instr.h:69
index list declaration
const Xt_int * xt_idxlist_get_indices_const(Xt_idxlist idxlist)
Definition: xt_idxlist.c:107
static void idxsection_pack(Xt_idxlist data, void *buffer, int buffer_size, int *position, MPI_Comm comm)
void xt_idxsection_initialize(void)
Xt_int local_start
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
int MPI_Comm
Definition: core.h:64
utility routines for MPI