diff --git a/Dockerfile b/Dockerfile index d17a00f..6c394bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:latest # install base dependences RUN apt-get update && \ apt-get install -y make cmake git curl build-essential m4 sudo gdbserver \ - gdb libreadline-dev bison flex zlib1g-dev tmux emacs25-nox zile zip vim gawk wget + gdb libreadline-dev bison flex zlib1g-dev libicu-dev icu-devtools tmux zile zip vim gawk wget # add postgres user and make data dir RUN groupadd -r postgres && useradd --no-log-init -r -m -s /bin/bash -g postgres -G sudo postgres @@ -12,9 +12,10 @@ RUN /bin/rm -Rf "$PGDATA" && mkdir "$PGDATA" WORKDIR "/home/postgres" # get postgres source and compile with debug and no optimization -RUN git clone --branch REL_12_STABLE https://github.com/postgres/postgres.git --depth=1 && \ +RUN git clone --branch REL_16_STABLE https://github.com/postgres/postgres.git --depth=1 && \ cd postgres && ./configure \ --prefix=/usr/ \ + --without-icu \ # --enable-debug \ # --enable-depend --enable-cassert --enable-profiling \ # CFLAGS="-ggdb -Og -g3 -fno-omit-frame-pointer" \ @@ -22,19 +23,19 @@ RUN git clone --branch REL_12_STABLE https://github.com/postgres/postgres.git -- && make -j 4 && make install # get GraphBLAS, compile with debug symbols -RUN curl -s -L http://faculty.cse.tamu.edu/davis/GraphBLAS/GraphBLAS-3.1.1.tar.gz | \ - tar zxvf - && cd GraphBLAS-3.1.1 && \ +RUN curl -s -L -J https://github.com/DrTimothyAldenDavis/GraphBLAS/archive/refs/tags/v9.2.0.tar.gz | \ + tar zxvf - && cd GraphBLAS-9.2.0 && \ # sed -i 's/^\/\/ #undef NDEBUG/#undef NDEBUG/g' Source/GB.h && \ # sed -i 's/^\/\/ #define GB_PRINT_MALLOC 1/#define GB_PRINT_MALLOC 1/g' Source/GB.h && \ make library \ CMAKE_OPTIONS='-DCMAKE_BUILD_TYPE=Debug' \ && make install -RUN git clone --branch 22July2019 https://github.com/GraphBLAS/LAGraph.git && \ - cd LAGraph && \ - make library \ +#RUN git clone --branch 22July2019 https://github.com/GraphBLAS/LAGraph.git && \ +# cd LAGraph && \ +# make library \ # CMAKE_OPTIONS='-DCMAKE_BUILD_TYPE=Debug' \ - && make install +# && make install RUN curl -s -L https://github.com/theory/pgtap/archive/v0.99.0.tar.gz | tar zxvf - && \ cd pgtap-0.99.0 && make && make install @@ -43,8 +44,8 @@ RUN curl -s -L https://github.com/theory/pgtap/archive/v0.99.0.tar.gz | tar zxvf RUN chown -R postgres:postgres /home/postgres # put test stuff into pg home -RUN mkdir "/home/postgres/pggraphblas" -WORKDIR "/home/postgres/pggraphblas" +RUN mkdir "/home/postgres/onesparse" +WORKDIR "/home/postgres/onesparse" COPY . . # RUN mkdir "/home/postgres/LAGraph" @@ -59,8 +60,8 @@ COPY . . RUN make && make install && make clean RUN ldconfig -# chown just pggraphblas -RUN chown -R postgres:postgres /home/postgres/pggraphblas +# chown just onesparse +RUN chown -R postgres:postgres /home/postgres/onesparse # make postgres a sudoer RUN echo "postgres ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \ diff --git a/Makefile b/Makefile index f932720..e4c7aa7 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,18 @@ #http://blog.pgxn.org/post/4783001135/extension-makefiles pg makefiles -EXTENSION = pggraphblas +EXTENSION = onesparse PG_CONFIG ?= pg_config DATA = $(wildcard *--*.sql) PGXS := $(shell $(PG_CONFIG) --pgxs) -MODULE_big = pggraphblas -OBJS = $(patsubst %.c,%.o,$(wildcard src/pggraphblas.c)) -SHLIB_LINK = -lgraphblas -llagraph -PG_CPPFLAGS = -O0 +MODULE_big = onesparse +OBJS = $(patsubst %.c,%.o,$(wildcard src/onesparse.c)) +SHLIB_LINK = -lgraphblas -lpq +PG_CPPFLAGS = -O0 -Wfatal-errors TESTS = $(wildcard test/sql/*.sql) REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS)) REGRESS_OPTS = --inputdir=test --load-language=plpgsql include $(PGXS) -sql: pggraphblas--0.0.1.sql - bash pggraphblas--0.0.1-gen.sql.sh +sql: onesparse--0.0.1.sql + bash onesparse--0.0.1-gen.sql.sh diff --git a/README.md b/README.md index f2486e7..7ca8631 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # summary -pgGraphBLAS is a postgres extension that bridges [The GraphBLAS +OneSparse is a postgres extension that bridges [The GraphBLAS API](http://graphblas.org) with the [PostgreSQL](https://postgresql.org) object relational database. @@ -10,7 +10,7 @@ real/integer matrix algebra operations, GraphBLAS supports up to 960 different "semiring" algebra operations, that can be used as basic building blocks to implement a wide variety of graph algorithms. -pgGraphBLAS leverages the expertise in the field of sparse matrix +OneSparse leverages the expertise in the field of sparse matrix programming by [The GraphBLAS Forum](http://graphblas.org) and uses the [SuiteSparse:GraphBLAS](http://faculty.cse.tamu.edu/davis/GraphBLAS.html) @@ -80,7 +80,7 @@ the matrix. The math used with sparse matrices is exactly the same as dense, the sparsity of the data doesn't matter to the math, but it does matter to how efficiently the matrix is implemented internally. -pgGraphBLAS is a postgres extension that provides access to two new +OneSparse is a postgres extension that provides access to two new types: `matrix` and `vector`, as well as the GraphBLAS api to manipulate these types. Aggregate functions are provided to build matrices from SQL queries, and set-returning functions are also @@ -141,7 +141,7 @@ search](https://en.wikipedia.org/wiki/Breadth-first_search). $$ language plpgsql; The above code is written in `plpgsql` which is postgres' procedural - query language. This language works well with pgGraphBLAS + query language. This language works well with OneSparse algorithmic approach. postgres=# create table t (m matrix); @@ -186,7 +186,7 @@ search](https://en.wikipedia.org/wiki/Breadth-first_search). In the above simple benchmark, the GraphBLAS version of BFS can be seen to be almost 12x faster than the [plpgsql procedural -version](https://github.com/michelp/pggraphblas/blob/master/demo/bfs.sql#L97). +version](https://github.com/OneSparse/OneSparse/blob/master/demo/bfs.sql#L97). # references @@ -233,7 +233,7 @@ data types, the following types map from GraphBLAS to PostgreSQL: Postgres does not support unsigned integers like GraphBLAS (is there a workaround? support the uint extension?) -pgGraphBLAS matrix and vector objects have an intrinsic type of data +OneSparse matrix and vector objects have an intrinsic type of data that they store. So, a matrix can store booleans, and various sized integers and floats. Once a matrix is created with a specific type it cannot be changed. @@ -257,7 +257,7 @@ Guide](https://github.com/sergiud/SuiteSparse/blob/master/GraphBLAS/Doc/GraphBLA GraphBLAS operations all take an optional `mask` argument. Check the GraphBLAS Users Guide for more information on masking operations. GraphBLAS operations can also take a descriptor argument, which in -pgGraphBLAS is broken out into four optional arguments supported by +OneSparse is broken out into four optional arguments supported by every function: - doutp text default null @@ -272,7 +272,7 @@ See the GraphBLAS Users Guide for more info. ## printing At the moment, there is no human parsable text -representation for vectors or matrices, so pgGraphBLAS provides a +representation for vectors or matrices, so OneSparse provides a `print` function that can give a text description of vectors or matrices: diff --git a/demo/bench.sql b/demo/bench.sql index c7e1ea3..3bddb6f 100644 --- a/demo/bench.sql +++ b/demo/bench.sql @@ -1,6 +1,6 @@ \timing on -create extension if not exists pggraphblas; +create extension if not exists onesparse; create table a (m matrix); diff --git a/demo/bfs.sql b/demo/bfs.sql index 7f5f7fe..e4e0a24 100644 --- a/demo/bfs.sql +++ b/demo/bfs.sql @@ -2,43 +2,7 @@ \ir fixtures.sql -drop function if exists bfs2; - -create function bfs2(tablename text, source bigint) returns vector as $$ -declare - A matrix; - n bigint; - v vector; - q vector; - level integer := 0; -- Start at level 1. - not_done bool := true; -- Flag to indicate still work to do. - -begin - execute format('select matrix(array_agg(i), array_agg(j), array_agg(true)) from %I', tablename) into A; - n := nrows(A); -- The number of result rows. - v := vector_integer(n); -- int32 result vector of vertex levels. - q := assign(vector_bool(n), false); -- bool mask of completed vertices. - - q := set_element(q, source, true); -- Set the source element to done. - - while not_done and level <= n loop -- While still work to do. - v := assign(v, level, mask=>q); -- Assign the current level to all - - q := mxv(transpose(A), q, q, -- Multiply q = Aq, - semiring=>'LOR_LAND_BOOL', -- using LOR_LAND_BOOL semiring - mask=>v, -- only those *not* masked - dmask=>'scmp', -- by complementing the mask - doutp=>'replace'); -- clearing results in q first - - not_done := reduce_bool(q); -- are there more neighbors? - - level := level + 1; -- increment the level - end loop; - return v; -end; -$$ language plpgsql; - -drop function if exists bfs; +drop function if exists bfs3; create function bfs3(A matrix, source bigint) returns vector as $$ declare diff --git a/demo/dbpedia/dbpedia.sql b/demo/dbpedia/dbpedia.sql index 737c839..4861235 100644 --- a/demo/dbpedia/dbpedia.sql +++ b/demo/dbpedia/dbpedia.sql @@ -1,6 +1,6 @@ \timing on begin; -create extension if not exists pggraphblas; +create extension if not exists onesparse; drop table if exists article; create table article ( diff --git a/demo/fixtures.sql b/demo/fixtures.sql index a5ec844..f9a394c 100644 --- a/demo/fixtures.sql +++ b/demo/fixtures.sql @@ -1,4 +1,4 @@ -create extension if not exists pggraphblas; +create extension if not exists onesparse; drop table if exists test; create table test ( diff --git a/pggraphblas--0.0.1.sql b/onesparse--0.0.1.sql similarity index 67% rename from pggraphblas--0.0.1.sql rename to onesparse--0.0.1.sql index 9a5f225..1cc01f1 100644 --- a/pggraphblas--0.0.1.sql +++ b/onesparse--0.0.1.sql @@ -1,16 +1,16 @@ -- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION pggraphblas" to load this file. \quit +\echo Use "CREATE EXTENSION onesparse" to load this file. \quit CREATE TYPE vector; CREATE FUNCTION vector_in(cstring) RETURNS vector -AS '$libdir/pggraphblas', 'vector_in' +AS '$libdir/onesparse', 'vector_in' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION vector_out(A vector) RETURNS cstring -AS '$libdir/pggraphblas', 'vector_out' +AS '$libdir/onesparse', 'vector_out' LANGUAGE C IMMUTABLE STRICT; CREATE TYPE vector ( @@ -25,61 +25,51 @@ CREATE TYPE matrix; CREATE FUNCTION matrix_in(cstring) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_in' +AS '$libdir/onesparse', 'matrix_in' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION matrix_out(matrix) RETURNS cstring -AS '$libdir/pggraphblas', 'matrix_out' +AS '$libdir/onesparse', 'matrix_out' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION nrows(matrix) RETURNS bigint -AS '$libdir/pggraphblas', 'matrix_nrows' +AS '$libdir/onesparse', 'matrix_nrows' LANGUAGE C STABLE; CREATE FUNCTION ncols(matrix) RETURNS bigint -AS '$libdir/pggraphblas', 'matrix_ncols' +AS '$libdir/onesparse', 'matrix_ncols' LANGUAGE C STABLE; CREATE FUNCTION nvals(matrix) RETURNS bigint -AS '$libdir/pggraphblas', 'matrix_nvals' +AS '$libdir/onesparse', 'matrix_nvals' LANGUAGE C STABLE; CREATE FUNCTION matrix_eq(A matrix, B matrix) RETURNS bool -AS '$libdir/pggraphblas', 'matrix_eq' +AS '$libdir/onesparse', 'matrix_eq' LANGUAGE C STABLE; CREATE FUNCTION matrix_ne(A matrix, B matrix) RETURNS bool -AS '$libdir/pggraphblas', 'matrix_ne' -LANGUAGE C STABLE; - -CREATE FUNCTION to_mm(A matrix) -RETURNS text -AS '$libdir/pggraphblas', 'matrix_mmwrite' -LANGUAGE C STABLE; - -CREATE FUNCTION from_mm(A text) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_mmread' +AS '$libdir/onesparse', 'matrix_ne' LANGUAGE C STABLE; CREATE FUNCTION print( A matrix, level integer default 2) RETURNS text -AS '$libdir/pggraphblas', 'matrix_print' +AS '$libdir/onesparse', 'matrix_print' LANGUAGE C STABLE; CREATE FUNCTION print( A vector, level integer default 2) RETURNS text -AS '$libdir/pggraphblas', 'vector_print' +AS '$libdir/onesparse', 'vector_print' LANGUAGE C STABLE; CREATE TYPE matrix ( @@ -93,37 +83,37 @@ CREATE TYPE matrix ( CREATE FUNCTION matrix(bigint[], bigint[], bool[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_bool' +AS '$libdir/onesparse', 'matrix_bool' LANGUAGE C STABLE; CREATE FUNCTION matrix(bigint[], bigint[], bigint[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int64' +AS '$libdir/onesparse', 'matrix_int64' LANGUAGE C STABLE; CREATE FUNCTION matrix(bigint[], bigint[], integer[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int32' +AS '$libdir/onesparse', 'matrix_int32' LANGUAGE C STABLE; CREATE FUNCTION matrix(bigint[], bigint[], smallint[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int16' +AS '$libdir/onesparse', 'matrix_int16' LANGUAGE C STABLE; CREATE FUNCTION matrix(bigint[], bigint[], real[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_float4' +AS '$libdir/onesparse', 'matrix_float4' LANGUAGE C STABLE; CREATE FUNCTION matrix(bigint[], bigint[], float[], bigint default null, bigint default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_float8' +AS '$libdir/onesparse', 'matrix_float8' LANGUAGE C STABLE; -- matrix extract @@ -138,39 +128,39 @@ CREATE FUNCTION xtract( dinp1 text default null ) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_xtract' +AS '$libdir/onesparse', 'matrix_xtract' LANGUAGE C STABLE; -- empty matrix construction CREATE FUNCTION matrix_bool(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_bool' +AS '$libdir/onesparse', 'matrix_bool' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_bigint(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int64' +AS '$libdir/onesparse', 'matrix_int64' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_integer(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int32' +AS '$libdir/onesparse', 'matrix_int32' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_smallint(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_int16' +AS '$libdir/onesparse', 'matrix_int16' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_real(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_float4' +AS '$libdir/onesparse', 'matrix_float4' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_float(nrows bigint, ncols bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_float8' +AS '$libdir/onesparse', 'matrix_float8' LANGUAGE C STABLE STRICT; CREATE FUNCTION mxm( @@ -186,7 +176,7 @@ CREATE FUNCTION mxm( dinp1 text default null ) RETURNS matrix -AS '$libdir/pggraphblas', 'mxm' +AS '$libdir/onesparse', 'mxm' LANGUAGE C STABLE; CREATE FUNCTION kron( @@ -202,101 +192,9 @@ CREATE FUNCTION kron( dinp1 text default null ) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_kron' -LANGUAGE C STABLE; - -CREATE FUNCTION matrix_random_bigint( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_int64' +AS '$libdir/onesparse', 'matrix_kron' LANGUAGE C STABLE; -CREATE FUNCTION matrix_random_integer( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_int32' -LANGUAGE C STABLE; - -CREATE FUNCTION matrix_random_smallint( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_int16' -LANGUAGE C STABLE; - -CREATE FUNCTION matrix_random_real( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_float4' -LANGUAGE C STABLE; - -CREATE FUNCTION matrix_random_float( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_float8' -LANGUAGE C STABLE; - -CREATE FUNCTION matrix_random_bool( - nrows bigint, - ncols bigint, - nvals bigint, - make_pattern bool default false, - make_symmetric bool default false, - make_skew_symmetric bool default false, - make_hermitian bool default false, - no_diagonal bool default false, - seed bigint default null - ) -RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_random_bool' -LANGUAGE C STABLE; - - - CREATE FUNCTION transpose( A matrix, inout C matrix default null, @@ -308,12 +206,12 @@ CREATE FUNCTION transpose( dinp1 text default null ) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_transpose' +AS '$libdir/onesparse', 'matrix_transpose' LANGUAGE C STABLE; CREATE FUNCTION mxm_op(A matrix, B matrix) RETURNS matrix -AS '$libdir/pggraphblas', 'mxm' +AS '$libdir/onesparse', 'mxm' LANGUAGE C STABLE STRICT; CREATE FUNCTION mxv( @@ -329,12 +227,12 @@ CREATE FUNCTION mxv( dinp1 text default null ) RETURNS vector -AS '$libdir/pggraphblas', 'mxv' +AS '$libdir/onesparse', 'mxv' LANGUAGE C STABLE; CREATE FUNCTION mxv_op(matrix, vector) RETURNS vector -AS '$libdir/pggraphblas', 'mxv' +AS '$libdir/onesparse', 'mxv' LANGUAGE C STABLE STRICT; CREATE FUNCTION vxm( @@ -350,12 +248,12 @@ CREATE FUNCTION vxm( dinp1 text default null ) RETURNS vector -AS '$libdir/pggraphblas', 'vxm' +AS '$libdir/onesparse', 'vxm' LANGUAGE C STABLE; CREATE FUNCTION vxm_op(vector, matrix) RETURNS vector -AS '$libdir/pggraphblas', 'vxm' +AS '$libdir/onesparse', 'vxm' LANGUAGE C STABLE STRICT; CREATE FUNCTION ewise_mult( @@ -372,7 +270,7 @@ CREATE FUNCTION ewise_mult( ) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_ewise_mult' +AS '$libdir/onesparse', 'matrix_ewise_mult' LANGUAGE C STABLE; CREATE FUNCTION ewise_add( @@ -389,56 +287,56 @@ CREATE FUNCTION ewise_add( ) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_ewise_add' +AS '$libdir/onesparse', 'matrix_ewise_add' LANGUAGE C STABLE; CREATE FUNCTION matrix_ewise_mult_op(A matrix, B matrix) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_ewise_mult' +AS '$libdir/onesparse', 'matrix_ewise_mult' LANGUAGE C STABLE STRICT; CREATE FUNCTION matrix_ewise_add_op(A matrix, B matrix) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_ewise_add' +AS '$libdir/onesparse', 'matrix_ewise_add' LANGUAGE C STABLE STRICT; -- matrix reduce to vector CREATE FUNCTION reduce(A matrix, semiring text default null) RETURNS vector -AS '$libdir/pggraphblas', 'matrix_reduce_vector' +AS '$libdir/onesparse', 'matrix_reduce_vector' LANGUAGE C STABLE; -- matrix reduce scalar CREATE FUNCTION reduce_bool(A matrix, semiring text default null) RETURNS bool -AS '$libdir/pggraphblas', 'matrix_reduce_bool' +AS '$libdir/onesparse', 'matrix_reduce_bool' LANGUAGE C STABLE; CREATE FUNCTION reduce_bigint(A matrix, semiring text default null) RETURNS bigint -AS '$libdir/pggraphblas', 'matrix_reduce_int64' +AS '$libdir/onesparse', 'matrix_reduce_int64' LANGUAGE C STABLE; CREATE FUNCTION reduce_integer(A matrix, semiring text default null) RETURNS integer -AS '$libdir/pggraphblas', 'matrix_reduce_int32' +AS '$libdir/onesparse', 'matrix_reduce_int32' LANGUAGE C STABLE; CREATE FUNCTION reduce_smallint(A matrix, semiring text default null) RETURNS smallint -AS '$libdir/pggraphblas', 'matrix_reduce_int16' +AS '$libdir/onesparse', 'matrix_reduce_int16' LANGUAGE C STABLE; CREATE FUNCTION reduce_real(A matrix, semiring text default null) RETURNS real -AS '$libdir/pggraphblas', 'matrix_reduce_float4' +AS '$libdir/onesparse', 'matrix_reduce_float4' LANGUAGE C STABLE; CREATE FUNCTION reduce_float(A matrix, semiring text default null) RETURNS float -AS '$libdir/pggraphblas', 'matrix_reduce_float8' +AS '$libdir/onesparse', 'matrix_reduce_float8' LANGUAGE C STABLE; -- matrix assign matrix @@ -448,7 +346,7 @@ CREATE FUNCTION assign( B matrix, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_matrix' +AS '$libdir/onesparse', 'matrix_assign_matrix' LANGUAGE C STABLE; -- matrix assign scalar @@ -459,7 +357,7 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_bool' +AS '$libdir/onesparse', 'matrix_assign_bool' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -468,7 +366,7 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_int64' +AS '$libdir/onesparse', 'matrix_assign_int64' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -477,7 +375,7 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_int32' +AS '$libdir/onesparse', 'matrix_assign_int32' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -486,7 +384,7 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_int16' +AS '$libdir/onesparse', 'matrix_assign_int16' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -495,7 +393,7 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_float4' +AS '$libdir/onesparse', 'matrix_assign_float4' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -504,39 +402,39 @@ CREATE FUNCTION assign( C matrix default null, mask matrix default null) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_assign_float8' +AS '$libdir/onesparse', 'matrix_assign_float8' LANGUAGE C STABLE; -- matrix set element CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value bool) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_bool' +AS '$libdir/onesparse', 'matrix_set_element_bool' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value bigint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_int64' +AS '$libdir/onesparse', 'matrix_set_element_int64' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value integer) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_int32' +AS '$libdir/onesparse', 'matrix_set_element_int32' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value smallint) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_int16' +AS '$libdir/onesparse', 'matrix_set_element_int16' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value real) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_float4' +AS '$libdir/onesparse', 'matrix_set_element_float4' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A matrix, i bigint, j bigint, value float) RETURNS matrix -AS '$libdir/pggraphblas', 'matrix_set_element_float8' +AS '$libdir/onesparse', 'matrix_set_element_float8' LANGUAGE C STABLE STRICT; @@ -596,53 +494,34 @@ CREATE TYPE matrix_element_bool AS (i bigint, j bigint, value bool); CREATE FUNCTION elements_bigint(A matrix) RETURNS SETOF matrix_element_bigint -AS '$libdir/pggraphblas', 'matrix_elements_int64' +AS '$libdir/onesparse', 'matrix_elements_int64' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_integer(A matrix) RETURNS SETOF matrix_element_integer -AS '$libdir/pggraphblas', 'matrix_elements_int32' +AS '$libdir/onesparse', 'matrix_elements_int32' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_smallint(A matrix) RETURNS SETOF matrix_element_smallint -AS '$libdir/pggraphblas', 'matrix_elements_int16' +AS '$libdir/onesparse', 'matrix_elements_int16' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_float(A matrix) RETURNS SETOF matrix_element_float -AS '$libdir/pggraphblas', 'matrix_elements_float8' +AS '$libdir/onesparse', 'matrix_elements_float8' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_real(A matrix) RETURNS SETOF matrix_element_real -AS '$libdir/pggraphblas', 'matrix_elements_float4' +AS '$libdir/onesparse', 'matrix_elements_float4' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_bool(A matrix) RETURNS SETOF matrix_element_bool -AS '$libdir/pggraphblas', 'matrix_elements_bool' +AS '$libdir/onesparse', 'matrix_elements_bool' LANGUAGE C STABLE STRICT; -CREATE FUNCTION bfs(A matrix, size bigint, AT matrix default null) -RETURNS vector -AS '$libdir/pggraphblas', 'matrix_bfs' -LANGUAGE C STABLE; - -CREATE TYPE pageranking AS (page bigint, rank float); - -CREATE FUNCTION pagerank(A matrix) -RETURNS pageranking -AS '$libdir/pggraphblas', 'matrix_pagerank' -LANGUAGE C STABLE; - -CREATE TYPE ssspath AS (source bigint, distance float, parent bigint, hops bigint); - --- CREATE FUNCTION sssp_bf(A matrix, start bigint) --- RETURNS ssspath --- AS '$libdir/pggraphblas', 'sssp_bf' --- LANGUAGE C STABLE; - -- vectors CREATE FUNCTION ewise_mult( @@ -658,7 +537,7 @@ CREATE FUNCTION ewise_mult( dinp1 text default null ) RETURNS vector -AS '$libdir/pggraphblas', 'vector_ewise_mult' +AS '$libdir/onesparse', 'vector_ewise_mult' LANGUAGE C STABLE; CREATE FUNCTION ewise_add( @@ -674,37 +553,37 @@ CREATE FUNCTION ewise_add( dinp1 text default null ) RETURNS vector -AS '$libdir/pggraphblas', 'vector_ewise_add' +AS '$libdir/onesparse', 'vector_ewise_add' LANGUAGE C STABLE; CREATE FUNCTION vector_ewise_mult_op(A vector, B vector) RETURNS vector -AS '$libdir/pggraphblas', 'vector_ewise_mult' +AS '$libdir/onesparse', 'vector_ewise_mult' LANGUAGE C STABLE STRICT; CREATE FUNCTION vector_ewise_add_op(A vector, B vector) RETURNS vector -AS '$libdir/pggraphblas', 'vector_ewise_add' +AS '$libdir/onesparse', 'vector_ewise_add' LANGUAGE C STABLE STRICT; CREATE FUNCTION vector_eq(A vector, B vector) RETURNS bool -AS '$libdir/pggraphblas', 'vector_eq' +AS '$libdir/onesparse', 'vector_eq' LANGUAGE C STABLE; CREATE FUNCTION vector_ne(A vector, B vector) RETURNS bool -AS '$libdir/pggraphblas', 'vector_ne' +AS '$libdir/onesparse', 'vector_ne' LANGUAGE C STABLE; CREATE FUNCTION size(A vector) RETURNS bigint -AS '$libdir/pggraphblas', 'vector_size' +AS '$libdir/onesparse', 'vector_size' LANGUAGE C STABLE; CREATE FUNCTION nvals(A vector) RETURNS bigint -AS '$libdir/pggraphblas', 'vector_nvals' +AS '$libdir/onesparse', 'vector_nvals' LANGUAGE C STABLE; CREATE FUNCTION xtract( @@ -717,7 +596,7 @@ CREATE FUNCTION xtract( dinp1 text default null ) RETURNS vector -AS '$libdir/pggraphblas', 'vector_xtract' +AS '$libdir/onesparse', 'vector_xtract' LANGUAGE C STABLE; -- vector reduce @@ -726,42 +605,42 @@ CREATE FUNCTION reduce_bool( A vector, semiring text default null) RETURNS bool -AS '$libdir/pggraphblas', 'vector_reduce_bool' +AS '$libdir/onesparse', 'vector_reduce_bool' LANGUAGE C STABLE; CREATE FUNCTION reduce_bigint( A vector, semiring text default null) RETURNS bigint -AS '$libdir/pggraphblas', 'vector_reduce_int64' +AS '$libdir/onesparse', 'vector_reduce_int64' LANGUAGE C STABLE; CREATE FUNCTION reduce_integer( A vector, semiring text default null) RETURNS integer -AS '$libdir/pggraphblas', 'vector_reduce_int32' +AS '$libdir/onesparse', 'vector_reduce_int32' LANGUAGE C STABLE; CREATE FUNCTION reduce_smallint( A vector, semiring text default null) RETURNS smallint -AS '$libdir/pggraphblas', 'vector_reduce_int16' +AS '$libdir/onesparse', 'vector_reduce_int16' LANGUAGE C STABLE; CREATE FUNCTION reduce_real( A vector, semiring text default null) RETURNS real -AS '$libdir/pggraphblas', 'vector_reduce_float4' +AS '$libdir/onesparse', 'vector_reduce_float4' LANGUAGE C STABLE; CREATE FUNCTION reduce_float( A vector, semiring text default null) RETURNS float -AS '$libdir/pggraphblas', 'vector_reduce_float8' +AS '$libdir/onesparse', 'vector_reduce_float8' LANGUAGE C STABLE; -- vector assign @@ -772,7 +651,7 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_bool' +AS '$libdir/onesparse', 'vector_assign_bool' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -781,7 +660,7 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_int64' +AS '$libdir/onesparse', 'vector_assign_int64' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -790,7 +669,7 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_int32' +AS '$libdir/onesparse', 'vector_assign_int32' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -799,7 +678,7 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_int16' +AS '$libdir/onesparse', 'vector_assign_int16' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -808,7 +687,7 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_float4' +AS '$libdir/onesparse', 'vector_assign_float4' LANGUAGE C STABLE; CREATE FUNCTION assign( @@ -817,39 +696,39 @@ CREATE FUNCTION assign( C vector default null, mask vector default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_assign_float8' +AS '$libdir/onesparse', 'vector_assign_float8' LANGUAGE C STABLE; -- vector set element CREATE FUNCTION set_element(A vector, index bigint, value bool) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_bool' +AS '$libdir/onesparse', 'vector_set_element_bool' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A vector, index bigint, value bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_int64' +AS '$libdir/onesparse', 'vector_set_element_int64' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A vector, index bigint, value integer) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_int32' +AS '$libdir/onesparse', 'vector_set_element_int32' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A vector, index bigint, value smallint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_int16' +AS '$libdir/onesparse', 'vector_set_element_int16' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A vector, index bigint, value real) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_float4' +AS '$libdir/onesparse', 'vector_set_element_float4' LANGUAGE C STABLE STRICT; CREATE FUNCTION set_element(A vector, index bigint, value float) RETURNS vector -AS '$libdir/pggraphblas', 'vector_set_element_float8' +AS '$libdir/onesparse', 'vector_set_element_float8' LANGUAGE C STABLE STRICT; CREATE OPERATOR * ( @@ -882,42 +761,42 @@ CREATE OPERATOR <> ( CREATE FUNCTION vector(bigint[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int64' +AS '$libdir/onesparse', 'vector_int64' LANGUAGE C; CREATE CAST (bigint[] AS vector) WITH FUNCTION vector(bigint[]) AS IMPLICIT; CREATE FUNCTION vector(integer[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int32' +AS '$libdir/onesparse', 'vector_int32' LANGUAGE C; CREATE CAST (integer[] AS vector) WITH FUNCTION vector(integer[]) AS IMPLICIT; CREATE FUNCTION vector(smallint[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int16' +AS '$libdir/onesparse', 'vector_int16' LANGUAGE C; CREATE CAST (smallint[] AS vector) WITH FUNCTION vector(smallint[]) AS IMPLICIT; CREATE FUNCTION vector(float[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_float8' +AS '$libdir/onesparse', 'vector_float8' LANGUAGE C; CREATE CAST (float[] AS vector) WITH FUNCTION vector(float[]) AS IMPLICIT; CREATE FUNCTION vector(real[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_float4' +AS '$libdir/onesparse', 'vector_float4' LANGUAGE C; CREATE CAST (real[] AS vector) WITH FUNCTION vector(real[]) AS IMPLICIT; CREATE FUNCTION vector(bool[]) RETURNS vector -AS '$libdir/pggraphblas', 'vector_bool' +AS '$libdir/onesparse', 'vector_bool' LANGUAGE C; CREATE CAST (bool[] AS vector) WITH FUNCTION vector(bool[]) AS IMPLICIT; @@ -926,64 +805,64 @@ CREATE CAST (bool[] AS vector) WITH FUNCTION vector(bool[]) AS IMPLICIT; CREATE FUNCTION vector_bigint(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_int64' +AS '$libdir/onesparse', 'vector_empty_int64' LANGUAGE C STRICT; CREATE FUNCTION vector_integer(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_int32' +AS '$libdir/onesparse', 'vector_empty_int32' LANGUAGE C STRICT; CREATE FUNCTION vector_smallint(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_int16' +AS '$libdir/onesparse', 'vector_empty_int16' LANGUAGE C STRICT; CREATE FUNCTION vector_float(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_float8' +AS '$libdir/onesparse', 'vector_empty_float8' LANGUAGE C STRICT; CREATE FUNCTION vector_real(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_float4' +AS '$libdir/onesparse', 'vector_empty_float4' LANGUAGE C STRICT; CREATE FUNCTION vector_bool(size bigint) RETURNS vector -AS '$libdir/pggraphblas', 'vector_empty_bool' +AS '$libdir/onesparse', 'vector_empty_bool' LANGUAGE C STRICT; -- sparse construction CREATE FUNCTION vector(bigint[], bigint[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int64' +AS '$libdir/onesparse', 'vector_int64' LANGUAGE C; CREATE FUNCTION vector(bigint[], integer[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int32' +AS '$libdir/onesparse', 'vector_int32' LANGUAGE C; CREATE FUNCTION vector(bigint[], smallint[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_int16' +AS '$libdir/onesparse', 'vector_int16' LANGUAGE C; CREATE FUNCTION vector(bigint[], float[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_float8' +AS '$libdir/onesparse', 'vector_float8' LANGUAGE C; CREATE FUNCTION vector(bigint[], real[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_float4' +AS '$libdir/onesparse', 'vector_float4' LANGUAGE C; CREATE FUNCTION vector(bigint[], bool[], bigint default null) RETURNS vector -AS '$libdir/pggraphblas', 'vector_bool' +AS '$libdir/onesparse', 'vector_bool' LANGUAGE C; -- tuple formats for vector edges @@ -997,30 +876,30 @@ CREATE TYPE vector_element_bool AS (index bigint, value bool); CREATE FUNCTION elements_bigint(A vector) RETURNS SETOF vector_element_bigint -AS '$libdir/pggraphblas', 'vector_elements_int64' +AS '$libdir/onesparse', 'vector_elements_int64' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_integer(A vector) RETURNS SETOF vector_element_integer -AS '$libdir/pggraphblas', 'vector_elements_int32' +AS '$libdir/onesparse', 'vector_elements_int32' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_smallint(A vector) RETURNS SETOF vector_element_smallint -AS '$libdir/pggraphblas', 'vector_elements_int16' +AS '$libdir/onesparse', 'vector_elements_int16' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_float(A vector) RETURNS SETOF vector_element_float -AS '$libdir/pggraphblas', 'vector_elements_float8' +AS '$libdir/onesparse', 'vector_elements_float8' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_real(A vector) RETURNS SETOF vector_element_real -AS '$libdir/pggraphblas', 'vector_elements_float4' +AS '$libdir/onesparse', 'vector_elements_float4' LANGUAGE C STABLE STRICT; CREATE FUNCTION elements_bool(A vector) RETURNS SETOF vector_element_bool -AS '$libdir/pggraphblas', 'vector_elements_bool' +AS '$libdir/onesparse', 'vector_elements_bool' LANGUAGE C STABLE STRICT; diff --git a/pggraphblas.control b/onesparse.control similarity index 60% rename from pggraphblas.control rename to onesparse.control index 27d93fd..8e1ef34 100644 --- a/pggraphblas.control +++ b/onesparse.control @@ -1,5 +1,6 @@ -# pggraphblas extension +# onesparse extension comment = 'Postgres extension for SuiteSparse::GraphBLAS' default_version = '0.0.1' -relocatable = true +relocatable = false +schema = 'onesparse' requires = '' diff --git a/psql b/psql index 2fff2f0..846a5fa 100755 --- a/psql +++ b/psql @@ -1 +1 @@ -docker run -it pggraphblas/test psql -U postgres +docker run -it onesparse/test psql -U postgres diff --git a/src/LAGraph_pagerank.c b/src/LAGraph_pagerank.c deleted file mode 100644 index e8887e2..0000000 --- a/src/LAGraph_pagerank.c +++ /dev/null @@ -1,346 +0,0 @@ -//------------------------------------------------------------------------------ -// SuiteSparse/GraphBLAS/Demo/Source/dpagerank: pagerank using a real semiring -//------------------------------------------------------------------------------ - -// A is a square unsymmetric binary matrix of size n-by-n, where A(i,j) is the -// edge (i,j). Self-edges are LAGRAPH_OK. A can be of any built-in type. - -// On output, P is pointer to an array of LAGraph_PageRank structs. P[0] is the -// highest ranked page, with pagerank P[0].pagerank and the page corresponds to -// node number P[0].page in the graph. P[1] is the next page, and so on, to -// the lowest-ranked page P[n-1].page with rank P[n-1].pagerank. - -// See dpagerank.m for the equivalent computation in MATLAB (except the random -// number generator differs). - -//------------------------------------------------------------------------------ -// helper macros -//------------------------------------------------------------------------------ - -// free all workspace -#define FREEWORK \ -{ \ - GrB_free (&D) ; \ - GrB_free (&C) ; \ - GrB_free (&r) ; \ - GrB_free (&t) ; \ - GrB_free (&d) ; \ - if (I != NULL) { free_function (I) ; I = NULL ; } \ - if (X != NULL) { free_function (X) ; X = NULL ; } \ - GrB_free (&op_div) ; \ - GrB_free (&op_diff) ; \ -} - -// error handler: free output P and all workspace -#define LAGRAPH_FREE_ALL \ -{ \ - if (P != NULL) { free_function (P) ; P = NULL ; } \ - FREEWORK ; \ -} - -//------------------------------------------------------------------------------ -// scalar operators -//------------------------------------------------------------------------------ - -#define DAMPING 0.85 - -float rsum ; -#pragma omp threadprivate(rsum) - -void fdiv (void *z, const void *x) -{ - (*((float *) z)) = (* ((float *) x)) / rsum ; -} - -void fdiff (void *z, const void *x, const void *y) -{ - float delta = (* ((float *) x)) - (* ((float *) y)) ; - (*((float *) z)) = delta * delta ; -} - -//------------------------------------------------------------------------------ -// comparison function for qsort -//------------------------------------------------------------------------------ - -int compar (const void *x, const void *y) -{ - LAGraph_PageRank *a = (LAGraph_PageRank *) x ; - LAGraph_PageRank *b = (LAGraph_PageRank *) y ; - - // sort by pagerank in descending order - if (a->pagerank > b->pagerank) - { - return (-1) ; - } - else if (a->pagerank == b->pagerank) - { - return (0) ; - } - else - { - return (1) ; - } -} - -//------------------------------------------------------------------------------ -// LAGraph_pagerank: compute the pagerank of all nodes in a graph -//------------------------------------------------------------------------------ - -GrB_Info LAGraph_pagerank2 // GrB_SUCCESS or error condition -( - LAGraph_PageRank **Phandle, // output: array of LAGraph_PageRank structs - GrB_Matrix A, // binary input graph, not modified - int itermax, // max number of iterations - double tol, // stop when norm (r-rnew,2) < tol - int *iters // number of iterations taken -) -{ - - //-------------------------------------------------------------------------- - // initializations - //-------------------------------------------------------------------------- - - double tic [2] ; - LAGraph_tic (tic) ; - - GrB_Info info ; - float *X = NULL ; - GrB_Index n, nvals, *I = NULL ; - LAGraph_PageRank *P = NULL ; - GrB_Vector r = NULL, t = NULL, d = NULL ; - GrB_UnaryOp op_div = NULL ; - GrB_BinaryOp op_diff = NULL ; - GrB_Matrix C = NULL, D = NULL ; - - if (Phandle == NULL) LAGRAPH_ERROR ("null pointer", GrB_NULL_POINTER) ; - (*Phandle) = NULL ; - - // n = size (A,1) ; // number of nodes - LAGRAPH_OK (GrB_Matrix_nrows (&n, A)) ; - if (n == 0) return (GrB_SUCCESS) ; - - // teleport = (1 - 0.85) / n - float one = 1.0 ; - float teleport = (one - DAMPING) / ((float) n) ; - - // r (i) = 1/n for all nodes i - float x = 1.0 / ((float) n) ; - LAGRAPH_OK (GrB_Vector_new (&r, GrB_FP32, n)) ; - LAGRAPH_OK (GrB_assign (r, NULL, NULL, x, GrB_ALL, n, NULL)) ; - - // d (i) = out deg of node i - LAGRAPH_OK (GrB_Vector_new (&d, GrB_FP32, n)) ; - LAGRAPH_OK (GrB_reduce (d, NULL, NULL, GrB_PLUS_FP32, A, NULL)) ; - - // D = (1/diag (d)) * DAMPING - #ifdef GxB_SUITESPARSE_GRAPHBLAS - GrB_Type type ; - LAGRAPH_OK (GxB_Vector_export (&d, &type, &n, &nvals, &I, (void **) (&X), - NULL)) ; - #else - nvals = n ; - I = malloc_function ((nvals + 1) * sizeof (GrB_Index)) ; - X = malloc_function ((nvals + 1) * sizeof (float)) ; - if (I == NULL || X == NULL) - { - LAGRAPH_ERROR ("out of memory", GrB_OUT_OF_MEMORY) ; - } - LAGRAPH_OK (GrB_Vector_extract (I, X, &nvals, d)) ; - LAGRAPH_OK (GrB_free (&d)) ; - #endif - - for (int64_t k = 0 ; k < nvals ; k++) X [k] = DAMPING / X [k] ; - LAGRAPH_OK (GrB_Matrix_new (&D, GrB_FP32, n, n)) ; - LAGRAPH_OK (GrB_Matrix_build (D, I, I, X, nvals, GrB_PLUS_FP32)) ; - free_function (I) ; - free_function (X) ; - - // GxB_print (D, 3) ; - - // C = diagonal matrix with all zeros on the diagonal. This ensures that - // the vectors r and t remain dense, which is faster. - LAGRAPH_OK (GrB_Matrix_new (&C, GrB_FP32, n, n)) ; - // GxB_set (C, GxB_HYPER, GxB_ALWAYS_HYPER) ; - - for (int64_t k = 0 ; k < n ; k++) - { - // C(k,k) = 0 - LAGRAPH_OK (GrB_Matrix_setElement (C, (float) 0, k, k)) ; - } - - - // GxB_print (A, 3) ; - - // GxB_print (C, 3) ; - - double tt = LAGraph_toc (tic) ; - fprintf (stderr, "init time %g\n", tt) ; - LAGraph_tic (tic) ; - - // C = C+(D*A)' = C+A'*D' using A(i,j)/D(i,i) as the multiplicative operator - LAGRAPH_OK (GrB_mxm (C, NULL, GrB_PLUS_FP32, GxB_PLUS_TIMES_FP32, A, D, - LAGraph_desc_ttoo)) ; - -/* - // C = C+(D*A) - LAGRAPH_OK (GrB_mxm (C, NULL, GrB_PLUS_FP32, GxB_PLUS_TIMES_FP32, D, A, - NULL)) ; -*/ - - LAGRAPH_OK (GrB_free (&D)) ; - - // create operators - LAGRAPH_OK (GrB_UnaryOp_new (&op_div, fdiv, GrB_FP32, GrB_FP32)) ; - LAGRAPH_OK (GrB_BinaryOp_new (&op_diff, fdiff, GrB_FP32, GrB_FP32, - GrB_FP32)) ; - - float ftol = tol*tol ; // use tol^2 so sqrt(rdiff) not needed - float rdiff = 1 ; // so first iteration is always done - - LAGRAPH_OK (GrB_Vector_new (&t, GrB_FP32, n)) ; - - // GxB_print (C, 2) ; - // GxB_fprint (C, 2, stderr) ; - - tt = LAGraph_toc (tic) ; - fprintf (stderr, "C time %g\n", tt) ; - LAGraph_tic (tic) ; - - //-------------------------------------------------------------------------- - // iterate to compute the pagerank of each node - //-------------------------------------------------------------------------- - - double t2 = 0 ; - - for ((*iters) = 0 ; (*iters) < itermax && rdiff > ftol ; (*iters)++) - { - - //---------------------------------------------------------------------- - // t = r*C + (teleport * sum (r)) ; - //---------------------------------------------------------------------- - - // GxB_print (r, 2) ; - - float s = 1 ; - LAGRAPH_OK (GrB_reduce (&s, NULL, GxB_PLUS_FP32_MONOID, r, NULL)) ; - // printf ("s %g\n", s) ; - - double tic2 [2] ; - LAGraph_tic (tic2) ; - -// LAGRAPH_OK (GrB_vxm (t, NULL, NULL, GxB_PLUS_TIMES_FP32, r, C, NULL)) ; - LAGRAPH_OK (GrB_mxv (t, NULL, NULL, GxB_PLUS_TIMES_FP32, C, r, NULL)) ; - - double t3 = LAGraph_toc (tic2) ; - t2 += t3 ; -// fprintf (stderr, "one mxv %g\n", t3) ; - -// LAGraph_tic (tic2) ; -// LAGRAPH_OK (GrB_mxv (t, NULL, NULL, GxB_PLUS_TIMES_FP32, C, r, NULL)) ; -// t3 = LAGraph_toc (tic2) ; -// fprintf (stderr, "another mxv %g\n", t3) ; - - s *= teleport ; - LAGRAPH_OK (GrB_assign (t, NULL, GrB_PLUS_FP32, s, GrB_ALL, n, NULL)) ; - - //---------------------------------------------------------------------- - // rdiff = sum ((r-t).^2) - //---------------------------------------------------------------------- - - LAGRAPH_OK (GrB_eWiseAdd (r, NULL, NULL, op_diff, r, t, NULL)) ; - LAGRAPH_OK (GrB_reduce (&rdiff, NULL, GxB_PLUS_FP32_MONOID, r, NULL)) ; - - //---------------------------------------------------------------------- - // swap r and t - //---------------------------------------------------------------------- - - GrB_Vector temp = r ; - r = t ; - t = temp ; -// LAGRAPH_OK (GrB_Vector_clear (t)) ; - - // GxB_print (r, 3) ; - } - - fprintf (stderr, "mxv %g\n", t2) ; - - LAGRAPH_OK (GrB_free (&C)) ; - LAGRAPH_OK (GrB_free (&t)) ; - - tt = LAGraph_toc (tic) ; - fprintf (stderr, "rank time %g\n", tt) ; - LAGraph_tic (tic) ; - - //-------------------------------------------------------------------------- - // scale the result - //-------------------------------------------------------------------------- - - // rsum = sum (r) - LAGRAPH_OK (GrB_reduce (&rsum, NULL, GxB_PLUS_FP32_MONOID, r, NULL)) ; - - // r = r / rsum - LAGRAPH_OK (GrB_apply (r, NULL, NULL, op_div, r, NULL)) ; - - //-------------------------------------------------------------------------- - // sort the nodes by pagerank - //-------------------------------------------------------------------------- - - // [r,irank] = sort (r, 'descend') ; - - // extract the contents of r - #ifdef GxB_SUITESPARSE_GRAPHBLAS - LAGRAPH_OK (GxB_Vector_export (&r, &type, &n, &nvals, &I, (void **) (&X), - NULL)) ; - #else - nvals = n ; - I = malloc_function (n * sizeof (GrB_Index)) ; - X = malloc_function (n * sizeof (float)) ; - if (I == NULL || X == NULL) - { - LAGRAPH_ERROR ("out of memory", GrB_OUT_OF_MEMORY) ; - } - LAGRAPH_OK (GrB_Vector_extractTuples (I, X, &nvals, r)) ; - LAGRAPH_OK (GrB_free (&r)) ; - #endif - - // this will always be true since r is dense, but check anyway: - if (nvals != n) return (GrB_PANIC) ; - - // P = struct (X,I) - P = malloc_function (n * sizeof (LAGraph_PageRank)) ; - if (P == NULL) - { - LAGRAPH_ERROR ("out of memory", GrB_OUT_OF_MEMORY) ; - } - for (int64_t k = 0 ; k < nvals ; k++) - { - // The kth ranked page is P[k].page (with k=0 being the highest rank), - // and its pagerank is P[k].pagerank. - P [k].pagerank = X [k] ; - // I [k] == k will be true for SuiteSparse:GraphBLAS but in general I - // can be returned in any order, so use I [k] instead of k, for other - // GraphBLAS implementations. - #ifdef GxB_SUITESPARSE_GRAPHBLAS - P [k].page = k ; - #else - P [k].page = I [k] ; - #endif - } - - // free workspace - FREEWORK ; - - // qsort (P) in descending order - qsort (P, n, sizeof (LAGraph_PageRank), compar) ; - - //-------------------------------------------------------------------------- - // return result - //-------------------------------------------------------------------------- - - tt = LAGraph_toc (tic) ; - fprintf (stderr, "fini time %g\n", tt) ; - - (*Phandle) = P ; - return (GrB_SUCCESS) ; -} - diff --git a/src/matrix.c b/src/matrix.c index ba46a72..e9428ba 100644 --- a/src/matrix.c +++ b/src/matrix.c @@ -1,7 +1,20 @@ -/* The same "header template" vector.h is used to generate the various +/* The same "header template" matrix.h is used to generate the various type specific functions. */ +#define SUFFIX _int64 // suffix for names +#define PG_TYPE int64 // postgres type +#define GB_TYPE GrB_INT64 // graphblas vector type +#define GB_DUP GrB_SECOND_INT64 // default duplicate index resolver +#define GB_MUL GrB_TIMES_INT64 // times bin op +#define GB_ADD GrB_PLUS_INT64 // times bin op +#define PG_GET PG_GETARG_INT64 // how to get value args +#define PG_RET PG_RETURN_INT64 +#define PG_DGT DatumGetInt64 // datum get type +#define PG_TGD Int64GetDatum // type get datum +#define PRINT_FMT(v) "%lu", v // printf fmt +#include "matrix.h" // "call" template + #define SUFFIX _bool #define PG_TYPE bool #define GB_TYPE GrB_BOOL @@ -54,19 +67,6 @@ #define PRINT_FMT(v) "%i", v #include "matrix.h" -#define SUFFIX _int64 // suffix for names -#define PG_TYPE int64 // postgres type -#define GB_TYPE GrB_INT64 // graphblas vector type -#define GB_DUP GrB_SECOND_INT64 // default duplicate index resolver -#define GB_MUL GrB_TIMES_INT64 // times bin op -#define GB_ADD GrB_PLUS_INT64 // times bin op -#define PG_GET PG_GETARG_INT64 // how to get value args -#define PG_RET PG_RETURN_INT64 -#define PG_DGT DatumGetInt64 // datum get type -#define PG_TGD Int64GetDatum // type get datum -#define PRINT_FMT(v) "%lu", v // printf fmt -#include "matrix.h" // "call" template - #define SUFFIX _float4 #define PG_TYPE float4 #define GB_TYPE GrB_FP32 @@ -95,720 +95,536 @@ /* MemoryContextCallback function to free matrices */ static void -context_callback_matrix_free(void* m) { - pgGrB_Matrix *mat = (pgGrB_Matrix *) m; - GrB_Matrix_free(&mat->M); +context_callback_matrix_free(void* m) +{ + OS_Matrix *mat = (OS_Matrix *) m; + GrB_Matrix_free(&mat->M); } /* Construct an empty flat matrix. */ -pgGrB_FlatMatrix * +OS_FlatMatrix * construct_empty_flat_matrix(GrB_Index nrows, - GrB_Index ncols, - GrB_Type type) { - pgGrB_FlatMatrix *result; - - result = (pgGrB_FlatMatrix *) palloc0(sizeof(pgGrB_FlatMatrix)); - SET_VARSIZE(result, sizeof(pgGrB_FlatMatrix)); - result->nrows = ncols; - result->ncols = nrows; - result->nvals = 0; - result->type = type; - return result; + GrB_Index ncols, + GrB_Type type) +{ + OS_FlatMatrix *result; + + result = (OS_FlatMatrix *) palloc0(sizeof(OS_FlatMatrix)); + SET_VARSIZE(result, sizeof(OS_FlatMatrix)); + result->nrows = ncols; + result->ncols = nrows; + result->nvals = 0; + result->type = type; + return result; } /* Helper function to always expanded datum -This is used by PGGRB_GETARG_MATRIX */ -pgGrB_Matrix * -DatumGetMatrix(Datum d) { - pgGrB_Matrix *A; - pgGrB_FlatMatrix *flat; - - if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(d))) { - A = MatrixGetEOHP(d); - Assert(A->em_magic == matrix_MAGIC); - return A; - } - flat = (pgGrB_FlatMatrix*)PG_DETOAST_DATUM(d); - TYPE_APPLY(d, flat->type, expand_flat_matrix, flat, CurrentMemoryContext); - return MatrixGetEOHP(d); + This is used by OS_GETARG_MATRIX */ +OS_Matrix * +DatumGetMatrix(Datum d) +{ + OS_Matrix *A; + OS_FlatMatrix *flat; + + if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(d))) + { + A = MatrixGetEOHP(d); + Assert(A->em_magic == matrix_MAGIC); + return A; + } + flat = (OS_FlatMatrix*)PG_DETOAST_DATUM(d); + TYPE_APPLY(d, flat->type, expand_flat_matrix, flat, CurrentMemoryContext); + return MatrixGetEOHP(d); } Datum -matrix_in(PG_FUNCTION_ARGS) { - pgGrB_FlatMatrix *flat; - char *input; - size_t len; - int bc; - Datum d; - - input = PG_GETARG_CSTRING(0); - len = strlen(input); - bc = (len) / 2 + VARHDRSZ; - flat = palloc(bc); - hex_decode(input, len, (char*)flat); - TYPE_APPLY(d, flat->type, expand_flat_matrix, flat, CurrentMemoryContext); - return d; +matrix_in(PG_FUNCTION_ARGS) +{ + OS_FlatMatrix *flat; + char *input; + size_t len; + int bc; + Datum d; + + input = PG_GETARG_CSTRING(0); + len = strlen(input); + bc = (len) / 2 + VARHDRSZ; + flat = palloc(bc); + hex_decode(input, len, (char*)flat); + TYPE_APPLY(d, flat->type, expand_flat_matrix, flat, CurrentMemoryContext); + return d; } Datum matrix_out(PG_FUNCTION_ARGS) { - Size size; - char *rp, *result, *buf; - pgGrB_Matrix *A = PGGRB_GETARG_MATRIX(0); - size = EOH_get_flat_size(&A->hdr); - buf = palloc(size); - EOH_flatten_into(&A->hdr, buf, size); - rp = result = palloc((size * 2) + 1); - rp += hex_encode(buf, size, rp); - *rp = '\0'; - PG_RETURN_CSTRING(result); + Size size; + char *rp, *result, *buf; + OS_Matrix *A = OS_GETARG_MATRIX(0); + size = EOH_get_flat_size(&A->hdr); + buf = palloc(size); + EOH_flatten_into(&A->hdr, buf, size); + rp = result = palloc((size * 2) + 1); + rp += hex_encode(buf, size, rp); + *rp = '\0'; + PG_RETURN_CSTRING(result); } Datum -matrix_nrows(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *mat; - GrB_Index count; - mat = PGGRB_GETARG_MATRIX(0); - CHECKD(GrB_Matrix_nrows(&count, mat->M)); - return Int64GetDatum(count); +matrix_nrows(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *mat; + GrB_Index count; + mat = OS_GETARG_MATRIX(0); + CHECKD(GrB_Matrix_nrows(&count, mat->M), mat->M); + return Int64GetDatum(count); } Datum -matrix_ncols(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *mat; - GrB_Index count; - mat = PGGRB_GETARG_MATRIX(0); - CHECKD(GrB_Matrix_ncols(&count, mat->M)); - return Int64GetDatum(count); +matrix_ncols(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *mat; + GrB_Index count; + mat = OS_GETARG_MATRIX(0); + CHECKD(GrB_Matrix_ncols(&count, mat->M), mat->M); + return Int64GetDatum(count); } Datum -matrix_nvals(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *mat; - GrB_Index count; - mat = PGGRB_GETARG_MATRIX(0); - CHECKD(GrB_Matrix_nvals(&count, mat->M)); - return Int64GetDatum(count); +matrix_nvals(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *mat; + GrB_Index count; + mat = OS_GETARG_MATRIX(0); + CHECKD(GrB_Matrix_nvals(&count, mat->M), mat->M); + return Int64GetDatum(count); } Datum -matrix_eq(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *B; - bool result; +matrix_eq(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A, *B; + bool result; - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); - CHECKD(LAGraph_isequal(&result, A->M, B->M, NULL)); - PG_RETURN_BOOL(result); + result = true; + PG_RETURN_BOOL(result); } Datum -matrix_ne(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *B; - bool result; +matrix_ne(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A, *B; + bool result; - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); - CHECKD(LAGraph_isequal(&result, A->M, B->M, NULL)); - PG_RETURN_BOOL(!result); + result = true; + PG_RETURN_BOOL(!result); } Datum -matrix_ewise_mult(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A, *B, *C = NULL, *mask = NULL; - Datum d; - char *binop_name, *accum_name; - GrB_BinaryOp binop = NULL, accum = NULL; - GrB_Descriptor desc = NULL; - GrB_Info info; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - - binop_name = matrix_times_binop(A, B); - accum_name = NULL; - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_MATRIX(3); - binop_name = PG_ARGISNULL(4) ? - binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); - accum_name = PG_ARGISNULL(5) ? - accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - binop = lookup_binop(binop_name); - if (binop == NULL) - elog(ERROR, "unknown binop name %s", binop_name); - if (accum_name != NULL) - accum = lookup_binop(accum_name); - - TYPE_APPLY(d, A->type, matrix_ewise_mult, A, B, C, mask, binop, accum, desc); - return d; +matrix_ewise_mult(PG_FUNCTION_ARGS) +{ + OS_Matrix *A, *B, *C = NULL, *mask = NULL; + Datum d; + char *binop_name, *accum_name; + GrB_BinaryOp binop = NULL, accum = NULL; + GrB_Descriptor desc = NULL; + GrB_Info info; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + + binop_name = matrix_times_binop(A, B); + accum_name = NULL; + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_MATRIX(3); + binop_name = PG_ARGISNULL(4) ? + binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); + accum_name = PG_ARGISNULL(5) ? + accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + binop = lookup_binop(binop_name); + if (binop == NULL) + elog(ERROR, "unknown binop name %s", binop_name); + if (accum_name != NULL) + accum = lookup_binop(accum_name); + + TYPE_APPLY(d, A->type, matrix_ewise_mult, A, B, C, mask, binop, accum, desc); + return d; } Datum -matrix_ewise_add(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A, *B, *C = NULL, *mask = NULL; - Datum d; - char *binop_name, *accum_name; - GrB_BinaryOp binop = NULL, accum = NULL; - GrB_Descriptor desc = NULL; - GrB_Info info; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - - accum_name = NULL; - binop_name = matrix_plus_binop(A, B); - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_MATRIX(3); - binop_name = PG_ARGISNULL(4) ? - binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); - accum_name = PG_ARGISNULL(5) ? - accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - binop = lookup_binop(binop_name); - if (binop == NULL) - elog(ERROR, "unknown binop name %s", binop_name); - if (accum_name != NULL) - accum = lookup_binop(accum_name); - - TYPE_APPLY(d, A->type, matrix_ewise_add, A, B, C, mask, binop, accum, desc); - return d; +matrix_ewise_add(PG_FUNCTION_ARGS) +{ + OS_Matrix *A, *B, *C = NULL, *mask = NULL; + Datum d; + char *binop_name, *accum_name; + GrB_BinaryOp binop = NULL, accum = NULL; + GrB_Descriptor desc = NULL; + GrB_Info info; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + + accum_name = NULL; + binop_name = matrix_plus_binop(A, B); + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_MATRIX(3); + binop_name = PG_ARGISNULL(4) ? + binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); + accum_name = PG_ARGISNULL(5) ? + accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + binop = lookup_binop(binop_name); + if (binop == NULL) + elog(ERROR, "unknown binop name %s", binop_name); + if (accum_name != NULL) + accum = lookup_binop(accum_name); + + TYPE_APPLY(d, A->type, matrix_ewise_add, A, B, C, mask, binop, accum, desc); + return d; } Datum -mxm(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A, *B, *C = NULL, *mask = NULL; - GrB_Info info; - GrB_Type type; - Datum d; - char *semiring_name, *binop_name; - GrB_Semiring semiring; - GrB_BinaryOp binop = NULL; - GrB_Descriptor desc = NULL; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - - semiring_name = mxm_semiring(A, B); - binop_name = NULL; - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_MATRIX(3); - semiring_name = PG_ARGISNULL(4) ? - semiring_name : - text_to_cstring(PG_GETARG_TEXT_PP(4)); - binop_name = PG_ARGISNULL(5) ? - NULL : - text_to_cstring(PG_GETARG_TEXT_PP(5)); - - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - semiring = lookup_semiring(semiring_name); - if (semiring == NULL) - elog(ERROR, "unknown semiring name %s", semiring_name); - - if (binop_name != NULL) - binop = lookup_binop(binop_name); - - if (semiring == NULL) - elog(ERROR, "unknown semiring name %s", semiring_name); - - type = mxm_type(A, B); - - TYPE_APPLY(d, type, mxm, A, B, C, mask, semiring, binop, desc); - return d; +mxm(PG_FUNCTION_ARGS) +{ + OS_Matrix *A, *B, *C = NULL, *mask = NULL; + GrB_Info info; + GrB_Type type; + Datum d; + char *semiring_name, *binop_name; + GrB_Semiring semiring; + GrB_BinaryOp binop = NULL; + GrB_Descriptor desc = NULL; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + + semiring_name = mxm_semiring(A, B); + binop_name = NULL; + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_MATRIX(3); + semiring_name = PG_ARGISNULL(4) ? + semiring_name : + text_to_cstring(PG_GETARG_TEXT_PP(4)); + binop_name = PG_ARGISNULL(5) ? + NULL : + text_to_cstring(PG_GETARG_TEXT_PP(5)); + + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + semiring = lookup_semiring(semiring_name); + if (semiring == NULL) + elog(ERROR, "unknown semiring name %s", semiring_name); + + if (binop_name != NULL) + binop = lookup_binop(binop_name); + + if (semiring == NULL) + elog(ERROR, "unknown semiring name %s", semiring_name); + + type = mxm_type(A, B); + + TYPE_APPLY(d, type, mxm, A, B, C, mask, semiring, binop, desc); + return d; } Datum -mxv(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A; - pgGrB_Vector *B, *C = NULL, *mask = NULL; - GrB_Type type; - Datum d; - char *semiring_name, *binop_name; - GrB_Semiring semiring; - GrB_BinaryOp binop = NULL; - GrB_Descriptor desc = NULL; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_VECTOR(1); - - semiring_name = mxv_semiring(A, B); - binop_name = NULL; - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_VECTOR(3); - semiring_name = PG_ARGISNULL(4) ? - semiring_name : - text_to_cstring(PG_GETARG_TEXT_PP(4)); - binop_name = PG_ARGISNULL(5) ? - NULL : - text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - if (binop_name != NULL) - binop = lookup_binop(binop_name); - - semiring = lookup_semiring(semiring_name); - if (semiring == NULL) - elog(ERROR, "unknown semiring name %s", semiring_name); - - type = mxv_type(A, B); - - TYPE_APPLY(d, type, mxv, A, B, C, mask, semiring, binop, desc); - return d; +mxv(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A; + OS_Vector *B, *C = NULL, *mask = NULL; + GrB_Type type; + Datum d; + char *semiring_name, *binop_name; + GrB_Semiring semiring; + GrB_BinaryOp binop = NULL; + GrB_Descriptor desc = NULL; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_VECTOR(1); + + semiring_name = mxv_semiring(A, B); + binop_name = NULL; + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_VECTOR(3); + semiring_name = PG_ARGISNULL(4) ? + semiring_name : + text_to_cstring(PG_GETARG_TEXT_PP(4)); + binop_name = PG_ARGISNULL(5) ? + NULL : + text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + if (binop_name != NULL) + binop = lookup_binop(binop_name); + + semiring = lookup_semiring(semiring_name); + if (semiring == NULL) + elog(ERROR, "unknown semiring name %s", semiring_name); + + type = mxv_type(A, B); + + TYPE_APPLY(d, type, mxv, A, B, C, mask, semiring, binop, desc); + return d; } Datum -vxm(PG_FUNCTION_ARGS) { - pgGrB_Matrix *B; - pgGrB_Vector *A, *C = NULL, *mask = NULL; - GrB_Type type; - GrB_Info info; - Datum d; - char *semiring_name, *binop_name; - GrB_Semiring semiring; - GrB_BinaryOp binop = NULL; - GrB_Descriptor desc = NULL; - - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_MATRIX(1); - - semiring_name = vxm_semiring(A, B); - binop_name = NULL; - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_VECTOR(3); - semiring_name = PG_ARGISNULL(4) ? semiring_name : PG_GETARG_CSTRING(4); - binop_name = PG_ARGISNULL(5) ? - NULL : - text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - if (binop_name != NULL) - binop = lookup_binop(binop_name); - - semiring = lookup_semiring(semiring_name); - if (semiring == NULL) - elog(ERROR, "unknown semiring name %s", semiring_name); - - type = vxm_type(A, B); - - TYPE_APPLY(d, type, vxm, A, B, C, mask, semiring, binop, desc); - return d; +vxm(PG_FUNCTION_ARGS) +{ + OS_Matrix *B; + OS_Vector *A, *C = NULL, *mask = NULL; + GrB_Type type; + GrB_Info info; + Datum d; + char *semiring_name, *binop_name; + GrB_Semiring semiring; + GrB_BinaryOp binop = NULL; + GrB_Descriptor desc = NULL; + + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_MATRIX(1); + + semiring_name = vxm_semiring(A, B); + binop_name = NULL; + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_VECTOR(3); + semiring_name = PG_ARGISNULL(4) ? semiring_name : PG_GETARG_CSTRING(4); + binop_name = PG_ARGISNULL(5) ? + NULL : + text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + if (binop_name != NULL) + binop = lookup_binop(binop_name); + + semiring = lookup_semiring(semiring_name); + if (semiring == NULL) + elog(ERROR, "unknown semiring name %s", semiring_name); + + type = vxm_type(A, B); + + TYPE_APPLY(d, type, vxm, A, B, C, mask, semiring, binop, desc); + return d; } Datum -matrix_reduce_vector(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A; - GrB_Semiring semiring; - GrB_Monoid monoid; - char *semiring_name; - pgGrB_Vector *val; - GrB_Index size; - GrB_Type type; - - A = PGGRB_GETARG_MATRIX(0); - semiring_name = PG_ARGISNULL(1)? - NULL: - text_to_cstring(PG_GETARG_TEXT_PP(1)); - - if (semiring_name == NULL) { - CHECKD(GxB_Matrix_type(&type, A->M)); - semiring_name = DEFAULT_SEMIRING(type); - } - - semiring = lookup_semiring(semiring_name); - CHECKD(GxB_Semiring_add(&monoid, semiring)); - - CHECKD(GrB_Matrix_ncols(&size, A->M)); - TYPE_APPLY(val, A->type, construct_empty_expanded_vector, size, CurrentMemoryContext); - - CHECKD(GrB_reduce(val->V, NULL, monoid, A->M, NULL)); - PGGRB_RETURN_VECTOR(val); +matrix_reduce_vector(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A; + GrB_Semiring semiring; + GrB_Monoid monoid; + char *semiring_name; + OS_Vector *val; + GrB_Index size; + GrB_Type type; + + A = OS_GETARG_MATRIX(0); + semiring_name = PG_ARGISNULL(1)? + NULL: + text_to_cstring(PG_GETARG_TEXT_PP(1)); + + if (semiring_name == NULL) + { + CHECKD(GxB_Matrix_type(&type, A->M), A->M); + semiring_name = DEFAULT_SEMIRING(type); + } + + semiring = lookup_semiring(semiring_name); + CHECKD(GxB_Semiring_add(&monoid, semiring), semiring); + + CHECKD(GrB_Matrix_ncols(&size, A->M), A->M); + TYPE_APPLY(val, A->type, construct_empty_expanded_vector, size, CurrentMemoryContext); + + CHECKD(GrB_reduce(val->V, NULL, monoid, A->M, NULL), A->M); + OS_RETURN_VECTOR(val); } Datum matrix_transpose(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *C = NULL, *mask; - GrB_Index m, n; - GrB_Descriptor desc = NULL; - - A = PGGRB_GETARG_MATRIX(0); - - if (PG_NARGS() > 0) { - C = PG_ARGISNULL(1) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(3); - if (PG_NARGS() > 3) { - GET_DESCRIPTOR(3, desc); - } - } - - if (C == NULL) { - CHECKD(GrB_Matrix_nrows(&m, A->M)); - CHECKD(GrB_Matrix_ncols(&n, A->M)); - TYPE_APPLY(C, A->type, construct_empty_expanded_matrix, m, n, CurrentMemoryContext); - } - - CHECKD(GrB_transpose(C->M, mask? mask->M:NULL, NULL, A->M, desc)); - PGGRB_RETURN_MATRIX(C); + GrB_Info info; + OS_Matrix *A, *C = NULL, *mask; + GrB_Index m, n; + GrB_Descriptor desc = NULL; + + A = OS_GETARG_MATRIX(0); + + if (PG_NARGS() > 0) + { + C = PG_ARGISNULL(1) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(3); + if (PG_NARGS() > 3) + GET_DESCRIPTOR(3, desc); + } + + if (C == NULL) + { + CHECKD(GrB_Matrix_nrows(&m, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&n, A->M), A->M); + TYPE_APPLY(C, A->type, construct_empty_expanded_matrix, m, n, CurrentMemoryContext); + } + + CHECKD(GrB_transpose(C->M, mask? mask->M:NULL, NULL, A->M, desc), A->M); + OS_RETURN_MATRIX(C); } Datum -matrix_assign_matrix(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *B, *mask; - GrB_Index nvals, *rows = NULL, *cols = NULL; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - mask = PG_ARGISNULL(2)? NULL : PGGRB_GETARG_MATRIX(2); - - CHECKD(GrB_Matrix_nvals(&nvals, B->M)); - - if (B != NULL) { - TYPE_APPLY(nvals, B->type, extract_rowscols, B, &rows, &cols, nvals); - } - - CHECKD(GrB_assign(A->M, - mask? mask->M: NULL, - NULL, - B->M, - rows? rows : GrB_ALL, - nvals, - cols? cols : GrB_ALL, - nvals, - NULL)); - PGGRB_RETURN_MATRIX(A); +matrix_assign_matrix(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A, *B, *mask; + GrB_Index nvals, *rows = NULL, *cols = NULL; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + mask = PG_ARGISNULL(2)? NULL : OS_GETARG_MATRIX(2); + + CHECKD(GrB_Matrix_nvals(&nvals, B->M), B->M); + + if (B != NULL) + TYPE_APPLY(nvals, B->type, extract_rowscols, B, &rows, &cols, nvals); + + CHECKD(GrB_assign(A->M, + mask? mask->M: NULL, + NULL, + B->M, + rows? rows : GrB_ALL, + nvals, + cols? cols : GrB_ALL, + nvals, + NULL), A->M); + OS_RETURN_MATRIX(A); } Datum matrix_kron(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A, *B, *C = NULL, *mask = NULL; - GrB_Info info; - GrB_Type type; - Datum d; - char *accum_name, *mulop_name; - GrB_BinaryOp accum = NULL, mulop = NULL; - GrB_Descriptor desc = NULL; - - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - accum_name = NULL; - mulop_name = NULL; - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_MATRIX(3); - accum_name = PG_ARGISNULL(4) ? - NULL : - text_to_cstring(PG_GETARG_TEXT_PP(4)); - mulop_name = PG_ARGISNULL(5) ? - NULL : - text_to_cstring(PG_GETARG_TEXT_PP(5)); - - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - if (accum_name != NULL) - accum = lookup_binop(accum_name); - - if (mulop_name == NULL) - mulop_name = matrix_times_binop(A, NULL); - - mulop = lookup_binop(mulop_name); - - type = mxm_type(A, B); - - TYPE_APPLY(d, type, matrix_kron, A, B, C, mask, accum, mulop, desc); - return d; + OS_Matrix *A, *B, *C = NULL, *mask = NULL; + GrB_Info info; + GrB_Type type; + Datum d; + char *accum_name, *mulop_name; + GrB_BinaryOp accum = NULL, mulop = NULL; + GrB_Descriptor desc = NULL; + + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + accum_name = NULL; + mulop_name = NULL; + + if (PG_NARGS() > 2) { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_MATRIX(3); + accum_name = PG_ARGISNULL(4) ? + NULL : + text_to_cstring(PG_GETARG_TEXT_PP(4)); + mulop_name = PG_ARGISNULL(5) ? + NULL : + text_to_cstring(PG_GETARG_TEXT_PP(5)); + + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + if (accum_name != NULL) + accum = lookup_binop(accum_name); + + if (mulop_name == NULL) + mulop_name = matrix_times_binop(A, NULL); + + mulop = lookup_binop(mulop_name); + + type = mxm_type(A, B); + + TYPE_APPLY(d, type, matrix_kron, A, B, C, mask, accum, mulop, desc); + return d; } Datum matrix_xtract(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *B, *C = NULL; - GrB_Index nrows, ncols, nvals, *rows, *cols; - GrB_Descriptor desc = NULL; + GrB_Info info; + OS_Matrix *A, *B, *C = NULL; + GrB_Index nrows, ncols, nvals, *rows, *cols; + GrB_Descriptor desc = NULL; - A = PGGRB_GETARG_MATRIX(0); - B = PGGRB_GETARG_MATRIX(1); - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - GET_DESCRIPTOR(3, desc); + A = OS_GETARG_MATRIX(0); + B = OS_GETARG_MATRIX(1); + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + GET_DESCRIPTOR(3, desc); - CHECKD(GrB_Matrix_nrows(&nrows, A->M)); - CHECKD(GrB_Matrix_ncols(&ncols, A->M)); + CHECKD(GrB_Matrix_nrows(&nrows, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&ncols, A->M), A->M); - if (C == NULL) { - TYPE_APPLY(C, A->type, construct_empty_expanded_matrix, nrows, ncols, CurrentMemoryContext); - } + if (C == NULL) + TYPE_APPLY(C, A->type, construct_empty_expanded_matrix, nrows, ncols, CurrentMemoryContext); - CHECKD(GrB_Matrix_nvals(&nvals, A->M)); - TYPE_APPLY(nvals, A->type, extract_rowscols, B, &rows, &cols, nvals); + CHECKD(GrB_Matrix_nvals(&nvals, A->M), A->M); + TYPE_APPLY(nvals, A->type, extract_rowscols, B, &rows, &cols, nvals); - CHECKD(GrB_Matrix_extract(C->M, NULL, NULL, A->M, rows, nrows, cols, ncols, NULL)); - PGGRB_RETURN_MATRIX(C); + CHECKD(GrB_Matrix_extract(C->M, NULL, NULL, A->M, rows, nrows, cols, ncols, NULL), A->M); + OS_RETURN_MATRIX(C); } Datum matrix_print(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A; - char *result, *buf; - size_t size; - FILE *fp; - int level; - A = PGGRB_GETARG_MATRIX(0); - level = PG_GETARG_INT32(1); - - fp = open_memstream(&buf, &size); - if (fp == NULL) - elog(ERROR, "unable to open memstream for matrix_print"); - GxB_fprint(A->M, level, fp); - fflush(fp); - result = palloc(size + 1); - memcpy(result, buf, size+1); - free(buf); - PG_RETURN_TEXT_P(cstring_to_text_with_len(result, size+1)); -} - -Datum -matrix_mmwrite(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A; - char *result, *buf; - size_t size; - FILE *fp; - A = PGGRB_GETARG_MATRIX(0); - - fp = open_memstream(&buf, &size); - if (fp == NULL) - elog(ERROR, "unable to open memstream for matrix_mmwrite"); - LAGraph_mmwrite(A->M, fp); - fflush(fp); - result = palloc(size + 1); - memcpy(result, buf, size+1); - free(buf); - PG_RETURN_TEXT_P(cstring_to_text_with_len(result, size+1)); -} - -Datum -matrix_mmread(PG_FUNCTION_ARGS) { - GrB_Matrix M; - pgGrB_Matrix *A; - GrB_Info info; - GrB_Index nrows, ncols; - GrB_Type type; - size_t size; - FILE *fp; - char *textdata; - text *input = PG_GETARG_TEXT_PP(0); - - textdata = text_to_cstring(input); - size = strlen(textdata); - fp = fmemopen(textdata, size, "r"); - if (fp == NULL) - elog(ERROR, "unable to open memstream for matrix_mmread"); - - LAGraph_mmread(&M, fp); - CHECKD(GrB_Matrix_nrows(&nrows, M)); - CHECKD(GrB_Matrix_ncols(&ncols, M)); - CHECKD(GxB_Matrix_type(&type, M)); - - TYPE_APPLY(A, type, construct_empty_expanded_matrix, nrows, ncols, CurrentMemoryContext); - CHECKD(GrB_free(&A->M)); - A->M = M; - PGGRB_RETURN_MATRIX(A); -} - -Datum -matrix_bfs(PG_FUNCTION_ARGS) { - pgGrB_Matrix *A, *AT; - pgGrB_Vector *R; - GrB_Vector V, P; - GrB_Index size, start; - GrB_Info info; - - A = PGGRB_GETARG_MATRIX(0); - start = PG_GETARG_INT64(1); - AT = PG_ARGISNULL(2)? NULL : PGGRB_GETARG_MATRIX(2); - - CHECKD(LAGraph_bfs_pushpull(&V, &P, A->M, AT? AT->M : NULL, start, 0, true)); - CHECKD(GrB_Matrix_nrows(&size, A->M)); - TYPE_APPLY(R, GrB_INT32, construct_empty_expanded_vector, size, CurrentMemoryContext); - CHECKD(GrB_free(&R->V)); - R->V = V; - PGGRB_RETURN_VECTOR(R); -} - -Datum -matrix_pagerank(PG_FUNCTION_ARGS) { - GrB_Info info; - FuncCallContext *funcctx; - TupleDesc tupdesc; - Datum result; - - Datum values[2]; - bool nulls[2] = {false, false}; - HeapTuple tuple; - GrB_Index nrows = 0; - pgGrB_Matrix *mat; - pgGrB_Matrix_PageRankState *state; - int iters; - LAGraph_PageRank *ranks = NULL; - - if (SRF_IS_FIRSTCALL()) { - MemoryContext oldcontext; - - funcctx = SRF_FIRSTCALL_INIT(); - oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - mat = PGGRB_GETARG_MATRIX(0); - - state = (pgGrB_Matrix_PageRankState*)palloc(sizeof(pgGrB_Matrix_PageRankState)); - CHECKD(GrB_Matrix_nrows(&nrows, mat->M)); - CHECKD(LAGraph_pagerank(&ranks, mat->M, 100, 0.0001, &iters)); - - state->ranks = ranks; - funcctx->max_calls = nrows; - funcctx->user_fctx = (void*)state; - - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context " - "that cannot accept type record"))); - BlessTupleDesc(tupdesc); - funcctx->tuple_desc = tupdesc; - - MemoryContextSwitchTo(oldcontext); - } - - funcctx = SRF_PERCALL_SETUP(); - state = (pgGrB_Matrix_PageRankState*)funcctx->user_fctx; - - if (funcctx->call_cntr < funcctx->max_calls) { - values[0] = Int64GetDatum(state->ranks[funcctx->call_cntr].page); - values[1] = Float8GetDatum(state->ranks[funcctx->call_cntr].pagerank); - - tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); - SRF_RETURN_NEXT(funcctx, result); - } else { - SRF_RETURN_DONE(funcctx); - } + OS_Matrix *A; + char *result, *buf; + size_t size; + FILE *fp; + int level; + A = OS_GETARG_MATRIX(0); + level = PG_GETARG_INT32(1); + + fp = open_memstream(&buf, &size); + if (fp == NULL) + elog(ERROR, "unable to open memstream for matrix_print"); + GxB_fprint(A->M, level, fp); + fflush(fp); + result = palloc(size + 1); + memcpy(result, buf, size+1); + free(buf); + PG_RETURN_TEXT_P(cstring_to_text_with_len(result, size+1)); } -/* Datum sssp_bf(PG_FUNCTION_ARGS) { */ -/* pgGrB_Matrix *A; */ -/* GrB_Vector pd, ppi, ph; */ -/* GrB_Index start, n; */ -/* GrB_Info info; */ -/* FuncCallContext *funcctx; */ -/* GrB_Index cnt, nrows; */ -/* TupleDesc tupdesc; */ -/* Datum result; */ -/* pgGrB_Matrix_SSSPState *state; */ -/* float8 distance; */ -/* int64 parent; */ -/* int64 hops; */ - -/* Datum values[4]; */ -/* bool nulls[4] = {false, false, false, false}; */ -/* HeapTuple tuple; */ - - -/* if (SRF_IS_FIRSTCALL()) { */ -/* MemoryContext oldcontext; */ - -/* funcctx = SRF_FIRSTCALL_INIT(); */ -/* oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); */ -/* A = PGGRB_GETARG_MATRIX(0); */ -/* start = PG_GETARG_INT64(1); */ - -/* state = (pgGrB_Matrix_SSSPState*)palloc(sizeof(pgGrB_Matrix_SSSPState)); */ - -/* CHECKD(GrB_Matrix_nrows(&n, A->M)); */ -/* for (GrB_Index i = 0; i < n; i++) { */ -/* CHECKD(GrB_Matrix_setElement_FP64 (A->M, 0, i, i)); */ -/* } */ - -/* CHECKD(LAGraph_BF_full(&pd, &ppi, &ph, A->M, start)); */ - -/* state->pd = pd; */ -/* state->ppi = ppi; */ -/* state->ph = ph; */ - -/* funcctx->max_calls = n; */ -/* funcctx->user_fctx = (void*)state; */ - -/* if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) */ -/* ereport(ERROR, */ -/* (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), */ -/* errmsg("function returning record called in context " */ -/* "that cannot accept type record"))); */ -/* BlessTupleDesc(tupdesc); */ -/* funcctx->tuple_desc = tupdesc; */ - -/* MemoryContextSwitchTo(oldcontext); */ -/* } */ - -/* funcctx = SRF_PERCALL_SETUP(); */ -/* state = (pgGrB_Matrix_SSSPState*)funcctx->user_fctx; */ - -/* cnt = funcctx->call_cntr; */ -/* if (cnt < funcctx->max_calls) { */ - -/* CHECKD(GrB_Vector_extractElement(&distance, state->pd, cnt)); */ -/* CHECKD(GrB_Vector_extractElement(&parent, state->ppi, cnt)); */ -/* CHECKD(GrB_Vector_extractElement(&hops, state->ph, cnt)); */ - -/* values[0] = Int64GetDatum(cnt); */ - -/* values[1] = distance == INFINITY? get_float8_infinity() : Float8GetDatum(distance); */ - -/* values[2] = Int64GetDatum(parent); */ -/* values[3] = Int64GetDatum(hops); */ - -/* tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); */ -/* result = HeapTupleGetDatum(tuple); */ -/* SRF_RETURN_NEXT(funcctx, result); */ -/* } else { */ -/* SRF_RETURN_DONE(funcctx); */ -/* } */ - -/* } */ +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/matrix.h b/src/matrix.h index d538949..6a9394c 100644 --- a/src/matrix.h +++ b/src/matrix.h @@ -2,770 +2,266 @@ /* Set Returning Function (matrix_elements) state for generating tuples from a matrix. - */ -typedef struct FN(pgGrB_Matrix_ExtractState) { - pgGrB_Matrix *mat; - GrB_Index *rows; - GrB_Index *cols; - PG_TYPE *vals; -} FN(pgGrB_Matrix_ExtractState); +*/ +typedef struct FN(OS_Matrix_ExtractState) +{ + OS_Matrix *mat; + GrB_Index *rows; + GrB_Index *cols; + PG_TYPE *vals; +} FN(OS_Matrix_ExtractState); /* Expanded Object Header "methods" for flattening matrices for storage */ static Size FN(matrix_get_flat_size)(ExpandedObjectHeader *eohptr); static void FN(matrix_flatten_into)(ExpandedObjectHeader *eohptr, - void *result, Size allocated_size); + void *result, Size allocated_size); -static const ExpandedObjectMethods FN(matrix_methods) = { - FN(matrix_get_flat_size), - FN(matrix_flatten_into) +static const ExpandedObjectMethods FN(matrix_methods) = +{ + FN(matrix_get_flat_size), + FN(matrix_flatten_into) }; /* Utility function that expands a flattened matrix datum. */ Datum -FN(expand_flat_matrix)(pgGrB_FlatMatrix *flat, - MemoryContext parentcontext); +FN(expand_flat_matrix)(OS_FlatMatrix *flat, + MemoryContext parentcontext); -GrB_Index FN(extract_rowscols)(pgGrB_Matrix *A, - GrB_Index **rows, - GrB_Index **cols, - GrB_Index nvals); - -pgGrB_Matrix * +OS_Matrix * FN(construct_empty_expanded_matrix)(GrB_Index nrows, - GrB_Index ncols, - MemoryContext parentcontext); - -Datum FN(matrix_ewise_mult)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc); - -Datum FN(matrix_ewise_add)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc); - -Datum -FN(mxm)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc); - -Datum -FN(matrix_kron)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp accum, - GrB_BinaryOp mulop, - GrB_Descriptor desc); - -Datum -FN(mxv)(pgGrB_Matrix *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc); - -Datum -FN(vxm)(pgGrB_Vector *A, - pgGrB_Matrix *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc); + GrB_Index ncols, + MemoryContext parentcontext); PG_FUNCTION_INFO_V1(FN(matrix)); PG_FUNCTION_INFO_V1(FN(matrix_empty)); -PG_FUNCTION_INFO_V1(FN(matrix_elements)); -PG_FUNCTION_INFO_V1(FN(matrix_reduce)); -PG_FUNCTION_INFO_V1(FN(matrix_assign)); -PG_FUNCTION_INFO_V1(FN(matrix_random)); -PG_FUNCTION_INFO_V1(FN(matrix_set_element)); /* Compute size of storage needed for matrix */ static Size -FN(matrix_get_flat_size)(ExpandedObjectHeader *eohptr) { - GrB_Info info; - pgGrB_Matrix *A = (pgGrB_Matrix *) eohptr; - Size nbytes; - GrB_Index nrows, ncols, nvals; - - Assert(A->em_magic == matrix_MAGIC); - - if (A->flat_size) - return A->flat_size; - - CHECKD(GrB_Matrix_nrows(&nrows, A->M)); - CHECKD(GrB_Matrix_ncols(&ncols, A->M)); - CHECKD(GrB_Matrix_nvals(&nvals, A->M)); - - nbytes = PGGRB_MATRIX_OVERHEAD(); -#ifdef IMPORT_EXPORT - nbytes += (nrows + 1) * sizeof(GrB_Index); - nbytes += nvals * sizeof(GrB_Index); - nbytes += nvals * sizeof(PG_TYPE); -#else - nbytes += nvals * sizeof(GrB_Index); - nbytes += nvals * sizeof(GrB_Index); - nbytes += nvals * sizeof(PG_TYPE); -#endif - - A->flat_size = nbytes; - return nbytes; +FN(matrix_get_flat_size)(ExpandedObjectHeader *eohptr) +{ + GrB_Info info; + OS_Matrix *A = (OS_Matrix *) eohptr; + + Assert(A->em_magic == matrix_MAGIC); + + if (A->flat_size) + return A->flat_size; + + A->flat_size = OS_MATRIX_OVERHEAD(); + return A->flat_size; } /* Flatten matrix into allocated result buffer */ static void FN(matrix_flatten_into)(ExpandedObjectHeader *eohptr, - void *result, Size allocated_size) { - GrB_Info info; - GrB_Index *rows, nrows, ncols, nvals; - pgGrB_Matrix *A = (pgGrB_Matrix *) eohptr; - pgGrB_FlatMatrix *flat = (pgGrB_FlatMatrix *) result; -#ifdef IMPORT_EXPORT - int64_t nonempty = -1; - GrB_Index *cols; - void *values; - GrB_Type type; -#endif - - Assert(A->em_magic == matrix_MAGIC); - Assert(allocated_size == A->flat_size); - - memset(flat, 0, allocated_size); - -#ifdef IMPORT_EXPORT - CHECKV(GxB_Matrix_export_CSR(&A->M, - &type, - &nrows, - &ncols, - &nvals, - &nonempty, - &rows, - &cols, - &values, - NULL)); - - if (nvals > 0) { - memcpy(PGGRB_MATRIX_DATA(flat), - rows, - (nrows+1)*sizeof(GrB_Index)); - memcpy((PGGRB_MATRIX_DATA(flat) + nrows+1), - cols, - nvals*sizeof(GrB_Index)); - memcpy((PGGRB_MATRIX_DATA(flat) + nrows+1 + nvals), - values, - nvals*sizeof(PG_TYPE)); - pfree(rows); - pfree(cols); - pfree(values); - } - flat->nonempty = nonempty; -#else - CHECKV(GrB_Matrix_nrows(&nrows, A->M)); - CHECKV(GrB_Matrix_ncols(&ncols, A->M)); - CHECKV(GrB_Matrix_nvals(&nvals, A->M)); - - rows = PGGRB_MATRIX_DATA(flat); - CHECKV(GrB_Matrix_extractTuples(rows, - rows + nvals, - rows + nvals + nvals, - &nvals, - A->M)); -#endif - - flat->type = GB_TYPE; - flat->nrows = nrows; - flat->ncols = ncols; - flat->nvals = nvals; - SET_VARSIZE(flat, allocated_size); + void *result, Size allocated_size) +{ + GrB_Info info; + GrB_Index *rows, nrows, ncols, nvals; + OS_Matrix *A = (OS_Matrix *) eohptr; + OS_FlatMatrix *flat = (OS_FlatMatrix *) result; + + Assert(A->em_magic == matrix_MAGIC); + Assert(allocated_size == A->flat_size); + + memset(flat, 0, allocated_size); + + flat->type = GB_TYPE; + flat->nrows = nrows; + flat->ncols = ncols; + flat->nvals = nvals; + SET_VARSIZE(flat, allocated_size); } /* Expand a flat matrix. */ Datum -FN(expand_flat_matrix)(pgGrB_FlatMatrix *flat, - MemoryContext parentcontext) { - GrB_Info info; - - pgGrB_Matrix *A; - - MemoryContext objcxt, oldcxt; - MemoryContextCallback *ctxcb; - - GrB_Index ncols, nrows, nvals; - GrB_Index *rows, *cols; - void *vals; - GrB_Type type; -#ifdef IMPORT_EXPORT - int64_t nonempty; -#endif - - /* Create a new context that will hold the expanded object. */ - objcxt = AllocSetContextCreate(parentcontext, - "expanded matrix", - ALLOCSET_DEFAULT_SIZES); - - /* Allocate a new expanded matrix */ - A = (pgGrB_Matrix*)MemoryContextAlloc(objcxt, - sizeof(pgGrB_Matrix)); - - /* Initialize the ExpandedObjectHeader member with flattening - * methods and new object context */ - EOH_init_header(&A->hdr, &FN(matrix_methods), objcxt); - - /* Used for debugging checks */ - A->em_magic = matrix_MAGIC; - - /* Switch to new object context */ - oldcxt = MemoryContextSwitchTo(objcxt); - - /* Get dimensional information from flat */ - nrows = flat->nrows; - ncols = flat->ncols; - nvals = flat->nvals; - type = flat->type; - - /* If there's actual values, build the matrix */ -#ifdef IMPORT_EXPORT - nonempty = flat->nonempty; - - if (nvals > 0) { - rows = malloc_function((nrows+1)*sizeof(GrB_Index)); - cols = malloc_function(nvals*sizeof(GrB_Index)); - vals = malloc_function(nvals*sizeof(PG_TYPE)); - memcpy(rows, - PGGRB_MATRIX_DATA(flat), - (nrows+1)*sizeof(GrB_Index)); - memcpy(cols, - PGGRB_MATRIX_DATA(flat) + nrows+1, - nvals*sizeof(GrB_Index)); - memcpy(vals, - PGGRB_MATRIX_DATA(flat) + nrows+1 + nvals, - nvals*sizeof(PG_TYPE)); - - CHECKD(GxB_Matrix_import_CSR(&A->M, - type, - nrows, - ncols, - nvals, - nonempty, - &rows, - &cols, - &vals, - NULL - )); - if (A->M == NULL) { - pfree(rows); - pfree(cols); - pfree(vals); - ereport(ERROR, (errmsg("Matrix import failed"))); - } - } else { - CHECKD(GrB_Matrix_new(&A->M, - type, - nrows, - ncols)); - } - -#else - /* Initialize the new matrix */ - CHECKD(GrB_Matrix_new(&A->M, - type, - nrows, - ncols)); - - if (nvals > 0) { - /* Rows, cols, and vals are pointers into the vardata area */ - rows = PGGRB_MATRIX_DATA(flat); - cols = rows + nrows; - vals = (PG_TYPE*)(cols + ncols); - - CHECKD(GrB_Matrix_build(A->M, - rows, - cols, - vals, - nvals, - GB_DUP)); - } -#endif - - A->type = type; - A->flat_size = 0; - - /* Create a context callback to free matrix when context is cleared */ - ctxcb = MemoryContextAlloc(objcxt, - sizeof(MemoryContextCallback)); - - ctxcb->func = context_callback_matrix_free; - ctxcb->arg = A; - MemoryContextRegisterResetCallback(objcxt, ctxcb); - - /* Switch back to old context */ - MemoryContextSwitchTo(oldcxt); - PGGRB_RETURN_MATRIX(A); +FN(expand_flat_matrix)(OS_FlatMatrix *flat, + MemoryContext parentcontext) +{ + GrB_Info info; + + OS_Matrix *A; + + MemoryContext objcxt, oldcxt; + MemoryContextCallback *ctxcb; + + GrB_Index ncols, nrows, nvals; + GrB_Index *rows, *cols; + void *vals; + GrB_Type type; + + /* Create a new context that will hold the expanded object. */ + objcxt = AllocSetContextCreate(parentcontext, + "expanded matrix", + ALLOCSET_DEFAULT_SIZES); + + /* Allocate a new expanded matrix */ + A = (OS_Matrix*)MemoryContextAlloc(objcxt, + sizeof(OS_Matrix)); + + /* Initialize the ExpandedObjectHeader member with flattening + * methods and new object context */ + EOH_init_header(&A->hdr, &FN(matrix_methods), objcxt); + + /* Used for debugging checks */ + A->em_magic = matrix_MAGIC; + + /* Switch to new object context */ + oldcxt = MemoryContextSwitchTo(objcxt); + + /* Get dimensional information from flat */ + nrows = flat->nrows; + ncols = flat->ncols; + nvals = flat->nvals; + type = flat->type; + A->type = type; + A->flat_size = 0; + + /* Create a context callback to free matrix when context is cleared */ + ctxcb = MemoryContextAlloc(objcxt, + sizeof(MemoryContextCallback)); + + ctxcb->func = context_callback_matrix_free; + ctxcb->arg = A; + MemoryContextRegisterResetCallback(objcxt, ctxcb); + + /* Switch back to old context */ + MemoryContextSwitchTo(oldcxt); + OS_RETURN_MATRIX(A); } /* Construct an empty expanded matrix. */ -pgGrB_Matrix * +OS_Matrix * FN(construct_empty_expanded_matrix)(GrB_Index nrows, - GrB_Index ncols, - MemoryContext parentcontext) { - pgGrB_FlatMatrix *flat; - Datum d; - flat = construct_empty_flat_matrix(nrows, ncols, GB_TYPE); - d = FN(expand_flat_matrix)(flat, parentcontext); - pfree(flat); - return (pgGrB_Matrix *) DatumGetEOHP(d); -} - -Datum -FN(matrix_empty)(PG_FUNCTION_ARGS) { - pgGrB_Matrix *retval; - GrB_Index nrows, ncols; - - nrows = PG_GETARG_INT64(0); - ncols = PG_GETARG_INT64(1); - - retval = FN(construct_empty_expanded_matrix)(nrows, - ncols, - CurrentMemoryContext); - PGGRB_RETURN_MATRIX(retval); -} - -Datum -FN(matrix_elements)(PG_FUNCTION_ARGS) { - GrB_Info info; - FuncCallContext *funcctx; - TupleDesc tupdesc; - Datum result; - - Datum values[3]; - bool nulls[3] = {false, false, false}; - HeapTuple tuple; - GrB_Index nvals = 0; - pgGrB_Matrix *mat; - FN(pgGrB_Matrix_ExtractState) *state; - - if (SRF_IS_FIRSTCALL()) { - MemoryContext oldcontext; - - funcctx = SRF_FIRSTCALL_INIT(); - oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - mat = PGGRB_GETARG_MATRIX(0); - - state = (FN(pgGrB_Matrix_ExtractState)*)palloc(sizeof(FN(pgGrB_Matrix_ExtractState))); - CHECKD(GrB_Matrix_nvals(&nvals, mat->M)); - - state->rows = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); - state->cols = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); - state->vals = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * nvals); - - CHECKD(GrB_Matrix_extractTuples(state->rows, - state->cols, - state->vals, - &nvals, - mat->M)); - state->mat = mat; - funcctx->max_calls = nvals; - funcctx->user_fctx = (void*)state; - - /* One-time setup code appears here: */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context " - "that cannot accept type record"))); - BlessTupleDesc(tupdesc); - funcctx->tuple_desc = tupdesc; - - MemoryContextSwitchTo(oldcontext); - } - - funcctx = SRF_PERCALL_SETUP(); - state = (FN(pgGrB_Matrix_ExtractState)*)funcctx->user_fctx; - mat = state->mat; - - if (funcctx->call_cntr < funcctx->max_calls) { - values[0] = Int64GetDatum(state->rows[funcctx->call_cntr]); - values[1] = Int64GetDatum(state->cols[funcctx->call_cntr]); - values[2] = PG_TGD(state->vals[funcctx->call_cntr]); - - tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); - SRF_RETURN_NEXT(funcctx, result); - } else { - SRF_RETURN_DONE(funcctx); - } -} - -Datum -FN(matrix_ewise_mult)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc - ) { - GrB_Info info; - GrB_Index m, n; - - if (C == NULL) { - CHECKD(GrB_Matrix_nrows(&m, A->M)); - CHECKD(GrB_Matrix_ncols(&n, A->M)); - C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); - } - CHECKD(GrB_eWiseMult(C->M, mask ? mask->M : NULL, accum, binop, A->M, B->M, desc)); - PGGRB_RETURN_MATRIX(C); -} - -Datum -FN(matrix_ewise_add)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc - ) { - GrB_Info info; - GrB_Index m, n; - - if (C == NULL) { - CHECKD(GrB_Matrix_nrows(&m, A->M)); - CHECKD(GrB_Matrix_ncols(&n, A->M)); - C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); - } - - CHECKD(GrB_eWiseAdd(C->M, mask ? mask->M : NULL, accum, binop, A->M, B->M, desc)); - PGGRB_RETURN_MATRIX(C); -} - -Datum -FN(mxm)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc) { - GrB_Info info; - - if (C == NULL) { - GrB_Index m, n; - CHECKD(GrB_Matrix_nrows(&m, A->M)); - CHECKD(GrB_Matrix_ncols(&n, B->M)); - C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); - } - CHECKD(GrB_mxm(C->M, mask ? mask->M : NULL, binop, semiring, A->M, B->M, desc)); - PGGRB_RETURN_MATRIX(C); + GrB_Index ncols, + MemoryContext parentcontext) +{ + OS_FlatMatrix *flat; + Datum d; + flat = construct_empty_flat_matrix(nrows, ncols, GB_TYPE); + d = FN(expand_flat_matrix)(flat, parentcontext); + pfree(flat); + return (OS_Matrix *) DatumGetEOHP(d); } Datum -FN(mxv)(pgGrB_Matrix *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc) { - GrB_Info info; - GrB_Index size; - - if (C == NULL) { - CHECKD(GrB_Matrix_ncols(&size, A->M)); - C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); - } - CHECKD(GrB_mxv(C->V, mask ? mask->V : NULL, binop, semiring, A->M, B->V, desc)); - PGGRB_RETURN_VECTOR(C); +FN(matrix_empty)(PG_FUNCTION_ARGS) +{ + OS_Matrix *retval; + GrB_Index nrows, ncols; + + nrows = PG_GETARG_INT64(0); + ncols = PG_GETARG_INT64(1); + + retval = FN(construct_empty_expanded_matrix)(nrows, + ncols, + CurrentMemoryContext); + OS_RETURN_MATRIX(retval); } -Datum -FN(vxm)(pgGrB_Vector *A, - pgGrB_Matrix *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_Semiring semiring, - GrB_BinaryOp binop, - GrB_Descriptor desc) { - GrB_Info info; - GrB_Index size; - - if (C == NULL) { - CHECKD(GrB_Vector_size(&size, A->V)); - C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); - } - CHECKD(GrB_vxm(C->V, mask ? mask->V : NULL, binop, semiring, A->V, B->M, desc)); - PGGRB_RETURN_VECTOR(C); -} Datum -FN(matrix)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *retval; - ArrayType *rows, *cols, *vals; - int *idims, *jdims, *vdims; - int i, count; - - GrB_Index *row_indices, *col_indices; - GrB_Index max_row_index, max_col_index; - PG_TYPE *values; - ArrayIterator array_iterator; - Datum value; - bool isnull; - - if (PG_NARGS() == 2) { - max_row_index = PG_GETARG_INT64(0); - max_col_index = PG_GETARG_INT64(1); - retval = FN(construct_empty_expanded_matrix)(max_row_index, - max_col_index, - CurrentMemoryContext); - PGGRB_RETURN_MATRIX(retval); - } - - rows = PG_GETARG_ARRAYTYPE_P(0); - cols = PG_GETARG_ARRAYTYPE_P(1); - vals = PG_GETARG_ARRAYTYPE_P(2); - - if (ARR_HASNULL(rows) || ARR_HASNULL(cols) || ARR_HASNULL(vals)) - ereport(ERROR, (errmsg("Matrix values may not be null"))); - - idims = ARR_DIMS(rows); - jdims = ARR_DIMS(cols); - vdims = ARR_DIMS(vals); - - if (!PG_ARGISNULL(3)) - max_row_index = PG_GETARG_INT64(3); - else - max_row_index = idims[0]; - - if (!PG_ARGISNULL(4)) - max_col_index = PG_GETARG_INT64(4); - else - max_col_index = jdims[0]; - - count = vdims[0]; - - if ((idims[0] != jdims[0]) || (jdims[0] != vdims[0])) - ereport(ERROR, (errmsg("Row, column, and value arrays must be same size."))); - - row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * max_row_index); - col_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * max_col_index); - values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * count); - - i = 0; - array_iterator = array_create_iterator(rows, 0, NULL); - while (array_iterate(array_iterator, &value, &isnull)) +FN(matrix)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *retval; + ArrayType *rows, *cols, *vals; + int *idims, *jdims, *vdims; + int i, count; + + GrB_Index *row_indices, *col_indices; + GrB_Index max_row_index, max_col_index; + PG_TYPE *values; + ArrayIterator array_iterator; + Datum value; + bool isnull; + + if (PG_NARGS() == 2) { + max_row_index = PG_GETARG_INT64(0); + max_col_index = PG_GETARG_INT64(1); + retval = FN(construct_empty_expanded_matrix)(max_row_index, + max_col_index, + CurrentMemoryContext); + OS_RETURN_MATRIX(retval); + } + + rows = PG_GETARG_ARRAYTYPE_P(0); + cols = PG_GETARG_ARRAYTYPE_P(1); + vals = PG_GETARG_ARRAYTYPE_P(2); + + if (ARR_HASNULL(rows) || ARR_HASNULL(cols) || ARR_HASNULL(vals)) + ereport(ERROR, (errmsg("Matrix values may not be null"))); + + idims = ARR_DIMS(rows); + jdims = ARR_DIMS(cols); + vdims = ARR_DIMS(vals); + + if (!PG_ARGISNULL(3)) + max_row_index = PG_GETARG_INT64(3); + else + max_row_index = idims[0]; + + if (!PG_ARGISNULL(4)) + max_col_index = PG_GETARG_INT64(4); + else + max_col_index = jdims[0]; + + count = vdims[0]; + + if ((idims[0] != jdims[0]) || (jdims[0] != vdims[0])) + ereport(ERROR, (errmsg("Row, column, and value arrays must be same size."))); + + row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * max_row_index); + col_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * max_col_index); + values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * count); + + i = 0; + array_iterator = array_create_iterator(rows, 0, NULL); + while (array_iterate(array_iterator, &value, &isnull)) { - row_indices[i] = DatumGetInt64(value); - if (row_indices[i] > max_row_index) - max_row_index = row_indices[i] + 1; - i++; - } - array_free_iterator(array_iterator); - - i = 0; - array_iterator = array_create_iterator(cols, 0, NULL); - while (array_iterate(array_iterator, &value, &isnull)) + row_indices[i] = DatumGetInt64(value); + if (row_indices[i] > max_row_index) + max_row_index = row_indices[i] + 1; + i++; + } + array_free_iterator(array_iterator); + + i = 0; + array_iterator = array_create_iterator(cols, 0, NULL); + while (array_iterate(array_iterator, &value, &isnull)) { - col_indices[i] = DatumGetInt64(value); - if (col_indices[i] > max_col_index) - max_col_index = col_indices[i] + 1; - i++; - } - array_free_iterator(array_iterator); - - i = 0; - array_iterator = array_create_iterator(vals, 0, NULL); - while (array_iterate(array_iterator, &value, &isnull)) + col_indices[i] = DatumGetInt64(value); + if (col_indices[i] > max_col_index) + max_col_index = col_indices[i] + 1; + i++; + } + array_free_iterator(array_iterator); + + i = 0; + array_iterator = array_create_iterator(vals, 0, NULL); + while (array_iterate(array_iterator, &value, &isnull)) { - values[i] = PG_DGT(value); - i++; - } - array_free_iterator(array_iterator); - - retval = FN(construct_empty_expanded_matrix)(max_row_index, - max_col_index, - CurrentMemoryContext); - - CHECKD(GrB_Matrix_build(retval->M, - row_indices, - col_indices, - values, - count, - GB_DUP)); - - PGGRB_RETURN_MATRIX(retval); -} - -Datum -FN(matrix_reduce)(PG_FUNCTION_ARGS) { - GrB_Info info; - GrB_Type type; - pgGrB_Matrix *A; - GrB_Semiring semiring; - GrB_Monoid monoid; - char *semiring_name; - PG_TYPE val; - - A = PGGRB_GETARG_MATRIX(0); - semiring_name = PG_ARGISNULL(1)? - NULL: - text_to_cstring(PG_GETARG_TEXT_PP(1)); - - if (semiring_name == NULL) { - CHECKD(GxB_Matrix_type(&type, A->M)); - semiring_name = DEFAULT_SEMIRING(type); - } - semiring = lookup_semiring(semiring_name); - CHECKD(GxB_Semiring_add(&monoid, semiring)); - CHECKD(GrB_reduce(&val, NULL, monoid, A->M, NULL)); - PG_RET(val); -} - -GrB_Index FN(extract_rowscols)(pgGrB_Matrix *A, - GrB_Index **rows, - GrB_Index **cols, - GrB_Index nvals) { - PG_TYPE *values; - GrB_Info info; - - *rows = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); - *cols = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); - values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * nvals); - - CHECKD(GrB_Matrix_extractTuples(*rows, - *cols, - values, - &nvals, - A->M)); - return nvals; + values[i] = PG_DGT(value); + i++; + } + array_free_iterator(array_iterator); + + retval = FN(construct_empty_expanded_matrix)(max_row_index, + max_col_index, + CurrentMemoryContext); + + CHECKD(GrB_Matrix_build(retval->M, + row_indices, + col_indices, + values, + count, + GB_DUP), retval->M); + + OS_RETURN_MATRIX(retval); } -Datum -FN(matrix_assign)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A, *B=NULL, *mask=NULL; - GrB_Index nrows, ncols, nvals; - GrB_Index *rows = NULL, *cols = NULL; - PG_TYPE val; - - A = PGGRB_GETARG_MATRIX(0); - val = PG_GET(1); - B = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_MATRIX(2); - mask = PG_ARGISNULL(3)? NULL : PGGRB_GETARG_MATRIX(3); - - if (B != NULL) { - CHECKD(GrB_Matrix_nvals(&nvals, B->M)); - nrows = ncols = nvals = FN(extract_rowscols)(B, &rows, &cols, nvals); - } else { - CHECKD(GrB_Matrix_nrows(&nrows, A->M)); - CHECKD(GrB_Matrix_ncols(&ncols, A->M)); - } - - CHECKD(GrB_assign(A->M, - mask? mask->M: NULL, - NULL, - val, - rows?rows:GrB_ALL, - nrows, - cols?cols:GrB_ALL, - ncols, - NULL)); - - PGGRB_RETURN_MATRIX(A); -} - -Datum -FN(matrix_kron)(pgGrB_Matrix *A, - pgGrB_Matrix *B, - pgGrB_Matrix *C, - pgGrB_Matrix *mask, - GrB_BinaryOp accum, - GrB_BinaryOp mulop, - GrB_Descriptor desc) { - GrB_Info info; - - if (C == NULL) { - GrB_Index m, n, p, q; - CHECKD(GrB_Matrix_nrows(&m, A->M)); - CHECKD(GrB_Matrix_ncols(&n, A->M)); - CHECKD(GrB_Matrix_nrows(&p, B->M)); - CHECKD(GrB_Matrix_ncols(&q, B->M)); - C = FN(construct_empty_expanded_matrix)(m*p, n*q, CurrentMemoryContext); - } - CHECKD(GxB_kron(C->M, mask ? mask->M : NULL, accum, mulop, A->M, B->M, desc)); - PGGRB_RETURN_MATRIX(C); -} - -Datum -FN(matrix_random)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A; - GrB_Matrix M; - GrB_Index nrows, ncols, nvals; - bool make_pattern, make_symmetric, make_skew_symmetric, make_hermitian, no_diagonal; - uint64_t seed; - - nrows = PG_GETARG_INT64(0); - ncols = PG_GETARG_INT64(1); - nvals = PG_GETARG_INT64(2); - make_pattern = PG_GETARG_BOOL(3); - make_symmetric = PG_GETARG_BOOL(4); - make_skew_symmetric = PG_GETARG_BOOL(5); - make_hermitian = PG_GETARG_BOOL(6); - no_diagonal = PG_GETARG_BOOL(7); - - A = FN(construct_empty_expanded_matrix)(nrows, - ncols, - CurrentMemoryContext); - - CHECKD(LAGraph_random(&M, - GB_TYPE, - nrows, - ncols, - nvals, - make_pattern, - make_symmetric, - make_skew_symmetric, - make_hermitian, - no_diagonal, - &seed)); - - CHECKD(GrB_free(&A->M)); - A->M = M; - PGGRB_RETURN_MATRIX(A); -} - -Datum -FN(matrix_set_element)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Matrix *A; - GrB_Index row, col; - PG_TYPE val; - - A = PGGRB_GETARG_MATRIX(0); - row = PG_GETARG_INT64(1); - col = PG_GETARG_INT64(2); - val = PG_GET(3); - - CHECKD(GrB_Matrix_setElement(A->M, val, row, col)); - PGGRB_RETURN_MATRIX(A); -} +#include "matrix_ops.h" #undef SUFFIX #undef PG_TYPE @@ -778,3 +274,8 @@ FN(matrix_set_element)(PG_FUNCTION_ARGS) { #undef PG_DGT #undef PG_TGD #undef PRINT_FMT + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/matrix_ops.h b/src/matrix_ops.h new file mode 100644 index 0000000..1be1af4 --- /dev/null +++ b/src/matrix_ops.h @@ -0,0 +1,376 @@ +GrB_Index FN(extract_rowscols)(OS_Matrix *A, + GrB_Index **rows, + GrB_Index **cols, + GrB_Index nvals); + +Datum FN(matrix_ewise_mult)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc); + +Datum FN(matrix_ewise_add)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc); + +Datum +FN(mxm)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc); + +Datum +FN(matrix_kron)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp accum, + GrB_BinaryOp mulop, + GrB_Descriptor desc); + +Datum +FN(mxv)(OS_Matrix *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc); + +Datum +FN(vxm)(OS_Vector *A, + OS_Matrix *B, + OS_Vector *C, + OS_Vector *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc); + + +PG_FUNCTION_INFO_V1(FN(matrix_elements)); +PG_FUNCTION_INFO_V1(FN(matrix_reduce)); +PG_FUNCTION_INFO_V1(FN(matrix_assign)); +PG_FUNCTION_INFO_V1(FN(matrix_random)); +PG_FUNCTION_INFO_V1(FN(matrix_set_element)); + +Datum +FN(matrix_elements)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + FuncCallContext *funcctx; + TupleDesc tupdesc; + Datum result; + + Datum values[3]; + bool nulls[3] = {false, false, false}; + HeapTuple tuple; + GrB_Index nvals = 0; + OS_Matrix *mat; + FN(OS_Matrix_ExtractState) *state; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcontext; + + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + mat = OS_GETARG_MATRIX(0); + + state = (FN(OS_Matrix_ExtractState)*)palloc(sizeof(FN(OS_Matrix_ExtractState))); + CHECKD(GrB_Matrix_nvals(&nvals, mat->M), mat->M); + + state->rows = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); + state->cols = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); + state->vals = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * nvals); + + CHECKD(GrB_Matrix_extractTuples(state->rows, + state->cols, + state->vals, + &nvals, + mat->M), mat->M); + state->mat = mat; + funcctx->max_calls = nvals; + funcctx->user_fctx = (void*)state; + + /* One-time setup code appears here: */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + BlessTupleDesc(tupdesc); + funcctx->tuple_desc = tupdesc; + + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + state = (FN(OS_Matrix_ExtractState)*)funcctx->user_fctx; + mat = state->mat; + + if (funcctx->call_cntr < funcctx->max_calls) + { + values[0] = Int64GetDatum(state->rows[funcctx->call_cntr]); + values[1] = Int64GetDatum(state->cols[funcctx->call_cntr]); + values[2] = PG_TGD(state->vals[funcctx->call_cntr]); + + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } + else + { + SRF_RETURN_DONE(funcctx); + } +} + +Datum +FN(matrix_ewise_mult)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc + ) +{ + GrB_Info info; + GrB_Index m, n; + + if (C == NULL) + { + CHECKD(GrB_Matrix_nrows(&m, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&n, A->M), A->M); + C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); + } + CHECKD(GrB_eWiseMult(C->M, mask ? mask->M : NULL, accum, binop, A->M, B->M, desc), A->M); + OS_RETURN_MATRIX(C); +} + +Datum +FN(matrix_ewise_add)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc + ) +{ + GrB_Info info; + GrB_Index m, n; + + if (C == NULL) + { + CHECKD(GrB_Matrix_nrows(&m, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&n, A->M), A->M); + C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); + } + + CHECKD(GrB_eWiseAdd(C->M, mask ? mask->M : NULL, accum, binop, A->M, B->M, desc), A->M); + OS_RETURN_MATRIX(C); +} + +Datum +FN(mxm)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc) +{ + GrB_Info info; + + if (C == NULL) + { + GrB_Index m, n; + CHECKD(GrB_Matrix_nrows(&m, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&n, B->M), A->M); + C = FN(construct_empty_expanded_matrix)(m, n, CurrentMemoryContext); + } + CHECKD(GrB_mxm(C->M, mask ? mask->M : NULL, binop, semiring, A->M, B->M, desc), A->M); + OS_RETURN_MATRIX(C); +} + +Datum +FN(mxv)(OS_Matrix *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc) +{ + GrB_Info info; + GrB_Index size; + + if (C == NULL) + { + CHECKD(GrB_Matrix_ncols(&size, A->M), A->M); + C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); + } + CHECKD(GrB_mxv(C->V, mask ? mask->V : NULL, binop, semiring, A->M, B->V, desc), A->M); + OS_RETURN_VECTOR(C); +} + +Datum +FN(vxm)(OS_Vector *A, + OS_Matrix *B, + OS_Vector *C, + OS_Vector *mask, + GrB_Semiring semiring, + GrB_BinaryOp binop, + GrB_Descriptor desc) +{ + GrB_Info info; + GrB_Index size; + + if (C == NULL) + { + CHECKD(GrB_Vector_size(&size, A->V), A->V); + C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); + } + CHECKD(GrB_vxm(C->V, mask ? mask->V : NULL, binop, semiring, A->V, B->M, desc), A->V); + OS_RETURN_VECTOR(C); +} + +Datum +FN(matrix_reduce)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + GrB_Type type; + OS_Matrix *A; + GrB_Semiring semiring; + GrB_Monoid monoid; + char *semiring_name; + PG_TYPE val; + + A = OS_GETARG_MATRIX(0); + semiring_name = PG_ARGISNULL(1)? + NULL: + text_to_cstring(PG_GETARG_TEXT_PP(1)); + + if (semiring_name == NULL) + { + CHECKD(GxB_Matrix_type(&type, A->M), A->M); + semiring_name = DEFAULT_SEMIRING(type); + } + semiring = lookup_semiring(semiring_name); + CHECKD(GxB_Semiring_add(&monoid, semiring), A->M); + CHECKD(GrB_reduce(&val, NULL, monoid, A->M, NULL), A->M); + PG_RET(val); +} + +GrB_Index FN(extract_rowscols)(OS_Matrix *A, + GrB_Index **rows, + GrB_Index **cols, + GrB_Index nvals) +{ + PG_TYPE *values; + GrB_Info info; + + *rows = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); + *cols = (GrB_Index*) palloc0(sizeof(GrB_Index) * nvals); + values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * nvals); + + CHECKD(GrB_Matrix_extractTuples(*rows, + *cols, + values, + &nvals, + A->M), A->M); + return nvals; +} + +Datum +FN(matrix_assign)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A, *B=NULL, *mask=NULL; + GrB_Index nrows, ncols, nvals; + GrB_Index *rows = NULL, *cols = NULL; + PG_TYPE val; + + A = OS_GETARG_MATRIX(0); + val = PG_GET(1); + B = PG_ARGISNULL(2) ? NULL : OS_GETARG_MATRIX(2); + mask = PG_ARGISNULL(3)? NULL : OS_GETARG_MATRIX(3); + + if (B != NULL) + { + CHECKD(GrB_Matrix_nvals(&nvals, B->M), A->M); + nrows = ncols = nvals = FN(extract_rowscols)(B, &rows, &cols, nvals); + } + else + { + CHECKD(GrB_Matrix_nrows(&nrows, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&ncols, A->M), A->M); + } + + CHECKD(GrB_assign(A->M, + mask? mask->M: NULL, + NULL, + val, + rows?rows:GrB_ALL, + nrows, + cols?cols:GrB_ALL, + ncols, + NULL), A->M); + + OS_RETURN_MATRIX(A); +} + +Datum +FN(matrix_kron)(OS_Matrix *A, + OS_Matrix *B, + OS_Matrix *C, + OS_Matrix *mask, + GrB_BinaryOp accum, + GrB_BinaryOp mulop, + GrB_Descriptor desc) +{ + GrB_Info info; + + if (C == NULL) + { + GrB_Index m, n, p, q; + CHECKD(GrB_Matrix_nrows(&m, A->M), A->M); + CHECKD(GrB_Matrix_ncols(&n, A->M), A->M); + CHECKD(GrB_Matrix_nrows(&p, B->M), B->M); + CHECKD(GrB_Matrix_ncols(&q, B->M), B->M); + C = FN(construct_empty_expanded_matrix)(m*p, n*q, CurrentMemoryContext); + } + CHECKD(GxB_kron(C->M, mask ? mask->M : NULL, accum, mulop, A->M, B->M, desc), A->M); + OS_RETURN_MATRIX(C); +} + +Datum +FN(matrix_set_element)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Matrix *A; + GrB_Index row, col; + PG_TYPE val; + + A = OS_GETARG_MATRIX(0); + row = PG_GETARG_INT64(1); + col = PG_GETARG_INT64(2); + val = PG_GET(3); + + CHECKD(GrB_Matrix_setElement(A->M, val, row, col), A->M); + OS_RETURN_MATRIX(A); +} + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/onesparse.c b/src/onesparse.c new file mode 100644 index 0000000..c4a104c --- /dev/null +++ b/src/onesparse.c @@ -0,0 +1,137 @@ +#include "onesparse.h" +PG_MODULE_MAGIC; + +OS_Semiring semirings[960]; +OS_BinaryOp binops[256]; +OS_UnaryOp uops[67]; +MemoryContext gb_context; + +#include "type.c" +#include "vector.c" +#include "matrix.c" + +void *calloc_function(size_t num, size_t size) +{ + MemoryContext oldcxt; + void *p; + size_t total; + total = num * size; + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + p = palloc_extended(total, MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); + MemoryContextSwitchTo(oldcxt); + return p; +} + +void *malloc_function(size_t size) +{ + MemoryContext oldcxt; + void *p; + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + + p = palloc_extended(size, MCXT_ALLOC_HUGE); + MemoryContextSwitchTo(oldcxt); + return p; +} + +void *realloc_function(void *p, size_t size) +{ + MemoryContext oldcxt; + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + p = repalloc_huge(p, size); + MemoryContextSwitchTo(oldcxt); + return p; +} + +void free_function(void *p) +{ + // MemoryContext oldcxt; + // oldcxt = MemoryContextSwitchTo(TopMemoryContext); + pfree(p); + // MemoryContextSwitchTo(oldcxt); +} + +void +_PG_init(void) +{ + GrB_Info info; + + info = GxB_init (GrB_NONBLOCKING, + malloc_function, + calloc_function, + realloc_function, + free_function); + + if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) { + elog(ERROR, "%s", "cannot initialize SuiteSparse"); + return; + } + + SEMIRING_GROUP(0, FIRST_); + SEMIRING_GROUP(40, SECOND_); + SEMIRING_GROUP(80, MIN_); + SEMIRING_GROUP(120, MAX_); + SEMIRING_GROUP(160, PLUS_); + SEMIRING_GROUP(200, MINUS_); + SEMIRING_GROUP(240, TIMES_); + SEMIRING_GROUP(280, DIV_); + SEMIRING_GROUP(320, ISEQ_); + SEMIRING_GROUP(360, ISNE_); + SEMIRING_GROUP(400, ISGT_); + SEMIRING_GROUP(440, ISLT_); + SEMIRING_GROUP(480, ISGE_); + SEMIRING_GROUP(520, ISLE_); + SEMIRING_GROUP(560, LOR_); + SEMIRING_GROUP(600, LAND_); + SEMIRING_GROUP(640, LXOR_); + SEMIRING_BOOL_GROUP(680, EQ_); + SEMIRING_BOOL_GROUP(720, NE_); + SEMIRING_BOOL_GROUP(760, GT_); + SEMIRING_BOOL_GROUP(800, LT_); + SEMIRING_BOOL_GROUP(840, GE_); + SEMIRING_BOOL_GROUP(880, LE_); + SEMIRING_PURE_BOOL_GROUP(920); + + BINOP_TYPES(0, GrB_, FIRST_); + BINOP_TYPES(11, GrB_, SECOND_); + BINOP_TYPES(22, GrB_, MIN_); + BINOP_TYPES(33, GrB_, MAX_); + BINOP_TYPES(44, GrB_, PLUS_); + BINOP_TYPES(55, GrB_, MINUS_); + BINOP_TYPES(66, GrB_, TIMES_); + BINOP_TYPES(77, GrB_, DIV_); + + BINOP_TYPES(88, GxB_, ISEQ_); + BINOP_TYPES(99, GxB_, ISNE_); + BINOP_TYPES(110, GxB_, ISGT_); + BINOP_TYPES(121, GxB_, ISLT_); + BINOP_TYPES(132, GxB_, ISGE_); + BINOP_TYPES(143, GxB_, ISLE_); + + BINOP_TYPES(154, GrB_, EQ_); + BINOP_TYPES(165, GrB_, NE_); + BINOP_TYPES(176, GrB_, GT_); + BINOP_TYPES(187, GrB_, LT_); + BINOP_TYPES(198, GrB_, GE_); + BINOP_TYPES(209, GrB_, LE_); + + BINOP_TYPES(220, GxB_, LOR_); + BINOP_TYPES(231, GxB_, LAND_); + BINOP_TYPES(242, GxB_, LXOR_); + + BINOP(254, GrB_, LOR,); + BINOP(255, GrB_, LAND,); + BINOP(256, GrB_, LXOR,); + + UOP_TYPES(0, GrB_, IDENTITY_); + UOP_TYPES(11, GrB_, AINV_); + UOP_TYPES(22, GrB_, MINV_); + UOP_TYPES(33, GxB_, LNOT_); + UOP_TYPES(44, GxB_, ONE_); + UOP_TYPES(55, GxB_, ABS_); + UOP(67, GrB_, LNOT,); +} + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/onesparse.h b/src/onesparse.h new file mode 100644 index 0000000..28ac2c7 --- /dev/null +++ b/src/onesparse.h @@ -0,0 +1,480 @@ +#ifndef PGGRAPHBLAS_H +#define PGGRAPHBLAS_H + +#include "suitesparse/GraphBLAS.h" +#include "postgres.h" +#include "utils/builtins.h" +#include "libpq/pqformat.h" +#include "funcapi.h" +#include "access/htup_details.h" +#include "utils/array.h" +#include "utils/arrayaccess.h" +#include "catalog/pg_type_d.h" +#include "catalog/pg_type.h" +#include "utils/lsyscache.h" +#include "nodes/pg_list.h" +#include "utils/varlena.h" +#include "libpq/libpq-fs.h" + +#define CCAT2(x, y) x ## y +#define CCAT(x, y) CCAT2(x, y) +#define FN(x) CCAT(x, SUFFIX) + +#define TYPE_APPLY(D, T, F, ...) do { \ + if ((T) == GrB_INT64) \ + D = F ## _int64(__VA_ARGS__); \ + else if ((T) == GrB_INT32) \ + D = F ## _int32(__VA_ARGS__); \ + else if ((T) == GrB_INT16) \ + D = F ## _int16(__VA_ARGS__); \ + else if ((T) == GrB_INT8) \ + D = F ## _int8(__VA_ARGS__); \ + else if ((T) == GrB_BOOL) \ + D = F ## _bool(__VA_ARGS__); \ + else if ((T) == GrB_FP64) \ + D = F ## _float8(__VA_ARGS__); \ + else if((T) == GrB_FP32) \ + D = F ## _float4(__VA_ARGS__); \ + else \ + elog(ERROR, "unsupported type"); \ + } while(0) + +#define DEFAULT_SEMIRING(T) \ + (T) == GrB_INT64? \ + "PLUS_TIMES_INT64" : \ + (T) == GrB_INT32? \ + "PLUS_TIMES_INT32" : \ + (T) == GrB_INT16? \ + "PLUS_TIMES_INT16" : \ + (T) == GrB_INT8? \ + "PLUS_TIMES_INT8" : \ + (T) == GrB_BOOL? \ + "LOR_LAND_BOOL" : \ + (T) == GrB_FP64? \ + "PLUS_TIMES_FP64" : \ + (T) == GrB_FP32? \ + "PLUS_TIMES_FP32" : \ + "unknown" + +#define DEFAULT_TIMES_BINOP(T) \ + (T) == GrB_INT64? \ + "TIMES_INT64" : \ + (T) == GrB_INT32? \ + "TIMES_INT32" : \ + (T) == GrB_INT16? \ + "TIMES_INT16" : \ + (T) == GrB_INT8? \ + "TIMES_INT8" : \ + (T) == GrB_BOOL? \ + "TIMES_BOOL" : \ + (T) == GrB_FP64? \ + "TIMES_FP64" : \ + (T) == GrB_FP32? \ + "TIMES_FP32" : \ + "unknown" + +#define DEFAULT_PLUS_BINOP(T) \ + (T) == GrB_INT64? \ + "PLUS_INT64" : \ + (T) == GrB_INT32? \ + "PLUS_INT32" : \ + (T) == GrB_INT16? \ + "PLUS_INT16" : \ + (T) == GrB_INT8? \ + "PLUS_INT8" : \ + (T) == GrB_BOOL? \ + "PLUS_BOOL" : \ + (T) == GrB_FP64? \ + "PLUS_FP64" : \ + (T) == GrB_FP32? \ + "PLUS_FP32" : \ + "unknown" + +/* dumb debug helper */ +#define elogn(s) elog(NOTICE, "%s", (s)) +#define elogn1(s, v) elog(NOTICE, "%s: %lu", (s), (v)) + +/* GraphBLAS API checking macros */ + +#define CHECKD(method, obj) \ + { \ + info = method ; \ + if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) \ + { \ + const char *emsg; \ + GrB_error(&emsg, obj); \ + elog(ERROR, "%s", emsg); \ + return (Datum) 0; \ + } \ + } \ + +#define CHECKV(method, obj) \ + { \ + info = method ; \ + if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) \ + { \ + const char *emsg; \ + GrB_error(&emsg, obj); \ + elog(ERROR, "%s", emsg); \ + return; \ + } \ + } \ + +GrB_Info isequal_type +( + bool *result, + GrB_Matrix A, + GrB_Matrix B, + GrB_BinaryOp op + ); + +GrB_Info isequal +( + bool *result, + GrB_Matrix A, + GrB_Matrix B, + GrB_BinaryOp userop + ); + +GrB_Info visequal_type +( + bool *result, + GrB_Vector A, + GrB_Vector B, + GrB_BinaryOp op + ); + +GrB_Info visequal +( + bool *result, + GrB_Vector A, + GrB_Vector B, + GrB_BinaryOp userop + ); +/* Flattened representation of matrix, used to store to disk. + + */ +typedef struct OS_FlatMatrix +{ + int32 vl_len_; + GrB_Index nrows; + GrB_Index ncols; + GrB_Index nvals; + GrB_Type type; + Oid lobjId; +} OS_FlatMatrix; + +/* ID for debugging crosschecks */ +#define matrix_MAGIC 689276813 + +/* Expanded representation of matrix. + + When loaded from storage, the flattened representation is used to + build the matrix with GrB_Matrix_build. +*/ +typedef struct OS_Matrix +{ + ExpandedObjectHeader hdr; + int em_magic; + GrB_Type type; + GrB_Matrix M; + Oid lobjId; + Size flat_size; +} OS_Matrix; + +/* helper to turn types into names. */ +char* grb_type_to_name(GrB_Type t); +GrB_Type grb_name_to_type(char* n); + +/* Callback function for freeing matrices. */ +static void +context_callback_matrix_free(void*); + +/* Helper function that either detoasts or expands matrices. */ +OS_Matrix* DatumGetMatrix(Datum d); + +/* Helper function to create an empty flattened matrix. */ +OS_FlatMatrix * +construct_empty_flat_matrix(GrB_Index nrows, + GrB_Index ncols, + GrB_Type type); + +/* Helper to detoast and expand matrix arguments */ +#define OS_GETARG_MATRIX(n) DatumGetMatrix(PG_GETARG_DATUM(n)) + +/* Helper to return Expanded Object Header Pointer from matrix. */ +#define OS_RETURN_MATRIX(A) return EOHPGetRWDatum(&(A)->hdr) + +/* Helper to compute flat matrix header size */ +#define OS_MATRIX_OVERHEAD() MAXALIGN(sizeof(OS_FlatMatrix)) + +/* Public API functions */ + +PG_FUNCTION_INFO_V1(matrix); +PG_FUNCTION_INFO_V1(matrix_in); +PG_FUNCTION_INFO_V1(matrix_out); + +PG_FUNCTION_INFO_V1(matrix_ncols); +PG_FUNCTION_INFO_V1(matrix_nrows); +PG_FUNCTION_INFO_V1(matrix_nvals); + +PG_FUNCTION_INFO_V1(mxm); +PG_FUNCTION_INFO_V1(mxv); +PG_FUNCTION_INFO_V1(vxm); +PG_FUNCTION_INFO_V1(matrix_kron); +PG_FUNCTION_INFO_V1(matrix_xtract); +PG_FUNCTION_INFO_V1(matrix_print); +PG_FUNCTION_INFO_V1(matrix_mmwrite); +PG_FUNCTION_INFO_V1(matrix_mmread); + +PG_FUNCTION_INFO_V1(matrix_eq); +PG_FUNCTION_INFO_V1(matrix_ne); + +PG_FUNCTION_INFO_V1(matrix_ewise_mult); +PG_FUNCTION_INFO_V1(matrix_ewise_add); +PG_FUNCTION_INFO_V1(matrix_reduce_vector); +PG_FUNCTION_INFO_V1(matrix_transpose); +PG_FUNCTION_INFO_V1(matrix_assign_matrix); +PG_FUNCTION_INFO_V1(matrix_bfs); + +/* Vectors */ + +/* Flattened representation of vector, used to store to disk. + + Actual array data is appended and for the moment cannot exceed 1GB. +*/ +typedef struct OS_FlatVector +{ + int32 vl_len_; + GrB_Index size; + GrB_Index nvals; + GrB_Type type; +} OS_FlatVector; + +/* ID for debugging crosschecks */ +#define vector_MAGIC 681276813 + +/* Expanded representation of vector. + + When loaded from storage, the flattened representation is used to + build the vector with GrB_Vector_build. +*/ +typedef struct OS_Vector +{ + ExpandedObjectHeader hdr; + int ev_magic; + GrB_Type type; + GrB_Vector V; + Size flat_size; +} OS_Vector; + +static void context_callback_vector_free(void*); + +/* Helper function that either detoasts or expands vectors. */ +OS_Vector* DatumGetVector(Datum d); + +/* Helper function to create an empty flattened vector. */ +OS_FlatVector* construct_empty_flat_vector(GrB_Index size, GrB_Type type); + +GrB_Type mxm_type(OS_Matrix *left, OS_Matrix *right); +GrB_Type mxv_type(OS_Matrix *left, OS_Vector *right); +GrB_Type vxm_type(OS_Vector *left, OS_Matrix *right); + +/* function to choose implicit semirings for overloaded operators */ +char* mxm_semiring(OS_Matrix *left, OS_Matrix *right); +char* mxv_semiring(OS_Matrix *left, OS_Vector *right); +char* vxm_semiring(OS_Vector *left, OS_Matrix *right); + +char* matrix_times_binop(OS_Matrix *left, OS_Matrix *right); +char* matrix_plus_binop(OS_Matrix *left, OS_Matrix *right); + +char* vector_times_binop(OS_Vector *left, OS_Vector *right); +char* vector_plus_binop(OS_Vector *left, OS_Vector *right); + +GrB_Semiring lookup_semiring(char *name); +GrB_BinaryOp lookup_binop(char *name); + +#define VectorGetEOHP(d) (OS_Vector *) DatumGetEOHP(d) +#define MatrixGetEOHP(d) (OS_Matrix *) DatumGetEOHP(d); + +/* Helper to detoast and expand vector arguments */ +#define OS_GETARG_VECTOR(n) DatumGetVector(PG_GETARG_DATUM(n)) + +/* Helper to return Expanded Object Header Pointer from vector. */ +#define OS_RETURN_VECTOR(A) return EOHPGetRWDatum(&(A)->hdr) + +/* Helper to compute flat vector header size */ +#define OS_VECTOR_OVERHEAD() MAXALIGN(sizeof(OS_FlatVector)) + + +PG_FUNCTION_INFO_V1(vector_in); +PG_FUNCTION_INFO_V1(vector_out); + +PG_FUNCTION_INFO_V1(vector_ewise_mult); +PG_FUNCTION_INFO_V1(vector_ewise_add); + +PG_FUNCTION_INFO_V1(vector_eq); +PG_FUNCTION_INFO_V1(vector_ne); + +PG_FUNCTION_INFO_V1(vector_nvals); +PG_FUNCTION_INFO_V1(vector_size); + +PG_FUNCTION_INFO_V1(vector_xtract); +PG_FUNCTION_INFO_V1(vector_print); + +typedef struct OS_Semiring +{ + char name[255]; + GrB_Semiring R; +} OS_Semiring; + +typedef struct OS_BinaryOp +{ + char name[255]; + GrB_BinaryOp B; +} OS_BinaryOp; + +typedef struct OS_UnaryOp +{ + char name[255]; + GrB_UnaryOp U; +} OS_UnaryOp; + +#define SEMIRING(N, PLS, TMS, TYP) do { \ + strlcpy(semirings[(N)].name, #PLS #TMS #TYP, 255); \ + semirings[(N)].R = GxB_ ## PLS ## TMS ## TYP; \ + } while (0) + +#define SEMIRING_TYPES(N, PLS, TMS) do { \ + SEMIRING (N, PLS, TMS, INT8); \ + SEMIRING(N+1, PLS, TMS, UINT8); \ + SEMIRING(N+2, PLS, TMS, INT16); \ + SEMIRING(N+3, PLS, TMS, UINT16); \ + SEMIRING(N+4, PLS, TMS, INT32); \ + SEMIRING(N+5, PLS, TMS, UINT32); \ + SEMIRING(N+6, PLS, TMS, INT64); \ + SEMIRING(N+7, PLS, TMS, UINT64); \ + SEMIRING(N+8, PLS, TMS, FP32); \ + SEMIRING(N+9, PLS, TMS, FP64); \ + } while(0) + +#define SEMIRING_PURE_BOOL(N, PLS) do { \ + SEMIRING(N, PLS, FIRST_, BOOL); \ + SEMIRING(N+1, PLS, SECOND_, BOOL); \ + SEMIRING(N+2, PLS, LOR_, BOOL); \ + SEMIRING(N+3, PLS, LAND_, BOOL); \ + SEMIRING(N+4, PLS, LXOR_, BOOL); \ + SEMIRING(N+5, PLS, EQ_, BOOL); \ + SEMIRING(N+6, PLS, GT_, BOOL); \ + SEMIRING(N+7, PLS, LT_, BOOL); \ + SEMIRING(N+8, PLS, GE_, BOOL); \ + SEMIRING(N+9, PLS, LE_, BOOL); \ + } while(0) + +#define SEMIRING_GROUP(N, TMS) do { \ + SEMIRING_TYPES((N), MIN_, TMS); \ + SEMIRING_TYPES((N)+10, MAX_, TMS); \ + SEMIRING_TYPES((N)+20, PLUS_, TMS); \ + SEMIRING_TYPES((N)+30, TIMES_, TMS); \ + } while(0) + +#define SEMIRING_BOOL_GROUP(N, TMS) do { \ + SEMIRING_TYPES((N), LOR_, TMS); \ + SEMIRING_TYPES((N)+10, LAND_, TMS); \ + SEMIRING_TYPES((N)+20, LXOR_, TMS); \ + SEMIRING_TYPES((N)+30, EQ_, TMS); \ + } while(0) + +#define SEMIRING_PURE_BOOL_GROUP(N) do { \ + SEMIRING_PURE_BOOL((N), LOR_); \ + SEMIRING_PURE_BOOL((N)+10, LAND_); \ + SEMIRING_PURE_BOOL((N)+20, LXOR_); \ + SEMIRING_PURE_BOOL((N)+30, EQ_); \ + } while(0) + +#define BINOP(N, PRE, OP, TYP) do { \ + strlcpy(binops[(N)].name, #OP #TYP, 255); \ + binops[(N)].B = PRE ## OP ## TYP; \ + } while (0) + +#define BINOP_TYPES(N, PRE, OP) do { \ + BINOP (N, PRE, OP, INT8); \ + BINOP(N+1, PRE, OP, UINT8); \ + BINOP(N+2, PRE, OP, INT16); \ + BINOP(N+3, PRE, OP, UINT16); \ + BINOP(N+4, PRE, OP, INT32); \ + BINOP(N+5, PRE, OP, UINT32); \ + BINOP(N+6, PRE, OP, INT64); \ + BINOP(N+7, PRE, OP, UINT64); \ + BINOP(N+8, PRE, OP, FP32); \ + BINOP(N+9, PRE, OP, FP64); \ + BINOP (N+10, PRE, OP, BOOL); \ + } while(0) + + +#define UOP(N, PRE, OP, TYP) do { \ + strlcpy(uops[(N)].name, #OP #TYP, 255); \ + uops[(N)].U = PRE ## OP ## TYP; \ + } while (0) + +#define UOP_TYPES(N, PRE, OP) do { \ + UOP (N, PRE, OP, INT8); \ + UOP(N+1, PRE, OP, UINT8); \ + UOP(N+2, PRE, OP, INT16); \ + UOP(N+3, PRE, OP, UINT16); \ + UOP(N+4, PRE, OP, INT32); \ + UOP(N+5, PRE, OP, UINT32); \ + UOP(N+6, PRE, OP, INT64); \ + UOP(N+7, PRE, OP, UINT64); \ + UOP(N+8, PRE, OP, FP32); \ + UOP(N+9, PRE, OP, FP64); \ + } while(0) + +#define RETURN_TYPECHCK1(A, B, OP, TYP) \ + if ((A) == GrB_##TYP || (B) == GrB_##TYP) \ + return #OP "_" #TYP + +#define RETURN_TYPECHCK2(A, B, TYP) \ + if ((A) == GrB_##TYP || (B) == GrB_##TYP) \ + return GrB_##TYP + +#define GETARG_DESCRIPTOR_VAL(ARG, DESC, FIELD, VAL) do { \ + char *desc_val; \ + if (!PG_ARGISNULL(ARG)) { \ + (desc_val) = text_to_cstring(PG_GETARG_TEXT_PP(ARG)); \ + if (strcmp((desc_val), "default") == 0) { \ + CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GxB_DEFAULT), DESC); \ + } else if (strcmp((desc_val), "replace") == 0) { \ + CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL), DESC); \ + } else if (strcmp((desc_val), "scmp") == 0) { \ + CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL), DESC); \ + } else if (strcmp((desc_val), "tran") == 0) { \ + CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL), DESC); \ + } else \ + elog(ERROR, "unknown outp descriptor value %s", desc_val); \ + } \ + } while(0) + +#define GET_DESCRIPTOR(N, D) do { \ + CHECKD(GrB_Descriptor_new(&D), D); \ + GETARG_DESCRIPTOR_VAL(N, D, OUTP, REPLACE); \ + GETARG_DESCRIPTOR_VAL(N+1, D, MASK, COMP_STRUCTURE); \ + GETARG_DESCRIPTOR_VAL(N+2, D, INP0, TRAN); \ + GETARG_DESCRIPTOR_VAL(N+3, D, INP1, TRAN); \ + } while (0) + +void _PG_init(void); + +void *malloc_function(size_t); +void *calloc_function(size_t, size_t); +void *realloc_function(void*, size_t); +void free_function(void*); + +#define IMPORT_EXPORT // Use import export + +#endif /* PGGRAPHBLAS_H */ + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/pggraphblas.c b/src/pggraphblas.c deleted file mode 100644 index 40ee0a7..0000000 --- a/src/pggraphblas.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "pggraphblas.h" -PG_MODULE_MAGIC; - -#define HUGE_ALLOC - -pgGrB_Semiring semirings[960]; -pgGrB_BinaryOp binops[256]; -pgGrB_UnaryOp uops[67]; -MemoryContext gb_context; - -#include "type.c" -#include "vector.c" -#include "matrix.c" - -void *calloc_function(size_t num, size_t size) { - MemoryContext oldcxt; - void *p; - size_t total; - total = num * size; - oldcxt = MemoryContextSwitchTo(TopMemoryContext); -#ifdef HUGE_ALLOC - p = palloc_extended(total, MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); -#else - p = palloc0(total); -#endif - MemoryContextSwitchTo(oldcxt); - return p; -} - -void *malloc_function(size_t size) { - MemoryContext oldcxt; - void *p; - oldcxt = MemoryContextSwitchTo(TopMemoryContext); - -#ifdef HUGE_ALLOC - p = palloc_extended(size, MCXT_ALLOC_HUGE); -#else - p = palloc(size); -#endif - MemoryContextSwitchTo(oldcxt); - return p; -} - -void *realloc_function(void *p, size_t size) { - MemoryContext oldcxt; - oldcxt = MemoryContextSwitchTo(TopMemoryContext); -#ifdef HUGE_ALLOC - p = repalloc_huge(p, size); -#else - p = repalloc(p, size); -#endif - MemoryContextSwitchTo(oldcxt); - return p; -} - -void free_function(void *p) { - // MemoryContext oldcxt; - // oldcxt = MemoryContextSwitchTo(TopMemoryContext); - pfree(p); - // MemoryContextSwitchTo(oldcxt); -} - -void -_PG_init(void) -{ - GrB_Info info; - -#ifdef IMPORT_EXPORT - info = LAGraph_xinit (malloc_function, - calloc_function, - realloc_function, - free_function, - false); -#else - info = LAGraph_init (GrB_BLOCKING); -#endif - - if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) { - elog(ERROR, "%s", GrB_error()); - return; - } - - SEMIRING_GROUP(0, FIRST_); - SEMIRING_GROUP(40, SECOND_); - SEMIRING_GROUP(80, MIN_); - SEMIRING_GROUP(120, MAX_); - SEMIRING_GROUP(160, PLUS_); - SEMIRING_GROUP(200, MINUS_); - SEMIRING_GROUP(240, TIMES_); - SEMIRING_GROUP(280, DIV_); - SEMIRING_GROUP(320, ISEQ_); - SEMIRING_GROUP(360, ISNE_); - SEMIRING_GROUP(400, ISGT_); - SEMIRING_GROUP(440, ISLT_); - SEMIRING_GROUP(480, ISGE_); - SEMIRING_GROUP(520, ISLE_); - SEMIRING_GROUP(560, LOR_); - SEMIRING_GROUP(600, LAND_); - SEMIRING_GROUP(640, LXOR_); - SEMIRING_BOOL_GROUP(680, EQ_); - SEMIRING_BOOL_GROUP(720, NE_); - SEMIRING_BOOL_GROUP(760, GT_); - SEMIRING_BOOL_GROUP(800, LT_); - SEMIRING_BOOL_GROUP(840, GE_); - SEMIRING_BOOL_GROUP(880, LE_); - SEMIRING_PURE_BOOL_GROUP(920); - - BINOP_TYPES(0, GrB_, FIRST_); - BINOP_TYPES(11, GrB_, SECOND_); - BINOP_TYPES(22, GrB_, MIN_); - BINOP_TYPES(33, GrB_, MAX_); - BINOP_TYPES(44, GrB_, PLUS_); - BINOP_TYPES(55, GrB_, MINUS_); - BINOP_TYPES(66, GrB_, TIMES_); - BINOP_TYPES(77, GrB_, DIV_); - - BINOP_TYPES(88, GxB_, ISEQ_); - BINOP_TYPES(99, GxB_, ISNE_); - BINOP_TYPES(110, GxB_, ISGT_); - BINOP_TYPES(121, GxB_, ISLT_); - BINOP_TYPES(132, GxB_, ISGE_); - BINOP_TYPES(143, GxB_, ISLE_); - - BINOP_TYPES(154, GrB_, EQ_); - BINOP_TYPES(165, GrB_, NE_); - BINOP_TYPES(176, GrB_, GT_); - BINOP_TYPES(187, GrB_, LT_); - BINOP_TYPES(198, GrB_, GE_); - BINOP_TYPES(209, GrB_, LE_); - - BINOP_TYPES(220, GxB_, LOR_); - BINOP_TYPES(231, GxB_, LAND_); - BINOP_TYPES(242, GxB_, LXOR_); - - BINOP(254, GrB_, LOR,); - BINOP(255, GrB_, LAND,); - BINOP(256, GrB_, LXOR,); - - UOP_TYPES(0, GrB_, IDENTITY_); - UOP_TYPES(11, GrB_, AINV_); - UOP_TYPES(22, GrB_, MINV_); - UOP_TYPES(33, GxB_, LNOT_); - UOP_TYPES(44, GxB_, ONE_); - UOP_TYPES(55, GxB_, ABS_); - UOP(67, GrB_, LNOT,); -} diff --git a/src/pggraphblas.h b/src/pggraphblas.h deleted file mode 100644 index cea040d..0000000 --- a/src/pggraphblas.h +++ /dev/null @@ -1,484 +0,0 @@ -#ifndef PGGRAPHBLAS_H -#define PGGRAPHBLAS_H - -#include "GraphBLAS.h" -#include "LAGraph.h" -#include "postgres.h" -#include "utils/builtins.h" -#include "libpq/pqformat.h" -#include "funcapi.h" -#include "access/htup_details.h" -#include "utils/array.h" -#include "utils/arrayaccess.h" -#include "catalog/pg_type_d.h" -#include "catalog/pg_type.h" -#include "utils/lsyscache.h" -#include "nodes/pg_list.h" -#include "utils/varlena.h" - -#define CCAT2(x, y) x ## y -#define CCAT(x, y) CCAT2(x, y) -#define FN(x) CCAT(x, SUFFIX) - -#define TYPE_APPLY(D, T, F, ...) do { \ - if ((T) == GrB_INT64) \ - D = F ## _int64(__VA_ARGS__); \ - else if ((T) == GrB_INT32) \ - D = F ## _int32(__VA_ARGS__); \ - else if ((T) == GrB_INT16) \ - D = F ## _int16(__VA_ARGS__); \ - else if ((T) == GrB_INT8) \ - D = F ## _int8(__VA_ARGS__); \ - else if ((T) == GrB_BOOL) \ - D = F ## _bool(__VA_ARGS__); \ - else if ((T) == GrB_FP64) \ - D = F ## _float8(__VA_ARGS__); \ - else if((T) == GrB_FP32) \ - D = F ## _float4(__VA_ARGS__); \ - else \ - elog(ERROR, "unsupported type"); \ - } while(0) - -#define DEFAULT_SEMIRING(T) \ - (T) == GrB_INT64? \ - "PLUS_TIMES_INT64" : \ - (T) == GrB_INT32? \ - "PLUS_TIMES_INT32" : \ - (T) == GrB_INT16? \ - "PLUS_TIMES_INT16" : \ - (T) == GrB_INT8? \ - "PLUS_TIMES_INT8" : \ - (T) == GrB_BOOL? \ - "LOR_LAND_BOOL" : \ - (T) == GrB_FP64? \ - "PLUS_TIMES_FP64" : \ - (T) == GrB_FP32? \ - "PLUS_TIMES_FP32" : \ - "unknown" - -#define DEFAULT_TIMES_BINOP(T) \ - (T) == GrB_INT64? \ - "TIMES_INT64" : \ - (T) == GrB_INT32? \ - "TIMES_INT32" : \ - (T) == GrB_INT16? \ - "TIMES_INT16" : \ - (T) == GrB_INT8? \ - "TIMES_INT8" : \ - (T) == GrB_BOOL? \ - "TIMES_BOOL" : \ - (T) == GrB_FP64? \ - "TIMES_FP64" : \ - (T) == GrB_FP32? \ - "TIMES_FP32" : \ - "unknown" - -#define DEFAULT_PLUS_BINOP(T) \ - (T) == GrB_INT64? \ - "PLUS_INT64" : \ - (T) == GrB_INT32? \ - "PLUS_INT32" : \ - (T) == GrB_INT16? \ - "PLUS_INT16" : \ - (T) == GrB_INT8? \ - "PLUS_INT8" : \ - (T) == GrB_BOOL? \ - "PLUS_BOOL" : \ - (T) == GrB_FP64? \ - "PLUS_FP64" : \ - (T) == GrB_FP32? \ - "PLUS_FP32" : \ - "unknown" - -/* dumb debug helper */ -#define elogn(s) elog(NOTICE, "%s", (s)) -#define elogn1(s, v) elog(NOTICE, "%s: %lu", (s), (v)) - -/* GraphBLAS API checking macros */ - -#define CHECKD(method) \ - { \ - info = method ; \ - if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) \ - { \ - elog(ERROR, "%s", GrB_error()); \ - return (Datum) 0; \ - } \ -} - -#define CHECKV(method) \ -{ \ - info = method ; \ - if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) \ - { \ - elog(ERROR, "%s", GrB_error()); \ - return; \ - } \ -} \ - -GrB_Info isequal_type -( - bool *result, - GrB_Matrix A, - GrB_Matrix B, - GrB_BinaryOp op - ); - -GrB_Info isequal -( - bool *result, - GrB_Matrix A, - GrB_Matrix B, - GrB_BinaryOp userop - ); - -GrB_Info visequal_type -( - bool *result, - GrB_Vector A, - GrB_Vector B, - GrB_BinaryOp op - ); - -GrB_Info visequal -( - bool *result, - GrB_Vector A, - GrB_Vector B, - GrB_BinaryOp userop - ); -/* Flattened representation of matrix, used to store to disk. - -Actual array data is appended and for the moment cannot exceed 1GB. -*/ -typedef struct pgGrB_FlatMatrix { - int32 vl_len_; - GrB_Index nrows; - GrB_Index ncols; - GrB_Index nvals; - GrB_Type type; - int64_t nonempty; -} pgGrB_FlatMatrix; - -/* ID for debugging crosschecks */ -#define matrix_MAGIC 689276813 - -/* Expanded representation of matrix. - -When loaded from storage, the flattened representation is used to -build the matrix with GrB_Matrix_build. -*/ -typedef struct pgGrB_Matrix { - ExpandedObjectHeader hdr; - int em_magic; - GrB_Type type; - GrB_Matrix M; - Size flat_size; -} pgGrB_Matrix; - -typedef struct pgGrB_Matrix_PageRankState { - LAGraph_PageRank *ranks; -} pgGrB_Matrix_PageRankState; - -typedef struct pgGrB_Matrix_SSSPState { - GrB_Vector pd; - GrB_Vector ppi; - GrB_Vector ph; -} pgGrB_Matrix_SSSPState; - -/* helper to turn types into names. */ -char* grb_type_to_name(GrB_Type t); -GrB_Type grb_name_to_type(char* n); - -/* Callback function for freeing matrices. */ -static void -context_callback_matrix_free(void*); - -/* Helper function that either detoasts or expands matrices. */ -pgGrB_Matrix * -DatumGetMatrix(Datum d); - -/* Helper function to create an empty flattened matrix. */ -pgGrB_FlatMatrix * -construct_empty_flat_matrix(GrB_Index nrows, - GrB_Index ncols, - GrB_Type type); - -/* Helper to detoast and expand matrixs arguments */ -#define PGGRB_GETARG_MATRIX(n) DatumGetMatrix(PG_GETARG_DATUM(n)) - -/* Helper to return Expanded Object Header Pointer from matrix. */ -#define PGGRB_RETURN_MATRIX(A) return EOHPGetRWDatum(&(A)->hdr) - -/* Helper to compute flat matrix header size */ -#define PGGRB_MATRIX_OVERHEAD() MAXALIGN(sizeof(pgGrB_FlatMatrix)) - -/* pointer to beginning of matrix data. */ -#define PGGRB_MATRIX_DATA(a) ((GrB_Index *)(((char *) (a)) + PGGRB_MATRIX_OVERHEAD())) - -/* Public API functions */ - -PG_FUNCTION_INFO_V1(matrix); -PG_FUNCTION_INFO_V1(matrix_in); -PG_FUNCTION_INFO_V1(matrix_out); - -PG_FUNCTION_INFO_V1(matrix_ncols); -PG_FUNCTION_INFO_V1(matrix_nrows); -PG_FUNCTION_INFO_V1(matrix_nvals); - -PG_FUNCTION_INFO_V1(mxm); -PG_FUNCTION_INFO_V1(mxv); -PG_FUNCTION_INFO_V1(vxm); -PG_FUNCTION_INFO_V1(matrix_kron); -PG_FUNCTION_INFO_V1(matrix_xtract); -PG_FUNCTION_INFO_V1(matrix_print); -PG_FUNCTION_INFO_V1(matrix_mmwrite); -PG_FUNCTION_INFO_V1(matrix_mmread); - -PG_FUNCTION_INFO_V1(matrix_eq); -PG_FUNCTION_INFO_V1(matrix_ne); - -PG_FUNCTION_INFO_V1(matrix_ewise_mult); -PG_FUNCTION_INFO_V1(matrix_ewise_add); -PG_FUNCTION_INFO_V1(matrix_reduce_vector); -PG_FUNCTION_INFO_V1(matrix_transpose); -PG_FUNCTION_INFO_V1(matrix_assign_matrix); -PG_FUNCTION_INFO_V1(matrix_bfs); -PG_FUNCTION_INFO_V1(matrix_pagerank); -/* PG_FUNCTION_INFO_V1(sssp_bf); */ - -/* Vectors */ - -/* Flattened representation of vector, used to store to disk. - -Actual array data is appended and for the moment cannot exceed 1GB. -*/ -typedef struct pgGrB_FlatVector { - int32 vl_len_; - GrB_Index size; - GrB_Index nvals; - GrB_Type type; -} pgGrB_FlatVector; - -/* ID for debugging crosschecks */ -#define vector_MAGIC 681276813 - -/* Expanded representation of vector. - -When loaded from storage, the flattened representation is used to -build the vector with GrB_Vector_build. -*/ -typedef struct pgGrB_Vector { - ExpandedObjectHeader hdr; - int ev_magic; - GrB_Type type; - GrB_Vector V; - Size flat_size; -} pgGrB_Vector; - -static void context_callback_vector_free(void*); - -/* Helper function that either detoasts or expands vectors. */ -pgGrB_Vector * -DatumGetVector(Datum d); - -/* Helper function to create an empty flattened vector. */ -pgGrB_FlatVector * -construct_empty_flat_vector(GrB_Index size, - GrB_Type type); - -GrB_Type mxm_type(pgGrB_Matrix *left, pgGrB_Matrix *right); -GrB_Type mxv_type(pgGrB_Matrix *left, pgGrB_Vector *right); -GrB_Type vxm_type(pgGrB_Vector *left, pgGrB_Matrix *right); - -/* function to choose implicit semirings for overloaded operators */ -char* mxm_semiring(pgGrB_Matrix *left, pgGrB_Matrix *right); -char* mxv_semiring(pgGrB_Matrix *left, pgGrB_Vector *right); -char* vxm_semiring(pgGrB_Vector *left, pgGrB_Matrix *right); - -char* matrix_times_binop(pgGrB_Matrix *left, pgGrB_Matrix *right); -char* matrix_plus_binop(pgGrB_Matrix *left, pgGrB_Matrix *right); - -char* vector_times_binop(pgGrB_Vector *left, pgGrB_Vector *right); -char* vector_plus_binop(pgGrB_Vector *left, pgGrB_Vector *right); - -GrB_Semiring lookup_semiring(char *name); -GrB_BinaryOp lookup_binop(char *name); - -#define VectorGetEOHP(d) (pgGrB_Vector *) DatumGetEOHP(d) -#define MatrixGetEOHP(d) (pgGrB_Matrix *) DatumGetEOHP(d); - -/* Helper to detoast and expand vectors arguments */ -#define PGGRB_GETARG_VECTOR(n) DatumGetVector(PG_GETARG_DATUM(n)) - -/* Helper to return Expanded Object Header Pointer from vector. */ -#define PGGRB_RETURN_VECTOR(A) return EOHPGetRWDatum(&(A)->hdr) - -/* Helper to compute flat vector header size */ -#define PGGRB_VECTOR_OVERHEAD() MAXALIGN(sizeof(pgGrB_FlatVector)) - -#define PGGRB_VECTOR_DATA(a) ((GrB_Index *)(((char *) (a)) + PGGRB_VECTOR_OVERHEAD())) - -PG_FUNCTION_INFO_V1(vector_in); -PG_FUNCTION_INFO_V1(vector_out); - -PG_FUNCTION_INFO_V1(vector_ewise_mult); -PG_FUNCTION_INFO_V1(vector_ewise_add); - -PG_FUNCTION_INFO_V1(vector_eq); -PG_FUNCTION_INFO_V1(vector_ne); - -PG_FUNCTION_INFO_V1(vector_nvals); -PG_FUNCTION_INFO_V1(vector_size); - -PG_FUNCTION_INFO_V1(vector_xtract); -PG_FUNCTION_INFO_V1(vector_print); - -typedef struct pgGrB_Semiring { - char name[255]; - GrB_Semiring R; -} pgGrB_Semiring; - -typedef struct pgGrB_BinaryOp { - char name[255]; - GrB_BinaryOp B; -} pgGrB_BinaryOp; - -typedef struct pgGrB_UnaryOp { - char name[255]; - GrB_UnaryOp U; -} pgGrB_UnaryOp; - -#define SEMIRING(N, PLS, TMS, TYP) do { \ - strlcpy(semirings[(N)].name, #PLS #TMS #TYP, 255); \ - semirings[(N)].R = GxB_ ## PLS ## TMS ## TYP; \ - } while (0) - -#define SEMIRING_TYPES(N, PLS, TMS) do { \ - SEMIRING (N, PLS, TMS, INT8); \ - SEMIRING(N+1, PLS, TMS, UINT8); \ - SEMIRING(N+2, PLS, TMS, INT16); \ - SEMIRING(N+3, PLS, TMS, UINT16); \ - SEMIRING(N+4, PLS, TMS, INT32); \ - SEMIRING(N+5, PLS, TMS, UINT32); \ - SEMIRING(N+6, PLS, TMS, INT64); \ - SEMIRING(N+7, PLS, TMS, UINT64); \ - SEMIRING(N+8, PLS, TMS, FP32); \ - SEMIRING(N+9, PLS, TMS, FP64); \ - } while(0) - -#define SEMIRING_PURE_BOOL(N, PLS) do { \ - SEMIRING(N, PLS, FIRST_, BOOL); \ - SEMIRING(N+1, PLS, SECOND_, BOOL); \ - SEMIRING(N+2, PLS, LOR_, BOOL); \ - SEMIRING(N+3, PLS, LAND_, BOOL); \ - SEMIRING(N+4, PLS, LXOR_, BOOL); \ - SEMIRING(N+5, PLS, EQ_, BOOL); \ - SEMIRING(N+6, PLS, GT_, BOOL); \ - SEMIRING(N+7, PLS, LT_, BOOL); \ - SEMIRING(N+8, PLS, GE_, BOOL); \ - SEMIRING(N+9, PLS, LE_, BOOL); \ - } while(0) - -#define SEMIRING_GROUP(N, TMS) do { \ - SEMIRING_TYPES((N), MIN_, TMS); \ - SEMIRING_TYPES((N)+10, MAX_, TMS); \ - SEMIRING_TYPES((N)+20, PLUS_, TMS); \ - SEMIRING_TYPES((N)+30, TIMES_, TMS); \ - } while(0) - -#define SEMIRING_BOOL_GROUP(N, TMS) do { \ - SEMIRING_TYPES((N), LOR_, TMS); \ - SEMIRING_TYPES((N)+10, LAND_, TMS); \ - SEMIRING_TYPES((N)+20, LXOR_, TMS); \ - SEMIRING_TYPES((N)+30, EQ_, TMS); \ - } while(0) - -#define SEMIRING_PURE_BOOL_GROUP(N) do { \ - SEMIRING_PURE_BOOL((N), LOR_); \ - SEMIRING_PURE_BOOL((N)+10, LAND_); \ - SEMIRING_PURE_BOOL((N)+20, LXOR_); \ - SEMIRING_PURE_BOOL((N)+30, EQ_); \ - } while(0) - -#define BINOP(N, PRE, OP, TYP) do { \ - strlcpy(binops[(N)].name, #OP #TYP, 255); \ - binops[(N)].B = PRE ## OP ## TYP; \ - } while (0) - -#define BINOP_TYPES(N, PRE, OP) do { \ - BINOP (N, PRE, OP, INT8); \ - BINOP(N+1, PRE, OP, UINT8); \ - BINOP(N+2, PRE, OP, INT16); \ - BINOP(N+3, PRE, OP, UINT16); \ - BINOP(N+4, PRE, OP, INT32); \ - BINOP(N+5, PRE, OP, UINT32); \ - BINOP(N+6, PRE, OP, INT64); \ - BINOP(N+7, PRE, OP, UINT64); \ - BINOP(N+8, PRE, OP, FP32); \ - BINOP(N+9, PRE, OP, FP64); \ - BINOP (N+10, PRE, OP, BOOL); \ - } while(0) - - -#define UOP(N, PRE, OP, TYP) do { \ - strlcpy(uops[(N)].name, #OP #TYP, 255); \ - uops[(N)].U = PRE ## OP ## TYP; \ - } while (0) - -#define UOP_TYPES(N, PRE, OP) do { \ - UOP (N, PRE, OP, INT8); \ - UOP(N+1, PRE, OP, UINT8); \ - UOP(N+2, PRE, OP, INT16); \ - UOP(N+3, PRE, OP, UINT16); \ - UOP(N+4, PRE, OP, INT32); \ - UOP(N+5, PRE, OP, UINT32); \ - UOP(N+6, PRE, OP, INT64); \ - UOP(N+7, PRE, OP, UINT64); \ - UOP(N+8, PRE, OP, FP32); \ - UOP(N+9, PRE, OP, FP64); \ - } while(0) - -#define RETURN_TYPECHCK1(A, B, OP, TYP) \ - if ((A) == GrB_##TYP || (B) == GrB_##TYP) \ - return #OP "_" #TYP - -#define RETURN_TYPECHCK2(A, B, TYP) \ - if ((A) == GrB_##TYP || (B) == GrB_##TYP) \ - return GrB_##TYP - -#define GETARG_DESCRIPTOR_VAL(ARG, DESC, FIELD, VAL) do { \ - char *desc_val; \ - if (!PG_ARGISNULL(ARG)) { \ - (desc_val) = text_to_cstring(PG_GETARG_TEXT_PP(ARG)); \ - if (strcmp((desc_val), "default") == 0) { \ - CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GxB_DEFAULT)); \ - } else if (strcmp((desc_val), "replace") == 0) { \ - CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL)); \ - } else if (strcmp((desc_val), "scmp") == 0) { \ - CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL)); \ - } else if (strcmp((desc_val), "tran") == 0) { \ - CHECKD(GrB_Descriptor_set((DESC), GrB_##FIELD, GrB_##VAL)); \ - } else \ - elog(ERROR, "unknown outp descriptor value %s", desc_val); \ - } \ - } while(0) - -#define GET_DESCRIPTOR(N, D) do { \ - CHECKD(GrB_Descriptor_new(&D)); \ - GETARG_DESCRIPTOR_VAL(N, D, OUTP, REPLACE); \ - GETARG_DESCRIPTOR_VAL(N+1, D, MASK, SCMP); \ - GETARG_DESCRIPTOR_VAL(N+2, D, INP0, TRAN); \ - GETARG_DESCRIPTOR_VAL(N+3, D, INP1, TRAN); \ - } while (0) - -void _PG_init(void); - -void *malloc_function(size_t); -void *calloc_function(size_t, size_t); -void *realloc_function(void*, size_t); -void free_function(void*); - -#define IMPORT_EXPORT // Use import export - -#endif /* PGGRAPHBLAS_H */ diff --git a/src/type.c b/src/type.c index b479cc6..aa5c991 100644 --- a/src/type.c +++ b/src/type.c @@ -1,173 +1,192 @@ -GrB_Semiring lookup_semiring(char *name) { - for (int i = 0; i < 960; i++) { - if (strcasecmp(semirings[i].name, name) == 0) - return semirings[i].R; - } - return NULL; +GrB_Semiring lookup_semiring(char *name) +{ + for (int i = 0; i < 960; i++) + { + if (strcasecmp(semirings[i].name, name) == 0) + return semirings[i].R; + } + return NULL; } -GrB_BinaryOp lookup_binop(char *name) { - for (int i = 0; i < 256; i++) { - if (strcasecmp(binops[i].name, name) == 0) - return binops[i].B; - } - return NULL; +GrB_BinaryOp lookup_binop(char *name) +{ + for (int i = 0; i < 256; i++) + { + if (strcasecmp(binops[i].name, name) == 0) + return binops[i].B; + } + return NULL; } -GrB_Type mxm_type(pgGrB_Matrix *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Matrix_type(&atype, left->M)); - CHECKD(GxB_Matrix_type(&btype, right->M)); - RETURN_TYPECHCK2(atype, btype, FP64); - RETURN_TYPECHCK2(atype, btype, FP32); - RETURN_TYPECHCK2(atype, btype, INT64); - RETURN_TYPECHCK2(atype, btype, INT32); - RETURN_TYPECHCK2(atype, btype, INT16); - RETURN_TYPECHCK2(atype, btype, BOOL); - return NULL; +GrB_Type mxm_type(OS_Matrix *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Matrix_type(&atype, left->M), left->M); + CHECKD(GxB_Matrix_type(&btype, right->M), right->M); + RETURN_TYPECHCK2(atype, btype, FP64); + RETURN_TYPECHCK2(atype, btype, FP32); + RETURN_TYPECHCK2(atype, btype, INT64); + RETURN_TYPECHCK2(atype, btype, INT32); + RETURN_TYPECHCK2(atype, btype, INT16); + RETURN_TYPECHCK2(atype, btype, BOOL); + return NULL; } -GrB_Type mxv_type(pgGrB_Matrix *left, pgGrB_Vector *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Matrix_type(&atype, left->M)); - CHECKD(GxB_Vector_type(&btype, right->V)); - RETURN_TYPECHCK2(atype, btype, FP64); - RETURN_TYPECHCK2(atype, btype, FP32); - RETURN_TYPECHCK2(atype, btype, INT64); - RETURN_TYPECHCK2(atype, btype, INT32); - RETURN_TYPECHCK2(atype, btype, INT16); - RETURN_TYPECHCK2(atype, btype, BOOL); - return NULL; +GrB_Type mxv_type(OS_Matrix *left, OS_Vector *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Matrix_type(&atype, left->M), left->M); + CHECKD(GxB_Vector_type(&btype, right->V), right->V); + RETURN_TYPECHCK2(atype, btype, FP64); + RETURN_TYPECHCK2(atype, btype, FP32); + RETURN_TYPECHCK2(atype, btype, INT64); + RETURN_TYPECHCK2(atype, btype, INT32); + RETURN_TYPECHCK2(atype, btype, INT16); + RETURN_TYPECHCK2(atype, btype, BOOL); + return NULL; } -GrB_Type vxm_type(pgGrB_Vector *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Vector_type(&atype, left->V)); - CHECKD(GxB_Matrix_type(&btype, right->M)); - RETURN_TYPECHCK2(atype, btype, FP64); - RETURN_TYPECHCK2(atype, btype, FP32); - RETURN_TYPECHCK2(atype, btype, INT64); - RETURN_TYPECHCK2(atype, btype, INT32); - RETURN_TYPECHCK2(atype, btype, INT16); - RETURN_TYPECHCK2(atype, btype, BOOL); - return NULL; +GrB_Type vxm_type(OS_Vector *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Vector_type(&atype, left->V), left->V); + CHECKD(GxB_Matrix_type(&btype, right->M), right->M); + RETURN_TYPECHCK2(atype, btype, FP64); + RETURN_TYPECHCK2(atype, btype, FP32); + RETURN_TYPECHCK2(atype, btype, INT64); + RETURN_TYPECHCK2(atype, btype, INT32); + RETURN_TYPECHCK2(atype, btype, INT16); + RETURN_TYPECHCK2(atype, btype, BOOL); + return NULL; } -char* mxm_semiring(pgGrB_Matrix *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Matrix_type(&atype, left->M)); - CHECKD(GxB_Matrix_type(&btype, right->M)); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); - RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); - return ""; +char* mxm_semiring(OS_Matrix *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Matrix_type(&atype, left->M), left->M); + CHECKD(GxB_Matrix_type(&btype, right->M), right->M); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); + RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); + return ""; } -char* mxv_semiring(pgGrB_Matrix *left, pgGrB_Vector *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Matrix_type(&atype, left->M)); - CHECKD(GxB_Vector_type(&btype, right->V)); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); - RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); - return ""; +char* mxv_semiring(OS_Matrix *left, OS_Vector *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Matrix_type(&atype, left->M), left->M); + CHECKD(GxB_Vector_type(&btype, right->V), right->V); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); + RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); + return ""; } -char* vxm_semiring(pgGrB_Vector *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type atype, btype; - CHECKD(GxB_Vector_type(&atype, left->V)); - CHECKD(GxB_Matrix_type(&btype, right->M)); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); - RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); - RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); - return ""; +char* vxm_semiring(OS_Vector *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type atype, btype; + CHECKD(GxB_Vector_type(&atype, left->V), left->V); + CHECKD(GxB_Matrix_type(&btype, right->M), right->M); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, FP32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT64); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT32); + RETURN_TYPECHCK1(atype, btype, PLUS_TIMES, INT16); + RETURN_TYPECHCK1(atype, btype, LOR_LAND, BOOL); + return ""; } -char* matrix_times_binop(pgGrB_Matrix *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type type; - CHECKD(GxB_Matrix_type(&type, left->M)); - return DEFAULT_TIMES_BINOP(type); +char* matrix_times_binop(OS_Matrix *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type type; + CHECKD(GxB_Matrix_type(&type, left->M), left->M); + return DEFAULT_TIMES_BINOP(type); } -char* matrix_plus_binop(pgGrB_Matrix *left, pgGrB_Matrix *right) { - GrB_Info info; - GrB_Type type; - CHECKD(GxB_Matrix_type(&type, left->M)); - return DEFAULT_PLUS_BINOP(type); +char* matrix_plus_binop(OS_Matrix *left, OS_Matrix *right) +{ + GrB_Info info; + GrB_Type type; + CHECKD(GxB_Matrix_type(&type, left->M), left->M); + return DEFAULT_PLUS_BINOP(type); } - -char* vector_times_binop(pgGrB_Vector *left, pgGrB_Vector *right) { - GrB_Info info; - GrB_Type type; - CHECKD(GxB_Vector_type(&type, left->V)); - return DEFAULT_TIMES_BINOP(type); +char* vector_times_binop(OS_Vector *left, OS_Vector *right) +{ + GrB_Info info; + GrB_Type type; + CHECKD(GxB_Vector_type(&type, left->V), left->V); + return DEFAULT_TIMES_BINOP(type); } -char* vector_plus_binop(pgGrB_Vector *left, pgGrB_Vector *right) { - GrB_Info info; - GrB_Type type; - CHECKD(GxB_Vector_type(&type, left->V)); - return DEFAULT_PLUS_BINOP(type); +char* vector_plus_binop(OS_Vector *left, OS_Vector *right) +{ + GrB_Info info; + GrB_Type type; + CHECKD(GxB_Vector_type(&type, left->V), left->V); + return DEFAULT_PLUS_BINOP(type); } -char* grb_type_to_name(GrB_Type t) { - if ( t == GrB_BOOL ) - return "bool"; - if ( t == GrB_INT8 ) - return "char"; - if ( t == GrB_UINT8 ) - return "uchar"; - if ( t == GrB_INT16 ) - return "smallint"; - if ( t == GrB_UINT16 ) - return "usmallint"; - if ( t == GrB_INT32 ) - return "integer"; - if ( t == GrB_UINT32 ) - return "uinteger"; - if ( t == GrB_INT64 ) - return "bigint"; - if ( t == GrB_UINT64 ) - return "ubigint"; - if ( t == GrB_FP32 ) - return "real"; - if ( t == GrB_FP64 ) - return "float"; - return "unknown"; +char* grb_type_to_name(GrB_Type t) +{ + if ( t == GrB_BOOL ) + return "bool"; + if ( t == GrB_INT8 ) + return "char"; + if ( t == GrB_UINT8 ) + return "uchar"; + if ( t == GrB_INT16 ) + return "smallint"; + if ( t == GrB_UINT16 ) + return "usmallint"; + if ( t == GrB_INT32 ) + return "integer"; + if ( t == GrB_UINT32 ) + return "uinteger"; + if ( t == GrB_INT64 ) + return "bigint"; + if ( t == GrB_UINT64 ) + return "ubigint"; + if ( t == GrB_FP32 ) + return "real"; + if ( t == GrB_FP64 ) + return "float"; + return "unknown"; } /* #define SEMIRING(add, mul) \ */ -/* {"GxB_" #add #mul "INT8", GxB_ ## add ## mul ## INT8}, \ */ -/* {"GxB_" #add #mul "INT16", GxB_ ## add ## mul ## INT16}, \ */ -/* {"GxB_" #add #mul "INT32", GxB_ ## add ## mul ## INT32}, \ */ -/* {"GxB_" #add #mul "INT64", GxB_ ## add ## mul ## INT64}, \ */ +/* {"GxB_" #add #mul "INT8", GxB_ ## add ## mul ## INT8}, \ */ +/* {"GxB_" #add #mul "INT16", GxB_ ## add ## mul ## INT16}, \ */ +/* {"GxB_" #add #mul "INT32", GxB_ ## add ## mul ## INT32}, \ */ +/* {"GxB_" #add #mul "INT64", GxB_ ## add ## mul ## INT64}, \ */ -/* struct pgGrB_Semiring */ +/* struct OS_Semiring */ /* { */ -/* const char* name; */ -/* GrB_Semiring semiring; */ +/* const char* name; */ +/* GrB_Semiring semiring; */ /* } */ -/* pgGrB_Semiring[] = */ +/* OS_Semiring[] = */ /* { */ /* SEMIRING(PLUS_, TIMES_); */ /* {"setinel", NULL} */ /* }; */ + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/vector.c b/src/vector.c index da0d66a..b93cf40 100644 --- a/src/vector.c +++ b/src/vector.c @@ -66,21 +66,21 @@ #define PRINT_FMT(v) "%i", v #include "vector.h" -#define SUFFIX _int64 // suffix for names -#define PG_TYPE int64 // postgres type -#define GB_TYPE GrB_INT64 // graphblas vector type -#define GB_DUP GrB_SECOND_INT64 // default duplicate index resolver -#define GB_MUL GrB_TIMES_INT64 // times bin op -#define GB_ADD GrB_PLUS_INT64 // times bin op -#define GB_EQ GxB_ISEQ_INT64 // equality operator +#define SUFFIX _int64 // suffix for names +#define PG_TYPE int64 // postgres type +#define GB_TYPE GrB_INT64 // graphblas vector type +#define GB_DUP GrB_SECOND_INT64 // default duplicate index resolver +#define GB_MUL GrB_TIMES_INT64 // times bin op +#define GB_ADD GrB_PLUS_INT64 // times bin op +#define GB_EQ GxB_ISEQ_INT64 // equality operator #define GB_NE GxB_ISNE_INT64 #define GB_RNG GxB_PLUS_TIMES_INT64 -#define PG_GET PG_GETARG_INT64 // how to get value args +#define PG_GET PG_GETARG_INT64 // how to get value args #define PG_RET PG_RETURN_INT64 -#define PG_DGT DatumGetInt64 // datum get type -#define PG_TGD Int64GetDatum // type get datum -#define PRINT_FMT(v) "%lu", v // printf fmt -#include "vector.h" // "call" template +#define PG_DGT DatumGetInt64 // datum get type +#define PG_TGD Int64GetDatum // type get datum +#define PRINT_FMT(v) "%lu", v // printf fmt +#include "vector.h" // "call" template #define SUFFIX _float4 #define PG_TYPE float4 @@ -116,238 +116,254 @@ /* MemoryContextCallback function to free matrices */ static void -context_callback_vector_free(void* a) { - pgGrB_Vector *A = (pgGrB_Vector *) a; - GrB_Vector_free(&A->V); +context_callback_vector_free(void* a) +{ + OS_Vector *A = (OS_Vector *) a; + GrB_Vector_free(&A->V); } /* Construct an empty flat vector. */ -pgGrB_FlatVector * -construct_empty_flat_vector(GrB_Index size, GrB_Type type) { - pgGrB_FlatVector *result; - - result = (pgGrB_FlatVector *) palloc0(sizeof(pgGrB_FlatVector)); - SET_VARSIZE(result, sizeof(pgGrB_FlatVector)); - result->size = size; - result->nvals = 0; - result->type = type; - return result; +OS_FlatVector * +construct_empty_flat_vector(GrB_Index size, GrB_Type type) +{ + OS_FlatVector *result; + + result = (OS_FlatVector *) palloc0(sizeof(OS_FlatVector)); + SET_VARSIZE(result, sizeof(OS_FlatVector)); + result->size = size; + result->nvals = 0; + result->type = type; + return result; } /* Helper function to always expanded datum -This is used by PGGRB_GETARG_VECTOR */ -pgGrB_Vector * -DatumGetVector(Datum d) { - pgGrB_Vector *A; - pgGrB_FlatVector *flat; - - if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(d))) { - A = VectorGetEOHP(d); - Assert(A->ev_magic == vector_MAGIC); - return A; - } - flat = (pgGrB_FlatVector*)PG_DETOAST_DATUM(d); - TYPE_APPLY(d, flat->type, expand_flat_vector, flat, CurrentMemoryContext); - return VectorGetEOHP(d); + This is used by OS_GETARG_VECTOR */ +OS_Vector * +DatumGetVector(Datum d) +{ + OS_Vector *A; + OS_FlatVector *flat; + + if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(d))) + { + A = VectorGetEOHP(d); + Assert(A->ev_magic == vector_MAGIC); + return A; + } + flat = (OS_FlatVector*)PG_DETOAST_DATUM(d); + TYPE_APPLY(d, flat->type, expand_flat_vector, flat, CurrentMemoryContext); + return VectorGetEOHP(d); } Datum vector_in(PG_FUNCTION_ARGS) { - pgGrB_FlatVector *flat; - char *input; - size_t len; - int bc; - Datum d; - - input = PG_GETARG_CSTRING(0); - len = strlen(input); - bc = (len) / 2 + VARHDRSZ; - flat = palloc(bc); - hex_decode(input, len, (char*)flat); - TYPE_APPLY(d, flat->type, expand_flat_vector, flat, CurrentMemoryContext); - return d; + OS_FlatVector *flat; + char *input; + size_t len; + int bc; + Datum d; + + input = PG_GETARG_CSTRING(0); + len = strlen(input); + bc = (len) / 2 + VARHDRSZ; + flat = palloc(bc); + hex_decode(input, len, (char*)flat); + TYPE_APPLY(d, flat->type, expand_flat_vector, flat, CurrentMemoryContext); + return d; } Datum vector_out(PG_FUNCTION_ARGS) { - Size size; - char *rp, *result, *buf; - pgGrB_Vector *A = PGGRB_GETARG_VECTOR(0); - size = EOH_get_flat_size(&A->hdr); - buf = palloc(size); - EOH_flatten_into(&A->hdr, buf, size); - rp = result = palloc((size * 2) + 1); - rp += hex_encode(buf, size, rp); - *rp = '\0'; - PG_RETURN_CSTRING(result); + Size size; + char *rp, *result, *buf; + OS_Vector *A = OS_GETARG_VECTOR(0); + size = EOH_get_flat_size(&A->hdr); + buf = palloc(size); + EOH_flatten_into(&A->hdr, buf, size); + rp = result = palloc((size * 2) + 1); + rp += hex_encode(buf, size, rp); + *rp = '\0'; + PG_RETURN_CSTRING(result); } Datum -vector_ewise_mult(PG_FUNCTION_ARGS) { - pgGrB_Vector *A, *B; - pgGrB_Vector *C = NULL, *mask = NULL; - Datum d; - char *binop_name, *accum_name; - GrB_BinaryOp binop = NULL, accum = NULL; - GrB_Descriptor desc = NULL; - GrB_Info info; - - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_VECTOR(1); - - accum_name = NULL; - binop_name = vector_times_binop(A, B); - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_VECTOR(3); - binop_name = PG_ARGISNULL(4) ? - binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); - accum_name = PG_ARGISNULL(5) ? - accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - binop = lookup_binop(binop_name); - if (binop == NULL) - elog(ERROR, "unknown binop name %s", binop_name); - if (accum_name != NULL) - accum = lookup_binop(accum_name); - - - TYPE_APPLY(d, A->type, vector_ewise_mult, A, B, C, mask, binop, accum, desc); - return d; +vector_ewise_mult(PG_FUNCTION_ARGS) +{ + OS_Vector *A, *B; + OS_Vector *C = NULL, *mask = NULL; + Datum d; + char *binop_name, *accum_name; + GrB_BinaryOp binop = NULL, accum = NULL; + GrB_Descriptor desc = NULL; + GrB_Info info; + + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_VECTOR(1); + + accum_name = NULL; + binop_name = vector_times_binop(A, B); + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_VECTOR(3); + binop_name = PG_ARGISNULL(4) ? + binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); + accum_name = PG_ARGISNULL(5) ? + accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + binop = lookup_binop(binop_name); + if (binop == NULL) + elog(ERROR, "unknown binop name %s", binop_name); + if (accum_name != NULL) + accum = lookup_binop(accum_name); + + + TYPE_APPLY(d, A->type, vector_ewise_mult, A, B, C, mask, binop, accum, desc); + return d; } Datum -vector_ewise_add(PG_FUNCTION_ARGS) { - pgGrB_Vector *A, *B; - pgGrB_Vector *C = NULL, *mask = NULL; - Datum d; - char *binop_name, *accum_name; - GrB_BinaryOp binop = NULL, accum = NULL; - GrB_Descriptor desc = NULL; - GrB_Info info; - - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_VECTOR(1); - - accum_name = NULL; - binop_name = vector_times_binop(A, B); - - if (PG_NARGS() > 2) { - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); - mask = PG_ARGISNULL(3) ? NULL : PGGRB_GETARG_VECTOR(3); - binop_name = PG_ARGISNULL(4) ? - binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); - accum_name = PG_ARGISNULL(5) ? - accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); - if (PG_NARGS() > 6) { - GET_DESCRIPTOR(6, desc); - } - } - - binop = lookup_binop(binop_name); - if (binop == NULL) - elog(ERROR, "unknown binop name %s", binop_name); - if (accum_name != NULL) - accum = lookup_binop(accum_name); - - - TYPE_APPLY(d, A->type, vector_ewise_add, A, B, C, mask, binop, accum, desc); - return d; +vector_ewise_add(PG_FUNCTION_ARGS) +{ + OS_Vector *A, *B; + OS_Vector *C = NULL, *mask = NULL; + Datum d; + char *binop_name, *accum_name; + GrB_BinaryOp binop = NULL, accum = NULL; + GrB_Descriptor desc = NULL; + GrB_Info info; + + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_VECTOR(1); + + accum_name = NULL; + binop_name = vector_times_binop(A, B); + + if (PG_NARGS() > 2) + { + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); + mask = PG_ARGISNULL(3) ? NULL : OS_GETARG_VECTOR(3); + binop_name = PG_ARGISNULL(4) ? + binop_name : text_to_cstring(PG_GETARG_TEXT_PP(4)); + accum_name = PG_ARGISNULL(5) ? + accum_name : text_to_cstring(PG_GETARG_TEXT_PP(5)); + if (PG_NARGS() > 6) + GET_DESCRIPTOR(6, desc); + } + + binop = lookup_binop(binop_name); + if (binop == NULL) + elog(ERROR, "unknown binop name %s", binop_name); + if (accum_name != NULL) + accum = lookup_binop(accum_name); + + + TYPE_APPLY(d, A->type, vector_ewise_add, A, B, C, mask, binop, accum, desc); + return d; } Datum -vector_nvals(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *vec; - GrB_Index nvals; - vec = PGGRB_GETARG_VECTOR(0); - CHECKD(GrB_Vector_nvals(&nvals, vec->V)); - return Int64GetDatum(nvals); +vector_nvals(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *vec; + GrB_Index nvals; + vec = OS_GETARG_VECTOR(0); + CHECKD(GrB_Vector_nvals(&nvals, vec->V), vec->V); + return Int64GetDatum(nvals); } Datum -vector_size(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *vec; - GrB_Index size; - vec = PGGRB_GETARG_VECTOR(0); - CHECKD(GrB_Vector_size(&size, vec->V)); - return Int64GetDatum(size); +vector_size(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *vec; + GrB_Index size; + vec = OS_GETARG_VECTOR(0); + CHECKD(GrB_Vector_size(&size, vec->V), vec->V); + return Int64GetDatum(size); } Datum -vector_eq(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A, *B; - bool result; +vector_eq(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A, *B; + bool result; - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_VECTOR(1); + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_VECTOR(1); - CHECKD(LAGraph_Vector_isequal(&result, A->V, B->V, NULL)); - PG_RETURN_BOOL(result); + result = true; + PG_RETURN_BOOL(result); } Datum -vector_ne(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A, *B; - bool result; +vector_ne(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A, *B; + bool result; - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_VECTOR(1); + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_VECTOR(1); - CHECKD(LAGraph_Vector_isequal(&result, A->V, B->V, NULL)); - PG_RETURN_BOOL(!result); + result = true; + PG_RETURN_BOOL(!result); } Datum -vector_xtract(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A, *B, *C = NULL; - GrB_Index size, *indexes; +vector_xtract(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A, *B, *C = NULL; + GrB_Index size, *indexes; - A = PGGRB_GETARG_VECTOR(0); - B = PGGRB_GETARG_VECTOR(1); - C = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); + A = OS_GETARG_VECTOR(0); + B = OS_GETARG_VECTOR(1); + C = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); - CHECKD(GrB_Vector_size(&size, A->V)); - if (C == NULL) { - TYPE_APPLY(C, A->type, construct_empty_expanded_vector, size, CurrentMemoryContext); - } + CHECKD(GrB_Vector_size(&size, A->V), A->V); + if (C == NULL) + TYPE_APPLY(C, A->type, construct_empty_expanded_vector, size, CurrentMemoryContext); - TYPE_APPLY(indexes, A->type, extract_indexes, B, size); + TYPE_APPLY(indexes, A->type, extract_indexes, B, size); - CHECKD(GrB_Vector_extract(C->V, NULL, NULL, A->V, indexes, size, NULL)); - PGGRB_RETURN_VECTOR(C); + CHECKD(GrB_Vector_extract(C->V, NULL, NULL, A->V, indexes, size, NULL), A->V); + OS_RETURN_VECTOR(C); } Datum -vector_print(PG_FUNCTION_ARGS) { - pgGrB_Vector *A; - char *result, *buf; - size_t size; - FILE *fp; - int level; - A = PGGRB_GETARG_VECTOR(0); - level = PG_GETARG_INT32(1); +vector_print(PG_FUNCTION_ARGS) +{ + OS_Vector *A; + char *result, *buf; + size_t size; + FILE *fp; + int level; + A = OS_GETARG_VECTOR(0); + level = PG_GETARG_INT32(1); - fp = open_memstream(&buf, &size); - if (fp == NULL) - elog(ERROR, "unable to open memstream for vector_print"); - GxB_fprint(A->V, level, fp); - fflush(fp); - result = palloc(size + 1); - memcpy(result, buf, size+1); - free(buf); - PG_RETURN_TEXT_P(cstring_to_text_with_len(result, size+1)); + fp = open_memstream(&buf, &size); + if (fp == NULL) + elog(ERROR, "unable to open memstream for vector_print"); + GxB_fprint(A->V, level, fp); + fflush(fp); + result = palloc(size + 1); + memcpy(result, buf, size+1); + free(buf); + PG_RETURN_TEXT_P(cstring_to_text_with_len(result, size+1)); } + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/vector.h b/src/vector.h index 6ab239f..fd7efe8 100644 --- a/src/vector.h +++ b/src/vector.h @@ -1,482 +1,243 @@ /* This is a "header template" see vector.c for specific instanciations */ -typedef struct FN(pgGrB_Vector_ExtractState) { - pgGrB_Vector *vec; - GrB_Index *indices; - PG_TYPE *vals; -} FN(pgGrB_Vector_ExtractState); +typedef struct FN(OS_Vector_ExtractState) +{ + OS_Vector *vec; + GrB_Index *indices; + PG_TYPE *vals; +} FN(OS_Vector_ExtractState); /* Expanded Object Header "methods" for flattening vectors for storage */ static Size FN(vector_get_flat_size)(ExpandedObjectHeader *eohptr); static void FN(vector_flatten_into)(ExpandedObjectHeader *eohptr, - void *result, Size allocated_size); + void *result, Size allocated_size); -static const ExpandedObjectMethods FN(vector_methods) = { - FN(vector_get_flat_size), - FN(vector_flatten_into) +static const ExpandedObjectMethods FN(vector_methods) = +{ + FN(vector_get_flat_size), + FN(vector_flatten_into) }; /* Utility function that expands a flattened vector datum. */ Datum -FN(expand_flat_vector)(pgGrB_FlatVector *flat, - MemoryContext parentcontext); +FN(expand_flat_vector)(OS_FlatVector *flat, + MemoryContext parentcontext); /* Helper function that creates an expanded empty vector. */ -pgGrB_Vector * +OS_Vector * FN(construct_empty_expanded_vector)(GrB_Index size, - MemoryContext parentcontext); - -Datum FN(vector_out)(pgGrB_Vector *vec); -Datum FN(vector_ewise_mult)(pgGrB_Vector *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc); -Datum FN(vector_ewise_add)(pgGrB_Vector *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc); - -Datum FN(vector_eq)(pgGrB_Vector *A, - pgGrB_Vector *B); - -Datum FN(vector_ne)(pgGrB_Vector *A, - pgGrB_Vector *B); - -GrB_Index *FN(extract_indexes)(pgGrB_Vector *A, GrB_Index size); - -PG_FUNCTION_INFO_V1(FN(vector)); -PG_FUNCTION_INFO_V1(FN(vector_empty)); -PG_FUNCTION_INFO_V1(FN(vector_elements)); -PG_FUNCTION_INFO_V1(FN(vector_reduce)); -PG_FUNCTION_INFO_V1(FN(vector_assign)); -PG_FUNCTION_INFO_V1(FN(vector_set_element)); + MemoryContext parentcontext); + /* Compute size of storage needed for vector */ static Size -FN(vector_get_flat_size)(ExpandedObjectHeader *eohptr) { - GrB_Info info; - pgGrB_Vector *A = (pgGrB_Vector *) eohptr; - Size nbytes; - GrB_Index size, nvals; - - Assert(A->ev_magic == vector_MAGIC); +FN(vector_get_flat_size)(ExpandedObjectHeader *eohptr) +{ + GrB_Info info; + OS_Vector *A = (OS_Vector *) eohptr; + GrB_Index size, nvals; - if (A->flat_size) - return A->flat_size; + Assert(A->ev_magic == vector_MAGIC); - CHECKD(GrB_Vector_size(&size, A->V)); - CHECKD(GrB_Vector_nvals(&nvals, A->V)); + if (A->flat_size) + return A->flat_size; - nbytes = PGGRB_VECTOR_OVERHEAD(); - nbytes += size * sizeof(GrB_Index); - nbytes += nvals * sizeof(PG_TYPE); + CHECKD(GrB_Vector_size(&size, A->V), A->V); + CHECKD(GrB_Vector_nvals(&nvals, A->V), A->V); - A->flat_size = nbytes; - return nbytes; + A->flat_size = OS_VECTOR_OVERHEAD(); + return A->flat_size; } /* Flatten vector into allocated result buffer */ static void FN(vector_flatten_into)(ExpandedObjectHeader *eohptr, - void *result, Size allocated_size) { - GrB_Info info; - GrB_Index *start, size, nvals; - pgGrB_Vector *A = (pgGrB_Vector *) eohptr; - pgGrB_FlatVector *flat = (pgGrB_FlatVector *) result; -#ifdef IMPORT_EXPORT - void *values; - GrB_Type type; -#endif - - Assert(A->ev_magic == vector_MAGIC); - Assert(allocated_size == A->flat_size); - - memset(flat, 0, allocated_size); - - CHECKV(GrB_Vector_nvals(&nvals, A->V)); - CHECKV(GrB_Vector_size(&size, A->V)); - -#ifdef IMPORT_EXPORT - CHECKV(GxB_Vector_export(&A->V, - &type, - &size, - &nvals, - &start, - &values, - NULL)); - - if (nvals > 0) { - memcpy(PGGRB_VECTOR_DATA(flat), start, nvals*sizeof(GrB_Index)); - memcpy((PGGRB_VECTOR_DATA(flat) + nvals), values, nvals*sizeof(PG_TYPE)); - pfree(start); - pfree(values); - } -#else - start = PGGRB_VECTOR_DATA(flat); - CHECKV(GrB_Vector_extractTuples(start, - start + size, - &nvals, - A->V)); -#endif - - flat->size = size; - flat->nvals = nvals; - flat->type = GB_TYPE; - - SET_VARSIZE(flat, allocated_size); + void *result, Size allocated_size) +{ + GrB_Info info; + GrB_Index size, nvals; + OS_Vector *A = (OS_Vector *) eohptr; + OS_FlatVector *flat = (OS_FlatVector *) result; + + Assert(A->ev_magic == vector_MAGIC); + Assert(allocated_size == A->flat_size); + + memset(flat, 0, allocated_size); + + CHECKV(GrB_Vector_nvals(&nvals, A->V), A->V); + CHECKV(GrB_Vector_size(&size, A->V), A->V); + + flat->size = size; + flat->nvals = nvals; + flat->type = GB_TYPE; + + SET_VARSIZE(flat, allocated_size); } /* Expand a flat vector. */ Datum -FN(expand_flat_vector)(pgGrB_FlatVector *flat, - MemoryContext parentcontext) { - GrB_Info info; - - pgGrB_Vector *A; - - MemoryContext objcxt, oldcxt; - MemoryContextCallback *ctxcb; - - GrB_Index size, nvals; - GrB_Index *indices; - PG_TYPE *vals; - GrB_Type type; - - /* Create a new context that will hold the expanded object. */ - objcxt = AllocSetContextCreate( - parentcontext, - "expanded vector", - ALLOCSET_DEFAULT_SIZES); - - /* Allocate a new expanded vector */ - A = (pgGrB_Vector*)MemoryContextAlloc( - objcxt, - sizeof(pgGrB_Vector)); - - /* Initialize the ExpandedObjectHeader member with flattening - * methods and new object context */ - EOH_init_header(&A->hdr, &FN(vector_methods), objcxt); - - /* Used for debugging checks */ - A->ev_magic = vector_MAGIC; - - /* Switch to new object context */ - oldcxt = MemoryContextSwitchTo(objcxt); - - /* Get dimensional information from flat */ - size = flat->size; - nvals = flat->nvals; - type = flat->type; - - /* indices and vals are pointers into the vardata area */ - - indices = PGGRB_VECTOR_DATA(flat); - vals = (PG_TYPE*)(indices + size); - - /* Initialize the new vector */ - CHECKD(GrB_Vector_new(&A->V, - type, - size)); - - /* Create a context callback to free vector when context is cleared */ - ctxcb = (MemoryContextCallback*)MemoryContextAlloc( - objcxt, - sizeof(MemoryContextCallback)); - - ctxcb->func = context_callback_vector_free; - ctxcb->arg = A; - MemoryContextRegisterResetCallback(objcxt, ctxcb); - - /* If there's actual values, build the vector */ - if (nvals > 0) { - CHECKD(GrB_Vector_build(A->V, - indices, - vals, - nvals, - GB_DUP)); - } - - A->type = type; - A->flat_size = 0; - - /* Switch back to old context */ - MemoryContextSwitchTo(oldcxt); - PGGRB_RETURN_VECTOR(A); -} +FN(expand_flat_vector)(OS_FlatVector *flat, + MemoryContext parentcontext) +{ + GrB_Info info; -/* Construct an empty expanded vector. */ -pgGrB_Vector * -FN(construct_empty_expanded_vector)(GrB_Index size, - MemoryContext parentcontext) { - pgGrB_FlatVector *flat; - Datum d; - flat = construct_empty_flat_vector(size, GB_TYPE); - d = FN(expand_flat_vector)(flat, parentcontext); - pfree(flat); - return (pgGrB_Vector *) DatumGetEOHP(d); -} + OS_Vector *A; -Datum -FN(vector_empty)(PG_FUNCTION_ARGS) { - pgGrB_Vector *retval; - GrB_Index max_index; - max_index = PG_GETARG_INT64(0); - retval = FN(construct_empty_expanded_vector)(max_index, CurrentMemoryContext); - PGGRB_RETURN_VECTOR(retval); - } + MemoryContext objcxt, oldcxt; + MemoryContextCallback *ctxcb; -/* cast implementation function. */ -Datum -FN(vector)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *retval; - ArrayType *indexes, *vals; - int *idims, *vdims; - int i; - GrB_Index vcount, size; - - GrB_Index *row_indices; - PG_TYPE *values; - ArrayIterator array_iterator; - Datum value; - bool isnull; - - if (PG_NARGS() == 1) { - indexes = NULL; - vals = PG_GETARG_ARRAYTYPE_P(0); - if (ARR_HASNULL(vals)) - ereport(ERROR, (errmsg("Value array may not contain NULLs"))); - vdims = ARR_DIMS(vals); - } else { - indexes = PG_GETARG_ARRAYTYPE_P(0); - vals = PG_GETARG_ARRAYTYPE_P(1); - if (ARR_HASNULL(vals) || ARR_HASNULL(indexes)) - ereport(ERROR, (errmsg("Neither value or indexc arrays may not contain NULLs"))); - - idims = ARR_DIMS(indexes); - vdims = ARR_DIMS(vals); - - if (idims[0] != vdims[0]) - ereport(ERROR, (errmsg("Index and Value arrays must be same size."))); - } - - size = vcount = vdims[0]; - - if (PG_NARGS() > 2 && !PG_ARGISNULL(2)) - size = PG_GETARG_INT64(2); - - row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * vcount); - values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * vcount); - - i = 0; - array_iterator = array_create_iterator(vals, 0, NULL); - while (array_iterate(array_iterator, &value, &isnull)) - { - if (indexes == NULL) - row_indices[i] = i; - values[i] = PG_DGT(value); - i++; - } - - i = 0; - if (indexes != NULL) { - array_iterator = array_create_iterator(indexes, 0, NULL); - while (array_iterate(array_iterator, &value, &isnull)) { - row_indices[i] = DatumGetInt64(value); - if (row_indices[i] > size) - size = row_indices[i] + 1; - i++; - } - } - - retval = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); - - CHECKD(GrB_Vector_build(retval->V, - row_indices, - values, - vcount, - GB_DUP)); - - PGGRB_RETURN_VECTOR(retval); -} + GrB_Index size, nvals; + GrB_Type type; -Datum -FN(vector_elements)(PG_FUNCTION_ARGS) { - GrB_Info info; - FuncCallContext *funcctx; - TupleDesc tupdesc; - Datum result; - - Datum values[3]; - bool nulls[2] = {false, false}; - HeapTuple tuple; - GrB_Index size = 0; - pgGrB_Vector *vec; - FN(pgGrB_Vector_ExtractState) *state; - - if (SRF_IS_FIRSTCALL()) { - MemoryContext oldcontext; - - funcctx = SRF_FIRSTCALL_INIT(); - oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - vec = (pgGrB_Vector *) PGGRB_GETARG_VECTOR(0); - - state = (FN(pgGrB_Vector_ExtractState)*)palloc(sizeof(FN(pgGrB_Vector_ExtractState))); - CHECKD(GrB_Vector_size(&size, vec->V)); - - state->indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * size); - state->vals = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * size); - - CHECKD(GrB_Vector_extractTuples(state->indices, - state->vals, - &size, - vec->V)); - state->vec = vec; - funcctx->max_calls = size; - funcctx->user_fctx = (void*)state; - - /* One-time setup code appears here: */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context " - "that cannot accept type record"))); - BlessTupleDesc(tupdesc); - funcctx->tuple_desc = tupdesc; - - MemoryContextSwitchTo(oldcontext); - } - - funcctx = SRF_PERCALL_SETUP(); - state = (FN(pgGrB_Vector_ExtractState)*)funcctx->user_fctx; - vec = state->vec; - - if (funcctx->call_cntr < funcctx->max_calls) { - values[0] = Int64GetDatum(state->indices[funcctx->call_cntr]); - values[1] = PG_TGD(state->vals[funcctx->call_cntr]); - - tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); - result = HeapTupleGetDatum(tuple); - SRF_RETURN_NEXT(funcctx, result); - } else { - SRF_RETURN_DONE(funcctx); - } -} + /* Create a new context that will hold the expanded object. */ + objcxt = AllocSetContextCreate( + parentcontext, + "expanded vector", + ALLOCSET_DEFAULT_SIZES); -Datum -FN(vector_ewise_mult)(pgGrB_Vector *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc) { - GrB_Info info; - GrB_Index size; - - if (C == NULL) { - CHECKD(GrB_Vector_size(&size, A->V)); - C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); - } - CHECKD(GrB_eWiseMult(C->V, mask ? mask->V : NULL, accum, binop, A->V, B->V, desc)); - PGGRB_RETURN_VECTOR(C); -} + /* Allocate a new expanded vector */ + A = (OS_Vector*)MemoryContextAlloc( + objcxt, + sizeof(OS_Vector)); -Datum -FN(vector_ewise_add)(pgGrB_Vector *A, - pgGrB_Vector *B, - pgGrB_Vector *C, - pgGrB_Vector *mask, - GrB_BinaryOp binop, - GrB_BinaryOp accum, - GrB_Descriptor desc) { - GrB_Info info; - GrB_Index size; - - if (C == NULL) { - CHECKD(GrB_Vector_size(&size, A->V)); - C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); - } - CHECKD(GrB_eWiseAdd(C->V, mask ? mask->V : NULL, accum, GB_ADD, A->V, B->V, desc)); - PGGRB_RETURN_VECTOR(C); -} + /* Initialize the ExpandedObjectHeader member with flattening + * methods and new object context */ + EOH_init_header(&A->hdr, &FN(vector_methods), objcxt); + + /* Used for debugging checks */ + A->ev_magic = vector_MAGIC; + + /* Switch to new object context */ + oldcxt = MemoryContextSwitchTo(objcxt); + + /* Get dimensional information from flat */ + size = flat->size; + nvals = flat->nvals; + type = flat->type; -GrB_Index *FN(extract_indexes)(pgGrB_Vector *A, - GrB_Index size) { - GrB_Index *row_indices; - PG_TYPE *values; - GrB_Info info; + /* Create a context callback to free vector when context is cleared */ + ctxcb = (MemoryContextCallback*)MemoryContextAlloc( + objcxt, + sizeof(MemoryContextCallback)); - row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * size); - values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * size); + ctxcb->func = context_callback_vector_free; + ctxcb->arg = A; + MemoryContextRegisterResetCallback(objcxt, ctxcb); - CHECKD(GrB_Vector_extractTuples(row_indices, - values, - &size, - A->V)); - return row_indices; + A->type = type; + A->flat_size = 0; + + /* Switch back to old context */ + MemoryContextSwitchTo(oldcxt); + OS_RETURN_VECTOR(A); +} + +/* Construct an empty expanded vector. */ +OS_Vector * +FN(construct_empty_expanded_vector)(GrB_Index size, + MemoryContext parentcontext) +{ + OS_FlatVector *flat; + Datum d; + flat = construct_empty_flat_vector(size, GB_TYPE); + d = FN(expand_flat_vector)(flat, parentcontext); + pfree(flat); + return (OS_Vector *) DatumGetEOHP(d); } Datum -FN(vector_reduce)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A; - GrB_Semiring semiring; - GrB_Monoid monoid; - char *semiring_name; - PG_TYPE val; - - A = PGGRB_GETARG_VECTOR(0); - semiring_name = PG_ARGISNULL(1) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(1)); - - semiring = semiring_name ? lookup_semiring(semiring_name) : GB_RNG; - CHECKD(GxB_Semiring_add(&monoid, semiring)); - CHECKD(GrB_reduce(&val, NULL, monoid, A->V, NULL)); - PG_RET(val); +FN(vector_empty)(PG_FUNCTION_ARGS) +{ + OS_Vector *retval; + GrB_Index max_index; + max_index = PG_GETARG_INT64(0); + retval = FN(construct_empty_expanded_vector)(max_index, CurrentMemoryContext); + OS_RETURN_VECTOR(retval); } +/* cast implementation function. */ Datum -FN(vector_assign)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A, *B, *mask; - GrB_Index size, *indexes = NULL; - PG_TYPE val; +FN(vector)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *retval; + ArrayType *indexes, *vals; + int *idims, *vdims; + int i; + GrB_Index vcount, size; + + GrB_Index *row_indices; + PG_TYPE *values; + ArrayIterator array_iterator; + Datum value; + bool isnull; + + if (PG_NARGS() == 1) + { + indexes = NULL; + vals = PG_GETARG_ARRAYTYPE_P(0); + if (ARR_HASNULL(vals)) + ereport(ERROR, (errmsg("Value array may not contain NULLs"))); + vdims = ARR_DIMS(vals); + } + else + { + indexes = PG_GETARG_ARRAYTYPE_P(0); + vals = PG_GETARG_ARRAYTYPE_P(1); + if (ARR_HASNULL(vals) || ARR_HASNULL(indexes)) + ereport(ERROR, (errmsg("Neither value or indexc arrays may not contain NULLs"))); - A = PGGRB_GETARG_VECTOR(0); - val = PG_GET(1); - B = PG_ARGISNULL(2) ? NULL : PGGRB_GETARG_VECTOR(2); - mask = PG_ARGISNULL(3)? NULL : PGGRB_GETARG_VECTOR(3); + idims = ARR_DIMS(indexes); + vdims = ARR_DIMS(vals); - CHECKD(GrB_Vector_size(&size, A->V)); + if (idims[0] != vdims[0]) + ereport(ERROR, (errmsg("Index and Value arrays must be same size."))); + } - if (B != NULL) - indexes = FN(extract_indexes)(B, size); + size = vcount = vdims[0]; - CHECKD(GrB_assign(A->V, mask? mask->V: NULL, NULL, val, indexes ? indexes : GrB_ALL, size, NULL)); - PGGRB_RETURN_VECTOR(A); -} + if (PG_NARGS() > 2 && !PG_ARGISNULL(2)) + size = PG_GETARG_INT64(2); -Datum -FN(vector_set_element)(PG_FUNCTION_ARGS) { - GrB_Info info; - pgGrB_Vector *A; - GrB_Index index; - PG_TYPE val; - - A = PGGRB_GETARG_VECTOR(0); - index = PG_GETARG_INT64(1); - val = PG_GET(2); - - CHECKD(GrB_Vector_setElement(A->V, val, index)); - PGGRB_RETURN_VECTOR(A); + row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * vcount); + values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * vcount); + + i = 0; + array_iterator = array_create_iterator(vals, 0, NULL); + while (array_iterate(array_iterator, &value, &isnull)) + { + if (indexes == NULL) + row_indices[i] = i; + values[i] = PG_DGT(value); + i++; + } + + i = 0; + if (indexes != NULL) + { + array_iterator = array_create_iterator(indexes, 0, NULL); + while (array_iterate(array_iterator, &value, &isnull)) + { + row_indices[i] = DatumGetInt64(value); + if (row_indices[i] > size) + size = row_indices[i] + 1; + i++; + } + } + + retval = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); + + CHECKD(GrB_Vector_build(retval->V, + row_indices, + values, + vcount, + GB_DUP), retval->V); + + OS_RETURN_VECTOR(retval); } +#include "vector_ops.h" + #undef SUFFIX #undef PG_TYPE #undef GB_TYPE @@ -491,3 +252,8 @@ FN(vector_set_element)(PG_FUNCTION_ARGS) { #undef PG_DGT #undef PG_TGD #undef PRINT_FMT + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/src/vector_ops.h b/src/vector_ops.h new file mode 100644 index 0000000..1447e79 --- /dev/null +++ b/src/vector_ops.h @@ -0,0 +1,220 @@ + +Datum FN(vector_out)(OS_Vector *vec); +Datum FN(vector_ewise_mult)(OS_Vector *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc); +Datum FN(vector_ewise_add)(OS_Vector *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc); + +Datum FN(vector_eq)(OS_Vector *A, + OS_Vector *B); + +Datum FN(vector_ne)(OS_Vector *A, + OS_Vector *B); + +GrB_Index *FN(extract_indexes)(OS_Vector *A, GrB_Index size); + +PG_FUNCTION_INFO_V1(FN(vector)); +PG_FUNCTION_INFO_V1(FN(vector_empty)); +PG_FUNCTION_INFO_V1(FN(vector_elements)); +PG_FUNCTION_INFO_V1(FN(vector_reduce)); +PG_FUNCTION_INFO_V1(FN(vector_assign)); +PG_FUNCTION_INFO_V1(FN(vector_set_element)); + +Datum +FN(vector_elements)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + FuncCallContext *funcctx; + TupleDesc tupdesc; + Datum result; + + Datum values[3]; + bool nulls[2] = {false, false}; + HeapTuple tuple; + GrB_Index size = 0; + OS_Vector *vec; + FN(OS_Vector_ExtractState) *state; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcontext; + + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + vec = (OS_Vector *) OS_GETARG_VECTOR(0); + + state = (FN(OS_Vector_ExtractState)*)palloc(sizeof(FN(OS_Vector_ExtractState))); + CHECKD(GrB_Vector_size(&size, vec->V), vec->V); + + state->indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * size); + state->vals = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * size); + + CHECKD(GrB_Vector_extractTuples(state->indices, + state->vals, + &size, + vec->V), vec->V); + state->vec = vec; + funcctx->max_calls = size; + funcctx->user_fctx = (void*)state; + + /* One-time setup code appears here: */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + BlessTupleDesc(tupdesc); + funcctx->tuple_desc = tupdesc; + + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + state = (FN(OS_Vector_ExtractState)*)funcctx->user_fctx; + vec = state->vec; + + if (funcctx->call_cntr < funcctx->max_calls) + { + values[0] = Int64GetDatum(state->indices[funcctx->call_cntr]); + values[1] = PG_TGD(state->vals[funcctx->call_cntr]); + + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } + else + { + SRF_RETURN_DONE(funcctx); + } +} + +Datum +FN(vector_ewise_mult)(OS_Vector *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc) +{ + GrB_Info info; + GrB_Index size; + + if (C == NULL) + { + CHECKD(GrB_Vector_size(&size, A->V), A->V); + C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); + } + CHECKD(GrB_eWiseMult(C->V, mask ? mask->V : NULL, accum, binop, A->V, B->V, desc), C->V); + OS_RETURN_VECTOR(C); +} + +Datum +FN(vector_ewise_add)(OS_Vector *A, + OS_Vector *B, + OS_Vector *C, + OS_Vector *mask, + GrB_BinaryOp binop, + GrB_BinaryOp accum, + GrB_Descriptor desc) +{ + GrB_Info info; + GrB_Index size; + + if (C == NULL) + { + CHECKD(GrB_Vector_size(&size, A->V), A->V); + C = FN(construct_empty_expanded_vector)(size, CurrentMemoryContext); + } + CHECKD(GrB_eWiseAdd(C->V, mask ? mask->V : NULL, accum, GB_ADD, A->V, B->V, desc), C->V); + OS_RETURN_VECTOR(C); +} + +GrB_Index *FN(extract_indexes)(OS_Vector *A, + GrB_Index size) +{ + GrB_Index *row_indices; + PG_TYPE *values; + GrB_Info info; + + row_indices = (GrB_Index*) palloc0(sizeof(GrB_Index) * size); + values = (PG_TYPE*) palloc0(sizeof(PG_TYPE) * size); + + CHECKD(GrB_Vector_extractTuples(row_indices, + values, + &size, + A->V), A->V); + return row_indices; +} + +Datum +FN(vector_reduce)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A; + GrB_Semiring semiring; + GrB_Monoid monoid; + char *semiring_name; + PG_TYPE val; + + A = OS_GETARG_VECTOR(0); + semiring_name = PG_ARGISNULL(1) ? NULL : text_to_cstring(PG_GETARG_TEXT_PP(1)); + + semiring = semiring_name ? lookup_semiring(semiring_name) : GB_RNG; + CHECKD(GxB_Semiring_add(&monoid, semiring), semiring); + CHECKD(GrB_reduce(&val, NULL, monoid, A->V, NULL), A->V); + PG_RET(val); +} + +Datum +FN(vector_assign)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A, *B, *mask; + GrB_Index size, *indexes = NULL; + PG_TYPE val; + + A = OS_GETARG_VECTOR(0); + val = PG_GET(1); + B = PG_ARGISNULL(2) ? NULL : OS_GETARG_VECTOR(2); + mask = PG_ARGISNULL(3)? NULL : OS_GETARG_VECTOR(3); + + CHECKD(GrB_Vector_size(&size, A->V), A->V); + + if (B != NULL) + indexes = FN(extract_indexes)(B, size); + + CHECKD(GrB_assign(A->V, mask? mask->V: NULL, NULL, val, indexes ? indexes : GrB_ALL, size, NULL), A->V); + OS_RETURN_VECTOR(A); +} + +Datum +FN(vector_set_element)(PG_FUNCTION_ARGS) +{ + GrB_Info info; + OS_Vector *A; + GrB_Index index; + PG_TYPE val; + + A = OS_GETARG_VECTOR(0); + index = PG_GETARG_INT64(1); + val = PG_GET(2); + + CHECKD(GrB_Vector_setElement(A->V, val, index), A->V); + OS_RETURN_VECTOR(A); +} + +/* Local Variables: */ +/* mode: c */ +/* c-file-style: "postgresql" */ +/* End: */ diff --git a/test.sh b/test.sh index 4ab96e2..3ae04e7 100755 --- a/test.sh +++ b/test.sh @@ -1,21 +1,21 @@ #!/bin/bash -DB_HOST="pggraphblas-test-db" +DB_HOST="onesparse-test-db" DB_NAME="postgres" SU="postgres" EXEC="docker exec $DB_HOST" EXECIT="docker exec -it $DB_HOST" echo force rm previous container -docker rm -f pggraphblas-test +docker rm -f onesparse-test set -e echo building test image -docker build . -t pggraphblas/test +docker build . -t onesparse/test echo running test container -docker run -v $(pwd)/tests/:/tests -v $(pwd)/demo/:/demo -v --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -d --name "$DB_HOST" pggraphblas/test +docker run -v $(pwd)/tests/:/tests -v $(pwd)/demo/:/demo -v --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -d --name "$DB_HOST" onesparse/test $EXECIT pg_ctl start # $EXEC make clean @@ -34,12 +34,12 @@ done if [ $# -eq 0 ] then echo running tests - $EXEC tmux new-session -d -s pggraphblas - $EXECIT tmux attach-session -t pggraphblas + $EXEC tmux new-session -d -s onesparse + $EXECIT tmux attach-session -t onesparse else echo running repl - $EXEC tmux new-session -d -s pggraphblas $* - $EXECIT tmux attach-session -t pggraphblas + $EXEC tmux new-session -d -s onesparse $* + $EXECIT tmux attach-session -t onesparse fi echo destroying test container and image diff --git a/tests/crash.sql b/tests/crash.sql index af9bd93..e775a33 100644 --- a/tests/crash.sql +++ b/tests/crash.sql @@ -1,4 +1,4 @@ -create extension if not exists pggraphblas; +create extension if not exists onesparse; \ir gdb.sql \i /demo/fixtures.sql diff --git a/tests/test.sql b/tests/test.sql index 142d885..2b95482 100644 --- a/tests/test.sql +++ b/tests/test.sql @@ -9,6 +9,6 @@ -- \set QUIET 1 create extension if not exists pgtap; -create extension if not exists pggraphblas; +create extension if not exists onesparse; \ir init.sql