diff --git a/bct.h b/bct.h index 2ef8f64..ec868db 100644 --- a/bct.h +++ b/bct.h @@ -164,6 +164,7 @@ namespace bct { void gsl_free(gsl_vector* v); void gsl_free(gsl_matrix* m); void gsl_free(std::vector& m); + void gsl_free(gsl_permutation* p); void init(); int number_of_edges_dir(const gsl_matrix* m); int number_of_edges_und(const gsl_matrix* m); diff --git a/bct_gsl.i b/bct_gsl.i index a4afd21..ec707c6 100644 --- a/bct_gsl.i +++ b/bct_gsl.i @@ -164,6 +164,7 @@ namespace bct { void gsl_free(gsl_vector* v); void gsl_free(gsl_matrix* m); void gsl_free(std::vector& m); + void gsl_free(gsl_permutation* p); void init(); int number_of_edges_dir(const gsl_matrix* m); int number_of_edges_und(const gsl_matrix* m); @@ -380,6 +381,8 @@ namespace matlab { PyObject* from_gsl(const gsl_vector* v); PyObject* from_gsl(const gsl_matrix* m); PyObject* from_gsl(const std::vector& m); +PyObject* from_gsl(const gsl_permutation* p); gsl_vector* to_gslv(PyObject* list); gsl_matrix* to_gslm(PyObject* list); std::vector to_gsl3dm(PyObject* list); +gsl_permutation* to_gslp(PyObject* list); diff --git a/bct_py.i b/bct_py.i index cb2c241..8dc2b0d 100644 --- a/bct_py.i +++ b/bct_py.i @@ -26,6 +26,11 @@ %typemap(freearg) std::vector { bct::gsl_free($1); } %typemap(out) std::vector { %append_output(from_gsl($1)); bct::gsl_free($1); } +%typemap(typecheck) gsl_permutation* { $1 = is_gslp($input) ? 1 : 0; } +%typemap(in) gsl_permutation* { $1 = to_gslp($input); } +%typemap(freearg) gsl_permutation* { bct::gsl_free($1); } +%typemap(out) gsl_permutation* { %append_output(from_gsl($1)); bct::gsl_free($1); } + %typemap(in, numinputs = 0) gsl_vector** (gsl_vector* temp) { $1 = &temp; } %typemap(argout) gsl_vector** { %append_output(from_gsl(*$1)); bct::gsl_free(*$1); } diff --git a/swig.i b/swig.i index 92a1fbf..228bca6 100644 --- a/swig.i +++ b/swig.i @@ -1,6 +1,9 @@ %{ + #include #include + #include #include + #include #include #include @@ -43,6 +46,35 @@ return is_ndim_list(object, 3); } + /* + * Checks if a PyObject* can be converted to a gsl_permutation*. + */ + bool is_gslp(PyObject* object) { + if (!is_ndim_list(object, 1)) { + return false; + } + int n = PyList_Size(object); + std::vector found(n, false); + for (int i = 0; i < n; i++) { + double value = PyFloat_AsDouble(PyList_GetItem(object, i)); + if (value < 0.0) { + return false; + } + double int_part; + double frac_part = std::modf(value, &int_part); + if (frac_part > std::numeric_limits::epsilon()) { + return false; + } + int index = (int)int_part; + if (index >= n || found[index]) { + return false; + } else { + found[index] = true; + } + } + return true; + } + /* * Converts a gsl_vector* to a Python list. */ @@ -95,6 +127,18 @@ return list; } + /* + * Converts a gsl_permutation* to a Python list. + */ + PyObject* from_gsl(const gsl_permutation* p) { + PyObject* list = PyList_New(p->size); + for (int i = 0; i < (int)p->size; i++) { + PyObject* value = PyFloat_FromDouble(gsl_permutation_get(p, i)); + PyList_SetItem(list, i, value); + } + return list; + } + /* * Converts a Python list to a gsl_vector*. */ @@ -151,4 +195,21 @@ } return m; } + + /* + * Converts a Python list to a gsl_permutation*. + */ + gsl_permutation* to_gslp(PyObject* list) { + int n = PyList_Size(list); + gsl_permutation* p = gsl_permutation_alloc(n); + for (int i = 0; i < n; i++) { + p->data[i] = (int)PyFloat_AsDouble(PyList_GetItem(list, i)); + } + if (gsl_permutation_valid(p) == 1) { + gsl_permutation_free(p); + return NULL; + } else { + return p; + } + } %} diff --git a/utility.cpp b/utility.cpp index 8f0ba2a..7e77871 100644 --- a/utility.cpp +++ b/utility.cpp @@ -1,6 +1,7 @@ #include "bct.h" #include #include +#include #include #include #include @@ -28,6 +29,7 @@ void bct::gsl_free(std::vector& m) { } } } +void bct::gsl_free(gsl_permutation* p) { gsl_permutation_free(p); } /* * Initializes the BCT library for external use.