Determining interest: Pure imaginary number library

Dear all, I have recently been playing a lot on numerical analysis problems containing complex numbers and functions. I have been using the SL std::complex<> library and could observe that some of the algorithms weren't optimized in cases where complex numbers have to be multiplied by pure imaginary numbers (i.e. x*sqrt(-1)). I have implemented a class to represent these numbers and overloaded all relevant operators in a more optimized fashion thanks to the knowledge that the real part of these complex numbers is 0. I could observe an important speed-up in some calculations. As an example, this piece of code (1D Schroedinger equation using finite differences): for(size_t i(0); i<nbPoints; ++i) { Psi_new[i] = Psi_old[i] + ii * hbar * deltaT / (12.*m*deltaX*deltaX) * (-Psi_cur[i-2] + 16.*Psi_cur[i-1] - 30.*Psi_cur[i] + 16.*Psi_cur[i+1] - Psi_cur[i+2]) - 2. * ii * V(x[i]) / hbar * deltaT * Psi_cur[i]; } is more than 2 times faster (g++ 4.6.1 core i7 2820QM) when the imaginary unit (constant) variable ii is defined to be Imaginary<double> ii(1.); than when it is defined as std::complex<double> ii(0.,1.); Some other expressions also benefit from this improvement and can run faster. Expressions including square roots or exponentials of pure imaginary numbers are improved a lot. The range of application of such a class is quite narrow but it may be helpful to speed-up some simple numerical problems. The source code as well as a working example is available here: http://code.google.com/p/cpp-imaginary-numbers/ Thanks, Matthieu

Interesting stuff but I found some minor problems with the code 1). in Imaginary.hpp on lines 293,300 * /// Returns the value of x divided by y template<typename T> inline Imaginary<T> operator/(const T& x, const Imaginary<T>& y) { Imaginary<T> r = y; r /= x; return r; } *as you can see there is an error in this we should be calculating x/y but instead y/x is calculated it should be Imaginary<T>(-x/y.imag()) i.e. x/(0 + y.imag()**/I/*) == x*(-*/i/*)/y.imag() 2). some of the comments are wrong in the cases of operator!=() on lines 383 & 390 & 397 & 404 & 411 it says ///Returns true if x equals y of course it should say true if x does not equal y no doubt you forgot to change them after cut/copy & paste thats how I make those sort of errors those are the only errors I found, simply beautiful code and very handy they should add it to the STL love your work Francis Grizzly Smit On 16/11/11 10:40, Matthieu Schaller wrote:
Dear all,
I have recently been playing a lot on numerical analysis problems containing complex numbers and functions. I have been using the SL std::complex<> library and could observe that some of the algorithms weren't optimized in cases where complex numbers have to be multiplied by pure imaginary numbers (i.e. x*sqrt(-1)). I have implemented a class to represent these numbers and overloaded all relevant operators in a more optimized fashion thanks to the knowledge that the real part of these complex numbers is 0. I could observe an important speed-up in some calculations. As an example, this piece of code (1D Schroedinger equation using finite differences):
for(size_t i(0); i<nbPoints; ++i) { Psi_new[i] = Psi_old[i] + ii * hbar * deltaT / (12.*m*deltaX*deltaX) * (-Psi_cur[i-2] + 16.*Psi_cur[i-1] - 30.*Psi_cur[i] + 16.*Psi_cur[i+1] - Psi_cur[i+2]) - 2. * ii * V(x[i]) / hbar * deltaT * Psi_cur[i];
}
is more than 2 times faster (g++ 4.6.1 core i7 2820QM) when the imaginary unit (constant) variable ii is defined to be
Imaginary<double> ii(1.);
than when it is defined as
std::complex<double> ii(0.,1.);
Some other expressions also benefit from this improvement and can run faster. Expressions including square roots or exponentials of pure imaginary numbers are improved a lot.
The range of application of such a class is quite narrow but it may be helpful to speed-up some simple numerical problems. The source code as well as a working example is available here: http://code.google.com/p/cpp-imaginary-numbers/
Thanks,
Matthieu
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Matthieu Schaller wrote:
Dear all,
I have recently been playing a lot on numerical analysis problems containing complex numbers and functions. I have been using the SL std::complex<> library and could observe that some of the algorithms weren't optimized in cases where complex numbers have to be multiplied by pure imaginary numbers (i.e. x*sqrt(-1)). I have implemented a class to represent these numbers and overloaded all relevant operators in a more optimized fashion thanks to the knowledge that the real part of these complex numbers is 0. I could observe an important speed-up in some calculations. As an example, this piece of code (1D Schroedinger equation using finite differences):
for(size_t i(0); i<nbPoints; ++i) { Psi_new[i] = Psi_old[i] + ii * hbar * deltaT / (12.*m*deltaX*deltaX) * (-Psi_cur[i-2] + 16.*Psi_cur[i-1] - 30.*Psi_cur[i] + 16.*Psi_cur[i+1] - Psi_cur[i+2]) - 2. * ii * V(x[i]) / hbar * deltaT * Psi_cur[i];
}
is more than 2 times faster (g++ 4.6.1 core i7 2820QM) when the imaginary unit (constant) variable ii is defined to be
Imaginary<double> ii(1.);
than when it is defined as
std::complex<double> ii(0.,1.);
Some other expressions also benefit from this improvement and can run faster. Expressions including square roots or exponentials of pure imaginary numbers are improved a lot.
The range of application of such a class is quite narrow but it may be helpful to speed-up some simple numerical problems. The source code as well as a working example is available here: http://code.google.com/p/cpp-imaginary-numbers/
Hi, I'm sure that if the performances can be improved, which seems logic, the Boost community will be interested by your library. Some comments related to the interface. I will replace T& imag(); const T& imag() const; by T imag() const; As there is no reason to provide non-const access to the internal representation. If these operations are needed by the non-member operators, maybe you can declare them private and move non-member operators as members, or declare them friends. Comparing imaginary and reals seems confusing to me ///Returns true if x equals y template<typename T> inline bool operator==(const Imaginary<T>& x, const T& y); template<typename T> inline bool operator==(const T& x, const Imaginary<T>& y); The following divide assign operator is missing: Imaginary<T>& operator/=(const Imaginary<T>& rhs) I would also expect an implicit conversion to complex as an imaginary is also a complex. and a kind of imaginary downcast from complex. template <typename T> imaginary<T> imaginary_cast(complex<T> const & rhs); My advice would be to boostify the code, write the documentation including as much performances tests as you consider could help to consider this library a should have. Good luck, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Determining-interest-Pure-imaginary-numbe... Sent from the Boost - Dev mailing list archive at Nabble.com.

