www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Imaginary and Complex

reply nick <nick.atamas gmail.com> writes:
I noticed that D has both imaginary and complex primitive types? What 
is the motivation behind this. Is the goal to perform better 
optimizations for numerical computations? Why couldn't the types be 
part of a standard library?
Jan 28 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
nick wrote:
 I noticed that D has both imaginary and complex primitive types? What is 
 the motivation behind this. Is the goal to perform better optimizations 
 for numerical computations? Why couldn't the types be part of a standard 
 library?
 
I think it's to simplify writing code that uses this kind of computation. The same reason that multiplication is a built-in operation, and not a function implemented in a library!!
Jan 28 2006
parent reply nick <nick.atamas gmail.com> writes:
On 2006-01-28 21:14:53 -0800, Hasan Aljudy <hasan.aljudy gmail.com> said:

 nick wrote:
 I noticed that D has both imaginary and complex primitive types? What 
 is the motivation behind this. Is the goal to perform better 
 optimizations for numerical computations? Why couldn't the types be 
 part of a standard library?
 
I think it's to simplify writing code that uses this kind of computation. The same reason that multiplication is a built-in operation, and not a function implemented in a library!!
Perhaps I should elaborate on my original question. The point Guy Steele makes in "Growing a Language" is that languages should be simple and elegant while providing tools to grow the language for specific niches. He points out that a really large segment of applications doesn't use imaginary numbers. Making imaginary and complex part of the spec. begs the question of "why not have more things." I may argue that vec2 (a 2 dimensional vector) is also really useful, and should thus be a primitive; this sort of logic can escalate out of control. (Hey, that's how OOP came about and operator overloading) I am asking why the decision was made to include imaginary and complex numbers directly in the language when operator overloading already provides a method to accomplish an almost identical result in a library. If having imaginary numbers in a library is not satisfactory, I would like to know why. Thus, my original question.
Jan 28 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"nick" <nick.atamas gmail.com> wrote in message 
news:drhm8t$16vk$1 digitaldaemon.com...
 Perhaps I should elaborate on my original question.

 The point Guy Steele makes in "Growing a Language" is that languages 
 should be simple and elegant while providing tools to grow the language 
 for specific niches. He points out that a really large segment of 
 applications doesn't use imaginary numbers. Making imaginary and complex 
 part of the spec. begs the question of "why not have more things." I may 
 argue that vec2 (a 2 dimensional vector) is also really useful, and should 
 thus be a primitive; this sort of logic can escalate out of control. (Hey, 
 that's how OOP came about and operator overloading)

 I am asking why the decision was made to include imaginary and complex 
 numbers directly in the language when operator overloading already 
 provides a method to accomplish an almost identical result in a library. 
 If having imaginary numbers in a library is not satisfactory, I would like 
 to know why. Thus, my original question.
It's a good question. I'll reply here in general, the specifics for complex numbers I gave a link to in the other message. It certainly is a tempting idea to have a small core language, with everything else user definable. A consequence of this is that tokens are user definable, syntax is user definable, and of course semantics are user definable. It doesn't take much of this to make code in such a language completely unmaintainable. If you look at a piece of code, there is no touchstone, no common reference point of view, to what the code does, it can be or do *anything*. A simple example of the trouble one can get into with this is the C++ overloading of << and >> in iostreams. If one wasn't already familiar with iostreams, what would one think when seeing all those <<? He'd think it would be shifting, when it is doing nothing of the sort. Some C++ people have taken this much, much further with the Spirit library, which uses operator overloading to create an *entirely new and distinct* language for building parsers. Unfortunately, this new language winds up looking exactly like regular C++, so there's no way for the poor maintainer to distinguish it. Another example is back in the 80's when macro assemblers were popular, many companies undertook to essentially write a new language using the macro processor, and then write 'assembler' files in that new language. One maintainer saddled with this mess told me he finally figured out a way to deal with it - he assembled it into a .obj file, then *disassembled* the .obj file back into assembler, and then replaced the original macro assembler source file with the disassembled source file, and worked from there. So, practically, one is stuck with not allowing user defined tokens or user defined syntax. Unfortunately, then one must give up hope of *seamlessly* integrating new types into the language via libraries, as C++'s <complex> demonstrates. Since user defined types cannot be seamlessly integrated in, the most practical approach is to hardwire in the most common types. Hence, D has the integer types, character types, floating point types, arrays, strings, and associative arrays hardwired in. That gets us the seamless integration. As an aside - do we *really* need strings to be a user defined type? I believe the C++ experience with that shows it to be a disaster. I can expound on that in detail if anyone cares <g>. Guy Steele says that few C++ users use imaginary and complex numbers. True. But I attribute that to the poor support for such in C++, which is why numeric programmers tend to stick with FORTRAN. The C and C++ committees and compiler vendors have historically neglected the interests of numeric programmers. (For example, look at the abandonment of 80 bit reals! Incredible.)
Jan 28 2006
parent reply nick <nick.atamas gmail.com> writes:
Walter Bright wrote:

 It's a good question. I'll reply here in general, the specifics for complex 
 numbers I gave a link to in the other message.
 
 So, practically, one is stuck with not allowing user defined tokens or user 
 defined syntax. Unfortunately, then one must give up hope of *seamlessly* 
 integrating new types into the language via libraries, as C++'s <complex> 
 demonstrates.
But D's operator overloading allows for *almost* seamlessly integrating math types into the language. Right? > As an aside - do we *really* need strings to be a user defined type? I
 believe the C++ experience with that shows it to be a disaster. I can 
 expound on that in detail if anyone cares <g>.
I have experienced a bit of unpleasantness with C++ strings, including a nontrivial variant of this: printf("Hello, %s", std::string("World")); //No c_str() -> SegFault; I would certainly like to hear the details.
 Guy Steele says that few C++ users use imaginary and complex numbers. True. 
 But I attribute that to the poor support for such in C++, which is why 
 numeric programmers tend to stick with FORTRAN. The C and C++ committees and 
 compiler vendors have historically neglected the interests of numeric 
 programmers. (For example, look at the abandonment of 80 bit reals! 
 Incredible.) 
Well, I thought Steele's point was more along the lines of "Java needs operator overloading", and complex numbers was just an example targeted at his audience. The link you sent me removed all doubt. The 80bit float issue is ridiculous, of course; especially because 80 bit floats are supported by both AMD and Intel.
Jan 29 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"nick" <nick.atamas gmail.com> wrote in message 
news:dri35u$1o0f$1 digitaldaemon.com...
 Walter Bright wrote:

 It's a good question. I'll reply here in general, the specifics for 
 complex numbers I gave a link to in the other message.

 So, practically, one is stuck with not allowing user defined tokens or 
 user defined syntax. Unfortunately, then one must give up hope of 
 *seamlessly* integrating new types into the language via libraries, as 
 C++'s <complex> demonstrates.
But D's operator overloading allows for *almost* seamlessly integrating math types into the language. Right?
Yes. But I would never suggest replacing the 'int' type with a class, and I've never heard even the die hard C++ "do it all in the library" people suggest going that far.
  > As an aside - do we *really* need strings to be a user defined type? I
 believe the C++ experience with that shows it to be a disaster. I can 
 expound on that in detail if anyone cares <g>.
I have experienced a bit of unpleasantness with C++ strings, including a nontrivial variant of this: printf("Hello, %s", std::string("World")); //No c_str() -> SegFault; I would certainly like to hear the details.
The big problem is everyone produces their own string package. This means that 3rd party libraries can't interoperate with each other - each is its own, incompatible ecosystem. The answer I hear from that is to standardize std::string. Ok, but then one is stuck with the inflexibility of a core string type with the clumsiness of a library string type - the worst of both worlds. For some more thoughts on this, see www.digitalmars.com/d/cppstrings.html. The lack of decent built in strings has been a serious problem for C++ since the beginning. With core strings that work, then 3rd party libraries won't bother inventing their own, and they can pass strings between each other as easilly as ints.
 Guy Steele says that few C++ users use imaginary and complex numbers. 
 True. But I attribute that to the poor support for such in C++, which is 
 why numeric programmers tend to stick with FORTRAN. The C and C++ 
 committees and compiler vendors have historically neglected the interests 
 of numeric programmers. (For example, look at the abandonment of 80 bit 
 reals! Incredible.)
Well, I thought Steele's point was more along the lines of "Java needs operator overloading", and complex numbers was just an example targeted at his audience. The link you sent me removed all doubt. The 80bit float issue is ridiculous, of course; especially because 80 bit floats are supported by both AMD and Intel.
Dropping support for it astounded me.
Jan 29 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Walter Bright wrote:
 "nick" <nick.atamas gmail.com> wrote in message 
 news:dri35u$1o0f$1 digitaldaemon.com...
 
Walter Bright wrote:


 [snip]
I have experienced a bit of unpleasantness with C++ strings, including a nontrivial variant of this: printf("Hello, %s", std::string("World")); //No c_str() -> SegFault; I would certainly like to hear the details.
The big problem is everyone produces their own string package. This means that 3rd party libraries can't interoperate with each other - each is its own, incompatible ecosystem. The answer I hear from that is to standardize std::string. Ok, but then one is stuck with the inflexibility of a core string type with the clumsiness of a library string type - the worst of both worlds. For some more thoughts on this, see www.digitalmars.com/d/cppstrings.html. The lack of decent built in strings has been a serious problem for C++ since the beginning. With core strings that work, then 3rd party libraries won't bother inventing their own, and they can pass strings between each other as easilly as ints.
But then, doesn't this mean that D should have a standard String class too? just like Java? I mean, think about java, how silly would it be for someone to invent their own String class? really silly I'd say. But for D, I think there are good reasons for inventing one's own string class: - True OOP tends to never use arrays, always use objects, (strings, collections .. etc). You may disagree with them, but the fact is there are people who would go about wrapping wchar[] in a class. For instance, I know one of my professors who would do that (if he ever used D). Frankly, he's the one who made me hate C++, and that's pretty much the reason why I decided to start using D. When I told him about D, he said that he didn't look deeply into it, but he noticed that alot of the "features" (he put it in quotes) use completely procedural constructs (i.e. arrays); I'm under the impressions that if the language doesn't provide enough OO support, he won't use it. (If he ever had to use D, he would probably invent a String class!) And guess what, if that's his opinion, it's probably the opinion of many others. So please, for the sake of attracting these people to D, let D have a standard String class!!! - Another thing is dealing with char, wchar, dchar inconsistencies? (sorry, I don't know much about that, but I assume there will be some conflicts if I use wchar[] and someone else uses dchar[] somewhere else).
Jan 29 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Hasan Aljudy wrote:
 When I told him about D, he said that he didn't look deeply into it, but 
 he noticed that alot of the "features" (he put it in quotes) use 
 completely procedural constructs (i.e. arrays);
