View mode: basic / threaded / horizontal-split · Log in · Help
May 01, 2009
Re: Fixing the imaginary/complex mess
Georg Wrede wrote:
> Don wrote:
>> D currently allows some conversions between complex/imaginary types 
>> and real types, which are highly dubious.
>>
>> Given creal z, ireal y, these casts are legal:
>> real x = cast(real)z;
>> x = cast(real)y; // always sets x==0, regardless of the value of y.
>> But I believe that should not be legal.
>>
>> For the first case, it should be written as:   real x = z.re;
>> (which is shorter and clearer), and the second case is probably a bug, 
>> and should be x = y.im; (unless the intention really was to set x=0!).
>>
>> By the same logic, we could have sqrt(-1)==0, since the real part is 0.
>>
>> The most important effect of disallowing these casts would be to fix a 
>> host of bugs and wierd behaviour. All the A op= B operations involve a 
>> cast to A. If those nonsensical casts become illegal, the nonsensical 
>> op= operations become illegal automatically.
>>
>> Eg, ireal y;
>> y *= y; // mathematically nonsense, y*y is real, so can't be stored in 
>> a pure imaginary type!
>>
>> There are a few segfault/ICE bugs (eg 718, 2839) which involve 
>> int/=complex, an operation which never makes any sense anyway.
>>
>> I think we're just making problems for ourselves by allowing these 
>> useless operations. I think they should be killed.
>> Does anyone object? (If not, I'll create a patch to do it; it's not 
>> very difficult).
> 
> It might be a good idea to write in the docs why these operations are 
> missing. Even better would of course be if the user got a message 
> stating that this operation isn't implemented because it doesn't make 
> mathematical sense.

I'll make sure the error messages are sensible.

> 
> If the latter isn't done, then many people will just think there's 
> something wrong with the compiler/language. Bad press we don't need.

I don't think anyone expects to be able to divide an integer by an 
imaginary, and then assign it to an integer. I was astonished that the 
compiler accepted it.
May 01, 2009
Re: Fixing the imaginary/complex mess
Andrei Alexandrescu wrote:
> Don wrote:
>> D currently allows some conversions between complex/imaginary types 
>> and real types, which are highly dubious.
>>
>> Given creal z, ireal y, these casts are legal:
>> real x = cast(real)z;
>> x = cast(real)y; // always sets x==0, regardless of the value of y.
>> But I believe that should not be legal.
>>
>> For the first case, it should be written as:   real x = z.re;
>> (which is shorter and clearer), and the second case is probably a bug, 
>> and should be x = y.im; (unless the intention really was to set x=0!).
>>
>> By the same logic, we could have sqrt(-1)==0, since the real part is 0.
>>
>> The most important effect of disallowing these casts would be to fix a 
>> host of bugs and wierd behaviour. All the A op= B operations involve a 
>> cast to A. If those nonsensical casts become illegal, the nonsensical 
>> op= operations become illegal automatically.
>>
>> Eg, ireal y;
>> y *= y; // mathematically nonsense, y*y is real, so can't be stored in 
>> a pure imaginary type!
>>
>> There are a few segfault/ICE bugs (eg 718, 2839) which involve 
>> int/=complex, an operation which never makes any sense anyway.
>>
>> I think we're just making problems for ourselves by allowing these 
>> useless operations. I think they should be killed.
>> Does anyone object? (If not, I'll create a patch to do it; it's not 
>> very difficult).
> 
> Since you're looking into this already, I suggest we move for the kill 
> and eliminate built-in complex.

I'd like to actually eliminate these operations from D1. Otherwise, I 
can't see the related D1 bugs ever getting fixed. Any code which relies 
on these operations is broken; I think there's an excellent chance that 
there isn't any code using it.
Also, these operations would not be provided by a library class, so I 
think it's a useful intermediate step.
We can't remove the complex types until we have a library solution.
May 01, 2009
Re: Fixing the imaginary/complex mess
Don wrote:
> I'd like to actually eliminate these operations from D1. Otherwise, I
> can't see the related D1 bugs ever getting fixed. Any code which relies
> on these operations is broken; I think there's an excellent chance that
> there isn't any code using it.
> Also, these operations would not be provided by a library class, so I
> think it's a useful intermediate step.
> We can't remove the complex types until we have a library solution.

I think it's perfectly acceptable to not fix these in D1 and only address them
in D2.  There's lots of things in D1 that are only fixed in D2.

Later,
Brad
May 01, 2009
Re: Fixing the imaginary/complex mess
Brad Roberts wrote:
> Don wrote:
>> I'd like to actually eliminate these operations from D1. Otherwise, I
>> can't see the related D1 bugs ever getting fixed. Any code which relies
>> on these operations is broken; I think there's an excellent chance that
>> there isn't any code using it.
>> Also, these operations would not be provided by a library class, so I
>> think it's a useful intermediate step.
>> We can't remove the complex types until we have a library solution.
> 
> I think it's perfectly acceptable to not fix these in D1 and only address them
> in D2.  There's lots of things in D1 that are only fixed in D2.

