Boost logo

Boost :

From: scott snyder (snyder_at_[hidden])
Date: 2001-12-02 19:55:34


hi -

This patch adds partial support for inplace operators to boost::python.
(Diffs are against boost 1.25.1.)
With these changes, definitions that use a thin wrapper will work, like this:

Hep3Vector& Hep3Vector___iadd__8 (Hep3Vector& self, const Hep3Vector& other)
{
  self += other;
  return self;
}

...

  this_class.def (Hep3Vector___iadd__8, "__iadd__");

However, i have not tried to make the python::operators<> syntax work
for inplace operations.

sss

--- boost/python/detail/types.hpp-orig Mon Nov 12 14:40:26 2001
+++ boost/python/detail/types.hpp Mon Nov 12 17:10:10 2001
@@ -57,7 +57,11 @@
         number_positive, number_absolute, number_nonzero, number_invert,
         number_lshift, number_rshift, number_and, number_xor, number_or,
         number_coerce, number_int, number_long, number_float, number_oct,
- number_hex
+ number_hex, number_inplace_add, number_inplace_subtract,
+ number_inplace_multiply, number_inplace_divide,
+ number_inplace_remainder, number_inplace_power,
+ number_inplace_lshift, number_inplace_rshift,
+ number_inplace_and, number_inplace_or, number_inplace_xor
     };
     
     void enable(capability);
@@ -116,6 +120,18 @@
     virtual PyObject* instance_number_oct(PyObject*) const;
     virtual PyObject* instance_number_hex(PyObject*) const;
 
+ virtual PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
+
  public: // Callbacks for rich comparisons
     virtual PyObject* instance_lt(PyObject*, PyObject*) const;
     virtual PyObject* instance_le(PyObject*, PyObject*) const;
--- boost/python/classes.hpp-orig Mon Nov 12 16:11:39 2001
+++ boost/python/classes.hpp Mon Nov 12 17:42:11 2001
@@ -78,6 +78,19 @@
     PyObject* gt(PyObject* other);
     PyObject* ge(PyObject* other);
 
+ // Inplace operations.
+ PyObject* inplace_add(PyObject* other);
+ PyObject* inplace_subtract(PyObject* other);
+ PyObject* inplace_multiply(PyObject* other);
+ PyObject* inplace_divide(PyObject* other);
+ PyObject* inplace_remainder(PyObject* other);
+ PyObject* inplace_power(PyObject* exponent, PyObject* modulus);
+ PyObject* inplace_lshift(PyObject* other);
+ PyObject* inplace_rshift(PyObject* other);
+ PyObject* inplace_and(PyObject* other);
+ PyObject* inplace_or(PyObject* other);
+ PyObject* inplace_xor(PyObject* other);
+
  private: // noncopyable, without the size bloat
     instance(const instance&);
     void operator=(const instance&);
@@ -178,6 +191,18 @@
     PyObject* instance_number_oct(PyObject*) const;
     PyObject* instance_number_hex(PyObject*) const;
 
+ PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
+
  private: // Implement rich comparisons
     PyObject* instance_lt(PyObject*, PyObject*) const;
     PyObject* instance_le(PyObject*, PyObject*) const;
@@ -494,6 +519,72 @@
 }
 
 template <class T>