Den 17-11-2011 12:42, Vicente Botet skrev:
Matthieu Schaller wrote:
Dear all,
Many years ago I proposed http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html Maybe it can be of interest. -Thorsten

Thorsten Ottosen-3 wrote:
Den 17-11-2011 12:42, Vicente Botet skrev:
Matthieu Schaller wrote:
Dear all,
Many years ago I proposed
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
Maybe it can be of interest.
How this proposal was received? Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Determining-interest-Pure-imaginary-numbe... Sent from the Boost - Dev mailing list archive at Nabble.com.

Den 18-11-2011 12:17, Vicente Botet skrev:
Thorsten Ottosen-3 wrote:
Den 17-11-2011 12:42, Vicente Botet skrev:
Matthieu Schaller wrote:
Dear all,
Many years ago I proposed
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
Maybe it can be of interest.
How this proposal was received?
As not worth doing. But I couldn't show examples of algorithms that where faster than without it. -Thorsten

Thorsten Ottosen-3 wrote:
Den 18-11-2011 12:17, Vicente Botet skrev:
Thorsten Ottosen-3 wrote:
Den 17-11-2011 12:42, Vicente Botet skrev:
Matthieu Schaller wrote:
Dear all,
Many years ago I proposed
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
Maybe it can be of interest.
How this proposal was received?
As not worth doing. But I couldn't show examples of algorithms that where faster than without it.
I agree that without a clear gain in performances, it will be difficult to justify the addition. This is secondary, I see in http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1612.pdf that you proposed a variable i so that complex_t z = 4.2 + 3.0*i; is well formed. This variable was removed from n1869, isn't it? While I like the trick, it could break a lot of code. Could the addition of a user literal allow to use it as complex_t z = 4.2 + 3.0i; Of course, when we have a double and we want an imaginary, 'i' could not be used anymore, and 1i will be necessary, which is unfortunate double d; complex_t z = 4.2 + d*1i; Just some impressions, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Determining-interest-Pure-imaginary-numbe... Sent from the Boost - Dev mailing list archive at Nabble.com.

