Skip to content

Commit

Permalink
Merge pull request #642 from gsomix/buffer_protocol
Browse files Browse the repository at this point in the history
[Check it!] Preliminary design of buffer protocol stuff.
  • Loading branch information
Soeren Sonnenburg committed Jul 13, 2012
2 parents fdd7763 + caae3ab commit a6d49a5
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 1 deletion.
@@ -0,0 +1,29 @@
from shogun.Features import RealFeatures
from numpy import array, float64, all

# create dense matrices A,B,C
matrix=array([[1,2,3],[4,0,0],[0,0,0],[0,5,0],[0,0,6],[9,9,9]], dtype=float64)

parameter_list = [[matrix]]

# ... of type LongInt
def features_dense_real_modular(A=matrix):

# ... of type Real, LongInt and Byte
a=RealFeatures(A)
a.set_feature_vector(array([1,4,0,0,0,9], dtype=float64), 0)

# get matrix
a_out = a.get_feature_matrix()

b = array(a) + a

print b
print a_out

assert(all(a_out==A))
return a_out

if __name__=='__main__':
print('dense_real')
features_dense_real_modular(*parameter_list[0])
57 changes: 56 additions & 1 deletion src/interfaces/modular/Features.i
Expand Up @@ -289,40 +289,95 @@ namespace shogun
namespace shogun
{
#ifdef USE_BOOL
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(BoolFeatures, bool, bool, "?\0")
#endif

%template(BoolFeatures) CDenseFeatures<bool>;
#endif

#ifdef USE_CHAR
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(CharFeatures, char, char, "c\0")
#endif

%template(CharFeatures) CDenseFeatures<char>;
#endif

#ifdef USE_UINT8
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(ByteFeatures, uint8_t, unsigned char, "B\0")
#endif

%template(ByteFeatures) CDenseFeatures<uint8_t>;
#endif

#ifdef USE_UINT16
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(WordFeatures, uint16_t, unsigned short, "H\0")
#endif

%template(WordFeatures) CDenseFeatures<uint16_t>;
#endif

#ifdef USE_INT16
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(ShortFeatures, int16_t, short, "h\0")
#endif

%template(ShortFeatures) CDenseFeatures<int16_t>;
#endif

#ifdef USE_INT32
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(IntFeatures, int32_t, int, "i\0")
#endif

%template(IntFeatures) CDenseFeatures<int32_t>;
#endif

#ifdef USE_UINT32
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(UIntFeatures, uint32_t, unsigned int, "I\0")
#endif

%template(UIntFeatures) CDenseFeatures<uint32_t>;
#endif

#ifdef USE_INT64
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(LongIntFeatures, int64_t, long, "l\0")
#endif

%template(LongIntFeatures) CDenseFeatures<int64_t>;
#endif

#ifdef USE_UINT64
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(ULongIntFeatures, uint64_t, unsigned long , "L\0")
#endif

%template(ULongIntFeatures) CDenseFeatures<uint64_t>;
#endif

#ifdef USE_FLOATMAX
%template(LongRealFeatures) CDenseFeatures<floatmax_t>;
#endif

#ifdef USE_FLOAT32
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(ShortRealFeatures, float64_t, double, "f\0")
#endif

%template(ShortRealFeatures) CDenseFeatures<float32_t>;
#endif

#ifdef USE_FLOAT64
%template(RealFeatures) CDenseFeatures<float64_t>;
#ifdef HAVE_PYTHON
BUFFER_DENSEFEATURES(RealFeatures, float64_t, double, "d\0")
#endif

%template(RealFeatures) CDenseFeatures<float64_t>;
#endif
}

Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/modular/modshogun.i
Expand Up @@ -44,6 +44,11 @@

%include "modshogun_ignores.i"

/* Include helper functions for python buffer protocol */
#ifdef HAVE_PYTHON
%include "python_buffer_protocol.i"
#endif

%include "Classifier_includes.i"
%include "Clustering_includes.i"
%include "Distance_includes.i"
Expand Down
80 changes: 80 additions & 0 deletions src/interfaces/python_modular/python_buffer_protocol.i
@@ -0,0 +1,80 @@
/* Buffer protocol stuff for DenseFeatures */
%define BUFFER_DENSEFEATURES(class_name, type_name, type, format_str)

%wrapper
%{

static int class_name ## _getbuffer(PyObject *exporter, Py_buffer *view, int flags)
{
CDenseFeatures< type > * self = (CDenseFeatures< type > *) 0;
void *argp1 = 0 ;
int res1 = 0 ;

int num_feat = 0, num_vec = 0;

Py_ssize_t* shape;
Py_ssize_t* stride;

static char* format = format_str;

res1 = SWIG_ConvertPtr(exporter, &argp1, SWIG_TypeQuery("shogun::CDenseFeatures<type>"), 0 | 0 );
if (!SWIG_IsOK(res1))
{
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" " class_name _getbuffer" "', argument " "1"" of type '" "CDenseFeatures< type > *""'");
}

self = reinterpret_cast< CDenseFeatures < type > * >(argp1);

view->buf = self->get_feature_matrix(num_feat, num_vec);

shape = new Py_ssize_t[2];
shape[0] = num_feat;
shape[1] = num_vec;

stride = new Py_ssize_t[2];
stride[0] = sizeof( type );
stride[1] = sizeof( type ) * num_feat;

view->len = shape[0]*stride[0];
view->itemsize = stride[0];
view->readonly = 0;

/* TODO fix warnings related to const char* -> char* */
view->format = format;
view->ndim = 2;
view->shape = shape;
view->strides = stride;
view->suboffsets = NULL;
view->internal = NULL;

view->obj = (PyObject*) exporter;
Py_INCREF(exporter);

return 0;

fail:
return -1;
}

static void class_name ## _releasebuffer(PyObject *exporter, Py_buffer *view)
{
if(view->shape != NULL)
delete[] view->shape;

if(view->strides != NULL)
delete[] view->strides;
}

static long class_name ## _flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE;
%}

%init
%{
/* TODO less "hacked" */
SwigPyBuiltin__shogun__CDenseFeaturesT_ ## type_name ## _t_type.ht_type.tp_flags = class_name ## _flags;
%}

%feature("python:bf_getbuffer") CDenseFeatures< type_name > #class_name "_getbuffer"
%feature("python:bf_releasebuffer") CDenseFeatures< type_name > #class_name "_releasebuffer"

%enddef

0 comments on commit a6d49a5

Please sign in to comment.