Re: [boost] Gauging Interest: polar_complex

I appreciate everyone's comments (and I'll respond to a number below), but it seems interest in this is not widespread enough to justify trying to formally include it. I'll probably clean it up a bit and post it on my own web-site at some point in case someone somewhere might find it useful. It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :) ------------------------------------------------------------ Regarding specific comments: Roland Schwarz wrote:
For some applications, polar complex numbers have significant advantages over Cartesian complex (e.g., std::complex) in efficiency and numerical accuracy.
Just out of curiosity: Can you give me an example of an algorithm where this would be of advantage?
Well, Hubert Holin gave one: tracking orbits (trajectories in polar coordinates). There are actually a number of subtleties to be aware of in mapping a physical 2D plane to the complex plane, so in that case, I would actually probably use a true polar_vector2D class rather than polar_complex. However, for field equations (including those from fluid dynamics, my area), using tools from complex analysis can create new, simpler formulations of problems in the complex plane. If the resulting mapping has a high order of circular symmetry, then polar_complex numbers have advantages. The most obvious use of polar_complex numbers would be in wave mechanics. The phase and magnitude are often weakly coupled; you can sometimes work with just one component in different parts of the calculations. At the lowest level, polar_complex numbers are best when the primary operations are multiplications/divisions and powers/roots. When you start adding/subtracting, then cartesian representations begin to win out (because of the cost of the trig functions). There's another advantage of polar_complex numbers that I didn't spell out separately: *development* efficiency, i.e. how quickly one can write an acceptable program for a simulation prototype or a quick-and-dirty calculation. Many problems (in fact, a majority of those I have worked with) are more naturally formulated in polar form; it's therefore easier to write a program that uses that representation. This is just the old programming adage "Think/write in the problem domain, not the language domain.". I'd address run-time efficiency later in those cases where it was a concern; I haven't yet seen any cases where the polar_complex representation was obviously inefficient. Hubert Holin wrote:
The main problems I foresee are in the commingling of the two different classes. It is interesting to see a complex number (among other ways) either as its two canonical coordinates, or in a polar representation, but sometimes we just want to switch between the two for a given instance. So I fear a substantial amount of typical run time will be spent doing conversions.
I defined explicit conversions to and from std::complex, but I used them fairly rarely. If the problem truly belongs in the polar representation, then you won't need many conversions. In fact, I wrote polar_complex in the first place in a case when I found myself very frequently calling abs, arg, and polar using std::complex -- the problem didn't belong in the cartesian representation. But you are right that the relation between them needs careful consideration; that was on my list of issues to address if I "boosted" it.
There is another, perhaps deeper, problem to consider, with the representation of complex numbers (and others), as evidenced by a thread on comp.std.c++ a couple of years back: layout guaranties. People wanted, in essence, to be able to break encapsulation when it suited them (for efficiency in time-critical code). The discussion also encompassed thoughts about the polar representation (which, as you remarked, also has advantages). As far as I know, there has been no tangible result to that thread.
In short, I am not sure a library for complex numbers in polar form would be worthwhile, but I certainly think that if you could make the above situation progress (as in: write a formal proposal), it would be a great win for us all.
Well, I needn't worry about polar_complex layout because there are no C or FORTRAN equivalents to be layout compatible with. :) Regarding std::complex, just about a month ago, I posted to comp.lang.c++.moderated about these very issues. The current status is in this paper: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1589.html The layout guarantee seems certain, and it lays out possible solutions for the second issue. I don't see much that I can add other than to give my recommendation on the solution and prod them to pick one already. I've already been doing both on clc++m; I suppose I could write Howard Hinnant directly, but he's responded to several threads so he's probably read most of my posts. This is becoming a digression, but my opinion, for what it's worth: std::complex should never have been encapsulated as it was in the first place. And to justify this, in addition to the efficiency issues, there is clarity of the code's intent. Consider: 1a) z = complex<double>(z.real(), 1); 2a) z.imag() = 1; 1b) z = complex<double>(z.real(), z.imag() + 1); 2b) z.imag() += 1; I think it's clearly much easier to read the intent of the code in the second cases. Matt Austern wrote:
But is it likely that you would want to use a package that provides complex numbers in polar form? My experience is that if you're working with complex numbers that you want to think of in the form r exp(i phi), then you'll probably just do the work of separating out the magnitude and phase ahead of time in your equations, and then compute with them separately. After all: if you're doing something where the magnitude-phase form is most convenient, it usually means that putting numbers in that form makes the equations simpler.
True to a degree, though such separation is not always possible, especially in non-linear situations. And a similar argument is true for cartesian complex: if you're doing something where the real-imaginary form is most convenient, it also usually means that putting numbers in that form makes the equations simpler. But it's usually easier to keep track of, for instance, just vector< complex<double> > Numbers; than vector<double> NumbersReal; vector<double> NumbersImag; and there's usually no harm in combining them like that (unless of course complex is over-encapsulated, but I digress again. . .). Similarly, vector< polar_complex<double> > Wave; is simpler to deal with than vector<double> WaveAmplitude; vector<double> WaveMagnitude; so combine them if there's no harm in doing so. This is appealing to the "development efficiency" (and code clarity) argument I made above.
Still, from the discussion on comp.std.cpp a few years back, I recall that there was a feeling that having multiple representations (say cartesian and polar) at the same time would have been nice. Of course, it would have been a bloated beast (at least in a naive implementation), and a slow one at that (to keep track of the various changes, in a naive implementation still). Furthermore it clashed with the desire to have some layout guaranty which played nice with C (that line of reasoning seems to have flown out in limbo, however).
This illustration is merely there as a reminder that the wish for concurrent multiple points of views of a given abstract entity is not a futile one, if one that I fear can't be translated from mathematics to CS. We've had another illustration of that recently with the affine space/vector space discussion in a GUI thread a few days back here (which also happens to be relevant to this discussion as well, at least in two dimensions).
Well now you are touching on an entirely separate point. For a mathematical primitive used in numerical work, making the same class hold different representations is a terrible idea. Pick the representation you need and stick with it, converting between representations only if/when you must. If you find yourself converting constantly, then you have picked the wrong algorithm or need another representation altogether. And how many representations should you implement in one class? Why cartesian and polar coordinates but not parabolic, elliptical, bipolar, etc.? ------------------------------------------------------------ Again, I appreciate all the comments, but the interest obviously isn't there for developing the class further. Thanks, Mickey Moore