Vicente Botet wrote: ...
Some comments related to the interface. I will replace
T& imag(); const T& imag() const;
by
T imag() const;
As there is no reason to provide non-const access to the internal representation.
I disagree - there is a use to provide non-const access. Unless it happens that the internal representation is not obvious. Removing non-const real() and imag() was done in std::complex, and I think that was a mistake. It makes some uses really annoying (requiring hacks). The reason for this, as I understand, is so a different internal rep could be used. And you know what? Who does that?!? I seriously doubt any implementation is not simply: flt m_real; flt m_imag; Sure, you could interally use polar notation - but noone does.

Le 18/11/11 16:51, Neal Becker a écrit :
Vicente Botet wrote:
...
Some comments related to the interface. I will replace
T& imag(); const T& imag() const;
by
T imag() const;
As there is no reason to provide non-const access to the internal representation.
I disagree - there is a use to provide non-const access. Unless it happens that the internal representation is not obvious.
What this non-const conversion allows? imaginary i; i.imag() = 3.0; Do you really think that i = imag(3.0); is less efficient or clear? Am I missing something? Best, Vicente

Thank you for your interest and your input. I have corrected the mistakes spotted by Francis Smit and added casts from/to std::complex as suggested by Vicente Botet. Some comments about your proposals. Comparing imaginary and reals seems confusing to me
///Returns true if x equals y template<typename T> inline bool operator==(const Imaginary<T>& x, const T& y); template<typename T> inline bool operator==(const T& x, const Imaginary<T>& y);
The SL offers comparison between std::complex<T> and T which only compare the real part of the complex number and verifies that its imaginary part is zero. I do the same here: I compare the imaginary part of both arguments and verify that the real part of the complex is zero.
The following divide assign operator is missing:
Imaginary<T>& operator/=(const Imaginary<T>& rhs)
I don't think so. If you divide an imaginary number by another imaginary number you obtain a real number which cannot be represented by this class. Hence, the absence of this operator. The same is true for *=.
Many years ago I proposed
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
Maybe it can be of interest.
This looks like what I'm presenting here. Your proposal goes further in the sense that it also modifies std::complex<T> to add the relevant constructors and operators to the SL complex class but I can't do that here even if it would be more "symmetric" vis-a-vis the real numbers. The complex class could be modified to interact in a better way with pure imaginary numbers but this cannot really be done. I will replace T& imag();
const T& imag() const;
by
T imag() const;
I have modified the code as you suggested as it seems that the norm imposes the latter form for std::complex. Even though I don't really see why. A non-const access could simplify the notation in some cases and I don't see any smarter implementation than just T m_real; T m_imag; but I will conform to the norm and only provide const access. While I like the trick, it could break a lot of code. Could the addition of
a user literal allow to use it as
complex_t z = 4.2 + 3.0i;
I haven't had a look at this until now but this may allow to simplify the notation even more. I see a slight drawback: it uses a C++11 feature which prevents its use with older compilers and these are often the compilers used by scientists on computing platforms. It is quite rare to have access to the last compiler versions in numerical computing. Thanks again for your input. I will "boostify" the code to make it follow more closely the code guiding rules, add a boost-like documentation and prepare more examples. Cheers, Matthieu