I think so many people are actually using D1, that ICE bugs really 
should get fixed.
> 
> Later,
> Brad
May 01, 2009
Re: Fixing the imaginary/complex mess
Don wrote:
> Georg Wrede wrote:
>> Don wrote:
>>> D currently allows some conversions between complex/imaginary types 
>>> and real types, which are highly dubious.
>>>
>>> Given creal z, ireal y, these casts are legal:
>>> real x = cast(real)z;
>>> x = cast(real)y; // always sets x==0, regardless of the value of y.
>>> But I believe that should not be legal.
>>>
>>> For the first case, it should be written as:   real x = z.re;
>>> (which is shorter and clearer), and the second case is probably a 
>>> bug, and should be x = y.im; (unless the intention really was to set 
>>> x=0!).
>>>
>>> By the same logic, we could have sqrt(-1)==0, since the real part is 0.
>>>
>>> The most important effect of disallowing these casts would be to fix 
>>> a host of bugs and wierd behaviour. All the A op= B operations 
>>> involve a cast to A. If those nonsensical casts become illegal, the 
>>> nonsensical op= operations become illegal automatically.
>>>
>>> Eg, ireal y;
>>> y *= y; // mathematically nonsense, y*y is real, so can't be stored 
>>> in a pure imaginary type!
>>>
>>> There are a few segfault/ICE bugs (eg 718, 2839) which involve 
>>> int/=complex, an operation which never makes any sense anyway.
>>>
>>> I think we're just making problems for ourselves by allowing these 
>>> useless operations. I think they should be killed.
>>> Does anyone object? (If not, I'll create a patch to do it; it's not 
>>> very difficult).
>>
>> It might be a good idea to write in the docs why these operations are 
>> missing. Even better would of course be if the user got a message 
>> stating that this operation isn't implemented because it doesn't make 
>> mathematical sense.
> 
> I'll make sure the error messages are sensible.
> 
>> If the latter isn't done, then many people will just think there's 
>> something wrong with the compiler/language. Bad press we don't need.
> 
> I don't think anyone expects to be able to divide an integer by an 
> imaginary, and then assign it to an integer. I was astonished that the 
> compiler accepted it.

Just goes to show you the average math knowledge. I never would have 
thought of omitting it either. :-)
May 03, 2009
Re: Fixing the imaginary/complex mess
Don wrote:
> I don't think anyone expects to be able to divide an integer by an 
> imaginary, and then assign it to an integer. I was astonished that the 
> compiler accepted it.

There actually is a reason - completeness. Mathematically, there is a 
definite answer to it, so why not fill in all the entries for all the 
combinations?
May 03, 2009
Re: Fixing the imaginary/complex mess
On Sun, May 3, 2009 at 2:35 AM, Walter Bright
<newshound1@digitalmars.com> wrote:
> Don wrote:
>>
>> I don't think anyone expects to be able to divide an integer by an
>> imaginary, and then assign it to an integer. I was astonished that the
>> compiler accepted it.
>
> There actually is a reason - completeness. Mathematically, there is a
> definite answer to it, so why not fill in all the entries for all the
> combinations?

But the result of int divided by imaginary is pure imaginary.  So I
think Don's point was that you shouldn't be able to assign that back
to an int.

--bb
May 04, 2009
Re: Fixing the imaginary/complex mess
Walter Bright wrote:
> Don wrote:
>> I don't think anyone expects to be able to divide an integer by an 
>> imaginary, and then assign it to an integer. I was astonished that the 
>> compiler accepted it.
> 
> There actually is a reason - completeness. Mathematically, there is a 
> definite answer to it, so why not fill in all the entries for all the 
> combinations?

In the case complex = int/complex, there's no problem. It's the case int 
= int/complex that doesn't make sense.
And that's fundamentally because cast(real)(2 + 3i) doesn't have a 
definite answer.
There's no mathematical operation to convert a complex number to a real.
Normally, to get a real result, you need to do something like 
multiplying by the complex conjugate. You CAN take the real part of a 
complex number, and you can also take the modulus (which makes a lot of 
sense if you're using polar represantation).

Of course, cast() is not a mathematical operation, it's a D operation, 
so we can define it however we like. But defining it
cast(real)z = z.re;
is an arbitrary decision, which introduces lots of complexity to the 
language, and the many compiler bugs are a consequence.
It's confusing for newbies (there's been questions on D.learn asking, "I 
can get the real part of a complex number with cast(real), but how do I 
get the imaginary part? cast(ireal) gives me an ireal, not a real!").

Since D supports the very nice .re syntax, there's really no reason to 
define cast(real) at all. z.re is better in 100% of use cases. There are 
*NO* use cases for cast(real); any use of cast(real) is a bug. We should 
kill it.
May 04, 2009
Re: Fixing the imaginary/complex mess
Don wrote:
> In the case complex = int/complex, there's no problem. It's the case int 
> = int/complex that doesn't make sense.
> And that's fundamentally because cast(real)(2 + 3i) doesn't have a 
> definite answer.

Devil's advocate: one could argue it's the same as cast(int) of a float -- it 
returns the closest representable value, for some definition of "closest".
May 04, 2009
Re: Fixing the imaginary/complex mess
Frits van Bommel wrote:
> Don wrote:
>> In the case complex = int/complex, there's no problem. It's the case 
>> int = int/complex that doesn't make sense.
>> And that's fundamentally because cast(real)(2 + 3i) doesn't have a 
>> definite answer.
> 
> Devil's advocate: one could argue it's the same as cast(int) of a float 
> -- it returns the closest representable value, for some definition of 
> "closest".

Sure, you're at liberty to argue anything. But mathematicians don't do 
that. Nor should we. It's misleading, and just not helpful.
BTW, another equally reasonable and equally unhelpful way you could 
define cast(real)(x + iy) is as sqrt(x*x - y*y).

The most justifiable way to do it would be to say
cast(real)(x+iy) is:
 if (y==0) return x; else throw(CastError);
But again, it's just not helpful. Make it a compile-time error.
1 2 3 4
Top | Discussion index | About this forum | D home