November 26, 2013
On 23/11/13 10:42, Joseph Rushton Wakeling wrote:
> Must say that, whatever the behind-the-scenes of the implementation, it seems a
> shame to lose the nice z = x + y*i notation.
>
> OTOH I guess that could lead to ambiguous code, e.g.
>
>      int i = 4;
>      complex z = x + y*i;     // what does i mean here?

I was wrong about this -- you have to write

    complex z = x + y * 1i

... which is unambiguous though I guess potentially still prone to typos :-)

November 26, 2013
On 19 November 2013 02:03, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> On 11/18/13 5:44 PM, Craig Dillabaugh wrote:
>>
>> The complex type in std.complex restricts the real/imaginary parts of the number to be float/double/real.  I am curious to know if there is a reason why integral types are not permitted. I checked the C++ equivalent and it does not have the same requirement.
>>
>> I mention this because some of my work is done with radar satellite images. All pixels in such an images are stored as complex numbers, but in all cases I am aware of they are stored a short int values. Most software that operates on the images uses complex<short> (most of it is C++).
>>
>> Is there any reason why complex numbers in D's standard lib must be of non-integral types?  I believe in C++ the type is optimized for floating point values, but allows other types.
>
>
> The simple reason is we couldn't find appropriate applications. If you make a good argument, we'll include integral types as well. Submit an enhancement request on bugzilla including your example and let's take it from there.
>

Gaussian integers / Graph plotting?

IMO I don't see a reason why not to support in the library if it requires no change on the compiler side.

Regards
Iain,
November 26, 2013
On 26/11/13 02:02, Andrei Alexandrescu wrote:
> If you got the blessing of some complex number expert, that would be great.

I'm in Italy, I could ask the pope ... :-)

As far as I can see the behaviour of std.complex.Complex is consistent both with C++'s std::complex and with D's own internal cfloat/cdouble/creal types.  The only case we don't cover with std.complex is that of multiplying a complex number with a purely imaginary one (the equivalent of multiplying, say, a creal and an ireal; multiplying a creal and a creal, even if the real part of the latter is 0, will give the same results as std.complex).

We _could_ tweak Complex internally so that in the event that its real part is 0, it behaves like a purely imaginary number, and if its imaginary part is 0, it behaves like a purely real number; but that's problematic for reasons already discussed, because it doesn't distinguish between a purely imaginary number versus one where the real part is so vanishingly small that FP considers it to be 0.

(It also leaves std.complex' behaviour incompatible with std::complex and other library implementations, though I guess that's less of a concern so long as we think what std.complex does is right.)

So, as other people have suggested, really the only thing we can reasonably do is to define a separate Imaginary type -- or get round the problems with the built-in complex and imaginary types.  It is really a shame if they are as problematic as I've heard. :-(
November 26, 2013
On 2013-11-26 01:02:12 +0000, Andrei Alexandrescu said:

> On 11/25/13 10:37 AM, Joseph Rushton Wakeling wrote:
>> On 25/11/13 18:51, Andrei Alexandrescu wrote:
>>> Doesn't sound all that bad to me. After all the built-in complex must
>>> be doing
>>> something similar. Of course if a separate imaginary type helps this
>>> and other
>>> cases, we should define it.
>> 
>> Well, if you want it I'm happy to write the patch.  It's just I'm not
>> sure that what is happening with std.complex is actually wrong if it's
>> to be considered correct that 0 * inf = nan.
> 
> If you got the blessing of some complex number expert, that would be great.
> 
> Andrei

With any luck, I'll be working on my PhD in computational physics using D toward the end of next year.    I'll definitely be giving feedback :) As of right now,  I have been out of the computational physics field for too long to give good feedback.  I can't wait to make a version of the concurrency library that works across machines :D

November 26, 2013
On Tuesday, 26 November 2013 at 11:22:38 UTC, Joseph Rushton Wakeling wrote:
> On 26/11/13 02:02, Andrei Alexandrescu wrote:
>> If you got the blessing of some complex number expert, that would be great.
>
> I'm in Italy, I could ask the pope ... :-)
>
> As far as I can see the behaviour of std.complex.Complex is consistent both with C++'s std::complex and with D's own internal cfloat/cdouble/creal types.  The only case we don't cover with std.complex is that of multiplying a complex number with a purely imaginary one (the equivalent of multiplying, say, a creal and an ireal; multiplying a creal and a creal, even if the real part of the latter is 0, will give the same results as std.complex).
>
> We _could_ tweak Complex internally so that in the event that its real part is 0, it behaves like a purely imaginary number, and if its imaginary part is 0, it behaves like a purely real number; but that's problematic for reasons already discussed, because it doesn't distinguish between a purely imaginary number versus one where the real part is so vanishingly small that FP considers it to be 0.
>
> (It also leaves std.complex' behaviour incompatible with std::complex and other library implementations, though I guess that's less of a concern so long as we think what std.complex does is right.)
>
> So, as other people have suggested, really the only thing we can reasonably do is to define a separate Imaginary type -- or get round the problems with the built-in complex and imaginary types.  It is really a shame if they are as problematic as I've heard. :-(

It seems to me that one really shouldn't special case for absolute values when dealing with floating point. A floating Imaginary type and an integer Complex type - both in std.complex - are the correct solutions IMO.
November 26, 2013
On 26/11/13 12:52, Shammah Chancellor wrote:
> With any luck, I'll be working on my PhD in computational physics using D toward
> the end of next year.    I'll definitely be giving feedback :) As of right now,
> I have been out of the computational physics field for too long to give good
> feedback.  I can't wait to make a version of the concurrency library that works
> across machines :D

Sounds very cool.  What kind of stuff will you be working on?

November 26, 2013
On 26/11/13 13:52, John Colvin wrote:
> It seems to me that one really shouldn't special case for absolute values when
> dealing with floating point. A floating Imaginary type and an integer Complex
> type - both in std.complex - are the correct solutions IMO.

Yup, agree.

November 26, 2013
On Tuesday, 26 November 2013 at 13:20:39 UTC, Joseph Rushton Wakeling wrote:
> On 26/11/13 13:52, John Colvin wrote:
>> It seems to me that one really shouldn't special case for absolute values when
>> dealing with floating point. A floating Imaginary type and an integer Complex
>> type - both in std.complex - are the correct solutions IMO.
>
> Yup, agree.

Just had a chat with one of our local numerics experts: He agreed that hidden special casing that breaks standards compliance is bad and that whatever the solution was it should be explicit.

However, the following situation arises:

Complex!double(1, -double.inf) * Complex!int(0, i);

What does IEEE say about that? 0 * inf == nan?
November 26, 2013
On 26/11/13 14:32, John Colvin wrote:
> What does IEEE say about that? 0 * inf == nan?

Can't speak for the standard, but in both D and C++, 0 * inf evaluates to nan.

November 26, 2013
26-Nov-2013 09:06, Daniel Murphy пишет:
> "Dmitry Olshansky" <dmitry.olsh@gmail.com> wrote in message
> news:l6tfm8$2hnj$1@digitalmars.com...
>>>
>>
>> Can't it just check for the real part being exactly zero and special- case
>> multiplication for that?
>>
>
> There is no such thing as exactly zero in floating point.  Only -0 and +0.

Well, let it be magnitude, "exactly" implies as good zero test as we need. I'm still of the opinion that a few predictable branches like `if(rhs.re.isZero)` won't kill it.

Regardless, the point is that built-ins hardly help here at all as you may just as well get an "exactly" 0+1i for some complex computation, and the result won't suddenly change type to i{real,double,float}.

-- 
Dmitry Olshansky