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