Ironically, the C++ standard library is designed to encourage the use of procedural constructs over OO ones.
 I'm under the
 impressions that if the language doesn't provide enough OO support, he 
 won't use it. (If he ever had to use D, he would probably invent a 
 String class!)
 And guess what, if that's his opinion, it's probably the opinion of many 
 others.
I'm sure it is. So what would you suggest? As a fan of the procedural/C++ style I can't really conceive a design I find acceptable. I'd much rather do everything via free functions (and that nifty trick that allows free functions to pretend they're member functions when used with arrays).
 - Another thing is dealing with char, wchar, dchar inconsistencies? 
 (sorry, I don't know much about that, but I assume there will be some 
 conflicts if I use wchar[] and someone else uses dchar[] somewhere else).
Explicit conversion is required, but that's it. Sean
Jan 29 2006
prev sibling parent reply nick <nick.atamas gmail.com> writes:
Hasan Aljudy wrote:
 But then, doesn't this mean that D should have a standard String class 
 too? just like Java?

 [..SNIP..]
 
 - Another thing is dealing with char, wchar, dchar inconsistencies? 
 (sorry, I don't know much about that, but I assume there will be some 
 conflicts if I use wchar[] and someone else uses dchar[] somewhere else).
You are right, a lot of people would not like /char[]/. I think the real reason they won't like it is because /char[]/ is because they like to see the word STRING and be reassured as to the purpose of an entity; the same logic applies to having a /bool/ instead of /int/. With that said, I can't think of too many instances where people would be thoroughly confused by this because an array of characters is USUALLY a string unless it's an array of bytes. However, since D has a type /byte/ it shouldn't be a problem. Finally, I think that string and/or String should be aliased to char[] to prevent people from writing their own classes.
Jan 29 2006
parent reply Sean Kelly <sean f4.ca> writes:
nick wrote:
 Hasan Aljudy wrote:
 But then, doesn't this mean that D should have a standard String class 
 too? just like Java?
