changeset 54:9180ce65a7bd pytave-native

Merge with dictionaries
author David Grundberg <individ@acc.umu.se>
date Thu, 04 Jun 2009 16:40:52 +0200
parents 57f243330695 (diff) a5beba1b4611 (current diff)
children 04e18a0cf25d
files package/pytave.py
diffstat 4 files changed, 113 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/octave_to_python.cc	Thu Jun 04 16:20:18 2009 +0200
+++ b/octave_to_python.cc	Thu Jun 04 16:40:52 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	Thu Jun 04 16:20:18 2009 +0200
+++ b/octave_to_python.h	Thu Jun 04 16:40:52 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	Thu Jun 04 16:20:18 2009 +0200
+++ b/package/pytave.py	Thu Jun 04 16:40:52 2009 +0200
@@ -23,6 +23,7 @@
 import _pytave
 import UserDict
 import sys
+import Numeric
 
 arg0 = sys.argv[0]
 interactive = sys.stdin.isatty() and (arg0 == '' or arg0 == '-')
@@ -31,7 +32,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.
 
@@ -65,6 +66,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.
@@ -75,19 +78,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.
@@ -100,9 +109,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.
 
@@ -135,7 +145,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"""
@@ -150,14 +161,15 @@
 	return _pytave.feval(1, "path", paths)[0]
 
 class _VariablesDict(UserDict.DictMixin):
-	def __init__(self, global_variables):
+	def __init__(self, global_variables, native):
 		self.global_variables = global_variables
+		self.native = native
 
 	def __getitem__(self, name):
 		if not isinstance(name, basestring):
 			raise TypeError('Expected a string, not a ' + repr(type(name)))
 		try:
-			return _pytave.getvar(name, self.global_variables)
+			return _pytave.getvar(name, self.global_variables, self.native)
 		except VarNameError:
 			raise KeyError('No Octave variable named ' + name)
 
@@ -171,9 +183,10 @@
 			raise TypeError('Expected a string, not a ' + repr(type(name)))
 		return _pytave.isvar(name, self.global_variables)
 
-
-locals = _VariablesDict(global_variables=False)
-globals = _VariablesDict(global_variables=True)
+locals = _VariablesDict(global_variables=False, native=False)
+globals = _VariablesDict(global_variables=True, native=False)
+native_locals = _VariablesDict(global_variables=False, native=True)
+native_globals = _VariablesDict(global_variables=True, native=True)
 
 def push_scope():
 	 """Creates a new anonymous local variable scope on the Octave call
--- a/pytave.cc	Thu Jun 04 16:20:18 2009 +0200
+++ b/pytave.cc	Thu Jun 04 16:40:52 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;
    }