From 80a3899e79f08b183e4866d887ccfc68b57f6e14 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Thu, 25 Mar 2021 19:59:47 +0530 Subject: [PATCH 01/14] add csr matrix --- ext/csr/csr_def.c | 143 ++++++++++++++++++++++++++++++++++++++++++ ext/csr/elementwise.c | 132 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 ext/csr/csr_def.c create mode 100644 ext/csr/elementwise.c diff --git a/ext/csr/csr_def.c b/ext/csr/csr_def.c new file mode 100644 index 0000000..0048224 --- /dev/null +++ b/ext/csr/csr_def.c @@ -0,0 +1,143 @@ +VALUE csr_init(int argc, VALUE* argv, VALUE self) { + csr_matrix* mat; + Data_Get_Struct(self, csr_matrix, mat); + + if(argc > 0){ + mat->dtype = sp_float64; + mat->ndims = 2; + mat->count = (size_t)RARRAY_LEN(argv[1]); + mat->shape = ALLOC_N(size_t, mat->ndims); + for(size_t index = 0; index < mat->ndims; index++) { + mat->shape[index] = (size_t)FIX2LONG(RARRAY_AREF(argv[0], index)); + } + mat->elements = ALLOC_N(double, mat->count); + mat->ip = ALLOC_N(size_t, mat->shape[0] + 1); + mat->ja = ALLOC_N(size_t, mat->count); + for(size_t index = 0; index <= mat->shape[0]; index++) mat->ip[index] = 0; + for(size_t index = 0; index < mat->count; index++) { + size_t row_index_val = (size_t)NUM2SIZET(RARRAY_AREF(argv[2], index)); + mat->ip[row_index_val] += 1; + } + for(size_t index = 0, cumsum = 0; index < mat->shape[0]; index++) { + size_t temp = mat->ip[index]; + mat->ip[index] = cumsum; + cumsum += temp; + } + mat->ip[mat->shape[0]] = mat->count; + for(size_t index = 0; index < mat->count; index++) { + size_t row = (size_t)NUM2SIZET(RARRAY_AREF(argv[2], index)); + size_t dest = mat->ip[row]; + + mat->ja[dest] = (size_t)NUM2SIZET(RARRAY_AREF(argv[3], index)); + mat->elements[dest] = (double)NUM2DBL(RARRAY_AREF(argv[1], index)); + + mat->ip[row] += 1; + } + + for(size_t index = 0, last = 0; index <= mat->shape[0]; index++) { + size_t temp = mat->ip[index]; + mat->ip[index] = last; + last = temp; + } + } + + return self; +} + + +VALUE csr_alloc(VALUE klass) { + csr_matrix* mat = ALLOC(csr_matrix); + + return Data_Wrap_Struct(klass, NULL, csr_free, mat); +} + + +void csr_free(csr_matrix* mat) { + xfree(mat); +} + + +VALUE csr_get_elements(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + VALUE* array = ALLOC_N(VALUE, input->count); + for (size_t index = 0; index < input->count; index++) { + array[index] = DBL2NUM(input->elements[index]); + } + + return rb_ary_new4(input->count, array); +} + + +VALUE csr_get_indices(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + VALUE* array_ja = ALLOC_N(VALUE, input->count); + for (size_t index = 0; index < input->count; index++) { + array_ja[index] = SIZET2NUM(input->ja[index]); + } + + return rb_ary_new4(input->count, array_ja); +} + + +VALUE csr_get_indptr(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + VALUE* array_ip = ALLOC_N(VALUE, input->shape[0] + 1); + for (size_t index = 0; index <= input->shape[0]; index++) { + array_ip[index] = SIZET2NUM(input->ip[index]); + } + + return rb_ary_new4(input->shape[0] + 1, array_ip); +} + + +VALUE csr_get_count(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + return SIZET2NUM(input->count); +} + + +VALUE csr_get_ndims(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + return SIZET2NUM(input->ndims); +} + + +VALUE csr_get_dtype(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); +} + + +VALUE csr_get_shape(VALUE self) { + csr_matrix* input; + + Data_Get_Struct(self, csr_matrix, input); + + VALUE* array = ALLOC_N(VALUE, input->ndims); + for (size_t index = 0; index < input->ndims; index++) { + array[index] = SIZET2NUM(input->shape[index]); + } + + return rb_ary_new4(input->ndims, array); +} + + +#include "elementwise.c" \ No newline at end of file diff --git a/ext/csr/elementwise.c b/ext/csr/elementwise.c new file mode 100644 index 0000000..2a0ed57 --- /dev/null +++ b/ext/csr/elementwise.c @@ -0,0 +1,132 @@ +double csr_perform_oper(double val_a, double val_b, char oper) { + switch(oper) { + case '+': + return (val_a + val_b); + case '-': + return (val_a - val_b); + case '*': + return (val_a * val_b); + default: //unknown operator + return 0.00; + } +} + + +/* + Takes two matrices and performs operator elementwise +*/ +VALUE csr_elementwise_binary(VALUE self, VALUE another, char oper) { + csr_matrix* left; + csr_matrix* right; + Data_Get_Struct(self, csr_matrix, left); + Data_Get_Struct(another, csr_matrix, right); + + csr_matrix* result = ALLOC(csr_matrix); + result->count = 0; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, 2 * left->count); + result->ip = ALLOC_N(size_t, left->shape[0] + 1); + result->ja = ALLOC_N(size_t, 2 * left->count); + + for(size_t index = 0; index <= result->shape[0]; index++) result->ip[index] = 0; + + size_t left_index = 0, right_index = 0, result_index = 0; + for(size_t index = 1; index <= result->shape[0]; index++) { + size_t left_row_ele_count = left->ip[index]; + size_t right_row_ele_count = right->ip[index]; + + while (left_index < left_row_ele_count && right_index < right_row_ele_count) { + if (left->ja[left_index] == right->ja[right_index]) { //left and right indices equal + double result_val = csr_perform_oper(left->elements[left_index], right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++, right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ja[result_index] = left->ja[left_index]; + + left_index++, right_index++, result_index++; + } + else if (left->ja[left_index] < right->ja[right_index]) { //left index smaller + double result_val = csr_perform_oper(left->elements[left_index], 0.0, oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ja[result_index] = left->ja[left_index]; + + left_index++, result_index++; + } + else { //right index smaller + double result_val = csr_perform_oper(0.0, right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = right->ia[right_index]; + result->ja[result_index] = right->ja[right_index]; + + right_index++, result_index++; + } + + result->count++; + result->ip[index] += 1; + } + + while (left_index < left_row_ele_count) { + double result_val = csr_perform_oper(left->elements[left_index], 0.0, oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ja[result_index] = left->ja[left_index]; + + left_index++, result_index++; + result->count++; + result->ip[index] += 1; + } + + while (right_index < right_row_ele_count) { + double result_val = csr_perform_oper(0.0, right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = right->ia[right_index]; + result->ja[result_index] = right->ja[right_index]; + + right_index++, result_index++; + result->count++; + result->ip[index] += 1; + } + + result->ip[index] += result->ip[index - 1]; + } + + return Data_Wrap_Struct(CSR, NULL, csr_free, result); +} + +VALUE csr_add(VALUE self, VALUE another) { + return csr_elementwise_binary(self, another, '+'); +} + +VALUE csr_sub(VALUE self, VALUE another) { + return csr_elementwise_binary(self, another, '-'); +} + +VALUE csr_mul(VALUE self, VALUE another) { + return csr_elementwise_binary(self, another, '*'); +} \ No newline at end of file From 99bb81a0d27f75b0d7e88cdb90ad20c5e9ce8533 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Thu, 25 Mar 2021 20:00:06 +0530 Subject: [PATCH 02/14] add csc matrix --- ext/csc/csc_def.c | 143 ++++++++++++++++++++++++++++++++++++++++++ ext/csc/elementwise.c | 132 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 ext/csc/csc_def.c create mode 100644 ext/csc/elementwise.c diff --git a/ext/csc/csc_def.c b/ext/csc/csc_def.c new file mode 100644 index 0000000..e48a5c5 --- /dev/null +++ b/ext/csc/csc_def.c @@ -0,0 +1,143 @@ +VALUE csc_init(int argc, VALUE* argv, VALUE self) { + csc_matrix* mat; + Data_Get_Struct(self, csc_matrix, mat); + + if(argc > 0){ + mat->dtype = sp_float64; + mat->ndims = 2; + mat->count = (size_t)RARRAY_LEN(argv[1]); + mat->shape = ALLOC_N(size_t, mat->ndims); + for(size_t index = 0; index < mat->ndims; index++) { + mat->shape[index] = (size_t)FIX2LONG(RARRAY_AREF(argv[0], index)); + } + mat->elements = ALLOC_N(double, mat->count); + mat->ia = ALLOC_N(size_t, mat->count); + mat->jp = ALLOC_N(size_t, mat->shape[1] + 1); + for(size_t index = 0; index <= mat->shape[1]; index++) mat->jp[index] = 0; + for(size_t index = 0; index < mat->count; index++) { + size_t col_index_val = (size_t)NUM2SIZET(RARRAY_AREF(argv[3], index)); + mat->jp[col_index_val] += 1; + } + for(size_t index = 0, cumsum = 0; index < mat->shape[1]; index++) { + size_t temp = mat->jp[index]; + mat->jp[index] = cumsum; + cumsum += temp; + } + mat->jp[mat->shape[1]] = mat->count; + for(size_t index = 0; index < mat->count; index++) { + size_t col = (size_t)NUM2SIZET(RARRAY_AREF(argv[3], index)); + size_t dest = mat->jp[col]; + + mat->ia[dest] = (size_t)NUM2SIZET(RARRAY_AREF(argv[2], index)); + mat->elements[dest] = (double)NUM2DBL(RARRAY_AREF(argv[1], index)); + + mat->jp[col] += 1; + } + + for(size_t index = 0, last = 0; index <= mat->shape[1]; index++) { + size_t temp = mat->jp[index]; + mat->jp[index] = last; + last = temp; + } + } + + return self; +} + + +VALUE csc_alloc(VALUE klass) { + csc_matrix* mat = ALLOC(csc_matrix); + + return Data_Wrap_Struct(klass, NULL, csc_free, mat); +} + + +void csc_free(csc_matrix* mat) { + xfree(mat); +} + + +VALUE csc_get_elements(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + VALUE* array = ALLOC_N(VALUE, input->count); + for (size_t index = 0; index < input->count; index++) { + array[index] = DBL2NUM(input->elements[index]); + } + + return rb_ary_new4(input->count, array); +} + + +VALUE csc_get_indices(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + VALUE* array_ia = ALLOC_N(VALUE, input->count); + for (size_t index = 0; index < input->count; index++) { + array_ia[index] = SIZET2NUM(input->ia[index]); + } + + return rb_ary_new4(input->count, array_ia); +} + + +VALUE csc_get_indptr(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + VALUE* array_jp = ALLOC_N(VALUE, input->shape[1] + 1); + for (size_t index = 0; index <= input->shape[1]; index++) { + array_jp[index] = SIZET2NUM(input->jp[index]); + } + + return rb_ary_new4(input->shape[1] + 1, array_jp); +} + + +VALUE csc_get_count(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + return SIZET2NUM(input->count); +} + + +VALUE csc_get_ndims(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + return SIZET2NUM(input->ndims); +} + + +VALUE csc_get_dtype(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); +} + + +VALUE csc_get_shape(VALUE self) { + csc_matrix* input; + + Data_Get_Struct(self, csc_matrix, input); + + VALUE* array = ALLOC_N(VALUE, input->ndims); + for (size_t index = 0; index < input->ndims; index++) { + array[index] = SIZET2NUM(input->shape[index]); + } + + return rb_ary_new4(input->ndims, array); +} + + +#include "elementwise.c" \ No newline at end of file diff --git a/ext/csc/elementwise.c b/ext/csc/elementwise.c new file mode 100644 index 0000000..4740563 --- /dev/null +++ b/ext/csc/elementwise.c @@ -0,0 +1,132 @@ +double csc_perform_oper(double val_a, double val_b, char oper) { + switch(oper) { + case '+': + return (val_a + val_b); + case '-': + return (val_a - val_b); + case '*': + return (val_a * val_b); + default: //unknown operator + return 0.00; + } +} + + +/* + Takes two matrices and performs operator elementwise +*/ +VALUE csc_elementwise_binary(VALUE self, VALUE another, char oper) { + csc_matrix* left; + csc_matrix* right; + Data_Get_Struct(self, csc_matrix, left); + Data_Get_Struct(another, csc_matrix, right); + + csc_matrix* result = ALLOC(csc_matrix); + result->count = 0; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, 2 * left->count); + result->ia = ALLOC_N(size_t, 2 * left->count); + result->jp = ALLOC_N(size_t, left->shape[1] + 1); + + for(size_t index = 0; index <= result->shape[1]; index++) result->jp[index] = 0; + + size_t left_index = 0, right_index = 0, result_index = 0; + for(size_t index = 1; index <= result->shape[1]; index++) { + size_t left_col_ele_count = left->jp[index]; + size_t right_col_ele_count = right->jp[index]; + + while (left_index < left_col_ele_count && right_index < right_col_ele_count) { + if (left->ia[left_index] == right->ia[right_index]) { //left and right indices equal + double result_val = csc_perform_oper(left->elements[left_index], right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++, right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ia[result_index] = left->ia[left_index]; + + left_index++, right_index++, result_index++; + } + else if (left->ia[left_index] < right->ia[right_index]) { //left index smaller + double result_val = csc_perform_oper(left->elements[left_index], 0.0, oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ia[result_index] = left->ia[left_index]; + + left_index++, result_index++; + } + else { //right index smaller + double result_val = csc_perform_oper(0.0, right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = right->ia[right_index]; + result->ia[result_index] = right->ia[right_index]; + + right_index++, result_index++; + } + + result->count++; + result->jp[index] += 1; + } + + while (left_index < left_col_ele_count) { + double result_val = csc_perform_oper(left->elements[left_index], 0.0, oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = left->ia[left_index]; + result->ia[result_index] = left->ia[left_index]; + + left_index++, result_index++; + result->count++; + result->jp[index] += 1; + } + + while (right_index < right_col_ele_count) { + double result_val = csc_perform_oper(0.0, right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; + // result->ia[result_index] = right->ia[right_index]; + result->ia[result_index] = right->ia[right_index]; + + right_index++, result_index++; + result->count++; + result->jp[index] += 1; + } + + result->jp[index] += result->jp[index - 1]; + } + + return Data_Wrap_Struct(CSC, NULL, csc_free, result); +} + +VALUE csc_add(VALUE self, VALUE another) { + return csc_elementwise_binary(self, another, '+'); +} + +VALUE csc_sub(VALUE self, VALUE another) { + return csc_elementwise_binary(self, another, '-'); +} + +VALUE csc_mul(VALUE self, VALUE another) { + return csc_elementwise_binary(self, another, '*'); +} \ No newline at end of file From 44df77c9d35c3eff33be0c1d37fb031d0cba31f1 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Thu, 25 Mar 2021 20:01:03 +0530 Subject: [PATCH 03/14] add csr/csc to the API; fix COO elementwise issue --- ext/coo/elementwise.c | 14 ++++++- ext/ruby_sparse.c | 98 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/ext/coo/elementwise.c b/ext/coo/elementwise.c index 55818f8..30e2675 100644 --- a/ext/coo/elementwise.c +++ b/ext/coo/elementwise.c @@ -79,7 +79,12 @@ VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { } while (left_index < left->count) { - result->elements[result_index] = left->elements[left_index]; + double result_val = coo_perform_oper(left->elements[left_index], 0.0, oper); + if(fabs(result_val) < 1e-6) { //near to zero + left_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; result->ia[result_index] = left->ia[left_index]; result->ja[result_index] = left->ja[left_index]; @@ -88,7 +93,12 @@ VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { } while (right_index < right->count) { - result->elements[result_index] = right->elements[right_index]; + double result_val = coo_perform_oper(0.0, right->elements[right_index], oper); + if(fabs(result_val) < 1e-6) { //near to zero + right_index++; + continue; //skip current result value + } + result->elements[result_index] = result_val; result->ia[result_index] = right->ia[right_index]; result->ja[result_index] = right->ja[right_index]; diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index 20eb943..3b4ba69 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -41,6 +41,28 @@ typedef struct COO_STRUCT size_t* ja; //col index }coo_matrix; +typedef struct CSR_STRUCT +{ + sp_dtype dtype; + size_t ndims; + size_t count; //count of non-zero elements + size_t* shape; + double* elements; //elements array + size_t* ip; //row pointer vals + size_t* ja; //col index +}csr_matrix; + +typedef struct CSC_STRUCT +{ + sp_dtype dtype; + size_t ndims; + size_t count; //count of non-zero elements + size_t* shape; + double* elements; //elements array + size_t* ia; //row index + size_t* jp; //col pointer vals +}csc_matrix; + typedef struct DIA_STRUCT { sp_dtype dtype; @@ -64,6 +86,8 @@ typedef struct DIA_STRUCT VALUE RubySparse = Qnil; VALUE SparseArray = Qnil; VALUE COO = Qnil; +VALUE CSR = Qnil; +VALUE CSC = Qnil; VALUE DIA = Qnil; // VALUE GCXS = Qnil; @@ -86,6 +110,42 @@ VALUE coo_mul(VALUE self, VALUE another); VALUE coo_from_nmatrix(VALUE self, VALUE nmat); +// csr methods declaration +VALUE csr_init(int argc, VALUE* argv, VALUE self); +VALUE csr_get_dtype(VALUE self); +VALUE csr_get_shape(VALUE self); +VALUE csr_get_elements(VALUE self); +VALUE csr_get_indices(VALUE self); +VALUE csr_get_indptr(VALUE self); +VALUE csr_get_count(VALUE self); +VALUE csr_get_ndims(VALUE self); +VALUE csr_alloc(VALUE klass); +void csr_free(csr_matrix* mat); + +VALUE csr_add(VALUE self, VALUE another); +VALUE csr_sub(VALUE self, VALUE another); +VALUE csr_mul(VALUE self, VALUE another); + +VALUE csr_from_nmatrix(VALUE self, VALUE nmat); + +// csc methods declaration +VALUE csc_init(int argc, VALUE* argv, VALUE self); +VALUE csc_get_dtype(VALUE self); +VALUE csc_get_shape(VALUE self); +VALUE csc_get_elements(VALUE self); +VALUE csc_get_indices(VALUE self); +VALUE csc_get_indptr(VALUE self); +VALUE csc_get_count(VALUE self); +VALUE csc_get_ndims(VALUE self); +VALUE csc_alloc(VALUE klass); +void csc_free(csc_matrix* mat); + +VALUE csc_add(VALUE self, VALUE another); +VALUE csc_sub(VALUE self, VALUE another); +VALUE csc_mul(VALUE self, VALUE another); + +VALUE csc_from_nmatrix(VALUE self, VALUE nmat); + // dia methods declaration VALUE dia_init(int argc, VALUE* argv, VALUE self); VALUE dia_get_dtype(VALUE self); @@ -108,6 +168,8 @@ void Init_ruby_sparse() { SparseArray = rb_define_class_under(RubySparse, "SparseArray", rb_cObject); COO = rb_define_class_under(RubySparse, "COO", SparseArray); + CSR = rb_define_class_under(RubySparse, "CSR", SparseArray); + CSC = rb_define_class_under(RubySparse, "CSC", SparseArray); DIA = rb_define_class_under(RubySparse, "DIA", SparseArray); // GCXS = rb_define_class_under(RubySparse, "GCXS", SparseArray); @@ -127,6 +189,40 @@ void Init_ruby_sparse() { //rb_define_singleton_method(COO, "from_nmatrix", coo_from_nmatrix, 1); + rb_define_alloc_func(CSR, csr_alloc); + rb_define_method(CSR, "initialize", csr_init, -1); + rb_define_method(CSR, "dtype", csr_get_dtype, 0); + rb_define_method(CSR, "shape", csr_get_shape, 0); + rb_define_method(CSR, "elements", csr_get_elements, 0); + rb_define_method(CSR, "indices", csr_get_indices, 0); + rb_define_method(CSR, "indptr", csr_get_indptr, 0); + rb_define_method(CSR, "nzcount", csr_get_count, 0); + rb_define_method(CSR, "dim", csr_get_ndims, 0); + + rb_define_method(CSR, "+", csr_add, 1); + rb_define_method(CSR, "-", csr_sub, 1); + rb_define_method(CSR, "*", csr_mul, 1); + + //rb_define_singleton_method(CSR, "from_nmatrix", csr_from_nmatrix, 1); + + + rb_define_alloc_func(CSC, csc_alloc); + rb_define_method(CSC, "initialize", csc_init, -1); + rb_define_method(CSC, "dtype", csc_get_dtype, 0); + rb_define_method(CSC, "shape", csc_get_shape, 0); + rb_define_method(CSC, "elements", csc_get_elements, 0); + rb_define_method(CSC, "indices", csc_get_indices, 0); + rb_define_method(CSC, "indptr", csc_get_indptr, 0); + rb_define_method(CSC, "nzcount", csc_get_count, 0); + rb_define_method(CSC, "dim", csc_get_ndims, 0); + + rb_define_method(CSC, "+", csc_add, 1); + rb_define_method(CSC, "-", csc_sub, 1); + rb_define_method(CSC, "*", csc_mul, 1); + + //rb_define_singleton_method(CSC, "from_nmatrix", csc_from_nmatrix, 1); + + rb_define_alloc_func(DIA, dia_alloc); rb_define_method(DIA, "initialize", dia_init, -1); rb_define_method(DIA, "dtype", dia_get_dtype, 0); @@ -142,6 +238,8 @@ void Init_ruby_sparse() { } #include "coo/coo_def.c" +#include "csr/csr_def.c" +#include "csc/csc_def.c" #include "dia/dia_def.c" #include "interfaces/nmatrix.c" From 5713790fc441a1c7d8fc42c57d1998d7ac07c843 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Thu, 25 Mar 2021 20:01:27 +0530 Subject: [PATCH 04/14] add tests for CSR/CSC --- test/elementwise_test.rb | 86 +++++++++++++++++++++++++++++++++++++++- test/sparse_test.rb | 66 ++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/test/elementwise_test.rb b/test/elementwise_test.rb index 718ea4e..9e6c1da 100644 --- a/test/elementwise_test.rb +++ b/test/elementwise_test.rb @@ -70,4 +70,88 @@ def test_mul assert_equal answer.elements, result.elements end -end \ No newline at end of file +end + +class RubySparse::CSR::ElementWiseTest < Minitest::Test + + def setup + @left = RubySparse::CSR.new [3, 3], [1, 2, 3], [0, 1, 2], [0, 1, 2] + @right = RubySparse::CSR.new [3, 3], [3, 2, 3], [0, 1, 2], [2, 2, 2] + end + + def test_add + result = RubySparse::CSR.new [3, 3], [1, 3, 2, 2, 6], [0, 0, 1, 1, 2], [0, 2, 1, 2, 2] + answer = @left + @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + + def test_sub + result = RubySparse::CSR.new [3, 3], [1, -3, 2, -2], [0, 0, 1, 1], [0, 2, 1, 2] + answer = @left - @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + + def test_mul + result = RubySparse::CSR.new [3, 3], [9], [2], [2] + answer = @left * @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + +end + +class RubySparse::CSC::ElementWiseTest < Minitest::Test + + def setup + @left = RubySparse::CSC.new [3, 3], [1, 2, 3], [0, 1, 2], [0, 1, 2] + @right = RubySparse::CSC.new [3, 3], [3, 2, 3], [0, 1, 2], [2, 2, 2] + end + + def test_add + result = RubySparse::CSC.new [3, 3], [1, 3, 2, 2, 6], [0, 0, 1, 1, 2], [0, 2, 1, 2, 2] + answer = @left + @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + + def test_sub + result = RubySparse::CSC.new [3, 3], [1, -3, 2, -2], [0, 0, 1, 1], [0, 2, 1, 2] + answer = @left - @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + + def test_mul + result = RubySparse::CSC.new [3, 3], [9], [2], [2] + answer = @left * @right + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + +end diff --git a/test/sparse_test.rb b/test/sparse_test.rb index 0362a52..cdadb0d 100644 --- a/test/sparse_test.rb +++ b/test/sparse_test.rb @@ -46,4 +46,70 @@ def test_elements assert_equal [1, 0, 3], @n.elements end +end + +class RubySparse::CSR::CreationTest < Minitest::Test + + def setup + @n = RubySparse::CSR.new [3, 3], [1, 2, 3], [0, 1, 2], [0, 1, 2] + @m = RubySparse::CSR.new [4, 6], [1, 2, 3, 4, 5, 6, 7, 8], [0, 0, 1, 1, 2, 2, 2, 3], [0, 1, 1, 3, 2, 3, 4, 5] + end + + def test_ndims + assert_equal 2, @n.dim + end + + def test_shape + assert_equal [3, 3], @n.shape + end + + def test_elements + assert_equal [1, 2, 3], @n.elements + end + + def test_indices + assert_equal [0, 1, 1, 3, 2, 3, 4, 5], @m.indices + end + + def test_indptr + assert_equal [0, 2, 4, 7, 8], @m.indptr + end + + def test_count + assert_equal 3, @n.nzcount + end + +end + +class RubySparse::CSC::CreationTest < Minitest::Test + + def setup + @n = RubySparse::CSC.new [3, 3], [1, 2, 3], [0, 1, 2], [0, 1, 2] + @m = RubySparse::CSC.new [4, 6], [1, 2, 3, 4, 5, 6, 7, 8], [0, 0, 1, 1, 2, 2, 2, 3], [0, 1, 1, 3, 2, 3, 4, 5] + end + + def test_ndims + assert_equal 2, @n.dim + end + + def test_shape + assert_equal [3, 3], @n.shape + end + + def test_elements + assert_equal [1, 2, 3], @n.elements + end + + def test_indices + assert_equal [0, 0, 1, 2, 1, 2, 2, 3], @m.indices + end + + def test_indptr + assert_equal [0, 1, 3, 4, 6, 7, 8], @m.indptr + end + + def test_count + assert_equal 3, @n.nzcount + end + end \ No newline at end of file From 46ef63c978aa926eb15550f4eceb92de8a912800 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Fri, 26 Mar 2021 01:17:41 +0530 Subject: [PATCH 05/14] add nmatrix conversion for CSR, CSC, DIA --- lib/ruby_sparse/ruby_sparse.rb | 143 +++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/lib/ruby_sparse/ruby_sparse.rb b/lib/ruby_sparse/ruby_sparse.rb index 8d06620..0a90cfa 100644 --- a/lib/ruby_sparse/ruby_sparse.rb +++ b/lib/ruby_sparse/ruby_sparse.rb @@ -74,5 +74,148 @@ class DIA < SparseArray # @elements = elements # end + def self.from_nmatrix(nmat) + nm_elements = nmat.elements + nm_shape = nmat.shape + + if nmat.dim != 2 + raise StandardError.new "NMatrix must be of 2 dimensions." + end + + dia_elements = [] + + for i in (0...nmat.shape[0]) + nm_index = (nmat.shape[1] * i) + i + nm_value = nm_elements[nm_index] + dia_elements.append(nm_value) + end + + dia_mat = self.new nm_shape, dia_elements + return dia_mat + end + + def to_nmatrix + nm_elements = Array.new(self.shape[0]*self.shape[1], 0) + for i in (0...self.shape[0]) + nm_index = (self.shape[1] * i) + i + nm_elements[nm_index] = self.elements[i] + end + + m = NMatrix.new self.shape, nm_elements + return m + end + + end + + class CSR < SparseArray + + # attr_reader :shape, :elements + + # def initialize shape, elements + # @shape = shape + # @elements = elements + # end + + def self.from_nmatrix(nmat) + nm_elements = nmat.elements + nm_shape = nmat.shape + + if nmat.dim != 2 + raise StandardError.new "NMatrix must be of 2 dimensions." + end + + csr_elements = [] + csr_ia = [] + csr_ja = [] + + for i in (0...nmat.shape[0]) + for j in (0...nmat.shape[1]) + nm_index = (nmat.shape[1] * i) + j + nm_value = nm_elements[nm_index] + if nm_value == 0 + next + end + csr_elements.append(nm_value) + csr_ia.append(i) + csr_ja.append(j) + end + end + + csr_mat = self.new nm_shape, csr_elements, csr_ia, csr_ja + return csr_mat + end + + def to_nmatrix + ip = self.indptr + ja = self.indices + + nm_elements = Array.new(self.shape[0]*self.shape[1], 0) + for i in (0...self.shape[0]) + for j in (ip[i]...ip[i + 1]) + nm_index = (self.shape[1] * i) + ja[j] + nm_elements[nm_index] = self.elements[j] + end + end + + m = NMatrix.new self.shape, nm_elements + return m + end + + end + + class CSC < SparseArray + + # attr_reader :shape, :elements + + # def initialize shape, elements + # @shape = shape + # @elements = elements + # end + + def self.from_nmatrix(nmat) + nm_elements = nmat.elements + nm_shape = nmat.shape + + if nmat.dim != 2 + raise StandardError.new "NMatrix must be of 2 dimensions." + end + + csc_elements = [] + csc_ia = [] + csc_ja = [] + + for i in (0...nmat.shape[0]) + for j in (0...nmat.shape[1]) + nm_index = (nmat.shape[1] * i) + j + nm_value = nm_elements[nm_index] + if nm_value == 0 + next + end + csc_elements.append(nm_value) + csc_ia.append(i) + csc_ja.append(j) + end + end + + csc_mat = self.new nm_shape, csc_elements, csc_ia, csc_ja + return csc_mat + end + + def to_nmatrix + ia = self.indices + jp = self.indptr + + nm_elements = Array.new(self.shape[0]*self.shape[1], 0) + for j in (0...self.shape[1]) + for i in (jp[i]...jp[i + 1]) + nm_index = (self.shape[0] * i) + ia[j] + nm_elements[nm_index] = self.elements[j] + end + end + + m = NMatrix.new self.shape, nm_elements + return m + end + end end \ No newline at end of file From bc7d088629856edb731820c9563fefa44913db98 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Fri, 26 Mar 2021 03:07:54 +0530 Subject: [PATCH 06/14] add basic pretty print and inspect --- lib/ruby_sparse/ruby_sparse.rb | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/lib/ruby_sparse/ruby_sparse.rb b/lib/ruby_sparse/ruby_sparse.rb index 0a90cfa..5ebce09 100644 --- a/lib/ruby_sparse/ruby_sparse.rb +++ b/lib/ruby_sparse/ruby_sparse.rb @@ -20,6 +20,24 @@ class COO < SparseArray # @elements = elements # end + def pretty_print(q) + self.inspect.pretty_print(q) + end + + def inspect #:nodoc: + original_inspect = super() + original_inspect = original_inspect[0...original_inspect.size-1] + original_inspect + "; " + inspect_helper.join("; ") + ">" + end + + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + def self.from_nmatrix(nmat) nm_elements = nmat.elements nm_shape = nmat.shape @@ -74,6 +92,24 @@ class DIA < SparseArray # @elements = elements # end + def pretty_print(q) + self.inspect.pretty_print(q) + end + + def inspect #:nodoc: + original_inspect = super() + original_inspect = original_inspect[0...original_inspect.size-1] + original_inspect + "; " + inspect_helper.join("; ") + ">" + end + + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + def self.from_nmatrix(nmat) nm_elements = nmat.elements nm_shape = nmat.shape @@ -116,6 +152,24 @@ class CSR < SparseArray # @elements = elements # end + def pretty_print(q) + self.inspect.pretty_print(q) + end + + def inspect #:nodoc: + original_inspect = super() + original_inspect = original_inspect[0...original_inspect.size-1] + original_inspect + "; " + inspect_helper.join("; ") + ">" + end + + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + def self.from_nmatrix(nmat) nm_elements = nmat.elements nm_shape = nmat.shape @@ -172,6 +226,24 @@ class CSC < SparseArray # @elements = elements # end + def pretty_print(q) + self.inspect.pretty_print(q) + end + + def inspect #:nodoc: + original_inspect = super() + original_inspect = original_inspect[0...original_inspect.size-1] + original_inspect + "; " + inspect_helper.join("; ") + ">" + end + + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + def self.from_nmatrix(nmat) nm_elements = nmat.elements nm_shape = nmat.shape From 03deb08de310b1f69b15a9c5607abf92aea08293 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Fri, 26 Mar 2021 04:06:52 +0530 Subject: [PATCH 07/14] add serialization support --- lib/ruby_sparse/ruby_sparse.rb | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/lib/ruby_sparse/ruby_sparse.rb b/lib/ruby_sparse/ruby_sparse.rb index 5ebce09..3aab6b5 100644 --- a/lib/ruby_sparse/ruby_sparse.rb +++ b/lib/ruby_sparse/ruby_sparse.rb @@ -80,6 +80,36 @@ def to_nmatrix m = NMatrix.new self.shape, nm_elements return m end + + def _dump data + [ + dim, + nzcount, + dtype, + shape, + elements, + coords[0], + coords[1], + ].join ":" + end + + def self._load args + values = args.split(":") + dim = values[0].to_i + nzcount = values[1].to_i + dtype = values[2].to_sym + shape = values[3...(3+dim)] + elements = values[(3+dim)...(3+dim+nzcount)] + ia = values[(3+dim+nzcount)...(3+dim+(2*nzcount))] + ja = values[(3+dim+(2*nzcount))...(3+dim+(3*nzcount))] + + (0...dim).each { |index| shape[index] = shape[index].to_i } + (0...nzcount).each { |index| elements[index] = elements[index].to_f } + (0...nzcount).each { |index| ia[index] = ia[index].to_i } + (0...nzcount).each { |index| ja[index] = ja[index].to_i } + + self.new(shape, elements, ia, ja) + end end @@ -141,6 +171,28 @@ def to_nmatrix return m end + def _dump data + [ + dim, + dtype, + shape, + elements, + ].join ":" + end + + def self._load args + values = args.split(":") + dim = values[0].to_i + dtype = values[1].to_sym + shape = values[2...(2+dim)] + elements = values[(2+dim)...(2+dim+shape[0].to_i)] + + (0...dim).each { |index| shape[index] = shape[index].to_i } + (0...shape[0]).each { |index| elements[index] = elements[index].to_f } + + self.new(shape, elements) + end + end class CSR < SparseArray @@ -215,6 +267,38 @@ def to_nmatrix return m end + def _dump data + [ + dim, + nzcount, + dtype, + shape, + elements, + indptr, + indices, + ].join ":" + end + + def self._load args + values = args.split(":") + dim = values[0].to_i + nzcount = values[1].to_i + dtype = values[2].to_sym + shape = values[3...(3+dim)] + elements = values[(3+dim)...(3+dim+nzcount)] + ip = values[(3+dim+nzcount)...(3+dim+nzcount+shape[0].to_i)] + ja = values[(3+dim+nzcount+shape[0].to_i)...(3+dim+(2*nzcount)+shape[0].to_i)] + + (0...dim).each { |index| shape[index] = shape[index].to_i } + (0...nzcount).each { |index| elements[index] = elements[index].to_f } + (0...shape[0]).each { |index| ip[index] = ip[index].to_i } + (0...nzcount).each { |index| ja[index] = ja[index].to_i } + + # convert ip to ia here and then pass ia below instead + + self.new(shape, elements, ip, ja) + end + end class CSC < SparseArray @@ -289,5 +373,37 @@ def to_nmatrix return m end + def _dump data + [ + dim, + nzcount, + dtype, + shape, + elements, + indices, + indptr, + ].join ":" + end + + def self._load args + values = args.split(":") + dim = values[0].to_i + nzcount = values[1].to_i + dtype = values[2].to_sym + shape = values[3...(3+dim)] + elements = values[(3+dim)...(3+dim+nzcount)] + ia = values[(3+dim+nzcount)...(3+dim+(2*nzcount))] + jp = values[(3+dim+(2*nzcount))...(3+dim+(2*nzcount)+shape[1].to_i)] + + (0...dim).each { |index| shape[index] = shape[index].to_i } + (0...nzcount).each { |index| elements[index] = elements[index].to_f } + (0...nzcount).each { |index| ia[index] = ia[index].to_i } + (0...shape[1]).each { |index| jp[index] = jp[index].to_i } + + # convert jp to ja here and then pass ja below instead + + self.new(shape, elements, ia, jp) + end + end end \ No newline at end of file From 626c999324ee2fbb74df59a5af7d67d540f47212 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Mon, 29 Mar 2021 02:34:07 +0530 Subject: [PATCH 08/14] use TypedData_Get_Struct instead of Data_Get_Struct --- ext/coo/coo_def.c | 16 ++++++++-------- ext/coo/elementwise.c | 6 +++--- ext/csc/csc_def.c | 18 +++++++++--------- ext/csc/elementwise.c | 6 +++--- ext/csr/csr_def.c | 18 +++++++++--------- ext/csr/elementwise.c | 6 +++--- ext/dia/dia_def.c | 14 +++++++------- ext/dia/elementwise.c | 6 +++--- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/ext/coo/coo_def.c b/ext/coo/coo_def.c index 563d1b9..059db98 100644 --- a/ext/coo/coo_def.c +++ b/ext/coo/coo_def.c @@ -1,6 +1,6 @@ VALUE coo_init(int argc, VALUE* argv, VALUE self) { coo_matrix* mat; - Data_Get_Struct(self, coo_matrix, mat); + TypedData_Get_Struct(self, coo_matrix, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -31,7 +31,7 @@ VALUE coo_init(int argc, VALUE* argv, VALUE self) { VALUE coo_alloc(VALUE klass) { coo_matrix* mat = ALLOC(coo_matrix); - return Data_Wrap_Struct(klass, NULL, coo_free, mat); + return TypedData_Wrap_Struct(klass, NULL, coo_free, mat); } @@ -43,7 +43,7 @@ void coo_free(coo_matrix* mat) { VALUE coo_get_elements(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -57,7 +57,7 @@ VALUE coo_get_elements(VALUE self) { VALUE coo_get_coords(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); VALUE* array_ia = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -78,7 +78,7 @@ VALUE coo_get_coords(VALUE self) { VALUE coo_get_count(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); return SIZET2NUM(input->count); } @@ -87,7 +87,7 @@ VALUE coo_get_count(VALUE self) { VALUE coo_get_ndims(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); return SIZET2NUM(input->ndims); } @@ -96,7 +96,7 @@ VALUE coo_get_ndims(VALUE self) { VALUE coo_get_dtype(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -105,7 +105,7 @@ VALUE coo_get_dtype(VALUE self) { VALUE coo_get_shape(VALUE self) { coo_matrix* input; - Data_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/coo/elementwise.c b/ext/coo/elementwise.c index 30e2675..7a7db55 100644 --- a/ext/coo/elementwise.c +++ b/ext/coo/elementwise.c @@ -18,8 +18,8 @@ double coo_perform_oper(double val_a, double val_b, char oper) { VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { coo_matrix* left; coo_matrix* right; - Data_Get_Struct(self, coo_matrix, left); - Data_Get_Struct(another, coo_matrix, right); + TypedData_Get_Struct(self, coo_matrix, left); + TypedData_Get_Struct(another, coo_matrix, right); coo_matrix* result = ALLOC(coo_matrix); result->count = 0; @@ -106,7 +106,7 @@ VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { result->count++; } - return Data_Wrap_Struct(COO, NULL, coo_free, result); + return TypedData_Wrap_Struct(COO, NULL, coo_free, result); } VALUE coo_add(VALUE self, VALUE another) { diff --git a/ext/csc/csc_def.c b/ext/csc/csc_def.c index e48a5c5..aaeceb2 100644 --- a/ext/csc/csc_def.c +++ b/ext/csc/csc_def.c @@ -1,6 +1,6 @@ VALUE csc_init(int argc, VALUE* argv, VALUE self) { csc_matrix* mat; - Data_Get_Struct(self, csc_matrix, mat); + TypedData_Get_Struct(self, csc_matrix, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -48,7 +48,7 @@ VALUE csc_init(int argc, VALUE* argv, VALUE self) { VALUE csc_alloc(VALUE klass) { csc_matrix* mat = ALLOC(csc_matrix); - return Data_Wrap_Struct(klass, NULL, csc_free, mat); + return TypedData_Wrap_Struct(klass, NULL, csc_free, mat); } @@ -60,7 +60,7 @@ void csc_free(csc_matrix* mat) { VALUE csc_get_elements(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -74,7 +74,7 @@ VALUE csc_get_elements(VALUE self) { VALUE csc_get_indices(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); VALUE* array_ia = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -88,7 +88,7 @@ VALUE csc_get_indices(VALUE self) { VALUE csc_get_indptr(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); VALUE* array_jp = ALLOC_N(VALUE, input->shape[1] + 1); for (size_t index = 0; index <= input->shape[1]; index++) { @@ -102,7 +102,7 @@ VALUE csc_get_indptr(VALUE self) { VALUE csc_get_count(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); return SIZET2NUM(input->count); } @@ -111,7 +111,7 @@ VALUE csc_get_count(VALUE self) { VALUE csc_get_ndims(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); return SIZET2NUM(input->ndims); } @@ -120,7 +120,7 @@ VALUE csc_get_ndims(VALUE self) { VALUE csc_get_dtype(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -129,7 +129,7 @@ VALUE csc_get_dtype(VALUE self) { VALUE csc_get_shape(VALUE self) { csc_matrix* input; - Data_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/csc/elementwise.c b/ext/csc/elementwise.c index 4740563..4a84663 100644 --- a/ext/csc/elementwise.c +++ b/ext/csc/elementwise.c @@ -18,8 +18,8 @@ double csc_perform_oper(double val_a, double val_b, char oper) { VALUE csc_elementwise_binary(VALUE self, VALUE another, char oper) { csc_matrix* left; csc_matrix* right; - Data_Get_Struct(self, csc_matrix, left); - Data_Get_Struct(another, csc_matrix, right); + TypedData_Get_Struct(self, csc_matrix, left); + TypedData_Get_Struct(another, csc_matrix, right); csc_matrix* result = ALLOC(csc_matrix); result->count = 0; @@ -116,7 +116,7 @@ VALUE csc_elementwise_binary(VALUE self, VALUE another, char oper) { result->jp[index] += result->jp[index - 1]; } - return Data_Wrap_Struct(CSC, NULL, csc_free, result); + return TypedData_Wrap_Struct(CSC, NULL, csc_free, result); } VALUE csc_add(VALUE self, VALUE another) { diff --git a/ext/csr/csr_def.c b/ext/csr/csr_def.c index 0048224..163ca89 100644 --- a/ext/csr/csr_def.c +++ b/ext/csr/csr_def.c @@ -1,6 +1,6 @@ VALUE csr_init(int argc, VALUE* argv, VALUE self) { csr_matrix* mat; - Data_Get_Struct(self, csr_matrix, mat); + TypedData_Get_Struct(self, csr_matrix, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -48,7 +48,7 @@ VALUE csr_init(int argc, VALUE* argv, VALUE self) { VALUE csr_alloc(VALUE klass) { csr_matrix* mat = ALLOC(csr_matrix); - return Data_Wrap_Struct(klass, NULL, csr_free, mat); + return TypedData_Wrap_Struct(klass, NULL, csr_free, mat); } @@ -60,7 +60,7 @@ void csr_free(csr_matrix* mat) { VALUE csr_get_elements(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -74,7 +74,7 @@ VALUE csr_get_elements(VALUE self) { VALUE csr_get_indices(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); VALUE* array_ja = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -88,7 +88,7 @@ VALUE csr_get_indices(VALUE self) { VALUE csr_get_indptr(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); VALUE* array_ip = ALLOC_N(VALUE, input->shape[0] + 1); for (size_t index = 0; index <= input->shape[0]; index++) { @@ -102,7 +102,7 @@ VALUE csr_get_indptr(VALUE self) { VALUE csr_get_count(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); return SIZET2NUM(input->count); } @@ -111,7 +111,7 @@ VALUE csr_get_count(VALUE self) { VALUE csr_get_ndims(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); return SIZET2NUM(input->ndims); } @@ -120,7 +120,7 @@ VALUE csr_get_ndims(VALUE self) { VALUE csr_get_dtype(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -129,7 +129,7 @@ VALUE csr_get_dtype(VALUE self) { VALUE csr_get_shape(VALUE self) { csr_matrix* input; - Data_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/csr/elementwise.c b/ext/csr/elementwise.c index 2a0ed57..d073142 100644 --- a/ext/csr/elementwise.c +++ b/ext/csr/elementwise.c @@ -18,8 +18,8 @@ double csr_perform_oper(double val_a, double val_b, char oper) { VALUE csr_elementwise_binary(VALUE self, VALUE another, char oper) { csr_matrix* left; csr_matrix* right; - Data_Get_Struct(self, csr_matrix, left); - Data_Get_Struct(another, csr_matrix, right); + TypedData_Get_Struct(self, csr_matrix, left); + TypedData_Get_Struct(another, csr_matrix, right); csr_matrix* result = ALLOC(csr_matrix); result->count = 0; @@ -116,7 +116,7 @@ VALUE csr_elementwise_binary(VALUE self, VALUE another, char oper) { result->ip[index] += result->ip[index - 1]; } - return Data_Wrap_Struct(CSR, NULL, csr_free, result); + return TypedData_Wrap_Struct(CSR, NULL, csr_free, result); } VALUE csr_add(VALUE self, VALUE another) { diff --git a/ext/dia/dia_def.c b/ext/dia/dia_def.c index 3bd4072..46a772e 100644 --- a/ext/dia/dia_def.c +++ b/ext/dia/dia_def.c @@ -1,6 +1,6 @@ VALUE dia_init(int argc, VALUE* argv, VALUE self) { dia_matrix* mat; - Data_Get_Struct(self, dia_matrix, mat); + TypedData_Get_Struct(self, dia_matrix, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -23,7 +23,7 @@ VALUE dia_init(int argc, VALUE* argv, VALUE self) { VALUE dia_alloc(VALUE klass) { dia_matrix* mat = ALLOC(dia_matrix); - return Data_Wrap_Struct(klass, NULL, dia_free, mat); + return TypedData_Wrap_Struct(klass, NULL, dia_free, mat); } @@ -35,7 +35,7 @@ void dia_free(dia_matrix* mat) { VALUE dia_get_elements(VALUE self) { dia_matrix* input; - Data_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -49,7 +49,7 @@ VALUE dia_get_elements(VALUE self) { VALUE dia_get_count(VALUE self) { dia_matrix* input; - Data_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, input); return SIZET2NUM(input->count); } @@ -58,7 +58,7 @@ VALUE dia_get_count(VALUE self) { VALUE dia_get_ndims(VALUE self) { dia_matrix* input; - Data_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, input); return SIZET2NUM(input->ndims); } @@ -67,7 +67,7 @@ VALUE dia_get_ndims(VALUE self) { VALUE dia_get_dtype(VALUE self) { dia_matrix* input; - Data_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -76,7 +76,7 @@ VALUE dia_get_dtype(VALUE self) { VALUE dia_get_shape(VALUE self) { dia_matrix* input; - Data_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/dia/elementwise.c b/ext/dia/elementwise.c index 7e14398..36ad982 100644 --- a/ext/dia/elementwise.c +++ b/ext/dia/elementwise.c @@ -18,8 +18,8 @@ double dia_perform_oper(double val_a, double val_b, char oper) { VALUE dia_elementwise_binary(VALUE self, VALUE another, char oper) { dia_matrix* left; dia_matrix* right; - Data_Get_Struct(self, dia_matrix, left); - Data_Get_Struct(another, dia_matrix, right); + TypedData_Get_Struct(self, dia_matrix, left); + TypedData_Get_Struct(another, dia_matrix, right); dia_matrix* result = ALLOC(dia_matrix); result->count = left->count; @@ -37,7 +37,7 @@ VALUE dia_elementwise_binary(VALUE self, VALUE another, char oper) { result->elements[result_index] = result_val; } - return Data_Wrap_Struct(DIA, NULL, dia_free, result); + return TypedData_Wrap_Struct(DIA, NULL, dia_free, result); } VALUE dia_add(VALUE self, VALUE another) { From 1757c11efa44390365dff0177808884548622508 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Mon, 29 Mar 2021 03:30:43 +0530 Subject: [PATCH 09/14] add memsize and modify free func --- ext/coo/coo_def.c | 33 +++++++++++++++++------- ext/coo/elementwise.c | 6 ++--- ext/csc/csc_def.c | 35 ++++++++++++++++++-------- ext/csc/elementwise.c | 6 ++--- ext/csr/csr_def.c | 35 ++++++++++++++++++-------- ext/csr/elementwise.c | 6 ++--- ext/dia/dia_def.c | 27 ++++++++++++++------ ext/dia/elementwise.c | 6 ++--- ext/ruby_sparse.c | 58 +++++++++++++++++++++++++++++++++++++++---- 9 files changed, 158 insertions(+), 54 deletions(-) diff --git a/ext/coo/coo_def.c b/ext/coo/coo_def.c index 059db98..cddaeab 100644 --- a/ext/coo/coo_def.c +++ b/ext/coo/coo_def.c @@ -1,6 +1,6 @@ VALUE coo_init(int argc, VALUE* argv, VALUE self) { coo_matrix* mat; - TypedData_Get_Struct(self, coo_matrix, mat); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -31,19 +31,34 @@ VALUE coo_init(int argc, VALUE* argv, VALUE self) { VALUE coo_alloc(VALUE klass) { coo_matrix* mat = ALLOC(coo_matrix); - return TypedData_Wrap_Struct(klass, NULL, coo_free, mat); + return TypedData_Wrap_Struct(klass, &coo_data_type, mat); } -void coo_free(coo_matrix* mat) { +void coo_free(void* ptr) { + coo_matrix *mat = (coo_matrix*)ptr; + if (mat->shape) xfree(mat->shape); + if (mat->elements) xfree(mat->elements); + if (mat->ia) xfree(mat->ia); + if (mat->ja) xfree(mat->ja); xfree(mat); } +size_t coo_memsize(const void* ptr) { + coo_matrix *mat = (coo_matrix*)ptr; + size_t size = sizeof(mat); + if (mat->shape) size += mat->ndims; + if (mat->elements) size += mat->count; + if (mat->ia) size += mat->count; + if (mat->ja) size += mat->count; + return size; +} + VALUE coo_get_elements(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -57,7 +72,7 @@ VALUE coo_get_elements(VALUE self) { VALUE coo_get_coords(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); VALUE* array_ia = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -78,7 +93,7 @@ VALUE coo_get_coords(VALUE self) { VALUE coo_get_count(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); return SIZET2NUM(input->count); } @@ -87,7 +102,7 @@ VALUE coo_get_count(VALUE self) { VALUE coo_get_ndims(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); return SIZET2NUM(input->ndims); } @@ -96,7 +111,7 @@ VALUE coo_get_ndims(VALUE self) { VALUE coo_get_dtype(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -105,7 +120,7 @@ VALUE coo_get_dtype(VALUE self) { VALUE coo_get_shape(VALUE self) { coo_matrix* input; - TypedData_Get_Struct(self, coo_matrix, input); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/coo/elementwise.c b/ext/coo/elementwise.c index 7a7db55..8d922f0 100644 --- a/ext/coo/elementwise.c +++ b/ext/coo/elementwise.c @@ -18,8 +18,8 @@ double coo_perform_oper(double val_a, double val_b, char oper) { VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { coo_matrix* left; coo_matrix* right; - TypedData_Get_Struct(self, coo_matrix, left); - TypedData_Get_Struct(another, coo_matrix, right); + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, left); + TypedData_Get_Struct(another, coo_matrix, &coo_data_type, right); coo_matrix* result = ALLOC(coo_matrix); result->count = 0; @@ -106,7 +106,7 @@ VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { result->count++; } - return TypedData_Wrap_Struct(COO, NULL, coo_free, result); + return TypedData_Wrap_Struct(COO, &coo_data_type, result); } VALUE coo_add(VALUE self, VALUE another) { diff --git a/ext/csc/csc_def.c b/ext/csc/csc_def.c index aaeceb2..439a5aa 100644 --- a/ext/csc/csc_def.c +++ b/ext/csc/csc_def.c @@ -1,6 +1,6 @@ VALUE csc_init(int argc, VALUE* argv, VALUE self) { csc_matrix* mat; - TypedData_Get_Struct(self, csc_matrix, mat); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -48,19 +48,34 @@ VALUE csc_init(int argc, VALUE* argv, VALUE self) { VALUE csc_alloc(VALUE klass) { csc_matrix* mat = ALLOC(csc_matrix); - return TypedData_Wrap_Struct(klass, NULL, csc_free, mat); + return TypedData_Wrap_Struct(klass, &csc_data_type, mat); } -void csc_free(csc_matrix* mat) { +void csc_free(void* ptr) { + csc_matrix *mat = (csc_matrix*)ptr; + if (mat->shape) xfree(mat->shape); + if (mat->elements) xfree(mat->elements); + if (mat->ia) xfree(mat->ia); + if (mat->jp) xfree(mat->jp); xfree(mat); } +size_t csc_memsize(const void* ptr) { + csc_matrix *mat = (csc_matrix*)ptr; + size_t size = sizeof(mat); + if (mat->shape) size += mat->ndims; + if (mat->elements) size += mat->count; + if (mat->ia) size += mat->count; + if (mat->jp) size += mat->shape[1]+1; + return size; +} + VALUE csc_get_elements(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -74,7 +89,7 @@ VALUE csc_get_elements(VALUE self) { VALUE csc_get_indices(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); VALUE* array_ia = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -88,7 +103,7 @@ VALUE csc_get_indices(VALUE self) { VALUE csc_get_indptr(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); VALUE* array_jp = ALLOC_N(VALUE, input->shape[1] + 1); for (size_t index = 0; index <= input->shape[1]; index++) { @@ -102,7 +117,7 @@ VALUE csc_get_indptr(VALUE self) { VALUE csc_get_count(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); return SIZET2NUM(input->count); } @@ -111,7 +126,7 @@ VALUE csc_get_count(VALUE self) { VALUE csc_get_ndims(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); return SIZET2NUM(input->ndims); } @@ -120,7 +135,7 @@ VALUE csc_get_ndims(VALUE self) { VALUE csc_get_dtype(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -129,7 +144,7 @@ VALUE csc_get_dtype(VALUE self) { VALUE csc_get_shape(VALUE self) { csc_matrix* input; - TypedData_Get_Struct(self, csc_matrix, input); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/csc/elementwise.c b/ext/csc/elementwise.c index 4a84663..aa8f0dc 100644 --- a/ext/csc/elementwise.c +++ b/ext/csc/elementwise.c @@ -18,8 +18,8 @@ double csc_perform_oper(double val_a, double val_b, char oper) { VALUE csc_elementwise_binary(VALUE self, VALUE another, char oper) { csc_matrix* left; csc_matrix* right; - TypedData_Get_Struct(self, csc_matrix, left); - TypedData_Get_Struct(another, csc_matrix, right); + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, left); + TypedData_Get_Struct(another, csc_matrix, &csc_data_type, right); csc_matrix* result = ALLOC(csc_matrix); result->count = 0; @@ -116,7 +116,7 @@ VALUE csc_elementwise_binary(VALUE self, VALUE another, char oper) { result->jp[index] += result->jp[index - 1]; } - return TypedData_Wrap_Struct(CSC, NULL, csc_free, result); + return TypedData_Wrap_Struct(CSC, &csc_data_type, result); } VALUE csc_add(VALUE self, VALUE another) { diff --git a/ext/csr/csr_def.c b/ext/csr/csr_def.c index 163ca89..04997e4 100644 --- a/ext/csr/csr_def.c +++ b/ext/csr/csr_def.c @@ -1,6 +1,6 @@ VALUE csr_init(int argc, VALUE* argv, VALUE self) { csr_matrix* mat; - TypedData_Get_Struct(self, csr_matrix, mat); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -48,19 +48,34 @@ VALUE csr_init(int argc, VALUE* argv, VALUE self) { VALUE csr_alloc(VALUE klass) { csr_matrix* mat = ALLOC(csr_matrix); - return TypedData_Wrap_Struct(klass, NULL, csr_free, mat); + return TypedData_Wrap_Struct(klass, &csr_data_type, mat); } -void csr_free(csr_matrix* mat) { +void csr_free(void* ptr) { + csr_matrix *mat = (csr_matrix*)ptr; + if (mat->shape) xfree(mat->shape); + if (mat->elements) xfree(mat->elements); + if (mat->ip) xfree(mat->ip); + if (mat->ja) xfree(mat->ja); xfree(mat); } +size_t csr_memsize(const void* ptr) { + csr_matrix *mat = (csr_matrix*)ptr; + size_t size = sizeof(mat); + if (mat->shape) size += mat->ndims; + if (mat->elements) size += mat->count; + if (mat->ip) size += mat->shape[0]+1; + if (mat->ja) size += mat->count; + return size; +} + VALUE csr_get_elements(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -74,7 +89,7 @@ VALUE csr_get_elements(VALUE self) { VALUE csr_get_indices(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); VALUE* array_ja = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -88,7 +103,7 @@ VALUE csr_get_indices(VALUE self) { VALUE csr_get_indptr(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); VALUE* array_ip = ALLOC_N(VALUE, input->shape[0] + 1); for (size_t index = 0; index <= input->shape[0]; index++) { @@ -102,7 +117,7 @@ VALUE csr_get_indptr(VALUE self) { VALUE csr_get_count(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); return SIZET2NUM(input->count); } @@ -111,7 +126,7 @@ VALUE csr_get_count(VALUE self) { VALUE csr_get_ndims(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); return SIZET2NUM(input->ndims); } @@ -120,7 +135,7 @@ VALUE csr_get_ndims(VALUE self) { VALUE csr_get_dtype(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -129,7 +144,7 @@ VALUE csr_get_dtype(VALUE self) { VALUE csr_get_shape(VALUE self) { csr_matrix* input; - TypedData_Get_Struct(self, csr_matrix, input); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/csr/elementwise.c b/ext/csr/elementwise.c index d073142..9c8e8cf 100644 --- a/ext/csr/elementwise.c +++ b/ext/csr/elementwise.c @@ -18,8 +18,8 @@ double csr_perform_oper(double val_a, double val_b, char oper) { VALUE csr_elementwise_binary(VALUE self, VALUE another, char oper) { csr_matrix* left; csr_matrix* right; - TypedData_Get_Struct(self, csr_matrix, left); - TypedData_Get_Struct(another, csr_matrix, right); + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, left); + TypedData_Get_Struct(another, csr_matrix, &csr_data_type, right); csr_matrix* result = ALLOC(csr_matrix); result->count = 0; @@ -116,7 +116,7 @@ VALUE csr_elementwise_binary(VALUE self, VALUE another, char oper) { result->ip[index] += result->ip[index - 1]; } - return TypedData_Wrap_Struct(CSR, NULL, csr_free, result); + return TypedData_Wrap_Struct(CSR, &csr_data_type, result); } VALUE csr_add(VALUE self, VALUE another) { diff --git a/ext/dia/dia_def.c b/ext/dia/dia_def.c index 46a772e..548e687 100644 --- a/ext/dia/dia_def.c +++ b/ext/dia/dia_def.c @@ -1,6 +1,6 @@ VALUE dia_init(int argc, VALUE* argv, VALUE self) { dia_matrix* mat; - TypedData_Get_Struct(self, dia_matrix, mat); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, mat); if(argc > 0){ mat->dtype = sp_float64; @@ -23,19 +23,30 @@ VALUE dia_init(int argc, VALUE* argv, VALUE self) { VALUE dia_alloc(VALUE klass) { dia_matrix* mat = ALLOC(dia_matrix); - return TypedData_Wrap_Struct(klass, NULL, dia_free, mat); + return TypedData_Wrap_Struct(klass, &dia_data_type, mat); } -void dia_free(dia_matrix* mat) { +void dia_free(void* ptr) { + dia_matrix *mat = (dia_matrix*)ptr; + if (mat->shape) xfree(mat->shape); + if (mat->elements) xfree(mat->elements); xfree(mat); } +size_t dia_memsize(const void* ptr) { + dia_matrix *mat = (dia_matrix*)ptr; + size_t size = sizeof(mat); + if (mat->shape) size += mat->ndims; + if (mat->elements) size += mat->count; + return size; +} + VALUE dia_get_elements(VALUE self) { dia_matrix* input; - TypedData_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); VALUE* array = ALLOC_N(VALUE, input->count); for (size_t index = 0; index < input->count; index++) { @@ -49,7 +60,7 @@ VALUE dia_get_elements(VALUE self) { VALUE dia_get_count(VALUE self) { dia_matrix* input; - TypedData_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); return SIZET2NUM(input->count); } @@ -58,7 +69,7 @@ VALUE dia_get_count(VALUE self) { VALUE dia_get_ndims(VALUE self) { dia_matrix* input; - TypedData_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); return SIZET2NUM(input->ndims); } @@ -67,7 +78,7 @@ VALUE dia_get_ndims(VALUE self) { VALUE dia_get_dtype(VALUE self) { dia_matrix* input; - TypedData_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype])); } @@ -76,7 +87,7 @@ VALUE dia_get_dtype(VALUE self) { VALUE dia_get_shape(VALUE self) { dia_matrix* input; - TypedData_Get_Struct(self, dia_matrix, input); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); VALUE* array = ALLOC_N(VALUE, input->ndims); for (size_t index = 0; index < input->ndims; index++) { diff --git a/ext/dia/elementwise.c b/ext/dia/elementwise.c index 36ad982..4d0e963 100644 --- a/ext/dia/elementwise.c +++ b/ext/dia/elementwise.c @@ -18,8 +18,8 @@ double dia_perform_oper(double val_a, double val_b, char oper) { VALUE dia_elementwise_binary(VALUE self, VALUE another, char oper) { dia_matrix* left; dia_matrix* right; - TypedData_Get_Struct(self, dia_matrix, left); - TypedData_Get_Struct(another, dia_matrix, right); + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, left); + TypedData_Get_Struct(another, dia_matrix, &dia_data_type, right); dia_matrix* result = ALLOC(dia_matrix); result->count = left->count; @@ -37,7 +37,7 @@ VALUE dia_elementwise_binary(VALUE self, VALUE another, char oper) { result->elements[result_index] = result_val; } - return TypedData_Wrap_Struct(DIA, NULL, dia_free, result); + return TypedData_Wrap_Struct(DIA, &dia_data_type, result); } VALUE dia_add(VALUE self, VALUE another) { diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index 3b4ba69..d6de3fd 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -41,6 +41,19 @@ typedef struct COO_STRUCT size_t* ja; //col index }coo_matrix; +void coo_free(void* ptr); +size_t coo_memsize(const void* ptr); + +static const rb_data_type_t coo_data_type = { + "ruby-sparse/coo", + { + 0, + coo_free, + coo_memsize, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + typedef struct CSR_STRUCT { sp_dtype dtype; @@ -52,6 +65,19 @@ typedef struct CSR_STRUCT size_t* ja; //col index }csr_matrix; +void csr_free(void* ptr); +size_t csr_memsize(const void* ptr); + +static const rb_data_type_t csr_data_type = { + "ruby-sparse/csr", + { + 0, + csr_free, + csr_memsize, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + typedef struct CSC_STRUCT { sp_dtype dtype; @@ -63,6 +89,19 @@ typedef struct CSC_STRUCT size_t* jp; //col pointer vals }csc_matrix; +void csc_free(void* ptr); +size_t csc_memsize(const void* ptr); + +static const rb_data_type_t csc_data_type = { + "ruby-sparse/csc", + { + 0, + csc_free, + csc_memsize, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + typedef struct DIA_STRUCT { sp_dtype dtype; @@ -72,6 +111,19 @@ typedef struct DIA_STRUCT double* elements; //elements array }dia_matrix; +void dia_free(void* ptr); +size_t dia_memsize(const void* ptr); + +static const rb_data_type_t dia_data_type = { + "ruby-sparse/dia", + { + 0, + dia_free, + dia_memsize, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + // typedef struct GCXS_STRUCT // { // sp_dtype dtype; @@ -81,7 +133,7 @@ typedef struct DIA_STRUCT // double* elements; //elements array // size_t* ia; //row index // size_t* ja; //col index -// }coo_matrix; +// }gcxs_matrix; VALUE RubySparse = Qnil; VALUE SparseArray = Qnil; @@ -102,7 +154,6 @@ VALUE coo_get_coords(VALUE self); VALUE coo_get_count(VALUE self); VALUE coo_get_ndims(VALUE self); VALUE coo_alloc(VALUE klass); -void coo_free(coo_matrix* mat); VALUE coo_add(VALUE self, VALUE another); VALUE coo_sub(VALUE self, VALUE another); @@ -120,7 +171,6 @@ VALUE csr_get_indptr(VALUE self); VALUE csr_get_count(VALUE self); VALUE csr_get_ndims(VALUE self); VALUE csr_alloc(VALUE klass); -void csr_free(csr_matrix* mat); VALUE csr_add(VALUE self, VALUE another); VALUE csr_sub(VALUE self, VALUE another); @@ -138,7 +188,6 @@ VALUE csc_get_indptr(VALUE self); VALUE csc_get_count(VALUE self); VALUE csc_get_ndims(VALUE self); VALUE csc_alloc(VALUE klass); -void csc_free(csc_matrix* mat); VALUE csc_add(VALUE self, VALUE another); VALUE csc_sub(VALUE self, VALUE another); @@ -154,7 +203,6 @@ VALUE dia_get_elements(VALUE self); VALUE dia_get_count(VALUE self); VALUE dia_get_ndims(VALUE self); VALUE dia_alloc(VALUE klass); -void dia_free(dia_matrix* mat); VALUE dia_add(VALUE self, VALUE another); VALUE dia_sub(VALUE self, VALUE another); From 4ece4af8f1ca38d36192bace0fe121adc50f3809 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Fri, 9 Apr 2021 03:11:19 +0530 Subject: [PATCH 10/14] add unary elementwise operators --- ext/coo/elementwise.c | 60 ++++++++++++++++++++++++++++++++++++++++- ext/csc/elementwise.c | 62 ++++++++++++++++++++++++++++++++++++++++++- ext/csr/elementwise.c | 62 ++++++++++++++++++++++++++++++++++++++++++- ext/dia/elementwise.c | 55 +++++++++++++++++++++++++++++++++++++- ext/ruby_sparse.c | 32 ++++++++++++++++++++++ 5 files changed, 267 insertions(+), 4 deletions(-) diff --git a/ext/coo/elementwise.c b/ext/coo/elementwise.c index 8d922f0..7e6559a 100644 --- a/ext/coo/elementwise.c +++ b/ext/coo/elementwise.c @@ -1,3 +1,7 @@ +#include "string.h" +#include "math.h" + + double coo_perform_oper(double val_a, double val_b, char oper) { switch(oper) { case '+': @@ -22,6 +26,7 @@ VALUE coo_elementwise_binary(VALUE self, VALUE another, char oper) { TypedData_Get_Struct(another, coo_matrix, &coo_data_type, right); coo_matrix* result = ALLOC(coo_matrix); + result->dtype = left->dtype; result->count = 0; result->ndims = left->ndims; result->shape = ALLOC_N(size_t, result->ndims); @@ -119,4 +124,57 @@ VALUE coo_sub(VALUE self, VALUE another) { VALUE coo_mul(VALUE self, VALUE another) { return coo_elementwise_binary(self, another, '*'); -} \ No newline at end of file +} + +double coo_unary_oper(double val, const char* oper) { + if (strcmp(oper, "sin") == 0) + return sin(val); + else if (strcmp(oper, "cos") == 0) + return cos(val); + else if (strcmp(oper, "tan") == 0) + return tan(val); + else + return 0.00; +} + +/* + Takes the matrix and performs unary operator elementwise +*/ +VALUE coo_elementwise_unary(VALUE self, const char* oper) { + coo_matrix* left; + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, left); + + coo_matrix* result = ALLOC(coo_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ia = ALLOC_N(size_t, left->count); + result->ja = ALLOC_N(size_t, left->count); + + for(size_t index = 0; index < result->count; index++) { + result->elements[index] = coo_unary_oper(left->elements[index], oper); + result->ia[index] = left->ia[index]; + result->ja[index] = left->ja[index]; + } + + return TypedData_Wrap_Struct(COO, &coo_data_type, result); +} + +VALUE coo_sin(VALUE self) { + return coo_elementwise_unary(self, "sin"); +} + +VALUE coo_cos(VALUE self) { + return coo_elementwise_unary(self, "cos"); +} + +VALUE coo_tan(VALUE self) { + return coo_elementwise_unary(self, "tan"); +} diff --git a/ext/csc/elementwise.c b/ext/csc/elementwise.c index aa8f0dc..a0f82e4 100644 --- a/ext/csc/elementwise.c +++ b/ext/csc/elementwise.c @@ -1,3 +1,7 @@ +#include "string.h" +#include "math.h" + + double csc_perform_oper(double val_a, double val_b, char oper) { switch(oper) { case '+': @@ -129,4 +133,60 @@ VALUE csc_sub(VALUE self, VALUE another) { VALUE csc_mul(VALUE self, VALUE another) { return csc_elementwise_binary(self, another, '*'); -} \ No newline at end of file +} + +double csc_unary_oper(double val, const char* oper) { + if (strcmp(oper, "sin") == 0) + return sin(val); + else if (strcmp(oper, "cos") == 0) + return cos(val); + else if (strcmp(oper, "tan") == 0) + return tan(val); + else + return 0.00; +} + +/* + Takes the matrix and performs unary operator elementwise +*/ +VALUE csc_elementwise_unary(VALUE self, const char* oper) { + csc_matrix* left; + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, left); + + csc_matrix* result = ALLOC(csc_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ia = ALLOC_N(size_t, left->count); + result->jp = ALLOC_N(size_t, left->shape[1] + 1); + + for(size_t index = 0; index < result->count; index++) { + result->elements[index] = csc_unary_oper(left->elements[index], oper); + result->ia[index] = left->ia[index]; + } + + for(size_t index = 0; index <= left->shape[1]; index++) { + result->jp[index] = left->jp[index]; + } + + return TypedData_Wrap_Struct(CSC, &csc_data_type, result); +} + +VALUE csc_sin(VALUE self) { + return csc_elementwise_unary(self, "sin"); +} + +VALUE csc_cos(VALUE self) { + return csc_elementwise_unary(self, "cos"); +} + +VALUE csc_tan(VALUE self) { + return csc_elementwise_unary(self, "tan"); +} diff --git a/ext/csr/elementwise.c b/ext/csr/elementwise.c index 9c8e8cf..24c20f4 100644 --- a/ext/csr/elementwise.c +++ b/ext/csr/elementwise.c @@ -1,3 +1,7 @@ +#include "string.h" +#include "math.h" + + double csr_perform_oper(double val_a, double val_b, char oper) { switch(oper) { case '+': @@ -129,4 +133,60 @@ VALUE csr_sub(VALUE self, VALUE another) { VALUE csr_mul(VALUE self, VALUE another) { return csr_elementwise_binary(self, another, '*'); -} \ No newline at end of file +} + +double csr_unary_oper(double val, const char* oper) { + if (strcmp(oper, "sin") == 0) + return sin(val); + else if (strcmp(oper, "cos") == 0) + return cos(val); + else if (strcmp(oper, "tan") == 0) + return tan(val); + else + return 0.00; +} + +/* + Takes the matrix and performs unary operator elementwise +*/ +VALUE csr_elementwise_unary(VALUE self, const char* oper) { + csr_matrix* left; + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, left); + + csr_matrix* result = ALLOC(csr_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ip = ALLOC_N(size_t, left->shape[0] + 1); + result->ja = ALLOC_N(size_t, left->count); + + for(size_t index = 0; index < result->count; index++) { + result->elements[index] = csr_unary_oper(left->elements[index], oper); + result->ja[index] = left->ja[index]; + } + + for(size_t index = 0; index <= left->shape[0]; index++) { + result->ip[index] = left->ip[index]; + } + + return TypedData_Wrap_Struct(CSR, &csr_data_type, result); +} + +VALUE csr_sin(VALUE self) { + return csr_elementwise_unary(self, "sin"); +} + +VALUE csr_cos(VALUE self) { + return csr_elementwise_unary(self, "cos"); +} + +VALUE csr_tan(VALUE self) { + return csr_elementwise_unary(self, "tan"); +} diff --git a/ext/dia/elementwise.c b/ext/dia/elementwise.c index 4d0e963..4fb8839 100644 --- a/ext/dia/elementwise.c +++ b/ext/dia/elementwise.c @@ -1,3 +1,7 @@ +#include "string.h" +#include "math.h" + + double dia_perform_oper(double val_a, double val_b, char oper) { switch(oper) { case '+': @@ -50,4 +54,53 @@ VALUE dia_sub(VALUE self, VALUE another) { VALUE dia_mul(VALUE self, VALUE another) { return dia_elementwise_binary(self, another, '*'); -} \ No newline at end of file +} + +double dia_unary_oper(double val, const char* oper) { + if (strcmp(oper, "sin") == 0) + return sin(val); + else if (strcmp(oper, "cos") == 0) + return cos(val); + else if (strcmp(oper, "tan") == 0) + return tan(val); + else + return 0.00; +} + +/* + Takes the matrix and performs unary operator elementwise +*/ +VALUE dia_elementwise_unary(VALUE self, const char* oper) { + dia_matrix* left; + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, left); + + dia_matrix* result = ALLOC(dia_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + + for(size_t index = 0; index < result->count; index++) { + result->elements[index] = dia_unary_oper(left->elements[index], oper); + } + + return TypedData_Wrap_Struct(DIA, &dia_data_type, result); +} + +VALUE dia_sin(VALUE self) { + return dia_elementwise_unary(self, "sin"); +} + +VALUE dia_cos(VALUE self) { + return dia_elementwise_unary(self, "cos"); +} + +VALUE dia_tan(VALUE self) { + return dia_elementwise_unary(self, "tan"); +} diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index d6de3fd..69e7f22 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -159,6 +159,10 @@ VALUE coo_add(VALUE self, VALUE another); VALUE coo_sub(VALUE self, VALUE another); VALUE coo_mul(VALUE self, VALUE another); +VALUE coo_sin(VALUE self); +VALUE coo_cos(VALUE self); +VALUE coo_tan(VALUE self); + VALUE coo_from_nmatrix(VALUE self, VALUE nmat); // csr methods declaration @@ -176,6 +180,10 @@ VALUE csr_add(VALUE self, VALUE another); VALUE csr_sub(VALUE self, VALUE another); VALUE csr_mul(VALUE self, VALUE another); +VALUE csr_sin(VALUE self); +VALUE csr_cos(VALUE self); +VALUE csr_tan(VALUE self); + VALUE csr_from_nmatrix(VALUE self, VALUE nmat); // csc methods declaration @@ -193,6 +201,10 @@ VALUE csc_add(VALUE self, VALUE another); VALUE csc_sub(VALUE self, VALUE another); VALUE csc_mul(VALUE self, VALUE another); +VALUE csc_sin(VALUE self); +VALUE csc_cos(VALUE self); +VALUE csc_tan(VALUE self); + VALUE csc_from_nmatrix(VALUE self, VALUE nmat); // dia methods declaration @@ -208,6 +220,10 @@ VALUE dia_add(VALUE self, VALUE another); VALUE dia_sub(VALUE self, VALUE another); VALUE dia_mul(VALUE self, VALUE another); +VALUE dia_sin(VALUE self); +VALUE dia_cos(VALUE self); +VALUE dia_tan(VALUE self); + VALUE dia_from_nmatrix(VALUE self, VALUE nmat); @@ -234,6 +250,10 @@ void Init_ruby_sparse() { rb_define_method(COO, "-", coo_sub, 1); rb_define_method(COO, "*", coo_mul, 1); + rb_define_method(COO, "sin", coo_sin, 0); + rb_define_method(COO, "cos", coo_cos, 0); + rb_define_method(COO, "tan", coo_tan, 0); + //rb_define_singleton_method(COO, "from_nmatrix", coo_from_nmatrix, 1); @@ -251,6 +271,10 @@ void Init_ruby_sparse() { rb_define_method(CSR, "-", csr_sub, 1); rb_define_method(CSR, "*", csr_mul, 1); + rb_define_method(CSR, "sin", csr_sin, 0); + rb_define_method(CSR, "cos", csr_cos, 0); + rb_define_method(CSR, "tan", csr_tan, 0); + //rb_define_singleton_method(CSR, "from_nmatrix", csr_from_nmatrix, 1); @@ -268,6 +292,10 @@ void Init_ruby_sparse() { rb_define_method(CSC, "-", csc_sub, 1); rb_define_method(CSC, "*", csc_mul, 1); + rb_define_method(CSC, "sin", csc_sin, 0); + rb_define_method(CSC, "cos", csc_cos, 0); + rb_define_method(CSC, "tan", csc_tan, 0); + //rb_define_singleton_method(CSC, "from_nmatrix", csc_from_nmatrix, 1); @@ -282,6 +310,10 @@ void Init_ruby_sparse() { rb_define_method(DIA, "-", dia_sub, 1); rb_define_method(DIA, "*", dia_mul, 1); + rb_define_method(DIA, "sin", dia_sin, 0); + rb_define_method(DIA, "cos", dia_cos, 0); + rb_define_method(DIA, "tan", dia_tan, 0); + //rb_define_singleton_method(DIA, "from_nmatrix", dia_from_nmatrix, 1); } From 688d8ba6373301f0d65dd54a4931d87236c89653 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Fri, 9 Apr 2021 03:12:08 +0530 Subject: [PATCH 11/14] add unary operator tests --- test/elementwise_test.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/elementwise_test.rb b/test/elementwise_test.rb index 9e6c1da..67e7e03 100644 --- a/test/elementwise_test.rb +++ b/test/elementwise_test.rb @@ -37,6 +37,16 @@ def test_mul assert_equal answer.coords, result.coords end + def test_sin + result = RubySparse::COO.new [3, 3], [0.8414709848078965, 0.9092974268256817, 0.1411200080598672], [0, 1, 2], [0, 1, 2] + answer = @left.sin + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.coords, result.coords + end + end class RubySparse::DIA::ElementWiseTest < Minitest::Test @@ -70,6 +80,14 @@ def test_mul assert_equal answer.elements, result.elements end + def test_sin + result = RubySparse::DIA.new [3, 3], [0.8414709848078965, 0.0, 0.1411200080598672] + answer = @left.sin + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.elements, result.elements + end + end class RubySparse::CSR::ElementWiseTest < Minitest::Test @@ -112,6 +130,17 @@ def test_mul assert_equal answer.indptr, result.indptr end + def test_sin + result = RubySparse::CSR.new [3, 3], [0.8414709848078965, 0.9092974268256817, 0.1411200080598672], [0, 1, 2], [0, 1, 2] + answer = @left.sin + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + end class RubySparse::CSC::ElementWiseTest < Minitest::Test @@ -154,4 +183,15 @@ def test_mul assert_equal answer.indptr, result.indptr end + def test_sin + result = RubySparse::CSC.new [3, 3], [0.8414709848078965, 0.9092974268256817, 0.1411200080598672], [0, 1, 2], [0, 1, 2] + answer = @left.sin + assert_equal answer.dim, result.dim + assert_equal answer.shape, result.shape + assert_equal answer.nzcount, result.nzcount + assert_equal answer.elements, result.elements + assert_equal answer.indices, result.indices + assert_equal answer.indptr, result.indptr + end + end From 6450772888ffcd71c020e1bf10989a56215833a5 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Sat, 10 Apr 2021 03:02:09 +0530 Subject: [PATCH 12/14] add inter sparse conversion --- ext/coo/coo_def.c | 96 ++++++++++++++++++++++++++++++++++ ext/csc/csc_def.c | 30 +++++++++++ ext/csr/csr_def.c | 30 +++++++++++ ext/ruby_sparse.c | 14 +++++ lib/ruby_sparse/ruby_sparse.rb | 78 ++++++++++++++------------- 5 files changed, 213 insertions(+), 35 deletions(-) diff --git a/ext/coo/coo_def.c b/ext/coo/coo_def.c index cddaeab..21df154 100644 --- a/ext/coo/coo_def.c +++ b/ext/coo/coo_def.c @@ -130,5 +130,101 @@ VALUE coo_get_shape(VALUE self) { return rb_ary_new4(input->ndims, array); } +VALUE coo_to_csr(VALUE self) { + coo_matrix* left; + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, left); + + csr_matrix* result = ALLOC(csr_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ip = ALLOC_N(size_t, left->shape[0] + 1); + result->ja = ALLOC_N(size_t, left->count); + + for(size_t index = 0; index <= result->shape[0]; index++) result->ip[index] = 0; + for(size_t index = 0; index < result->count; index++) { + size_t row_index_val = left->ia[index]; + result->ip[row_index_val] += 1; + } + for(size_t index = 0, cumsum = 0; index < result->shape[0]; index++) { + size_t temp = result->ip[index]; + result->ip[index] = cumsum; + cumsum += temp; + } + result->ip[result->shape[0]] = result->count; + for(size_t index = 0; index < result->count; index++) { + size_t row = left->ia[index]; + size_t dest = result->ip[row]; + + result->ja[dest] = left->ja[index]; + result->elements[dest] = left->elements[index]; + + result->ip[row] += 1; + } + + for(size_t index = 0, last = 0; index <= result->shape[0]; index++) { + size_t temp = result->ip[index]; + result->ip[index] = last; + last = temp; + } + + return TypedData_Wrap_Struct(CSR, &csr_data_type, result); +} + +VALUE coo_to_csc(VALUE self) { + coo_matrix* left; + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, left); + + csc_matrix* result = ALLOC(csc_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ia = ALLOC_N(size_t, left->count); + result->jp = ALLOC_N(size_t, left->shape[1] + 1); + + for(size_t index = 0; index <= result->shape[1]; index++) result->jp[index] = 0; + for(size_t index = 0; index < result->count; index++) { + size_t col_index_val = left->ja[index]; + result->jp[col_index_val] += 1; + } + for(size_t index = 0, cumsum = 0; index < result->shape[1]; index++) { + size_t temp = result->jp[index]; + result->jp[index] = cumsum; + cumsum += temp; + } + result->jp[result->shape[1]] = result->count; + for(size_t index = 0; index < result->count; index++) { + size_t col = left->ja[index]; + size_t dest = result->jp[col]; + + result->ia[dest] = left->ia[index]; + result->elements[dest] = left->elements[index]; + + result->jp[col] += 1; + } + + for(size_t index = 0, last = 0; index <= result->shape[1]; index++) { + size_t temp = result->jp[index]; + result->jp[index] = last; + last = temp; + } + + return TypedData_Wrap_Struct(CSC, &csc_data_type, result); +} + #include "elementwise.c" \ No newline at end of file diff --git a/ext/csc/csc_def.c b/ext/csc/csc_def.c index 439a5aa..e8a5eae 100644 --- a/ext/csc/csc_def.c +++ b/ext/csc/csc_def.c @@ -154,5 +154,35 @@ VALUE csc_get_shape(VALUE self) { return rb_ary_new4(input->ndims, array); } +VALUE csc_to_coo(VALUE self) { + csc_matrix* left; + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, left); + + coo_matrix* result = ALLOC(coo_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ia = ALLOC_N(size_t, left->count); + result->ja = ALLOC_N(size_t, left->count); + + for(size_t j = 0; j < left->shape[1]; j++) { + for(size_t i = left->jp[j]; i < left->jp[j + 1]; i++) { + // size_t index = (left->shape[0] * j) + left->ia[i]; + result->elements[i] = left->elements[i]; + result->ia[i] = left->ia[i]; + result->ja[i] = j; + } + } + + return TypedData_Wrap_Struct(COO, &coo_data_type, result); +} + #include "elementwise.c" \ No newline at end of file diff --git a/ext/csr/csr_def.c b/ext/csr/csr_def.c index 04997e4..6db9946 100644 --- a/ext/csr/csr_def.c +++ b/ext/csr/csr_def.c @@ -154,5 +154,35 @@ VALUE csr_get_shape(VALUE self) { return rb_ary_new4(input->ndims, array); } +VALUE csr_to_coo(VALUE self) { + csr_matrix* left; + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, left); + + coo_matrix* result = ALLOC(coo_matrix); + result->dtype = left->dtype; + result->count = left->count; + result->ndims = left->ndims; + result->shape = ALLOC_N(size_t, result->ndims); + + for (size_t index = 0; index < result->ndims; index++) { + result->shape[index] = left->shape[index]; + } + + result->elements = ALLOC_N(double, left->count); + result->ia = ALLOC_N(size_t, left->count); + result->ja = ALLOC_N(size_t, left->count); + + for(size_t i = 0; i < left->shape[0]; i++) { + for(size_t j = left->ip[i]; j < left->ip[i + 1]; j++) { + // size_t index = (left->shape[1] * i) + left->ja[j]; + result->elements[j] = left->elements[j]; + result->ia[j] = i; + result->ja[j] = left->ja[j]; + } + } + + return TypedData_Wrap_Struct(COO, &coo_data_type, result); +} + #include "elementwise.c" \ No newline at end of file diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index 69e7f22..0f594d0 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -155,6 +155,9 @@ VALUE coo_get_count(VALUE self); VALUE coo_get_ndims(VALUE self); VALUE coo_alloc(VALUE klass); +VALUE coo_to_csr(VALUE self); +VALUE coo_to_csc(VALUE self); + VALUE coo_add(VALUE self, VALUE another); VALUE coo_sub(VALUE self, VALUE another); VALUE coo_mul(VALUE self, VALUE another); @@ -176,6 +179,8 @@ VALUE csr_get_count(VALUE self); VALUE csr_get_ndims(VALUE self); VALUE csr_alloc(VALUE klass); +VALUE csr_to_coo(VALUE self); + VALUE csr_add(VALUE self, VALUE another); VALUE csr_sub(VALUE self, VALUE another); VALUE csr_mul(VALUE self, VALUE another); @@ -197,6 +202,8 @@ VALUE csc_get_count(VALUE self); VALUE csc_get_ndims(VALUE self); VALUE csc_alloc(VALUE klass); +VALUE csc_to_coo(VALUE self); + VALUE csc_add(VALUE self, VALUE another); VALUE csc_sub(VALUE self, VALUE another); VALUE csc_mul(VALUE self, VALUE another); @@ -246,6 +253,9 @@ void Init_ruby_sparse() { rb_define_method(COO, "nzcount", coo_get_count, 0); rb_define_method(COO, "dim", coo_get_ndims, 0); + rb_define_method(COO, "to_csr", coo_to_csr, 0); + rb_define_method(COO, "to_csc", coo_to_csc, 0); + rb_define_method(COO, "+", coo_add, 1); rb_define_method(COO, "-", coo_sub, 1); rb_define_method(COO, "*", coo_mul, 1); @@ -267,6 +277,8 @@ void Init_ruby_sparse() { rb_define_method(CSR, "nzcount", csr_get_count, 0); rb_define_method(CSR, "dim", csr_get_ndims, 0); + rb_define_method(CSR, "to_coo", csr_to_coo, 0); + rb_define_method(CSR, "+", csr_add, 1); rb_define_method(CSR, "-", csr_sub, 1); rb_define_method(CSR, "*", csr_mul, 1); @@ -288,6 +300,8 @@ void Init_ruby_sparse() { rb_define_method(CSC, "nzcount", csc_get_count, 0); rb_define_method(CSC, "dim", csc_get_ndims, 0); + rb_define_method(CSC, "to_coo", csc_to_coo, 0); + rb_define_method(CSC, "+", csc_add, 1); rb_define_method(CSC, "-", csc_sub, 1); rb_define_method(CSC, "*", csc_mul, 1); diff --git a/lib/ruby_sparse/ruby_sparse.rb b/lib/ruby_sparse/ruby_sparse.rb index 3aab6b5..c6760f5 100644 --- a/lib/ruby_sparse/ruby_sparse.rb +++ b/lib/ruby_sparse/ruby_sparse.rb @@ -29,14 +29,6 @@ def inspect #:nodoc: original_inspect = original_inspect[0...original_inspect.size-1] original_inspect + "; " + inspect_helper.join("; ") + ">" end - - protected - - def inspect_helper #:nodoc: - ary = [] - ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" - ary - end def self.from_nmatrix(nmat) nm_elements = nmat.elements @@ -110,6 +102,14 @@ def self._load args self.new(shape, elements, ia, ja) end + + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end end @@ -131,14 +131,6 @@ def inspect #:nodoc: original_inspect = original_inspect[0...original_inspect.size-1] original_inspect + "; " + inspect_helper.join("; ") + ">" end - - protected - - def inspect_helper #:nodoc: - ary = [] - ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" - ary - end def self.from_nmatrix(nmat) nm_elements = nmat.elements @@ -193,6 +185,14 @@ def self._load args self.new(shape, elements) end + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + end class CSR < SparseArray @@ -213,14 +213,6 @@ def inspect #:nodoc: original_inspect = original_inspect[0...original_inspect.size-1] original_inspect + "; " + inspect_helper.join("; ") + ">" end - - protected - - def inspect_helper #:nodoc: - ary = [] - ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" - ary - end def self.from_nmatrix(nmat) nm_elements = nmat.elements @@ -267,6 +259,10 @@ def to_nmatrix return m end + def to_csc + return self.to_coo.to_csc + end + def _dump data [ dim, @@ -299,6 +295,14 @@ def self._load args self.new(shape, elements, ip, ja) end + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + end class CSC < SparseArray @@ -319,14 +323,6 @@ def inspect #:nodoc: original_inspect = original_inspect[0...original_inspect.size-1] original_inspect + "; " + inspect_helper.join("; ") + ">" end - - protected - - def inspect_helper #:nodoc: - ary = [] - ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" - ary - end def self.from_nmatrix(nmat) nm_elements = nmat.elements @@ -363,9 +359,9 @@ def to_nmatrix nm_elements = Array.new(self.shape[0]*self.shape[1], 0) for j in (0...self.shape[1]) - for i in (jp[i]...jp[i + 1]) - nm_index = (self.shape[0] * i) + ia[j] - nm_elements[nm_index] = self.elements[j] + for i in (jp[j]...jp[j + 1]) + nm_index = (self.shape[0] * j) + ia[i] + nm_elements[nm_index] = self.elements[i] end end @@ -373,6 +369,10 @@ def to_nmatrix return m end + def to_csr + return self.to_coo.to_csr + end + def _dump data [ dim, @@ -405,5 +405,13 @@ def self._load args self.new(shape, elements, ia, jp) end + protected + + def inspect_helper #:nodoc: + ary = [] + ary << "shape: [#{shape.join(',')}]" << "dtype: #{dtype}" << "nnz: #{nzcount}" + ary + end + end end \ No newline at end of file From 071278520ed144f4773ea9824b6e76614c4325dc Mon Sep 17 00:00:00 2001 From: uditgulati Date: Sat, 10 Apr 2021 03:39:56 +0530 Subject: [PATCH 13/14] add iteration for sparse types --- ext/coo/coo_def.c | 3 ++- ext/coo/iteration.c | 27 +++++++++++++++++++++++++++ ext/csc/csc_def.c | 3 ++- ext/csc/iteration.c | 30 ++++++++++++++++++++++++++++++ ext/csr/csr_def.c | 3 ++- ext/csr/iteration.c | 30 ++++++++++++++++++++++++++++++ ext/dia/dia_def.c | 3 ++- ext/dia/iteration.c | 11 +++++++++++ ext/ruby_sparse.c | 22 ++++++++++++++++++++++ 9 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 ext/coo/iteration.c create mode 100644 ext/csc/iteration.c create mode 100644 ext/csr/iteration.c create mode 100644 ext/dia/iteration.c diff --git a/ext/coo/coo_def.c b/ext/coo/coo_def.c index 21df154..b8ea941 100644 --- a/ext/coo/coo_def.c +++ b/ext/coo/coo_def.c @@ -227,4 +227,5 @@ VALUE coo_to_csc(VALUE self) { } -#include "elementwise.c" \ No newline at end of file +#include "elementwise.c" +#include "iteration.c" \ No newline at end of file diff --git a/ext/coo/iteration.c b/ext/coo/iteration.c new file mode 100644 index 0000000..fab96ee --- /dev/null +++ b/ext/coo/iteration.c @@ -0,0 +1,27 @@ +VALUE coo_each(VALUE self) { + coo_matrix* input; + + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); + + for (size_t index = 0; index < input->count; index++) { + rb_yield(DBL2NUM(input->elements[index])); + } + + return self; +} + +VALUE coo_each_with_indices(VALUE self) { + coo_matrix* input; + + TypedData_Get_Struct(self, coo_matrix, &coo_data_type, input); + + VALUE* result_array = ALLOC_N(VALUE, input->ndims + 1); + for (size_t index = 0; index < input->count; index++) { + result_array[0] = DBL2NUM(input->elements[index]); + result_array[1] = INT2NUM(input->ia[index]); + result_array[2] = INT2NUM(input->ja[index]); + rb_yield(rb_ary_new4(input->ndims + 1, result_array)); + } + + return self; +} \ No newline at end of file diff --git a/ext/csc/csc_def.c b/ext/csc/csc_def.c index e8a5eae..4d41287 100644 --- a/ext/csc/csc_def.c +++ b/ext/csc/csc_def.c @@ -185,4 +185,5 @@ VALUE csc_to_coo(VALUE self) { } -#include "elementwise.c" \ No newline at end of file +#include "elementwise.c" +#include "iteration.c" \ No newline at end of file diff --git a/ext/csc/iteration.c b/ext/csc/iteration.c new file mode 100644 index 0000000..341d48e --- /dev/null +++ b/ext/csc/iteration.c @@ -0,0 +1,30 @@ +VALUE csc_each(VALUE self) { + csc_matrix* input; + + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); + + for (size_t index = 0; index < input->count; index++) { + rb_yield(DBL2NUM(input->elements[index])); + } + + return self; +} + +VALUE csc_each_column(VALUE self) { + csc_matrix* input; + + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); + + for (size_t j = 0; j < input->shape[1]; j++) { + size_t col_len = input->jp[j + 1] - input->jp[j]; + VALUE* col_array = ALLOC_N(VALUE, col_len); + + for(size_t i = input->jp[j]; i < input->jp[j + 1]; i++) { + col_array[i - input->jp[j]] = DBL2NUM(input->elements[i]); + } + + rb_yield(rb_ary_new4(col_len, col_array)); + } + + return self; +} \ No newline at end of file diff --git a/ext/csr/csr_def.c b/ext/csr/csr_def.c index 6db9946..5d32ebe 100644 --- a/ext/csr/csr_def.c +++ b/ext/csr/csr_def.c @@ -185,4 +185,5 @@ VALUE csr_to_coo(VALUE self) { } -#include "elementwise.c" \ No newline at end of file +#include "elementwise.c" +#include "iteration.c" \ No newline at end of file diff --git a/ext/csr/iteration.c b/ext/csr/iteration.c new file mode 100644 index 0000000..52cc41c --- /dev/null +++ b/ext/csr/iteration.c @@ -0,0 +1,30 @@ +VALUE csr_each(VALUE self) { + csr_matrix* input; + + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); + + for (size_t index = 0; index < input->count; index++) { + rb_yield(DBL2NUM(input->elements[index])); + } + + return self; +} + +VALUE csr_each_row(VALUE self) { + csr_matrix* input; + + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); + + for (size_t i = 0; i < input->shape[0]; i++) { + size_t row_len = input->ip[i + 1] - input->ip[i]; + VALUE* row_array = ALLOC_N(VALUE, row_len); + + for(size_t j = input->ip[i]; j < input->ip[i + 1]; j++) { + row_array[j - input->ip[i]] = DBL2NUM(input->elements[j]); + } + + rb_yield(rb_ary_new4(row_len, row_array)); + } + + return self; +} \ No newline at end of file diff --git a/ext/dia/dia_def.c b/ext/dia/dia_def.c index 548e687..3b590df 100644 --- a/ext/dia/dia_def.c +++ b/ext/dia/dia_def.c @@ -98,4 +98,5 @@ VALUE dia_get_shape(VALUE self) { } -#include "elementwise.c" \ No newline at end of file +#include "elementwise.c" +#include "iteration.c" \ No newline at end of file diff --git a/ext/dia/iteration.c b/ext/dia/iteration.c new file mode 100644 index 0000000..e27ff3a --- /dev/null +++ b/ext/dia/iteration.c @@ -0,0 +1,11 @@ +VALUE dia_each(VALUE self) { + dia_matrix* input; + + TypedData_Get_Struct(self, dia_matrix, &dia_data_type, input); + + for (size_t index = 0; index < input->count; index++) { + rb_yield(DBL2NUM(input->elements[index])); + } + + return self; +} \ No newline at end of file diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index 0f594d0..006ee7e 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -166,6 +166,9 @@ VALUE coo_sin(VALUE self); VALUE coo_cos(VALUE self); VALUE coo_tan(VALUE self); +VALUE coo_each(VALUE self); +VALUE coo_each_with_indices(VALUE self); + VALUE coo_from_nmatrix(VALUE self, VALUE nmat); // csr methods declaration @@ -189,6 +192,9 @@ VALUE csr_sin(VALUE self); VALUE csr_cos(VALUE self); VALUE csr_tan(VALUE self); +VALUE csr_each(VALUE self); +VALUE csr_each_row(VALUE self); + VALUE csr_from_nmatrix(VALUE self, VALUE nmat); // csc methods declaration @@ -212,6 +218,9 @@ VALUE csc_sin(VALUE self); VALUE csc_cos(VALUE self); VALUE csc_tan(VALUE self); +VALUE csc_each(VALUE self); +VALUE csc_each_column(VALUE self); + VALUE csc_from_nmatrix(VALUE self, VALUE nmat); // dia methods declaration @@ -231,6 +240,8 @@ VALUE dia_sin(VALUE self); VALUE dia_cos(VALUE self); VALUE dia_tan(VALUE self); +VALUE dia_each(VALUE self); + VALUE dia_from_nmatrix(VALUE self, VALUE nmat); @@ -264,6 +275,9 @@ void Init_ruby_sparse() { rb_define_method(COO, "cos", coo_cos, 0); rb_define_method(COO, "tan", coo_tan, 0); + rb_define_method(COO, "each", coo_each, 0); + rb_define_method(COO, "each_with_indices", coo_each_with_indices, 0); + //rb_define_singleton_method(COO, "from_nmatrix", coo_from_nmatrix, 1); @@ -287,6 +301,9 @@ void Init_ruby_sparse() { rb_define_method(CSR, "cos", csr_cos, 0); rb_define_method(CSR, "tan", csr_tan, 0); + rb_define_method(CSR, "each", csr_each, 0); + rb_define_method(CSR, "each_row", csr_each_row, 0); + //rb_define_singleton_method(CSR, "from_nmatrix", csr_from_nmatrix, 1); @@ -310,6 +327,9 @@ void Init_ruby_sparse() { rb_define_method(CSC, "cos", csc_cos, 0); rb_define_method(CSC, "tan", csc_tan, 0); + rb_define_method(CSC, "each", csc_each, 0); + rb_define_method(CSC, "each_column", csc_each_column, 0); + //rb_define_singleton_method(CSC, "from_nmatrix", csc_from_nmatrix, 1); @@ -328,6 +348,8 @@ void Init_ruby_sparse() { rb_define_method(DIA, "cos", dia_cos, 0); rb_define_method(DIA, "tan", dia_tan, 0); + rb_define_method(DIA, "each", dia_each, 0); + //rb_define_singleton_method(DIA, "from_nmatrix", dia_from_nmatrix, 1); } From 9a426a5f03ca0b1f327c45b56b809109acc584f0 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Wed, 14 Apr 2021 21:08:50 +0530 Subject: [PATCH 14/14] add with_indices iterator for CSR, CSC --- ext/csc/iteration.c | 23 +++++++++++++++++++++++ ext/csr/iteration.c | 23 +++++++++++++++++++++++ ext/ruby_sparse.c | 4 ++++ 3 files changed, 50 insertions(+) diff --git a/ext/csc/iteration.c b/ext/csc/iteration.c index 341d48e..a3af78e 100644 --- a/ext/csc/iteration.c +++ b/ext/csc/iteration.c @@ -26,5 +26,28 @@ VALUE csc_each_column(VALUE self) { rb_yield(rb_ary_new4(col_len, col_array)); } + return self; +} + +VALUE csc_each_with_indices(VALUE self) { + csc_matrix* input; + + TypedData_Get_Struct(self, csc_matrix, &csc_data_type, input); + + VALUE* result_array = ALLOC_N(VALUE, input->ndims + 1); + + for (size_t j = 0; j < input->shape[1]; j++) { + size_t col_index = j; + for(size_t i = input->jp[j]; i < input->jp[j + 1]; i++) { + size_t row_index = input->ia[i]; + size_t index = i; + result_array[0] = DBL2NUM(input->elements[index]); + result_array[1] = INT2NUM(row_index); + result_array[2] = INT2NUM(col_index); + rb_yield(rb_ary_new4(input->ndims + 1, result_array)); + + } + } + return self; } \ No newline at end of file diff --git a/ext/csr/iteration.c b/ext/csr/iteration.c index 52cc41c..c1a4781 100644 --- a/ext/csr/iteration.c +++ b/ext/csr/iteration.c @@ -26,5 +26,28 @@ VALUE csr_each_row(VALUE self) { rb_yield(rb_ary_new4(row_len, row_array)); } + return self; +} + +VALUE csr_each_with_indices(VALUE self) { + csr_matrix* input; + + TypedData_Get_Struct(self, csr_matrix, &csr_data_type, input); + + VALUE* result_array = ALLOC_N(VALUE, input->ndims + 1); + + for (size_t i = 0; i < input->shape[0]; i++) { + size_t row_index = i; + for(size_t j = input->ip[i]; j < input->ip[i + 1]; j++) { + size_t col_index = input->ja[j]; + size_t index = j; + result_array[0] = DBL2NUM(input->elements[index]); + result_array[1] = INT2NUM(row_index); + result_array[2] = INT2NUM(col_index); + rb_yield(rb_ary_new4(input->ndims + 1, result_array)); + + } + } + return self; } \ No newline at end of file diff --git a/ext/ruby_sparse.c b/ext/ruby_sparse.c index 006ee7e..98d2662 100644 --- a/ext/ruby_sparse.c +++ b/ext/ruby_sparse.c @@ -194,6 +194,7 @@ VALUE csr_tan(VALUE self); VALUE csr_each(VALUE self); VALUE csr_each_row(VALUE self); +VALUE csr_each_with_indices(VALUE self); VALUE csr_from_nmatrix(VALUE self, VALUE nmat); @@ -220,6 +221,7 @@ VALUE csc_tan(VALUE self); VALUE csc_each(VALUE self); VALUE csc_each_column(VALUE self); +VALUE csc_each_with_indices(VALUE self); VALUE csc_from_nmatrix(VALUE self, VALUE nmat); @@ -303,6 +305,7 @@ void Init_ruby_sparse() { rb_define_method(CSR, "each", csr_each, 0); rb_define_method(CSR, "each_row", csr_each_row, 0); + rb_define_method(CSR, "each_with_indices", csr_each_with_indices, 0); //rb_define_singleton_method(CSR, "from_nmatrix", csr_from_nmatrix, 1); @@ -329,6 +332,7 @@ void Init_ruby_sparse() { rb_define_method(CSC, "each", csc_each, 0); rb_define_method(CSC, "each_column", csc_each_column, 0); + rb_define_method(CSC, "each_with_indices", csc_each_with_indices, 0); //rb_define_singleton_method(CSC, "from_nmatrix", csc_from_nmatrix, 1);