$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: nksauter_at_[hidden]
Date: 2001-05-11 23:40:35
Now that Python 2.1 supports the notion of rich comparisons I
would like to implement support for these operators in the
Boost.Python library. My first attempt at doing this succeeded
only partially: I was able to define the Python 2.1 customization
functions (__gt__, __ge__, __lt__, __le__, __eq__, __ne__)
but this did not produce the expected result of overloading the
operators themselves, that is, a<b, etc. I am attaching the
relevant code in the hope that someone will be able to understand
what is missing.
Nick Sauter
Lawrence Berkeley Labs
To reproduce my test:
1. Make differences to boost/python/detail/extension_class.hpp:
619,624d618
< choose_op<(which & op_gt)>::template
args<Operand>::add(this);
< choose_op<(which & op_ge)>::template
args<Operand>::add(this);
< choose_op<(which & op_lt)>::template
args<Operand>::add(this);
< choose_op<(which & op_le)>::template
args<Operand>::add(this);
< choose_op<(which & op_eq)>::template
args<Operand>::add(this);
< choose_op<(which & op_ne)>::template
args<Operand>::add(this);
654,659d647
< choose_op<(which & op_gt)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_ge)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_lt)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_le)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_eq)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_ne)>::template
args<Left,Right>::add(this);
2. Make differences to boost/python/operators.hpp:
68,74c68
< op_cmp = 0x100000,
< op_gt = 0x200000,
< op_ge = 0x400000,
< op_lt = 0x800000,
< op_le = 0x1000000,
< op_eq = 0x2000000,
< op_ne = 0x4000000
---
> op_cmp = 0x100000
310,315d303
< PY_DEFINE_BINARY_OPERATORS(gt, >);
< PY_DEFINE_BINARY_OPERATORS(ge, >=);
< PY_DEFINE_BINARY_OPERATORS(lt, <);
< PY_DEFINE_BINARY_OPERATORS(le, <=);
< PY_DEFINE_BINARY_OPERATORS(eq, ==);
< PY_DEFINE_BINARY_OPERATORS(ne, !=);
3. Now compile the following extension module, richcmpmodule.cpp:
#include <boost/python/cross_module.hpp>
#include <libs/python/example/dvect.h>
namespace {
#include <cctbx/basic/from_bpl_import.h>
#include <libs/python/example/dvect_conversions.cpp>
}//namespace
#define DVECT_BINARY_OPERATORS( oper ) \
vects::dvect operator##oper (const vects::dvect& a, const
vects::dvect& b) {\
if (a.size()!=b.size()){throw boost::python::argument_error();}
\
vects::dvect result(a.size());
\
vects::dvect::const_iterator a_it = a.begin();
\
vects::dvect::const_iterator b_it = b.begin();
\
vects::dvect::iterator r_it = result.begin();
\
for (int i=0; i<a.size(); i++) { r_it[i] = (a_it[i] ##oper
b_it[i]);
} \
return result;
\
}
DVECT_BINARY_OPERATORS( + )
DVECT_BINARY_OPERATORS( - )
DVECT_BINARY_OPERATORS( * )
DVECT_BINARY_OPERATORS( / )
DVECT_BINARY_OPERATORS( > )
DVECT_BINARY_OPERATORS( >= )
DVECT_BINARY_OPERATORS( < )
DVECT_BINARY_OPERATORS( <= )
DVECT_BINARY_OPERATORS( == )
DVECT_BINARY_OPERATORS( != )
#undef DVECT_BINARY_OPERATORS
BOOST_PYTHON_MODULE_INIT(richcmp)
{
try
{
python::module_builder richcmp_module("richcmp");
python::class_builder<vects::dvect> dvect_class(richcmp_module,
"dvect");
dvect_class.def(python::constructor<python::tuple>());
dvect_class.def(&vects::dvect::as_tuple,"as_tuple");
#define all_operators (boost::python::op_mul | boost::python::op_add
|
boost::python::op_div | boost::python::op_sub )
dvect_class.def(boost::python::operators<all_operators>());
#define comp_operators (boost::python::op_gt | boost::python::op_ge
|\
boost::python::op_lt | boost::python::op_le | \
boost::python::op_eq | boost::python::op_ne)
dvect_class.def(boost::python::operators<comp_operators>());
}
catch(...){python::handle_exception();}//Deal with the exception
for
Python
}
4. Test the module:
import richcmp
dv = richcmp.dvect((1,2,3,4,5))
print dv.as_tuple()
dv2 = richcmp.dvect((6,7,8,9,10))
print dv2.as_tuple()
print (dv+dv2).as_tuple()
print dv.__eq__(dv2).as_tuple()
print dv.__ne__(dv2).as_tuple()
print (dv == dv2) #result should be a dvect but comes out as an int