Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RubyGrant 2020 related work #14

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
132 changes: 122 additions & 10 deletions ext/coo/coo_def.c
Original file line number Diff line number Diff line change
@@ -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, &coo_data_type, mat);

if(argc > 0){
mat->dtype = sp_float64;
Expand Down Expand Up @@ -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 Data_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;

Data_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++) {
Expand All @@ -57,7 +72,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, &coo_data_type, input);

VALUE* array_ia = ALLOC_N(VALUE, input->count);
for (size_t index = 0; index < input->count; index++) {
Expand All @@ -78,7 +93,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, &coo_data_type, input);

return SIZET2NUM(input->count);
}
Expand All @@ -87,7 +102,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, &coo_data_type, input);

return SIZET2NUM(input->ndims);
}
Expand All @@ -96,7 +111,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, &coo_data_type, input);

return ID2SYM(rb_intern(DTYPE_NAMES[input->dtype]));
}
Expand All @@ -105,7 +120,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, &coo_data_type, input);

VALUE* array = ALLOC_N(VALUE, input->ndims);
for (size_t index = 0; index < input->ndims; index++) {
Expand All @@ -115,5 +130,102 @@ 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"
#include "elementwise.c"
#include "iteration.c"
80 changes: 74 additions & 6 deletions ext/coo/elementwise.c
Original file line number Diff line number Diff line change
@@ -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 '+':
Expand All @@ -18,10 +22,11 @@ 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, &coo_data_type, left);
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);
Expand Down Expand Up @@ -79,7 +84,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];

Expand All @@ -88,15 +98,20 @@ 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];

right_index++, result_index++;
result->count++;
}

return Data_Wrap_Struct(COO, NULL, coo_free, result);
return TypedData_Wrap_Struct(COO, &coo_data_type, result);
}

VALUE coo_add(VALUE self, VALUE another) {
Expand All @@ -109,4 +124,57 @@ VALUE coo_sub(VALUE self, VALUE another) {

VALUE coo_mul(VALUE self, VALUE another) {
return coo_elementwise_binary(self, another, '*');
}
}

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");
}
27 changes: 27 additions & 0 deletions ext/coo/iteration.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading