Re: Fixing the imaginary/complex mess

2011-06-13 Thread Robert Clipsham

On 12/06/2011 23:37, bearophile wrote:

Andrei:


Don, instead of this fix, could be at best phase everything
built-in about complex out?


Two usages of complex numbers in the RosettaCode site.

Acommon place where you find complex numbers is to plot
Mandelbrot/Julia sets: http://rosettacode.org/wiki/Mandelbrot_set#D

import std.stdio, std.math;

void main() { enum maxIter = 1000; foreach (y; -39 .. 39) { foreach
(x; -39 .. 39) { auto c = y/40.0 - 0.5 + x/40.0i, z = 0.0 + 0.0i, i =
0; for (; i  maxIter  abs(z)  4; i++) z = z ^^ 2 + c; write(i ==
maxIter ? '#' : ' '); } writeln(); } }



Version using std.complex:

import std.stdio, std.complex;

void main() { enum maxIter = 1000; foreach (y; -39 .. 39) { foreach
(x; -39 .. 39) { auto c = Complex!double(y/40.0 - 0.5, x/40.0), z =
Complex!double(0, 0), i = 0; for (; i  maxIter  z.abs()  4; i++)
z = z ^^ 2 + c; write(i == maxIter ? '#' : ' '); } writeln(); } }


I think it's worth adding to std.complex module few examples of
usage, plus a complex() function so you are allowed to write (the
imaginary part defaults to zero if the real part is set to zero):
auto z = complex(5);


I seemed to think the plan for complex numbers was to do what happened 
with associative arrays, that is, keep the language syntax, but have the 
feature implemented in the library. Is this not the case?


--
Robert
http://octarineparrot.com/


Re: Fixing the imaginary/complex mess

2011-06-13 Thread Lars T. Kyllingstad
On Mon, 13 Jun 2011 12:36:27 +0100, Robert Clipsham wrote:

 On 12/06/2011 23:37, bearophile wrote:
 Andrei:

 Don, instead of this fix, could be at best phase everything built-in
 about complex out?

 Two usages of complex numbers in the RosettaCode site.

 Acommon place where you find complex numbers is to plot
 Mandelbrot/Julia sets: http://rosettacode.org/wiki/Mandelbrot_set#D

 import std.stdio, std.math;

 void main() { enum maxIter = 1000; foreach (y; -39 .. 39) { foreach (x;
 -39 .. 39) { auto c = y/40.0 - 0.5 + x/40.0i, z = 0.0 + 0.0i, i = 0;
 for (; i  maxIter  abs(z)  4; i++) z = z ^^ 2 + c; write(i ==
 maxIter ? '#' : ' '); } writeln(); } }



 Version using std.complex:

 import std.stdio, std.complex;

 void main() { enum maxIter = 1000; foreach (y; -39 .. 39) { foreach (x;
 -39 .. 39) { auto c = Complex!double(y/40.0 - 0.5, x/40.0), z =
 Complex!double(0, 0), i = 0; for (; i  maxIter  z.abs()  4; i++) z
 = z ^^ 2 + c; write(i == maxIter ? '#' : ' '); } writeln(); } }


 I think it's worth adding to std.complex module few examples of usage,
 plus a complex() function so you are allowed to write (the imaginary
 part defaults to zero if the real part is set to zero): auto z =
 complex(5);
 
 I seemed to think the plan for complex numbers was to do what happened
 with associative arrays, that is, keep the language syntax, but have the
 feature implemented in the library. Is this not the case?

That was my understanding as well, which is why I never added a complex() 
helper function.

It is, however, my humble opinion that we should just get rid of the 
complex literals.  (Otherwise, std.complex would have to be moved into 
druntime.)

-Lars


Re: Fixing the imaginary/complex mess

2011-06-13 Thread Andrei Alexandrescu

On 6/13/11 6:36 AM, Robert Clipsham wrote:

I seemed to think the plan for complex numbers was to do what happened
with associative arrays, that is, keep the language syntax, but have the
feature implemented in the library. Is this not the case?


