# HG changeset patch # User David Grundberg # Date 1244126101 -7200 # Node ID 57f243330695db5fbdabf01579d8aeb29e8e3d62 # Parent b001edc0f81ab64a2a30afdc80bad82cb9a794c7 Jaroslav's patch diff -r b001edc0f81a -r 57f243330695 octave_to_python.cc --- a/octave_to_python.cc Wed Jun 03 16:41:44 2009 +0200 +++ b/octave_to_python.cc Thu Jun 04 16:35:01 2009 +0200 @@ -31,6 +31,7 @@ #include #include "pytavedefs.h" #include "exceptions.h" +#include "octave_to_python.h" /* From docs: * Note that the names of the element type constants refer to the C data @@ -45,9 +46,6 @@ namespace pytave { - void octvalue_to_pyobj(boost::python::object &py_object, - const octave_value& octvalue); - template static void copy_octarray_to_pyarrobj( PyArrayObject *pyarr, @@ -55,7 +53,8 @@ const unsigned int matindex, const unsigned int matstride, const int dimension, - const unsigned int offset) { + const unsigned int offset, + bool = true) { unsigned char *ptr = (unsigned char*) pyarr->data; if (dimension == pyarr->nd - 1) { // Last dimension, base case @@ -76,6 +75,39 @@ } } + template <> + void copy_octarray_to_pyarrobj( + PyArrayObject *pyarr, + const Cell &matrix, + const unsigned int matindex, + const unsigned int matstride, + const int dimension, + const unsigned int offset, + bool native) { + unsigned char *ptr = (unsigned char*) pyarr->data; + if (dimension == pyarr->nd - 1) { + // Last dimension, base case + for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + object pyobj; + octvalue_to_pyobj (pyobj, matrix.elem(matindex + i*matstride), native); + Py_INCREF (pyobj.ptr()); + *(PyObject **)&ptr[offset + i*pyarr->strides[dimension]] + = pyobj.ptr(); + } + } else { + for (int i = 0; i < pyarr->dimensions[dimension]; i++) { + copy_octarray_to_pyarrobj( + pyarr, + matrix, + matindex + i*matstride, + matstride * pyarr->dimensions[dimension], + dimension + 1, + offset + i*pyarr->strides[dimension], + native); + } + } + } + static PyArrayObject *createPyArr(const dim_vector &dims, int pyarrtype) { int dimensions[dims.length()]; @@ -89,11 +121,11 @@ template static PyArrayObject *create_array(const OctaveBase &octarr, - int pyarraytype) { + int pyarraytype, bool native = true) { PyArrayObject *pyarr = createPyArr(octarr.dims(), pyarraytype); try { copy_octarray_to_pyarrobj - (pyarr, octarr, 0, 1, 0, 0); + (pyarr, octarr, 0, 1, 0, 0, native); } catch (value_convert_exception &pe) { Py_DECREF(pyarr); throw; @@ -160,7 +192,8 @@ } } - static PyArrayObject *octvalue_to_pyarrobj(const octave_value &matrix) { + static PyArrayObject *octvalue_to_pyarrobj(const octave_value &matrix, + bool native = true) { if (matrix.is_double_type ()) { if (matrix.is_complex_type ()) { return create_array @@ -211,14 +244,23 @@ return create_sint_array( matrix.int8_array_value()); } + if (!native && matrix.is_string()) { + return create_array( + matrix.char_array_value(), PyArray_CHAR, native); + } + if (!native && matrix.is_cell()) { + return create_array( + matrix.cell_value(), PyArray_OBJECT, native); + } throw value_convert_exception("Octave matrix type not known, " "conversion not implemented"); } static void octvalue_to_pyarr(boost::python::object &py_object, - const octave_value& octvalue) { - PyArrayObject *pyarr = octvalue_to_pyarrobj(octvalue); + const octave_value& octvalue, + bool native = true) { + PyArrayObject *pyarr = octvalue_to_pyarrobj(octvalue, native); py_object = object(handle((PyObject *)pyarr)); } @@ -227,39 +269,44 @@ } static void octcell_to_pyobject(boost::python::object &py_object, - const Cell& cell) { - py_object = boost::python::list(); + const Cell& cell, bool native) { + if (native) { + py_object = boost::python::list(); - if(!is_1xn_or_0x0(cell.dims())) { - throw value_convert_exception( - "Only one-dimensional (row mayor) cell arrays can be converted."); - } + if(!is_1xn_or_0x0(cell.dims())) { + throw value_convert_exception( + "Only one-dimensional (row mayor) cell arrays can be converted."); + } - for(octave_idx_type i = 0 ; i < cell.length(); i++) { - boost::python::object py_val; + for(octave_idx_type i = 0 ; i < cell.length(); i++) { + boost::python::object py_val; + + octvalue_to_pyobj(py_val, cell.elem(i), native); - octvalue_to_pyobj(py_val, cell.elem(i)); - - ((boost::python::list&)py_object).insert(i, py_val); - } + ((boost::python::list&)py_object).insert(i, py_val); + } + } else + octvalue_to_pyarr(py_object, cell, native); } static void octmap_to_pyobject(boost::python::object &py_object, - const Octave_map& map) { + const Octave_map& map, + bool native = true) { py_object = boost::python::dict(); string_vector keys = map.keys(); for(octave_idx_type i = 0 ; i < keys.length(); i++) { boost::python::object py_val; - octvalue_to_pyobj(py_val, map.contents(keys[i])); + octcell_to_pyobject(py_val, map.contents(keys[i]), native); py_object[keys[i]] = py_val; } } void octvalue_to_pyobj(boost::python::object &py_object, - const octave_value& octvalue) { + const octave_value& octvalue, + bool native) { if (octvalue.is_undefined()) throw value_convert_exception( "Octave value `undefined'. Can not convert to a Python object"); @@ -275,29 +322,32 @@ else throw value_convert_exception( "Conversion for this scalar not implemented"); - } else if (octvalue.is_string()) { + } else if (native && octvalue.is_string()) { if (! is_1xn_or_0x0 (octvalue.dims ())) throw value_convert_exception( "Multi-row character matrices can not be converted."); py_object = str(octvalue.string_value()); + } else if (!native && octvalue.is_string()) { + octvalue_to_pyarr(py_object, octvalue, native); } else if (octvalue.is_matrix_type()) { octvalue_to_pyarr(py_object, octvalue); } else if (octvalue.is_map()) { - octmap_to_pyobject(py_object, octvalue.map_value()); + octmap_to_pyobject(py_object, octvalue.map_value(), native); } else if (octvalue.is_cell()) { - octcell_to_pyobject(py_object, octvalue.cell_value()); + octcell_to_pyobject(py_object, octvalue.cell_value(), native); } else throw value_convert_exception( "Conversion from Octave value not implemented"); } void octlist_to_pytuple(boost::python::tuple &python_tuple, - const octave_value_list &octave_list) { + const octave_value_list &octave_list, + bool native) { boost::python::list seq; int length = octave_list.length(); for (int i = 0; i < length; i++) { boost::python::object py_object; - octvalue_to_pyobj(py_object, octave_list(i)); + octvalue_to_pyobj(py_object, octave_list(i), native); seq.append(py_object); } python_tuple = tuple(seq); diff -r b001edc0f81a -r 57f243330695 octave_to_python.h --- a/octave_to_python.h Wed Jun 03 16:41:44 2009 +0200 +++ b/octave_to_python.h Thu Jun 04 16:35:01 2009 +0200 @@ -22,9 +22,9 @@ namespace pytave { void octvalue_to_pyobj(boost::python::object &py_object, - const octave_value& octvalue); + const octave_value& octvalue, bool native = true); void octlist_to_pytuple(boost::python::tuple &python_tuple, - const octave_value_list &octave_list); + const octave_value_list &octave_list, bool native = true); } #endif /* OCTAVE_TO_PYTHON_H */ diff -r b001edc0f81a -r 57f243330695 package/pytave.py --- a/package/pytave.py Wed Jun 03 16:41:44 2009 +0200 +++ b/package/pytave.py Thu Jun 04 16:35:01 2009 +0200 @@ -22,6 +22,7 @@ import _pytave import sys +import Numeric arg0 = sys.argv[0] interactive = sys.stdin.isatty() and (arg0 == '' or arg0 == '-') @@ -30,7 +31,7 @@ (OctaveError, ValueConvertError, ObjectConvertError, ParseError, \ VarNameError) = _pytave.get_exceptions(); -def feval(nargout, funcname, *arguments): +def feval(nargout, funcname, *arguments, **kwargs): """Executes an Octave function called funcname. @@ -64,6 +65,8 @@ UINT, SINT, -''- LONG, -''- DOUBLE -''- + CHAR character array + OBJECT cell array All other objects causes a pytave.ObjectConvertError to be raised. This exception inherits TypeError. @@ -74,19 +77,25 @@ Scalar values to objects: bool bool real scalar float (64-bit) - any string* str + any string str* (if native = True) struct dict - cell* list + cell list* (if native = True) * Cell arrays must be one-dimensional (row vector) and character matrices must only have one row. Any other form will raise a ValueConvertError. + This is required unless native = False. Matrix values to Numeric arrays: + double DOUBLE + single FLOAT + logical DOUBLE int64 LONG int32, uint32 INT, UINT int16, uint16 SHORT, USHORT int8, unint8 SBYTE, UBYTE + char CHAR (if native = False) + cell OBJECT (if native = False) All other values causes a pytave.ValueConvertError to be raised. This exception inherits TypeError. @@ -99,9 +108,10 @@ """ - return _pytave.feval(nargout, funcname, arguments) + return _pytave.feval(nargout, funcname, arguments, + kwargs.get("native", True)) -def eval(nargout, code, silent=True): +def eval(nargout, code, **kwargs): """Executes a given Octave code. @@ -134,7 +144,8 @@ """ - return _pytave.eval(nargout, code, silent) + return _pytave.eval(nargout,code,kwargs.get("silent",True), + kwargs.get("native",True)) def addpath(*arguments): """See Octave documentation""" @@ -148,7 +159,7 @@ """See Octave documentation""" return _pytave.feval(1, "path", paths)[0] -def getvar(name, fglobal = False): +def getvar(name, **kwargs): """Queries a variable by name from the current Octave scope. This is pretty much equivalent to calling eval(name), but is much faster because the Octave parser is bypassed. @@ -159,9 +170,10 @@ If the variable is not defined, VarNameError exception is raised. """ - return _pytave.getvar(name, fglobal) + return _pytave.getvar(name,kwargs.get("fglobal",False), + kwargs.get("native", True)) -def setvar(name, val, fglobal = False): +def setvar(name, val, **kwargs): """Sets a variable by name from the current Octave scope. It is quite fast because the Octave parser is bypassed. @@ -174,9 +186,9 @@ If the variable name is not valid, VarNameError exception is raised. """ - return _pytave.setvar(name, val, fglobal) + return _pytave.setvar(name, val, kwargs.get("fglobal",False)) -def isvar(name, fglobal = False): +def isvar(name, **kwargs): """Checks whether a variable exists in the current Octave scope. It is quite fast because the Octave parser is bypassed. @@ -187,7 +199,7 @@ If the variable is defined, returns True, otherwise returns False. """ - return _pytave.isvar(name, fglobal) + return _pytave.isvar(name, kwargs.get("fglobal",False)) def push_scope(): """Creates a new anonymous local variable scope on the Octave call diff -r b001edc0f81a -r 57f243330695 pytave.cc --- a/pytave.cc Wed Jun 03 16:41:44 2009 +0200 +++ b/pytave.cc Thu Jun 04 16:35:01 2009 +0200 @@ -129,7 +129,8 @@ boost::python::tuple func_eval(const int nargout, const string &funcname, - const boost::python::tuple &arguments) { + const boost::python::tuple &arguments, + bool native) { octave_value_list octave_args, retval; @@ -160,7 +161,7 @@ if (nargout >= 0) { boost::python::tuple pytuple; - octlist_to_pytuple(pytuple, retval); + octlist_to_pytuple(pytuple, retval, native); return pytuple; } else { // Return () if nargout < 0. @@ -170,7 +171,8 @@ boost::python::tuple str_eval(int nargout, const string &code, - bool silent) { + bool silent, + bool native) { octave_value_list retval; int parse_status; @@ -205,7 +207,7 @@ if (nargout >= 0) { boost::python::tuple pytuple; - octlist_to_pytuple(pytuple, retval); + octlist_to_pytuple(pytuple, retval, native); return pytuple; } else { // Return () if nargout < 0. @@ -214,7 +216,7 @@ } boost::python::object getvar(const string& name, - bool global) { + bool global, bool native) { octave_value val; if (global) @@ -227,7 +229,7 @@ } boost::python::object pyobject; - octvalue_to_pyobj(pyobject, val); + octvalue_to_pyobj(pyobject, val, native); return pyobject; }