+PyObject* class_t<T>::instance_number_inplace_add(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_add(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_subtract(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_subtract(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_multiply(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_multiply(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_divide(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_divide(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_remainder(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_remainder(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const
+{
+ return downcast<T>(obj)->inplace_power(exponent, modulus);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_lshift(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_lshift(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_rshift(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_rshift(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_and(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_and(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_or(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_or(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_xor(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_xor(other);
+}
+
+template <class T>
 PyObject* class_t<T>::instance_lt(PyObject* obj, PyObject* other) const
 {
     return downcast<T>(obj)->lt(other);
--- libs/python/src/types.cpp-orig Mon Nov 12 14:44:51 2001
+++ libs/python/src/types.cpp Wed Nov 28 17:54:06 2001
@@ -424,6 +424,61 @@
     return call(obj, &type_object_base::instance_number_hex);
 }
 
+static PyObject* do_instance_nb_inplace_add(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_add, other);
+}
+
+static PyObject* do_instance_nb_inplace_subtract(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_subtract, other);
+}
+
+static PyObject* do_instance_nb_inplace_multiply(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_multiply, other);
+}
+
+static PyObject* do_instance_nb_inplace_divide(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_divide, other);
+}
+
+static PyObject* do_instance_nb_inplace_remainder(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_remainder, other);
+}
+
+static PyObject* do_instance_nb_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus)
+{
+ return call(obj, &type_object_base::instance_number_inplace_power, exponent, modulus);
+}
+
+static PyObject* do_instance_nb_inplace_lshift(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_lshift, other);
+}
+
+static PyObject* do_instance_nb_inplace_rshift(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_rshift, other);
+}
+
+static PyObject* do_instance_nb_inplace_and(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_and, other);
+}
+
+static PyObject* do_instance_nb_inplace_or(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_or, other);
+}
+
+static PyObject* do_instance_nb_inplace_xor(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_xor, other);
+}
+
 } // extern "C"
 
 namespace
@@ -480,6 +535,41 @@
     return false;
 }
 
+#if PYTHON_API_VERSION >= 1010
+# define ENABLE_INPLACE_CAPABILITY1 \
+ dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS;
+#else
+# define ENABLE_INPLACE_CAPABILITY1
+#endif
+#define ENABLE_INPLACE_CAPABILITY(field) \
+ case type_object_base::number_##field: \
+ create_method_table_if_null(dest->tp_as_number); \
+ dest->tp_as_number->nb_##field = &do_instance_nb_##field; \
+ detail::shared_pod_manager::replace_if_equal(dest->tp_as_number); \
+ ENABLE_INPLACE_CAPABILITY1 \
+ return true
+
+bool add_capability_inplace(type_object_base::capability capability, PyTypeObject* dest)
+{
+ assert(dest != 0);
+ switch (capability)
+ {
+ ENABLE_INPLACE_CAPABILITY (inplace_add);
+ ENABLE_INPLACE_CAPABILITY (inplace_subtract);
+ ENABLE_INPLACE_CAPABILITY (inplace_multiply);
+ ENABLE_INPLACE_CAPABILITY (inplace_divide);
+ ENABLE_INPLACE_CAPABILITY (inplace_remainder);
+ ENABLE_INPLACE_CAPABILITY (inplace_power);
+ ENABLE_INPLACE_CAPABILITY (inplace_lshift);
+ ENABLE_INPLACE_CAPABILITY (inplace_rshift);
+ ENABLE_INPLACE_CAPABILITY (inplace_and);
+ ENABLE_INPLACE_CAPABILITY (inplace_or);
+ ENABLE_INPLACE_CAPABILITY (inplace_xor);
+ default:
+ return false;
+ }
+}
+
 #define ENABLE_MAPPING_CAPABILITY(field) \
     case type_object_base::mapping_##field: \
         create_method_table_if_null(dest); \
@@ -595,6 +685,8 @@
         return;
     if(add_capability_richcompare(capability, dest_))
         return;
+ if(add_capability_inplace(capability, dest_))
+ return;
     if(add_capability_mapping(capability, dest_->tp_as_mapping))
         return;
     if(add_capability_sequence(capability, dest_->tp_as_sequence))
@@ -1022,6 +1114,61 @@
     return unimplemented("instance_number_hex");
 }
 
+PyObject* type_object_base::instance_number_inplace_add(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_add");
+}
+
+PyObject* type_object_base::instance_number_inplace_subtract(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_subtract");
+}
+
+PyObject* type_object_base::instance_number_inplace_multiply(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_multiply");
+}
+
+PyObject* type_object_base::instance_number_inplace_divide(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_divide");
+}
+
+PyObject* type_object_base::instance_number_inplace_remainder(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_remainder");
+}
+
+PyObject* type_object_base::instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_power");
+}
+
+PyObject* type_object_base::instance_number_inplace_lshift(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_lshift");
+}
+
+PyObject* type_object_base::instance_number_inplace_rshift(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_rshift");
+}
+
+PyObject* type_object_base::instance_number_inplace_and(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_and");
+}
+
+PyObject* type_object_base::instance_number_inplace_or(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_or");
+}
+
+PyObject* type_object_base::instance_number_inplace_xor(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_xor");
+}
+
 PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const
 {
     return unimplemented("instance_lt");
--- libs/python/src/classes.cpp-orig Mon Nov 12 14:45:43 2001
+++ libs/python/src/classes.cpp Mon Nov 12 17:46:49 2001
@@ -766,6 +766,64 @@
     return callback<PyObject*>::call_method(this, "__ge__", other);
 }
 
+PyObject* instance::inplace_add(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__iadd__", other);
+}
+
+PyObject* instance::inplace_subtract(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__isub__", other);
+}
+
+PyObject* instance::inplace_multiply(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__imul__", other);
+}
+
+PyObject* instance::inplace_divide(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__idiv__", other);
+}
+
+PyObject* instance::inplace_remainder(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__imod__", other);
+}
+
+PyObject* instance::inplace_power(PyObject* exponent, PyObject* modulus)
+{
+ if (as_object(modulus->ob_type) == Py_None)
+ return callback<PyObject*>::call_method(this, "__ipow__", exponent);
+ else
+ return callback<PyObject*>::call_method(this, "__ipow__", exponent, modulus);
+}
+
+PyObject* instance::inplace_lshift(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ilshift__", other);
+}
+
+PyObject* instance::inplace_rshift(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__irshift__", other);
+}
+
+PyObject* instance::inplace_and(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__iand__", other);
+}
+
+PyObject* instance::inplace_or(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ior__", other);
+}
+
+PyObject* instance::inplace_xor(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ixor__", other);
+}
+
 namespace {
   struct named_capability
   {
@@ -783,6 +841,17 @@
       { "__le__", detail::type_object_base::richcompare },
       { "__eq__", detail::type_object_base::richcompare },
       { "__ne__", detail::type_object_base::richcompare },
+ { "__iadd__", detail::type_object_base::number_inplace_add },
+ { "__isub__", detail::type_object_base::number_inplace_subtract },
+ { "__imul__", detail::type_object_base::number_inplace_multiply },
+ { "__idiv__", detail::type_object_base::number_inplace_divide },
+ { "__imod__", detail::type_object_base::number_inplace_remainder },
+ { "__ipow__", detail::type_object_base::number_inplace_power },
+ { "__ilshift__", detail::type_object_base::number_inplace_lshift },
+ { "__irshift__", detail::type_object_base::number_inplace_rshift },
+ { "__iand__", detail::type_object_base::number_inplace_and },
+ { "__ixor__", detail::type_object_base::number_inplace_xor },
+ { "__ior__", detail::type_object_base::number_inplace_or },
       { "__repr__", detail::type_object_base::repr },
       { "__str__", detail::type_object_base::str },
       { "__call__", detail::type_object_base::call },


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk