$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Review request: extended complex number library
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-03-06 16:24:29
Le 06/03/12 19:49, Vicente J. Botet Escriba a écrit :
> Le 06/03/12 13:28, Neal Becker a écrit :
>> Matthieu Schaller wrote:
>>
>>> Dear all,
>>>
>>> Following the comments from V. Escriba, I formally propose my complex
>>> number library for review.
>>> The library is an extension of the std::complex class addressing two
>>> issues:
>>> - The standard does not guaranty the behaviour of the complex class if
>>> instantiated with types other than float/double/long double.
>>> - Some calculation where pure imaginary numbers (i.e. multiples of
>>> sqrt(-1)) appear are unnecessarily slowed down due to the lack of
>>> support for these numbers.
>>> The code I submit contains two interleaved classes boost::complex and
>>> boost::imaginary which can be instantiated with any type T provided T
>>> overloads the usual arithmetic operators and some basic (real)
>>> mathematical functions depending on which complex function will be
>>> used. It is thus an extended version of Thorsten Ottosen's n1869
>>> proposal
>>> (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html)
>>>
>>> Performance tests show some non-negligible speed-ups compared to
>>> std::complex for calculations where pure imaginary numbers are
>>> involved.
>>> A speed-up of 25% has been observed when solving the Schroedinger
>>> equation explicitly on a regular mesh and some comparable figures
>>> can be
>>> observed when computing the Mandelbrot set (the two examples snippets
>>> provided in the archive).
>>> Furthermore, the functions (sin(), exp(), log(),...) involving
>>> boost::imaginary numbers are more precise than their equivalent using a
>>> std::complex with the real part set to 0.
>>>
>>> The code and (doxygen) documentation is available in the repository
>>> http://code.google.com/p/cpp-imaginary-numbers/
>>> A comprehensive zip archive can be found in the "download" and the code
>>> can also be checked-out via the SVN repository.
>>> The archive contains the class header, two examples, a comprehensive
>>> precision test, a brute-force performance test and the documentation.
>>>
>>> I'd be happy to answer any question from your side and to provide more
>>> detailed information if required.
>>>
>>> Regards,
>>>
>>> Matthieu
>> Seems quite interesting. One issue I have though, as a user of
>> gcc/libstdc++, I
>> see that the versions of many std::complex operations seem to be
>> optimized in
>> terms of gcc builtins. For example:
>>
>> #if _GLIBCXX_USE_C99_COMPLEX
>> inline float
>> __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); }
>>
>> inline double
>> __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); }
>>
>>
>> So if I switched to boost::complex, I'd loose these optimizations.
>>
>> Is it useful to have an imaginary library that complements
>> std::complex, rather
>> than replaces it?
>>
>
> Hi,
>
> you are right. The goal been to provide a faster library implies that
> the Boost library should use the standard library when the standard is
> more efficient, and we could expect that the standard is faster for
> the scope it covers.
>
> This means that overloading such as
>
> template<>
> inline float abs(const complex<float>& x)
> {
> return std::sqrt(x.real() * x.real() + x.imag() * x.imag());
> }
> should be replaced by
>
> template<>
> inline float abs(const complex<float>& x) {
> return std::abs(x);
> }
>
>
BTW, the preceding code would work only if the conversion to
std::complex are implicit.
I'm not sure implicit conversion are desirable, but what about explicit
conversions to/from std::complex? and a make_complex function? This
could allow to replace e.g. the code
template<>
inline complex<float> cos(const complex<float>& x)
{
const std::complex<float> temp(x.real(), x.imag());
const std::complex<float> ret = cos(temp);
return complex<float>(ret.real(), ret.imag());
}
by
template<>
inline complex<float> cos(const complex<float>& x)
{
return make_complex(std::cos(std::complex<float>(x));
}
An alternative that could perform better could be to specialize
boost::math::complex for float so that it contains a std::complex<float>
member, let me call it underlying.
template<>
inline complex<float> cos(const complex<float>& x)
{
return make_complex(std::cos(x.get_underlying());
}
Of course, inspecting the generated code will be needed to see if the
compiler is able to optimize this better.
Best,
Vicente