Yet Another eXchange Tool  0.9.0
xt_idxlist_collection.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 <stdlib.h>
51 #include <stdio.h>
52 #include <assert.h>
53 #include <string.h>
54 
55 #include "mpi.h"
56 
57 #include "xt/xt_core.h"
58 #include "xt/xt_idxlist.h"
59 #include "xt_idxlist_internal.h"
62 #include "xt/xt_idxempty.h"
63 #include "xt/xt_mpi.h"
64 #include "xt_idxlist_unpack.h"
65 #include "xt_stripe_util.h"
66 #include "core/core.h"
67 #include "core/ppm_xfuncs.h"
68 #include "ensure_array_size.h"
69 
70 static void
72 
73 static size_t
75 
76 static void
77 idxlist_collection_pack(Xt_idxlist data, void *buffer, int buffer_size,
78  int *position, MPI_Comm comm);
79 
80 static Xt_idxlist
82 
83 static void
85 
86 static const Xt_int *
88 
89 static void
91  struct Xt_stripe ** stripes,
92  int * num_stripes);
93 
94 static int
96  Xt_int * index);
97 
98 static int
100  int * position);
101 
102 static int
104  int * position, int offset);
105 
106 static Xt_int
108 
109 static Xt_int
111 
112 static const struct xt_idxlist_vtable idxlist_collection_vtable = {
114  .get_pack_size = idxlist_collection_get_pack_size,
115  .pack = idxlist_collection_pack,
116  .copy = idxlist_collection_copy,
117  .get_indices = idxlist_collection_get_indices,
118  .get_indices_const = idxlist_collection_get_indices_const,
119  .get_index_stripes = idxlist_collection_get_index_stripes,
120  .get_index_at_position = idxlist_collection_get_index_at_position,
121  .get_indices_at_positions = NULL,
122  .get_position_of_index = idxlist_collection_get_position_of_index,
123  .get_positions_of_indices = NULL,
124  .get_position_of_index_off = idxlist_collection_get_position_of_index_off,
125  .get_positions_of_indices_off = NULL,
126  .get_min_index = idxlist_collection_get_min_index,
127  .get_max_index = idxlist_collection_get_max_index,
128  .get_bounding_box = NULL,
129  .idxlist_pack_code = COLLECTION,
130 };
131 
133 
135 
136  struct Xt_idxlist_ parent;
137 
139 
142 };
143 
145 xt_idxlist_collection_new(Xt_idxlist *idxlists, int num_idxlists) {
146  // ensure that yaxt is initialized
147  assert(xt_initialized());
148 
149  Xt_idxlist result;
150  if (num_idxlists > 1)
151  {
152  Xt_idxlist_collection collectionlist
153  = xmalloc(sizeof (*collectionlist)
154  + (size_t)num_idxlists * sizeof (collectionlist->idxlists[0]));
155 
156  collectionlist->num_idxlists = num_idxlists;
157  collectionlist->index_array_cache = NULL;
158 
159  long long num_indices = 0;
160  for (int i = 0; i < num_idxlists; ++i)
161  {
162  collectionlist->idxlists[i] = xt_idxlist_copy(idxlists[i]);
163  num_indices += idxlists[i]->num_indices;
164  }
165 
166  assert(num_indices <= INT_MAX);
168  (int)num_indices);
169 
170  result = (Xt_idxlist)collectionlist;
171  }
172  else if (num_idxlists == 1)
173  result = xt_idxlist_copy(idxlists[0]);
174  else /* num_idxlists == 0 */
175  result = xt_idxempty_new();
176  return result;
177 }
178 
179 static void
181 
182  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)data;
183 
184  int num_lists = collectionlist->num_idxlists;
185  for (int i = 0; i < num_lists; ++i)
186  xt_idxlist_delete(collectionlist->idxlists[i]);
187 
188  free(collectionlist->index_array_cache);
189  free(collectionlist);
190 }
191 
192 static size_t
194 
195  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)data;
196 
197  int size_header, num_lists = collectionlist->num_idxlists;
198  size_t size_idxlists = 0;
199 
200  xt_mpi_call(MPI_Pack_size(2, MPI_INT, comm, &size_header), comm);
201 
202  for (int i = 0; i < num_lists; ++i)
203  size_idxlists
204  += xt_idxlist_get_pack_size(collectionlist->idxlists[i], comm);
205 
206  return (size_t)size_header + size_idxlists;
207 }
208 
209 static void
210 idxlist_collection_pack(Xt_idxlist data, void *buffer, int buffer_size,
211  int *position, MPI_Comm comm) {
212 
213  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)data;
214  int num_lists = collectionlist->num_idxlists;
215  int header[2] = { COLLECTION, num_lists };
216 
217  xt_mpi_call(MPI_Pack(header, 2, MPI_INT, buffer,
218  buffer_size, position, comm), comm);
219 
220  for (int i = 0; i < num_lists; ++i)
221  xt_idxlist_pack(collectionlist->idxlists[i], buffer, buffer_size,
222  position, comm);
223 }
224 
226 xt_idxlist_collection_unpack(void *buffer, int buffer_size, int *position,
227  MPI_Comm comm) {
228 
229  int num_lists;
230  xt_mpi_call(MPI_Unpack(buffer, buffer_size, position,
231  &num_lists, 1, MPI_INT, comm), comm);
232 
233  Xt_idxlist_collection collectionlist
234  = xmalloc(sizeof (*collectionlist)
235  + (size_t)num_lists * sizeof (collectionlist->idxlists[0]));
236 
237  collectionlist->index_array_cache = NULL;
238  collectionlist->num_idxlists = num_lists;
239 
240  long long num_indices = 0;
241  for (int i = 0; i < num_lists; ++i) {
242  collectionlist->idxlists[i] = xt_idxlist_unpack(buffer, buffer_size,
243  position, comm);
244  num_indices += collectionlist->idxlists[i]->num_indices;
245  }
246 
247  assert(num_indices <= INT_MAX);
249  (int)num_indices);
250  return (Xt_idxlist)collectionlist;
251 }
252 
255  Xt_idxlist XT_UNUSED(idxlist_dst)) {
256 
257  return NULL;
258 }
259 
260 static Xt_idxlist
262 
263  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
264 
265  return xt_idxlist_collection_new(collectionlist->idxlists,
266  collectionlist->num_idxlists);
267 }
268 
269 static void
271 
272  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
274  int offlist = 0, num_lists = collectionlist->num_idxlists;
275 
276  for (int i = 0; i < num_lists; ++i) {
277 
278  xt_idxlist_get_indices(collectionlist->idxlists[i], indices+offlist);
279  offlist += xt_idxlist_get_num_indices(collectionlist->idxlists[i]);
280  }
281 }
282 
283 static const Xt_int *
285 
286  Xt_idxlist_collection collection = (Xt_idxlist_collection)idxlist;
287 
288  if (collection->index_array_cache) return collection->index_array_cache;
289 
290  unsigned num_indices = (unsigned)idxlist->num_indices;
291 
292  Xt_int *tmp_index_array
293  = xmalloc(num_indices * sizeof (collection->index_array_cache[0]));
294 
295  idxlist_collection_get_indices(idxlist, tmp_index_array);
296 
297  collection->index_array_cache = tmp_index_array;
298 
299  return collection->index_array_cache;
300 }
301 
302 
303 static void
305  struct Xt_stripe ** stripes,
306  int * num_stripes) {
307 
308  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
309 
310  struct Xt_stripe * temp_stripes = NULL;
311  size_t temp_stripes_array_size = 0;
312  int num_temp_stripes = 0;
313 
314  xt_idxlist_get_index_stripes(collectionlist->idxlists[0], &temp_stripes,
315  &num_temp_stripes);
316  temp_stripes_array_size = (size_t)num_temp_stripes;
317 
318  struct Xt_stripe * curr_stripes = NULL;
319  int curr_num_stripes = 0, num_lists = collectionlist->num_idxlists;
320  for (int i = 1; i < num_lists; ++i) {
321 
322 
324  &curr_stripes,
325  &curr_num_stripes);
326 
327  ENSURE_ARRAY_SIZE(temp_stripes, temp_stripes_array_size,
328  num_temp_stripes + curr_num_stripes);
329 
330  curr_num_stripes
331  = (int)xt_stripes_merge_copy((size_t)curr_num_stripes,
332  temp_stripes + num_temp_stripes,
333  curr_stripes,
334  num_temp_stripes > 0);
335 
336  num_temp_stripes += curr_num_stripes;
337  }
338 
339  free(curr_stripes);
340 
341  *stripes = xrealloc(temp_stripes,
342  (size_t)num_temp_stripes * sizeof(*temp_stripes));
343  *num_stripes = num_temp_stripes;
344 }
345 
346 static int
348  Xt_int * index) {
349 
350  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
351  int num_lists = collectionlist->num_idxlists;
352 
353  for (int i = 0; i < num_lists; ++i) {
354  int n = xt_idxlist_get_num_indices(collectionlist->idxlists[i]);
355  if (position >= n)
356  position -= n;
357  else {
358  return xt_idxlist_get_index_at_position(collectionlist->idxlists[i],
359  position, index);
360  }
361  }
362  return 1;
363 
364 }
365 
366 static int
368  int * position, int offset) {
369 
370  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
371 
372  int curr_num_indices = 0;
373 
374  int idxlist_offsets = 0;
375 
376  assert(offset >= 0);
377 
378  int i = 0, num_lists = collectionlist->num_idxlists;
379 
380  do {
381  idxlist_offsets += curr_num_indices;
382  curr_num_indices = xt_idxlist_get_num_indices(collectionlist->idxlists[i]);
383  } while (idxlist_offsets + curr_num_indices <= offset && ++i < num_lists);
384 
385  offset -= idxlist_offsets;
386 
387  for (;i < num_lists; ++i)
388  if (!xt_idxlist_get_position_of_index_off(collectionlist->idxlists[i],
389  index, position, offset)) {
390  *position += idxlist_offsets;
391  return 0;
392  } else {
393  idxlist_offsets
394  += xt_idxlist_get_num_indices(collectionlist->idxlists[i]);
395  offset = 0;
396  }
397 
398  return 1;
399 }
400 
401 static int
403  int * position) {
404 
405  return idxlist_collection_get_position_of_index_off(idxlist, index,
406  position, 0);
407 }
408 
409 static Xt_int
411 
412  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
413 
414  int num_lists = collectionlist->num_idxlists;
415  assert(num_lists > 0);
416 
417  Xt_int tmp_min, min = xt_idxlist_get_min_index(collectionlist->idxlists[0]);
418 
419  for (int i = 1; i < num_lists; ++i)
420  if ((tmp_min = xt_idxlist_get_min_index(collectionlist->idxlists[i])) < min)
421  min = tmp_min;
422 
423  return min;
424 }
425 
426 static Xt_int
428 
429  Xt_idxlist_collection collectionlist = (Xt_idxlist_collection)idxlist;
430 
431  int num_lists = collectionlist->num_idxlists;
432  assert(num_lists > 0);
433 
434  Xt_int tmp_max, max = xt_idxlist_get_max_index(collectionlist->idxlists[0]);
435 
436  for (int i = 1; i < num_lists; ++i)
437  if ((tmp_max = xt_idxlist_get_max_index(collectionlist->idxlists[i])) > max)
438  max = tmp_max;
439 
440  return max;
441 }
442 
443 /*
444  * Local Variables:
445  * c-basic-offset: 2
446  * coding: utf-8
447  * indent-tabs-mode: nil
448  * show-trailing-whitespace: t
449  * require-trailing-newline: t
450  * End:
451  */
int MPI_Comm
Definition: core.h:64
#define XT_UNUSED(x)
Definition: core.h:84
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
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
void(* delete)(Xt_idxlist)
base definitions header file
int xt_initialized(void)
Definition: xt_init.c:107
XT_INT Xt_int
Definition: xt_core.h:68
struct Xt_idxlist_ * Xt_idxlist
Definition: xt_core.h:80
Xt_idxlist xt_idxempty_new(void)
Definition: xt_idxempty.c:165
void xt_idxlist_get_index_stripes_keep_buf(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
Definition: xt_idxlist.c:127
index list declaration
int xt_idxlist_get_num_indices(Xt_idxlist idxlist)
Definition: xt_idxlist.c:98
Xt_idxlist xt_idxlist_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
Xt_int xt_idxlist_get_min_index(Xt_idxlist idxlist)
Definition: xt_idxlist.c:307
int xt_idxlist_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
Definition: xt_idxlist.c:158
Xt_int xt_idxlist_get_max_index(Xt_idxlist idxlist)
Definition: xt_idxlist.c:312
void xt_idxlist_get_indices(Xt_idxlist idxlist, Xt_int *indices)
Definition: xt_idxlist.c:102
int xt_idxlist_get_position_of_index_off(Xt_idxlist idxlist, Xt_int index, int *position, int offset)
Definition: xt_idxlist.c:264
void xt_idxlist_pack(Xt_idxlist idxlist, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition: xt_idxlist.c:85
size_t xt_idxlist_get_pack_size(Xt_idxlist idxlist, MPI_Comm comm)
Definition: xt_idxlist.c:79
void xt_idxlist_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
Definition: xt_idxlist.c:118
Xt_idxlist xt_idxlist_copy(Xt_idxlist idxlist)
Definition: xt_idxlist.c:93
void xt_idxlist_delete(Xt_idxlist idxlist)
Definition: xt_idxlist.c:74
Xt_idxlist xt_idxlist_collection_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
static void idxlist_collection_get_indices(Xt_idxlist idxlist, Xt_int *indices)
Xt_idxlist xt_idxlist_collection_get_intersection(Xt_idxlist XT_UNUSED(idxlist_src), Xt_idxlist XT_UNUSED(idxlist_dst))
static int idxlist_collection_get_position_of_index_off(Xt_idxlist idxlist, Xt_int index, int *position, int offset)
static int idxlist_collection_get_position_of_index(Xt_idxlist idxlist, Xt_int index, int *position)
static void idxlist_collection_delete(Xt_idxlist data)
struct Xt_idxlist_collection_ * Xt_idxlist_collection
static Xt_idxlist idxlist_collection_copy(Xt_idxlist idxlist)
static Xt_int idxlist_collection_get_max_index(Xt_idxlist idxlist)
static size_t idxlist_collection_get_pack_size(Xt_idxlist data, MPI_Comm comm)
static Xt_int idxlist_collection_get_min_index(Xt_idxlist idxlist)
static const struct xt_idxlist_vtable idxlist_collection_vtable
static int idxlist_collection_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
static void idxlist_collection_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
static void idxlist_collection_pack(Xt_idxlist data, void *buffer, int buffer_size, int *position, MPI_Comm comm)
static const Xt_int * idxlist_collection_get_indices_const(Xt_idxlist idxlist)
Xt_idxlist xt_idxlist_collection_new(Xt_idxlist *idxlists, int num_idxlists)
Provide non-public declarations common to all index lists.
static void Xt_idxlist_init(Xt_idxlist idxlist, const struct xt_idxlist_vtable *vtable, int num_indices)
@ COLLECTION
utility routines for MPI
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
size_t xt_stripes_merge_copy(size_t num_stripes, struct Xt_stripe *stripes_dst, const struct Xt_stripe *stripes_src, bool lookback)
Definition: xt_stripe.c:122