>
 [..SNIP..]

 - Another thing is dealing with char, wchar, dchar inconsistencies? 
 (sorry, I don't know much about that, but I assume there will be some 
 conflicts if I use wchar[] and someone else uses dchar[] somewhere else).
You are right, a lot of people would not like /char[]/. I think the real reason they won't like it is because /char[]/ is because they like to see the word STRING and be reassured as to the purpose of an entity; the same logic applies to having a /bool/ instead of /int/. With that said, I can't think of too many instances where people would be thoroughly confused by this because an array of characters is USUALLY a string unless it's an array of bytes. However, since D has a type /byte/ it shouldn't be a problem. Finally, I think that string and/or String should be aliased to char[] to prevent people from writing their own classes.
This might be the best approach. Simply add these aliases: alias char[] string; alias wchar[] wstring; alias dchar[] dstring; and then implement the rest as free functions (which, as I mentioned in my other post, can be called as if they were member functions in D). This would give D a string "class" of sorts, though it would not be inheritable. Sean
Jan 29 2006
parent reply nick <nick.atamas gmail.com> writes:
Could you explain the concept of a free function?
Jan 29 2006
parent reply Sean Kelly <sean f4.ca> writes:
nick wrote:
 Could you explain the concept of a free function?
For whatever reason, DMD makes this possible: char[] str; // this is a "free function" int toInteger( char[] s ) { ... } int i = toInteger( str ), j = str.toInteger(); Both of the above calling conventions work for arrays (though not for primitives). By "free function" I merely meant a function that is declared at global scope. Sean
Jan 29 2006
parent reply nick <nick.atamas gmail.com> writes:
Sean Kelly wrote:
 nick wrote:
 Could you explain the concept of a free function?
