#define LG_FREE_ALL \
{ \
GrB_free (&CL) ; \
GrB_free (&S) ; \
GrB_free (&U) ; \
GrB_free (&W) ; \
GrB_free (&x) ; \
GrB_free (&LCC) ; \
GrB_free (&LAGraph_COMB_FP64) ; \
}
#include "LG_internal.h"
#include <LAGraph.h>
#include <LAGraphX.h>
#define F_UNARY(f) ((void (*)(void *, const void *)) f)
void LAGraph_comb_dir_fp64
(
void *z,
const void *x
)
{
double xd = *(double *) x ;
double *zd = (double *) z ;
(*zd) = ((xd) * (xd - 1)) ;
}
#define LAGRAPH_COMB_DIR_FP64 \
"void LAGraph_comb_dir_fp64 \n" \
"( \n" \
" void *z, \n" \
" const void *x \n" \
") \n" \
"{ \n" \
" double xd = *(double *) x ; \n" \
" double *zd = (double *) z ; \n" \
" (*zd) = ((xd) * (xd - 1)); \n" \
"}"
void LAGraph_comb_undir_fp64
(
void *z,
const void *x
)
{
double xd = *(double *) x ;
double *zd = (double *) z ;
(*zd) = ((xd) * (xd - 1)) / 2;
}
#define LAGRAPH_COMB_UNDIR_FP64 \
"void LAGraph_comb_undir_fp64 \n" \
"( \n" \
" void *z, \n" \
" const void *x \n" \
") \n" \
"{ \n" \
" double xd = *(double *) x ; \n" \
" double *zd = (double *) z ; \n" \
" (*zd) = ((xd) * (xd - 1)) / 2; \n" \
"}"
int LAGraph_lcc (
GrB_Vector *LCC_handle, LAGraph_Graph G, char *msg
)
{
LG_CLEAR_MSG ;
if (LCC_handle == NULL)
{
return (GrB_NULL_POINTER) ;
}
GrB_Matrix CL = NULL, S = NULL, U = NULL ;
GrB_Vector W = NULL, LCC = NULL, x = NULL ;
GrB_UnaryOp LAGraph_COMB_FP64 = NULL ;
GrB_Info info ;
LG_ASSERT_MSG (G->is_symmetric_structure != LAGraph_BOOLEAN_UNKNOWN,
LAGRAPH_NOT_CACHED,
"G->is_symmetric_structure is required") ;
LG_ASSERT_MSG (G->nself_edges != LAGRAPH_UNKNOWN,
LAGRAPH_NOT_CACHED,
"G->nself_edges is required") ;
GrB_Matrix A = G->A ;
GrB_Index n ;
GRB_TRY (GrB_Matrix_nrows (&n, A)) ;
GRB_TRY (GrB_Matrix_new (&S, GrB_FP64, n, n));
GRB_TRY (GrB_apply (S, GrB_NULL, GrB_NULL, GrB_ONEB_FP64, A, 0, GrB_NULL));
if (G->nself_edges != 0) {
GRB_TRY (GrB_select (S, GrB_NULL, GrB_NULL, GrB_OFFDIAG, S, 0, GrB_NULL));
}
#if LAGRAPH_SUITESPARSE
if (G->is_symmetric_structure == LAGraph_TRUE) {
GRB_TRY (GxB_UnaryOp_new(&LAGraph_COMB_FP64,
F_UNARY(LAGraph_comb_undir_fp64),
GrB_FP64, GrB_FP64,
"LAGraph_comb_undir_fp64",
LAGRAPH_COMB_UNDIR_FP64
));
} else {
GRB_TRY (GxB_UnaryOp_new(&LAGraph_COMB_FP64,
F_UNARY(LAGraph_comb_dir_fp64),
GrB_FP64, GrB_FP64,
"LAGraph_comb_dir_fp64",
LAGRAPH_COMB_DIR_FP64
));
}
#else
if (G->is_symmetric_structure == LAGraph_TRUE) {
GRB_TRY (GrB_UnaryOp_new(&LAGraph_COMB_FP64,
F_UNARY(LAGraph_comb_undir_fp64),
GrB_FP64, GrB_FP64
));
} else {
GRB_TRY (GrB_UnaryOp_new(&LAGraph_COMB_FP64,
F_UNARY(LAGraph_comb_dir_fp64),
GrB_FP64, GrB_FP64
));
}
#endif
GRB_TRY (GrB_Matrix_new (&U, GrB_FP64, n, n)) ;
if (G->is_symmetric_structure == LAGraph_FALSE) {
GRB_TRY (GrB_eWiseAdd (S, NULL, NULL, GrB_PLUS_FP64, S, S, GrB_DESC_T1))
}
GRB_TRY (GrB_select (U, NULL, NULL, GrB_TRIU, S, 0, NULL)) ;
GRB_TRY (GrB_Vector_new (&W, GrB_FP64, n)) ;
GRB_TRY (GrB_Vector_new (&x, GrB_INT64, n)) ;
GRB_TRY (GrB_assign (x, NULL, NULL, 0, GrB_ALL, n, NULL)) ;
GRB_TRY (GrB_mxv (W, NULL, NULL, LAGraph_plus_one_fp64, S, x, NULL)) ;
GrB_free (&x) ;
GRB_TRY (GrB_apply(W, NULL, NULL, LAGraph_COMB_FP64, W, NULL));
GRB_TRY (GrB_Matrix_new (&CL, GrB_FP64, n, n)) ;
GRB_TRY (GrB_mxm (CL, S, NULL, LAGraph_plus_second_fp64, S, U, GrB_DESC_ST1));
GRB_TRY (GrB_free (&S)) ;
GRB_TRY (GrB_free (&U)) ;
GRB_TRY (GrB_Vector_new (&LCC, GrB_FP64, n)) ;
GRB_TRY (GrB_reduce (LCC, NULL, NULL, GrB_PLUS_FP64, CL, NULL)) ;
GRB_TRY (GrB_free (&CL)) ;
GRB_TRY (GrB_eWiseMult (LCC, NULL, NULL, GrB_DIV_FP64, LCC, W, NULL)) ;
(*LCC_handle) = LCC ; LCC = NULL ;
LG_FREE_ALL ;
return (GrB_SUCCESS) ;
}