No, the current vision is to completely replace complex with library 
artifacts. Walter wants to keep the i postfix as a hack, but I think 
that's completely unnecessary.


A complex() convenience function should be useful. If anyone has the 
time, please create a pull request. It should never automatically create 
Complex with an integral type, as bearophile mentioned. For the rare 
cases where complex is needed with integrals, it should be fine to use 
Complex!int etc. directly.



Andrei



Re: Fixing the imaginary/complex mess

2011-06-13 Thread Lars T. Kyllingstad
On Mon, 13 Jun 2011 08:36:32 -0500, Andrei Alexandrescu wrote:

 On 6/13/11 6:36 AM, Robert Clipsham wrote:
 I seemed to think the plan for complex numbers was to do what happened
 with associative arrays, that is, keep the language syntax, but have
 the feature implemented in the library. Is this not the case?
 
 No, the current vision is to completely replace complex with library
 artifacts. Walter wants to keep the i postfix as a hack, but I think
 that's completely unnecessary.
 
 A complex() convenience function should be useful. If anyone has the
 time, please create a pull request. It should never automatically create
 Complex with an integral type, as bearophile mentioned. For the rare
 cases where complex is needed with integrals, it should be fine to use
 Complex!int etc. directly.

Sure, I'll add complex().

Regarding Complex!int:  I have explicitly restricted Complex to floating-
point types.  Here is a message I sent to the Phobos mailing list, 
explaining why:

http://lists.puremagic.com/pipermail/phobos/2010-April/000286.html

See also Don's reply to that message, it really drives the point home:

http://lists.puremagic.com/pipermail/phobos/2010-April/000287.html

-Lars


Re: Fixing the imaginary/complex mess

2011-06-13 Thread Lars T. Kyllingstad
On Mon, 13 Jun 2011 14:51:52 +, Lars T. Kyllingstad wrote:

 On Mon, 13 Jun 2011 08:36:32 -0500, Andrei Alexandrescu wrote:
 
 A complex() convenience function should be useful. If anyone has the
 time, please create a pull request. [...]
 
 Sure, I'll add complex().

As promised:
https://github.com/D-Programming-Language/phobos/pull/103

-Lars


Re: Fixing the imaginary/complex mess

2011-06-13 Thread bearophile
Andrei:

 Walter wants to keep the i postfix as a hack, but I think 
 that's completely unnecessary.

Before deciding I'd like to know the rationale to keep it. In principle I like 
handy complex number literals. In practice I don't use them often enough...

Another note: I'd like std.math.abs to perform what std.complex.Complex!T.abs 
does. So I will be able to use it functionally (currently std.math.abs is able 
to digest built-in complex numbers too):

alias Complex!double C;
C[] a = [C(1,2), C(2,4)];
auto m = map!abs(a);

Bye,
bearophile


Re: Fixing the imaginary/complex mess

2011-06-12 Thread Andrei Alexandrescu

On 04/30/2009 02:20 PM, 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).


Don, instead of this fix, could be at best phase everything built-in 
about complex out?


Thanks,

Andrei


Re: Fixing the imaginary/complex mess

2011-06-12 Thread bearophile
Andrei:

 Don, instead of this fix, could be at best phase everything built-in 
 about complex out?

Two usages of complex numbers in the RosettaCode site.

Acommon place where you find complex numbers is to plot  Mandelbrot/Julia sets:
http://rosettacode.org/wiki/Mandelbrot_set#D

import std.stdio, std.math;

void main() {
enum maxIter = 1000;
foreach (y; -39 .. 39) {
foreach (x; -39 .. 39) {
auto c = y/40.0 - 0.5 + x/40.0i,
 z = 0.0 + 0.0i,
 i = 0;
for (; i  maxIter  abs(z)  4; i++)
z = z ^^ 2 + c;
write(i == maxIter ? '#' : ' ');
}
writeln();
}
}



Version using std.complex:

import std.stdio, std.complex;