Le 19/11/11 12:21, Matthieu Schaller a écrit :
Thank you for your interest and your input.
I have corrected the mistakes spotted by Francis Smit and added casts from/to std::complex as suggested by Vicente Botet.
Some comments about your proposals.
Comparing imaginary and reals seems confusing to me
///Returns true if x equals y template<typename T> inline bool operator==(const Imaginary<T>& x, const T& y); template<typename T> inline bool operator==(const T& x, const Imaginary<T>& y);
The SL offers comparison between std::complex<T> and T which only compare the real part of the complex number and verifies that its imaginary part is zero. I do the same here: I compare the imaginary part of both arguments and verify that the real part of the complex is zero.
Ummm, yes but an imaginary is not a real, and the comparison works only when both are 0. Is this really useful?
The following divide assign operator is missing:
Imaginary<T>& operator/=(const Imaginary<T>& rhs)
I don't think so. If you divide an imaginary number by another imaginary number you obtain a real number which cannot be represented by this class. Hence, the absence of this operator. The same is true for *=.
Sorry for my ignorance :(
Many years ago I proposed
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
Maybe it can be of interest.
This looks like what I'm presenting here. Your proposal goes further in the sense that it also modifies std::complex<T> to add the relevant constructors and operators to the SL complex class but I can't do that here even if it would be more "symmetric" vis-a-vis the real numbers. The complex class could be modified to interact in a better way with pure imaginary numbers but this cannot really be done.
What about defining a boost::complex<> class that behaves like the proposed one.
I will replace
T& imag();
const T& imag() const;
by
T imag() const;
I have modified the code as you suggested as it seems that the norm imposes the latter form for std::complex. Even though I don't really see why. A non-const access could simplify the notation in some cases and I don't see any smarter implementation than just T m_real; T m_imag; but I will conform to the norm and only provide const access.
While I like the trick, it could break a lot of code. Could the addition of
a user literal allow to use it as
complex_t z = 4.2 + 3.0i;
I haven't had a look at this until now but this may allow to simplify the notation even more. I see a slight drawback: it uses a C++11 feature which prevents its use with older compilers and these are often the compilers used by scientists on computing platforms. It is quite rare to have access to the last compiler versions in numerical computing.
Maybe defining a variable i inside a specific namespace could avoid complex_t z = 4.2 + 3.0 imag::i;
Thanks again for your input. I will "boostify" the code to make it follow more closely the code guiding rules, add a boost-like documentation and prepare more examples. Good luck, Vicente

Comparing imaginary and reals seems confusing to me
///Returns true if x equals y
template<typename T> inline bool operator==(const Imaginary<T>& x, const T& y); template<typename T> inline bool operator==(const T& x, const Imaginary<T>& y);
The SL offers comparison between std::complex<T> and T which only compare the real part of the complex number and verifies that its imaginary part is zero. I do the same here: I compare the imaginary part of both arguments and verify that the real part of the complex is zero.
Ummm, yes but an imaginary is not a real, and the comparison works only when both are 0. Is this really useful?
Sorry. I misread your comment. These operators return true only if x==0 and y==0. So, you are right, not very useful. They are just here for the sake of completeness. The same is true for the operator != which almost always return true. What about defining a boost::complex<> class that behaves like the proposed
one.
This could be done. But in my opinion, there isn't any other optimisation available. The only point in doing so would be to allow for these operators. The very nature of complex numbers does not allow compile-time optimisations like what can be done for matrices. bests, Matthieu

Dear all, My advice would be to boostify the code, write the documentation including
as much performances tests as you consider could help to consider this library a should have.
I have modified the code to match the quality criterions, added a comprehensive (doxygen) documentation and modified all the directories to mimic the main trunk. You can also find in the sources a test file which tests all operators and functions for accuracy. It uses boost::test and shows that all functions are accurate within 10e-12 (four doubles) when compared to the same computation done with std::complex<>. When the result is not completely identical, the imaginary<> class version is always closer to the analytical result than the std::complex<> one. The only exception is the tanh() function which differs from the std::complex<> one by 1e-9 for numbers close to 0. I have also added another example (computing the Julia fractal set in mathematics) showing a ~5% gain in performance. The speed-up in this case is much less impressive but the algorithm does not only use imaginary numbers. I could also provide an example which brutally compares the speed of some functions and operators but I prefer presenting real applications rather than artificially improved codes. Is there something that could obviously be improved ? Is there some interest in pushing this further ? Regards, Matthieu Schaller

Le 25/11/11 10:35, Matthieu Schaller a écrit :
Dear all,
My advice would be to boostify the code, write the documentation including
as much performances tests as you consider could help to consider this library a should have.
I have modified the code to match the quality criterions, added a comprehensive (doxygen) documentation and modified all the directories to mimic the main trunk. The directory structure is
- boost -- imaginary - libs -- imaginary --- test --- doc --- example --- perf (if you have some performance tests)
You can also find in the sources a test file which tests all operators and functions for accuracy. It uses boost::test and shows that all functions are accurate within 10e-12 (four doubles) when compared to the same computation done with std::complex<>. When the result is not completely identical, the imaginary<> class version is always closer to the analytical result than the std::complex<> one. The only exception is the tanh() function which differs from the std::complex<> one by 1e-9 for numbers close to 0.
I have also added another example (computing the Julia fractal set in mathematics) showing a ~5% gain in performance. The speed-up in this case is much less impressive but the algorithm does not only use imaginary numbers.
I could also provide an example which brutally compares the speed of some functions and operators but I prefer presenting real applications rather than artificially improved codes. This is right for the examples section, but I would add some performance tests for the specific operations that will reinforce the motivation. Is there something that could obviously be improved ?
Quickbook documentation, a motivation section, + a performance analysis section. I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ...
Is there some interest in pushing this further ? Yes sure.
Best, Vicente

I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ...
Before we all get too carried away, there is an issue with "mycomplex<my_big_num>" which is that if "my_big_num" implements expression templates to optimize arithmetic operations, then these expression template end up in the wrong place with "mycomplex<my_big_num>" : which is to say inside mycomplex's implementation, instead of on mycomplex's own external operators (which is where you really need the expression templates given that each mycomplex temporary will contain 2 values). I'm hoping eventually to extend the "mp_number" stuff in the sandbox (under the "big_number" directory) to cover complex extended precision arithmetic, but it may take a while :-( And finally, there's already a small amount of complex number code in Boost under Boost.Math (just adds some extra TR1 functions), so if adding imaginary support is small enough, we could adopt it under Boost.Math I guess - or vice versa if the new code is large enough to warrant having it's own library. Just thinking out loud here that it would be better to have all the complex number code in one place if possible (and it makes sense to do so). Apologies for not jumping in on this discussion before... John.

Le 29. 11. 11 12:39, John Maddock a écrit :
I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ... This can be done. The boost::complex class could simply be an implementation of the n1869 draft by Thorsten Ottosen then:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html With the addition of the TR1 reciprocal trigonometric functions and the small updates brought by C++11. On top of this, some mathematical operators could be specialized for float and double if some performance improvements can be obtained in those cases. I will work on this.
Before we all get too carried away, there is an issue with "mycomplex<my_big_num>" which is that if "my_big_num" implements expression templates to optimize arithmetic operations, then these expression template end up in the wrong place with "mycomplex<my_big_num>" : which is to say inside mycomplex's implementation, instead of on mycomplex's own external operators (which is where you really need the expression templates given that each mycomplex temporary will contain 2 values).
I may be wrong but I don't see how complex numbers could benefit from template expressions. The two "components" get mixed in almost every expression and cannot be decoupled. The complex<> class always ends up using the operators of its template argument which in the case of a GMP-like number means that the appropriate template operators are called. The complex number operators always end up using real number arithmetic. So mycomplex<my_big_num> would use your "improved" operators.
And finally, there's already a small amount of complex number code in Boost under Boost.Math (just adds some extra TR1 functions), so if adding imaginary support is small enough, we could adopt it under Boost.Math I guess - or vice versa if the new code is large enough to warrant having it's own library. Just thinking out loud here that it would be better to have all the complex number code in one place if possible (and it makes sense to do so).
The TR1 operators could be moved into (next to) this new complex<> class in order to group everything. I would anyway have to implement them if I want the class to be as close as possible to the SL-one as these mathematical functions are now part of the standards. Thanks for your input. -- Matthieu Schaller

I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ... This can be done. The boost::complex class could simply be an implementation of the n1869 draft by Thorsten Ottosen then:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
With the addition of the TR1 reciprocal trigonometric functions and the small updates brought by C++11. On top of this, some mathematical operators could be specialized for float and double if some performance improvements can be obtained in those cases. I will work on this.
Before we all get too carried away, there is an issue with "mycomplex<my_big_num>" which is that if "my_big_num" implements expression templates to optimize arithmetic operations, then these expression template end up in the wrong place with "mycomplex<my_big_num>" : which is to say inside mycomplex's implementation, instead of on mycomplex's own external operators (which is where you really need the expression templates given that each mycomplex temporary will contain 2 values).
I may be wrong but I don't see how complex numbers could benefit from template expressions. The two "components" get mixed in almost every expression and cannot be decoupled. The complex<> class always ends up using the operators of its template argument which in the case of a GMP-like number means that the appropriate template operators are called. The complex number operators always end up using real number arithmetic. So mycomplex<my_big_num> would use your "improved" operators.
And finally, there's already a small amount of complex number code in Boost under Boost.Math (just adds some extra TR1 functions), so if adding imaginary support is small enough, we could adopt it under Boost.Math I guess - or vice versa if the new code is large enough to warrant having it's own library. Just thinking out loud here that it would be better to have all the complex number code in one place if possible (and it makes sense to do so).
The TR1 operators could be moved into (next to) this new complex<> class in order to group everything. I would anyway have to implement them if I want the class to be as close as possible to the SL-one as these mathematical functions are now part of the standards.
Thanks for your input.
We over in Boost.Units land are also interested in a boost::complex implementation that plays better with units. Here's a snippet of code from Janek Kozicki that doesn't quite work the way it should: Hi, I wrote a short function that integrates Huyghens spherical wave for diffraction. (This is a single slit experiment btw). I have some questions, marked with (*) double integral( const quantity<length> x // x - position where light intensity is calculated , const quantity<length> R // R - distance from slit to screen , const quantity<length> D // D - slit width , const quantity<length> lambda // lambda - wavelength , double steps // steps - number of integration steps // (*) ) { complex<double> i(0,1); complex<double> a(0); static const double pi = 3.14159265358979323846; // (**) quantity<wavenumber,complex<double> > k=2*pi/lambda; quantity<length> d=-0.5*D; // d - position on the slit quantity<length> dd=D/steps; // dd - width of integral step // integrate from -d to d: exp(i*k*r)/r for( ; d<= 0.5*D ; d+=dd ) { quantity<length> r=sqrt(pow<2>(R)+pow<2>(x-d)); a += (dd*exp(i*k*r)/r).value(); // (***) -> shouldn't need .value() here... } return pow<2>(abs(a)); } We have a skeleton of a complex class that partially works with units in lib/units/examples/complex.cpp, but it is not fleshed out. Seems like it would be silly to have multiple competing implementations... Matthias

Le 29. 11. 11 17:31, Matthieu Schaller a écrit :
Le 29. 11. 11 12:39, John Maddock a écrit :
I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ... This can be done. The boost::complex class could simply be an implementation of the n1869 draft by Thorsten Ottosen then:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
With the addition of the TR1 reciprocal trigonometric functions and the small updates brought by C++11. On top of this, some mathematical operators could be specialized for float and double if some performance improvements can be obtained in those cases. I will work on this.
Dear all, Some news about this idea. I worked on an implementation of a complex number library which should work with any time T providing the relevant operators and basic mathematical functions. The design I had in mind is the following: provide a template class and specialisations for the float, double and long double types using the basic mathematical SL functions for these three types wherever required. This is fine and works in a satisfactory way in terms of precision. Now, this way of doing the computation is much slower than the SL version of std::complex<>. This is simply because the standard functions use built-in functions which in some cases can be as much as ten times faster than purely applying the mathematical definition. In other words a boost::complex<> library would be outperformed by the std::complex<> library in almost all non-trivial computations when used with the POD floating point numbers. Does someone have an idea of how these issue could be solved ? As such a performance drop almost kills all the motivation to use such a boost::complex<> class. Regards, Matthieu Schaller

Matthieu Schaller wrote
Le 29. 11. 11 17:31, Matthieu Schaller a écrit :
Le 29. 11. 11 12:39, John Maddock a écrit :
I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ... This can be done. The boost::complex class could simply be an implementation of the n1869 draft by Thorsten Ottosen then:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
With the addition of the TR1 reciprocal trigonometric functions and the small updates brought by C++11. On top of this, some mathematical operators could be specialized for float and double if some performance improvements can be obtained in those cases. I will work on this.
Dear all,
Some news about this idea. I worked on an implementation of a complex number library which should work with any time T providing the relevant operators and basic mathematical functions. The design I had in mind is the following: provide a template class and specialisations for the float, double and long double types using the basic mathematical SL functions for these three types wherever required.
This is fine and works in a satisfactory way in terms of precision. Now, this way of doing the computation is much slower than the SL version of std::complex<>. This is simply because the standard functions use built-in functions which in some cases can be as much as ten times faster than purely applying the mathematical definition. In other words a boost::complex<> library would be outperformed by the std::complex<> library in almost all non-trivial computations when used with the POD floating point numbers. Does someone have an idea of how these issue could be solved ? As such a performance drop almost kills all the motivation to use such a boost::complex<> class.
Is there anything that prevents the use of the standard std:.complex in the specializations of boost::complex<> boost::imaginary<> for float and double? Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Determining-interest-Pure-imaginary-numbe... Sent from the Boost - Dev mailing list archive at Nabble.com.

Le dimanche 25 décembre 2011, Vicente Botet <vicente.botet@wanadoo.fr> a écrit :
Matthieu Schaller wrote
Le 29. 11. 11 17:31, Matthieu Schaller a écrit :
Le 29. 11. 11 12:39, John Maddock a écrit :
I also think that it will be worth defining a boost::complex class on the style of the rejected standard proposal that will integrate better with the imaginary class. The standard complex class has a constraint that a boost::complex class could avoid, it only accepts the builtin double and float types. This complex class could accept any type conforming to the expected Concept. I'm sure that others are expecting a complex class that can be used with specific classes, as arbitrary precision, ... This can be done. The boost::complex class could simply be an implementation of the n1869 draft by Thorsten Ottosen then:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html
With the addition of the TR1 reciprocal trigonometric functions and the small updates brought by C++11. On top of this, some mathematical operators could be specialized for float and double if some performance improvements can be obtained in those cases. I will work on this.
Dear all,
Some news about this idea. I worked on an implementation of a complex number library which should work with any time T providing the relevant operators and basic mathematical functions. The design I had in mind is the following: provide a template class and specialisations for the float, double and long double types using the basic mathematical SL functions for these three types wherever required.
This is fine and works in a satisfactory way in terms of precision. Now, this way of doing the computation is much slower than the SL version of std::complex<>. This is simply because the standard functions use built-in functions which in some cases can be as much as ten times faster than purely applying the mathematical definition. In other words a boost::complex<> library would be outperformed by the std::complex<> library in almost all non-trivial computations when used with the POD floating point numbers. Does someone have an idea of how these issue could be solved ? As such a performance drop almost kills all the motivation to use such a boost::complex<> class.
Is there anything that prevents the use of the standard std:.complex in
the
specializations of boost::complex<> boost::imaginary<> for float and double?
Nothing but the idea of having a stand-alone package. Regards, Matthieu

Dear all, A few months ago I proposed to add an imaginary number class to boost in order to extend the std::complex class and improve performance when computations involving pure imaginary numbers are involved. Some of you showed some interest and proposed some possible improvements, the main one being to actually replace the std::complex class by a boost::complex and boost::imaginary pair of classes in order for all operations to be truly symmetric and closer to the mathematical notation. I have applied these modifications and the code now corresponds to an extended version of Thorsten Ottosen's n1869 proposal (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html) The sources and documentation are available here : http://code.google.com/p/cpp-imaginary-numbers/ They can be retrieved via the SVN repository or downloaded directly as an archive. The archive contains the complex.hpp header, a performance test, an accuracy test and two examples showing the benefits of the imaginary numbers in "downscaled" real life situations. I have tentatively embedded everything in the boost::math namespace in order to look for potential naming conflicts between my code and the existing boost ones. I would be happy to hear any comment from your side and still hope that this work is of some interest to you. Regards, Matthieu -- Matthieu Schaller PhD student - Durham University

Le 29/02/12 13:36, Matthieu Schaller a écrit :
Dear all,
A few months ago I proposed to add an imaginary number class to boost in order to extend the std::complex class and improve performance when computations involving pure imaginary numbers are involved. Some of you showed some interest and proposed some possible improvements, the main one being to actually replace the std::complex class by a boost::complex and boost::imaginary pair of classes in order for all operations to be truly symmetric and closer to the mathematical notation.
I have applied these modifications and the code now corresponds to an extended version of Thorsten Ottosen's n1869 proposal (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1869.html)
The sources and documentation are available here : http://code.google.com/p/cpp-imaginary-numbers/ They can be retrieved via the SVN repository or downloaded directly as an archive.
The archive contains the complex.hpp header, a performance test, an accuracy test and two examples showing the benefits of the imaginary numbers in "downscaled" real life situations. I have tentatively embedded everything in the boost::math namespace in order to look for potential naming conflicts between my code and the existing boost ones.
I would be happy to hear any comment from your side and still hope that this work is of some interest to you.
Hi, glad to see you have an almost complete library. I don't like the comparison between reals and imaginary just because they share a value. /// Returns true if x does not equal y template<typename T> inline bool operator!=(const imaginary<T>& x, const T& y) { return x.imag() != T(0.) || y != T(0.); } I think that I found a copy/paste issue in template<typename T> inline complex<T> conj(const complex<T>& x) { return imaginary<T>(x.real(), -x.imag()); } The line should be return complex<T>(x.real(), -x.imag()); I would be great if you can ensure that every function has been tested at least once ;-) I guess you could request the library to be added on the review schedule. Best, Vicente
participants (8)
-
Grizzly(Francis Smit)
-
John Maddock
-
Matthias Schabel
-
Matthieu Schaller
-
Neal Becker
-
Thorsten Ottosen
-
Vicente Botet
-
Vicente J. Botet Escriba