#define LG_FREE_WORK \
{ \
GrB_free (&frontier); \
}
#define LG_FREE_ALL \
{ \
LG_FREE_WORK ; \
GrB_free (&l_parent); \
GrB_free (&l_level); \
}
#include "LG_internal.h"
#ifdef LG_BFS_EXTENDED
int LG_BreadthFirstSearch_vanilla_Extended
(
GrB_Vector *level,
GrB_Vector *parent,
const LAGraph_Graph G,
GrB_Index src,
int64_t max_level, int64_t dest, char *msg
)
#else
int LG_BreadthFirstSearch_vanilla
(
GrB_Vector *level,
GrB_Vector *parent,
const LAGraph_Graph G,
GrB_Index src,
char *msg
)
#endif
{
LG_CLEAR_MSG ;
GrB_Vector frontier = NULL; GrB_Vector l_parent = NULL; GrB_Vector l_level = NULL;
bool compute_level = (level != NULL);
bool compute_parent = (parent != NULL);
if (compute_level ) (*level ) = NULL;
if (compute_parent) (*parent) = NULL;
LG_ASSERT_MSG (compute_level || compute_parent, GrB_NULL_POINTER,
"either level or parent must be non-NULL") ;
LG_TRY (LAGraph_CheckGraph (G, msg)) ;
GrB_Matrix A = G->A ;
GrB_Index n;
GRB_TRY( GrB_Matrix_nrows (&n, A) );
LG_ASSERT_MSG (src < n, GrB_INVALID_INDEX, "invalid source node") ;
GrB_Type int_type = (n > INT32_MAX) ? GrB_INT64 : GrB_INT32 ;
GrB_BinaryOp
second_op = (n > INT32_MAX) ? GrB_SECOND_INT64 : GrB_SECOND_INT32 ;
GrB_Semiring semiring = NULL;
GrB_IndexUnaryOp ramp = NULL ;
if (compute_parent)
{
GRB_TRY (GrB_Vector_new(&l_parent, int_type, n)) ;
semiring = (n > INT32_MAX) ?
GrB_MIN_FIRST_SEMIRING_INT64 : GrB_MIN_FIRST_SEMIRING_INT32;
GRB_TRY (GrB_Vector_new(&frontier, int_type, n)) ;
GRB_TRY (GrB_Vector_setElement(frontier, src, src)) ;
ramp = (n > INT32_MAX) ? GrB_ROWINDEX_INT64 : GrB_ROWINDEX_INT32 ;
}
else
{
semiring = LAGraph_any_one_bool ;
GRB_TRY (GrB_Vector_new(&frontier, GrB_BOOL, n)) ;
GRB_TRY (GrB_Vector_setElement(frontier, true, src)) ;
}
if (compute_level)
{
GRB_TRY (GrB_Vector_new(&l_level, int_type, n)) ;
}
GrB_Index nq = 1 ; GrB_Index last_nq = 0 ;
GrB_Index current_level = 0;
GrB_Index nvals = 1;
GrB_Vector mask = (compute_parent) ? l_parent : l_level ;
do
{
if (compute_level)
{
GRB_TRY( GrB_assign(l_level, frontier, GrB_NULL,
current_level, GrB_ALL, n, GrB_DESC_S) );
}
if (compute_parent)
{
GRB_TRY( GrB_assign(l_parent, frontier, GrB_NULL,
frontier, GrB_ALL, n, GrB_DESC_S) );
GRB_TRY (GrB_apply (frontier, GrB_NULL, GrB_NULL, ramp,
frontier, 0, GrB_NULL)) ;
}
#ifdef LG_BFS_EXTENDED
{
if (max_level >= 0 && current_level >= max_level)
{
break ;
}
if (dest >= 0)
{
int64_t x ; GrB_Info info = GrB_Vector_extractElement (&x, mask, dest) ;
if (info == GrB_SUCCESS)
{
break ;
}
GRB_TRY (info) ;
}
}
#endif
++current_level;
GRB_TRY( GrB_vxm(frontier, mask, GrB_NULL, semiring,
frontier, A, GrB_DESC_RSC) );
GRB_TRY( GrB_Vector_nvals(&nvals, frontier) );
} while (nvals > 0);
if (compute_parent) (*parent) = l_parent ;
if (compute_level ) (*level ) = l_level ;
LG_FREE_WORK ;
return (GrB_SUCCESS) ;
}