
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