Mickey Moore wrote:
I appreciate everyone's comments (and I'll respond to a number below), but it seems interest in this is not widespread enough to justify trying to formally include it. I'll probably clean it up a bit and post it on my own web-site at some point in case someone somewhere might find it useful.
It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :)
No, it probably only means that people are more opinionated when it comes to artistic design than they are knowledgable about polar complex numbers <g>.

Edward Diener wrote:
Mickey Moore wrote:
I appreciate everyone's comments (and I'll respond to a number below), but it seems interest in this is not widespread enough to justify trying to formally include it. I'll probably clean it up a bit and post it on my own web-site at some point in case someone somewhere might find it useful.
It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :)
No, it probably only means that people are more opinionated when it comes to artistic design than they are knowledgable about polar complex numbers <g>.
Or maybe a whole lot of people eager to contribute somehow who are having a little of C. Northcote Parkinson's nuclear adversion that we have grown so fond of mentioning (1958). A question: Is this form of the "bicycle shed"--which seems to be the most prevailent within Boost--a bad thing? When Poul-Henning Kamp was writing on the topic in 1999, he seemed to be primarily referring to undue discussion on a proposal as an unnecessary barrier to its progress. On Boost lists, though, most of this activity is not obstructionist, but perhaps just people attracted more to the task of drawing pretty rockets than to fixing bugs in their least favorite part of Boost code. Beman Dawes' writing on the web page seems to indicate that this latter sort of activity is the primary problem, without mentioning the obstructionist effect. Aaron W. LaFramboise

Aaron W. LaFramboise wrote:
Edward Diener wrote:
Mickey Moore wrote:
It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :)
No, it probably only means that people are more opinionated when it comes to artistic design than they are knowledgable about polar complex numbers <g>.
Or maybe a whole lot of people eager to contribute somehow who are having a little of C. Northcote Parkinson's nuclear adversion that we have grown so fond of mentioning (1958).
Or more likely... People just need a break from all the hard work that was the 1.32.0 release. People need fun diversions once in a while. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com - 102708583/icq