void main() {
enum maxIter = 1000;
foreach (y; -39 .. 39) {
foreach (x; -39 .. 39) {
auto c = Complex!double(y/40.0 - 0.5, x/40.0),
 z = Complex!double(0, 0),
 i = 0;
for (; i  maxIter  z.abs()  4; i++)
z = z ^^ 2 + c;
write(i == maxIter ? '#' : ' ');
}
writeln();
}
}


I think it's worth adding to std.complex module few examples of usage, plus a 
complex() function so you are allowed to write (the imaginary part defaults to 
zero if the real part is set to zero):
auto z = complex(5);

Instead of:
auto z = Complex!double(5, 0);


complex(5) probably has to create a Complex!double and not a Complex!int (that 
is not even supported, std.complex.Complex support floating point values only).

---

Another common usage of D complex numbers is to represent generic 2D points.
http://rosettacode.org/wiki/Constrained_random_points_on_a_circle#D

Original code (to plot some points in a circle):

import std.stdio, std.random, std.math;
 
void main() {
char[31][31] table = ' ';
 
foreach (i; 0 .. 100) {
int x, y;
do {
x = uniform(-15, 16);
y = uniform(-15, 16);
} while(abs(12.5 - abs(x + y * 1i))  2.5);
table[x + 15][y + 15] = '*';
}
 
foreach (row; table)
writeln(row);
}


Version using std.complex:

import std.stdio, std.random, std.complex, std.math;

void main() {
char[31][31] table = ' ';

foreach (i; 0 .. 100) {
int x, y;
do {
x = uniform(-15, 16);
y = uniform(-15, 16);
} while(abs(12.5 - Complex!double(x, y).abs)  2.5);
table[x + 15][y + 15] = '*';
}

foreach (row; table)
writeln(row);
}

---

Regarding the printing of Complex values, this program:

import std.stdio, std.complex;
void main() {
writeln(Complex!double(0, -1));
}


Prints:
0-1i


While Python prints the same complex number as:

 0-1j
-1j

Bye,
bearophile


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Don

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.




Re: Fixing the imaginary/complex mess

2009-05-04 Thread Don

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.


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Frits van Bommel

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.


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Georg Wrede

Don wrote:

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.


Walter, could the error message then include Please use z.re or z.im to 
get the parts, instead of a cast. or something. Otherwise we have to 
explain to all users separately what's going on, /and/ that the omission 
of implementing the cast in D isn't an omission.


Re: Fixing the imaginary/complex mess

2009-05-04 Thread bearophile
Don Wrote:
 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.

I am with you. Making the language tidy is the way to go :-)
Thank you for your work, and keep improving things when you can.

Bye,
bearophile


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Derek Parnell
On Mon, 04 May 2009 10:56:41 +0200, 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.

Hmmm. not quite because we can not do ...

   int i = floatnum.integer;

but we can do 

   real r = complexnum.re;

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Jason House
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.

I consider this to be a much different case. Assuming the float to an int 
results on approximately the same number... And everyone knows what to expect. 
It's also possible to convert back to float and still have approximately the 
same number. 

For complex to int, the same things are not true. Conversion to float and then 
back to real can give a much different number... And not just for overflow, but 
normal uses of complex numbers. It's also unclear to mathematically inclined 
folk like me and Don what the conversion is supposed to do. A magnitude makes 
as much, if not more, sense.

Adding to all this, there are easier, shorter, and clearer ways to do all of 
these conversions, and you _have_ to agree with Don ;)


Re: Fixing the imaginary/complex mess

2009-05-04 Thread Steven Schveighoffer
On Mon, 04 May 2009 09:44:18 -0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



Georg Wrede wrote:
Walter, could the error message then include Please use z.re or z.im  
to get the parts, instead of a cast. or something. Otherwise we have  
to explain to all users separately what's going on, /and/ that the  
omission of implementing the cast in D isn't an omission.


If we cut the limb, why first apply an ointment to it?


I think the point is relevant to D1, where you can't really remove the  
limb, but you can apply make-up to make it look less deformed ;)


-Steve


Re: Fixing the imaginary/complex mess

