changeset 53:57f243330695 pytave-native

Jaroslav's patch
author David Grundberg <individ@acc.umu.se>
date Thu, 04 Jun 2009 16:35:01 +0200
parents b001edc0f81a
children 9180ce65a7bd
files octave_to_python.cc octave_to_python.h package/pytave.py pytave.cc
diffstat 4 files changed, 113 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- 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 <iostream>
 #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 <class PythonPrimitive, class OctaveBase>
    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<PyObject *, Cell>(
+                                  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<PyObject *, Cell>(
+               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 <class PythonPrimitive, class OctaveBase>
    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
-            <PythonPrimitive, OctaveBase>(pyarr, octarr, 0, 1, 0, 0);
+            <PythonPrimitive, OctaveBase>(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<Complex, ComplexNDArray>
@@ -211,14 +244,23 @@
          return create_sint_array<int8NDArray, sizeof(int8_t)>(
             matrix.int8_array_value());
       }
+      if (!native && matrix.is_string()) {
+         return create_array<char, charNDArray>(
+            matrix.char_array_value(), PyArray_CHAR, native);
+      }
+      if (!native && matrix.is_cell()) {
+         return create_array<PyObject *, Cell>(
+            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>((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);
--- 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 */
--- 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
--- 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;
    }