Mickey Moore <mgmoore@austin.rr.com> writes: | Regarding std::complex, just about a month ago, I posted to | comp.lang.c++.moderated about these very issues. The current status | is in this paper: | http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1589.html | The layout guarantee seems certain, and it lays out possible solutions | for the second issue. I don't see much that I can add other than to | give my recommendation on the solution and prod them to pick one | already. I've already been doing both on clc++m; I suppose I could | write Howard Hinnant directly, but he's responded to several threads | so he's probably read most of my posts. | | This is becoming a digression, but my opinion, for what it's worth: | std::complex should never have been encapsulated as it was in the | first place. And to justify this, in addition to the efficiency | issues, there is clarity of the code's intent. Consider: | | 1a) z = complex<double>(z.real(), 1); | 2a) z.imag() = 1; | | 1b) z = complex<double>(z.real(), z.imag() + 1); | 2b) z.imag() += 1; | | I think it's clearly much easier to read the intent of the code in the | second cases. The original issue was submitted and fix proposal was agreed upon, and even went into a Ready status (I think). Then, when I was not watching out, it suddenly came out in Open status along with some rationale I still find strange. Quantum process, mind you. -- Gaby

Mickey Moore wrote:
I appreciate everyone's comments (and I'll respond to a number below), but it seems interest in this is not widespread enough to justify trying to formally include it. I'll probably clean it up a bit and post it on my own web-site at some point in case someone somewhere might find it useful.
Well, my question is, why is it useful to you? I mean, it sounds like the consensus is, if you want to use polar form, you will just need it in intermediate computations, and not in any explicit representations. So why have you not settled on this solution?
[...] There's another advantage of polar_complex numbers that I didn't spell out separately: *development* efficiency, i.e. how quickly one can write an acceptable program for a simulation prototype or a quick-and-dirty calculation. Many problems (in fact, a majority of those I have worked with) are more naturally formulated in polar form; it's therefore easier to write a program that uses that representation. This is just the old programming adage "Think/write in the problem domain, not the language domain.".
I personally think this is a good argument, but I don't have a need for complex numbers in my work, so I can't speak as a domain expert.
[...] Well, I needn't worry about polar_complex layout because there are no C or FORTRAN equivalents to be layout compatible with. :)
Regardless, you should be mindful of representations which *do* give you layout guarantees, vs. those that don't. For instance, elements of an array are guaranteed to be contiguous, whereas members of a struct may be separated by padding. If someone wants to get at the raw data, they may prefer a type with a guaranteed layout so they can do dirty "bare metal" coding.
[...] Similarly, vector< polar_complex<double> > Wave; is simpler to deal with than vector<double> WaveAmplitude; vector<double> WaveMagnitude; so combine them if there's no harm in doing so.
This is appealing to the "development efficiency" (and code clarity) argument I made above.
This sounds like a good argument too, but might be even more compelling with some actual use-cases cited.
[...] Again, I appreciate all the comments, but the interest obviously isn't there for developing the class further.
Well, I wouldn't jump to that conclusion. I think it is worth noting that C++ hasn't exactly attracted a large numerics community, so the response you get right now may be more a reflection of that fact than anything else. I wonder if we had a lot of numerics people that perhaps more of them would say: "Yes, I definitely need polar complex numbers in my work and your encapsulation is very helpful." As it is, the competent numerics people seem to form a rather small segment of the Boost community. So in this case, perhaps you need to be an advocate for numerics, rather than assuming that because there is not a current need that there is no need at all. What might be particularly helpful is if you can get numerics people using *other languages* to say that polar representations are very useful in their work. That might be a compelling reason to add such support to C++. Or perhaps such support is not widespread, but useful; and people don't use it more because it doesn't exist. Then you need to argue why it is better than rewriting your equations to avoid needing intermediate polar representations. So my point is, programmers must be a jack-of-all-trades to some extent. The libraries that get the most attention are the ones that have the most general applicability, whether the library itself has considerable merit or not. Sometimes a proposal doesn't get attention because it lacks merit, and sometimes it doesn't get attention because the Boost community itself lacks experience in that domain. I think it is important to distinguish those cases and treat them appropriately. That is not to say that Hubert or Matt or anyone else is not a good mathematician or numerics expert. That is merely to say that they are not sufficiently numerous to form a compelling sample size. So don't judge the interest by the magnitude of the response. Instead, argue your case until everyone reaches a consensus or a deadlock. Even as a non-expert in this area, it seems to me that neither state has been reached, so more debate seems perfectly reasonable. In fact, it seems that education as much as debate is required here, and it is merely a lack of domain breadth that leads to a lack of interest. You have to remember that programmers are economical by nature, and resist adding things that aren't compellingly useful if it can be avoided. So you just need to motivate your library some more, and draw on the experiences of others in numerics if you must. I think people are willing to consider more use cases if you simply bring them to our attention.
[...] It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :)
There's several things wrong with that conclusion. First of all, I think it's safe to say that the Boost community takes a certain amount of pride in its image. Something like a logo goes straight to the heart of that pride, which is why it is such a passionate issue for us. Second, art is by nature not rigorous and scientific, so anyone can contribute and comment without being proven wrong. Third, the logo is a creative expression issue, which is unlike anything else that goes on in Boost, so you really can't compare it to library proposals. Fourth, some issues and libraries simply need time to incubate in the collective consciousness, and only reach a critical amount of interest after an inscrutable length of time. It may be that in the future, we have enough numerics people that we will want to look at polar forms in earnest. It is probably the case that the Boost web site in general, and the logo in particular, have reached that critical point where change is motivated. In any case, a certain amount of humility isn't a bad thing; just don't overgeneralize because I think we have unique issues going on. Dave

