1 // Copyright Alain Miniussi 2014.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // Authors: Alain Miniussi
7
8 #include <boost/mpi/detail/offsets.hpp>
9 #include <boost/mpi/detail/antiques.hpp>
10
11 namespace boost { namespace mpi {
12 namespace detail {
13
14 // Convert a sequence of sizes [S0..Sn] to a sequence displacement
15 // [O0..On] where O[0] = 0 and O[k+1] = O[k]+S[k].
16 void
sizes2offsets(int const * sizes,int * offsets,int n)17 sizes2offsets(int const* sizes, int* offsets, int n)
18 {
19 offsets[0] = 0;
20 for(int i = 1; i < n; ++i) {
21 offsets[i] = offsets[i-1] + sizes[i-1];
22 }
23 }
24
25 // Convert a sequence of sizes [S0..Sn] to a sequence displacement
26 // [O0..On] where O[0] = 0 and O[k+1] = O[k]+S[k].
27 void
sizes2offsets(std::vector<int> const & sizes,std::vector<int> & offsets)28 sizes2offsets(std::vector<int> const& sizes, std::vector<int>& offsets)
29 {
30 int sz = sizes.size();
31 offsets.resize(sz);
32 sizes2offsets(c_data(sizes), c_data(offsets), sz);
33 }
34
35 // Given a sequence of sizes (typically the number of records dispatched
36 // to each process in a scater) and a sequence of displacements (typically the
37 // slot index at with those record starts), convert the later to a number
38 // of skipped slots.
39 void
offsets2skipped(int const * sizes,int const * offsets,int * skipped,int n)40 offsets2skipped(int const* sizes, int const* offsets, int* skipped, int n)
41 {
42 skipped[0] = 0;
43 for(int i = 1; i < n; ++i) {
44 skipped[i] -= offsets[i-1] + sizes[i-1];
45 }
46 }
47
48 // Reconstruct offsets from sizes assuming no padding.
49 // Only takes place if on the root process and if
50 // displs are not already provided.
51 // If memory was allocated, returns a pointer to it
52 // otherwise null.
53 int*
make_offsets(communicator const & comm,int const * sizes,int const * displs,int root)54 make_offsets(communicator const& comm, int const* sizes, int const* displs, int root)
55 {
56 if (root == -1 || root == comm.rank()) {
57 assert(sizes);
58 if (!displs) {
59 int nproc = comm.size();
60 int* offsets = new int[nproc];
61 displs = offsets;
62 sizes2offsets(sizes, offsets, nproc);
63 return offsets;
64 } else {
65 return 0;
66 }
67 } else {
68 return 0;
69 }
70 }
71
72 // Reconstruct skip slots from sizes and offsets.
73 // Only takes place if on the root process and if
74 // displs are provided.
75 // If memory was allocated, returns a pointer to it
76 // otherwise null.
77 int*
make_skipped_slots(communicator const & comm,int const * sizes,int const * displs,int root)78 make_skipped_slots(communicator const& comm, int const* sizes, int const* displs, int root)
79 {
80 if (root == -1 || root == comm.rank()) {
81 assert(sizes);
82 if (displs) {
83 int nproc = comm.size();
84 int* skipped = new int[nproc];
85 std::copy(displs, displs+nproc, skipped);
86 offsets2skipped(sizes, displs, skipped, nproc);
87 return skipped;
88 } else {
89 return 0;
90 }
91 } else {
92 return 0;
93 }
94 }
95 }
96 }}
97