1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3 *
4 * (C) 2001 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
6 */
7
8 #include "mpiimpl.h"
9 #include "group.h"
10
11 /* -- Begin Profiling Symbol Block for routine MPI_Group_difference */
12 #if defined(HAVE_PRAGMA_WEAK)
13 #pragma weak MPI_Group_difference = PMPI_Group_difference
14 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
15 #pragma _HP_SECONDARY_DEF PMPI_Group_difference MPI_Group_difference
16 #elif defined(HAVE_PRAGMA_CRI_DUP)
17 #pragma _CRI duplicate MPI_Group_difference as PMPI_Group_difference
18 #endif
19 /* -- End Profiling Symbol Block */
20
21 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
22 the MPI routines */
23 #ifndef MPICH_MPI_FROM_PMPI
24 #undef MPI_Group_difference
25 #define MPI_Group_difference PMPI_Group_difference
26
27 #undef FUNCNAME
28 #define FUNCNAME MPIR_Group_difference_impl
29 #undef FCNAME
30 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIR_Group_difference_impl(MPID_Group * group_ptr1,MPID_Group * group_ptr2,MPID_Group ** new_group_ptr)31 int MPIR_Group_difference_impl(MPID_Group *group_ptr1, MPID_Group *group_ptr2, MPID_Group **new_group_ptr)
32 {
33 int mpi_errno = MPI_SUCCESS;
34 int size1, i, k, g1_idx, g2_idx, l1_pid, l2_pid, nnew;
35 MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GROUP_DIFFERENCE_IMPL);
36
37 MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GROUP_DIFFERENCE_IMPL);
38 /* Return a group consisting of the members of group1 that are *not*
39 in group2 */
40 size1 = group_ptr1->size;
41 /* Insure that the lpid lists are setup */
42 MPIR_Group_setup_lpid_pairs( group_ptr1, group_ptr2 );
43
44 for (i = 0; i < size1; i++)
45 group_ptr1->lrank_to_lpid[i].flag = 0;
46
47 g1_idx = group_ptr1->idx_of_first_lpid;
48 g2_idx = group_ptr2->idx_of_first_lpid;
49
50 nnew = size1;
51 while (g1_idx >= 0 && g2_idx >= 0) {
52 l1_pid = group_ptr1->lrank_to_lpid[g1_idx].lpid;
53 l2_pid = group_ptr2->lrank_to_lpid[g2_idx].lpid;
54 if (l1_pid < l2_pid) {
55 g1_idx = group_ptr1->lrank_to_lpid[g1_idx].next_lpid;
56 }
57 else if (l1_pid > l2_pid) {
58 g2_idx = group_ptr2->lrank_to_lpid[g2_idx].next_lpid;
59 }
60 else {
61 /* Equal */
62 group_ptr1->lrank_to_lpid[g1_idx].flag = 1;
63 g1_idx = group_ptr1->lrank_to_lpid[g1_idx].next_lpid;
64 g2_idx = group_ptr2->lrank_to_lpid[g2_idx].next_lpid;
65 nnew --;
66 }
67 }
68 /* Create the group */
69 if (nnew == 0) {
70 /* See 5.3.2, Group Constructors. For many group routines,
71 the standard explicitly says to return MPI_GROUP_EMPTY;
72 for others it is implied */
73 *new_group_ptr = MPID_Group_empty;
74 goto fn_exit;
75 }
76 else {
77 mpi_errno = MPIR_Group_create( nnew, new_group_ptr );
78 /* --BEGIN ERROR HANDLING-- */
79 if (mpi_errno) {
80 goto fn_fail;
81 }
82 /* --END ERROR HANDLING-- */
83 (*new_group_ptr)->rank = MPI_UNDEFINED;
84 k = 0;
85 for (i=0; i<size1; i++) {
86 if (!group_ptr1->lrank_to_lpid[i].flag) {
87 (*new_group_ptr)->lrank_to_lpid[k].lrank = k;
88 (*new_group_ptr)->lrank_to_lpid[k].lpid = group_ptr1->lrank_to_lpid[i].lpid;
89 if (i == group_ptr1->rank)
90 (*new_group_ptr)->rank = k;
91 k++;
92 }
93 }
94 /* TODO calculate is_local_dense_monotonic */
95 }
96
97
98 fn_exit:
99 MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GROUP_DIFFERENCE_IMPL);
100 return mpi_errno;
101 fn_fail:
102 goto fn_exit;
103 }
104
105
106 #endif
107
108 #undef FUNCNAME
109 #define FUNCNAME MPI_Group_difference
110 #undef FCNAME
111 #define FCNAME MPIU_QUOTE(FUNCNAME)
112
113 /*@
114
115 MPI_Group_difference - Makes a group from the difference of two groups
116
117 Input Parameters:
118 + group1 - first group (handle)
119 - group2 - second group (handle)
120
121 Output Parameter:
122 . newgroup - difference group (handle)
123
124 Notes:
125 The generated group containc the members of 'group1' that are not in 'group2'.
126
127 .N ThreadSafe
128
129 .N Fortran
130
131 .N Errors
132 .N MPI_SUCCESS
133 .N MPI_ERR_GROUP
134 .N MPI_ERR_EXHAUSTED
135
136 .seealso: MPI_Group_free
137 @*/
MPI_Group_difference(MPI_Group group1,MPI_Group group2,MPI_Group * newgroup)138 int MPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
139 {
140 int mpi_errno = MPI_SUCCESS;
141 MPID_Group *group_ptr1 = NULL;
142 MPID_Group *group_ptr2 = NULL;
143 MPID_Group *new_group_ptr;
144 MPID_MPI_STATE_DECL(MPID_STATE_MPI_GROUP_DIFFERENCE);
145
146 MPIR_ERRTEST_INITIALIZED_ORDIE();
147
148 MPIU_THREAD_CS_ENTER(ALLFUNC,);
149 MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_GROUP_DIFFERENCE);
150
151 /* Validate parameters, especially handles needing to be converted */
152 # ifdef HAVE_ERROR_CHECKING
153 {
154 MPID_BEGIN_ERROR_CHECKS;
155 {
156 MPIR_ERRTEST_GROUP(group1, mpi_errno);
157 MPIR_ERRTEST_GROUP(group2, mpi_errno);
158 }
159 MPID_END_ERROR_CHECKS;
160 }
161 # endif
162
163 /* Convert MPI object handles to object pointers */
164 MPID_Group_get_ptr( group1, group_ptr1 );
165 MPID_Group_get_ptr( group2, group_ptr2 );
166
167 /* Validate parameters and objects (post conversion) */
168 # ifdef HAVE_ERROR_CHECKING
169 {
170 MPID_BEGIN_ERROR_CHECKS;
171 {
172 /* Validate group_ptr */
173 MPID_Group_valid_ptr( group_ptr1, mpi_errno );
174 MPID_Group_valid_ptr( group_ptr2, mpi_errno );
175 /* If either group_ptr is not valid, it will be reset to null */
176 if (mpi_errno) goto fn_fail;
177 }
178 MPID_END_ERROR_CHECKS;
179 }
180 # endif /* HAVE_ERROR_CHECKING */
181
182 /* ... body of routine ... */
183
184 mpi_errno = MPIR_Group_difference_impl(group_ptr1, group_ptr2, &new_group_ptr);
185 if (mpi_errno) goto fn_fail;
186
187 MPIU_OBJ_PUBLISH_HANDLE(*newgroup, new_group_ptr->handle);
188
189 /* ... end of body of routine ... */
190
191 fn_exit:
192 MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_GROUP_DIFFERENCE);
193 MPIU_THREAD_CS_EXIT(ALLFUNC,);
194 return mpi_errno;
195
196 fn_fail:
197 /* --BEGIN ERROR HANDLING-- */
198 # ifdef HAVE_ERROR_CHECKING
199 {
200 mpi_errno = MPIR_Err_create_code(
201 mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_group_difference",
202 "**mpi_group_difference %G %G %p", group1, group2, newgroup);
203 }
204 # endif
205 mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno );
206 goto fn_exit;
207 /* --END ERROR HANDLING-- */
208 }
209