diff --git a/src/types.cpp b/src/types.cpp index 3367dba8..fe108225 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -455,6 +455,61 @@ static PyObject* do_instance_nb_hex(PyObject* obj) 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 @@ -511,6 +566,41 @@ bool add_capability_richcompare(type_object_base::capability capability, PyTypeO 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); \ @@ -626,6 +716,8 @@ namespace detail { 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)) @@ -970,7 +1062,7 @@ PyObject* type_object_base::instance_number_divmod(PyObject*, PyObject*) const PyObject* type_object_base::instance_number_power(PyObject*, PyObject*, PyObject*) const { - return unimplemented("instance_number_divmod"); + return unimplemented("instance_number_power"); } PyObject* type_object_base::instance_number_negative(PyObject*) const @@ -1053,6 +1145,61 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const 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"); diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 7cd7e0ce..61f56407 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -667,7 +667,7 @@ int total_Ints = 0; struct Int { - explicit Int(int i) : i_(i) { + explicit Int(int i) : i_(i), j_(0) { #ifndef NDEBUG ++total_Ints; #endif @@ -675,12 +675,29 @@ struct Int #ifndef NDEBUG ~Int() { --total_Ints; } - Int(const Int& rhs) : i_(rhs.i_) { ++total_Ints; } + Int(const Int& rhs) : i_(rhs.i_), j_(rhs.j_) { ++total_Ints; } #endif int i() const { return i_; } + int j() const { return j_; } int i_; + int j_; + + Int& operator +=(Int const& r) { ++j_; i_ += r.i_; return *this; } + Int& operator -=(Int const& r) { ++j_; i_ -= r.i_; return *this; } + Int& operator *=(Int const& r) { ++j_; i_ *= r.i_; return *this; } + Int& operator /=(Int const& r) { ++j_; i_ /= r.i_; return *this; } + Int& operator %=(Int const& r) { ++j_; i_ %= r.i_; return *this; } + Int& ipow (Int const& r) { ++j_; + int o=i_; + for (int k=1; k>=(Int const& r) { ++j_; i_ >>= r.i_; return *this; } + Int& operator &=(Int const& r) { ++j_; i_ &= r.i_; return *this; } + Int& operator |=(Int const& r) { ++j_; i_ |= r.i_; return *this; } + Int& operator ^=(Int const& r) { ++j_; i_ ^= r.i_; return *this; } }; Int operator+(Int const & l, Int const & r) { return Int(l.i_ + r.i_); } @@ -868,6 +885,19 @@ namespace bpl_test { double freal(const std::complex& c) { return c.real(); } double fimag(std::complex c) { return c.imag(); } + // Wrappers for inplace operators. + Int& int_iadd(Int& self, const Int& r) { self += r; return self; } + Int& int_isub(Int& self, const Int& r) { self -= r; return self; } + Int& int_imul(Int& self, const Int& r) { self *= r; return self; } + Int& int_idiv(Int& self, const Int& r) { self /= r; return self; } + Int& int_imod(Int& self, const Int& r) { self %= r; return self; } + Int& int_ipow(Int& self, const Int& r) { self.ipow (r); return self; } + Int& int_ilshift(Int& self, const Int& r) { self <<= r; return self; } + Int& int_irshift(Int& self, const Int& r) { self >>= r; return self; } + Int& int_iand(Int& self, const Int& r) { self &= r; return self; } + Int& int_ior(Int& self, const Int& r) { self |= r; return self; } + Int& int_ixor(Int& self, const Int& r) { self ^= r; return self; } + /************************************************************/ /* */ /* init the module */ @@ -1042,6 +1072,7 @@ void init_module(boost::python::module_builder& m) boost::python::class_builder int_class(m, "Int"); int_class.def(boost::python::constructor()); int_class.def(&Int::i, "i"); + int_class.def(&Int::j, "j"); // wrap homogeneous operators int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_neg | @@ -1061,6 +1092,19 @@ void init_module(boost::python::module_builder& m) boost::python::left_operand()); // export non-operator function as heterogeneous reverse-argument operator int_class.def(&rmul, "__rmul__"); + + // inplace operators. + int_class.def(&int_iadd, "__iadd__"); + int_class.def(&int_isub, "__isub__"); + int_class.def(&int_imul, "__imul__"); + int_class.def(&int_idiv, "__idiv__"); + int_class.def(&int_imod, "__imod__"); + int_class.def(&int_ipow, "__ipow__"); + int_class.def(&int_ilshift, "__ilshift__"); + int_class.def(&int_irshift, "__irshift__"); + int_class.def(&int_iand, "__iand__"); + int_class.def(&int_ior, "__ior__"); + int_class.def(&int_ixor, "__ixor__"); boost::python::class_builder enum_owner(m, "EnumOwner");