{"id":19672038,"url":"https://github.com/michelp/glaph","last_synced_at":"2025-02-27T05:14:33.632Z","repository":{"id":145540992,"uuid":"338736686","full_name":"michelp/glaph","owner":"michelp","description":"You gotta glaph about it","archived":false,"fork":false,"pushed_at":"2021-02-22T18:49:31.000Z","size":56,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-10T03:44:29.949Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michelp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-14T05:31:54.000Z","updated_at":"2021-02-22T18:49:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"8253e19c-0036-44bb-84d1-80fca6f0cdcc","html_url":"https://github.com/michelp/glaph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fglaph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fglaph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fglaph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fglaph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michelp","download_url":"https://codeload.github.com/michelp/glaph/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240981562,"owners_count":19888346,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T17:10:40.391Z","updated_at":"2025-02-27T05:14:33.610Z","avatar_url":"https://github.com/michelp.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# glaph: (G)enerics (L)ibrary for Gr(aph)BLAS\n\nglaph is an include-only C library of macros, inline functions and\npure evil that make working with the GraphBLAS API less C like and\nmore \"Python like\".  Just copy the header files directory into your\nproject and do:\n\n    #include \"glaph/glaph.h\"\n\n## So what's so funny\n\nGlaph is macro and inline function meta-boilerplate for dealing with\nGraphBLAS objects.  Instead of:\n\n\tGrB_Matrix A;\n    GrB_TRY(GrB_Matrix_new(\u0026A, GrB_FP64, nrows, ncols));\n    \nIn glaph you just do:\n\n\tGrB_Matrix A;\n    GL_NEW(A);\n    \nIt initializes it as a hypersparse matrix with default type FP64.  It\nis now ready to use in your program for many cases.  But this is a\nrather tame example of a glaph macro.  Lets say instead you want a 10\nby 10 boolean matrix:\n\n    GL_NEW(A, 10, 10, .type=GrB_BOOL);\n    \nIt's the same macro, it's just generic enough to handle various cases\nincluding optional types and dimensions provided as keywork arguments.\nHow about a new vector?  Same macro, just pass a vector argument\ninstead.  In this case it takes only one index argument for the vector\nsize:\n\n\tGrB_Vector j;\n    GL_NEW(j);                        // hypersparse FP_64\n    GL_NEW(j, 10, .type=GrB_BOOL);    // size=10 BOOL\n    \nNow, everyone knows C doesn't have keyword arguments.  Glaph bends\nreality with some macro and inline function sleigh of hand to make\nusing the C api a lot easier by making many of the optional arguments\ndefaulted internally my the glaph macros.  Combined with the\npolymorphism of C11 style `_Generic()` macros, there is a lot of\nsimplication, and glaph algorithms are usualy line for line\noperationally identical to their Python equivalents.  \n\nThere are no external dependencies and no runtime.  Glaph generates C\ncode using standard `#define` C preprocessor macros that is directly\ncompiled like any other GraphBLAS program.  \n\nAnother example is that where the GraphBLAS C API provides `GrB_mxm`,\n`GrB_mxv` and `GrB_vxm` for Matix/Matrix, Matrix/Vector, and\nVector/Matrix multiplication respectively, glaph has only `GL_AXB(C,\nA, B)`:\n\n        GL_AXB(C, A, B,\n               .mask=M,\n               .accum=GrB_MIN_INT64);\n               \n        GL_AXB(c, a, B,\n               .mask=m,\n               .semiring=GrB_MIN_PLUS_SEMIRING_INT64);\n\n        GL_AXB(c, A, b,\n               .mask=m,\n               .semiring=GrB_MIN_PLUS_SEMIRING_INT64, \n               .accum=GrB_MIN_INT64);\n               \nThe only invalid combination is (Vector, Vector, Vector) which will\nthrow a compiler error.\n\nOne of the consequence of glaph using C metaprogramming is that the C\ncompiler optimizing pass will generate the same code that you would\nhave written by hand.  The keyword arguments structs and inline\nfunctions \"evaporate\" to static arguments, just as if you had placed\nthem there by hand.  In a sense glaph self-destructs when it's\ncompiled, leaving only a GraphBLAS program behind.\n\n## shortest path example\n\nThis is the shortest path example:\n\n    GrB_Vector sssp(GrB_Matrix A, uint64_t start) {\n        GrB_Vector v, w;\n        GL_NEW(v);\n        GL_NEW(w);\n        GL_ASSIGN(v, start, 0);\n        GL_FORI(i, A) {\n            GL_CLEAR(w);\n            GL_ASSIGN(w, v);\n            GL_AXB(v, v, A,\n                   .semiring=GrB_MIN_PLUS_SEMIRING_INT64, \n                   .accum=GrB_MIN_INT64);\n            if (GL_ISEQ(w, v))\n                break;\n        }\n        GL_FREE(w);\n        return v;\n    }\n\nHere is the equivalent Python with pygraphblas:\n\n    def sssp(A, start):\n        v = Vector.sparse(A.type, A.nrows)\n        v[start] = 0\n        with INT64.MIN_PLUS, Accum(INT64.MIN):\n            for i in A.I:\n                w.clear()\n                w[:] = v\n                v @= A\n                if w.iseq(v):\n                    break\n            return v\n\n## Even more Generic\n\nSuiteSparse comes with a number of generic macros that can work with\nvarious types with the same funciton name.  Instead of calling\n`GrB_Matrix_assign_FP64`, you can just call `GrB_assign` with the\nright order and type of arguments that the compiler will pick the\nright concrete function (for matrices with double floating point\narguments, as given in this example).\n\nglaph takes this idea even further, instead of\n`GrB_Matrix_setElement`, the `ASSIGN` macro can handle the scalar case\nas well as the already supported vector and matrix cases.  It also\nincludes support for `GxB_Scalar`, All in one macro.\n\nThis pattern is carred over to `GL_EXTRACT` as well, you can extract\nsub-graphs, vectors, Scalars, and C scalar values all with one macro,\neach with its own distinct set of keyword arguments depending on the\ninput types of the operation.\n\nAll macros take the pattern:\n\n   GL_NAME(C, [A, [B, ...] ...])\n   \nThey all require at least one input (for things like `GL_PRINT`) or\noutput.  Glaph macros NEVER return values so never do something like\n`x = GL_NAME(...)`.  If the macro has output, it is always the first\nargument.  Keyword arguments depend on whatever pattern of positional\narguments matched the _Generic expansion.  `GL_EXTRACT` for example,\nwill accept `mask`, `accum` and `desc` keywork arguments in all cases\nexcept scalar.  Trying to use inappropriate keyworks arguments will\nresult in a compiler error.\n\nAll glaph macros automatically check for and handle SuiteSparse\nerrors.  The default behavior is to print and abort on any error\nexcept `GrB_SUCCESS` or `GrB_NO_VALUE`.  You can re-define the\n`GL_CATCH` macro to handle your own errors.\n\n## Keyword arguments?\n\nFor example `AXB` is the generic matrix mulitpilicaiton macro in\nglaph.  It covers all cases that `GrB_mxm`, `GrB_vxm` and `GrB_mxv`\ncover in the API.  Just Do `AXB (C, A, B)` and the macro will expand\nto the correct underlying function for the argument types with all the\noptional arguments filled in with `NULL`.\n\nAll other arguments to those 3 functions are optional, so they are\nspecified by keyword argument:\n\n    AXB (v, AT, w,\n         .mask=M,\n         .accum=GrB_PLUS_FP32,\n         .semiring=GxB_PLUS_SECOND_FP32,\n         .desc=GrB_DESC_T0);\n\nThe \"keyword arguments\" are really the guts of a struct initializer\nthat the macro is hiding from you.  No worries, it all works out\ngreat.  In fact, the C compiler knows that these structs are all\nstatically initialized, and completely optimizes all of glaph away,\nexactly compiling the same assembly code that using the GraphBLAS API\ndirectly \"by hand\" would create.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichelp%2Fglaph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichelp%2Fglaph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichelp%2Fglaph/lists"}