From c7ad83154300b121cde3b610294c59c0645a855f Mon Sep 17 00:00:00 2001 From: GomezGab Date: Wed, 1 Apr 2026 14:50:45 -0500 Subject: [PATCH 1/8] add python generator for JIT strings --- CMakeLists.txt | 14 + experimental/CMakeLists.txt | 32 ++ experimental/algorithm/LAGr_SwapEdges.c | 252 +++++--------- .../algorithm/LAGraph_RichClubCoefficient.c | 313 +++++++++--------- jit_generator.py | 95 ++++++ src/CMakeLists.txt | 32 ++ src/utility/LG_internal.h | 11 + 7 files changed, 414 insertions(+), 335 deletions(-) create mode 100644 jit_generator.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d7e4298e1..8bae11179f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,20 @@ else ( ) endif ( ) message ( STATUS "LAGraph has OpenMP: ${LAGRAPH_HAS_OPENMP}" ) +#------------------------------------------------------------------------------- +# find Python3 (for JIT kernel header generation) +#------------------------------------------------------------------------------- + +find_package ( Python3 REQUIRED COMPONENTS Interpreter ) +set ( JIT_INCLUDE_DIR "${CMAKE_BINARY_DIR}/jit_include" ) +file ( MAKE_DIRECTORY "${JIT_INCLUDE_DIR}" ) +include_directories ( "${JIT_INCLUDE_DIR}" ) + +# Predefine LG_JIT_KERNEL as a no-op for the compiler. +# LG_internal.h defines a non-trivial fallback for IDEs that don't apply +# compile flags, so that JIT string variables are still recognized there. +add_compile_definitions ( "LG_JIT_BUILD" ) + # check for strict usage if ( SUITESPARSE_USE_STRICT AND LAGRAPH_USE_OPENMP AND NOT LAGRAPH_HAS_OPENMP ) message ( FATAL_ERROR "OpenMP required for LAGraph but not found" ) diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index 7f14c63122..d6e5d123de 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -19,6 +19,27 @@ include_directories ( file ( GLOB LAGRAPHX_LIB_SOURCES "utility/*.c" "algorithm/*.c" ) +#------------------------------------------------------------------------------- +# JIT kernel header generation (one _jit.h per source file) +#------------------------------------------------------------------------------- + +set ( LAGRAPHX_JIT_HEADERS "" ) +foreach ( SRC IN LISTS LAGRAPHX_LIB_SOURCES ) + get_filename_component ( SRC_NAME "${SRC}" NAME_WE ) + set ( JIT_HEADER "${JIT_INCLUDE_DIR}/${SRC_NAME}_jit.h" ) + add_custom_command ( + OUTPUT "${JIT_HEADER}" + COMMAND Python3::Interpreter + "${PROJECT_SOURCE_DIR}/jit_generator.py" + --input "${SRC}" --output "${JIT_HEADER}" + DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/jit_generator.py" + COMMENT "JIT: generating ${SRC_NAME}_jit.h" + ) + list ( APPEND LAGRAPHX_JIT_HEADERS "${JIT_HEADER}" ) +endforeach () + +add_custom_target ( LAGraphXJITGenerate DEPENDS ${LAGRAPHX_JIT_HEADERS} ) + #------------------------------------------------------------------------------- # dynamic lagraphx library properties #------------------------------------------------------------------------------- @@ -107,6 +128,17 @@ if ( NOT NO_LIBM ) endif ( ) endif ( ) +#------------------------------------------------------------------------------- +# JIT header dependency: ensure headers are generated before compilation +#------------------------------------------------------------------------------- + +if ( BUILD_SHARED_LIBS ) + add_dependencies ( LAGraphX LAGraphXJITGenerate ) +endif ( ) +if ( BUILD_STATIC_LIBS ) + add_dependencies ( LAGraphX_static LAGraphXJITGenerate ) +endif ( ) + #------------------------------------------------------------------------------- # applications #------------------------------------------------------------------------------- diff --git a/experimental/algorithm/LAGr_SwapEdges.c b/experimental/algorithm/LAGr_SwapEdges.c index e18b428b73..e34b39e71e 100755 --- a/experimental/algorithm/LAGr_SwapEdges.c +++ b/experimental/algorithm/LAGr_SwapEdges.c @@ -77,56 +77,44 @@ #include "LG_internal.h" #include "LAGraphX.h" -void LG_SE_shift_and - (uint16_t *z, const uint16_t *x) - { - (*z) = (*x) & ((*x) << 8); - (*z) |= (*z) >> 8; - } -#define SHIFT_AND \ -"void LG_SE_shift_and \n"\ -" (uint16_t *z, const uint16_t *x) \n"\ -" { \n"\ -" (*z) = (*x) & ((*x) << 8); \n"\ -" (*z) |= (*z) >> 8; \n"\ -" }" +#include "LAGr_SwapEdges_jit.h" + +LG_JIT_KERNEL(LG_SE_shift_and) +void LG_SE_shift_and (uint16_t *z, const uint16_t *x) +{ + (*z) = (*x) & ((*x) << 8); + (*z) |= (*z) >> 8; +} +LG_JIT_KERNEL(LG_SE_edge_type64) typedef struct { - uint64_t a; + uint64_t a; uint64_t b; } LG_SE_edge_type64; -#define EDGE_TYPE64 \ -"typedef struct { uint64_t a; uint64_t b; } LG_SE_edge_type64;" +LG_JIT_KERNEL(LG_SE_swap_type64) typedef struct { uint64_t a; uint64_t b; uint64_t c; uint64_t d; } LG_SE_swap_type64; -#define SWAP_TYPE64 \ -"typedef struct { \n"\ -" uint64_t a; uint64_t b; uint64_t c; uint64_t d; \n"\ -"} LG_SE_swap_type64;" +LG_JIT_KERNEL(LG_SE_edge_type32) typedef struct { - uint32_t a; + uint32_t a; uint32_t b; } LG_SE_edge_type32; -#define EDGE_TYPE32 \ -"typedef struct { uint32_t a; uint32_t b; } LG_SE_edge_type32;" +LG_JIT_KERNEL(LG_SE_swap_type32) typedef struct { - uint32_t a; + uint32_t a; uint32_t b; - uint32_t c; + uint32_t c; uint32_t d; } LG_SE_swap_type32; -#define SWAP_TYPE32 \ -"typedef struct { \n"\ -" uint32_t a; uint32_t b; uint32_t c; uint32_t d; \n"\ -"}LG_SE_swap_type32;" +LG_JIT_KERNEL(LG_SE_swap_bc64) void LG_SE_swap_bc64 (LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, GrB_Index I, GrB_Index J, const bool *y) { @@ -136,15 +124,16 @@ void LG_SE_swap_bc64 { uint64_t temp = z->d; z->d = z->b; - z->b = temp; + z->b = temp; } else { uint64_t temp = z->c; z->c = z->b; - z->b = temp; - } + z->b = temp; + } } +LG_JIT_KERNEL(LG_SE_swap_bc32) void LG_SE_swap_bc32 (LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, GrB_Index I, GrB_Index J, const bool *y) { @@ -160,50 +149,13 @@ void LG_SE_swap_bc32 { uint32_t temp = z->c; z->c = z->b; - z->b = temp; - } + z->b = temp; + } } -#define SWAP_BC64 \ -"void LG_SE_swap_bc64 \n"\ -"(LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, GrB_Index I, GrB_Index J, const bool *y)\n"\ -"{ \n"\ -" memcpy(z, x, sizeof(*z)) ; //unnessesary when aliassed but done for safety.\n"\ -" if(z->a == z->c || z->b == z->c || z->a == z->d || z->b == z->d ) return; \n"\ -" if(I & 1) \n"\ -" { \n"\ -" uint64_t temp = z->d; \n"\ -" z->d = z->b; \n"\ -" z->b = temp; \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" uint64_t temp = z->c; \n"\ -" z->c = z->b; \n"\ -" z->b = temp; \n"\ -" } \n"\ -"}" -#define SWAP_BC32 \ -"void LG_SE_swap_bc32 \n"\ -"(LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, GrB_Index I, GrB_Index J, const bool *y)\n"\ -"{ \n"\ -" memcpy(z, x, sizeof(*z)) ; //unnessesary when aliassed but done for safety.\n"\ -" if(z->a == z->c || z->b == z->c || z->a == z->d || z->b == z->d ) return; \n"\ -" if(I & 1) \n"\ -" { \n"\ -" uint32_t temp = z->d; \n"\ -" z->d = z->b; \n"\ -" z->b = temp; \n"\ -" } \n"\ -" else \n"\ -" { \n"\ -" uint32_t temp = z->c; \n"\ -" z->c = z->b; \n"\ -" z->b = temp; \n"\ -" } \n"\ -"}" // using xorshift, from https://en.wikipedia.org/wiki/Xorshift // with a state of uint64_t, or xorshift64star. +LG_JIT_KERNEL(LG_SE_hash_edge64) void LG_SE_hash_edge64 (uint64_t *z, const LG_SE_edge_type64 *x, const uint64_t *mask) { @@ -214,107 +166,57 @@ void LG_SE_hash_edge64 (*z) ^= (*z) << 17; (*z) &= (*mask); } + +LG_JIT_KERNEL(LG_SE_hash_edge32) void LG_SE_hash_edge32 (uint64_t *z, const LG_SE_edge_type32 *x, const uint64_t *mask) { (*z) = x->a ^ x->b; - (*z) ^= (*z) << 13; - (*z) ^= (*z) >> 7; + (*z) ^= (*z) << 13; + (*z) ^= (*z) >> 7; (*z) ^= (uint64_t)((x->a < x->b)? x->a: x->b); - (*z) ^= (*z) << 17; + (*z) ^= (*z) << 17; (*z) &= (*mask); } -#define HASH_EDGE64 \ -"void LG_SE_hash_edge64 \n"\ -"(uint64_t *z, const LG_SE_edge_type64 *x, const uint64_t *mask) \n"\ -"{ \n"\ -" (*z) = x->a ^ x->b; \n"\ -" (*z) ^= (*z) << 13; \n"\ -" (*z) ^= (*z) >> 7; \n"\ -" (*z) ^= (uint64_t)((x->a < x->b)? x->a: x->b); \n"\ -" (*z) ^= (*z) << 17; \n"\ -" (*z) &= (*mask); \n"\ -"}" -#define HASH_EDGE32 \ -"void LG_SE_hash_edge32 \n"\ -"(uint64_t *z, const LG_SE_edge_type32 *x, const uint64_t *mask) \n"\ -"{ \n"\ -" (*z) = x->a ^ x->b; \n"\ -" (*z) ^= (*z) << 13; \n"\ -" (*z) ^= (*z) >> 7; \n"\ -" (*z) ^= (uint64_t)((x->a < x->b)? x->a: x->b); \n"\ -" (*z) ^= (*z) << 17; \n"\ -" (*z) &= (*mask); \n"\ -"}" +LG_JIT_KERNEL(LG_SE_add_term) void LG_SE_add_term (int8_t *z, const int8_t *x, const int8_t *y) { (*z) = (*x) | (*y) + ((int8_t)1 & (*x) & (*y)) ; } -#define ADD_TERM \ -"void LG_SE_add_term \n"\ -"(int8_t *z, const int8_t *x, const int8_t *y) \n"\ -"{ \n"\ -" (*z) = (*x) | (*y) + ((int8_t)1 & (*x) & (*y)) ; \n"\ -"}" +LG_JIT_KERNEL(LG_SE_edge2nd64_bool) void LG_SE_edge2nd64_bool (LG_SE_edge_type64 *z, const bool *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; } + +LG_JIT_KERNEL(LG_SE_edge2nd32_bool) void LG_SE_edge2nd32_bool (LG_SE_edge_type32 *z, const bool *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; } + +LG_JIT_KERNEL(LG_SE_edge2nd64_edge) void LG_SE_edge2nd64_edge (LG_SE_edge_type64 *z, const LG_SE_edge_type64 *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; } + +LG_JIT_KERNEL(LG_SE_edge2nd32_edge) void LG_SE_edge2nd32_edge (LG_SE_edge_type32 *z, const LG_SE_edge_type32 *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; } -#define EDGE2ND32_BOOL \ -"void LG_SE_edge2nd32_bool \n"\ -"(LG_SE_edge_type32 *z, const bool *x, const LG_SE_edge_type32 *y) \n"\ -"{ \n"\ -" //if(y->a == 0 && y->b == 0) return; \n"\ -" z->a = y->a; \n"\ -" z->b = y->b; \n"\ -"}" -#define EDGE2ND64_BOOL \ -"void LG_SE_edge2nd64_bool \n"\ -"(LG_SE_edge_type64 *z, const bool *x, const LG_SE_edge_type64 *y) \n"\ -"{ \n"\ -" //if(y->a == 0 && y->b == 0) return; \n"\ -" z->a = y->a; \n"\ -" z->b = y->b; \n"\ -"}" -#define EDGE2ND32_EDGE \ -"void LG_SE_edge2nd32_edge \n"\ -"(LG_SE_edge_type32 *z, const LG_SE_edge_type32 *x, const LG_SE_edge_type32 *y)\n"\ -"{ \n"\ -" //if(y->a == 0 && y->b == 0) return; \n"\ -" z->a = y->a; \n"\ -" z->b = y->b; \n"\ -"}" -#define EDGE2ND64_EDGE \ -"void LG_SE_edge2nd64_edge \n"\ -"(LG_SE_edge_type64 *z, const LG_SE_edge_type64 *x, const LG_SE_edge_type64 *y)\n"\ -"{ \n"\ -" //if(y->a == 0 && y->b == 0) return; \n"\ -" z->a = y->a; \n"\ -" z->b = y->b; \n"\ -"}" // FIXME: make loopTry, loopMin, totSwaps, seed inputs GrB_Scalar // FIXME: make pSwaps GrB_Scalar @@ -378,12 +280,12 @@ int LAGr_SwapEdges // 2^60 holds the buckets in which hashes collided. GrB_Vector exists = NULL; - + GrB_UnaryOp lg_shiftland = NULL; // b1 <---> a2 or b1 <---> b2 GrB_IndexUnaryOp swap_pair = NULL; - + // z = h_y(x) GrB_BinaryOp hash_seed_e = NULL; @@ -424,7 +326,7 @@ int LAGr_SwapEdges GrB_Scalar one8 = NULL; GrB_Index ind_size = 0; - + //-------------------------------------------------------------------------- // Check inputs //-------------------------------------------------------------------------- @@ -435,7 +337,7 @@ int LAGr_SwapEdges ) ; // char type[LAGRAPH_MAX_NAME_LEN]; LG_ASSERT_MSG (G->nself_edges == 0, LAGRAPH_NO_SELF_EDGES_ALLOWED, - "G->nself_edges must be zero") ; + "G->nself_edges must be zero") ; LG_ASSERT (G_new != NULL, GrB_NULL_POINTER) ; LG_ASSERT (pSwaps != NULL, GrB_NULL_POINTER) ; *G_new = NULL ; @@ -453,12 +355,12 @@ int LAGr_SwapEdges GRB_TRY (GrB_Matrix_new (&A_tril, GrB_BOOL, n, n)) ; GRB_TRY (GrB_Vector_new(&Ai, GrB_BOOL, 0)) ; GRB_TRY (GrB_Vector_new(&Aj, GrB_BOOL, 0)) ; - + // Extract lower triangular edges GRB_TRY (GrB_select (A_tril, NULL, NULL, GrB_TRIL, A, 0, NULL)) ; GRB_TRY (GrB_Matrix_nvals(&e, A_tril)) ; GRB_TRY (GxB_Matrix_extractTuples_Vector(Ai, Aj, NULL, A_tril, NULL)) ; - #ifdef COVERAGE +#ifdef COVERAGE if(n > 100) { // Make Ai and Aj 64 bit @@ -473,7 +375,7 @@ int LAGr_SwapEdges Aj = temp_i; temp_i = NULL; } - #endif +#endif int codei = 0, codej = 0; GRB_TRY (GxB_Vector_type(&Ai_type, Ai)) ; GrB_get(Ai, &codei, GrB_EL_TYPE_CODE); @@ -489,57 +391,57 @@ int LAGr_SwapEdges if(codei == GrB_UINT32_CODE) // Use uint32 if possible { GRB_TRY (GxB_Type_new( - &lg_edge, sizeof(LG_SE_edge_type32), "LG_SE_edge_type32", EDGE_TYPE32)) ; + &lg_edge, sizeof(LG_SE_edge_type32), "LG_SE_edge_type32", LG_SE_edge_type32_JIT_STR)) ; GRB_TRY (GxB_Type_new( - &lg_swap, sizeof(LG_SE_swap_type32), "LG_SE_swap_type32", SWAP_TYPE32)) ; + &lg_swap, sizeof(LG_SE_swap_type32), "LG_SE_swap_type32", LG_SE_swap_type32_JIT_STR)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge32), - GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge32", HASH_EDGE32 + GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge32", LG_SE_hash_edge32_JIT_STR )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc32), - lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc32", SWAP_BC32 + lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc32", LG_SE_swap_bc32_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( - &second_edge, (GxB_binary_function) (&LG_SE_edge2nd32_edge), - lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd32_edge", EDGE2ND32_EDGE + &second_edge, (GxB_binary_function) (&LG_SE_edge2nd32_edge), + lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd32_edge", LG_SE_edge2nd32_edge_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( - &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd32_bool), - lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", EDGE2ND32_BOOL + &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd32_bool), + lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", LG_SE_edge2nd32_bool_JIT_STR )) ; } else //uint64 types - { +{ GRB_TRY (GxB_Type_new( - &lg_edge, sizeof(LG_SE_edge_type64), "LG_SE_edge_type64", EDGE_TYPE64)) ; + &lg_edge, sizeof(LG_SE_edge_type64), "LG_SE_edge_type64", LG_SE_edge_type64_JIT_STR)) ; GRB_TRY (GxB_Type_new( - &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", SWAP_TYPE64)) ; + &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", LG_SE_edge_type64_JIT_STR)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge64), - GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", HASH_EDGE64 + GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", LG_SE_hash_edge64_JIT_STR )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc64), - lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc64", SWAP_BC64 + lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc64", LG_SE_swap_bc64_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( - &second_edge, (GxB_binary_function) (&LG_SE_edge2nd64_edge), - lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd64_edge", EDGE2ND64_EDGE + &second_edge, (GxB_binary_function) (&LG_SE_edge2nd64_edge), + lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd64_edge", LG_SE_edge2nd64_edge_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( - &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd64_bool), - lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", EDGE2ND64_BOOL + &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd64_bool), + lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", LG_SE_edge2nd64_bool_JIT_STR )) ; } - + GRB_TRY (GxB_UnaryOp_new ( &lg_shiftland, (GxB_unary_function) (&LG_SE_shift_and), - GrB_UINT16, GrB_UINT16, "LG_SE_shift_and", SHIFT_AND + GrB_UINT16, GrB_UINT16, "LG_SE_shift_and", LG_SE_shift_and_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( &add_term_biop, (GxB_binary_function) (&LG_SE_add_term), - GrB_INT8, GrB_INT8, GrB_INT8, "LG_SE_add_term", ADD_TERM + GrB_INT8, GrB_INT8, GrB_INT8, "LG_SE_add_term", LG_SE_add_term_JIT_STR )) ; GRB_TRY (GxB_Monoid_terminal_new_INT8( @@ -563,7 +465,7 @@ int LAGr_SwapEdges //-------------------------------------------------------------------------- GRB_TRY (GrB_Vector_new(&E_vec, Ai_type, 2 * e)) ; - + // Filling out E_vec helps assign be much quicker. GRB_TRY (GrB_assign( E_vec, NULL, NULL, 0, GrB_ALL, 0, NULL)); @@ -582,7 +484,7 @@ int LAGr_SwapEdges e /= 2; GRB_TRY (GxB_Vector_load( E_vec, &indices, lg_edge, e, ind_size, E_hand, NULL)); - + // Find Hash Size int shift_e = 63 - (int) floor (log2 ((double) e)) ; uint64_t ehash_size = (1ull << (67-shift_e)) ; @@ -601,7 +503,7 @@ int LAGr_SwapEdges GRB_TRY (GrB_Vector_new(&ramp_v, GrB_UINT64, e + 1)) ; GRB_TRY (GrB_Vector_assign_UINT64 (ramp_v, NULL, NULL, 0, GrB_ALL, 0, NULL)) ; GRB_TRY (GrB_Vector_apply_IndexOp_UINT64 (ramp_v, NULL, NULL, - GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; + GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; GrB_Index ramp_size; // Constants @@ -618,7 +520,7 @@ int LAGr_SwapEdges random_v, NULL, NULL, 0, GrB_ALL, e, NULL)) ; LG_TRY( LAGraph_Random_Seed(random_v, seed, msg)) ; - + // printf("Entering loop, Good Luck:\n") ; while(num_swaps < totSwaps) { @@ -634,7 +536,7 @@ int LAGr_SwapEdges LG_TRY (LAGraph_FastAssign_Semiring( r_permute, NULL, NULL, r_60, x, ramp_v, GxB_ANY_FIRSTJ_INT64, NULL, msg)) ; - + GrB_Index edges_permed = 0; GRB_TRY (GrB_Vector_nvals(&edges_permed, r_permute)) ; GRB_TRY (GrB_Vector_new(&edge_perm, GrB_BOOL, edges_permed)) ; @@ -643,7 +545,7 @@ int LAGr_SwapEdges // Chose only the edges we need from edge_perm GRB_TRY (GrB_Vector_resize(edge_perm, n_keep * 2)) ; - + // Get the desired edges from the E_vec array. GRB_TRY (GrB_Vector_new(&M, lg_edge, n_keep * 2)) ; GRB_TRY (GxB_Vector_extract_Vector( @@ -688,7 +590,7 @@ int LAGr_SwapEdges GRB_TRY (GrB_Vector_new(&dup_swaps_v, GrB_INT8, n_keep * 2)) ; GRB_TRY (GrB_set(dup_swaps_v, GxB_BITMAP, GxB_SPARSITY_CONTROL)) ; - + GRB_TRY (GrB_Vector_clear(x)) ; GRB_TRY (GrB_Vector_resize(x, e)) ; GRB_TRY (GrB_Vector_assign_BOOL( @@ -698,7 +600,7 @@ int LAGr_SwapEdges exists, NULL, NULL, hashed_edges, x, ramp_v, GxB_ANY_PAIR_UINT8, NULL, msg )) ; - + GRB_TRY (GrB_Vector_clear(x)) ; GRB_TRY (GrB_Vector_resize(x, n_keep * 2)) ; GRB_TRY (GrB_Vector_assign_BOOL( @@ -715,7 +617,7 @@ int LAGr_SwapEdges con->b = NULL; GRB_TRY (GrB_free(&con)) ; // exist has to be full at this point - + // "Count" all of the edges that fit into each bucket. Stop counting at // 2 since we will have to throw that whole bucket away anyway. @@ -760,7 +662,7 @@ int LAGr_SwapEdges GRB_TRY (GxB_Vector_load( dup_swaps_v, (void **) &dup_swaps, GrB_INT8, M_nvals * 2, dup_arr_size, M_hand, NULL)) ; - + GRB_TRY (GrB_Vector_clear(exists)) ; // --------------------------------------------------------------------- // Place Good Swaps back into E_vec @@ -774,7 +676,7 @@ int LAGr_SwapEdges // dup_swaps_v, which will become nvals(M) after loading M from the // container con. GRB_TRY (GrB_reduce (&n_keep, NULL, GrB_PLUS_MONOID_UINT64, - dup_swaps_v, NULL)) ; + dup_swaps_v, NULL)) ; con->nvals = n_keep; con->format = GxB_BITMAP; dup_swaps_v = NULL; @@ -822,8 +724,8 @@ int LAGr_SwapEdges LG_FREE_WORK ; (*pSwaps) = num_swaps ; return (num_swaps >= totSwaps)? GrB_SUCCESS : LAGRAPH_INSUFFICIENT_SWAPS ; - #else +#else // printf("LAGr_SwapEdges Needs GB v10\n") ; return (GrB_NOT_IMPLEMENTED) ; - #endif +#endif } diff --git a/experimental/algorithm/LAGraph_RichClubCoefficient.c b/experimental/algorithm/LAGraph_RichClubCoefficient.c index 0a66f15dc4..2eb2f4cc3b 100755 --- a/experimental/algorithm/LAGraph_RichClubCoefficient.c +++ b/experimental/algorithm/LAGraph_RichClubCoefficient.c @@ -64,35 +64,28 @@ #include "LG_internal.h" #include "LAGraphX.h" +#include "LAGraph_RichClubCoefficient_jit.h" typedef void (*LAGraph_binary_function) (void *, const void *, const void *) ; -#define ISEQ_2ISLT \ - "void LG_RCC_iseq_2islt(int64_t *z, const int64_t *x, const int64_t *y) \n"\ - "{ \n"\ - "(*z) = (int64_t)((*x < *y) + (*x <= *y)) ; \n"\ - "}" +LG_JIT_KERNEL(LG_RCC_iseq_2islt) void LG_RCC_iseq_2islt(int64_t *z, const int64_t *x, const int64_t *y) { (*z) = (int64_t)((*x < *y) + (*x <= *y)) ; } -#define RICH_CLUB_FORMULA \ - "void LG_RCC_rich_club_formula(double *z, const int64_t *x, const int64_t *y) \n"\ - "{ \n"\ - " (*z) = ((double)(*x)) / (((double)(*y)) * (((double)(*y)) - 1.0)) ; \n"\ - "}" +LG_JIT_KERNEL(LG_RCC_rich_club_formula) void LG_RCC_rich_club_formula(double *z, const int64_t *x, const int64_t *y) { (*z) = ((double)(*x)) / (((double)(*y)) * (((double)(*y)) - 1.0)); -} +} int LAGraph_RichClubCoefficient ( // output: //rccs(i): rich club coefficent of i - GrB_Vector *rccs, + GrB_Vector *rccs, - // input: + // input: LAGraph_Graph G, //input graph char *msg ) @@ -149,16 +142,16 @@ int LAGraph_RichClubCoefficient GrB_Matrix P = NULL; GrB_Index n ; - + GrB_Index edge_vec_nvals; int64_t max_deg; bool iso = false; void *a_space = NULL; - + int64_t *node_edges_arr = NULL, *deg_arr = NULL, - *epd_arr = NULL, *ones = NULL, - *vpd_arr = NULL; + *epd_arr = NULL, *ones = NULL, + *vpd_arr = NULL; GrB_Type epd_type = NULL, vpd_type = NULL; uint64_t epd_n = 0, vpd_n = 0, epd_size = 0, vpd_size = 0; int epd_h = 0, vpd_h = 0; @@ -174,9 +167,9 @@ int LAGraph_RichClubCoefficient G->kind == LAGraph_ADJACENCY_UNDIRECTED, GrB_INVALID_VALUE, "G->A must be symmetric") ; LG_ASSERT_MSG (G->out_degree != NULL, GrB_EMPTY_OBJECT, - "G->out_degree must be defined") ; + "G->out_degree must be defined") ; LG_ASSERT_MSG (G->nself_edges == 0, GrB_INVALID_VALUE, - "G->nself_edges must be zero") ; + "G->nself_edges must be zero") ; //-------------------------------------------------------------------------- // Initializations @@ -187,25 +180,25 @@ int LAGraph_RichClubCoefficient GRB_TRY (GrB_Vector_new(°rees, GrB_INT64, n)) ; GRB_TRY (GrB_Vector_new(&node_edges, GrB_INT64, n)) ; - #if LAGRAPH_SUITESPARSE +#if LAGRAPH_SUITESPARSE GRB_TRY (GxB_BinaryOp_new( &iseq_2lt, (LAGraph_binary_function) (&LG_RCC_iseq_2islt), - GrB_INT64, GrB_INT64, GrB_INT64, "LG_RCC_iseq_2islt", ISEQ_2ISLT)) ; + GrB_INT64, GrB_INT64, GrB_INT64, "LG_RCC_iseq_2islt", LG_RCC_iseq_2islt_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new( &rcCalculation, (LAGraph_binary_function) (&LG_RCC_rich_club_formula), GrB_FP64, GrB_INT64, GrB_INT64, - "LG_RCC_rich_club_formula", RICH_CLUB_FORMULA)) ; - #else + "LG_RCC_rich_club_formula", LG_RCC_rich_club_formula_JIT_STR)) ; +#else GRB_TRY (GrB_BinaryOp_new( &iseq_2lt, (LAGraph_binary_function) (&LG_RCC_iseq_2islt), GrB_INT64, GrB_INT64, GrB_INT64)) ; GRB_TRY (GrB_BinaryOp_new( &rcCalculation, (LAGraph_binary_function) (&LG_RCC_rich_club_formula), GrB_FP64, GrB_INT64, GrB_INT64 )) ; - #endif +#endif GRB_TRY (GrB_Semiring_new(&plus_2le, GrB_PLUS_MONOID_INT64, iseq_2lt)) ; - + GRB_TRY (GrB_Vector_reduce_INT64( &max_deg, NULL, GrB_MAX_MONOID_INT64, G->out_degree, NULL)) ; GRB_TRY (GrB_Vector_new(&edges_per_deg, GrB_INT64, max_deg)) ; @@ -226,13 +219,13 @@ int LAGraph_RichClubCoefficient GRB_TRY (GrB_Matrix_diag(&D, degrees, 0)) ; // Each edge in the graph gets the value of the degree of its row node - #if LAGRAPH_SUITESPARSE +#if LAGRAPH_SUITESPARSE GRB_TRY (GrB_mxm( A_deg, NULL, NULL, GxB_ANY_FIRST_INT64, D, A, NULL)) ; - #else +#else GRB_TRY (GrB_mxm( A_deg, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_INT64, D, A, NULL)) ; - #endif +#endif // Sum the number of edges each node is "responsible" for. GRB_TRY (GrB_mxv( node_edges, NULL, GrB_PLUS_INT64, plus_2le, A_deg, degrees, NULL)) ; @@ -241,141 +234,141 @@ int LAGraph_RichClubCoefficient // each degree and then doing a cummulative sum to know the amount of edges // and nodes at degree geq k. GRB_TRY (GrB_Vector_nvals (&edge_vec_nvals, node_edges)) ; - #if LG_SUITESPARSE_GRAPHBLAS_V10 - if(n == edge_vec_nvals) - { - deg_x = degrees; - degrees = NULL; - node_edges_x = node_edges; - node_edges = NULL; - } - else - { - GRB_TRY (GrB_Vector_assign( - degrees, G->out_degree, NULL, degrees, GrB_ALL, 0, GrB_DESC_RS - )) ; - GRB_TRY (GrB_Vector_new(°_x, GrB_BOOL, 0)) ; - GRB_TRY (GrB_Vector_new(&node_edges_x, GrB_BOOL, 0)) ; - GRB_TRY (GxB_Vector_extractTuples_Vector( - NULL, deg_x, degrees, NULL - )) ; - GRB_TRY (GxB_Vector_extractTuples_Vector( - NULL, node_edges_x, node_edges, NULL - )) ; - } - GRB_TRY (GrB_Vector_nvals(&edge_vec_nvals, node_edges_x)) - GRB_TRY (GrB_Vector_new(&ones_v, GrB_INT64, edge_vec_nvals)) ; - - - GRB_TRY (GrB_Vector_assign_INT64( - edges_per_deg, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; - GRB_TRY (GrB_Vector_assign_INT64( - verts_per_deg, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; - GRB_TRY (GrB_Vector_assign_INT64( - ones_v, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; - - #ifndef COVERAGE - GRB_TRY (GrB_Vector_new(&ramp_v, GrB_INT64, edge_vec_nvals + 1)) ; - GRB_TRY (GrB_Vector_assign_INT64( - ramp_v, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; - GRB_TRY (GrB_apply ( - ramp_v, NULL, NULL, GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; - #endif - - LG_TRY (LAGraph_FastAssign_Semiring ( - edges_per_deg, NULL, GrB_PLUS_INT64, deg_x, node_edges_x, ramp_v, - LAGraph_plus_second_int64, NULL, msg - )) ; - LG_TRY (LAGraph_FastAssign_Semiring ( - verts_per_deg, NULL, GrB_PLUS_INT64, deg_x, ones_v, ramp_v, - LAGraph_plus_one_int64, NULL, msg - )) ; - - GRB_TRY (GxB_Vector_unload( - edges_per_deg, (void **) &epd_arr, &epd_type, - &epd_n, &epd_size, &epd_h, NULL)) ; - GRB_TRY (GxB_Vector_unload( - verts_per_deg, (void **) &vpd_arr, &vpd_type, - &vpd_n, &vpd_size, &vpd_h, NULL)) ; - - LG_ASSERT (max_deg == vpd_n && max_deg == epd_n, GrB_INVALID_VALUE) ; - //run a cummulative sum (backwards) on vpd_arr - for(int64_t i = max_deg - 1; i > 0; --i) - { - vpd_arr[i-1] += vpd_arr[i] ; - epd_arr[i-1] += epd_arr[i] ; - } - GRB_TRY(GxB_Vector_load( - edges_per_deg, (void **) &epd_arr, epd_type, - epd_n, epd_size, epd_h, NULL)) ; - GRB_TRY(GxB_Vector_load( - verts_per_deg, (void **) &vpd_arr, vpd_type, - vpd_n, vpd_size, vpd_h, NULL)) ; - #else - LG_TRY (LAGraph_Malloc( - &a_space, edge_vec_nvals * 3 + max_deg * 4, sizeof(int64_t), NULL +#if LG_SUITESPARSE_GRAPHBLAS_V10 + if(n == edge_vec_nvals) + { + deg_x = degrees; + degrees = NULL; + node_edges_x = node_edges; + node_edges = NULL; + } + else +{ + GRB_TRY (GrB_Vector_assign( + degrees, G->out_degree, NULL, degrees, GrB_ALL, 0, GrB_DESC_RS )) ; - int64_t *T = a_space; - deg_arr = T; T += edge_vec_nvals; - node_edges_arr = T; T += edge_vec_nvals; - ones = T; T += edge_vec_nvals; - epd_arr = T; T += max_deg; - vpd_arr = T; T += max_deg; - epd_index = T; T += max_deg; - vpd_index = T; T += max_deg; - - #pragma omp parallel for schedule(static) - for(uint64_t i = 0; i < edge_vec_nvals; ++i) - { - ones[i] = 1ll; - } - GRB_TRY (GrB_Vector_apply_BinaryOp2nd_INT64( - degrees, NULL, NULL, GrB_MINUS_INT64, G->out_degree, 1, NULL)) ; - //TODO: remove NULL for Vanilla GB - GRB_TRY (GrB_Vector_extractTuples_INT64( - NULL, deg_arr, &edge_vec_nvals, degrees + GRB_TRY (GrB_Vector_new(°_x, GrB_BOOL, 0)) ; + GRB_TRY (GrB_Vector_new(&node_edges_x, GrB_BOOL, 0)) ; + GRB_TRY (GxB_Vector_extractTuples_Vector( + NULL, deg_x, degrees, NULL )) ; - GRB_TRY (GrB_Vector_extractTuples_INT64( - NULL, node_edges_arr, &edge_vec_nvals, node_edges + GRB_TRY (GxB_Vector_extractTuples_Vector( + NULL, node_edges_x, node_edges, NULL )) ; + } + GRB_TRY (GrB_Vector_nvals(&edge_vec_nvals, node_edges_x)) + GRB_TRY (GrB_Vector_new(&ones_v, GrB_INT64, edge_vec_nvals)) ; - // Build with degrees as indecies and handle duplicates via adition - GRB_TRY (GrB_Vector_build_INT64 ( - edges_per_deg, deg_arr, node_edges_arr, edge_vec_nvals, - GrB_PLUS_INT64)) ; - GRB_TRY (GrB_Vector_build_INT64 ( - verts_per_deg, deg_arr, ones, edge_vec_nvals, GrB_PLUS_INT64)) ; - GRB_TRY (GrB_Vector_assign_INT64( - edges_per_deg, edges_per_deg, NULL, (int64_t) 0, - GrB_ALL, 0, GrB_DESC_SC)) ; - GRB_TRY (GrB_Vector_assign_INT64( - verts_per_deg, verts_per_deg, NULL, (int64_t) 0, - GrB_ALL, 0, GrB_DESC_SC)) ; - - // Extract into arrays - GRB_TRY (GrB_Vector_extractTuples_INT64( - epd_index, epd_arr, &max_deg, edges_per_deg - )) ; - GRB_TRY (GrB_Vector_extractTuples_INT64( - vpd_index, vpd_arr, &max_deg, verts_per_deg - )) ; - //run a cummulative sum (backwards) on vpd_arr - for(int64_t i = max_deg - 1; i > 0; --i) - { - vpd_arr[i-1] += vpd_arr[i] ; - epd_arr[i-1] += epd_arr[i] ; - } - GRB_TRY (GrB_Vector_clear(edges_per_deg)) ; - GRB_TRY (GrB_Vector_clear(verts_per_deg)) ; - GRB_TRY (GrB_Vector_build_INT64( - edges_per_deg, epd_index, epd_arr, max_deg, NULL - )) ; - GRB_TRY (GrB_Vector_build_INT64( - verts_per_deg, vpd_index, vpd_arr, max_deg, NULL - )) ; - T = deg_arr = node_edges_arr = ones = NULL ; - epd_index = vpd_index = epd_arr = vpd_arr = NULL ; - #endif + + GRB_TRY (GrB_Vector_assign_INT64( + edges_per_deg, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; + GRB_TRY (GrB_Vector_assign_INT64( + verts_per_deg, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; + GRB_TRY (GrB_Vector_assign_INT64( + ones_v, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; + +#ifndef COVERAGE + GRB_TRY (GrB_Vector_new(&ramp_v, GrB_INT64, edge_vec_nvals + 1)) ; + GRB_TRY (GrB_Vector_assign_INT64( + ramp_v, NULL, NULL, (int64_t) 0, GrB_ALL, 0, NULL)) ; + GRB_TRY (GrB_apply ( + ramp_v, NULL, NULL, GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; +#endif + + LG_TRY (LAGraph_FastAssign_Semiring ( + edges_per_deg, NULL, GrB_PLUS_INT64, deg_x, node_edges_x, ramp_v, + LAGraph_plus_second_int64, NULL, msg + )) ; + LG_TRY (LAGraph_FastAssign_Semiring ( + verts_per_deg, NULL, GrB_PLUS_INT64, deg_x, ones_v, ramp_v, + LAGraph_plus_one_int64, NULL, msg + )) ; + + GRB_TRY (GxB_Vector_unload( + edges_per_deg, (void **) &epd_arr, &epd_type, + &epd_n, &epd_size, &epd_h, NULL)) ; + GRB_TRY (GxB_Vector_unload( + verts_per_deg, (void **) &vpd_arr, &vpd_type, + &vpd_n, &vpd_size, &vpd_h, NULL)) ; + + LG_ASSERT (max_deg == vpd_n && max_deg == epd_n, GrB_INVALID_VALUE) ; + //run a cummulative sum (backwards) on vpd_arr + for(int64_t i = max_deg - 1; i > 0; --i) + { + vpd_arr[i-1] += vpd_arr[i] ; + epd_arr[i-1] += epd_arr[i] ; + } + GRB_TRY(GxB_Vector_load( + edges_per_deg, (void **) &epd_arr, epd_type, + epd_n, epd_size, epd_h, NULL)) ; + GRB_TRY(GxB_Vector_load( + verts_per_deg, (void **) &vpd_arr, vpd_type, + vpd_n, vpd_size, vpd_h, NULL)) ; +#else + LG_TRY (LAGraph_Malloc( + &a_space, edge_vec_nvals * 3 + max_deg * 4, sizeof(int64_t), NULL + )) ; + int64_t *T = a_space; + deg_arr = T; T += edge_vec_nvals; + node_edges_arr = T; T += edge_vec_nvals; + ones = T; T += edge_vec_nvals; + epd_arr = T; T += max_deg; + vpd_arr = T; T += max_deg; + epd_index = T; T += max_deg; + vpd_index = T; T += max_deg; + + #pragma omp parallel for schedule(static) + for(uint64_t i = 0; i < edge_vec_nvals; ++i) + { + ones[i] = 1ll; + } + GRB_TRY (GrB_Vector_apply_BinaryOp2nd_INT64( + degrees, NULL, NULL, GrB_MINUS_INT64, G->out_degree, 1, NULL)) ; + //TODO: remove NULL for Vanilla GB + GRB_TRY (GrB_Vector_extractTuples_INT64( + NULL, deg_arr, &edge_vec_nvals, degrees + )) ; + GRB_TRY (GrB_Vector_extractTuples_INT64( + NULL, node_edges_arr, &edge_vec_nvals, node_edges + )) ; + + // Build with degrees as indecies and handle duplicates via adition + GRB_TRY (GrB_Vector_build_INT64 ( + edges_per_deg, deg_arr, node_edges_arr, edge_vec_nvals, + GrB_PLUS_INT64)) ; + GRB_TRY (GrB_Vector_build_INT64 ( + verts_per_deg, deg_arr, ones, edge_vec_nvals, GrB_PLUS_INT64)) ; + GRB_TRY (GrB_Vector_assign_INT64( + edges_per_deg, edges_per_deg, NULL, (int64_t) 0, + GrB_ALL, 0, GrB_DESC_SC)) ; + GRB_TRY (GrB_Vector_assign_INT64( + verts_per_deg, verts_per_deg, NULL, (int64_t) 0, + GrB_ALL, 0, GrB_DESC_SC)) ; + + // Extract into arrays + GRB_TRY (GrB_Vector_extractTuples_INT64( + epd_index, epd_arr, &max_deg, edges_per_deg + )) ; + GRB_TRY (GrB_Vector_extractTuples_INT64( + vpd_index, vpd_arr, &max_deg, verts_per_deg + )) ; + //run a cummulative sum (backwards) on vpd_arr + for(int64_t i = max_deg - 1; i > 0; --i) + { + vpd_arr[i-1] += vpd_arr[i] ; + epd_arr[i-1] += epd_arr[i] ; + } + GRB_TRY (GrB_Vector_clear(edges_per_deg)) ; + GRB_TRY (GrB_Vector_clear(verts_per_deg)) ; + GRB_TRY (GrB_Vector_build_INT64( + edges_per_deg, epd_index, epd_arr, max_deg, NULL + )) ; + GRB_TRY (GrB_Vector_build_INT64( + verts_per_deg, vpd_index, vpd_arr, max_deg, NULL + )) ; + T = deg_arr = node_edges_arr = ones = NULL ; + epd_index = vpd_index = epd_arr = vpd_arr = NULL ; +#endif /** * Cumulative sum (TODO: should be a GBLAS method!) @@ -393,7 +386,7 @@ int LAGraph_RichClubCoefficient * * If plus biop is not a monoid, this method should still work? */ - + //Computes the RCC of a matrix GRB_TRY(GrB_eWiseMult( *rccs, NULL, NULL, rcCalculation, diff --git a/jit_generator.py b/jit_generator.py new file mode 100644 index 0000000000..f613854bb2 --- /dev/null +++ b/jit_generator.py @@ -0,0 +1,95 @@ +import argparse +import io +import re + +import pcpp + + +class _Preprocessor(pcpp.Preprocessor): + """Preprocessor that silently passes through unfound includes.""" + + def on_include_not_found( + self, is_malformed, is_system_include, curdir, includepath + ): + raise pcpp.OutputDirective(pcpp.Action.IgnoreAndPassThrough) + + def on_error(self, file, line, msg): + pass # suppress errors from missing include contents + + +def _preprocess(input_file): + pp = _Preprocessor() + pp.line_directive = None # suppress #line markers in output + pp.define("LG_JIT_KERNEL(name) __LG_JIT_KERNEL__(name)") + pp.parse(open(input_file).read(), input_file) + out = io.StringIO() + pp.write(out) + return out.getvalue() + + +_MARKER_RE = re.compile(r"__LG_JIT_KERNEL__\((\w+)\)") + + +def extract_jit_kernels(input_file): + # 1. Expand all macros, passing through any #include directives that can't be resolved + expanded_code = _preprocess(input_file) + + lines = expanded_code.splitlines() + kernels = {} + + i = 0 + while i < len(lines): + m = _MARKER_RE.search(lines[i]) + if m: + kernel_name = m.group(1) + + # Advance to the next non-empty line (the struct/function definition) + i += 1 + while i < len(lines) and not lines[i].strip(): + i += 1 + + # 2. Brace-count to find the end of the definition + content = [] + brace_count = 0 + started = False + + while i < len(lines): + line = lines[i] + content.append(line) + brace_count += line.count("{") + brace_count -= line.count("}") + + if "{" in line: + started = True + + if started and brace_count == 0: + break + i += 1 + + # Join and format as a C string literal + full_body = "\n".join(content) + escaped_body = ( + full_body.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + ) + kernels[kernel_name] = f'"{escaped_body}"' + i += 1 + return kernels + + +def write_jit_header(input_file, output_file): + """Generate a JIT header for input_file and write it to output_file.""" + kernels = extract_jit_kernels(input_file) + with open(output_file, "w") as f: + f.write("#pragma once\n") + for name, string_lit in kernels.items(): + f.write(f"static const char* {name}_JIT_STR = {string_lit};\n") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Extract LG_JIT_KERNEL-marked definitions from a C file as string literals." + ) + parser.add_argument("--input", required=True, help="Input C source file") + parser.add_argument("--output", required=True, help="Output header file to generate") + args = parser.parse_args() + write_jit_header(args.input, args.output) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 451f0bd2ba..5f62698186 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,27 @@ include_directories ( utility ) file ( GLOB LAGRAPH_LIB_SOURCES "utility/*.c" "algorithm/*.c" ) +#------------------------------------------------------------------------------- +# JIT kernel header generation (one _jit.h per source file) +#------------------------------------------------------------------------------- + +set ( LAGRAPH_JIT_HEADERS "" ) +foreach ( SRC IN LISTS LAGRAPH_LIB_SOURCES ) + get_filename_component ( SRC_NAME "${SRC}" NAME_WE ) + set ( JIT_HEADER "${JIT_INCLUDE_DIR}/${SRC_NAME}_jit.h" ) + add_custom_command ( + OUTPUT "${JIT_HEADER}" + COMMAND Python3::Interpreter + "${PROJECT_SOURCE_DIR}/jit_generator.py" + --input "${SRC}" --output "${JIT_HEADER}" + DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/jit_generator.py" + COMMENT "JIT: generating ${SRC_NAME}_jit.h" + ) + list ( APPEND LAGRAPH_JIT_HEADERS "${JIT_HEADER}" ) +endforeach () + +add_custom_target ( LAGraphJITGenerate DEPENDS ${LAGRAPH_JIT_HEADERS} ) + #------------------------------------------------------------------------------- # dynamic lagraph library properties #------------------------------------------------------------------------------- @@ -99,6 +120,17 @@ if ( LAGRAPH_HAS_OPENMP ) endif ( ) endif ( ) +#------------------------------------------------------------------------------- +# JIT header dependency: ensure headers are generated before compilation +#------------------------------------------------------------------------------- + +if ( BUILD_SHARED_LIBS ) + add_dependencies ( LAGraph LAGraphJITGenerate ) +endif ( ) +if ( BUILD_STATIC_LIBS ) + add_dependencies ( LAGraph_static LAGraphJITGenerate ) +endif ( ) + #------------------------------------------------------------------------------- # applications #------------------------------------------------------------------------------- diff --git a/src/utility/LG_internal.h b/src/utility/LG_internal.h index 6d72dfc8cc..5195671fda 100644 --- a/src/utility/LG_internal.h +++ b/src/utility/LG_internal.h @@ -706,4 +706,15 @@ int LG_KindName #endif +// LG_JIT_KERNEL(name) marks a function or struct for JIT string extraction by +// jit_generator.py. During a CMake build (LG_JIT_BUILD is defined), it +// expands to nothing — the real string constants come from the generated +// _jit.h headers. Without LG_JIT_BUILD (e.g. in an IDE without compile +// flags), it declares a NULL placeholder so the IDE recognises the symbols. +#ifdef LG_JIT_BUILD +# define LG_JIT_KERNEL(name) +#else +# define LG_JIT_KERNEL(name) static const char *name##_JIT_STR = NULL; +#endif + #endif From 66139753e09e3459aa695fb4933a4e6ac6591508 Mon Sep 17 00:00:00 2001 From: GomezGab Date: Wed, 1 Apr 2026 17:06:40 -0500 Subject: [PATCH 2/8] msf JIT with macros and comments --- experimental/CMakeLists.txt | 4 +- experimental/algorithm/LAGr_SwapEdges.c | 59 +- experimental/algorithm/LAGraph_msf.c | 605 +++++++-------------- src/CMakeLists.txt | 4 +- src/utility/LG_internal.h | 4 +- jit_generator.py => tools/jit_generator.py | 11 +- 6 files changed, 234 insertions(+), 453 deletions(-) rename jit_generator.py => tools/jit_generator.py (86%) diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index d6e5d123de..f469b524eb 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -30,9 +30,9 @@ foreach ( SRC IN LISTS LAGRAPHX_LIB_SOURCES ) add_custom_command ( OUTPUT "${JIT_HEADER}" COMMAND Python3::Interpreter - "${PROJECT_SOURCE_DIR}/jit_generator.py" + "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" --input "${SRC}" --output "${JIT_HEADER}" - DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/jit_generator.py" + DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" COMMENT "JIT: generating ${SRC_NAME}_jit.h" ) list ( APPEND LAGRAPHX_JIT_HEADERS "${JIT_HEADER}" ) diff --git a/experimental/algorithm/LAGr_SwapEdges.c b/experimental/algorithm/LAGr_SwapEdges.c index e34b39e71e..9dfee32e42 100755 --- a/experimental/algorithm/LAGr_SwapEdges.c +++ b/experimental/algorithm/LAGr_SwapEdges.c @@ -115,9 +115,10 @@ typedef struct { } LG_SE_swap_type32; LG_JIT_KERNEL(LG_SE_swap_bc64) -void LG_SE_swap_bc64 -(LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, GrB_Index I, GrB_Index J, const bool *y) -{ +void LG_SE_swap_bc64 ( + LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, + GrB_Index I, GrB_Index J, const bool *y +) { memcpy(z, x, sizeof(*z)) ; //unnessesary when aliassed but done for safety. if(z->a == z->c || z->b == z->c || z->a == z->d || z->b == z->d ) return; if(I & 1) @@ -134,16 +135,17 @@ void LG_SE_swap_bc64 } } LG_JIT_KERNEL(LG_SE_swap_bc32) -void LG_SE_swap_bc32 -(LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, GrB_Index I, GrB_Index J, const bool *y) -{ +void LG_SE_swap_bc32( + LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, + GrB_Index I, GrB_Index J, const bool *y +) { memcpy(z, x, sizeof(*z)) ; //unnessesary when aliassed but done for safety. if(z->a == z->c || z->b == z->c || z->a == z->d || z->b == z->d ) return; if(I & 1) { uint32_t temp = z->d; z->d = z->b; - z->b = temp; + z->b = temp; } else { @@ -391,47 +393,59 @@ int LAGr_SwapEdges if(codei == GrB_UINT32_CODE) // Use uint32 if possible { GRB_TRY (GxB_Type_new( - &lg_edge, sizeof(LG_SE_edge_type32), "LG_SE_edge_type32", LG_SE_edge_type32_JIT_STR)) ; + &lg_edge, sizeof(LG_SE_edge_type32), + "LG_SE_edge_type32", LG_SE_edge_type32_JIT_STR)) ; GRB_TRY (GxB_Type_new( - &lg_swap, sizeof(LG_SE_swap_type32), "LG_SE_swap_type32", LG_SE_swap_type32_JIT_STR)) ; + &lg_swap, sizeof(LG_SE_swap_type32), + "LG_SE_swap_type32", LG_SE_swap_type32_JIT_STR)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge32), - GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge32", LG_SE_hash_edge32_JIT_STR + GrB_UINT64, lg_edge, GrB_UINT64, + "LG_SE_hash_edge32", LG_SE_hash_edge32_JIT_STR )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc32), - lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc32", LG_SE_swap_bc32_JIT_STR + lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc32", + LG_SE_swap_bc32_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( &second_edge, (GxB_binary_function) (&LG_SE_edge2nd32_edge), - lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd32_edge", LG_SE_edge2nd32_edge_JIT_STR + lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd32_edge", + LG_SE_edge2nd32_edge_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd32_bool), - lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", LG_SE_edge2nd32_bool_JIT_STR + lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", + LG_SE_edge2nd32_bool_JIT_STR )) ; } else //uint64 types { GRB_TRY (GxB_Type_new( - &lg_edge, sizeof(LG_SE_edge_type64), "LG_SE_edge_type64", LG_SE_edge_type64_JIT_STR)) ; + &lg_edge, sizeof(LG_SE_edge_type64), "LG_SE_edge_type64", + LG_SE_edge_type64_JIT_STR)) ; GRB_TRY (GxB_Type_new( - &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", LG_SE_edge_type64_JIT_STR)) ; + &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", + LG_SE_edge_type64_JIT_STR)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge64), - GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", LG_SE_hash_edge64_JIT_STR + GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", + LG_SE_hash_edge64_JIT_STR )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc64), - lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc64", LG_SE_swap_bc64_JIT_STR + lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc64", + LG_SE_swap_bc64_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( &second_edge, (GxB_binary_function) (&LG_SE_edge2nd64_edge), - lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd64_edge", LG_SE_edge2nd64_edge_JIT_STR + lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd64_edge", + LG_SE_edge2nd64_edge_JIT_STR )) ; GRB_TRY(GxB_BinaryOp_new( &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd64_bool), - lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", LG_SE_edge2nd64_bool_JIT_STR + lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", + LG_SE_edge2nd64_bool_JIT_STR )) ; } @@ -501,9 +515,10 @@ int LAGr_SwapEdges // Ramp GRB_TRY (GrB_Vector_new(&ramp_v, GrB_UINT64, e + 1)) ; - GRB_TRY (GrB_Vector_assign_UINT64 (ramp_v, NULL, NULL, 0, GrB_ALL, 0, NULL)) ; - GRB_TRY (GrB_Vector_apply_IndexOp_UINT64 (ramp_v, NULL, NULL, - GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; + GRB_TRY (GrB_Vector_assign_UINT64 ( + ramp_v, NULL, NULL, 0, GrB_ALL, 0, NULL)) ; + GRB_TRY (GrB_Vector_apply_IndexOp_UINT64 ( + ramp_v, NULL, NULL, GrB_ROWINDEX_INT64, ramp_v, 0, NULL)) ; GrB_Index ramp_size; // Constants diff --git a/experimental/algorithm/LAGraph_msf.c b/experimental/algorithm/LAGraph_msf.c index 3d5e8b8098..bd8c89b855 100755 --- a/experimental/algorithm/LAGraph_msf.c +++ b/experimental/algorithm/LAGraph_msf.c @@ -38,6 +38,7 @@ #include "LG_internal.h" #include #include +#include "LAGraph_msf_jit.h" //------------------------------------------------------------------------------ // tuple: a tuple containing (weight,index) @@ -47,77 +48,40 @@ // LG_MSF_tuple_fp is used if the input graph is FP32 or FP64. Likewise for the // other *_int and *_fp types and operators. -typedef struct -{ - int64_t wInt; - uint64_t idx; -} LG_MSF_tuple_int; - -#define TUPLE_INT \ -"typedef struct \n" \ -"{ \n" \ -" int64_t wInt; \n" \ -" uint64_t idx; \n" \ -"} LG_MSF_tuple_int;" - -typedef struct -{ - double wFp; - uint64_t idx; -} LG_MSF_tuple_fp; +#define LG_MSF_TUPLE(ctype) \ +typedef struct \ +{ \ + ctype wInt; \ + uint64_t idx; \ +} LG_MSF_tuple_##ctype; + +LG_JIT_KERNEL(LG_MSF_tuple_double) +LG_MSF_TUPLE(double) -#define TUPLE_FP \ -"typedef struct \n" \ -"{ \n" \ -" double wFp; \n" \ -" uint64_t idx; \n" \ -"} LG_MSF_tuple_fp;" +LG_JIT_KERNEL(LG_MSF_tuple_int64_t) +LG_MSF_TUPLE(int64_t) //------------------------------------------------------------------------------ // context_type: context for IndexUnaryOps (using the theta input) //------------------------------------------------------------------------------ -typedef struct -{ - uint64_t *parent; // parent of each vertex in the spanning forest - struct - { - int64_t wInt; - uint64_t idx; - } *w_partner; // partner vertex in the spanning forest -} LG_MSF_context_int; - -#define LG_MSF_CONTEXT_INT \ -"typedef struct \n" \ -"{ \n" \ -" uint64_t *parent; \n" \ -" struct \n" \ -" { \n" \ -" int64_t wInt; \n" \ -" uint64_t idx; \n" \ -" } *w_partner; \n" \ -"} LG_MSF_context_int;" - -typedef struct -{ - uint64_t *parent; // parent of each vertex in the spanning forest - struct - { - double wFp; - uint64_t idx; - } *w_partner; // partner vertex in the spanning forest -} LG_MSF_context_fp; - -#define LG_MSF_CONTEXT_FP \ -"typedef struct \n" \ -"{ \n" \ -" uint64_t *parent; \n" \ -" struct \n" \ -" { \n" \ -" double wFp; \n" \ -" uint64_t idx; \n" \ -" } *w_partner; \n" \ -"} LG_MSF_context_fp;" +#define LG_MSF_CONTEXT(ctype) \ +typedef struct \ +{ \ + uint64_t *parent; /* parent of each vertex in the spanning forest */ \ + struct \ + { \ + ctype wInt; \ + uint64_t idx; \ + } *w_partner; /* partner vertex in the spanning forest */ \ +} LG_MSF_context_##ctype; + +LG_JIT_KERNEL(LG_MSF_context_double) +LG_MSF_CONTEXT(double) + +LG_JIT_KERNEL(LG_MSF_context_int64_t) +LG_MSF_CONTEXT(int64_t) + //------------------------------------------------------------------------------ // selectEdge: index-unary operator to select edges of min weight @@ -128,59 +92,24 @@ typedef struct // 1. weight[i] == A(i, j) -- where weight[i] stores i's minimum edge weight // 2. parent[j] == partner[i] -- j belongs to the specified connected component -void LG_MSF_selectEdge_int -( - bool *z, - const int64_t *x, - GrB_Index i, - GrB_Index j, - const LG_MSF_context_int *theta -) -{ - (*z) = (theta->w_partner[i].wInt == *x) && - (theta->parent[j] == theta->w_partner[i].idx); -} - -#define SELECTEDGE_INT \ -"void LG_MSF_selectEdge_int \n"\ -"( \n"\ -" bool *z, \n"\ -" const int64_t *x, \n"\ -" GrB_Index i, \n"\ -" GrB_Index j, \n"\ -" const LG_MSF_context_int *theta \n"\ -") \n"\ -"{ \n"\ -" (*z) = (theta->w_partner[i].wInt == *x) && \n"\ -" (theta->parent[j] == theta->w_partner[i].idx);\n"\ -"}" - -void LG_MSF_selectEdge_fp -( - bool *z, - const double *x, - GrB_Index i, - GrB_Index j, - const LG_MSF_context_fp *theta -) -{ - (*z) = (theta->w_partner[i].wFp == *x) && - (theta->parent[j] == theta->w_partner[i].idx); +#define LG_MSF_SELECTEDGE(ctype) \ +void LG_MSF_selectEdge_##ctype \ +( \ + bool *z, \ + const ctype *x, \ + GrB_Index i, \ + GrB_Index j, \ + const LG_MSF_context_##ctype *theta \ +) \ +{ \ + (*z) = (theta->w_partner[i].wInt == *x) && \ + (theta->parent[j] == theta->w_partner[i].idx); \ } -#define SELECTEDGE_FP \ -"void LG_MSF_selectEdge_fp \n"\ -"( \n"\ -" bool *z, \n"\ -" const double *x, \n"\ -" GrB_Index i, \n"\ -" GrB_Index j, \n"\ -" const LG_MSF_context_fp *theta \n"\ -") \n"\ -"{ \n"\ -" (*z) = (theta->w_partner[i].wFp == *x) && \n"\ -" (theta->parent[j] == theta->w_partner[i].idx);\n"\ -"}" +LG_JIT_KERNEL(LG_MSF_selectEdge_double) +LG_MSF_SELECTEDGE(double) +LG_JIT_KERNEL(LG_MSF_selectEdge_int64_t) +LG_MSF_SELECTEDGE(int64_t) //------------------------------------------------------------------------------ // removeEdge: remove edge (i,j) when i and j have the same parent @@ -189,309 +118,136 @@ void LG_MSF_selectEdge_fp // edge removal: // A(i, j) is removed when parent[i] == parent[j] -void LG_MSF_removeEdge_int -( - bool *z, - const int64_t *x, - GrB_Index i, - GrB_Index j, - const LG_MSF_context_int *theta -) -{ - (*z) = (theta->parent[i] != theta->parent[j]); +#define LG_MSF_REMOVEEDGE(ctype) \ +void LG_MSF_removeEdge_##ctype \ +( \ + bool *z, \ + const ctype *x, \ + GrB_Index i, \ + GrB_Index j, \ + const LG_MSF_context_##ctype *theta \ +) \ +{ \ + (*z) = (theta->parent[i] != theta->parent[j]); \ } -#define REMOVEEDGE_INT \ -"void LG_MSF_removeEdge_int \n"\ -"( \n"\ -" bool *z, \n"\ -" const int64_t *x, \n"\ -" GrB_Index i, \n"\ -" GrB_Index j, \n"\ -" const LG_MSF_context_int *theta \n"\ -") \n"\ -"{ \n"\ -" (*z) = (theta->parent[i] != theta->parent[j]);\n"\ -"}" - -void LG_MSF_removeEdge_fp -( - bool *z, - const double *x, - GrB_Index i, - GrB_Index j, - const LG_MSF_context_fp *theta -) -{ - (*z) = (theta->parent[i] != theta->parent[j]); -} - -#define REMOVEEDGE_FP \ -"void LG_MSF_removeEdge_fp \n"\ -"( \n"\ -" bool *z, \n"\ -" const double *x, \n"\ -" GrB_Index i, \n"\ -" GrB_Index j, \n"\ -" const LG_MSF_context_fp *theta \n"\ -") \n"\ -"{ \n"\ -" (*z) = (theta->parent[i] != theta->parent[j]);\n"\ -"}" +LG_JIT_KERNEL(LG_MSF_removeEdge_double) +LG_MSF_REMOVEEDGE(double) +LG_JIT_KERNEL(LG_MSF_removeEdge_int64_t) +LG_MSF_REMOVEEDGE(int64_t) //------------------------------------------------------------------------------ // combine: create a tuple from a weight and an index //------------------------------------------------------------------------------ -void LG_MSF_combine_int -( - LG_MSF_tuple_int *z, - const int64_t *x, - const uint64_t *y -) -{ - z->wInt = *x; - z->idx = *y; -} - -#define COMBINE_INT \ -"void LG_MSF_combine_int \n"\ -"( \n"\ -" LG_MSF_tuple_int *z, \n"\ -" const int64_t *x, \n"\ -" const uint64_t *y \n"\ -") \n"\ -"{ \n"\ -" z->wInt = *x; \n"\ -" z->idx = *y; \n"\ -"}" - -void LG_MSF_combine_fp -( - LG_MSF_tuple_fp *z, - const double *x, - const uint64_t *y -) -{ - z->wFp = *x; - z->idx = *y; +#define LG_MSF_COMBINE(ctype) \ +void LG_MSF_combine_##ctype \ +( \ + LG_MSF_tuple_##ctype *z, \ + const ctype *x, \ + const uint64_t *y \ +) \ +{ \ + z->wInt = *x; \ + z->idx = *y; \ } -#define COMBINE_FP \ -"void LG_MSF_combine_fp \n"\ -"( \n"\ -" LG_MSF_tuple_fp *z, \n"\ -" const double *x, \n"\ -" const uint64_t *y \n"\ -") \n"\ -"{ \n"\ -" z->wFp = *x; \n"\ -" z->idx = *y; \n"\ -"}" +LG_JIT_KERNEL(LG_MSF_combine_double) +LG_MSF_COMBINE(double) +LG_JIT_KERNEL(LG_MSF_combine_int64_t) +LG_MSF_COMBINE(int64_t) //------------------------------------------------------------------------------ // get_first: get first item in a tuple (the weight) //------------------------------------------------------------------------------ -void LG_MSF_get_first_int (int64_t *y, const LG_MSF_tuple_int *x) -{ - *y = x->wInt; -} - -#define GET_FIRST_INT \ -"void LG_MSF_get_first_int (int64_t *y, const LG_MSF_tuple_int *x) \n" \ -"{ \n" \ -" *y = x->wInt; \n" \ -"}" - -void LG_MSF_get_first_fp (double *y, const LG_MSF_tuple_fp *x) -{ - *y = x->wFp; +#define LG_MSF_GET_FIRST(ctype) \ +void LG_MSF_get_first_##ctype (ctype *y, const LG_MSF_tuple_##ctype *x) \ +{ \ + *y = x->wInt; \ } - -#define GET_FIRST_FP \ -"void LG_MSF_get_first_fp (double *y, const LG_MSF_tuple_fp *x) \n" \ -"{ \n" \ -" *y = x->wFp; \n" \ -"}" +LG_JIT_KERNEL(LG_MSF_get_first_double) +LG_MSF_GET_FIRST(double) +LG_JIT_KERNEL(LG_MSF_get_first_int64_t) +LG_MSF_GET_FIRST(int64_t) //------------------------------------------------------------------------------ // get_second: get second item in a tuple (the index) //------------------------------------------------------------------------------ -void LG_MSF_get_second_int (uint64_t *y, const LG_MSF_tuple_int *x) -{ - *y = x->idx; -} - -#define GET_SECOND_INT \ -"void LG_MSF_get_second_int (uint64_t *y, const LG_MSF_tuple_int *x) \n" \ -"{ \n" \ -" *y = x->idx; \n" \ -"}" - -void LG_MSF_get_second_fp (uint64_t *y, const LG_MSF_tuple_fp *x) -{ - *y = x->idx; +#define LG_MSF_GET_SECOND(ctype) \ +void LG_MSF_get_second_##ctype (uint64_t *y, const LG_MSF_tuple_##ctype *x)\ +{ \ + *y = x->idx; \ } - -#define GET_SECOND_FP \ -"void LG_MSF_get_second_fp (uint64_t *y, const LG_MSF_tuple_fp *x) \n" \ -"{ \n" \ -" *y = x->idx; \n" \ -"}" +LG_JIT_KERNEL(LG_MSF_get_second_double) +LG_MSF_GET_SECOND(double) +LG_JIT_KERNEL(LG_MSF_get_second_int64_t) +LG_MSF_GET_SECOND(int64_t) //------------------------------------------------------------------------------ // tupleMin: z = the min tuple of x and y //------------------------------------------------------------------------------ -void LG_MSF_tupleMin_int -( - LG_MSF_tuple_int *z, - const LG_MSF_tuple_int *x, - const LG_MSF_tuple_int *y -) -{ - bool xSmaller = x->wInt < y->wInt || - (x->wInt == y->wInt && x->idx < y->idx); - z->wInt = (xSmaller)? x->wInt: y->wInt; - z->idx = (xSmaller)? x->idx: y->idx; -} - -#define TUPLEMIN_INT \ -"void LG_MSF_tupleMin_int \n"\ -"( \n"\ -" LG_MSF_tuple_int *z, \n"\ -" const LG_MSF_tuple_int *x, \n"\ -" const LG_MSF_tuple_int *y \n"\ -") \n"\ -"{ \n"\ -" bool xSmaller = x->wInt < y->wInt || \n"\ -" (x->wInt == y->wInt && x->idx < y->idx);\n"\ -" z->wInt = (xSmaller)? x->wInt: y->wInt; \n"\ -" z->idx = (xSmaller)? x->idx: y->idx; \n"\ -"}" - -void LG_MSF_tupleMin_fp -( - LG_MSF_tuple_fp *z, - const LG_MSF_tuple_fp *x, - const LG_MSF_tuple_fp *y -) -{ - bool xSmaller = x->wFp < y->wFp || (x->wFp == y->wFp && x->idx < y->idx); - z->wFp = (xSmaller)? x->wFp: y->wFp; - z->idx = (xSmaller)? x->idx: y->idx; +#define LG_MSF_TUPLEMIN(ctype) \ +void LG_MSF_tupleMin_##ctype \ +( \ + LG_MSF_tuple_##ctype *z, \ + const LG_MSF_tuple_##ctype *x, \ + const LG_MSF_tuple_##ctype *y \ +) \ +{ \ + bool xSmaller = x->wInt < y->wInt || \ + (x->wInt == y->wInt && x->idx < y->idx); \ + z->wInt = (xSmaller)? x->wInt: y->wInt; \ + z->idx = (xSmaller)? x->idx: y->idx; \ } -#define TUPLEMIN_FP \ -"void LG_MSF_tupleMin_fp \n"\ -"( \n"\ -" LG_MSF_tuple_fp *z, \n"\ -" const LG_MSF_tuple_fp *x, \n"\ -" const LG_MSF_tuple_fp *y \n"\ -") \n"\ -"{ \n"\ -" bool xSmaller = x->wFp < y->wFp || (x->wFp == y->wFp && x->idx < y->idx);\n"\ -" z->wFp = (xSmaller)? x->wFp: y->wFp; \n"\ -" z->idx = (xSmaller)? x->idx: y->idx; \n"\ -"}" +LG_JIT_KERNEL(LG_MSF_tupleMin_double) +LG_MSF_TUPLEMIN(double) +LG_JIT_KERNEL(LG_MSF_tupleMin_int64_t) +LG_MSF_TUPLEMIN(int64_t) //------------------------------------------------------------------------------ // tuple2nd: z = y //------------------------------------------------------------------------------ -void LG_MSF_tuple2nd_int -( - LG_MSF_tuple_int *z, - const void *x, - const LG_MSF_tuple_int *y -) -{ - z->wInt = y->wInt; - z->idx = y->idx; +#define LG_MSF_TUPLE2ND(ctype) \ +void LG_MSF_tuple2nd_##ctype \ +( \ + LG_MSF_tuple_##ctype *z, \ + const void *x, \ + const LG_MSF_tuple_##ctype *y \ +) \ +{ \ + z->wInt = y->wInt; \ + z->idx = y->idx; \ } -#define TUPLE2ND_INT \ -"void LG_MSF_tuple2nd_int \n"\ -"( \n"\ -" LG_MSF_tuple_int *z, \n"\ -" const void *x, \n"\ -" const LG_MSF_tuple_int *y\n"\ -") \n"\ -"{ \n"\ -" z->wInt = y->wInt; \n"\ -" z->idx = y->idx; \n"\ -"}" - -void LG_MSF_tuple2nd_fp -( - LG_MSF_tuple_fp *z, - const void *x, - const LG_MSF_tuple_fp *y -) -{ - z->wFp = y->wFp; - z->idx = y->idx; -} - -#define TUPLE2ND_FP \ -"void LG_MSF_tuple2nd_fp \n"\ -"( \n"\ -" LG_MSF_tuple_fp *z, \n"\ -" const void *x, \n"\ -" const LG_MSF_tuple_fp *y\n"\ -") \n"\ -"{ \n"\ -" z->wFp = y->wFp; \n"\ -" z->idx = y->idx; \n"\ -"}" +LG_JIT_KERNEL(LG_MSF_tuple2nd_double) +LG_MSF_TUPLE2ND(double) +LG_JIT_KERNEL(LG_MSF_tuple2nd_int64_t) +LG_MSF_TUPLE2ND(int64_t) //------------------------------------------------------------------------------ // tupleEq: true if two tuples are equal //------------------------------------------------------------------------------ -void LG_MSF_tupleEq_int -( - bool *z, - const LG_MSF_tuple_int *x, - const LG_MSF_tuple_int *y -) -{ - *z = (x->wInt == y->wInt) && (x->idx == y->idx); -} - -#define TUPLEEQ_INT \ -"void LG_MSF_tupleEq_int \n"\ -"( \n"\ -" bool *z, \n"\ -" const LG_MSF_tuple_int *x, \n"\ -" const LG_MSF_tuple_int *y \n"\ -") \n"\ -"{ \n"\ -" *z = (x->wInt == y->wInt) && (x->idx == y->idx);\n"\ -"}" - -void LG_MSF_tupleEq_fp -( - bool *z, - const LG_MSF_tuple_fp *x, - const LG_MSF_tuple_fp *y -) -{ - *z = (x->wFp == y->wFp) && (x->idx == y->idx); +#define LG_MSF_TUPLEEQ(ctype) \ +void LG_MSF_tupleEq_##ctype \ +( \ + bool *z, \ + const LG_MSF_tuple_##ctype *x, \ + const LG_MSF_tuple_##ctype *y \ +) \ +{ \ + *z = (x->wInt == y->wInt) && (x->idx == y->idx); \ } -#define TUPLEEQ_FP \ -"void LG_MSF_tupleEq_fp \n"\ -"( \n"\ -" bool *z, \n"\ -" const LG_MSF_tuple_fp *x, \n"\ -" const LG_MSF_tuple_fp *y \n"\ -") \n"\ -"{ \n"\ -" *z = (x->wFp == y->wFp) && (x->idx == y->idx);\n"\ -"}" +LG_JIT_KERNEL(LG_MSF_tupleEq_double) +LG_MSF_TUPLEEQ(double) +LG_JIT_KERNEL(LG_MSF_tupleEq_int64_t) +LG_MSF_TUPLEEQ(int64_t) //------------------------------------------------------------------------------ @@ -613,10 +369,10 @@ int LAGraph_msf #if LG_SUITESPARSE_GRAPHBLAS_V10 LG_CLEAR_MSG ; - LG_MSF_context_int context_int = {.parent = NULL, .w_partner = NULL } ; - LG_MSF_context_fp context_fp = {.parent = NULL, .w_partner = NULL } ; - LG_MSF_tuple_int inf_int = {.wInt = INT64_MAX, .idx = UINT64_MAX}; - LG_MSF_tuple_fp inf_fp = {.wFp = INFINITY , .idx = UINT64_MAX}; + LG_MSF_context_int64_t context_int = {.parent = NULL, .w_partner = NULL } ; + LG_MSF_context_double context_fp = {.parent = NULL, .w_partner = NULL } ; + LG_MSF_tuple_int64_t inf_int = {.wInt = INT64_MAX, .idx = UINT64_MAX}; + LG_MSF_tuple_double inf_fp = {.wInt = INFINITY , .idx = UINT64_MAX}; GrB_Info info; GrB_Index n; @@ -699,55 +455,59 @@ int LAGraph_msf // types and ops for INT64 weights //---------------------------------------------------------------------- - GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_int), - "LG_MSF_tuple_int", TUPLE_INT)) ; + GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_int64_t), + "LG_MSF_tuple_int64_t", LG_MSF_tuple_int64_t_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &combine, (GxB_binary_function) LG_MSF_combine_int, + &combine, (GxB_binary_function) LG_MSF_combine_int64_t, tuple, weight_type, GrB_UINT64, - "LG_MSF_combine_int", COMBINE_INT)) ; + "LG_MSF_combine_int64_t", LG_MSF_combine_int64_t_JIT_STR)) ; GRB_TRY (GrB_Scalar_setElement_INT64(max_weight, INT64_MAX)) ; GRB_TRY (GxB_BinaryOp_new ( - &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_int, + &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_int64_t, tuple, tuple, tuple, - "LG_MSF_tupleMin_int", TUPLEMIN_INT)) ; + "LG_MSF_tupleMin_int64_t", LG_MSF_tupleMin_int64_t_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_int, + &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_int64_t, tuple, GrB_BOOL, tuple, - "LG_MSF_tuple2nd_int", TUPLE2ND_INT)) ; + "LG_MSF_tuple2nd_int64_t", LG_MSF_tuple2nd_int64_t_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_int, + &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_int64_t, GrB_BOOL, tuple, tuple, - "LG_MSF_tupleEq_int", TUPLEEQ_INT)) ; + "LG_MSF_tupleEq_int64_t", LG_MSF_tupleEq_int64_t_JIT_STR)) ; inf = (void *) (&inf_int) ; GRB_TRY (GxB_UnaryOp_new ( - &get_first, (GxB_unary_function) LG_MSF_get_first_int, weight_type, - tuple, "LG_MSF_get_first_int", GET_FIRST_INT)) ; + &get_first, (GxB_unary_function) LG_MSF_get_first_int64_t, + weight_type, tuple, + "LG_MSF_get_first_int64_t", LG_MSF_get_first_int64_t_JIT_STR)) ; GRB_TRY (GxB_UnaryOp_new ( - &get_second, (GxB_unary_function) LG_MSF_get_second_int, GrB_UINT64, - tuple, "LG_MSF_get_second_int", GET_SECOND_INT)) ; + &get_second, (GxB_unary_function) LG_MSF_get_second_int64_t, + GrB_UINT64, tuple, + "LG_MSF_get_second_int64_t", LG_MSF_get_second_int64_t_JIT_STR)) ; // context type GRB_TRY (GxB_Type_new ( - &context_type, sizeof (LG_MSF_context_int), - "LG_MSF_context_int", LG_MSF_CONTEXT_INT)) ; + &context_type, sizeof (LG_MSF_context_int64_t), + "LG_MSF_context_int64_t", LG_MSF_context_int64_t_JIT_STR)) ; // ops for GrB_select GRB_TRY(GxB_IndexUnaryOp_new ( - &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_int, + &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_int64_t, GrB_BOOL, weight_type, context_type, - "LG_MSF_selectEdge_int", SELECTEDGE_INT)) ; + "LG_MSF_selectEdge_int64_t", LG_MSF_selectEdge_int64_t_JIT_STR)) ; GRB_TRY(GxB_IndexUnaryOp_new ( - &removeEdge, (void *) LG_MSF_removeEdge_int, GrB_BOOL, weight_type, - context_type, "LG_MSF_removeEdge_int", REMOVEEDGE_INT)) ; + &removeEdge, (void *) LG_MSF_removeEdge_int64_t, GrB_BOOL, + weight_type, context_type, + "LG_MSF_removeEdge_int64_t", LG_MSF_removeEdge_int64_t_JIT_STR + )) ; } else @@ -757,54 +517,57 @@ int LAGraph_msf // types and ops for FP64 weights //---------------------------------------------------------------------- - GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_fp), - "LG_MSF_tuple_fp", TUPLE_FP)) ; + GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_double), + "LG_MSF_tuple_double", LG_MSF_tuple_double_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &combine, (GxB_binary_function) LG_MSF_combine_fp, + &combine, (GxB_binary_function) LG_MSF_combine_double, tuple, weight_type, GrB_UINT64, - "LG_MSF_combine_fp", COMBINE_FP)) ; + "LG_MSF_combine_double", LG_MSF_combine_double_JIT_STR)) ; GRB_TRY (GrB_Scalar_setElement_FP64(max_weight, INFINITY)) ; GRB_TRY (GxB_BinaryOp_new ( - &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_fp, + &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_double, tuple, tuple, tuple, - "LG_MSF_tupleMin_fp", TUPLEMIN_FP)) ; + "LG_MSF_tupleMin_double", LG_MSF_tupleMin_double_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_fp, + &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_double, tuple, GrB_BOOL, tuple, - "LG_MSF_tuple2nd_fp", TUPLE2ND_FP)) ; + "LG_MSF_tuple2nd_double", LG_MSF_tuple2nd_double_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new ( - &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_fp, + &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_double, GrB_BOOL, tuple, tuple, - "LG_MSF_tupleEq_fp", TUPLEEQ_FP)) ; + "LG_MSF_tupleEq_double", LG_MSF_tupleEq_double_JIT_STR)) ; inf = (void *) (&inf_fp) ; GRB_TRY (GxB_UnaryOp_new ( - &get_first, (GxB_unary_function) LG_MSF_get_first_fp, weight_type, - tuple, "LG_MSF_get_first_fp", GET_FIRST_FP)) ; + &get_first, (GxB_unary_function) LG_MSF_get_first_double, + weight_type, tuple, + "LG_MSF_get_first_double", LG_MSF_get_first_double_JIT_STR)) ; GRB_TRY (GxB_UnaryOp_new ( - &get_second, (GxB_unary_function) LG_MSF_get_second_fp, GrB_UINT64, - tuple, "LG_MSF_get_second_fp", GET_SECOND_FP)) ; + &get_second, (GxB_unary_function) LG_MSF_get_second_double, + GrB_UINT64, tuple, + "LG_MSF_get_second_double", LG_MSF_get_second_double_JIT_STR)) ; GRB_TRY (GxB_Type_new ( - &context_type, sizeof (LG_MSF_context_fp), - "LG_MSF_context_fp", LG_MSF_CONTEXT_FP)) ; + &context_type, sizeof (LG_MSF_context_double), + "LG_MSF_context_double", LG_MSF_context_double_JIT_STR)) ; // ops for GrB_select GRB_TRY(GxB_IndexUnaryOp_new ( - &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_fp, + &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_double, GrB_BOOL, weight_type, context_type, - "LG_MSF_selectEdge_fp", SELECTEDGE_FP)) ; + "LG_MSF_selectEdge_double", LG_MSF_selectEdge_double_JIT_STR)) ; GRB_TRY(GxB_IndexUnaryOp_new ( - &removeEdge, (void *) LG_MSF_removeEdge_fp, GrB_BOOL, weight_type, - context_type, "LG_MSF_removeEdge_fp", REMOVEEDGE_FP)) ; + &removeEdge, (void *) LG_MSF_removeEdge_double, + GrB_BOOL, weight_type, context_type, + "LG_MSF_removeEdge_double", LG_MSF_removeEdge_double_JIT_STR)) ; } GRB_TRY (GrB_Monoid_new_UDT (&tupleMin_monoid, tupleMin, inf)) ; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5f62698186..7386ef07e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,9 +28,9 @@ foreach ( SRC IN LISTS LAGRAPH_LIB_SOURCES ) add_custom_command ( OUTPUT "${JIT_HEADER}" COMMAND Python3::Interpreter - "${PROJECT_SOURCE_DIR}/jit_generator.py" + "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" --input "${SRC}" --output "${JIT_HEADER}" - DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/jit_generator.py" + DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" COMMENT "JIT: generating ${SRC_NAME}_jit.h" ) list ( APPEND LAGRAPH_JIT_HEADERS "${JIT_HEADER}" ) diff --git a/src/utility/LG_internal.h b/src/utility/LG_internal.h index 5195671fda..3d16c6c549 100644 --- a/src/utility/LG_internal.h +++ b/src/utility/LG_internal.h @@ -708,8 +708,8 @@ int LG_KindName // LG_JIT_KERNEL(name) marks a function or struct for JIT string extraction by // jit_generator.py. During a CMake build (LG_JIT_BUILD is defined), it -// expands to nothing — the real string constants come from the generated -// _jit.h headers. Without LG_JIT_BUILD (e.g. in an IDE without compile +// expands to nothing - the real string constants come from the generated +// _jit.h headers. Without LG_JIT_BUILD (ie. in an IDE without compile // flags), it declares a NULL placeholder so the IDE recognises the symbols. #ifdef LG_JIT_BUILD # define LG_JIT_KERNEL(name) diff --git a/jit_generator.py b/tools/jit_generator.py similarity index 86% rename from jit_generator.py rename to tools/jit_generator.py index f613854bb2..420d678441 100644 --- a/jit_generator.py +++ b/tools/jit_generator.py @@ -19,7 +19,6 @@ def on_error(self, file, line, msg): def _preprocess(input_file): pp = _Preprocessor() - pp.line_directive = None # suppress #line markers in output pp.define("LG_JIT_KERNEL(name) __LG_JIT_KERNEL__(name)") pp.parse(open(input_file).read(), input_file) out = io.StringIO() @@ -31,7 +30,7 @@ def _preprocess(input_file): def extract_jit_kernels(input_file): - # 1. Expand all macros, passing through any #include directives that can't be resolved + # Expand all macros, passing through any #include directives that can't be resolved expanded_code = _preprocess(input_file) lines = expanded_code.splitlines() @@ -48,7 +47,7 @@ def extract_jit_kernels(input_file): while i < len(lines) and not lines[i].strip(): i += 1 - # 2. Brace-count to find the end of the definition + # Brace-count to find the end of the definition content = [] brace_count = 0 started = False @@ -80,6 +79,8 @@ def write_jit_header(input_file, output_file): """Generate a JIT header for input_file and write it to output_file.""" kernels = extract_jit_kernels(input_file) with open(output_file, "w") as f: + f.write("// This is a generated file containing all of the JIT strings\n") + f.write("// for the kernels defined in " + input_file + "\n") f.write("#pragma once\n") for name, string_lit in kernels.items(): f.write(f"static const char* {name}_JIT_STR = {string_lit};\n") @@ -90,6 +91,8 @@ def write_jit_header(input_file, output_file): description="Extract LG_JIT_KERNEL-marked definitions from a C file as string literals." ) parser.add_argument("--input", required=True, help="Input C source file") - parser.add_argument("--output", required=True, help="Output header file to generate") + parser.add_argument( + "--output", required=True, help="Output header file to generate" + ) args = parser.parse_args() write_jit_header(args.input, args.output) From 997ab3e38f76bf52045c2ce8b4c38e82fb26fd95 Mon Sep 17 00:00:00 2001 From: GomezGab Date: Wed, 1 Apr 2026 17:12:11 -0500 Subject: [PATCH 3/8] install necessarry libraries on github action --- .github/workflows/build-arch-emu.yaml | 3 +++ .github/workflows/build.yml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/build-arch-emu.yaml b/.github/workflows/build-arch-emu.yaml index a864cd7949..13a4788254 100644 --- a/.github/workflows/build-arch-emu.yaml +++ b/.github/workflows/build-arch-emu.yaml @@ -55,6 +55,8 @@ jobs: libtool git sudo + python3 + py3-pip - name: disable QEMU emulation if: matrix.arch == 'armv7' @@ -79,6 +81,7 @@ jobs: - name: build and test LAGraph run: | + pip3 install pcpp cd build cmake .. JOBS=2 make diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3523ac8d0..36b5c9d599 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,7 @@ jobs: - name: Install tools for build run: | sudo apt install -y lcov + pip3 install pcpp - name: Build GraphBLAS run: | @@ -82,6 +83,7 @@ jobs: brew tap-new libomp/cask brew extract --version=14.0.6 libomp libomp/cask brew install libomp@14.0.6 + pip3 install --break-system-packages pcpp - name: Build GraphBLAS run: | From 6c3a90200b3fe6510a394875f7bf596c90399e6d Mon Sep 17 00:00:00 2001 From: Gabriel Gomez Date: Sat, 4 Apr 2026 18:30:25 -0500 Subject: [PATCH 4/8] simplify build and use native C macro expansion --- experimental/CMakeLists.txt | 32 ------ experimental/algorithm/LAGr_SwapEdges.c | 62 ++++++------ .../algorithm/LAGraph_RichClubCoefficient.c | 25 +++-- experimental/algorithm/LAGraph_msf.c | 64 ++++-------- src/CMakeLists.txt | 32 ------ src/utility/LG_internal.h | 16 +-- tools/jit_generator.py | 98 ------------------- 7 files changed, 68 insertions(+), 261 deletions(-) delete mode 100644 tools/jit_generator.py diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index f469b524eb..7f14c63122 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -19,27 +19,6 @@ include_directories ( file ( GLOB LAGRAPHX_LIB_SOURCES "utility/*.c" "algorithm/*.c" ) -#------------------------------------------------------------------------------- -# JIT kernel header generation (one _jit.h per source file) -#------------------------------------------------------------------------------- - -set ( LAGRAPHX_JIT_HEADERS "" ) -foreach ( SRC IN LISTS LAGRAPHX_LIB_SOURCES ) - get_filename_component ( SRC_NAME "${SRC}" NAME_WE ) - set ( JIT_HEADER "${JIT_INCLUDE_DIR}/${SRC_NAME}_jit.h" ) - add_custom_command ( - OUTPUT "${JIT_HEADER}" - COMMAND Python3::Interpreter - "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" - --input "${SRC}" --output "${JIT_HEADER}" - DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" - COMMENT "JIT: generating ${SRC_NAME}_jit.h" - ) - list ( APPEND LAGRAPHX_JIT_HEADERS "${JIT_HEADER}" ) -endforeach () - -add_custom_target ( LAGraphXJITGenerate DEPENDS ${LAGRAPHX_JIT_HEADERS} ) - #------------------------------------------------------------------------------- # dynamic lagraphx library properties #------------------------------------------------------------------------------- @@ -128,17 +107,6 @@ if ( NOT NO_LIBM ) endif ( ) endif ( ) -#------------------------------------------------------------------------------- -# JIT header dependency: ensure headers are generated before compilation -#------------------------------------------------------------------------------- - -if ( BUILD_SHARED_LIBS ) - add_dependencies ( LAGraphX LAGraphXJITGenerate ) -endif ( ) -if ( BUILD_STATIC_LIBS ) - add_dependencies ( LAGraphX_static LAGraphXJITGenerate ) -endif ( ) - #------------------------------------------------------------------------------- # applications #------------------------------------------------------------------------------- diff --git a/experimental/algorithm/LAGr_SwapEdges.c b/experimental/algorithm/LAGr_SwapEdges.c index 9dfee32e42..c47ad0c045 100755 --- a/experimental/algorithm/LAGr_SwapEdges.c +++ b/experimental/algorithm/LAGr_SwapEdges.c @@ -77,44 +77,43 @@ #include "LG_internal.h" #include "LAGraphX.h" -#include "LAGr_SwapEdges_jit.h" -LG_JIT_KERNEL(LG_SE_shift_and) +LG_JIT_KERNEL( void LG_SE_shift_and (uint16_t *z, const uint16_t *x) { (*z) = (*x) & ((*x) << 8); (*z) |= (*z) >> 8; -} +}, LG_SE_shift_and) -LG_JIT_KERNEL(LG_SE_edge_type64) +LG_JIT_KERNEL( typedef struct { uint64_t a; uint64_t b; -} LG_SE_edge_type64; +} LG_SE_edge_type64;, LG_SE_edge_type64) -LG_JIT_KERNEL(LG_SE_swap_type64) +LG_JIT_KERNEL( typedef struct { - uint64_t a; + uint64_t a; uint64_t b; - uint64_t c; + uint64_t c; uint64_t d; -} LG_SE_swap_type64; +} LG_SE_swap_type64;, LG_SE_swap_type64) -LG_JIT_KERNEL(LG_SE_edge_type32) +LG_JIT_KERNEL( typedef struct { uint32_t a; uint32_t b; -} LG_SE_edge_type32; +} LG_SE_edge_type32;, LG_SE_edge_type32) -LG_JIT_KERNEL(LG_SE_swap_type32) +LG_JIT_KERNEL( typedef struct { uint32_t a; uint32_t b; uint32_t c; uint32_t d; -} LG_SE_swap_type32; +} LG_SE_swap_type32;, LG_SE_swap_type32) -LG_JIT_KERNEL(LG_SE_swap_bc64) +LG_JIT_KERNEL( void LG_SE_swap_bc64 ( LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, GrB_Index I, GrB_Index J, const bool *y @@ -133,8 +132,9 @@ void LG_SE_swap_bc64 ( z->c = z->b; z->b = temp; } -} -LG_JIT_KERNEL(LG_SE_swap_bc32) +}, LG_SE_swap_bc64) + +LG_JIT_KERNEL( void LG_SE_swap_bc32( LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, GrB_Index I, GrB_Index J, const bool *y @@ -153,11 +153,11 @@ void LG_SE_swap_bc32( z->c = z->b; z->b = temp; } -} +}, LG_SE_swap_bc32) // using xorshift, from https://en.wikipedia.org/wiki/Xorshift // with a state of uint64_t, or xorshift64star. -LG_JIT_KERNEL(LG_SE_hash_edge64) +LG_JIT_KERNEL( void LG_SE_hash_edge64 (uint64_t *z, const LG_SE_edge_type64 *x, const uint64_t *mask) { @@ -167,9 +167,9 @@ void LG_SE_hash_edge64 (*z) ^= (x->a < x->b)? x->a: x->b; (*z) ^= (*z) << 17; (*z) &= (*mask); -} +}, LG_SE_hash_edge64) -LG_JIT_KERNEL(LG_SE_hash_edge32) +LG_JIT_KERNEL( void LG_SE_hash_edge32 (uint64_t *z, const LG_SE_edge_type32 *x, const uint64_t *mask) { @@ -179,46 +179,46 @@ void LG_SE_hash_edge32 (*z) ^= (uint64_t)((x->a < x->b)? x->a: x->b); (*z) ^= (*z) << 17; (*z) &= (*mask); -} +}, LG_SE_hash_edge32) -LG_JIT_KERNEL(LG_SE_add_term) +LG_JIT_KERNEL( void LG_SE_add_term (int8_t *z, const int8_t *x, const int8_t *y) { (*z) = (*x) | (*y) + ((int8_t)1 & (*x) & (*y)) ; -} +}, LG_SE_add_term) -LG_JIT_KERNEL(LG_SE_edge2nd64_bool) +LG_JIT_KERNEL( void LG_SE_edge2nd64_bool (LG_SE_edge_type64 *z, const bool *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; -} +}, LG_SE_edge2nd64_bool) -LG_JIT_KERNEL(LG_SE_edge2nd32_bool) +LG_JIT_KERNEL( void LG_SE_edge2nd32_bool (LG_SE_edge_type32 *z, const bool *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; -} +}, LG_SE_edge2nd32_bool) -LG_JIT_KERNEL(LG_SE_edge2nd64_edge) +LG_JIT_KERNEL( void LG_SE_edge2nd64_edge (LG_SE_edge_type64 *z, const LG_SE_edge_type64 *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; -} +}, LG_SE_edge2nd64_edge) -LG_JIT_KERNEL(LG_SE_edge2nd32_edge) +LG_JIT_KERNEL( void LG_SE_edge2nd32_edge (LG_SE_edge_type32 *z, const LG_SE_edge_type32 *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; -} +}, LG_SE_edge2nd32_edge) // FIXME: make loopTry, loopMin, totSwaps, seed inputs GrB_Scalar // FIXME: make pSwaps GrB_Scalar diff --git a/experimental/algorithm/LAGraph_RichClubCoefficient.c b/experimental/algorithm/LAGraph_RichClubCoefficient.c index 2eb2f4cc3b..5ff0aa5ca1 100755 --- a/experimental/algorithm/LAGraph_RichClubCoefficient.c +++ b/experimental/algorithm/LAGraph_RichClubCoefficient.c @@ -64,21 +64,19 @@ #include "LG_internal.h" #include "LAGraphX.h" -#include "LAGraph_RichClubCoefficient_jit.h" -typedef void (*LAGraph_binary_function) (void *, const void *, const void *) ; - -LG_JIT_KERNEL(LG_RCC_iseq_2islt) +LG_JIT_KERNEL( void LG_RCC_iseq_2islt(int64_t *z, const int64_t *x, const int64_t *y) { (*z) = (int64_t)((*x < *y) + (*x <= *y)) ; -} +}, LG_RCC_iseq_2islt) -LG_JIT_KERNEL(LG_RCC_rich_club_formula) +LG_JIT_KERNEL( void LG_RCC_rich_club_formula(double *z, const int64_t *x, const int64_t *y) { (*z) = ((double)(*x)) / (((double)(*y)) * (((double)(*y)) - 1.0)); -} +}, LG_RCC_rich_club_formula) + int LAGraph_RichClubCoefficient ( // output: @@ -182,18 +180,19 @@ int LAGraph_RichClubCoefficient GRB_TRY (GrB_Vector_new(&node_edges, GrB_INT64, n)) ; #if LAGRAPH_SUITESPARSE GRB_TRY (GxB_BinaryOp_new( - &iseq_2lt, (LAGraph_binary_function) (&LG_RCC_iseq_2islt), - GrB_INT64, GrB_INT64, GrB_INT64, "LG_RCC_iseq_2islt", LG_RCC_iseq_2islt_JIT_STR)) ; + &iseq_2lt, (GxB_binary_function) (&LG_RCC_iseq_2islt), + GrB_INT64, GrB_INT64, GrB_INT64, "LG_RCC_iseq_2islt", +LG_RCC_iseq_2islt_JIT_STR)) ; GRB_TRY (GxB_BinaryOp_new( - &rcCalculation, (LAGraph_binary_function) (&LG_RCC_rich_club_formula), - GrB_FP64, GrB_INT64, GrB_INT64, + &rcCalculation, (GxB_binary_function) (&LG_RCC_rich_club_formula), + GrB_FP64, GrB_INT64, GrB_INT64, "LG_RCC_rich_club_formula", LG_RCC_rich_club_formula_JIT_STR)) ; #else GRB_TRY (GrB_BinaryOp_new( - &iseq_2lt, (LAGraph_binary_function) (&LG_RCC_iseq_2islt), + &iseq_2lt, (GxB_binary_function) (&LG_RCC_iseq_2islt), GrB_INT64, GrB_INT64, GrB_INT64)) ; GRB_TRY (GrB_BinaryOp_new( - &rcCalculation, (LAGraph_binary_function) (&LG_RCC_rich_club_formula), + &rcCalculation, (GxB_binary_function) (&LG_RCC_rich_club_formula), GrB_FP64, GrB_INT64, GrB_INT64 )) ; #endif diff --git a/experimental/algorithm/LAGraph_msf.c b/experimental/algorithm/LAGraph_msf.c index bd8c89b855..cba347b7fd 100755 --- a/experimental/algorithm/LAGraph_msf.c +++ b/experimental/algorithm/LAGraph_msf.c @@ -38,7 +38,6 @@ #include "LG_internal.h" #include #include -#include "LAGraph_msf_jit.h" //------------------------------------------------------------------------------ // tuple: a tuple containing (weight,index) @@ -55,11 +54,9 @@ typedef struct \ uint64_t idx; \ } LG_MSF_tuple_##ctype; -LG_JIT_KERNEL(LG_MSF_tuple_double) -LG_MSF_TUPLE(double) +LG_JIT_KERNEL(LG_MSF_TUPLE(double), LG_MSF_tuple_double) -LG_JIT_KERNEL(LG_MSF_tuple_int64_t) -LG_MSF_TUPLE(int64_t) +LG_JIT_KERNEL(LG_MSF_TUPLE(int64_t), LG_MSF_tuple_int64_t) //------------------------------------------------------------------------------ // context_type: context for IndexUnaryOps (using the theta input) @@ -76,12 +73,8 @@ typedef struct \ } *w_partner; /* partner vertex in the spanning forest */ \ } LG_MSF_context_##ctype; -LG_JIT_KERNEL(LG_MSF_context_double) -LG_MSF_CONTEXT(double) - -LG_JIT_KERNEL(LG_MSF_context_int64_t) -LG_MSF_CONTEXT(int64_t) - +LG_JIT_KERNEL(LG_MSF_CONTEXT(double), LG_MSF_context_double) +LG_JIT_KERNEL(LG_MSF_CONTEXT(int64_t), LG_MSF_context_int64_t) //------------------------------------------------------------------------------ // selectEdge: index-unary operator to select edges of min weight @@ -106,10 +99,8 @@ void LG_MSF_selectEdge_##ctype \ (theta->parent[j] == theta->w_partner[i].idx); \ } -LG_JIT_KERNEL(LG_MSF_selectEdge_double) -LG_MSF_SELECTEDGE(double) -LG_JIT_KERNEL(LG_MSF_selectEdge_int64_t) -LG_MSF_SELECTEDGE(int64_t) +LG_JIT_KERNEL(LG_MSF_SELECTEDGE(double), LG_MSF_selectEdge_double) +LG_JIT_KERNEL(LG_MSF_SELECTEDGE(int64_t), LG_MSF_selectEdge_int64_t) //------------------------------------------------------------------------------ // removeEdge: remove edge (i,j) when i and j have the same parent @@ -131,10 +122,8 @@ void LG_MSF_removeEdge_##ctype \ (*z) = (theta->parent[i] != theta->parent[j]); \ } -LG_JIT_KERNEL(LG_MSF_removeEdge_double) -LG_MSF_REMOVEEDGE(double) -LG_JIT_KERNEL(LG_MSF_removeEdge_int64_t) -LG_MSF_REMOVEEDGE(int64_t) +LG_JIT_KERNEL(LG_MSF_REMOVEEDGE(double), LG_MSF_removeEdge_double) +LG_JIT_KERNEL(LG_MSF_REMOVEEDGE(int64_t), LG_MSF_removeEdge_int64_t) //------------------------------------------------------------------------------ // combine: create a tuple from a weight and an index @@ -152,10 +141,8 @@ void LG_MSF_combine_##ctype \ z->idx = *y; \ } -LG_JIT_KERNEL(LG_MSF_combine_double) -LG_MSF_COMBINE(double) -LG_JIT_KERNEL(LG_MSF_combine_int64_t) -LG_MSF_COMBINE(int64_t) +LG_JIT_KERNEL(LG_MSF_COMBINE(double), LG_MSF_combine_double) +LG_JIT_KERNEL(LG_MSF_COMBINE(int64_t), LG_MSF_combine_int64_t) //------------------------------------------------------------------------------ // get_first: get first item in a tuple (the weight) @@ -166,10 +153,8 @@ void LG_MSF_get_first_##ctype (ctype *y, const LG_MSF_tuple_##ctype *x) \ { \ *y = x->wInt; \ } -LG_JIT_KERNEL(LG_MSF_get_first_double) -LG_MSF_GET_FIRST(double) -LG_JIT_KERNEL(LG_MSF_get_first_int64_t) -LG_MSF_GET_FIRST(int64_t) +LG_JIT_KERNEL(LG_MSF_GET_FIRST(double), LG_MSF_get_first_double) +LG_JIT_KERNEL(LG_MSF_GET_FIRST(int64_t), LG_MSF_get_first_int64_t) //------------------------------------------------------------------------------ // get_second: get second item in a tuple (the index) @@ -180,10 +165,8 @@ void LG_MSF_get_second_##ctype (uint64_t *y, const LG_MSF_tuple_##ctype *x)\ { \ *y = x->idx; \ } -LG_JIT_KERNEL(LG_MSF_get_second_double) -LG_MSF_GET_SECOND(double) -LG_JIT_KERNEL(LG_MSF_get_second_int64_t) -LG_MSF_GET_SECOND(int64_t) +LG_JIT_KERNEL(LG_MSF_GET_SECOND(double), LG_MSF_get_second_double) +LG_JIT_KERNEL(LG_MSF_GET_SECOND(int64_t), LG_MSF_get_second_int64_t) //------------------------------------------------------------------------------ // tupleMin: z = the min tuple of x and y @@ -203,10 +186,8 @@ void LG_MSF_tupleMin_##ctype \ z->idx = (xSmaller)? x->idx: y->idx; \ } -LG_JIT_KERNEL(LG_MSF_tupleMin_double) -LG_MSF_TUPLEMIN(double) -LG_JIT_KERNEL(LG_MSF_tupleMin_int64_t) -LG_MSF_TUPLEMIN(int64_t) +LG_JIT_KERNEL(LG_MSF_TUPLEMIN(double), LG_MSF_tupleMin_double) +LG_JIT_KERNEL(LG_MSF_TUPLEMIN(int64_t), LG_MSF_tupleMin_int64_t) //------------------------------------------------------------------------------ // tuple2nd: z = y @@ -224,10 +205,8 @@ void LG_MSF_tuple2nd_##ctype \ z->idx = y->idx; \ } -LG_JIT_KERNEL(LG_MSF_tuple2nd_double) -LG_MSF_TUPLE2ND(double) -LG_JIT_KERNEL(LG_MSF_tuple2nd_int64_t) -LG_MSF_TUPLE2ND(int64_t) +LG_JIT_KERNEL(LG_MSF_TUPLE2ND(double), LG_MSF_tuple2nd_double) +LG_JIT_KERNEL(LG_MSF_TUPLE2ND(int64_t), LG_MSF_tuple2nd_int64_t) //------------------------------------------------------------------------------ // tupleEq: true if two tuples are equal @@ -244,10 +223,8 @@ void LG_MSF_tupleEq_##ctype \ *z = (x->wInt == y->wInt) && (x->idx == y->idx); \ } -LG_JIT_KERNEL(LG_MSF_tupleEq_double) -LG_MSF_TUPLEEQ(double) -LG_JIT_KERNEL(LG_MSF_tupleEq_int64_t) -LG_MSF_TUPLEEQ(int64_t) +LG_JIT_KERNEL(LG_MSF_TUPLEEQ(double), LG_MSF_tupleEq_double) +LG_JIT_KERNEL(LG_MSF_TUPLEEQ(int64_t), LG_MSF_tupleEq_int64_t) //------------------------------------------------------------------------------ @@ -454,7 +431,6 @@ int LAGraph_msf //---------------------------------------------------------------------- // types and ops for INT64 weights //---------------------------------------------------------------------- - GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_int64_t), "LG_MSF_tuple_int64_t", LG_MSF_tuple_int64_t_JIT_STR)) ; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7386ef07e2..451f0bd2ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,27 +17,6 @@ include_directories ( utility ) file ( GLOB LAGRAPH_LIB_SOURCES "utility/*.c" "algorithm/*.c" ) -#------------------------------------------------------------------------------- -# JIT kernel header generation (one _jit.h per source file) -#------------------------------------------------------------------------------- - -set ( LAGRAPH_JIT_HEADERS "" ) -foreach ( SRC IN LISTS LAGRAPH_LIB_SOURCES ) - get_filename_component ( SRC_NAME "${SRC}" NAME_WE ) - set ( JIT_HEADER "${JIT_INCLUDE_DIR}/${SRC_NAME}_jit.h" ) - add_custom_command ( - OUTPUT "${JIT_HEADER}" - COMMAND Python3::Interpreter - "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" - --input "${SRC}" --output "${JIT_HEADER}" - DEPENDS "${SRC}" "${PROJECT_SOURCE_DIR}/tools/jit_generator.py" - COMMENT "JIT: generating ${SRC_NAME}_jit.h" - ) - list ( APPEND LAGRAPH_JIT_HEADERS "${JIT_HEADER}" ) -endforeach () - -add_custom_target ( LAGraphJITGenerate DEPENDS ${LAGRAPH_JIT_HEADERS} ) - #------------------------------------------------------------------------------- # dynamic lagraph library properties #------------------------------------------------------------------------------- @@ -120,17 +99,6 @@ if ( LAGRAPH_HAS_OPENMP ) endif ( ) endif ( ) -#------------------------------------------------------------------------------- -# JIT header dependency: ensure headers are generated before compilation -#------------------------------------------------------------------------------- - -if ( BUILD_SHARED_LIBS ) - add_dependencies ( LAGraph LAGraphJITGenerate ) -endif ( ) -if ( BUILD_STATIC_LIBS ) - add_dependencies ( LAGraph_static LAGraphJITGenerate ) -endif ( ) - #------------------------------------------------------------------------------- # applications #------------------------------------------------------------------------------- diff --git a/src/utility/LG_internal.h b/src/utility/LG_internal.h index 3d16c6c549..dcb6fd0fb3 100644 --- a/src/utility/LG_internal.h +++ b/src/utility/LG_internal.h @@ -49,6 +49,11 @@ #define MATCH(s1,s2,n) (strncmp (s1, s2, n) == 0) #define MATCHNAME(s1,s2) MATCH (s1, s2, LAGRAPH_MAX_NAME_LEN) +//------------------------------------------------------------------------------ +// JIT string generation +//------------------------------------------------------------------------------ +#define LG_JIT_KERNEL(f, name) static const char* name##_JIT_STR = LG_XSTR(f); f + //------------------------------------------------------------------------------ // typedefs //------------------------------------------------------------------------------ @@ -706,15 +711,4 @@ int LG_KindName #endif -// LG_JIT_KERNEL(name) marks a function or struct for JIT string extraction by -// jit_generator.py. During a CMake build (LG_JIT_BUILD is defined), it -// expands to nothing - the real string constants come from the generated -// _jit.h headers. Without LG_JIT_BUILD (ie. in an IDE without compile -// flags), it declares a NULL placeholder so the IDE recognises the symbols. -#ifdef LG_JIT_BUILD -# define LG_JIT_KERNEL(name) -#else -# define LG_JIT_KERNEL(name) static const char *name##_JIT_STR = NULL; -#endif - #endif diff --git a/tools/jit_generator.py b/tools/jit_generator.py deleted file mode 100644 index 420d678441..0000000000 --- a/tools/jit_generator.py +++ /dev/null @@ -1,98 +0,0 @@ -import argparse -import io -import re - -import pcpp - - -class _Preprocessor(pcpp.Preprocessor): - """Preprocessor that silently passes through unfound includes.""" - - def on_include_not_found( - self, is_malformed, is_system_include, curdir, includepath - ): - raise pcpp.OutputDirective(pcpp.Action.IgnoreAndPassThrough) - - def on_error(self, file, line, msg): - pass # suppress errors from missing include contents - - -def _preprocess(input_file): - pp = _Preprocessor() - pp.define("LG_JIT_KERNEL(name) __LG_JIT_KERNEL__(name)") - pp.parse(open(input_file).read(), input_file) - out = io.StringIO() - pp.write(out) - return out.getvalue() - - -_MARKER_RE = re.compile(r"__LG_JIT_KERNEL__\((\w+)\)") - - -def extract_jit_kernels(input_file): - # Expand all macros, passing through any #include directives that can't be resolved - expanded_code = _preprocess(input_file) - - lines = expanded_code.splitlines() - kernels = {} - - i = 0 - while i < len(lines): - m = _MARKER_RE.search(lines[i]) - if m: - kernel_name = m.group(1) - - # Advance to the next non-empty line (the struct/function definition) - i += 1 - while i < len(lines) and not lines[i].strip(): - i += 1 - - # Brace-count to find the end of the definition - content = [] - brace_count = 0 - started = False - - while i < len(lines): - line = lines[i] - content.append(line) - brace_count += line.count("{") - brace_count -= line.count("}") - - if "{" in line: - started = True - - if started and brace_count == 0: - break - i += 1 - - # Join and format as a C string literal - full_body = "\n".join(content) - escaped_body = ( - full_body.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") - ) - kernels[kernel_name] = f'"{escaped_body}"' - i += 1 - return kernels - - -def write_jit_header(input_file, output_file): - """Generate a JIT header for input_file and write it to output_file.""" - kernels = extract_jit_kernels(input_file) - with open(output_file, "w") as f: - f.write("// This is a generated file containing all of the JIT strings\n") - f.write("// for the kernels defined in " + input_file + "\n") - f.write("#pragma once\n") - for name, string_lit in kernels.items(): - f.write(f"static const char* {name}_JIT_STR = {string_lit};\n") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Extract LG_JIT_KERNEL-marked definitions from a C file as string literals." - ) - parser.add_argument("--input", required=True, help="Input C source file") - parser.add_argument( - "--output", required=True, help="Output header file to generate" - ) - args = parser.parse_args() - write_jit_header(args.input, args.output) From c8b993a9062dc7cbd6d2e2f1417c72ed3b8cd739 Mon Sep 17 00:00:00 2001 From: Gabriel Gomez Date: Sat, 4 Apr 2026 18:52:41 -0500 Subject: [PATCH 5/8] revert github workflows --- .github/workflows/build-arch-emu.yaml | 3 --- .github/workflows/build.yml | 2 -- CMakeLists.txt | 14 -------------- 3 files changed, 19 deletions(-) diff --git a/.github/workflows/build-arch-emu.yaml b/.github/workflows/build-arch-emu.yaml index 13a4788254..a864cd7949 100644 --- a/.github/workflows/build-arch-emu.yaml +++ b/.github/workflows/build-arch-emu.yaml @@ -55,8 +55,6 @@ jobs: libtool git sudo - python3 - py3-pip - name: disable QEMU emulation if: matrix.arch == 'armv7' @@ -81,7 +79,6 @@ jobs: - name: build and test LAGraph run: | - pip3 install pcpp cd build cmake .. JOBS=2 make diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 36b5c9d599..c3523ac8d0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,6 @@ jobs: - name: Install tools for build run: | sudo apt install -y lcov - pip3 install pcpp - name: Build GraphBLAS run: | @@ -83,7 +82,6 @@ jobs: brew tap-new libomp/cask brew extract --version=14.0.6 libomp libomp/cask brew install libomp@14.0.6 - pip3 install --break-system-packages pcpp - name: Build GraphBLAS run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bae11179f..0d7e4298e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,20 +190,6 @@ else ( ) endif ( ) message ( STATUS "LAGraph has OpenMP: ${LAGRAPH_HAS_OPENMP}" ) -#------------------------------------------------------------------------------- -# find Python3 (for JIT kernel header generation) -#------------------------------------------------------------------------------- - -find_package ( Python3 REQUIRED COMPONENTS Interpreter ) -set ( JIT_INCLUDE_DIR "${CMAKE_BINARY_DIR}/jit_include" ) -file ( MAKE_DIRECTORY "${JIT_INCLUDE_DIR}" ) -include_directories ( "${JIT_INCLUDE_DIR}" ) - -# Predefine LG_JIT_KERNEL as a no-op for the compiler. -# LG_internal.h defines a non-trivial fallback for IDEs that don't apply -# compile flags, so that JIT string variables are still recognized there. -add_compile_definitions ( "LG_JIT_BUILD" ) - # check for strict usage if ( SUITESPARSE_USE_STRICT AND LAGRAPH_USE_OPENMP AND NOT LAGRAPH_HAS_OPENMP ) message ( FATAL_ERROR "OpenMP required for LAGraph but not found" ) From 0b4bb1953151f582e2c287d6cf31d5daa5a1a09e Mon Sep 17 00:00:00 2001 From: Gabriel Gomez Date: Sat, 4 Apr 2026 22:37:21 -0500 Subject: [PATCH 6/8] fix swapedges bug --- experimental/algorithm/LAGr_SwapEdges.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/experimental/algorithm/LAGr_SwapEdges.c b/experimental/algorithm/LAGr_SwapEdges.c index c47ad0c045..815b698e40 100755 --- a/experimental/algorithm/LAGr_SwapEdges.c +++ b/experimental/algorithm/LAGr_SwapEdges.c @@ -418,6 +418,11 @@ int LAGr_SwapEdges lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", LG_SE_edge2nd32_bool_JIT_STR )) ; + + LG_SE_edge_type32 iden_second = {0,0}; + GRB_TRY (GrB_Monoid_new_UDT( + &second_edge_monoid, second_edge, (void *) &iden_second + )) ; } else //uint64 types { @@ -426,7 +431,7 @@ int LAGr_SwapEdges LG_SE_edge_type64_JIT_STR)) ; GRB_TRY (GxB_Type_new( &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", - LG_SE_edge_type64_JIT_STR)) ; + LG_SE_swap_type64_JIT_STR)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge64), GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", @@ -447,6 +452,11 @@ int LAGr_SwapEdges lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", LG_SE_edge2nd64_bool_JIT_STR )) ; + + LG_SE_edge_type64 iden_second = {0,0}; + GRB_TRY (GrB_Monoid_new_UDT( + &second_edge_monoid, second_edge, (void *) &iden_second + )) ; } GRB_TRY (GxB_UnaryOp_new ( @@ -462,11 +472,6 @@ int LAGr_SwapEdges &add_term_monoid, add_term_biop, (int8_t) 0, (int8_t) 2 )) ; - LG_SE_edge_type64 iden_second = {0,0}; - GRB_TRY (GrB_Monoid_new_UDT( - &second_edge_monoid, second_edge, (void *) &iden_second - )) ; - GRB_TRY(GrB_Semiring_new( &plus_term_one, add_term_monoid, GrB_ONEB_INT8 )) ; From 90cd5a81c9896a13ae79fc8fc44b249649a633cb Mon Sep 17 00:00:00 2001 From: Gabriel Gomez Date: Sat, 4 Apr 2026 23:08:21 -0500 Subject: [PATCH 7/8] LG_JIT_KERNEL -> LG_JIT_STRING --- experimental/algorithm/LAGr_SwapEdges.c | 86 +++++++++---------- .../algorithm/LAGraph_RichClubCoefficient.c | 12 +-- experimental/algorithm/LAGraph_msf.c | 80 ++++++++--------- src/utility/LG_internal.h | 2 +- 4 files changed, 90 insertions(+), 90 deletions(-) diff --git a/experimental/algorithm/LAGr_SwapEdges.c b/experimental/algorithm/LAGr_SwapEdges.c index 815b698e40..a72ffc636e 100755 --- a/experimental/algorithm/LAGr_SwapEdges.c +++ b/experimental/algorithm/LAGr_SwapEdges.c @@ -78,42 +78,42 @@ #include "LG_internal.h" #include "LAGraphX.h" -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_shift_and (uint16_t *z, const uint16_t *x) { (*z) = (*x) & ((*x) << 8); (*z) |= (*z) >> 8; -}, LG_SE_shift_and) +}, LG_SE_SHIFT_AND) -LG_JIT_KERNEL( +LG_JIT_STRING( typedef struct { uint64_t a; uint64_t b; -} LG_SE_edge_type64;, LG_SE_edge_type64) +} LG_SE_edge_type64;, LG_SE_EDGE_TYPE64) -LG_JIT_KERNEL( +LG_JIT_STRING( typedef struct { uint64_t a; uint64_t b; uint64_t c; uint64_t d; -} LG_SE_swap_type64;, LG_SE_swap_type64) +} LG_SE_swap_type64;, LG_SE_SWAP_TYPE64) -LG_JIT_KERNEL( +LG_JIT_STRING( typedef struct { uint32_t a; uint32_t b; -} LG_SE_edge_type32;, LG_SE_edge_type32) +} LG_SE_edge_type32;, LG_SE_EDGE_TYPE32) -LG_JIT_KERNEL( +LG_JIT_STRING( typedef struct { uint32_t a; uint32_t b; uint32_t c; uint32_t d; -} LG_SE_swap_type32;, LG_SE_swap_type32) +} LG_SE_swap_type32;, LG_SE_SWAP_TYPE32) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_swap_bc64 ( LG_SE_swap_type64 *z, const LG_SE_swap_type64 *x, GrB_Index I, GrB_Index J, const bool *y @@ -132,9 +132,9 @@ void LG_SE_swap_bc64 ( z->c = z->b; z->b = temp; } -}, LG_SE_swap_bc64) +}, LG_SE_SWAP_BC64) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_swap_bc32( LG_SE_swap_type32 *z, const LG_SE_swap_type32 *x, GrB_Index I, GrB_Index J, const bool *y @@ -153,11 +153,11 @@ void LG_SE_swap_bc32( z->c = z->b; z->b = temp; } -}, LG_SE_swap_bc32) +}, LG_SE_SWAP_BC32) // using xorshift, from https://en.wikipedia.org/wiki/Xorshift // with a state of uint64_t, or xorshift64star. -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_hash_edge64 (uint64_t *z, const LG_SE_edge_type64 *x, const uint64_t *mask) { @@ -167,9 +167,9 @@ void LG_SE_hash_edge64 (*z) ^= (x->a < x->b)? x->a: x->b; (*z) ^= (*z) << 17; (*z) &= (*mask); -}, LG_SE_hash_edge64) +}, LG_SE_HASH_EDGE64) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_hash_edge32 (uint64_t *z, const LG_SE_edge_type32 *x, const uint64_t *mask) { @@ -179,46 +179,46 @@ void LG_SE_hash_edge32 (*z) ^= (uint64_t)((x->a < x->b)? x->a: x->b); (*z) ^= (*z) << 17; (*z) &= (*mask); -}, LG_SE_hash_edge32) +}, LG_SE_HASH_EDGE32) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_add_term (int8_t *z, const int8_t *x, const int8_t *y) { (*z) = (*x) | (*y) + ((int8_t)1 & (*x) & (*y)) ; -}, LG_SE_add_term) +}, LG_SE_ADD_TERM) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_edge2nd64_bool (LG_SE_edge_type64 *z, const bool *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; -}, LG_SE_edge2nd64_bool) +}, LG_SE_EDGE2ND64_BOOL) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_edge2nd32_bool (LG_SE_edge_type32 *z, const bool *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; -}, LG_SE_edge2nd32_bool) +}, LG_SE_EDGE2ND32_BOOL) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_edge2nd64_edge (LG_SE_edge_type64 *z, const LG_SE_edge_type64 *x, const LG_SE_edge_type64 *y) { z->a = y->a; z->b = y->b; -}, LG_SE_edge2nd64_edge) +}, LG_SE_EDGE2ND64_EDGE) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_SE_edge2nd32_edge (LG_SE_edge_type32 *z, const LG_SE_edge_type32 *x, const LG_SE_edge_type32 *y) { z->a = y->a; z->b = y->b; -}, LG_SE_edge2nd32_edge) +}, LG_SE_EDGE2ND32_EDGE) // FIXME: make loopTry, loopMin, totSwaps, seed inputs GrB_Scalar // FIXME: make pSwaps GrB_Scalar @@ -394,29 +394,29 @@ int LAGr_SwapEdges { GRB_TRY (GxB_Type_new( &lg_edge, sizeof(LG_SE_edge_type32), - "LG_SE_edge_type32", LG_SE_edge_type32_JIT_STR)) ; + "LG_SE_edge_type32", LG_SE_EDGE_TYPE32)) ; GRB_TRY (GxB_Type_new( &lg_swap, sizeof(LG_SE_swap_type32), - "LG_SE_swap_type32", LG_SE_swap_type32_JIT_STR)) ; + "LG_SE_swap_type32", LG_SE_SWAP_TYPE32)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge32), GrB_UINT64, lg_edge, GrB_UINT64, - "LG_SE_hash_edge32", LG_SE_hash_edge32_JIT_STR + "LG_SE_hash_edge32", LG_SE_HASH_EDGE32 )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc32), lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc32", - LG_SE_swap_bc32_JIT_STR + LG_SE_SWAP_BC32 )) ; GRB_TRY(GxB_BinaryOp_new( &second_edge, (GxB_binary_function) (&LG_SE_edge2nd32_edge), lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd32_edge", - LG_SE_edge2nd32_edge_JIT_STR + LG_SE_EDGE2ND32_EDGE )) ; GRB_TRY(GxB_BinaryOp_new( &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd32_bool), lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd32_bool", - LG_SE_edge2nd32_bool_JIT_STR + LG_SE_EDGE2ND32_BOOL )) ; LG_SE_edge_type32 iden_second = {0,0}; @@ -428,29 +428,29 @@ int LAGr_SwapEdges { GRB_TRY (GxB_Type_new( &lg_edge, sizeof(LG_SE_edge_type64), "LG_SE_edge_type64", - LG_SE_edge_type64_JIT_STR)) ; + LG_SE_EDGE_TYPE64)) ; GRB_TRY (GxB_Type_new( &lg_swap, sizeof(LG_SE_swap_type64), "LG_SE_swap_type64", - LG_SE_swap_type64_JIT_STR)) ; + LG_SE_SWAP_TYPE64)) ; GRB_TRY(GxB_BinaryOp_new( &hash_seed_e, (GxB_binary_function) (&LG_SE_hash_edge64), GrB_UINT64, lg_edge, GrB_UINT64, "LG_SE_hash_edge64", - LG_SE_hash_edge64_JIT_STR + LG_SE_HASH_EDGE64 )) ; GRB_TRY (GxB_IndexUnaryOp_new ( &swap_pair, (GxB_index_unary_function) (&LG_SE_swap_bc64), lg_swap, lg_swap, GrB_BOOL, "LG_SE_swap_bc64", - LG_SE_swap_bc64_JIT_STR + LG_SE_SWAP_BC64 )) ; GRB_TRY(GxB_BinaryOp_new( &second_edge, (GxB_binary_function) (&LG_SE_edge2nd64_edge), lg_edge, lg_edge, lg_edge, "LG_SE_edge2nd64_edge", - LG_SE_edge2nd64_edge_JIT_STR + LG_SE_EDGE2ND64_EDGE )) ; GRB_TRY(GxB_BinaryOp_new( &second_bool_edge, (GxB_binary_function) (&LG_SE_edge2nd64_bool), lg_edge, GrB_BOOL, lg_edge, "LG_SE_edge2nd64_bool", - LG_SE_edge2nd64_bool_JIT_STR + LG_SE_EDGE2ND64_BOOL )) ; LG_SE_edge_type64 iden_second = {0,0}; @@ -461,11 +461,11 @@ int LAGr_SwapEdges GRB_TRY (GxB_UnaryOp_new ( &lg_shiftland, (GxB_unary_function) (&LG_SE_shift_and), - GrB_UINT16, GrB_UINT16, "LG_SE_shift_and", LG_SE_shift_and_JIT_STR + GrB_UINT16, GrB_UINT16, "LG_SE_shift_and", LG_SE_SHIFT_AND )) ; GRB_TRY(GxB_BinaryOp_new( - &add_term_biop, (GxB_binary_function) (&LG_SE_add_term), - GrB_INT8, GrB_INT8, GrB_INT8, "LG_SE_add_term", LG_SE_add_term_JIT_STR + &add_term_biop, (GxB_binary_function) (&LG_SE_add_term), + GrB_INT8, GrB_INT8, GrB_INT8, "LG_SE_add_term", LG_SE_ADD_TERM )) ; GRB_TRY (GxB_Monoid_terminal_new_INT8( diff --git a/experimental/algorithm/LAGraph_RichClubCoefficient.c b/experimental/algorithm/LAGraph_RichClubCoefficient.c index 5ff0aa5ca1..d20ed9dac1 100755 --- a/experimental/algorithm/LAGraph_RichClubCoefficient.c +++ b/experimental/algorithm/LAGraph_RichClubCoefficient.c @@ -65,17 +65,17 @@ #include "LG_internal.h" #include "LAGraphX.h" -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_RCC_iseq_2islt(int64_t *z, const int64_t *x, const int64_t *y) { (*z) = (int64_t)((*x < *y) + (*x <= *y)) ; -}, LG_RCC_iseq_2islt) +}, LG_RCC_ISEQ_2ISLT) -LG_JIT_KERNEL( +LG_JIT_STRING( void LG_RCC_rich_club_formula(double *z, const int64_t *x, const int64_t *y) { (*z) = ((double)(*x)) / (((double)(*y)) * (((double)(*y)) - 1.0)); -}, LG_RCC_rich_club_formula) +}, LG_RCC_RICH_CLUB_FORMULA) int LAGraph_RichClubCoefficient ( @@ -182,11 +182,11 @@ int LAGraph_RichClubCoefficient GRB_TRY (GxB_BinaryOp_new( &iseq_2lt, (GxB_binary_function) (&LG_RCC_iseq_2islt), GrB_INT64, GrB_INT64, GrB_INT64, "LG_RCC_iseq_2islt", -LG_RCC_iseq_2islt_JIT_STR)) ; +LG_RCC_ISEQ_2ISLT)) ; GRB_TRY (GxB_BinaryOp_new( &rcCalculation, (GxB_binary_function) (&LG_RCC_rich_club_formula), GrB_FP64, GrB_INT64, GrB_INT64, - "LG_RCC_rich_club_formula", LG_RCC_rich_club_formula_JIT_STR)) ; + "LG_RCC_rich_club_formula", LG_RCC_RICH_CLUB_FORMULA)) ; #else GRB_TRY (GrB_BinaryOp_new( &iseq_2lt, (GxB_binary_function) (&LG_RCC_iseq_2islt), diff --git a/experimental/algorithm/LAGraph_msf.c b/experimental/algorithm/LAGraph_msf.c index cba347b7fd..193c6fe322 100755 --- a/experimental/algorithm/LAGraph_msf.c +++ b/experimental/algorithm/LAGraph_msf.c @@ -54,9 +54,9 @@ typedef struct \ uint64_t idx; \ } LG_MSF_tuple_##ctype; -LG_JIT_KERNEL(LG_MSF_TUPLE(double), LG_MSF_tuple_double) +LG_JIT_STRING(LG_MSF_TUPLE(double), LG_MSF_TUPLE_DOUBLE) -LG_JIT_KERNEL(LG_MSF_TUPLE(int64_t), LG_MSF_tuple_int64_t) +LG_JIT_STRING(LG_MSF_TUPLE(int64_t), LG_MSF_TUPLE_INT64_T) //------------------------------------------------------------------------------ // context_type: context for IndexUnaryOps (using the theta input) @@ -73,8 +73,8 @@ typedef struct \ } *w_partner; /* partner vertex in the spanning forest */ \ } LG_MSF_context_##ctype; -LG_JIT_KERNEL(LG_MSF_CONTEXT(double), LG_MSF_context_double) -LG_JIT_KERNEL(LG_MSF_CONTEXT(int64_t), LG_MSF_context_int64_t) +LG_JIT_STRING(LG_MSF_CONTEXT(double), LG_MSF_CONTEXT_DOUBLE) +LG_JIT_STRING(LG_MSF_CONTEXT(int64_t), LG_MSF_CONTEXT_INT64_T) //------------------------------------------------------------------------------ // selectEdge: index-unary operator to select edges of min weight @@ -99,8 +99,8 @@ void LG_MSF_selectEdge_##ctype \ (theta->parent[j] == theta->w_partner[i].idx); \ } -LG_JIT_KERNEL(LG_MSF_SELECTEDGE(double), LG_MSF_selectEdge_double) -LG_JIT_KERNEL(LG_MSF_SELECTEDGE(int64_t), LG_MSF_selectEdge_int64_t) +LG_JIT_STRING(LG_MSF_SELECTEDGE(double), LG_MSF_SELECTEDGE_DOUBLE) +LG_JIT_STRING(LG_MSF_SELECTEDGE(int64_t), LG_MSF_SELECTEDGE_INT64_T) //------------------------------------------------------------------------------ // removeEdge: remove edge (i,j) when i and j have the same parent @@ -122,8 +122,8 @@ void LG_MSF_removeEdge_##ctype \ (*z) = (theta->parent[i] != theta->parent[j]); \ } -LG_JIT_KERNEL(LG_MSF_REMOVEEDGE(double), LG_MSF_removeEdge_double) -LG_JIT_KERNEL(LG_MSF_REMOVEEDGE(int64_t), LG_MSF_removeEdge_int64_t) +LG_JIT_STRING(LG_MSF_REMOVEEDGE(double), LG_MSF_REMOVEEDGE_DOUBLE) +LG_JIT_STRING(LG_MSF_REMOVEEDGE(int64_t), LG_MSF_REMOVEEDGE_INT64_T) //------------------------------------------------------------------------------ // combine: create a tuple from a weight and an index @@ -141,8 +141,8 @@ void LG_MSF_combine_##ctype \ z->idx = *y; \ } -LG_JIT_KERNEL(LG_MSF_COMBINE(double), LG_MSF_combine_double) -LG_JIT_KERNEL(LG_MSF_COMBINE(int64_t), LG_MSF_combine_int64_t) +LG_JIT_STRING(LG_MSF_COMBINE(double), LG_MSF_COMBINE_DOUBLE) +LG_JIT_STRING(LG_MSF_COMBINE(int64_t), LG_MSF_COMBINE_INT64_T) //------------------------------------------------------------------------------ // get_first: get first item in a tuple (the weight) @@ -153,8 +153,8 @@ void LG_MSF_get_first_##ctype (ctype *y, const LG_MSF_tuple_##ctype *x) \ { \ *y = x->wInt; \ } -LG_JIT_KERNEL(LG_MSF_GET_FIRST(double), LG_MSF_get_first_double) -LG_JIT_KERNEL(LG_MSF_GET_FIRST(int64_t), LG_MSF_get_first_int64_t) +LG_JIT_STRING(LG_MSF_GET_FIRST(double), LG_MSF_GET_FIRST_DOUBLE) +LG_JIT_STRING(LG_MSF_GET_FIRST(int64_t), LG_MSF_GET_FIRST_INT64_T) //------------------------------------------------------------------------------ // get_second: get second item in a tuple (the index) @@ -165,8 +165,8 @@ void LG_MSF_get_second_##ctype (uint64_t *y, const LG_MSF_tuple_##ctype *x)\ { \ *y = x->idx; \ } -LG_JIT_KERNEL(LG_MSF_GET_SECOND(double), LG_MSF_get_second_double) -LG_JIT_KERNEL(LG_MSF_GET_SECOND(int64_t), LG_MSF_get_second_int64_t) +LG_JIT_STRING(LG_MSF_GET_SECOND(double), LG_MSF_GET_SECOND_DOUBLE) +LG_JIT_STRING(LG_MSF_GET_SECOND(int64_t), LG_MSF_GET_SECOND_INT64_T) //------------------------------------------------------------------------------ // tupleMin: z = the min tuple of x and y @@ -186,8 +186,8 @@ void LG_MSF_tupleMin_##ctype \ z->idx = (xSmaller)? x->idx: y->idx; \ } -LG_JIT_KERNEL(LG_MSF_TUPLEMIN(double), LG_MSF_tupleMin_double) -LG_JIT_KERNEL(LG_MSF_TUPLEMIN(int64_t), LG_MSF_tupleMin_int64_t) +LG_JIT_STRING(LG_MSF_TUPLEMIN(double), LG_MSF_TUPLEMIN_DOUBLE) +LG_JIT_STRING(LG_MSF_TUPLEMIN(int64_t), LG_MSF_TUPLEMIN_INT64_T) //------------------------------------------------------------------------------ // tuple2nd: z = y @@ -205,8 +205,8 @@ void LG_MSF_tuple2nd_##ctype \ z->idx = y->idx; \ } -LG_JIT_KERNEL(LG_MSF_TUPLE2ND(double), LG_MSF_tuple2nd_double) -LG_JIT_KERNEL(LG_MSF_TUPLE2ND(int64_t), LG_MSF_tuple2nd_int64_t) +LG_JIT_STRING(LG_MSF_TUPLE2ND(double), LG_MSF_TUPLE2ND_DOUBLE) +LG_JIT_STRING(LG_MSF_TUPLE2ND(int64_t), LG_MSF_TUPLE2ND_INT64_T) //------------------------------------------------------------------------------ // tupleEq: true if two tuples are equal @@ -223,8 +223,8 @@ void LG_MSF_tupleEq_##ctype \ *z = (x->wInt == y->wInt) && (x->idx == y->idx); \ } -LG_JIT_KERNEL(LG_MSF_TUPLEEQ(double), LG_MSF_tupleEq_double) -LG_JIT_KERNEL(LG_MSF_TUPLEEQ(int64_t), LG_MSF_tupleEq_int64_t) +LG_JIT_STRING(LG_MSF_TUPLEEQ(double), LG_MSF_TUPLEEQ_DOUBLE) +LG_JIT_STRING(LG_MSF_TUPLEEQ(int64_t), LG_MSF_TUPLEEQ_INT64_T) //------------------------------------------------------------------------------ @@ -432,57 +432,57 @@ int LAGraph_msf // types and ops for INT64 weights //---------------------------------------------------------------------- GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_int64_t), - "LG_MSF_tuple_int64_t", LG_MSF_tuple_int64_t_JIT_STR)) ; + "LG_MSF_tuple_int64_t", LG_MSF_TUPLE_INT64_T)) ; GRB_TRY (GxB_BinaryOp_new ( &combine, (GxB_binary_function) LG_MSF_combine_int64_t, tuple, weight_type, GrB_UINT64, - "LG_MSF_combine_int64_t", LG_MSF_combine_int64_t_JIT_STR)) ; + "LG_MSF_combine_int64_t", LG_MSF_COMBINE_INT64_T)) ; GRB_TRY (GrB_Scalar_setElement_INT64(max_weight, INT64_MAX)) ; GRB_TRY (GxB_BinaryOp_new ( &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_int64_t, tuple, tuple, tuple, - "LG_MSF_tupleMin_int64_t", LG_MSF_tupleMin_int64_t_JIT_STR)) ; + "LG_MSF_tupleMin_int64_t", LG_MSF_TUPLEMIN_INT64_T)) ; GRB_TRY (GxB_BinaryOp_new ( &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_int64_t, tuple, GrB_BOOL, tuple, - "LG_MSF_tuple2nd_int64_t", LG_MSF_tuple2nd_int64_t_JIT_STR)) ; + "LG_MSF_tuple2nd_int64_t", LG_MSF_TUPLE2ND_INT64_T)) ; GRB_TRY (GxB_BinaryOp_new ( &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_int64_t, GrB_BOOL, tuple, tuple, - "LG_MSF_tupleEq_int64_t", LG_MSF_tupleEq_int64_t_JIT_STR)) ; + "LG_MSF_tupleEq_int64_t", LG_MSF_TUPLEEQ_INT64_T)) ; inf = (void *) (&inf_int) ; GRB_TRY (GxB_UnaryOp_new ( &get_first, (GxB_unary_function) LG_MSF_get_first_int64_t, weight_type, tuple, - "LG_MSF_get_first_int64_t", LG_MSF_get_first_int64_t_JIT_STR)) ; + "LG_MSF_get_first_int64_t", LG_MSF_GET_FIRST_INT64_T)) ; GRB_TRY (GxB_UnaryOp_new ( &get_second, (GxB_unary_function) LG_MSF_get_second_int64_t, GrB_UINT64, tuple, - "LG_MSF_get_second_int64_t", LG_MSF_get_second_int64_t_JIT_STR)) ; + "LG_MSF_get_second_int64_t", LG_MSF_GET_SECOND_INT64_T)) ; // context type GRB_TRY (GxB_Type_new ( &context_type, sizeof (LG_MSF_context_int64_t), - "LG_MSF_context_int64_t", LG_MSF_context_int64_t_JIT_STR)) ; + "LG_MSF_context_int64_t", LG_MSF_CONTEXT_INT64_T)) ; // ops for GrB_select GRB_TRY(GxB_IndexUnaryOp_new ( &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_int64_t, GrB_BOOL, weight_type, context_type, - "LG_MSF_selectEdge_int64_t", LG_MSF_selectEdge_int64_t_JIT_STR)) ; + "LG_MSF_selectEdge_int64_t", LG_MSF_SELECTEDGE_INT64_T)) ; GRB_TRY(GxB_IndexUnaryOp_new ( &removeEdge, (void *) LG_MSF_removeEdge_int64_t, GrB_BOOL, weight_type, context_type, - "LG_MSF_removeEdge_int64_t", LG_MSF_removeEdge_int64_t_JIT_STR + "LG_MSF_removeEdge_int64_t", LG_MSF_REMOVEEDGE_INT64_T )) ; } @@ -494,56 +494,56 @@ int LAGraph_msf //---------------------------------------------------------------------- GRB_TRY (GxB_Type_new (&tuple, sizeof (LG_MSF_tuple_double), - "LG_MSF_tuple_double", LG_MSF_tuple_double_JIT_STR)) ; + "LG_MSF_tuple_double", LG_MSF_TUPLE_DOUBLE)) ; GRB_TRY (GxB_BinaryOp_new ( &combine, (GxB_binary_function) LG_MSF_combine_double, tuple, weight_type, GrB_UINT64, - "LG_MSF_combine_double", LG_MSF_combine_double_JIT_STR)) ; + "LG_MSF_combine_double", LG_MSF_COMBINE_DOUBLE)) ; GRB_TRY (GrB_Scalar_setElement_FP64(max_weight, INFINITY)) ; GRB_TRY (GxB_BinaryOp_new ( &tupleMin, (GxB_binary_function) LG_MSF_tupleMin_double, tuple, tuple, tuple, - "LG_MSF_tupleMin_double", LG_MSF_tupleMin_double_JIT_STR)) ; + "LG_MSF_tupleMin_double", LG_MSF_TUPLEMIN_DOUBLE)) ; GRB_TRY (GxB_BinaryOp_new ( &tuple2nd, (GxB_binary_function) LG_MSF_tuple2nd_double, tuple, GrB_BOOL, tuple, - "LG_MSF_tuple2nd_double", LG_MSF_tuple2nd_double_JIT_STR)) ; + "LG_MSF_tuple2nd_double", LG_MSF_TUPLE2ND_DOUBLE)) ; GRB_TRY (GxB_BinaryOp_new ( &tupleEq, (GxB_binary_function) LG_MSF_tupleEq_double, GrB_BOOL, tuple, tuple, - "LG_MSF_tupleEq_double", LG_MSF_tupleEq_double_JIT_STR)) ; + "LG_MSF_tupleEq_double", LG_MSF_TUPLEEQ_DOUBLE)) ; inf = (void *) (&inf_fp) ; GRB_TRY (GxB_UnaryOp_new ( &get_first, (GxB_unary_function) LG_MSF_get_first_double, weight_type, tuple, - "LG_MSF_get_first_double", LG_MSF_get_first_double_JIT_STR)) ; + "LG_MSF_get_first_double", LG_MSF_GET_FIRST_DOUBLE)) ; GRB_TRY (GxB_UnaryOp_new ( &get_second, (GxB_unary_function) LG_MSF_get_second_double, GrB_UINT64, tuple, - "LG_MSF_get_second_double", LG_MSF_get_second_double_JIT_STR)) ; + "LG_MSF_get_second_double", LG_MSF_GET_SECOND_DOUBLE)) ; GRB_TRY (GxB_Type_new ( &context_type, sizeof (LG_MSF_context_double), - "LG_MSF_context_double", LG_MSF_context_double_JIT_STR)) ; + "LG_MSF_context_double", LG_MSF_CONTEXT_DOUBLE)) ; // ops for GrB_select GRB_TRY(GxB_IndexUnaryOp_new ( &selectEdge, (GxB_index_unary_function) LG_MSF_selectEdge_double, GrB_BOOL, weight_type, context_type, - "LG_MSF_selectEdge_double", LG_MSF_selectEdge_double_JIT_STR)) ; + "LG_MSF_selectEdge_double", LG_MSF_SELECTEDGE_DOUBLE)) ; GRB_TRY(GxB_IndexUnaryOp_new ( &removeEdge, (void *) LG_MSF_removeEdge_double, GrB_BOOL, weight_type, context_type, - "LG_MSF_removeEdge_double", LG_MSF_removeEdge_double_JIT_STR)) ; + "LG_MSF_removeEdge_double", LG_MSF_REMOVEEDGE_DOUBLE)) ; } GRB_TRY (GrB_Monoid_new_UDT (&tupleMin_monoid, tupleMin, inf)) ; diff --git a/src/utility/LG_internal.h b/src/utility/LG_internal.h index dcb6fd0fb3..fe319451e8 100644 --- a/src/utility/LG_internal.h +++ b/src/utility/LG_internal.h @@ -52,7 +52,7 @@ //------------------------------------------------------------------------------ // JIT string generation //------------------------------------------------------------------------------ -#define LG_JIT_KERNEL(f, name) static const char* name##_JIT_STR = LG_XSTR(f); f +#define LG_JIT_STRING(f, name) static const char* name = LG_XSTR(f); f //------------------------------------------------------------------------------ // typedefs From 9caed21fe4edc666a732cc6707323bcb4a9c4154 Mon Sep 17 00:00:00 2001 From: Gabriel Gomez Date: Sun, 5 Apr 2026 00:25:17 -0500 Subject: [PATCH 8/8] use LG_JIT_STRING in other functions --- .../LAGr_EdgeBetweennessCentrality.c | 11 +--- .../algorithm/LAGraph_Coarsen_Matching.c | 42 ++++++++----- .../algorithm/LAGraph_EstimateDiameter.c | 2 + .../algorithm/LAGraph_FastGraphletTransform.c | 9 ++- experimental/algorithm/LAGraph_lcc.c | 30 ++------- experimental/algorithm/LAGraph_scc.c | 62 ++++++++----------- src/utility/LAGraph_Random.c | 28 ++------- 7 files changed, 71 insertions(+), 113 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 8ec8f7384e..e7b42820b9 100755 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -69,20 +69,13 @@ // (1+x)/y function for double: z = (1 + x) / y //------------------------------------------------------------------------------ +LG_JIT_STRING( void LG_EBC_add_one_divide_function (double *z, const double *x, const double *y) { double a = (*(x)) ; double b = (*(y)) ; (*(z)) = (1 + a) / b ; -} - -#define ADD_ONE_DIVIDE_FUNCTION_DEFN \ -"void LG_EBC_add_one_divide_function (double *z, const double *x, const double *y)\n" \ -"{ \n" \ -" double a = (*(x)) ; \n" \ -" double b = (*(y)) ; \n" \ -" (*(z)) = (1 + a) / b ; \n" \ -"}" +}, ADD_ONE_DIVIDE_FUNCTION_DEFN) //------------------------------------------------------------------------------ // LAGr_EdgeBetweennessCentrality: edge betweenness-centrality diff --git a/experimental/algorithm/LAGraph_Coarsen_Matching.c b/experimental/algorithm/LAGraph_Coarsen_Matching.c index b3275d03f6..bd144aa348 100644 --- a/experimental/algorithm/LAGraph_Coarsen_Matching.c +++ b/experimental/algorithm/LAGraph_Coarsen_Matching.c @@ -89,12 +89,19 @@ This method requires O(n + e) space for an undirected graph with e edges and n n #if LAGRAPH_SUITESPARSE -void LG_CM_valueeq_index_func (bool *z, const uint64_t *x, GrB_Index i, GrB_Index j, const void *y) { +LG_JIT_STRING( +void LG_CM_valueeq_index_func ( + bool *z, + const uint64_t *x, + GrB_Index i, + GrB_Index j, + const void *y +) { (*z) = ((*x) == i) ; -} +}, LG_CM_VALUEEQ_INDEX_FUNC_DEFN) static int LAGraph_Parent_to_S -( +( // input/outputs: GrB_Matrix *result, // resulting S matrix GrB_Vector *newlabels, // The contents of some newlabels_result[i], where newlabels_result is as described at the top of the file. @@ -162,28 +169,31 @@ static int LAGraph_Parent_to_S - GrB_extract into parent_cpy from parent_cpy with row indices as values from original parent - This fills in the new parents for discarded nodes */ - - GRB_TRY (GrB_IndexUnaryOp_new (&VALUEEQ_ROWINDEX_UINT64, F_INDEX_UNARY(LG_CM_valueeq_index_func), GrB_BOOL, GrB_UINT64, GrB_UINT64)) ; + + GRB_TRY (GxB_IndexUnaryOp_new ( + &VALUEEQ_ROWINDEX_UINT64, F_INDEX_UNARY(LG_CM_valueeq_index_func), + GrB_BOOL, GrB_UINT64, GrB_UINT64, "LG_CM_valueeq_index_func", + LG_CM_VALUEEQ_INDEX_FUNC_DEFN)) ; // identify preserved nodes GRB_TRY (GrB_select (parent_cpy, NULL, NULL, VALUEEQ_ROWINDEX_UINT64, parent, 0, NULL)) ; GRB_TRY (GrB_free (&VALUEEQ_ROWINDEX_UINT64)) ; - + // get indices of preserved nodes GRB_TRY (GxB_Vector_unpack_CSC ( - parent_cpy, - &preserved_indices, - (void**) &preserved_values, - &preserved_indices_size, - &preserved_values_size, - NULL, + parent_cpy, + &preserved_indices, + (void**) &preserved_values, + &preserved_indices_size, + &preserved_values_size, + NULL, &num_preserved, &is_jumbled, NULL )) ; LG_TRY (LAGraph_Free ((void**)(&preserved_values), msg)) ; - + // build ramp vector LG_TRY (LAGraph_Malloc ((void**) &ramp, num_preserved, sizeof(uint64_t), msg)) ; @@ -272,9 +282,9 @@ static int LAGraph_Parent_to_S LG_FREE_WORK ; \ } -#ifdef burble - #define CHKPT(msg){ printf("*** [CHKPT] *** %s\n", msg) ; } -#else +#ifdef burble + #define CHKPT(msg){ printf("*** [CHKPT] *** %s\n", msg) ; } +#else #define CHKPT(msg){} #endif diff --git a/experimental/algorithm/LAGraph_EstimateDiameter.c b/experimental/algorithm/LAGraph_EstimateDiameter.c index ba19fa94bb..4606367385 100755 --- a/experimental/algorithm/LAGraph_EstimateDiameter.c +++ b/experimental/algorithm/LAGraph_EstimateDiameter.c @@ -47,6 +47,7 @@ #include "LG_internal.h" #include "LAGraphX.h" +// FIXME: this mod function definition is wrong. void LG_ED_mod32 (int32_t *z, const int32_t *x, const int32_t *y) ; void LG_ED_mod32 (int32_t *z, const int32_t *x, const int32_t *y) { @@ -63,6 +64,7 @@ void LG_ED_mod32 (int32_t *z, const int32_t *x, const int32_t *y) " (*z) = t % (*y) ; \n" \ "}" +// FIXME: this mod function definition is wrong. void LG_ED_mod64 (int64_t *z, const int64_t *x, const int64_t *y) ; void LG_ED_mod64 (int64_t *z, const int64_t *x, const int64_t *y) { diff --git a/experimental/algorithm/LAGraph_FastGraphletTransform.c b/experimental/algorithm/LAGraph_FastGraphletTransform.c index 0628cf0c35..5b61ad0077 100644 --- a/experimental/algorithm/LAGraph_FastGraphletTransform.c +++ b/experimental/algorithm/LAGraph_FastGraphletTransform.c @@ -95,7 +95,10 @@ #include "LG_internal.h" #include "LAGraphX.h" -void LG_FGT_sub_one_mult (int64_t *z, const int64_t *x) { (*z) = (*x) * ((*x)-1) ; } +LG_JIT_STRING( +void LG_FGT_sub_one_mult (int64_t *z, const int64_t *x) { +(*z) = (*x) * ((*x)-1) ; +}, LG_FGT_SUB_ONE_MULT_DEFN) int LAGraph_FastGraphletTransform ( @@ -208,7 +211,9 @@ int LAGraph_FastGraphletTransform GRB_TRY (GrB_Vector_new (&d_3, GrB_INT64, n)) ; - GRB_TRY (GrB_UnaryOp_new (&Sub_one_mult, F_UNARY (LG_FGT_sub_one_mult), GrB_INT64, GrB_INT64)) ; + GRB_TRY (GxB_UnaryOp_new ( + &Sub_one_mult, F_UNARY (LG_FGT_sub_one_mult), GrB_INT64, GrB_INT64, + "LG_FGT_sub_one_mult", LG_FGT_SUB_ONE_MULT_DEFN)) ; GRB_TRY (GrB_apply (d_3, NULL, NULL, Sub_one_mult, d_1, NULL)) ; GRB_TRY (GrB_apply (d_3, NULL, NULL, GrB_DIV_INT64, d_3, (int64_t) 2, NULL)) ; diff --git a/experimental/algorithm/LAGraph_lcc.c b/experimental/algorithm/LAGraph_lcc.c index f418fee343..e40bf0e354 100755 --- a/experimental/algorithm/LAGraph_lcc.c +++ b/experimental/algorithm/LAGraph_lcc.c @@ -88,6 +88,7 @@ // z = x * (x - 1), used by LAGraph_lcc. // This operator calculates the 2-permutation of d(v). +LG_JIT_STRING( void LG_lcc_comb_dir_fp64 ( void *z, @@ -97,22 +98,11 @@ void LG_lcc_comb_dir_fp64 double xd = *(double *) x ; double *zd = (double *) z ; (*zd) = ((xd) * (xd - 1)) ; -} - -#define LAGRAPH_COMB_DIR_FP64 \ -"void LG_lcc_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" \ -"}" +}, LAGRAPH_COMB_DIR_FP64) // z = x * (x - 1) / 2, used by LAGraph_lcc. // This operator calculates the 2-combination of d(v). +LG_JIT_STRING( void LG_lcc_comb_undir_fp64 ( void *z, @@ -122,19 +112,7 @@ void LG_lcc_comb_undir_fp64 double xd = *(double *) x ; double *zd = (double *) z ; (*zd) = ((xd) * (xd - 1)) / 2; -} - -#define LAGRAPH_COMB_UNDIR_FP64 \ -"void LG_lcc_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" \ -"}" +}, LAGRAPH_COMB_UNDIR_FP64) //------------------------------------------------------------------------------ diff --git a/experimental/algorithm/LAGraph_scc.c b/experimental/algorithm/LAGraph_scc.c index f5a4e8c639..e26628ae78 100755 --- a/experimental/algorithm/LAGraph_scc.c +++ b/experimental/algorithm/LAGraph_scc.c @@ -35,18 +35,12 @@ //**************************************************************************** //arrays used in SelectOp -typedef struct -{ - uint64_t *F, *B; +LG_JIT_STRING( +typedef struct { + uint64_t *F; + uint64_t *B; bool *M; -} LG_SCC_Context; -#define SCCCONTEXT \ -"typedef struct \n" \ -"{\n" \ -" uint64_t *F, *B;\n" \ -" bool *M;\n" \ -"} LG_SCC_Context;\n" - +} LG_SCC_Context;, SCCCONTEXT) // LG_SCC_edge_removal: // - remove the edges connected to newly identified SCCs (vertices u with M[u]==1) @@ -61,21 +55,18 @@ typedef struct // an edge (u, v) if either F[u]!=F[v] or B[u]!=B[v] holds, which can accelerate // the SCC computation in the future rounds. -void LG_SCC_edge_removal (bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk) ; -void LG_SCC_edge_removal (bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk) -{ - (*z) = (!thunk->M[i] && !thunk->M[j] - && thunk->F[i] == thunk->F[j] +LG_JIT_STRING( +void LG_SCC_edge_removal ( + bool *z, + const void *x, + GrB_Index i, + GrB_Index j, + const LG_SCC_Context *thunk +) { + (*z) = (!thunk->M[i] && !thunk->M[j] + && thunk->F[i] == thunk->F[j] && thunk->B[i] == thunk->B[j]) ; -} -#define EDGE_REMOVAL \ -"void LG_SCC_edge_removal \n" \ -"(bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk)\n" \ -"{\n" \ -" (*z) = (!thunk->M[i] && !thunk->M[j] \n" \ -" && thunk->F[i] == thunk->F[j] \n" \ -" && thunk->B[i] == thunk->B[j]) ;\n" \ -"}\n" +}, EDGE_REMOVAL) //**************************************************************************** // LG_SCC_trim_one: remove the edges connected to trivial SCCs @@ -83,17 +74,16 @@ void LG_SCC_edge_removal (bool *z, const void *x, GrB_Index i, GrB_Index j, cons // - M[i] = i | if vertex i is a trivial SCC // M[i] = n | otherwise -void LG_SCC_trim_one (bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk) ; -void LG_SCC_trim_one (bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk) -{ +LG_JIT_STRING( +void LG_SCC_trim_one ( + bool *z, + const void *x, + GrB_Index i, + GrB_Index j, + const LG_SCC_Context *thunk +) { (*z) = (thunk->F[i] == thunk->F[j]) ; -} -#define TRIM_ONE \ -"void LG_SCC_trim_one\n" \ -"(bool *z, const void *x, GrB_Index i, GrB_Index j, const LG_SCC_Context *thunk)\n" \ -"{\n" \ -" (*z) = (thunk->F[i] == thunk->F[j]) ;\n" \ -"}\n" +}, TRIM_ONE) //**************************************************************************** // label propagation @@ -197,7 +187,7 @@ int LAGraph_scc GRB_TRY (GrB_Matrix_nrows (&n, A)); GRB_TRY (GrB_Matrix_ncols (&ncols, A)); LG_ASSERT(n == ncols, GrB_DIMENSION_MISMATCH); - + #if !LG_SUITESPARSE_GRAPHBLAS_V10 LG_TRY (LAGraph_Malloc ((void **) &contx.F, n, sizeof (uint64_t), msg)) ; LG_TRY (LAGraph_Malloc ((void **) &contx.B, n, sizeof (uint64_t), msg)) ; diff --git a/src/utility/LAGraph_Random.c b/src/utility/LAGraph_Random.c index ca4cf43b1f..9c7bfd5ebe 100644 --- a/src/utility/LAGraph_Random.c +++ b/src/utility/LAGraph_Random.c @@ -86,6 +86,7 @@ uint64_t LG_Random64 (uint64_t *state) } // return a random uint64_t; as a unary operator +LG_JIT_STRING( void LG_rand_next_f2 (uint64_t *z, const uint64_t *x) { uint64_t state = (*x) ; @@ -93,17 +94,7 @@ void LG_rand_next_f2 (uint64_t *z, const uint64_t *x) state ^= state >> 7 ; state ^= state << 17 ; (*z) = state ; -} - -#define LG_RAND_NEXT_F2_DEFN \ -"void LG_rand_next_f2 (uint64_t *z, const uint64_t *x) \n" \ -"{ \n" \ -" uint64_t state = (*x) ; \n" \ -" state ^= state << 13 ; \n" \ -" state ^= state >> 7 ; \n" \ -" state ^= state << 17 ; \n" \ -" (*z) = state ; \n" \ -"}" +}, LG_RAND_NEXT_F2_DEFN) // From these references, the recommendation is to create the initial state of // a random number generator with an entirely different random number @@ -146,6 +137,7 @@ void LG_rand_next_f2 (uint64_t *z, const uint64_t *x) // The init function computes z = splitmix64 (i + seed), but it does not // advance the seed value on return. +LG_JIT_STRING( void LG_rand_init_func (uint64_t *z, const void *x, GrB_Index i, GrB_Index j, const uint64_t *seed) { @@ -155,19 +147,7 @@ void LG_rand_init_func (uint64_t *z, const void *x, result = (result ^ (result >> 27)) * 0x94D049BB133111EBLL ; result = (result ^ (result >> 31)) ; (*z) = result ; -} - -#define LG_RAND_INIT_F_DEFN \ -"void LG_rand_init_func (uint64_t *z, const void *x, \n" \ -" GrB_Index i, GrB_Index j, const uint64_t *seed) \n" \ -"{ \n" \ -" uint64_t state = i + (*seed) ; \n" \ -" uint64_t result = (state += 0x9E3779B97F4A7C15LL) ; \n" \ -" result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9LL ; \n" \ -" result = (result ^ (result >> 27)) * 0x94D049BB133111EBLL ; \n" \ -" result = (result ^ (result >> 31)) ; \n" \ -" (*z) = result ; \n" \ -"}" +}, LG_RAND_INIT_F_DEFN) //------------------------------------------------------------------------------ // LG_Random_Init: create the random state operator