From 63f1bf4ab8d82dabdb24c34675150cbbb4821073 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Sat, 12 Sep 2020 19:00:04 +0200 Subject: [PATCH 1/8] Add set/get global options .. currently only double and int values --- graphblas-java/src/main/c/unsafe.c | 30 +++++++++++++ .../github/fabianmurariu/unsafe/GRBCORE.java | 44 +++++++++++++++++++ .../fabianmurariu/unsafe/GRAPHBLASSpec.scala | 12 +++++ 3 files changed, 86 insertions(+) diff --git a/graphblas-java/src/main/c/unsafe.c b/graphblas-java/src/main/c/unsafe.c index c08bc05..735d87c 100644 --- a/graphblas-java/src/main/c/unsafe.c +++ b/graphblas-java/src/main/c/unsafe.c @@ -26,6 +26,36 @@ JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *jvm, void *reserved) { return check_grb_error(GrB_init(GrB_NONBLOCKING) ); } + JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_getGlobalInt + (JNIEnv * env, jclass cls, jint field) { + GxB_Option_Field global_field = (GxB_Option_Field) field; + int value; + check_grb_error(GxB_Global_Option_get(global_field, &value)); + + return (jint) value; + } + + JNIEXPORT jdouble JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_getGlobalDouble + (JNIEnv * env, jclass cls, jint field) { + GxB_Option_Field global_field = (GxB_Option_Field) field; + double value; + check_grb_error(GxB_Global_Option_get(global_field, &value)); + + return (jdouble) value; + } + + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_setGlobalInt + (JNIEnv * env, jclass cls, jint field, jint value) { + GxB_Option_Field global_field = (GxB_Option_Field) field; + return check_grb_error(GxB_Global_Option_set(global_field, value)); + } + + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_setGlobalDouble + (JNIEnv * env, jclass cls, jint field, jdouble value) { + GxB_Option_Field global_field = (GxB_Option_Field) field; + return check_grb_error(GxB_Global_Option_set(global_field, value)); + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_grbWait (JNIEnv * env, jclass cls) { return check_grb_error(GrB_wait()); diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java index 67a8fb6..b9a6437 100644 --- a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java @@ -112,6 +112,50 @@ public final class GRBCORE { // Monoid public static native long freeMonoid(Buffer monoid); + // Global options + // Fields (get and set) + public static int GxB_HYPER = 0; + public static int GxB_FORMAT = 1; // defines CSR/CSC format: GxB_BY_ROW or GxB_BY_COL + public static int GxB_NTHREADS = 5; + public static int GxB_CHUNK = 7; + + // Fields only for get (only supporting the ones returning ints for now) + public static int GxB_MODE = 2; // mode passed to GrB_init (blocking or non-blocking) + public static int GxB_THREAD_SAFETY = 3; // thread library that allows GraphBLAS to be thread-safe for user threads. + public static int GxB_THREADING = 4; // thread library used for internal GraphBLAS threads + //public static int GxB_LIBRARY_NAME = 8; // name of the library (char *) + //public static int GxB_LIBRARY_VERSION = 9; // library version (3 int's) + //public static int GxB_LIBRARY_DATE = 10; // date of the library (char *) + //public static int GxB_LIBRARY_ABOUT = 11; // about the library (char *) + //public static int GxB_LIBRARY_URL = 12; // URL for the library (char *) + //public static int GxB_LIBRARY_LICENSE = 13; // license of the library (char *) + //public static int GxB_LIBRARY_COMPILE_DATE = 14; // date library was compiled (char *) + //public static int GxB_LIBRARY_COMPILE_TIME = 15; // time library was compiled (char *) + //public static int GxB_API_VERSION = 16; // API version (3 int's) + //public static int GxB_API_DATE = 17; // date of the API (char *) + //public static int GxB_API_ABOUT = 18; // about the API (char *) + //public static int GxB_API_URL = 19; // URL for the API (char *) + + // Values + // for GxB_FORMAT + public static int GxB_BY_ROW = 0; // CSR + public static int GxB_BY_COL = 1; // CSC + public static int GxB_NO_FORMAT = -1; // not defined + + public static int GxB_THREAD_NONE = 0; // no threading + public static int GxB_THREAD_OPENMP = 1; // OpenMP + public static int GxB_THREAD_POSIX = 2; // POSIX pthreads + public static int GxB_THREAD_WINDOWS = 3; // Windows threads + public static int GxB_THREAD_ANSI = 4; // ANSI C11 threads + + + public static native long setGlobalInt(int field, int value); + // f.i. for hyper ratio or chunk + public static native long setGlobalDouble(int field, double value); + public static native int getGlobalInt(int field); + public static native double getGlobalDouble(int field); + // TODO return global string value or int array? f.i. version or library date + // Descriptor // Fields public static int GrB_OUTP = 0; // descriptor for output of a method diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala index 18f5211..b5b9316 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala @@ -98,6 +98,18 @@ class GRAPHBLASSpec extends AnyFlatSpec with ScalaCheckDrivenPropertyChecks with testSettersAndGettersVector[Double](GRAPHBLAS.doubleType()) { (vec, i, value) => GRAPHBLAS.setVectorElementDouble(vec, i, value) } { (vec, i) => GRAPHBLAS.getVectorElementDouble(vec, i).headOption } + behavior of "GxB_Global_Option_get/set" + + it should "get/set concurrency and hyper-ratio" in { + val concurrency = 7 + GRBCORE.setGlobalInt(GRBCORE.GxB_NTHREADS, concurrency) + GRBCORE.getGlobalInt(GRBCORE.GxB_NTHREADS) shouldBe concurrency + + val hyperRatio = 0.001337 + GRBCORE.setGlobalDouble(GRBCORE.GxB_HYPER, hyperRatio) + GRBCORE.getGlobalDouble(GRBCORE.GxB_HYPER) shouldBe hyperRatio + } + override protected def beforeAll(): Unit = { GRBCORE.initNonBlocking() } From 2cd7cd4dc266916ba1951ea3115234310be7717e Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Sun, 13 Sep 2020 18:40:17 +0200 Subject: [PATCH 2/8] Add initBlocking() --- graphblas-java/src/main/c/unsafe.c | 5 +++++ .../main/java/com/github/fabianmurariu/unsafe/GRBCORE.java | 5 +++++ .../com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala | 2 ++ 3 files changed, 12 insertions(+) diff --git a/graphblas-java/src/main/c/unsafe.c b/graphblas-java/src/main/c/unsafe.c index 735d87c..c14bf2a 100644 --- a/graphblas-java/src/main/c/unsafe.c +++ b/graphblas-java/src/main/c/unsafe.c @@ -26,6 +26,11 @@ JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *jvm, void *reserved) { return check_grb_error(GrB_init(GrB_NONBLOCKING) ); } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_initBlocking + (JNIEnv * env, jclass cls) { + return check_grb_error(GrB_init(GrB_BLOCKING) ); + } + JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBCORE_getGlobalInt (JNIEnv * env, jclass cls, jint field) { GxB_Option_Field global_field = (GxB_Option_Field) field; diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java index b9a6437..71a7545 100644 --- a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java @@ -68,6 +68,7 @@ public final class GRBCORE { public static long NOT_REALLY_GRB_ALL = Long.MIN_VALUE; // placeholder for GrB_ALL public static long[] GrB_ALL = {NOT_REALLY_GRB_ALL}; public static native long initNonBlocking(); + public static native long initBlocking(); public static native long grbWait(); public static native long grbFinalize(); @@ -142,6 +143,10 @@ public final class GRBCORE { public static int GxB_BY_COL = 1; // CSC public static int GxB_NO_FORMAT = -1; // not defined + // for GrB_Mode + public static int GrB_NONBLOCKING = 0; + public static int GrB_BLOCKING = 1; + public static int GxB_THREAD_NONE = 0; // no threading public static int GxB_THREAD_OPENMP = 1; // OpenMP public static int GxB_THREAD_POSIX = 2; // POSIX pthreads diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala index b5b9316..62c2049 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala @@ -108,6 +108,8 @@ class GRAPHBLASSpec extends AnyFlatSpec with ScalaCheckDrivenPropertyChecks with val hyperRatio = 0.001337 GRBCORE.setGlobalDouble(GRBCORE.GxB_HYPER, hyperRatio) GRBCORE.getGlobalDouble(GRBCORE.GxB_HYPER) shouldBe hyperRatio + + GRBCORE.getGlobalInt(GRBCORE.GxB_MODE) shouldBe GRBCORE.GrB_NONBLOCKING } override protected def beforeAll(): Unit = { From 71e3ef355a73c7c3444e251f45a4e9ac85cc93f3 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Tue, 8 Sep 2020 18:43:02 +0200 Subject: [PATCH 3/8] Add vector version of assign, subassign and eWiseAdd/Mult .. also a small change to VectorHandler to produce vectors with a size of > 1 (before it was always one when debugging) --- graphblas-java/src/main/c/unsafe_ops.c | 211 +++++++++++++++++- .../fabianmurariu/unsafe/GRBOPSVEC.java | 108 +++++++++ .../src/main/templates/c/unsafe_gen.c.ftl | 1 - .../unsafe/AssignExtractSpec.scala | 62 ++++- .../unsafe/AssignScalarSpec.scala | 4 +- .../fabianmurariu/unsafe/ElemWiseSpec.scala | 68 +++++- .../unsafe/SparseVectorHandler.scala | 57 +++++ .../fabianmurariu/unsafe/VectorUtils.scala | 25 ++- 8 files changed, 512 insertions(+), 24 deletions(-) create mode 100644 graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSVEC.java diff --git a/graphblas-java/src/main/c/unsafe_ops.c b/graphblas-java/src/main/c/unsafe_ops.c index 0945ef4..f686908 100644 --- a/graphblas-java/src/main/c/unsafe_ops.c +++ b/graphblas-java/src/main/c/unsafe_ops.c @@ -1,5 +1,6 @@ #include "com_github_fabianmurariu_unsafe_GRBCORE.h" #include "com_github_fabianmurariu_unsafe_GRBOPSMAT.h" +#include "com_github_fabianmurariu_unsafe_GRBOPSVEC.h" #include #include #include "GraphBLAS.h" @@ -74,6 +75,23 @@ JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseMu } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_elemWiseMulIntersectMonoid + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject monoid, jobject u, jobject v, jobject desc) { + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + GrB_Vector second = (GrB_Vector) (*env)->GetDirectBufferAddress(env, v); + GrB_Monoid semi = (GrB_Monoid) (*env)->GetDirectBufferAddress(env, monoid); + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + return check_grb_error(GrB_eWiseMult(out, m, acc, semi, first, second, d)); + + } + JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseAddUnionMonoid (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject monoid, jobject A, jobject B, jobject desc) { @@ -91,6 +109,23 @@ JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseAd } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_elemWiseAddUnionMonoid + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject monoid, jobject u, jobject v, jobject desc) { + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + GrB_Vector second = (GrB_Vector) (*env)->GetDirectBufferAddress(env, v); + GrB_Monoid semi = (GrB_Monoid) (*env)->GetDirectBufferAddress(env, monoid); + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + return check_grb_error(GrB_eWiseAdd(out, m, acc, semi, first, second, d)); + + } + JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseMulIntersectBinOp (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject monoid, jobject A, jobject B, jobject desc) { @@ -108,6 +143,23 @@ JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseMu } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_elemWiseMulIntersectBinOp + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject bin_op, jobject u, jobject v, jobject desc) { + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + GrB_Vector second = (GrB_Vector) (*env)->GetDirectBufferAddress(env, v); + GrB_BinaryOp semi = (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, bin_op); + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + return check_grb_error(GrB_eWiseMult(out, m, acc, semi, first, second, d)); + + } + JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseAddUnionBinOp (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject monoid, jobject A, jobject B, jobject desc) { @@ -125,6 +177,23 @@ JNIEXPORT jint JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_elemWiseAd } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_elemWiseAddUnionBinOp + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject bin_op, jobject u, jobject v, jobject desc) { + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + GrB_Vector second = (GrB_Vector) (*env)->GetDirectBufferAddress(env, v); + GrB_BinaryOp semi = (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, bin_op); + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + return check_grb_error(GrB_eWiseAdd(out, m, acc, semi, first, second, d)); + + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_extract (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject A, jlongArray is, jlong ni, jlongArray js, jlong nj, jobject desc) { long java_max = 9223372036854775807; @@ -204,6 +273,53 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_extract } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject u, jlongArray is, jlong ni, jobject desc) { + long java_max = 9223372036854775807; + GrB_Index grb_ni; + + grb_ni = ni == java_max ? GxB_RANGE : (GrB_Index) ni; + grb_ni = ni == java_max-1 ? GxB_STRIDE : (GrB_Index) ni; + grb_ni = ni == java_max-2 ? GxB_BACKWARDS : (GrB_Index) ni; + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + + jlong *java_is; + GrB_Index *I = NULL; + + java_is = (*env)->GetLongArrayElements(env, is, NULL); + + GrB_Index sizei; + + if (grb_ni == GxB_RANGE) { + sizei = 2; + } else if (grb_ni == GxB_BACKWARDS || grb_ni == GxB_STRIDE){ + sizei = 3; + } else { + sizei = grb_ni; + } + + I = malloc (sizei * sizeof (GrB_Index)) ; + + for (int i = 0; i < sizei; i++) { + I[i] = (GrB_Index)java_is[i]; + } + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + long res = check_grb_error(GrB_extract(out, m, acc, first, I, grb_ni, d)); + + (*env)->ReleaseLongArrayElements(env, is, java_is, 0); + free(I); + + return res; + + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_assign (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject A, jlongArray is, jlong ni, jlongArray js, jlong nj, jobject desc) { long java_max = 9223372036854775807; @@ -269,7 +385,7 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_assign GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; - long res = check_grb_error(GrB_assign(out, m, acc, first, I, grb_nj, J, grb_nj, d)); + long res = check_grb_error(GrB_assign(out, m, acc, first, I, grb_ni, J, grb_nj, d)); (*env)->ReleaseLongArrayElements(env, is, java_is, 0); (*env)->ReleaseLongArrayElements(env, js, java_js, 0); @@ -284,6 +400,53 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_assign } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_assign + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject u, jlongArray is, jlong ni, jobject desc) { + long java_max = 9223372036854775807; + GrB_Index grb_ni; + + grb_ni = ni == java_max ? GxB_RANGE : (GrB_Index) ni; + grb_ni = ni == java_max-1 ? GxB_STRIDE : (GrB_Index) ni; + grb_ni = ni == java_max-2 ? GxB_BACKWARDS : (GrB_Index) ni; + + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + + jlong *java_is; + GrB_Index *I = NULL; + + java_is = (*env)->GetLongArrayElements(env, is, NULL); + + GrB_Index sizei; + + if (grb_ni == GxB_RANGE) { + sizei = 2; + } else if (grb_ni == GxB_BACKWARDS || grb_ni == GxB_STRIDE){ + sizei = 3; + } else { + sizei = grb_ni; + } + + I = malloc (sizei * sizeof (GrB_Index)) ; + + for (int i = 0; i < sizei; i++) { + I[i] = (GrB_Index)java_is[i]; + } + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + long res = check_grb_error(GrB_assign(out, m, acc, first, I, grb_ni, d)); + + (*env)->ReleaseLongArrayElements(env, is, java_is, 0); + free(I); + + return res; + + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_subAssign (JNIEnv * env, jclass cls, jobject mat, jobject mask, jobject accum, jobject A, jlongArray is, jlong ni, jlongArray js, jlong nj, jobject desc) { // if we receive max java long we treat it as GxB_RANGE @@ -364,6 +527,52 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_subAssign } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_subAssign + (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject u, jlongArray is, jlong ni, jobject desc) { + // if we receive max java long we treat it as GxB_RANGE + long java_max = 9223372036854775807; + GrB_Index grb_ni; + + grb_ni = ni == java_max ? GxB_RANGE : (GrB_Index) ni; + grb_ni = ni == java_max-1 ? GxB_STRIDE : (GrB_Index) ni; + grb_ni = ni == java_max-2 ? GxB_BACKWARDS : (GrB_Index) ni; + + GrB_Matrix out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Matrix first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + + jlong *java_is; + GrB_Index *I = NULL; + + java_is = (*env)->GetLongArrayElements(env, is, NULL); + + GrB_Index sizei; + if (grb_ni == GxB_RANGE) { + sizei = 2; + } else if (grb_ni == GxB_BACKWARDS || grb_ni == GxB_STRIDE){ + sizei = 3; + } else { + sizei = grb_ni; + } + + I = malloc (sizei * sizeof (GrB_Index)) ; + + for (int i = 0; i < sizei; i++) { + I[i] = (GrB_Index)java_is[i]; + } + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + + long res = check_grb_error(GxB_Vector_subassign(out, m, acc, first, I, grb_ni, d)); + + (*env)->ReleaseLongArrayElements(env, is, java_is, 0); + free(I); + + return res; + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_matrixReduceBinOp (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject bin_op, jobject A, jobject desc) { GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSVEC.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSVEC.java new file mode 100644 index 0000000..3bad491 --- /dev/null +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSVEC.java @@ -0,0 +1,108 @@ +package com.github.fabianmurariu.unsafe; + +import java.nio.Buffer; + +public class GRBOPSVEC { + + static { + NarSystem.loadLibrary(); + } + + /** + * {@code w = accum (w, u.*v)} + * + * @param w input/output matrix for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w,T) + * @param monoid defines ’.*’ for T=u.*v + * @param u first input: vector u + * @param v second input: vector v + * @param desc descriptor for w, Mask, u, and v + * @return GrB_Info status + */ + public static native long elemWiseMulIntersectMonoid(Buffer w, Buffer mask, Buffer accum, Buffer monoid, Buffer u, Buffer v, Buffer desc); + + /** + * {@code w = accum (w, u.*v)} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w,T) + * @param binOp defines ’.*’ for T=u.*v + * @param u first input: vector u + * @param v second input: vector v + * @param desc descriptor for w, Mask, u, and v + * @return GrB_Info status + */ + public static native long elemWiseMulIntersectBinOp(Buffer w, Buffer mask, Buffer accum, Buffer binOp, Buffer u, Buffer v, Buffer desc); + + /** + * {@code w = accum (w, u.+v)} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w,T) + * @param monoid defines ’.+’ for T=u.+v + * @param u first input: vector u + * @param v second input: vector v + * @param desc descriptor for w, Mask, u, and v + * @return GrB_Info status + */ + public static native long elemWiseAddUnionMonoid(Buffer w, Buffer mask, Buffer accum, Buffer monoid, Buffer u, Buffer v, Buffer desc); + + /** + * {@code w = accum (w, u.+v)} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w,T) + * @param binOp defines ’.+’ for T=u.+v + * @param u first input: vector u + * @param v second input: vector v + * @param desc descriptor for w, Mask, u, and v + * @return GrB_Info status + */ + public static native long elemWiseAddUnionBinOp(Buffer w, Buffer mask, Buffer accum, Buffer binOp, Buffer u, Buffer v, Buffer desc); + + /** + * {@code w(I,J) = accum (w(i),u)} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w(I,J),T) + * @param u first input: vector u + * @param I row indices + * @param ni number of row indices + * @param desc descriptor for w, Mask, and u + * @return GrB_Info status + */ + public static native long assign(Buffer w, Buffer mask, Buffer accum, Buffer u, long[] I, long ni, Buffer desc); + + /** + * {@code w(I,J) = accum (w(i),u)} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w(I,J),T) + * @param u first input: vector u + * @param I row indices + * @param ni number of row indices + * @param desc descriptor for w, Mask, and u + * @return GrB_Info status + */ + public static native long subAssign(Buffer w, Buffer mask, Buffer accum, Buffer u, long[] I, long ni, Buffer desc); + + /** + * {@code w = accum (w, u(i))} + * + * @param w input/output vector for results + * @param mask optional mask for w, unused if NULL + * @param accum optional accum for Z=accum(w(I,J),T) + * @param u first input: vector u + * @param I row indices + * @param ni number of row indices + * @param desc descriptor for w, Mask, and u + * @return GrB_Info status + */ + public static native long extract(Buffer w, Buffer mask, Buffer accum, Buffer u, long[] I, long ni, Buffer desc); +} diff --git a/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl b/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl index 2a9d418..59c7313 100644 --- a/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl +++ b/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl @@ -204,7 +204,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala index 55feecf..f83d9c3 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala @@ -14,17 +14,17 @@ trait AssignExtractSpec { self: AnyFlatSpec with ScalaCheckDrivenPropertyChecks with Matchers => - behavior of "GrB_extract" + behavior of "GrB_Matrix_extract" - testGrBExtract[Boolean] - testGrBExtract[Byte] - testGrBExtract[Short] - testGrBExtract[Int] - testGrBExtract[Long] - testGrBExtract[Float] - testGrBExtract[Double] + testGrBMatrixExtract[Boolean] + testGrBMatrixExtract[Byte] + testGrBMatrixExtract[Short] + testGrBMatrixExtract[Int] + testGrBMatrixExtract[Long] + testGrBMatrixExtract[Float] + testGrBMatrixExtract[Double] - private def testGrBExtract[T: SparseMatrixHandler](implicit A: Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { + private def testGrBMatrixExtract[T: SparseMatrixHandler](implicit A: Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { it should s"call GrB_extract for GrB_Matrix of type ${CT.toString()}" in forAll { mt: MatrixTuples[T] => val mat = SparseMatrixHandler[T].buildMatrix(mt) @@ -60,7 +60,49 @@ trait AssignExtractSpec { } } - private def testGrBAssign[T: SparseMatrixHandler](implicit A: Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { + behavior of "GrB_Vector_extract" + + testGrBVectorExtract[Boolean] + testGrBVectorExtract[Byte] + testGrBVectorExtract[Short] + testGrBVectorExtract[Int] + testGrBVectorExtract[Long] + testGrBVectorExtract[Float] + testGrBVectorExtract[Double] + + private def testGrBVectorExtract[T: SparseVectorHandler](implicit A: Arbitrary[VectorVals[T]], CT: ClassTag[T]): Unit = { + it should s"call GrB_extract for GrB_Vector of type ${CT.toString()}" in forAll { mt: VectorVals[T] => + val vec = SparseVectorHandler[T].buildVector(mt) + + // pick half of the indices and extract them into another mat + val (_, right) = mt.vals.splitAt(mt.vals.size / 2) + val dRight = right.distinctBy(t => t._1 -> t._2) + val ni: Vector[Long] = dRight.map(_._1) + + val into = SparseVectorHandler[T].createVector(ni.size) + + val res = GRBOPSVEC.extract(into, null, null, vec, ni.toArray, ni.size, null) + assert(res == 0) + + val expected: immutable.IndexedSeq[T] = (for { + i <- ni.indices + } yield SparseVectorHandler[T].get(vec)(ni(i))).flatten + + SparseVectorHandler[T].extractTuples(into) should contain theSameElementsAs expected + } + } + +// behavior of "GrB_assign" +// +// testGrBMatrixAssign[Boolean] +// testGrBMatrixAssign[Byte] +// testGrBMatrixAssign[Short] +// testGrBMatrixAssign[Int] +// testGrBMatrixAssign[Long] +// testGrBMatrixAssign[Float] +// testGrBMatrixAssign[Double] + + private def testGrBMatrixAssign[T: SparseMatrixHandler](implicit A: Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { it should s"call GrB_assign for GrB_Matrix of type ${CT.toString()}" in forAll { mt: MatrixTuples[T] => val mat = SparseMatrixHandler[T].buildMatrix(mt) diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignScalarSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignScalarSpec.scala index 9cf257b..1e9d70a 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignScalarSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignScalarSpec.scala @@ -10,7 +10,7 @@ import scala.reflect.ClassTag trait AssignScalarSpec { self: AnyFlatSpec with ScalaCheckDrivenPropertyChecks with Matchers => - behavior of "GrB_Vector_assign" + behavior of "GrB_Vector_assignScalar" testVectorAssignScalar[Boolean] testVectorAssignScalar[Byte] @@ -20,7 +20,7 @@ trait AssignScalarSpec { testVectorAssignScalar[Float] testVectorAssignScalar[Double] - def testVectorAssignScalar[T: SparseVectorHandler](implicit A: Arbitrary[VectorVals[T]], CT: ClassTag[T]) = { + def testVectorAssignScalar[T: SparseVectorHandler](implicit A: Arbitrary[VectorVals[T]], CT: ClassTag[T]): Unit = { it should s"create a vector of type ${CT.toString()}, assign a scalar value" in forAll { mt: VectorVals[T] => val handler = SparseVectorHandler[T] diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/ElemWiseSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/ElemWiseSpec.scala index e3a5eec..2340884 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/ElemWiseSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/ElemWiseSpec.scala @@ -13,14 +13,14 @@ trait ElemWiseSpec { behavior of "GrB_eWise*_Matrix" - eWiseMult[Byte] - eWiseMult[Short] - eWiseMult[Int] - eWiseMult[Long] - eWiseMult[Float] - eWiseMult[Double] - - def eWiseMult[T: SparseMatrixHandler: MonoidHandler:BinaryOpHandler](implicit A:Arbitrary[MatrixTuplesMul[T]], N: Numeric[T], CT: ClassTag[T]): Unit = { + eWiseMultMatrix[Byte] + eWiseMultMatrix[Short] + eWiseMultMatrix[Int] + eWiseMultMatrix[Long] + eWiseMultMatrix[Float] + eWiseMultMatrix[Double] + + def eWiseMultMatrix[T: SparseMatrixHandler : MonoidHandler : BinaryOpHandler](implicit A: Arbitrary[MatrixTuplesMul[T]], N: Numeric[T], CT: ClassTag[T]): Unit = { it should s"apply plus(A, B) for the intersection of all items on type ${CT.toString()}" in forAll { mt: MatrixTuplesMul[T] => val a = SparseMatrixHandler[T].buildMatrix(mt.left) @@ -63,4 +63,56 @@ trait ElemWiseSpec { ret2 shouldBe GRBCORE.GrB_SUCCESS } } + + + behavior of "GrB_eWise*_Vector" + + eWiseMultVector[Byte] + eWiseMultVector[Short] + eWiseMultVector[Int] + eWiseMultVector[Long] + eWiseMultVector[Float] + eWiseMultVector[Double] + + def eWiseMultVector[T: SparseVectorHandler : MonoidHandler : BinaryOpHandler](implicit A: Arbitrary[VectorValsMul[T]], N: Numeric[T], CT: ClassTag[T]): Unit = { + it should s"apply plus(A, B) for the intersection of all items on type ${CT.toString()}" in forAll { mt: VectorValsMul[T] => + + val a = SparseVectorHandler[T].buildVector(mt.left) + val b = SparseVectorHandler[T].buildVector(mt.right) + + val expectedSize = mt.left.vals.map(_._1).intersect(mt.right.vals.map(_._1)).size + + val c1 = SparseVectorHandler[T].createVector(mt.left.size) + val c2 = SparseVectorHandler[T].createVector(mt.left.size) + + val m = MonoidHandler[T].plus + val op = BinaryOpHandler[T].plus + + GRBOPSVEC.elemWiseMulIntersectMonoid(c1, null, null, m, a, b, null) shouldBe GRBCORE.GrB_SUCCESS + GRBOPSVEC.elemWiseMulIntersectBinOp(c2, null, null, op, a, b, null) shouldBe GRBCORE.GrB_SUCCESS + + GRBCORE.nvalsVector(c1) shouldBe expectedSize + GRBCORE.nvalsVector(c2) shouldBe expectedSize + } + + it should s"apply plus(A, B) for the union of all items on type ${CT.toString()}" in forAll { mt: VectorValsMul[T] => + + val a = SparseVectorHandler[T].buildVector(mt.left) + val b = SparseVectorHandler[T].buildVector(mt.right) + + val expectedSize = mt.left.vals.map(_._1).union(mt.right.vals.map(_._1)).toSet.size + + val c1 = SparseVectorHandler[T].createVector(mt.left.size) + val c2 = SparseVectorHandler[T].createVector(mt.left.size) + + val m = MonoidHandler[T].plus + val op = BinaryOpHandler[T].plus + + GRBOPSVEC.elemWiseAddUnionMonoid(c1, null, null, m, a, b, null) shouldBe GRBCORE.GrB_SUCCESS + GRBOPSVEC.elemWiseAddUnionBinOp(c2, null, null, op, a, b, null) shouldBe GRBCORE.GrB_SUCCESS + + GRBCORE.nvalsVector(c1) shouldBe expectedSize + GRBCORE.nvalsVector(c2) shouldBe expectedSize + } + } } diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SparseVectorHandler.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SparseVectorHandler.scala index ba26df3..25249e5 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SparseVectorHandler.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SparseVectorHandler.scala @@ -30,6 +30,7 @@ trait SparseVectorHandler[T] { def clear(vec: Buffer): Unit = GRBCORE.clearVec(vec) + def extractTuples(mat: Buffer): Array[T] } object SparseVectorHandler { @@ -44,6 +45,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Boolean): Unit = GRAPHBLAS.assignVectorBoolean(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Boolean] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Boolean](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesBoolean(vec, vs, is) + vs + } } implicit val byteVectorHandler: SparseVectorHandler[Byte] = new SparseVectorHandler[Byte] { @@ -55,6 +64,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Byte): Unit = GRAPHBLAS.assignVectorByte(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Byte] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Byte](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesByte(vec, vs, is) + vs + } } implicit val shortVectorHandler: SparseVectorHandler[Short] = new SparseVectorHandler[Short] { @@ -66,6 +83,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Short): Unit = GRAPHBLAS.assignVectorShort(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Short] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Short](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesShort(vec, vs, is) + vs + } } implicit val intVectorHandler: SparseVectorHandler[Int] = new SparseVectorHandler[Int] { @@ -77,6 +102,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Int): Unit = GRAPHBLAS.assignVectorInt(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Int] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Int](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesInt(vec, vs, is) + vs + } } implicit val longVectorHandler: SparseVectorHandler[Long] = new SparseVectorHandler[Long] { @@ -88,6 +121,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Long): Unit = GRAPHBLAS.assignVectorLong(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Long] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Long](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesLong(vec, vs, is) + vs + } } implicit val floatVectorHandler: SparseVectorHandler[Float] = new SparseVectorHandler[Float] { @@ -99,6 +140,14 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Float): Unit = GRAPHBLAS.assignVectorFloat(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Float] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Float](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesFloat(vec, vs, is) + vs + } } implicit val doubleVectorHandler: SparseVectorHandler[Double] = new SparseVectorHandler[Double] { @@ -110,5 +159,13 @@ object SparseVectorHandler { def assign(vec: Buffer)(v: Double): Unit = GRAPHBLAS.assignVectorDouble(vec, null, null, v, GRBCORE.GrB_ALL, size(vec), null) + + def extractTuples(vec: Buffer): Array[Double] = { + val nvals = GRBCORE.nvalsVector(vec) + val vs = new Array[Double](nvals.toInt) + val is = new Array[Long](nvals.toInt) + GRAPHBLAS.extractVectorTuplesDouble(vec, vs, is) + vs + } } } diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/VectorUtils.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/VectorUtils.scala index 799e7c1..a2607c9 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/VectorUtils.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/VectorUtils.scala @@ -39,6 +39,10 @@ trait VectorUtils { case class VectorVals[T](size: Long, vals: Vector[(Long, T)]) +// tuples for multiplication +case class VectorValsMul[T](left: VectorVals[T], right: VectorVals[T]) + + object VectorVals { implicit def fakeChooseBoolean: Gen.Choose[Boolean] = (min: Boolean, max: Boolean) => { @@ -56,7 +60,7 @@ object VectorVals { } yield (i, t) val gen = for { - size <- Gen.posNum[Long] + size <- Gen.choose(1, 100) vals <- Gen.nonEmptyContainerOf[Vector, (Long, Boolean)](genVal(size)).map(_.distinctBy(_._1)) } yield VectorVals(size, vals) @@ -78,7 +82,24 @@ object VectorVals { } } +object VectorValsMul { + implicit def arbMul[T: Gen.Choose](implicit A: Arbitrary[VectorDimensions], N: Numeric[T]): Arbitrary[VectorValsMul[T]] = { + def genVal(size: Long): Gen[(Long, T)] = for { + i <- Gen.choose(0, size - 1) + t <- Gen.oneOf[T](Gen.posNum, Gen.negNum) + } yield (i, t) + + val gen = for { + size <- Gen.choose(1, 100) + vals <- Gen.nonEmptyContainerOf[Vector, (Long, T)](genVal(size)).map(_.distinctBy(_._1)) + otherVals <- Gen.nonEmptyContainerOf[Vector, (Long, T)](genVal(size)).map(_.distinctBy(_._1)) + } yield VectorValsMul(VectorVals[T](size, vals), VectorVals(size, otherVals)) + + Arbitrary(gen) + } +} + case class VectorDimensions(size: Int) object VectorDimensions{ implicit val arb:Arbitrary[VectorDimensions] = Arbitrary(Gen.posNum[Int].map(VectorDimensions(_))) -} \ No newline at end of file +} From 94278c11c660b42cdc50e0e7f600385784842ad0 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Wed, 16 Sep 2020 16:39:48 +0200 Subject: [PATCH 4/8] Allow null as GrB_ALL replacement in vector-extract --- graphblas-java/src/main/c/unsafe_ops.c | 28 +++++++++++++------ .../unsafe/AssignExtractSpec.scala | 10 +++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/graphblas-java/src/main/c/unsafe_ops.c b/graphblas-java/src/main/c/unsafe_ops.c index f686908..626b49e 100644 --- a/graphblas-java/src/main/c/unsafe_ops.c +++ b/graphblas-java/src/main/c/unsafe_ops.c @@ -286,10 +286,9 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); jlong *java_is; + // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index *I = NULL; - java_is = (*env)->GetLongArrayElements(env, is, NULL); - GrB_Index sizei; if (grb_ni == GxB_RANGE) { @@ -300,10 +299,22 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract sizei = grb_ni; } - I = malloc (sizei * sizeof (GrB_Index)) ; + GrB_Index vectorSize; + check_grb_error(GrB_Vector_size(&vectorSize, first)); - for (int i = 0; i < sizei; i++) { - I[i] = (GrB_Index)java_is[i]; + if (vectorSize == grb_ni || is == NULL) { + I = GrB_ALL; + } + else { + java_is = (*env)->GetLongArrayElements(env, is, NULL); + + I = malloc (sizei * sizeof (GrB_Index)); + + for (int i = 0; i < sizei; i++) { + I[i] = (GrB_Index)java_is[i]; + } + + (*env)->ReleaseLongArrayElements(env, is, java_is, 0); } // Optionals @@ -311,10 +322,11 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; - long res = check_grb_error(GrB_extract(out, m, acc, first, I, grb_ni, d)); + long res = check_grb_error(GrB_Vector_extract(out, m, acc, first, I, grb_ni, d)); - (*env)->ReleaseLongArrayElements(env, is, java_is, 0); - free(I); + if (I != GrB_ALL) { + free(I); + } return res; diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala index f83d9c3..37a08bf 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala @@ -90,6 +90,16 @@ trait AssignExtractSpec { SparseVectorHandler[T].extractTuples(into) should contain theSameElementsAs expected } + + it should s"call GrB_extract all for GrB_Vector of type ${CT.toString()}" in forAll { mt: VectorVals[T] => + val vec = SparseVectorHandler[T].buildVector(mt) + + val into = SparseVectorHandler[T].createVector(mt.size) + + GRBOPSVEC.extract(into, null, null, vec, null, mt.size, null) shouldBe GRBCORE.GrB_SUCCESS + + SparseVectorHandler[T].extractTuples(into) should contain theSameElementsAs SparseVectorHandler[T].extractTuples(vec) + } } // behavior of "GrB_assign" From 91d02ea593eb7627db555e450d938f6476d08b3f Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Wed, 16 Sep 2020 17:35:17 +0200 Subject: [PATCH 5/8] Allow null as GrB_ALL replacement in vector-assign --- graphblas-java/src/main/c/unsafe_ops.c | 39 ++++++++++++------- .../unsafe/AssignExtractSpec.scala | 22 +++++++++++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/graphblas-java/src/main/c/unsafe_ops.c b/graphblas-java/src/main/c/unsafe_ops.c index 626b49e..f0ec6f3 100644 --- a/graphblas-java/src/main/c/unsafe_ops.c +++ b/graphblas-java/src/main/c/unsafe_ops.c @@ -424,27 +424,35 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_assign GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); - jlong *java_is; GrB_Index *I = NULL; - java_is = (*env)->GetLongArrayElements(env, is, NULL); + GrB_Index vectorSize; + check_grb_error(GrB_Vector_size(&vectorSize, first)); - GrB_Index sizei; - if (grb_ni == GxB_RANGE) { - sizei = 2; - } else if (grb_ni == GxB_BACKWARDS || grb_ni == GxB_STRIDE){ - sizei = 3; - } else { - sizei = grb_ni; + if (vectorSize == grb_ni || is == NULL) { + I = GrB_ALL; } + else { + jlong *java_is = (*env)->GetLongArrayElements(env, is, NULL); + + GrB_Index sizei; + if (grb_ni == GxB_RANGE) { + sizei = 2; + } else if (grb_ni == GxB_BACKWARDS || grb_ni == GxB_STRIDE){ + sizei = 3; + } else { + sizei = grb_ni; + } - I = malloc (sizei * sizeof (GrB_Index)) ; + I = malloc (sizei * sizeof (GrB_Index)) ; - for (int i = 0; i < sizei; i++) { - I[i] = (GrB_Index)java_is[i]; - } + for (int i = 0; i < sizei; i++) { + I[i] = (GrB_Index)java_is[i]; + } + (*env)->ReleaseLongArrayElements(env, is, java_is, 0); + } // Optionals GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; @@ -452,8 +460,9 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_assign long res = check_grb_error(GrB_assign(out, m, acc, first, I, grb_ni, d)); - (*env)->ReleaseLongArrayElements(env, is, java_is, 0); - free(I); + if(I != GrB_ALL) { + free(I); + } return res; diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala index 37a08bf..504530b 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala @@ -102,6 +102,28 @@ trait AssignExtractSpec { } } + behavior of "GrB_Vector_assign" + + testGrBVectorAssign[Boolean] + testGrBVectorAssign[Byte] + testGrBVectorAssign[Short] + testGrBVectorAssign[Int] + testGrBVectorAssign[Long] + testGrBVectorAssign[Float] + testGrBVectorAssign[Double] + + private def testGrBVectorAssign[T: SparseVectorHandler](implicit A: Arbitrary[VectorVals[T]], CT: ClassTag[T]): Unit = { + it should s"call GrB_assign for GrB_Vector of type ${CT.toString()} and assign everything" in forAll { mt: VectorVals[T] => + val vec = SparseVectorHandler[T].buildVector(mt) + + val output = SparseVectorHandler[T].createVector(mt.size) + + GRBOPSVEC.assign(output, null, null, vec, null, mt.size, null) + + SparseVectorHandler[T].extractTuples(output) should contain theSameElementsAs SparseVectorHandler[T].extractTuples(vec) + } + } + // behavior of "GrB_assign" // // testGrBMatrixAssign[Boolean] From 1857a1f8d61b3f0ea7a5d33ddac7fdc7ace89de5 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Wed, 16 Sep 2020 21:28:51 +0200 Subject: [PATCH 6/8] Add most of matrix select + pre defined select ops .. ! Thunk not mapped yet --- graphblas-java/src/main/c/unsafe_gen.c | 41 +++++++++++++++++++ graphblas-java/src/main/c/unsafe_ops.c | 20 ++++++++- graphblas-java/src/main/data.json | 14 ++++++- .../fabianmurariu/unsafe/GRAPHBLAS.java | 13 ++++++ .../fabianmurariu/unsafe/GRBOPSMAT.java | 15 +++++++ .../src/main/templates/c/unsafe_gen.c.ftl | 7 ++++ graphblas-java/src/main/templates/data.json | 14 ++++++- .../fabianmurariu/unsafe/GRAPHBLAS.java.ftl | 6 +++ .../fabianmurariu/unsafe/GRAPHBLASSpec.scala | 3 +- .../fabianmurariu/unsafe/SelectSpec.scala | 31 ++++++++++++++ 10 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala diff --git a/graphblas-java/src/main/c/unsafe_gen.c b/graphblas-java/src/main/c/unsafe_gen.c index 296f160..6e669dc 100644 --- a/graphblas-java/src/main/c/unsafe_gen.c +++ b/graphblas-java/src/main/c/unsafe_gen.c @@ -2713,3 +2713,44 @@ JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRBMONOID_createM (JNIEnv * env, jclass cls){ return (*env)->NewDirectByteBuffer(env, GxB_EQ_BOOL_MONOID, 0); } + + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpTRIL + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_TRIL, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpTRIU + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_TRIU, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpDIAG + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_DIAG, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpOFFDIAG + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_OFFDIAG, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpNONZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_NONZERO, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpEQ_ZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_EQ_ZERO, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpGT_ZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_GT_ZERO, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpGE_ZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_GE_ZERO, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpLT_ZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_LT_ZERO, 0); + } + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOpLE_ZERO + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_LE_ZERO, 0); + } diff --git a/graphblas-java/src/main/c/unsafe_ops.c b/graphblas-java/src/main/c/unsafe_ops.c index f0ec6f3..38559aa 100644 --- a/graphblas-java/src/main/c/unsafe_ops.c +++ b/graphblas-java/src/main/c/unsafe_ops.c @@ -558,8 +558,8 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_subAssign grb_ni = ni == java_max-1 ? GxB_STRIDE : (GrB_Index) ni; grb_ni = ni == java_max-2 ? GxB_BACKWARDS : (GrB_Index) ni; - GrB_Matrix out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - GrB_Matrix first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); + GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); + GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); jlong *java_is; GrB_Index *I = NULL; @@ -594,6 +594,22 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_subAssign return res; } +JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_select + (JNIEnv * env, jclass cls, jobject C, jobject mask, jobject accum, jobject op, jobject A, jobject Thunk, jobject desc) { + // Non-optionals + GrB_Matrix out = (GrB_Matrix) (*env)->GetDirectBufferAddress(env, C); + GrB_Matrix first = (GrB_Matrix) (*env)->GetDirectBufferAddress(env, A); + GxB_SelectOp grb_op = (GxB_SelectOp) (*env)->GetDirectBufferAddress(env, op); + + // Optionals + GrB_Vector m = mask != NULL ? (GrB_Vector) (*env)->GetDirectBufferAddress(env, mask) : NULL ; + GrB_BinaryOp acc = accum != NULL ? (GrB_BinaryOp) (*env)->GetDirectBufferAddress(env, accum) : NULL; + GrB_Descriptor d = desc != NULL ? (GrB_Descriptor) (*env)->GetDirectBufferAddress(env, desc) : NULL; + GxB_Scalar grb_thunk = NULL; + + return check_grb_error(GxB_Matrix_select(out, m, acc, grb_op, first, grb_thunk, d)); + } + JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSMAT_matrixReduceBinOp (JNIEnv * env, jclass cls, jobject vec, jobject mask, jobject accum, jobject bin_op, jobject A, jobject desc) { GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); diff --git a/graphblas-java/src/main/data.json b/graphblas-java/src/main/data.json index 8ee4a1b..16f18c4 100644 --- a/graphblas-java/src/main/data.json +++ b/graphblas-java/src/main/data.json @@ -92,5 +92,17 @@ "java_type": "double", "c_type": "double" } + ], + "select_ops": [ + "TRIL", + "TRIU", + "DIAG", + "OFFDIAG", + "NONZERO", + "EQ_ZERO", + "GT_ZERO", + "GE_ZERO", + "LT_ZERO", + "LE_ZERO" ] -} \ No newline at end of file +} diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java index 34361f9..382168c 100644 --- a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java @@ -334,4 +334,17 @@ public final class GRAPHBLAS { public static native Buffer lorBinaryOp(); public static native Buffer landBinaryOp(); public static native Buffer lxorBinaryOp(); + +// SelectOps (GraphBLAS extension) +// TODO list all pre-defined select ops + public static native Buffer selectOpTRIL(); + public static native Buffer selectOpTRIU(); + public static native Buffer selectOpDIAG(); + public static native Buffer selectOpOFFDIAG(); + public static native Buffer selectOpNONZERO(); + public static native Buffer selectOpEQ_ZERO(); + public static native Buffer selectOpGT_ZERO(); + public static native Buffer selectOpGE_ZERO(); + public static native Buffer selectOpLT_ZERO(); + public static native Buffer selectOpLE_ZERO(); } diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSMAT.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSMAT.java index 1f37b0c..5619507 100644 --- a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSMAT.java +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBOPSMAT.java @@ -154,6 +154,21 @@ public class GRBOPSMAT { */ public static native long extract(Buffer C, Buffer mask, Buffer accum, Buffer A, long[] I, long ni, long[] J, long nj, Buffer desc); + /** + * {@code C = accum (C, op(A,k)) or op(A’,k)} + * + * @param C input/output matrix for results + * @param mask optional mask for C, unused if NULL + * @param accum optional accum for Z=accum(C,T) + * @param op operator to apply to the entries + * @param A first input: matrix A + * @param Thunk Optional .. not mapped yet! + * @param desc descriptor for C, mask, and A + * @return + */ + public static native long select(Buffer C, Buffer mask, Buffer accum, Buffer op, Buffer A, Buffer Thunk, Buffer desc); + + // w = accum (w,reduce(A)) // input/output vector for results // optional mask for w, unused if NULL diff --git a/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl b/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl index 59c7313..f6dd32d 100644 --- a/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl +++ b/graphblas-java/src/main/templates/c/unsafe_gen.c.ftl @@ -302,3 +302,10 @@ JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRBMONOID_createM return (*env)->NewDirectByteBuffer(env, ${op.grb_name}_BOOL_MONOID, 0); } + + <#list properties.select_ops as op> + JNIEXPORT jobject JNICALL Java_com_github_fabianmurariu_unsafe_GRAPHBLAS_selectOp${op} + (JNIEnv * env, jclass cls){ + return (*env)->NewDirectByteBuffer(env, GxB_${op}, 0); + } + diff --git a/graphblas-java/src/main/templates/data.json b/graphblas-java/src/main/templates/data.json index 8ee4a1b..16f18c4 100644 --- a/graphblas-java/src/main/templates/data.json +++ b/graphblas-java/src/main/templates/data.json @@ -92,5 +92,17 @@ "java_type": "double", "c_type": "double" } + ], + "select_ops": [ + "TRIL", + "TRIU", + "DIAG", + "OFFDIAG", + "NONZERO", + "EQ_ZERO", + "GT_ZERO", + "GE_ZERO", + "LT_ZERO", + "LE_ZERO" ] -} \ No newline at end of file +} diff --git a/graphblas-java/src/main/templates/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java.ftl b/graphblas-java/src/main/templates/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java.ftl index 1ba4c4d..0b96dc2 100644 --- a/graphblas-java/src/main/templates/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java.ftl +++ b/graphblas-java/src/main/templates/java/com/github/fabianmurariu/unsafe/GRAPHBLAS.java.ftl @@ -54,4 +54,10 @@ public final class GRAPHBLAS { <#list properties.binary_ops_bool_bool as op> public static native Buffer ${op.name}BinaryOp(); + +// SelectOps (GraphBLAS extension) +// TODO list all pre-defined select ops +<#list properties.select_ops as op> + public static native Buffer selectOp${op}(); + } diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala index 62c2049..c16db20 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/GRAPHBLASSpec.scala @@ -16,7 +16,8 @@ class GRAPHBLASSpec extends AnyFlatSpec with ScalaCheckDrivenPropertyChecks with with MxmSpec with AssignExtractSpec with AssignScalarSpec - with ElemWiseSpec { + with ElemWiseSpec + with SelectSpec { behavior of "GrB_Matrix" diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala new file mode 100644 index 0000000..8cbe18d --- /dev/null +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala @@ -0,0 +1,31 @@ +package com.github.fabianmurariu.unsafe + +import java.nio.Buffer + +import org.scalacheck.Arbitrary +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks + +import scala.reflect.ClassTag + +trait SelectSpec { + self: AnyFlatSpec with ScalaCheckDrivenPropertyChecks with Matchers => + + behavior of "GrB_Matrix_select" + + testMatrixSelect[Boolean] + + private def testMatrixSelect[T: SparseMatrixHandler](implicit A:Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { + it should s"call GrB_select for GrB_Matrix of type ${CT.toString()}" in forAll { mt: MatrixTuples[T] => + val mat = SparseMatrixHandler[T].buildMatrix(mt) + val out = SparseMatrixHandler[T].createMatrix(mt.dim.rows, mt.dim.cols) + + val selectOp = GRAPHBLAS.selectOpDIAG() + GRBOPSMAT.select(out, null, null, selectOp, mat, null, null) shouldBe GRBCORE.GrB_SUCCESS + + // check could be improved + mt.vals.filter(p => (p._1 == p._2)).size shouldBe GRBCORE.nvalsMatrix(out) + } + } +} From 9295fb6c61cadfc9c4c9e84bd04d2ea5eb49ddf1 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Fri, 18 Sep 2020 13:44:03 +0200 Subject: [PATCH 7/8] Use GrB_ALL instead of null --- graphblas-java/src/main/c/unsafe_gen.c | 7 ------- graphblas-java/src/main/c/unsafe_ops.c | 18 ++++++------------ .../unsafe/AssignExtractSpec.scala | 4 ++-- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/graphblas-java/src/main/c/unsafe_gen.c b/graphblas-java/src/main/c/unsafe_gen.c index 6e669dc..0910209 100644 --- a/graphblas-java/src/main/c/unsafe_gen.c +++ b/graphblas-java/src/main/c/unsafe_gen.c @@ -1277,7 +1277,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1318,7 +1317,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1359,7 +1357,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1400,7 +1397,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1441,7 +1437,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1482,7 +1477,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); @@ -1523,7 +1517,6 @@ long check_grb_error(GrB_Info info); // NON OPTIONAL STUFF GrB_Vector w = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java GrB_Index* I = NULL; GrB_Index grb_ni = (GrB_Index) ni; jlong * java_is = (*env)->GetLongArrayElements(env, is, NULL); diff --git a/graphblas-java/src/main/c/unsafe_ops.c b/graphblas-java/src/main/c/unsafe_ops.c index 38559aa..cd4a940 100644 --- a/graphblas-java/src/main/c/unsafe_ops.c +++ b/graphblas-java/src/main/c/unsafe_ops.c @@ -285,8 +285,7 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract GrB_Vector out = (GrB_Vector) (*env)->GetDirectBufferAddress(env, vec); GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); - jlong *java_is; - // !DIFFERENCE: ni == vector size -> GrB_ALL .. as no way to get pointer to GrB_ALL object in java + jlong *java_is = (*env)->GetLongArrayElements(env, is, NULL); GrB_Index *I = NULL; GrB_Index sizei; @@ -299,15 +298,12 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_extract sizei = grb_ni; } - GrB_Index vectorSize; - check_grb_error(GrB_Vector_size(&vectorSize, first)); + long java_min = -9223372036854775808; - if (vectorSize == grb_ni || is == NULL) { + if (java_is[0] == java_min) { I = GrB_ALL; } else { - java_is = (*env)->GetLongArrayElements(env, is, NULL); - I = malloc (sizei * sizeof (GrB_Index)); for (int i = 0; i < sizei; i++) { @@ -425,17 +421,15 @@ JNIEXPORT jlong JNICALL Java_com_github_fabianmurariu_unsafe_GRBOPSVEC_assign GrB_Vector first = (GrB_Vector) (*env)->GetDirectBufferAddress(env, u); GrB_Index *I = NULL; + jlong *java_is = (*env)->GetLongArrayElements(env, is, NULL); - GrB_Index vectorSize; - check_grb_error(GrB_Vector_size(&vectorSize, first)); + long java_min = -9223372036854775808; - if (vectorSize == grb_ni || is == NULL) { + if (java_is[0] == java_min) { I = GrB_ALL; } else { - jlong *java_is = (*env)->GetLongArrayElements(env, is, NULL); - GrB_Index sizei; if (grb_ni == GxB_RANGE) { sizei = 2; diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala index 504530b..c7e275f 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala @@ -96,7 +96,7 @@ trait AssignExtractSpec { val into = SparseVectorHandler[T].createVector(mt.size) - GRBOPSVEC.extract(into, null, null, vec, null, mt.size, null) shouldBe GRBCORE.GrB_SUCCESS + GRBOPSVEC.extract(into, null, null, vec, GRBCORE.GrB_ALL, mt.size, null) shouldBe GRBCORE.GrB_SUCCESS SparseVectorHandler[T].extractTuples(into) should contain theSameElementsAs SparseVectorHandler[T].extractTuples(vec) } @@ -118,7 +118,7 @@ trait AssignExtractSpec { val output = SparseVectorHandler[T].createVector(mt.size) - GRBOPSVEC.assign(output, null, null, vec, null, mt.size, null) + GRBOPSVEC.assign(output, null, null, vec, GRBCORE.GrB_ALL, mt.size, null) SparseVectorHandler[T].extractTuples(output) should contain theSameElementsAs SparseVectorHandler[T].extractTuples(vec) } From 63b3e2e4e3e2aed5ed22154e3b713edebe50b240 Mon Sep 17 00:00:00 2001 From: FlorentinD Date: Wed, 23 Sep 2020 10:31:18 +0200 Subject: [PATCH 8/8] Improve select test and remove commented out constants --- .../com/github/fabianmurariu/unsafe/GRBCORE.java | 12 ------------ .../fabianmurariu/unsafe/AssignExtractSpec.scala | 15 ++------------- .../github/fabianmurariu/unsafe/SelectSpec.scala | 4 +++- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java index 71a7545..9860455 100644 --- a/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java +++ b/graphblas-java/src/main/java/com/github/fabianmurariu/unsafe/GRBCORE.java @@ -124,18 +124,6 @@ public final class GRBCORE { public static int GxB_MODE = 2; // mode passed to GrB_init (blocking or non-blocking) public static int GxB_THREAD_SAFETY = 3; // thread library that allows GraphBLAS to be thread-safe for user threads. public static int GxB_THREADING = 4; // thread library used for internal GraphBLAS threads - //public static int GxB_LIBRARY_NAME = 8; // name of the library (char *) - //public static int GxB_LIBRARY_VERSION = 9; // library version (3 int's) - //public static int GxB_LIBRARY_DATE = 10; // date of the library (char *) - //public static int GxB_LIBRARY_ABOUT = 11; // about the library (char *) - //public static int GxB_LIBRARY_URL = 12; // URL for the library (char *) - //public static int GxB_LIBRARY_LICENSE = 13; // license of the library (char *) - //public static int GxB_LIBRARY_COMPILE_DATE = 14; // date library was compiled (char *) - //public static int GxB_LIBRARY_COMPILE_TIME = 15; // time library was compiled (char *) - //public static int GxB_API_VERSION = 16; // API version (3 int's) - //public static int GxB_API_DATE = 17; // date of the API (char *) - //public static int GxB_API_ABOUT = 18; // about the API (char *) - //public static int GxB_API_URL = 19; // URL for the API (char *) // Values // for GxB_FORMAT diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala index c7e275f..0f19309 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/AssignExtractSpec.scala @@ -1,7 +1,5 @@ package com.github.fabianmurariu.unsafe -import java.nio.Buffer - import org.scalacheck.Arbitrary import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -124,16 +122,7 @@ trait AssignExtractSpec { } } -// behavior of "GrB_assign" -// -// testGrBMatrixAssign[Boolean] -// testGrBMatrixAssign[Byte] -// testGrBMatrixAssign[Short] -// testGrBMatrixAssign[Int] -// testGrBMatrixAssign[Long] -// testGrBMatrixAssign[Float] -// testGrBMatrixAssign[Double] - + // FIXME: somehow assign throws an GrB_DIMENSION_MISMATCH private def testGrBMatrixAssign[T: SparseMatrixHandler](implicit A: Arbitrary[MatrixTuples[T]], CT: ClassTag[T]): Unit = { it should s"call GrB_assign for GrB_Matrix of type ${CT.toString()}" in forAll { mt: MatrixTuples[T] => val mat = SparseMatrixHandler[T].buildMatrix(mt) @@ -145,7 +134,7 @@ trait AssignExtractSpec { val ni: Vector[Long] = dRight.map(_._1) val nj: Vector[Long] = dRight.map(_._2) - val into = SparseMatrixHandler[T].createMatrix(ni.size, nj.size) + val into = SparseMatrixHandler[T].createMatrix(mt.dim.rows, mt.dim.cols) val res = GRBOPSMAT.assign(into, null, null, mat, ni.toArray, ni.size, nj.toArray, nj.size, null) assert(res == 0) diff --git a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala index 8cbe18d..83c20a6 100644 --- a/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala +++ b/graphblas-java/src/test/scala/com/github/fabianmurariu/unsafe/SelectSpec.scala @@ -25,7 +25,9 @@ trait SelectSpec { GRBOPSMAT.select(out, null, null, selectOp, mat, null, null) shouldBe GRBCORE.GrB_SUCCESS // check could be improved - mt.vals.filter(p => (p._1 == p._2)).size shouldBe GRBCORE.nvalsMatrix(out) + val actual = SparseMatrixHandler[T].extractAllTuples(out) + val expected = mt.vals.filter(p => (p._1 == p._2)) + actual should contain theSameElementsAs expected } } }