For whatever reason, DMD makes this possible: char[] str; // this is a "free function" int toInteger( char[] s ) { ... } int i = toInteger( str ), j = str.toInteger(); Both of the above calling conventions work for arrays (though not for primitives). By "free function" I merely meant a function that is declared at global scope. Sean
Oh. Right. Actually that makes perfect sense to me. My understanding is that this comes directly from how classes are implemented (/this/ gets passed in as the first parameter). I could be totally wrong though.
Jan 29 2006
parent reply Sean Kelly <sean f4.ca> writes:
nick wrote:
 Sean Kelly wrote:
 nick wrote:
 Could you explain the concept of a free function?
For whatever reason, DMD makes this possible: char[] str; // this is a "free function" int toInteger( char[] s ) { ... } int i = toInteger( str ), j = str.toInteger(); Both of the above calling conventions work for arrays (though not for primitives). By "free function" I merely meant a function that is declared at global scope.
Oh. Right. Actually that makes perfect sense to me. My understanding is that this comes directly from how classes are implemented (/this/ gets passed in as the first parameter). I could be totally wrong though.
I think you're right. Though I don't understand why this wouldn't extend to primitives as well. Sean
Jan 29 2006
parent Dave <Dave_member pathlink.com> writes:
In article <drjodu$18oc$1 digitaldaemon.com>, Sean Kelly says...
nick wrote:
 Sean Kelly wrote:
 nick wrote:
 Could you explain the concept of a free function?