2009-05-03 Thread Walter Bright

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?


Re: Fixing the imaginary/complex mess

2009-05-03 Thread Bill Baxter
On Sun, May 3, 2009 at 2:35 AM, Walter Bright
newshou...@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


Fixing the imaginary/complex mess

2009-04-30 Thread Don
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).


Re: Fixing the imaginary/complex mess

2009-04-30 Thread dsimcha
== Quote from Don (nos...@nospam.com)'s article
 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).

I'm totally ok with you creating such a patch and applying it, as I don't use
complex numbers anyhow, but if we're going to look at fixing complex numbers,
shouldn't we discuss whether they even still belong in the core language?  IMHO
they don't because D's user defined types have advanced pretty significantly 
since
the decision was made to put them in, and they're a *very* niche feature.  The
only people who need complex and imaginary numbers are scientific computing
people, and not all or even most scientific computing people need them.

Show of hands, how many people here actually use D's complex numbers on a 
regular
enough basis that you would miss them if they were removed from the core 
language
completely?


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Andrei Alexandrescu

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.


Andrei


Re: Fixing the imaginary/complex mess

2009-04-30 Thread bearophile
Don:
 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).

I agree to disallow/fix those things.
And thanks for your work!

-

dsimcha:
Show of hands, how many people here actually use D's complex numbers on a 
regular enough basis that you would miss them if they were removed from the 
core language completely?

D is in a flux state still, so I think very few engineer/scientists are using 
it (I am not using complex numbers). So probably the answers your will receive 
will not be enough to judge future true usages of the D language.
A possible solution is to remove complex types now from D2 (moving them in 
Phobos and Tango), and later if enough people ask for them, to put them back 
into the built-ins.
Are there problems in adding them back later if they are asked for and regarded 
as useful?

-

Andrei Alexandrescu:
Since you're looking into this already, I suggest we move for the kill and 
eliminate built-in complex.

Is the current semantics fully doable with std lib complex numbers?

Bye,
bearophile


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Robert Fraser

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.


Andrei


Ehhh why not leave complex and just kill imaginary? That'd solve 
most of the problems.


Re: Fixing the imaginary/complex mess

2009-04-30 Thread bearophile
Robert Fraser:
 Ehhh why not leave complex and just kill imaginary? That'd solve 
 most of the problems.

You can't remove only half of a feature of the language, so I don't like this 
idea.
I accept to remove them fully if their semantics can be fully replaced by the 
std lib. Otherwise just let Don fix the broken things.

Bye,
bearophile


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Georg Wrede

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.


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.




Re: Fixing the imaginary/complex mess

2009-04-30 Thread Robert Fraser

bearophile wrote:

Robert Fraser:
Ehhh why not leave complex and just kill imaginary? That'd solve 
most of the problems.


You can't remove only half of a feature of the language, so I don't like this 
idea.
I accept to remove them fully if their semantics can be fully replaced by the 
std lib. Otherwise just let Don fix the broken things.

Bye,
bearophile


It's not necessarily removing half a feature. Imaginary numbers aren't 
closed under many operations. The idea is that imaginary literals are 
turned into complex. So ireal x = 10i; becomes creal x = 0 + 10i;. 
Since complex numbers are closed under all the builtin operators, it 
eliminates many of the problems (casts from complex to real).


Putting it in a library eliminates the ability to use complex/imaginary 
literals (unless it's a runtime type).


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Joel C. Salomon
Robert Fraser wrote:
 Ehhh why not leave complex and just kill imaginary? That'd solve
 most of the problems.

The reasons for a separate imaginary type are listed in the D docs at
http://digitalmars.com/d/2.0/cppcomplex.html, referencing William
Kahan’s “Branch Cuts for Complex Elementary Functions, or Much Ado About
Nothing’s Sign Bit”.

It just doesn’t have to be a built-in type anymore.

—Joel Salomon


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Don

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.


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Don

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.


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Brad Roberts
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


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Don

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


Re: Fixing the imaginary/complex mess

2009-04-30 Thread Georg Wrede

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. :-)