diff --git a/Dockerfile b/Dockerfile index f20e91f..e20d1b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,71 @@ -ARG BASE_CONTAINER=python:3.10-slim-buster -FROM ${BASE_CONTAINER} as suitesparse +ARG BASE_CONTAINER=python:3.12-slim-bookworm +FROM ${BASE_CONTAINER} AS suitesparse ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -yq build-essential cmake git ARG SUITESPARSE -ARG COMPACT +ARG COMPACT=0 WORKDIR /build RUN git clone https://github.com/eliben/pycparser.git --depth 1 -WORKDIR /build/GraphBLAS/build +# Use `-DJITINIT=2` so that the JIT functionality is available, but disabled by default. +# Level 2, "run", means that pre-JIT kernels may be used, which does not require a compiler at runtime. +# Disable JIT entirely to avoid segfaulting in tests (matches CI in suitesparse.sh). RUN git clone https://github.com/DrTimothyAldenDavis/GraphBLAS.git --depth 1 --branch ${SUITESPARSE} \ && cd GraphBLAS/build \ - && cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DGBCOMPACT=${COMPACT} \ + && cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCOMPACT=${COMPACT} \ + -DJITINIT=2 \ + -DGRAPHBLAS_USE_JIT=OFF \ && make -j$(nproc) \ && make install -FROM ${BASE_CONTAINER} as psg -ARG SUITESPARSE +FROM ${BASE_CONTAINER} AS psg ARG VERSION -ENV PYTHONUNBUFFERED 1 +ENV PYTHONUNBUFFERED=1 -COPY --from=suitesparse /usr/include/GraphBLAS.h /usr/local/include/ -COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas* /usr/lib/x86_64-linux-gnu/ -COPY --from=suitesparse /build/pycparser/utils/fake_libc_include/* /usr/local/lib/python3.10/site-packages/pycparser/utils/fake_libc_include/ +COPY --from=suitesparse /usr/include/suitesparse/GraphBLAS.h /usr/local/include/suitesparse/GraphBLAS.h +# Copy only the real versioned library; recreate symlinks (Docker COPY collapses cross-stage symlinks). +COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas.so.*.*.* /usr/lib/x86_64-linux-gnu/ +RUN cd /usr/lib/x86_64-linux-gnu \ + && REAL=$(ls libgraphblas.so.*.*.*) \ + && SOMAJOR=libgraphblas.so.$(echo "$REAL" | sed -E 's/libgraphblas\.so\.([0-9]+).*/\1/') \ + && ln -sf "$REAL" "$SOMAJOR" \ + && ln -sf "$SOMAJOR" libgraphblas.so \ + && ldconfig RUN apt-get update && apt-get install -yq build-essential git -RUN pip3 install numpy cffi pytest cython +RUN pip3 install --break-system-packages numpy cffi pytest cython pycparser setuptools wheel setuptools-git-versioning + +COPY --from=suitesparse /build/pycparser/utils/fake_libc_include/* /usr/local/lib/python3.12/site-packages/pycparser/utils/fake_libc_include/ RUN mkdir -p /psg ADD . /psg WORKDIR /psg -RUN git tag ${VERSION} && \ +# `git tag || true` so the build is idempotent when ${VERSION} already matches an existing tag in the source tree. +RUN (git tag ${VERSION} || true) && \ python3 suitesparse_graphblas/create_headers.py && \ - python3 setup.py install && \ + pip3 install --break-system-packages --no-build-isolation --no-deps . && \ ldconfig #RUN pytest --pyargs suitesparse_graphblas.tests RUN apt-get -y --purge remove git python3-pip && apt-get clean FROM ${BASE_CONTAINER} -COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas* /usr/lib/x86_64-linux-gnu/ -COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgomp* /usr/lib/x86_64-linux-gnu/ -COPY --from=psg /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages +COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas.so.*.*.* /usr/lib/x86_64-linux-gnu/ +COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgomp.so.*.*.* /usr/lib/x86_64-linux-gnu/ +COPY --from=psg /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages +RUN cd /usr/lib/x86_64-linux-gnu \ + && GBREAL=$(ls libgraphblas.so.*.*.*) \ + && GBSOMAJOR=libgraphblas.so.$(echo "$GBREAL" | sed -E 's/libgraphblas\.so\.([0-9]+).*/\1/') \ + && ln -sf "$GBREAL" "$GBSOMAJOR" \ + && ln -sf "$GBSOMAJOR" libgraphblas.so \ + && GMREAL=$(ls libgomp.so.*.*.*) \ + && GMSOMAJOR=libgomp.so.$(echo "$GMREAL" | sed -E 's/libgomp\.so\.([0-9]+).*/\1/') \ + && ln -sf "$GMREAL" "$GMSOMAJOR" \ + && ldconfig diff --git a/suitesparse_graphblas/__init__.py b/suitesparse_graphblas/__init__.py index 72838b0..e57ca27 100644 --- a/suitesparse_graphblas/__init__.py +++ b/suitesparse_graphblas/__init__.py @@ -228,7 +228,7 @@ class burble: >>> from suitesparse_graphblas import burble, lib, matrix >>> - >>> A = matrix.new(lib.GrB_BOOL, 3, 3) + >>> A = matrix.matrix_new(lib.GrB_BOOL, 3, 3) >>> burble.is_enabled False >>> burble.enable() @@ -239,7 +239,7 @@ class burble: Example with explicit enable and disable: >>> burble.enable() - >>> n = matrix.nvals(A) + >>> n = matrix.matrix_nvals(A) [ GrB_Matrix_nvals 1.91e-06 sec ] >>> burble.disable() @@ -247,7 +247,7 @@ class burble: Example as a context manager: >>> with burble(): - >>> n = matrix.nvals(A) + >>> n = matrix.matrix_nvals(A) [ GrB_Matrix_nvals 1.91e-06 sec ] diff --git a/suitesparse_graphblas/io/binary.py b/suitesparse_graphblas/io/binary.py index 4e95931..190cc28 100644 --- a/suitesparse_graphblas/io/binary.py +++ b/suitesparse_graphblas/io/binary.py @@ -123,19 +123,19 @@ def binwrite(A, filename, comments=None, opener=Path.open): typecode = ffinew("int32_t*") matrix_type = ffi.new("GrB_Type*") - nrows[0] = matrix.nrows(A) - ncols[0] = matrix.ncols(A) - nvals[0] = matrix.nvals(A) - matrix_type[0] = matrix.type(A) + nrows[0] = matrix.matrix_nrows(A) + ncols[0] = matrix.matrix_ncols(A) + nvals[0] = matrix.matrix_nvals(A) + matrix_type[0] = matrix.matrix_type(A) check_status(A, lib.GxB_Type_size(typesize, matrix_type[0])) typecode[0] = _ss_typecodes[matrix_type[0]] - format[0] = matrix.format(A) - hyper_switch[0] = matrix.hyper_switch(A) - bitmap_switch[0] = matrix.bitmap_switch(A) - sparsity_status[0] = matrix.sparsity_status(A) - sparsity_control[0] = matrix.sparsity_control(A) + format[0] = matrix.matrix_format(A) + hyper_switch[0] = matrix.matrix_hyper_switch(A) + bitmap_switch[0] = matrix.matrix_bitmap_switch(A) + sparsity_status[0] = matrix.matrix_sparsity_status(A) + sparsity_control[0] = matrix.matrix_sparsity_control(A) by_row = format[0] == lib.GxB_BY_ROW by_col = format[0] == lib.GxB_BY_COL @@ -446,7 +446,7 @@ def binread(filename, opener=Path.open): Ax[0] = readinto_new_buffer(f, "uint8_t*", typesize[0] if is_iso[0] else Ax_size[0]) - A = matrix.new(atype, nrows[0], ncols[0]) + A = matrix.matrix_new(atype, nrows[0], ncols[0]) if by_col and is_hyper: check_status( @@ -546,7 +546,7 @@ def binread(filename, opener=Path.open): else: raise TypeError("Unknown format {format[0]}") - matrix.set_sparsity_control(A, sparsity_control[0]) - matrix.set_hyper_switch(A, hyper_switch[0]) - matrix.set_bitmap_switch(A, bitmap_switch[0]) + matrix.matrix_set_sparsity_control(A, sparsity_control[0]) + matrix.matrix_set_hyper_switch(A, hyper_switch[0]) + matrix.matrix_set_bitmap_switch(A, bitmap_switch[0]) return A diff --git a/suitesparse_graphblas/io/serialize.py b/suitesparse_graphblas/io/serialize.py index fcc7804..63e2e3d 100644 --- a/suitesparse_graphblas/io/serialize.py +++ b/suitesparse_graphblas/io/serialize.py @@ -88,7 +88,7 @@ def deserialize_matrix(data, *, free=True, nthreads=None): """Deserialize a Matrix from bytes. The `free` argument is called when the object is garbage - collected, the default is `matrix.free()`. If `free` is None then + collected, the default is `matrix.matrix_free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the matrix. """ @@ -108,7 +108,7 @@ def deserialize_matrix(data, *, free=True, nthreads=None): if free: if callable(free): return ffi.gc(A, free) - return ffi.gc(A, matrix.free) + return ffi.gc(A, matrix.matrix_free) return A @@ -116,7 +116,7 @@ def deserialize_vector(data, *, free=True, nthreads=None): """Deserialize a Vector from bytes. The `free` argument is called when the object is garbage - collected, the default is `vector.free()`. If `free` is None then + collected, the default is `vector.vector_free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the vector. """ @@ -136,7 +136,7 @@ def deserialize_vector(data, *, free=True, nthreads=None): if free: if callable(free): return ffi.gc(v, free) - return ffi.gc(v, vector.free) + return ffi.gc(v, vector.vector_free) return v diff --git a/suitesparse_graphblas/matrix.py b/suitesparse_graphblas/matrix.py index 5efa15d..7646090 100644 --- a/suitesparse_graphblas/matrix.py +++ b/suitesparse_graphblas/matrix.py @@ -1,31 +1,31 @@ -from suitesparse_graphblas import check_status, ffi, lib +from suitesparse_graphblas import check_status, ffi, lib, supports_complex from .io.serialize import deserialize_matrix as deserialize # noqa: F401 from .io.serialize import serialize_matrix as serialize # noqa: F401 -def free(A): +def matrix_free(A): """Free a matrix.""" check_status(A, lib.GrB_Matrix_free(A)) -def new(T, nrows=lib.GxB_INDEX_MAX, ncols=lib.GxB_INDEX_MAX, *, free=free): +def matrix_new(T, nrows=lib.GxB_INDEX_MAX, ncols=lib.GxB_INDEX_MAX, *, free=matrix_free): """Create a new `GrB_Matrix` of type `T` and initialize it. The following example creates an eight bit unsigned 2x2 matrix: - >>> A = new(lib.GrB_UINT8, 2, 2) - >>> shape(A) + >>> A = matrix_new(lib.GrB_UINT8, 2, 2) + >>> matrix_shape(A) (2, 2) The default value for `nrows` and `ncols` is `lib.GxB_INDEX_MAX` which creates a Matrix with maximal bounds: - >>> A = new(lib.GrB_UINT8) - >>> shape(A) == (lib.GxB_INDEX_MAX, lib.GxB_INDEX_MAX) + >>> A = matrix_new(lib.GrB_UINT8) + >>> matrix_shape(A) == (lib.GxB_INDEX_MAX, lib.GxB_INDEX_MAX) True The `free` argument is called when the object is garbage - collected, the default is `matrix.free()`. If `free` is None then + collected, the default is `matrix.matrix_free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the matrix. @@ -37,11 +37,11 @@ def new(T, nrows=lib.GxB_INDEX_MAX, ncols=lib.GxB_INDEX_MAX, *, free=free): return A -def type(A): +def matrix_type(A): """Return the GraphBLAS type of the vector. - >>> A = new(lib.GrB_UINT8) - >>> type(A) == lib.GrB_UINT8 + >>> A = matrix_new(lib.GrB_UINT8) + >>> matrix_type(A) == lib.GrB_UINT8 True """ @@ -50,11 +50,11 @@ def type(A): return T[0] -def nrows(A): +def matrix_nrows(A): """Return the number of rows in the matrix. - >>> A = new(lib.GrB_UINT8, 2, 3) - >>> nrows(A) + >>> A = matrix_new(lib.GrB_UINT8, 2, 3) + >>> matrix_nrows(A) 2 """ @@ -63,11 +63,11 @@ def nrows(A): return n[0] -def ncols(A): +def matrix_ncols(A): """Return the number of columns in the matrix. - >>> A = new(lib.GrB_UINT8, 2, 3) - >>> ncols(A) + >>> A = matrix_new(lib.GrB_UINT8, 2, 3) + >>> matrix_ncols(A) 3 """ @@ -76,11 +76,11 @@ def ncols(A): return n[0] -def nvals(A): +def matrix_nvals(A): """Return the number of stored elements in the matrix. - >>> A = new(lib.GrB_UINT8, 2, 3) - >>> nvals(A) + >>> A = matrix_new(lib.GrB_UINT8, 2, 3) + >>> matrix_nvals(A) 0 """ @@ -89,22 +89,22 @@ def nvals(A): return n[0] -def shape(A): +def matrix_shape(A): """Return the shape of the matrix as a two tuple `(nrows, ncols)` - >>> A = new(lib.GrB_UINT8, 2, 2) - >>> shape(A) + >>> A = matrix_new(lib.GrB_UINT8, 2, 2) + >>> matrix_shape(A) (2, 2) """ - return (nrows(A), ncols(A)) + return (matrix_nrows(A), matrix_ncols(A)) -def format(A): +def matrix_format(A): """Return the format of the matrix. - >>> A = new(lib.GrB_UINT8, 2, 2) - >>> format(A) == lib.GxB_BY_ROW + >>> A = matrix_new(lib.GrB_UINT8, 2, 2) + >>> matrix_format(A) == lib.GxB_BY_ROW True """ @@ -113,12 +113,12 @@ def format(A): return format[0] -def set_format(A, format): +def matrix_set_format(A, format): """Set the format of the matrix. - >>> A = new(lib.GrB_UINT8, 2, 2) - >>> set_format(A, lib.GxB_BY_COL) - >>> format(A) == lib.GxB_BY_COL + >>> A = matrix_new(lib.GrB_UINT8, 2, 2) + >>> matrix_set_format(A, lib.GxB_BY_COL) + >>> matrix_format(A) == lib.GxB_BY_COL True """ @@ -126,14 +126,14 @@ def set_format(A, format): check_status(A, lib.GxB_Matrix_Option_set_INT32(A[0], lib.GxB_FORMAT, format_val)) -def sparsity_status(A): +def matrix_sparsity_status(A): """Get the sparsity status of the matrix.""" sparsity_status = ffi.new("int32_t*") check_status(A, lib.GxB_Matrix_Option_get_INT32(A[0], lib.GxB_SPARSITY_STATUS, sparsity_status)) return sparsity_status[0] -def sparsity_control(A): +def matrix_sparsity_control(A): """Get the sparsity control of the matrix.""" sparsity_control = ffi.new("int32_t*") check_status( @@ -142,7 +142,7 @@ def sparsity_control(A): return sparsity_control[0] -def set_sparsity_control(A, sparsity): +def matrix_set_sparsity_control(A, sparsity): """Set the sparsity control of the matrix.""" sparsity_control = ffi.cast("int32_t", sparsity) check_status( @@ -150,27 +150,27 @@ def set_sparsity_control(A, sparsity): ) -def hyper_switch(A): +def matrix_hyper_switch(A): """Get the hyper switch of the matrix.""" hyper_switch = ffi.new("double*") check_status(A, lib.GxB_Matrix_Option_get_FP64(A[0], lib.GxB_HYPER_SWITCH, hyper_switch)) return hyper_switch[0] -def set_hyper_switch(A, hyper_switch): +def matrix_set_hyper_switch(A, hyper_switch): """Set the hyper switch of the matrix.""" hyper_switch = ffi.cast("double", hyper_switch) check_status(A, lib.GxB_Matrix_Option_set_FP64(A[0], lib.GxB_HYPER_SWITCH, hyper_switch)) -def bitmap_switch(A): +def matrix_bitmap_switch(A): """Get the bitmap switch of the matrix.""" bitmap_switch = ffi.new("double*") check_status(A, lib.GxB_Matrix_Option_get_FP64(A[0], lib.GxB_BITMAP_SWITCH, bitmap_switch)) return bitmap_switch[0] -def set_bitmap_switch(A, bitmap_switch): +def matrix_set_bitmap_switch(A, bitmap_switch): """Set the bitmap switch of the matrix.""" bitmap_switch = ffi.cast("double", bitmap_switch) check_status(A, lib.GxB_Matrix_Option_set_FP64(A[0], lib.GxB_BITMAP_SWITCH, bitmap_switch)) @@ -179,24 +179,335 @@ def set_bitmap_switch(A, bitmap_switch): def set_bool(A, value, i, j): """Set a boolean value to the matrix at row `i` column `j`. - >>> A = new(lib.GrB_BOOL, 3, 3) + >>> A = matrix_new(lib.GrB_BOOL, 3, 3) >>> set_bool(A, True, 2, 2) - >>> bool(A, 2, 2) == True + >>> get_bool(A, 2, 2) == True True """ check_status(A, lib.GrB_Matrix_setElement_BOOL(A[0], value, i, j)) -def bool(A, i, j): +def get_bool(A, i, j): """Get a boolean value from the matrix at row `i` column `j`. - >>> A = new(lib.GrB_BOOL, 3, 3) + >>> A = matrix_new(lib.GrB_BOOL, 3, 3) >>> set_bool(A, True, 2, 2) - >>> bool(A, 2, 2) == True + >>> get_bool(A, 2, 2) == True True """ value = ffi.new("bool*") check_status(A, lib.GrB_Matrix_extractElement_BOOL(value, A[0], i, j)) return value[0] + + +def set_int8(A, value, i, j): + """Set an int8 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT8, 3, 3) + >>> set_int8(A, 7, 2, 2) + >>> get_int8(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_INT8(A[0], value, i, j)) + + +def get_int8(A, i, j): + """Get an int8 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT8, 3, 3) + >>> set_int8(A, 7, 2, 2) + >>> get_int8(A, 2, 2) == 7 + True + + """ + value = ffi.new("int8_t*") + check_status(A, lib.GrB_Matrix_extractElement_INT8(value, A[0], i, j)) + return value[0] + + +def set_int16(A, value, i, j): + """Set an int16 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT16, 3, 3) + >>> set_int16(A, 7, 2, 2) + >>> get_int16(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_INT16(A[0], value, i, j)) + + +def get_int16(A, i, j): + """Get an int16 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT16, 3, 3) + >>> set_int16(A, 7, 2, 2) + >>> get_int16(A, 2, 2) == 7 + True + + """ + value = ffi.new("int16_t*") + check_status(A, lib.GrB_Matrix_extractElement_INT16(value, A[0], i, j)) + return value[0] + + +def set_int32(A, value, i, j): + """Set an int32 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT32, 3, 3) + >>> set_int32(A, 7, 2, 2) + >>> get_int32(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_INT32(A[0], value, i, j)) + + +def get_int32(A, i, j): + """Get an int32 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT32, 3, 3) + >>> set_int32(A, 7, 2, 2) + >>> get_int32(A, 2, 2) == 7 + True + + """ + value = ffi.new("int32_t*") + check_status(A, lib.GrB_Matrix_extractElement_INT32(value, A[0], i, j)) + return value[0] + + +def set_int64(A, value, i, j): + """Set an int64 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT64, 3, 3) + >>> set_int64(A, 7, 2, 2) + >>> get_int64(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_INT64(A[0], value, i, j)) + + +def get_int64(A, i, j): + """Get an int64 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_INT64, 3, 3) + >>> set_int64(A, 7, 2, 2) + >>> get_int64(A, 2, 2) == 7 + True + + """ + value = ffi.new("int64_t*") + check_status(A, lib.GrB_Matrix_extractElement_INT64(value, A[0], i, j)) + return value[0] + + +def set_uint8(A, value, i, j): + """Set a uint8 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT8, 3, 3) + >>> set_uint8(A, 7, 2, 2) + >>> get_uint8(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_UINT8(A[0], value, i, j)) + + +def get_uint8(A, i, j): + """Get a uint8 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT8, 3, 3) + >>> set_uint8(A, 7, 2, 2) + >>> get_uint8(A, 2, 2) == 7 + True + + """ + value = ffi.new("uint8_t*") + check_status(A, lib.GrB_Matrix_extractElement_UINT8(value, A[0], i, j)) + return value[0] + + +def set_uint16(A, value, i, j): + """Set a uint16 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT16, 3, 3) + >>> set_uint16(A, 7, 2, 2) + >>> get_uint16(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_UINT16(A[0], value, i, j)) + + +def get_uint16(A, i, j): + """Get a uint16 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT16, 3, 3) + >>> set_uint16(A, 7, 2, 2) + >>> get_uint16(A, 2, 2) == 7 + True + + """ + value = ffi.new("uint16_t*") + check_status(A, lib.GrB_Matrix_extractElement_UINT16(value, A[0], i, j)) + return value[0] + + +def set_uint32(A, value, i, j): + """Set a uint32 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT32, 3, 3) + >>> set_uint32(A, 7, 2, 2) + >>> get_uint32(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_UINT32(A[0], value, i, j)) + + +def get_uint32(A, i, j): + """Get a uint32 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT32, 3, 3) + >>> set_uint32(A, 7, 2, 2) + >>> get_uint32(A, 2, 2) == 7 + True + + """ + value = ffi.new("uint32_t*") + check_status(A, lib.GrB_Matrix_extractElement_UINT32(value, A[0], i, j)) + return value[0] + + +def set_uint64(A, value, i, j): + """Set a uint64 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT64, 3, 3) + >>> set_uint64(A, 7, 2, 2) + >>> get_uint64(A, 2, 2) == 7 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_UINT64(A[0], value, i, j)) + + +def get_uint64(A, i, j): + """Get a uint64 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_UINT64, 3, 3) + >>> set_uint64(A, 7, 2, 2) + >>> get_uint64(A, 2, 2) == 7 + True + + """ + value = ffi.new("uint64_t*") + check_status(A, lib.GrB_Matrix_extractElement_UINT64(value, A[0], i, j)) + return value[0] + + +def set_fp32(A, value, i, j): + """Set an fp32 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_FP32, 3, 3) + >>> set_fp32(A, 1.5, 2, 2) + >>> get_fp32(A, 2, 2) == 1.5 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_FP32(A[0], value, i, j)) + + +def get_fp32(A, i, j): + """Get an fp32 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_FP32, 3, 3) + >>> set_fp32(A, 1.5, 2, 2) + >>> get_fp32(A, 2, 2) == 1.5 + True + + """ + value = ffi.new("float*") + check_status(A, lib.GrB_Matrix_extractElement_FP32(value, A[0], i, j)) + return value[0] + + +def set_fp64(A, value, i, j): + """Set an fp64 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_FP64, 3, 3) + >>> set_fp64(A, 1.5, 2, 2) + >>> get_fp64(A, 2, 2) == 1.5 + True + + """ + check_status(A, lib.GrB_Matrix_setElement_FP64(A[0], value, i, j)) + + +def get_fp64(A, i, j): + """Get an fp64 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GrB_FP64, 3, 3) + >>> set_fp64(A, 1.5, 2, 2) + >>> get_fp64(A, 2, 2) == 1.5 + True + + """ + value = ffi.new("double*") + check_status(A, lib.GrB_Matrix_extractElement_FP64(value, A[0], i, j)) + return value[0] + + +if supports_complex(): + + def set_fc32(A, value, i, j): + """Set an fc32 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GxB_FC32, 3, 3) + >>> set_fc32(A, 2+3j, 2, 2) + >>> get_fc32(A, 2, 2) == 2+3j + True + + """ + check_status(A, lib.GxB_Matrix_setElement_FC32(A[0], value, i, j)) + + def get_fc32(A, i, j): + """Get an fc32 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GxB_FC32, 3, 3) + >>> set_fc32(A, 2+3j, 2, 2) + >>> get_fc32(A, 2, 2) == 2+3j + True + + """ + value = ffi.new("GxB_FC32_t*") + check_status(A, lib.GxB_Matrix_extractElement_FC32(value, A[0], i, j)) + return value[0] + + def set_fc64(A, value, i, j): + """Set an fc64 value to the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GxB_FC64, 3, 3) + >>> set_fc64(A, 2+3j, 2, 2) + >>> get_fc64(A, 2, 2) == 2+3j + True + + """ + check_status(A, lib.GxB_Matrix_setElement_FC64(A[0], value, i, j)) + + def get_fc64(A, i, j): + """Get an fc64 value from the matrix at row `i` column `j`. + + >>> A = matrix_new(lib.GxB_FC64, 3, 3) + >>> set_fc64(A, 2+3j, 2, 2) + >>> get_fc64(A, 2, 2) == 2+3j + True + + """ + value = ffi.new("GxB_FC64_t*") + check_status(A, lib.GxB_Matrix_extractElement_FC64(value, A[0], i, j)) + return value[0] diff --git a/suitesparse_graphblas/scalar.py b/suitesparse_graphblas/scalar.py index c0d5747..289ca51 100644 --- a/suitesparse_graphblas/scalar.py +++ b/suitesparse_graphblas/scalar.py @@ -1,20 +1,20 @@ -from suitesparse_graphblas import check_status, exceptions, ffi, lib +from suitesparse_graphblas import check_status, exceptions, ffi, lib, supports_complex -def free(v): +def scalar_free(v): """Free a scalar.""" check_status(v, lib.GxB_Scalar_free(v)) -def new(T, *, free=free): +def scalar_new(T, *, free=scalar_free): """Create a new `GxB_Scalar` of type `T` and initialize it. The `free` argument is called when the object is garbage - collected, the default is `scalar.free()`. If `free` is None then + collected, the default is `scalar.scalar_free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the scalar. - >>> S = new(lib.GrB_UINT8) + >>> S = scalar_new(lib.GrB_UINT8) """ s = ffi.new("GxB_Scalar*") @@ -24,11 +24,11 @@ def new(T, *, free=free): return s -def type(s): +def scalar_type(s): """Return the GraphBLAS type of the scalar. - >>> S = new(lib.GrB_UINT8) - >>> type(S) == lib.GrB_UINT8 + >>> S = scalar_new(lib.GrB_UINT8) + >>> scalar_type(S) == lib.GrB_UINT8 True """ @@ -40,21 +40,21 @@ def type(s): def set_bool(s, value): """Set a boolean value to the scalar. - >>> s = new(lib.GrB_BOOL) + >>> s = scalar_new(lib.GrB_BOOL) >>> set_bool(s, True) - >>> bool(s) == True + >>> get_bool(s) == True True """ check_status(s, lib.GxB_Scalar_setElement_BOOL(s[0], value)) -def bool(s): +def get_bool(s): """Get a boolean value from the scalar. - >>> s = new(lib.GrB_BOOL) + >>> s = scalar_new(lib.GrB_BOOL) >>> set_bool(s, True) - >>> bool(s) == True + >>> get_bool(s) == True True """ @@ -63,3 +63,338 @@ def bool(s): if res == exceptions.NoValue: return None return value[0] + + +def set_int8(s, value): + """Set an int8 value to the scalar. + + >>> s = scalar_new(lib.GrB_INT8) + >>> set_int8(s, 7) + >>> get_int8(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_INT8(s[0], value)) + + +def get_int8(s): + """Get an int8 value from the scalar. + + >>> s = scalar_new(lib.GrB_INT8) + >>> set_int8(s, 7) + >>> get_int8(s) == 7 + True + + """ + value = ffi.new("int8_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_INT8(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_int16(s, value): + """Set an int16 value to the scalar. + + >>> s = scalar_new(lib.GrB_INT16) + >>> set_int16(s, 7) + >>> get_int16(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_INT16(s[0], value)) + + +def get_int16(s): + """Get an int16 value from the scalar. + + >>> s = scalar_new(lib.GrB_INT16) + >>> set_int16(s, 7) + >>> get_int16(s) == 7 + True + + """ + value = ffi.new("int16_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_INT16(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_int32(s, value): + """Set an int32 value to the scalar. + + >>> s = scalar_new(lib.GrB_INT32) + >>> set_int32(s, 7) + >>> get_int32(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_INT32(s[0], value)) + + +def get_int32(s): + """Get an int32 value from the scalar. + + >>> s = scalar_new(lib.GrB_INT32) + >>> set_int32(s, 7) + >>> get_int32(s) == 7 + True + + """ + value = ffi.new("int32_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_INT32(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_int64(s, value): + """Set an int64 value to the scalar. + + >>> s = scalar_new(lib.GrB_INT64) + >>> set_int64(s, 7) + >>> get_int64(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_INT64(s[0], value)) + + +def get_int64(s): + """Get an int64 value from the scalar. + + >>> s = scalar_new(lib.GrB_INT64) + >>> set_int64(s, 7) + >>> get_int64(s) == 7 + True + + """ + value = ffi.new("int64_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_INT64(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_uint8(s, value): + """Set a uint8 value to the scalar. + + >>> s = scalar_new(lib.GrB_UINT8) + >>> set_uint8(s, 7) + >>> get_uint8(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_UINT8(s[0], value)) + + +def get_uint8(s): + """Get a uint8 value from the scalar. + + >>> s = scalar_new(lib.GrB_UINT8) + >>> set_uint8(s, 7) + >>> get_uint8(s) == 7 + True + + """ + value = ffi.new("uint8_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_UINT8(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_uint16(s, value): + """Set a uint16 value to the scalar. + + >>> s = scalar_new(lib.GrB_UINT16) + >>> set_uint16(s, 7) + >>> get_uint16(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_UINT16(s[0], value)) + + +def get_uint16(s): + """Get a uint16 value from the scalar. + + >>> s = scalar_new(lib.GrB_UINT16) + >>> set_uint16(s, 7) + >>> get_uint16(s) == 7 + True + + """ + value = ffi.new("uint16_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_UINT16(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_uint32(s, value): + """Set a uint32 value to the scalar. + + >>> s = scalar_new(lib.GrB_UINT32) + >>> set_uint32(s, 7) + >>> get_uint32(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_UINT32(s[0], value)) + + +def get_uint32(s): + """Get a uint32 value from the scalar. + + >>> s = scalar_new(lib.GrB_UINT32) + >>> set_uint32(s, 7) + >>> get_uint32(s) == 7 + True + + """ + value = ffi.new("uint32_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_UINT32(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_uint64(s, value): + """Set a uint64 value to the scalar. + + >>> s = scalar_new(lib.GrB_UINT64) + >>> set_uint64(s, 7) + >>> get_uint64(s) == 7 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_UINT64(s[0], value)) + + +def get_uint64(s): + """Get a uint64 value from the scalar. + + >>> s = scalar_new(lib.GrB_UINT64) + >>> set_uint64(s, 7) + >>> get_uint64(s) == 7 + True + + """ + value = ffi.new("uint64_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_UINT64(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_fp32(s, value): + """Set an fp32 value to the scalar. + + >>> s = scalar_new(lib.GrB_FP32) + >>> set_fp32(s, 1.5) + >>> get_fp32(s) == 1.5 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_FP32(s[0], value)) + + +def get_fp32(s): + """Get an fp32 value from the scalar. + + >>> s = scalar_new(lib.GrB_FP32) + >>> set_fp32(s, 1.5) + >>> get_fp32(s) == 1.5 + True + + """ + value = ffi.new("float*") + res = check_status(s, lib.GxB_Scalar_extractElement_FP32(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +def set_fp64(s, value): + """Set an fp64 value to the scalar. + + >>> s = scalar_new(lib.GrB_FP64) + >>> set_fp64(s, 1.5) + >>> get_fp64(s) == 1.5 + True + + """ + check_status(s, lib.GxB_Scalar_setElement_FP64(s[0], value)) + + +def get_fp64(s): + """Get an fp64 value from the scalar. + + >>> s = scalar_new(lib.GrB_FP64) + >>> set_fp64(s, 1.5) + >>> get_fp64(s) == 1.5 + True + + """ + value = ffi.new("double*") + res = check_status(s, lib.GxB_Scalar_extractElement_FP64(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + +if supports_complex(): + + def set_fc32(s, value): + """Set an fc32 value to the scalar. + + >>> s = scalar_new(lib.GxB_FC32) + >>> set_fc32(s, 2+3j) + >>> get_fc32(s) == 2+3j + True + + """ + check_status(s, lib.GxB_Scalar_setElement_FC32(s[0], value)) + + def get_fc32(s): + """Get an fc32 value from the scalar. + + >>> s = scalar_new(lib.GxB_FC32) + >>> set_fc32(s, 2+3j) + >>> get_fc32(s) == 2+3j + True + + """ + value = ffi.new("GxB_FC32_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_FC32(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] + + def set_fc64(s, value): + """Set an fc64 value to the scalar. + + >>> s = scalar_new(lib.GxB_FC64) + >>> set_fc64(s, 2+3j) + >>> get_fc64(s) == 2+3j + True + + """ + check_status(s, lib.GxB_Scalar_setElement_FC64(s[0], value)) + + def get_fc64(s): + """Get an fc64 value from the scalar. + + >>> s = scalar_new(lib.GxB_FC64) + >>> set_fc64(s, 2+3j) + >>> get_fc64(s) == 2+3j + True + + """ + value = ffi.new("GxB_FC64_t*") + res = check_status(s, lib.GxB_Scalar_extractElement_FC64(value, s[0])) + if res == exceptions.NoValue: + return None + return value[0] diff --git a/suitesparse_graphblas/tests/test_io.py b/suitesparse_graphblas/tests/test_io.py index dcdf857..a06afb9 100644 --- a/suitesparse_graphblas/tests/test_io.py +++ b/suitesparse_graphblas/tests/test_io.py @@ -90,7 +90,7 @@ def _test_elements(T): def test_serialize_matrix(): T = lib.GrB_INT64 - A = matrix.new(T, 2, 2) + A = matrix.matrix_new(T, 2, 2) for args in zip(*_test_elements(T)): f = _element_setters[T] check_status(A, f(A[0], *args)) @@ -98,12 +98,12 @@ def test_serialize_matrix(): B = matrix.deserialize(data) # Test equal - C = matrix.new(lib.GrB_BOOL, 2, 2) + C = matrix.matrix_new(lib.GrB_BOOL, 2, 2) check_status( C, lib.GrB_Matrix_eWiseAdd_BinaryOp(C[0], NULL, NULL, _eq_ops[T], A[0], B[0], NULL), ) - assert matrix.nvals(A) == matrix.nvals(B) == matrix.nvals(C) + assert matrix.matrix_nvals(A) == matrix.matrix_nvals(B) == matrix.matrix_nvals(C) is_eq = ffi.new("bool*") check_status( C, @@ -114,19 +114,19 @@ def test_serialize_matrix(): def test_serialize_vector(): T = lib.GrB_INT64 - v = vector.new(T, 3) + v = vector.vector_new(T, 3) check_status(v, lib.GrB_Vector_setElement_INT64(v[0], 2, 0)) check_status(v, lib.GrB_Vector_setElement_INT64(v[0], 10, 1)) data = vector.serialize(v, lib.GxB_COMPRESSION_LZ4HC, level=7) w = vector.deserialize(data) # Test equal - x = vector.new(lib.GrB_BOOL, 3) + x = vector.vector_new(lib.GrB_BOOL, 3) check_status( x, lib.GrB_Vector_eWiseAdd_BinaryOp(x[0], NULL, NULL, _eq_ops[T], v[0], w[0], NULL), ) - assert vector.nvals(v) == vector.nvals(w) == vector.nvals(x) + assert vector.vector_nvals(v) == vector.vector_nvals(w) == vector.vector_nvals(x) is_eq = ffi.new("bool*") check_status( x, @@ -140,7 +140,7 @@ def test_matrix_binfile_read_write(tmp_path): for format in (lib.GxB_BY_ROW, lib.GxB_BY_COL): for T in grb_types: for sparsity in (lib.GxB_HYPERSPARSE, lib.GxB_SPARSE, lib.GxB_BITMAP, lib.GxB_FULL): - A = matrix.new(T, 2, 2) + A = matrix.matrix_new(T, 2, 2) if T is not lib.GxB_FULL: for args in zip(*_test_elements(T)): @@ -162,21 +162,21 @@ def test_matrix_binfile_read_write(tmp_path): NULL, ), ) - matrix.set_sparsity_control(A, sparsity) - matrix.set_format(A, format) + matrix.matrix_set_sparsity_control(A, sparsity) + matrix.matrix_set_format(A, format) binfilef = tmp_path / "binfilewrite_test.binfile" binary.binwrite(A, binfilef, opener=opener) B = binary.binread(binfilef, opener=opener) - assert matrix.type(A) == matrix.type(B) - assert matrix.nrows(A) == matrix.nrows(B) - assert matrix.ncols(A) == matrix.ncols(B) - assert matrix.hyper_switch(A) == matrix.hyper_switch(B) - assert matrix.bitmap_switch(A) == matrix.bitmap_switch(B) - # assert matrix.sparsity_control(A) == matrix.sparsity_control(B) + assert matrix.matrix_type(A) == matrix.matrix_type(B) + assert matrix.matrix_nrows(A) == matrix.matrix_nrows(B) + assert matrix.matrix_ncols(A) == matrix.matrix_ncols(B) + assert matrix.matrix_hyper_switch(A) == matrix.matrix_hyper_switch(B) + assert matrix.matrix_bitmap_switch(A) == matrix.matrix_bitmap_switch(B) + # assert matrix.matrix_sparsity_control(A) == matrix.matrix_sparsity_control(B) - C = matrix.new(lib.GrB_BOOL, 2, 2) + C = matrix.matrix_new(lib.GrB_BOOL, 2, 2) check_status( C, @@ -185,7 +185,9 @@ def test_matrix_binfile_read_write(tmp_path): ), ) - assert matrix.nvals(A) == matrix.nvals(B) == matrix.nvals(C) + assert ( + matrix.matrix_nvals(A) == matrix.matrix_nvals(B) == matrix.matrix_nvals(C) + ) is_eq = ffi.new("bool*") check_status( diff --git a/suitesparse_graphblas/vector.py b/suitesparse_graphblas/vector.py index a6a15c6..66f9a5e 100644 --- a/suitesparse_graphblas/vector.py +++ b/suitesparse_graphblas/vector.py @@ -1,29 +1,29 @@ -from suitesparse_graphblas import check_status, ffi, lib +from suitesparse_graphblas import check_status, ffi, lib, supports_complex from .io.serialize import deserialize_vector as deserialize # noqa: F401 from .io.serialize import serialize_vector as serialize # noqa: F401 -def free(v): +def vector_free(v): """Free a vector.""" check_status(v, lib.GrB_Vector_free(v)) -def new(T, size=lib.GxB_INDEX_MAX, *, free=free): +def vector_new(T, size=lib.GxB_INDEX_MAX, *, free=vector_free): """Create a new `GrB_Vector` of type `T` and initialize it. - >>> A = new(lib.GrB_UINT8, 2) - >>> size(A) + >>> A = vector_new(lib.GrB_UINT8, 2) + >>> vector_size(A) 2 The default `size` is `lib.GxB_INDEX_MAX`. - >>> A = new(lib.GrB_UINT8) - >>> size(A) == lib.GxB_INDEX_MAX + >>> A = vector_new(lib.GrB_UINT8) + >>> vector_size(A) == lib.GxB_INDEX_MAX True The `free` argument is called when the object is garbage - collected, the default is `vector.free()`. If `free` is None then + collected, the default is `vector.vector_free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the vector. """ @@ -34,11 +34,11 @@ def new(T, size=lib.GxB_INDEX_MAX, *, free=free): return v -def type(v): +def vector_type(v): """Return the GraphBLAS type of the vector. - >>> v = new(lib.GrB_UINT8, 2) - >>> type(v) == lib.GrB_UINT8 + >>> v = vector_new(lib.GrB_UINT8, 2) + >>> vector_type(v) == lib.GrB_UINT8 True @@ -48,11 +48,11 @@ def type(v): return T[0] -def size(v): +def vector_size(v): """Return the size of the vector. - >>> v = new(lib.GrB_UINT8, 2) - >>> size(v) == 2 + >>> v = vector_new(lib.GrB_UINT8, 2) + >>> vector_size(v) == 2 True """ @@ -61,14 +61,14 @@ def size(v): return n[0] -def nvals(v): +def vector_nvals(v): """Return the number of stored elements in the vector. - >>> v = new(lib.GrB_BOOL, 2) - >>> nvals(v) + >>> v = vector_new(lib.GrB_BOOL, 2) + >>> vector_nvals(v) 0 >>> set_bool(v, True, 1) - >>> nvals(v) + >>> vector_nvals(v) 1 """ @@ -80,24 +80,335 @@ def nvals(v): def set_bool(v, value, i): """Set a boolean value to the vector at position `i`. - >>> v = new(lib.GrB_BOOL, 3) + >>> v = vector_new(lib.GrB_BOOL, 3) >>> set_bool(v, True, 2) - >>> bool(v, 2) == True + >>> get_bool(v, 2) == True True """ check_status(v, lib.GrB_Vector_setElement_BOOL(v[0], value, i)) -def bool(v, i): +def get_bool(v, i): """Get a boolean value from the vector at position `i`. - >>> v = new(lib.GrB_BOOL, 3) + >>> v = vector_new(lib.GrB_BOOL, 3) >>> set_bool(v, True, 2) - >>> bool(v, 2) == True + >>> get_bool(v, 2) == True True """ value = ffi.new("bool*") check_status(v, lib.GrB_Vector_extractElement_BOOL(value, v[0], i)) return value[0] + + +def set_int8(v, value, i): + """Set an int8 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT8, 3) + >>> set_int8(v, 7, 2) + >>> get_int8(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_INT8(v[0], value, i)) + + +def get_int8(v, i): + """Get an int8 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT8, 3) + >>> set_int8(v, 7, 2) + >>> get_int8(v, 2) == 7 + True + + """ + value = ffi.new("int8_t*") + check_status(v, lib.GrB_Vector_extractElement_INT8(value, v[0], i)) + return value[0] + + +def set_int16(v, value, i): + """Set an int16 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT16, 3) + >>> set_int16(v, 7, 2) + >>> get_int16(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_INT16(v[0], value, i)) + + +def get_int16(v, i): + """Get an int16 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT16, 3) + >>> set_int16(v, 7, 2) + >>> get_int16(v, 2) == 7 + True + + """ + value = ffi.new("int16_t*") + check_status(v, lib.GrB_Vector_extractElement_INT16(value, v[0], i)) + return value[0] + + +def set_int32(v, value, i): + """Set an int32 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT32, 3) + >>> set_int32(v, 7, 2) + >>> get_int32(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_INT32(v[0], value, i)) + + +def get_int32(v, i): + """Get an int32 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT32, 3) + >>> set_int32(v, 7, 2) + >>> get_int32(v, 2) == 7 + True + + """ + value = ffi.new("int32_t*") + check_status(v, lib.GrB_Vector_extractElement_INT32(value, v[0], i)) + return value[0] + + +def set_int64(v, value, i): + """Set an int64 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT64, 3) + >>> set_int64(v, 7, 2) + >>> get_int64(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_INT64(v[0], value, i)) + + +def get_int64(v, i): + """Get an int64 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_INT64, 3) + >>> set_int64(v, 7, 2) + >>> get_int64(v, 2) == 7 + True + + """ + value = ffi.new("int64_t*") + check_status(v, lib.GrB_Vector_extractElement_INT64(value, v[0], i)) + return value[0] + + +def set_uint8(v, value, i): + """Set a uint8 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT8, 3) + >>> set_uint8(v, 7, 2) + >>> get_uint8(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_UINT8(v[0], value, i)) + + +def get_uint8(v, i): + """Get a uint8 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT8, 3) + >>> set_uint8(v, 7, 2) + >>> get_uint8(v, 2) == 7 + True + + """ + value = ffi.new("uint8_t*") + check_status(v, lib.GrB_Vector_extractElement_UINT8(value, v[0], i)) + return value[0] + + +def set_uint16(v, value, i): + """Set a uint16 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT16, 3) + >>> set_uint16(v, 7, 2) + >>> get_uint16(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_UINT16(v[0], value, i)) + + +def get_uint16(v, i): + """Get a uint16 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT16, 3) + >>> set_uint16(v, 7, 2) + >>> get_uint16(v, 2) == 7 + True + + """ + value = ffi.new("uint16_t*") + check_status(v, lib.GrB_Vector_extractElement_UINT16(value, v[0], i)) + return value[0] + + +def set_uint32(v, value, i): + """Set a uint32 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT32, 3) + >>> set_uint32(v, 7, 2) + >>> get_uint32(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_UINT32(v[0], value, i)) + + +def get_uint32(v, i): + """Get a uint32 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT32, 3) + >>> set_uint32(v, 7, 2) + >>> get_uint32(v, 2) == 7 + True + + """ + value = ffi.new("uint32_t*") + check_status(v, lib.GrB_Vector_extractElement_UINT32(value, v[0], i)) + return value[0] + + +def set_uint64(v, value, i): + """Set a uint64 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT64, 3) + >>> set_uint64(v, 7, 2) + >>> get_uint64(v, 2) == 7 + True + + """ + check_status(v, lib.GrB_Vector_setElement_UINT64(v[0], value, i)) + + +def get_uint64(v, i): + """Get a uint64 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_UINT64, 3) + >>> set_uint64(v, 7, 2) + >>> get_uint64(v, 2) == 7 + True + + """ + value = ffi.new("uint64_t*") + check_status(v, lib.GrB_Vector_extractElement_UINT64(value, v[0], i)) + return value[0] + + +def set_fp32(v, value, i): + """Set an fp32 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_FP32, 3) + >>> set_fp32(v, 1.5, 2) + >>> get_fp32(v, 2) == 1.5 + True + + """ + check_status(v, lib.GrB_Vector_setElement_FP32(v[0], value, i)) + + +def get_fp32(v, i): + """Get an fp32 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_FP32, 3) + >>> set_fp32(v, 1.5, 2) + >>> get_fp32(v, 2) == 1.5 + True + + """ + value = ffi.new("float*") + check_status(v, lib.GrB_Vector_extractElement_FP32(value, v[0], i)) + return value[0] + + +def set_fp64(v, value, i): + """Set an fp64 value to the vector at position `i`. + + >>> v = vector_new(lib.GrB_FP64, 3) + >>> set_fp64(v, 1.5, 2) + >>> get_fp64(v, 2) == 1.5 + True + + """ + check_status(v, lib.GrB_Vector_setElement_FP64(v[0], value, i)) + + +def get_fp64(v, i): + """Get an fp64 value from the vector at position `i`. + + >>> v = vector_new(lib.GrB_FP64, 3) + >>> set_fp64(v, 1.5, 2) + >>> get_fp64(v, 2) == 1.5 + True + + """ + value = ffi.new("double*") + check_status(v, lib.GrB_Vector_extractElement_FP64(value, v[0], i)) + return value[0] + + +if supports_complex(): + + def set_fc32(v, value, i): + """Set an fc32 value to the vector at position `i`. + + >>> v = vector_new(lib.GxB_FC32, 3) + >>> set_fc32(v, 2+3j, 2) + >>> get_fc32(v, 2) == 2+3j + True + + """ + check_status(v, lib.GxB_Vector_setElement_FC32(v[0], value, i)) + + def get_fc32(v, i): + """Get an fc32 value from the vector at position `i`. + + >>> v = vector_new(lib.GxB_FC32, 3) + >>> set_fc32(v, 2+3j, 2) + >>> get_fc32(v, 2) == 2+3j + True + + """ + value = ffi.new("GxB_FC32_t*") + check_status(v, lib.GxB_Vector_extractElement_FC32(value, v[0], i)) + return value[0] + + def set_fc64(v, value, i): + """Set an fc64 value to the vector at position `i`. + + >>> v = vector_new(lib.GxB_FC64, 3) + >>> set_fc64(v, 2+3j, 2) + >>> get_fc64(v, 2) == 2+3j + True + + """ + check_status(v, lib.GxB_Vector_setElement_FC64(v[0], value, i)) + + def get_fc64(v, i): + """Get an fc64 value from the vector at position `i`. + + >>> v = vector_new(lib.GxB_FC64, 3) + >>> set_fc64(v, 2+3j, 2) + >>> get_fc64(v, 2) == 2+3j + True + + """ + value = ffi.new("GxB_FC64_t*") + check_status(v, lib.GxB_Vector_extractElement_FC64(value, v[0], i)) + return value[0]