For whatever reason, DMD makes this possible: char[] str; // this is a "free function" int toInteger( char[] s ) { ... } int i = toInteger( str ), j = str.toInteger(); Both of the above calling conventions work for arrays (though not for primitives). By "free function" I merely meant a function that is declared at global scope.
Oh. Right. Actually that makes perfect sense to me. My understanding is that this comes directly from how classes are implemented (/this/ gets passed in as the first parameter). I could be totally wrong though.
I think you're right. Though I don't understand why this wouldn't extend to primitives as well.
The transformation is done in expression.c: Expression *CallExp::semantic(Scope *sc) I doesn't look like there is any reason this can't be done with primitives either. I think it would be great if we could write functions that would then be called as a 'property' for primitives. For example, what we can do now with strings; char[] lowercase(char[] str) {...} char[] str = ...; str.lowercase(); One problem (inconsistency?) with that is currently 'str.lowercase()' has to be called with the parantheses, so doesn't have property or 'field' like syntax.
Sean
Jan 29 2006
prev sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Walter Bright wrote:
 
 For some more thoughts on this, see www.digitalmars.com/d/cppstrings.html.
 
There's a doc bug inn "Filling a string": char[] str = "hello"; str[1..2] = '?'; // str is "h??lo" str is "h?llo" and not "h??lo". Dunno if there is a problem too with the C++ example. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Feb 01 2006
next sibling parent Yves Jacoby <kloune gmail.com> writes:
On Wed, 01 Feb 2006 13:49:57 +0000, Bruno Medeiros wrote:

 Walter Bright wrote:
 
 For some more thoughts on this, see www.digitalmars.com/d/cppstrings.html.
 
There's a doc bug inn "Filling a string": char[] str = "hello"; str[1..2] = '?'; // str is "h??lo" str is "h?llo" and not "h??lo". Dunno if there is a problem too with the C++ example.
Hi, I have another example for that, but same problem, somehow the end index is the real end index+1. I thought it was implemented like that in the language, so that if you wanted to fill the complete array you would do: str[0..length]='?'.
Feb 01 2006
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
You're right, I'll fix it. 
Feb 01 2006
prev sibling next sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"nick" <nick.atamas gmail.com> wrote in message 
news:drhcqv$h8s$1 digitaldaemon.com...
I noticed that D has both imaginary and complex primitive types? What is 
the motivation behind this. Is the goal to perform better optimizations for 
numerical computations? Why couldn't the types be part of a standard 
library?
This should help: www.digitalmars.com/d/cppcomplex.html
Jan 28 2006
parent nick.atamas gmail.com writes:
In article <drhkto$13uq$1 digitaldaemon.com>, Walter Bright says...
"nick" <nick.atamas gmail.com> wrote in message 
news:drhcqv$h8s$1 digitaldaemon.com...
I noticed that D has both imaginary and complex primitive types? What is 
the motivation behind this. Is the goal to perform better optimizations for 
numerical computations? Why couldn't the types be part of a standard 
library?
This should help: www.digitalmars.com/d/cppcomplex.html
Thanks, that's exactly what I was looking for. I'm going to go read more so that I am not asking stupid questions.
Jan 28 2006
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
nick wrote:

 I noticed that D has both imaginary and complex primitive types?
Even better, D has an "imaginary real" type. (that would be ireal) :-P See http://www.digitalmars.com/d/archives/digitalmars/D/24116.html --anders
Jan 29 2006
parent reply nick <nick.atamas gmail.com> writes:
Anders F Björklund wrote:
 nick wrote:
 
 I noticed that D has both imaginary and complex primitive types?
Even better, D has an "imaginary real" type. (that would be ireal) :-P See http://www.digitalmars.com/d/archives/digitalmars/D/24116.html --anders
Yes, I saw that when I search for 'imaginary' before posting this thread. It is a bit of a misnomer, but you could think of it as i*real which would be correct-ish, right?
Jan 29 2006
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
nick wrote:

 Yes, I saw that when I search for 'imaginary' before posting this 
 thread. It is a bit of a misnomer, but you could think of it as i*real 
 which would be correct-ish, right?
I don't like the real type either, so... Think it should be an alias. (my suggestion was to rename real to extended, and fix it at 80 bits) --anders
Jan 29 2006