1 #if COMPILATION// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;-*-
2 OMPI_CXX=$CXX mpic++ $0 -o $0x -lboost_serialization&&mpirun --oversubscribe -n 4 $0x&&rm $0x;exit
3 #endif
4 // © Alfredo A. Correa 2018-2020
5
6 #ifndef MPI3_GROUP_HPP
7 #define MPI3_GROUP_HPP
8
9 #include "detail/equality.hpp"
10
11 #include "../mpi3/error.hpp"
12
13 #include "../mpi3/detail/iterator_traits.hpp"
14 #include "../mpi3/detail/call.hpp"
15
16 #include<cassert>
17
18 #define OMPI_SKIP_MPICXX 1 // https://github.com/open-mpi/ompi/issues/5157
19 #include<mpi.h>
20
21 namespace boost{
22 namespace mpi3{
23
24 //class communicator;
25 //template<class T = void> struct window;
26
27 class group{
28 MPI_Group impl_ = MPI_GROUP_EMPTY;
29 public:
30 friend class communicator;
31 template<class T> friend struct window;
operator &()32 MPI_Group operator&(){return impl_;}
get()33 MPI_Group& get(){return impl_;}
34 // std::pointer_traits<MPI_Group>::element_type const* operator&() const{return impl_;} // this doesn't work because in mpich MPI_Group is not a pointer type
35 group() = default;
group(group && other)36 group(group&& other) noexcept : impl_{std::exchange(other.impl_, MPI_GROUP_EMPTY)}{}
group(group const & other)37 group(group const& other){MPI_(Group_excl)(other.impl_, 0, nullptr, &impl_);}
38 // explicit group(communicator const& c);//{MPI_Comm_group(c.impl_, &impl_);}
39 // explicit group(window<> const& w);
swap(group & other)40 void swap(group& other) noexcept{std::swap(impl_, other.impl_);}
operator =(group other)41 group& operator=(group other) noexcept{swap(other); return *this;}
clear()42 void clear(){
43 if(impl_ != MPI_GROUP_EMPTY) MPI_(Group_free)(&impl_);
44 impl_ = MPI_GROUP_EMPTY;
45 }
~group()46 ~group(){if(impl_ != MPI_GROUP_EMPTY) MPI_(Group_free)(&impl_);}
include(std::initializer_list<int> il)47 group include(std::initializer_list<int> il){
48 group ret; MPI_(Group_incl)(impl_, il.size(), il.begin(), &ret.impl_); return ret;
49 }
exclude(std::initializer_list<int> il)50 group exclude(std::initializer_list<int> il){
51 group ret; MPI_(Group_excl)(impl_, il.size(), il.begin(), &ret.impl_); return ret;
52 }
rank() const53 int rank() const{int rank = -1; MPI_(Group_rank)(impl_, &rank); return rank;}
root() const54 bool root() const{assert(not empty()); return rank() == 0;}
size() const55 int size() const{int size=-1; MPI_(Group_size)(impl_, &size); return size;}
sliced(int first,int last,int stride=1) const56 group sliced(int first, int last, int stride = 1) const{
57 int ranges[][3] = {{first, last - 1, stride}};
58 group ret; MPI_(Group_range_incl)(impl_, 1, ranges, &ret.impl_); return ret;
59 }
empty() const60 bool empty() const{return size()==0;}
compare(group const & self,group const & other)61 friend auto compare(group const& self, group const& other){
62 int result; MPI_(Group_compare)(self.impl_, other.impl_, &result);
63 return static_cast<mpi3::detail::equality>(result);
64 }
operator ==(group const & other) const65 bool operator==(group const& other) const{
66 auto e=compare(*this, other);
67 return e == mpi3::detail::identical or e == mpi3::detail::congruent;
68 }
operator !=(group const & other) const69 bool operator!=(group const& other) const{return not operator==(other);}
is_permutation(group const & self,group const & other)70 bool friend is_permutation(group const& self, group const& other){
71 return compare(self, other) != mpi3::detail::unequal;
72 }
set_intersection(group const & self,group const & other)73 friend group set_intersection(group const& self, group const& other){
74 group ret; MPI_(Group_intersection)(self.impl_, other.impl_, &ret.impl_); return ret;
75 }
set_difference(group const & self,group const & other)76 friend group set_difference(group const& self, group const& other){
77 group ret; MPI_(Group_difference)(self.impl_, other.impl_, &ret.impl_); return ret;
78 }
set_union(group const & self,group const & other)79 friend group set_union(group const& self, group const& other){
80 group ret; MPI_(Group_union)(self.impl_, other.impl_, &ret.impl_); return ret;
81 }
translate_rank(int rank,group const & other) const82 int translate_rank(int rank, group const& other) const{
83 int out; MPI_(Group_translate_ranks)(impl_, 1, &rank, other.impl_, &out); return out;
84 }
85 };
86
87 }}
88
89 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90
91 #if not __INCLUDE_LEVEL__ // def _TEST_MPI3_GROUP
92
93 #include "../mpi3/main.hpp"
94
95 #include<iostream>
96
97 using std::cout;
98 namespace mpi3 = boost::mpi3;
99
main(int,char * [],mpi3::communicator world)100 int mpi3::main(int, char*[], mpi3::communicator world){
101
102 mpi3::communicator w1 = world;
103 assert( w1.size() == world.size() );
104 assert( w1.rank() == world.rank() );
105
106 mpi3::group g1{w1};
107 {
108 mpi3::group g2 = g1;
109 assert( g1 == g2 );
110 }
111 assert( g1.rank() == w1.rank() );
112
113 mpi3::communicator w2 = w1.create(g1);
114 assert( w2.size() == w1.size() );
115 assert( w2.rank() == w1.rank() );
116 assert( w2.rank() == world.rank() );
117
118 return 0;
119 }
120
121 #endif
122 #endif
123
124
125