std::complex vs python complex

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

std::complex vs python complex

Holger Brandsmeier
Dear list,

I exported a wrapper for std::complex<double> to python and I am
willing to always use this class in python and I never want to use
pythons own `complex` data type.

However, a funny thing happens when I export the addition operator
(the implemenation is given in the STL ...)
        .def(self + self)

Now I get that:
type(scalar_cd(1,2) + scalar_cd(1,2))
<type 'complex'>

But my own type is of the form:
type(scalar_cd(1,2))
<class 'parfem.scalarPy.scalar_cd'>


Why did this happen and how can I avoid this? Later own I get problems
when I want to pass this back to C++.

I remember that pythons own complex type is a bit special and does not
cooperate nicely with boost::python and std::complex<> but how did
python/boost::python end up converting the result of the addition to
`complex`?

I am using:
Python 2.7.2
boost-1.46.1

Best regards,
Holger Brandsmeier
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: std::complex vs python complex

Jim Bosch-2
On 04/10/2012 06:58 AM, Holger Brandsmeier wrote:

> Dear list,
>
> I exported a wrapper for std::complex<double>  to python and I am
> willing to always use this class in python and I never want to use
> pythons own `complex` data type.
>
> However, a funny thing happens when I export the addition operator
> (the implemenation is given in the STL ...)
>          .def(self + self)
>
> Now I get that:
> type(scalar_cd(1,2) + scalar_cd(1,2))
> <type 'complex'>
>
> But my own type is of the form:
> type(scalar_cd(1,2))
> <class 'parfem.scalarPy.scalar_cd'>
>
>
> Why did this happen and how can I avoid this? Later own I get problems
> when I want to pass this back to C++.
>
> I remember that pythons own complex type is a bit special and does not
> cooperate nicely with boost::python and std::complex<>  but how did
> python/boost::python end up converting the result of the addition to
> `complex`?
>
> I am using:
> Python 2.7.2
> boost-1.46.1
>

Does your custom complex type provide implicit conversion to std::complex?

If so, I'm guessing there's something going wrong with overload
resolution; Boost.Python's operator wrappers simply invoke the C++
operators and lookup the Python conversion based on the result type.
You can test this yourself with something like this:

--------------------------------------------------------------------

// use any namespace other than the one your classes are defined in
namespace {

template <typename T> void test_expr(T const & x) {
     std::cerr << typeid(x).name() << std::endl;
}

} // <anonymous>

int main() {
     test_expr(whatever::scalar_cd(1,2) + whatever::scalar_cd(1,2));
     return 0;
}

--------------------------------------------------------------------

If the output you see when running the above is std::complex, you'll
have a test case that doesn't involve Boost.Python you can use to debug
your overload resolution.  If not, let me know, and I'll dig deeper into
what Boost.Python's doing.

HTH!

Jim
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: std::complex vs python complex

Holger Brandsmeier
Jim,

I didn't implement my own `version of std::complex` I just exported
`std::complex` as my own class. I only later found out that this type
is already exported by boost::python itself. I just stopped exporting
`std::complex` by myself which mostly works.

I am not fully happy with the situation as I also export
`std::complex<dd_real>` and `std::complex<qd_real>` which are complex
variables build upon 128bit and 256bit doubles. For consistency I
would like to treat complex numbers with 64bit, 128bit and 256bit
doubles all the same and to completely ignore python's own `complex`
type. That way I avoid problems where parts of the code work for 64bit
complex numbers but fail to work once I switch to 128bit. It is
probably difficult to stop boost::python from its special treatment of
`std::complex` and how it ties this to python's `complex`, so I will
have to live with the current situation.

-Holger

On Tue, Apr 10, 2012 at 17:37, Jim Bosch <[hidden email]> wrote:

> On 04/10/2012 06:58 AM, Holger Brandsmeier wrote:
>>
>> Dear list,
>>
>> I exported a wrapper for std::complex<double>  to python and I am
>> willing to always use this class in python and I never want to use
>> pythons own `complex` data type.
>>
>> However, a funny thing happens when I export the addition operator
>> (the implemenation is given in the STL ...)
>>         .def(self + self)
>>
>> Now I get that:
>> type(scalar_cd(1,2) + scalar_cd(1,2))
>> <type 'complex'>
>>
>> But my own type is of the form:
>> type(scalar_cd(1,2))
>> <class 'parfem.scalarPy.scalar_cd'>
>>
>>
>> Why did this happen and how can I avoid this? Later own I get problems
>> when I want to pass this back to C++.
>>
>> I remember that pythons own complex type is a bit special and does not
>> cooperate nicely with boost::python and std::complex<>  but how did
>> python/boost::python end up converting the result of the addition to
>> `complex`?
>>
>> I am using:
>> Python 2.7.2
>> boost-1.46.1
>>
>
> Does your custom complex type provide implicit conversion to std::complex?
>
> If so, I'm guessing there's something going wrong with overload resolution;
> Boost.Python's operator wrappers simply invoke the C++ operators and lookup
> the Python conversion based on the result type. You can test this yourself
> with something like this:
>
> --------------------------------------------------------------------
>
> // use any namespace other than the one your classes are defined in
> namespace {
>
> template <typename T> void test_expr(T const & x) {
>    std::cerr << typeid(x).name() << std::endl;
> }
>
> } // <anonymous>
>
> int main() {
>    test_expr(whatever::scalar_cd(1,2) + whatever::scalar_cd(1,2));
>    return 0;
> }
>
> --------------------------------------------------------------------
>
> If the output you see when running the above is std::complex, you'll have a
> test case that doesn't involve Boost.Python you can use to debug your
> overload resolution.  If not, let me know, and I'll dig deeper into what
> Boost.Python's doing.
>
> HTH!
>
> Jim
> _______________________________________________
> Cplusplus-sig mailing list
> [hidden email]
> http://mail.python.org/mailman/listinfo/cplusplus-sig
_______________________________________________
Cplusplus-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Loading...