Somewhere in the E.U., le 29/11/2004 Bonjour In article <6.1.0.6.2.20041123072043.027c5898@pop-server.austin.rr.com>, Mickey Moore <mgmoore@austin.rr.com> wrote:
I appreciate everyone's comments (and I'll respond to a number below), but it seems interest in this is not widespread enough to justify trying to formally include it. I'll probably clean it up a bit and post it on my own web-site at some point in case someone somewhere might find it useful.
It was a good exercise in humility to note that, judging from the message frequency, people are at least a hundred times more interested in the new logo for the Boost web-site. :)
------------------------------------------------------------
Regarding specific comments:
Roland Schwarz wrote:
For some applications, polar complex numbers have significant advantages over Cartesian complex (e.g., std::complex) in efficiency and numerical accuracy.
Just out of curiosity: Can you give me an example of an algorithm where this would be of advantage?
Well, Hubert Holin gave one: tracking orbits (trajectories in polar coordinates). There are actually a number of subtleties to be aware of in mapping a physical 2D plane to the complex plane, so in that case, I would actually probably use a true polar_vector2D class rather than polar_complex.
Yes. [SNIP]
This illustration is merely there as a reminder that the wish for concurrent multiple points of views of a given abstract entity is not a futile one, if one that I fear can't be translated from mathematics to CS. We've had another illustration of that recently with the affine space/vector space discussion in a GUI thread a few days back here (which also happens to be relevant to this discussion as well, at least in two dimensions).
Well now you are touching on an entirely separate point. For a mathematical primitive used in numerical work, making the same class hold different representations is a terrible idea. Pick the representation you need and stick with it, converting between representations only if/when you must. If you find yourself converting constantly, then you have picked the wrong algorithm or need another representation altogether. And how many representations should you implement in one class? Why cartesian and polar coordinates but not parabolic, elliptical, bipolar, etc.?
------------------------------------------------------------
Again, I appreciate all the comments, but the interest obviously isn't there for developing the class further.
Thanks, Mickey Moore
Well, as others in this thread have said, it is not because you have not (yet) convinced the few of us which have replied, that your proposal has no merit. There is definitely the possibility that other arguments would sway us (but then they would have to really be good). I would like to comment further on the above part of your post. What you refer to as "making the same class hold different representations is a terrible idea", would be what I call a naive implementation. Certainly, "stacking" representations and insuring that they are always in synch would result in an awfully bloated, miserably slow creature. However, the goal of "multiplicity of concurrent points of view" ("structural polymorphism"?) is a compelling one. I am only dreaming out loud here, but is there really no way of having some aspect of it? Something like a "lazy" implementation, perhaps, that would freeze its actual internals at critical junctures rather than all the time? I certainly do not know how to create such a thing, but considering the invention of expression templates and the other metamagic we see here, one can only wonder if such is really impossible. Merci Hubert Holin
participants (7)
-
Aaron W. LaFramboise
-
David B. Held
-
Edward Diener
-
Gabriel Dos Reis
-
Hubert Holin
-
Mickey Moore
-
Rene Rivera