1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpiimpl.h"
7 
8 /* -- Begin Profiling Symbol Block for routine MPI_Graph_neighbors_count */
9 #if defined(HAVE_PRAGMA_WEAK)
10 #pragma weak MPI_Graph_neighbors_count = PMPI_Graph_neighbors_count
11 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
12 #pragma _HP_SECONDARY_DEF PMPI_Graph_neighbors_count  MPI_Graph_neighbors_count
13 #elif defined(HAVE_PRAGMA_CRI_DUP)
14 #pragma _CRI duplicate MPI_Graph_neighbors_count as PMPI_Graph_neighbors_count
15 #elif defined(HAVE_WEAK_ATTRIBUTE)
16 int MPI_Graph_neighbors_count(MPI_Comm comm, int rank, int *nneighbors)
17     __attribute__ ((weak, alias("PMPI_Graph_neighbors_count")));
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_Graph_neighbors_count
25 #define MPI_Graph_neighbors_count PMPI_Graph_neighbors_count
26 
MPIR_Graph_neighbors_count_impl(MPIR_Comm * comm_ptr,int rank,int * nneighbors)27 int MPIR_Graph_neighbors_count_impl(MPIR_Comm * comm_ptr, int rank, int *nneighbors)
28 {
29     int mpi_errno = MPI_SUCCESS;
30     MPIR_Topology *graph_ptr;
31 
32     graph_ptr = MPIR_Topology_get(comm_ptr);
33 
34     MPIR_ERR_CHKANDJUMP((!graph_ptr ||
35                          graph_ptr->kind != MPI_GRAPH), mpi_errno, MPI_ERR_TOPOLOGY,
36                         "**notgraphtopo");
37     MPIR_ERR_CHKANDJUMP2((rank < 0 ||
38                           rank >= graph_ptr->topo.graph.nnodes), mpi_errno, MPI_ERR_RANK, "**rank",
39                          "**rank %d %d", rank, graph_ptr->topo.graph.nnodes);
40 
41     if (rank == 0)
42         *nneighbors = graph_ptr->topo.graph.index[rank];
43     else
44         *nneighbors = graph_ptr->topo.graph.index[rank] - graph_ptr->topo.graph.index[rank - 1];
45 
46   fn_exit:
47     return mpi_errno;
48   fn_fail:
49     goto fn_exit;
50 }
51 
52 #endif
53 
54 
55 /*@
56 MPI_Graph_neighbors_count - Returns the number of neighbors of a node
57                             associated with a graph topology
58 
59 Input Parameters:
60 + comm - communicator with graph topology (handle)
61 - rank - rank of process in group of 'comm' (integer)
62 
63 Output Parameters:
64 . nneighbors - number of neighbors of specified process (integer)
65 
66 .N SignalSafe
67 
68 .N Fortran
69 
70 .N Errors
71 .N MPI_SUCCESS
72 .N MPI_ERR_TOPOLOGY
73 .N MPI_ERR_COMM
74 .N MPI_ERR_ARG
75 .N MPI_ERR_RANK
76 @*/
MPI_Graph_neighbors_count(MPI_Comm comm,int rank,int * nneighbors)77 int MPI_Graph_neighbors_count(MPI_Comm comm, int rank, int *nneighbors)
78 {
79     int mpi_errno = MPI_SUCCESS;
80     MPIR_Comm *comm_ptr = NULL;
81     MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GRAPH_NEIGHBORS_COUNT);
82 
83     MPIR_ERRTEST_INITIALIZED_ORDIE();
84     /* Note that this routine does not require a CS_ENTER/EXIT */
85     MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GRAPH_NEIGHBORS_COUNT);
86 
87     /* Validate parameters, especially handles needing to be converted */
88 #ifdef HAVE_ERROR_CHECKING
89     {
90         MPID_BEGIN_ERROR_CHECKS;
91         {
92             MPIR_ERRTEST_COMM(comm, mpi_errno);
93         }
94         MPID_END_ERROR_CHECKS;
95     }
96 #endif
97 
98     /* Convert MPI object handles to object pointers */
99     MPIR_Comm_get_ptr(comm, comm_ptr);
100 
101     /* Validate parameters and objects (post conversion) */
102 #ifdef HAVE_ERROR_CHECKING
103     {
104         MPID_BEGIN_ERROR_CHECKS;
105         {
106             /* Validate comm_ptr */
107             MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, TRUE);
108             if (mpi_errno)
109                 goto fn_fail;
110             MPIR_ERRTEST_ARGNULL(nneighbors, "nneighbors", mpi_errno);
111             /* If comm_ptr is not value, it will be reset to null */
112         }
113         MPID_END_ERROR_CHECKS;
114     }
115 #endif /* HAVE_ERROR_CHECKING */
116 
117     /* ... body of routine ...  */
118 
119     mpi_errno = MPIR_Graph_neighbors_count_impl(comm_ptr, rank, nneighbors);
120     MPIR_ERR_CHECK(mpi_errno);
121 
122     /* ... end of body of routine ... */
123 
124   fn_exit:
125     MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GRAPH_NEIGHBORS_COUNT);
126     return mpi_errno;
127 
128   fn_fail:
129     /* --BEGIN ERROR HANDLING-- */
130 #ifdef HAVE_ERROR_CHECKING
131     {
132         mpi_errno =
133             MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER,
134                                  "**mpi_graph_neighbors_count",
135                                  "**mpi_graph_neighbors_count %C %d %p", comm, rank, nneighbors);
136     }
137 #endif
138     mpi_errno = MPIR_Err_return_comm(comm_ptr, __func__, mpi_errno);
139     goto fn_exit;
140     /* --END ERROR HANDLING-- */
141 }
142